Merged in GZDB r2469.

This commit is contained in:
MascaraSnake 2016-01-23 02:50:13 +01:00
parent 2cb8570eec
commit b524dd8277
10 changed files with 257 additions and 120 deletions

View File

@ -711,6 +711,7 @@
<None Include="Resources\ZoneBuilder.bmp" />
<None Include="app.manifest" />
<None Include="Resources\ScriptSnippet.xpm" />
<EmbeddedResource Include="Resources\SkySphere.md3" />
<None Include="Resources\ThingStatistics.png" />
<None Include="Resources\Copy.png" />
<None Include="Resources\Cut.png" />

View File

@ -28,12 +28,15 @@ using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.GZDoom;
using CodeImp.DoomBuilder.GZBuilder.MD3;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.ZDoom;
using SlimDX;
using SlimDX.Direct3D9;
using Matrix = SlimDX.Matrix;
#endregion
@ -496,9 +499,6 @@ namespace CodeImp.DoomBuilder.Data
alltextures.AddFlat(img.Value);
}
//mxd. Create skybox texture(s)
SetupSkybox();
// Start background loading
StartBackgroundLoader();
@ -1853,9 +1853,6 @@ namespace CodeImp.DoomBuilder.Data
foreach(Thing t in General.Map.Map.Things) t.UpdateCache();
// Rebuild skybox texture
SetupSkybox();
// Rebuild geometry if in Visual mode
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode")
{
@ -1884,7 +1881,11 @@ namespace CodeImp.DoomBuilder.Data
return;
}
//rebuild geometry if in Visual mode
// Reset skybox texture
skybox.Dispose();
skybox = null;
// Rebuild geometry if in Visual mode
if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode")
{
General.Editing.Mode.OnReloadResources();
@ -2361,6 +2362,10 @@ namespace CodeImp.DoomBuilder.Data
#endregion
#region ================== mxd. Skybox Making
internal void UpdateSkybox()
{
if (skybox == null) SetupSkybox();
}
private void SetupSkybox()
{
@ -2396,7 +2401,7 @@ namespace CodeImp.DoomBuilder.Data
Bitmap img = GetTextureBitmap(skytex);
if (img != null)
{
skybox = MakeClassicSkyBox(img, true);
skybox = MakeClassicSkyBox(img);
}
}
}
@ -2406,137 +2411,186 @@ namespace CodeImp.DoomBuilder.Data
{
ImageData tex = LoadInternalTexture("MissingSky3D.png");
tex.CreateTexture();
skybox = MakeClassicSkyBox(new Bitmap(tex.GetBitmap()), false);
skybox = MakeClassicSkyBox(new Bitmap(tex.GetBitmap()));
tex.Dispose();
}
}
private static CubeTexture MakeClassicSkyBox(Bitmap img, bool dogradients)
{
// CubeTexture must be square with power of 2 sides
int targetwidth = General.NextPowerOf2(img.Width);
int targetheight = General.NextPowerOf2(img.Height);
// Get averaged top and bottom colors
Color topcolor, bottomcolor;
if (dogradients)
//INFO: 1. Looks like GZDoom tries to tile a sky texture into a 1024 pixel width texture.
//INFO: 2. If sky texture width <= height, it will be tiled to fit into 512 pixel height texture vertically.
private static CubeTexture MakeClassicSkyBox(Bitmap img)
{
// Get averaged top and bottom colors from the original image
int tr = 0, tg = 0, tb = 0, br = 0, bg = 0, bb = 0;
for (int i = 0; i < img.Width; i++)
const int colorsampleheight = 28; // TODO: is this value calculated from the image's height?
for (int w = 0; w < img.Width; w++)
{
Color c = img.GetPixel(i, 0);
for (int h = 0; h < colorsampleheight; h++)
{
Color c = img.GetPixel(w, h);
tr += c.R;
tg += c.G;
tb += c.B;
c = img.GetPixel(i, img.Height - 1);
c = img.GetPixel(w, img.Height - 1 - h);
br += c.R;
bg += c.G;
bb += c.B;
}
topcolor = Color.FromArgb(255, tr / img.Width, tg / img.Width, tb / img.Width);
bottomcolor = Color.FromArgb(255, br / img.Width, bg / img.Width, bb / img.Width);
}
else
{
// This should be built-in sky texture
Color c = img.GetPixel(img.Width / 2, 0);
topcolor = Color.FromArgb(255, c);
c = img.GetPixel(img.Width / 2, img.Height - 1);
bottomcolor = Color.FromArgb(255, c);
}
// Make it Po2
if (img.Width != targetwidth || img.Height != targetheight) img = ResizeImage(img, targetwidth, targetheight);
int pixelscount = img.Width * colorsampleheight;
Color topcolor = Color.FromArgb(255, tr / pixelscount, tg / pixelscount, tb / pixelscount);
Color bottomcolor = Color.FromArgb(255, br / pixelscount, bg / pixelscount, bb / pixelscount);
// Make it square
if (targetwidth > targetheight)
{
int c = targetwidth / targetheight;
Bitmap result = new Bitmap(targetwidth, targetwidth, img.PixelFormat);
// Make tiling image
int horiztiles = (int)Math.Ceiling(1024.0f / img.Width);
int verttiles = img.Height > 256 ? 1 : 2;
// Tile vertically
using (Graphics g = Graphics.FromImage(result))
Bitmap skyimage = new Bitmap(1024, img.Height * verttiles, img.PixelFormat);
// Draw original image
using (Graphics g = Graphics.FromImage(skyimage))
{
for (int i = 0; i < c; i++) g.DrawImage(img, 0, targetheight * i);
for (int w = 0; w < horiztiles; w++)
{
for (int h = 0; h < verttiles; h++)
{
g.DrawImage(img, img.Width * w, img.Height * h);
}
img = result;
}
else if (targetwidth < targetheight)
{
int c = targetheight / targetwidth;
Bitmap result = new Bitmap(targetheight, targetheight);
// Tile horizontally
using (Graphics g = Graphics.FromImage(result))
{
for (int i = 0; i < c; i++) g.DrawImage(img, targetwidth * i, 0);
}
img = result;
}
// Make top and bottom images
Bitmap top = new Bitmap(img.Width, img.Height);
using (Graphics g = Graphics.FromImage(top))
const int capsimgsize = 16;
Bitmap topimg = new Bitmap(capsimgsize, capsimgsize);
using (Graphics g = Graphics.FromImage(topimg))
{
using (SolidBrush b = new SolidBrush(topcolor))
{
g.FillRectangle(b, 0, 0, img.Width, img.Height);
}
g.FillRectangle(b, 0, 0, capsimgsize, capsimgsize);
}
Bitmap bottom = new Bitmap(img.Width, img.Height);
using (Graphics g = Graphics.FromImage(bottom))
Bitmap bottomimg = new Bitmap(capsimgsize, capsimgsize);
using (Graphics g = Graphics.FromImage(bottomimg))
{
using (SolidBrush b = new SolidBrush(bottomcolor))
{
g.FillRectangle(b, 0, 0, img.Width, img.Height);
}
g.FillRectangle(b, 0, 0, capsimgsize, capsimgsize);
}
// Apply top/bottom gradients
if (dogradients)
using (Graphics g = Graphics.FromImage(skyimage))
{
using (Graphics g = Graphics.FromImage(img))
{
int gradientheight = img.Height / 6;
Rectangle area = new Rectangle(0, 0, img.Width, gradientheight);
Rectangle area = new Rectangle(0, 0, skyimage.Width, colorsampleheight);
using (LinearGradientBrush b = new LinearGradientBrush(area, topcolor, Color.FromArgb(0, topcolor), 90f))
{
g.FillRectangle(b, area);
}
area = new Rectangle(0, img.Height - gradientheight, img.Width, gradientheight);
area = new Rectangle(0, skyimage.Height - colorsampleheight, skyimage.Width, colorsampleheight);
using (LinearGradientBrush b = new LinearGradientBrush(area, Color.FromArgb(0, bottomcolor), bottomcolor, 90f))
{
area.Y += 1;
g.FillRectangle(b, area);
}
}
}
// Load the skysphere model...
Device device = General.Map.Graphics.Device;
World3DShader effect = General.Map.Graphics.Shaders.World3D;
BoundingBoxSizes bbs = new BoundingBoxSizes();
Stream modeldata = General.ThisAssembly.GetManifestResourceStream("CodeImp.DoomBuilder.Resources.SkySphere.md3");
ModelReader.MD3LoadResult result = ModelReader.ReadMD3Model(ref bbs, true, modeldata, device, 0);
if (result.Meshes.Count != 3) throw new Exception("Skybox creation failed: " + result.Errors);
// Make skysphere textures...
Texture texside = TextureFromBitmap(device, skyimage);
Texture textop = TextureFromBitmap(device, topimg);
Texture texbottom = TextureFromBitmap(device, bottomimg);
// Calculate model scaling (gl.skydone.cpp:RenderDome() in GZDoom)
float yscale;
if (img.Height < 128) yscale = 128 / 230.0f;
else if (img.Height < 200) yscale = img.Height / 230.0f;
else if (img.Height < 241) yscale = 1.0f + ((img.Height - 200.0f) / 200.0f) * 1.17f;
else yscale = 1.2f * 1.17f;
// Make cubemap texture
CubeTexture cubemap = new CubeTexture(General.Map.Graphics.Device, img.Width, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
const int cubemaptexsize = 1024;
CubeTexture cubemap = new CubeTexture(device, cubemaptexsize, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
// Draw faces
img.RotateFlip(RotateFlipType.Rotate180FlipX);
DrawCubemapFace(cubemap, CubeMapFace.NegativeX, img);
// Set render settings...
device.SetRenderState(RenderState.ZEnable, false);
device.SetRenderState(RenderState.CullMode, Cull.None);
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
DrawCubemapFace(cubemap, CubeMapFace.NegativeY, img);
// Make custom rendertarget
Surface rendertarget = Surface.CreateRenderTarget(device, cubemaptexsize, cubemaptexsize, Format.A8R8G8B8, MultisampleType.None, 0, false);
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
DrawCubemapFace(cubemap, CubeMapFace.PositiveX, img);
// Setup matrices
Vector3 offset = new Vector3(0f, 0f, -1.8f); // Sphere size is 10 mu
Matrix mworld = Matrix.Multiply(Matrix.Identity, Matrix.Translation(offset) * Matrix.Scaling(1.0f, 1.0f, yscale));
Matrix mprojection = Matrix.PerspectiveFovLH(Angle2D.PIHALF, 1.0f, 0.5f, 100.0f);
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
DrawCubemapFace(cubemap, CubeMapFace.PositiveY, img);
// Place camera at origin
effect.CameraPosition = new Vector4();
DrawCubemapFace(cubemap, CubeMapFace.PositiveZ, top);
DrawCubemapFace(cubemap, CubeMapFace.NegativeZ, bottom);
// Set the rendertarget to our own RT surface
device.SetRenderTarget(0, rendertarget);
// Set custom depth stencil
device.DepthStencilSurface = Surface.CreateDepthStencil(device, cubemaptexsize, cubemaptexsize, General.Map.Graphics.DepthBuffer.Description.Format, MultisampleType.None, 0, false);
// Begin rendering
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkRed, 1.0f, 0);
device.BeginScene();
effect.Begin();
effect.BeginPass(1); // Fullbright pass
// Render to the six faces of the cube map
for (int i = 0; i < 6; i++)
{
Matrix faceview = GetCubeMapViewMatrix((CubeMapFace)i);
effect.WorldViewProj = mworld * faceview * mprojection;
// Render the skysphere meshes
for (int j = 0; j < result.Meshes.Count; j++)
{
// Set appropriate texture
switch (result.Skins[j])
{
case "top.png": effect.Texture1 = textop; break;
case "bottom.png": effect.Texture1 = texbottom; break;
case "side.png": effect.Texture1 = texside; break;
default: throw new Exception("Unexpected skin!");
}
// Commit changes
effect.ApplySettings();
// Render mesh
result.Meshes[j].DrawSubset(0);
}
// Copy the rendered image from our RT surface to the texture face
Surface cubeface = cubemap.GetCubeMapSurface((CubeMapFace)i, 0);
device.StretchRectangle(rendertarget, cubeface, TextureFilter.None);
cubeface.Dispose();
}
// End rendering
effect.EndPass();
effect.End();
device.EndScene();
// Dispose unneeded stuff
rendertarget.Dispose();
textop.Dispose();
texside.Dispose();
texbottom.Dispose();
// Dispose skybox meshes
foreach (Mesh m in result.Meshes) m.Dispose();
// All done...
return cubemap;
@ -2757,6 +2811,62 @@ namespace CodeImp.DoomBuilder.Data
return destimage;
}
private static Matrix GetCubeMapViewMatrix(CubeMapFace face)
{
Vector3 lookdir, updir;
switch (face)
{
case CubeMapFace.PositiveX:
lookdir = new Vector3(1.0f, 0.0f, 0.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f);
break;
case CubeMapFace.NegativeX:
lookdir = new Vector3(-1.0f, 0.0f, 0.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f);
break;
case CubeMapFace.PositiveY:
lookdir = new Vector3(0.0f, 1.0f, 0.0f);
updir = new Vector3(0.0f, 0.0f, -1.0f);
break;
case CubeMapFace.NegativeY:
lookdir = new Vector3(0.0f, -1.0f, 0.0f);
updir = new Vector3(0.0f, 0.0f, 1.0f);
break;
case CubeMapFace.PositiveZ:
lookdir = new Vector3(0.0f, 0.0f, 1.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f);
break;
case CubeMapFace.NegativeZ:
lookdir = new Vector3(0.0f, 0.0f, -1.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f);
break;
default:
throw new Exception("Unknown CubeMapFace!");
}
Vector3 eye = new Vector3();
return Matrix.LookAtLH(eye, lookdir, updir);
}
private static Texture TextureFromBitmap(Device device, Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);
ms.Seek(0, SeekOrigin.Begin);
Texture result = Texture.FromStream(device, ms);
ms.Close();
ms.Dispose();
return result;
}
#endregion
}
}

View File

@ -23,7 +23,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
{
#region ================== Variables
private class MD3LoadResult
internal class MD3LoadResult
{
public List<string> Skins;
public List<Mesh> Meshes;
@ -232,7 +232,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
#region ================== MD3
private static MD3LoadResult ReadMD3Model(ref BoundingBoxSizes bbs, bool useSkins, MemoryStream s, Device device, int frame)
internal static MD3LoadResult ReadMD3Model(ref BoundingBoxSizes bbs, bool useSkins, Stream s, Device device, int frame)
{
long start = s.Position;
MD3LoadResult result = new MD3LoadResult();
@ -423,7 +423,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
#region ================== MD2
private static MD3LoadResult ReadMD2Model(ref BoundingBoxSizes bbs, MemoryStream s, Device device, int frame, string framename)
private static MD3LoadResult ReadMD2Model(ref BoundingBoxSizes bbs, Stream s, Device device, int frame, string framename)
{
long start = s.Position;
MD3LoadResult result = new MD3LoadResult();

View File

@ -551,6 +551,12 @@ namespace CodeImp.DoomBuilder.Geometry
newsector.Brightness = General.Settings.DefaultBrightness;
}
//mxd. Better any height than none
if (newsector.CeilHeight - newsector.FloorHeight <= 0)
{
newsector.CeilHeight = newsector.FloorHeight + (General.Settings.DefaultCeilingHeight - General.Settings.DefaultFloorHeight);
}
//mxd. Apply overrides?
if (useOverrides)
{

View File

@ -1180,15 +1180,26 @@ namespace CodeImp.DoomBuilder.Properties {
}
}
internal static System.Drawing.Bitmap Sky
{
get
{
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Sky {
get {
object obj = ResourceManager.GetObject("Sky", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] SkySphere {
get {
object obj = ResourceManager.GetObject("SkySphere", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>

View File

@ -547,6 +547,9 @@
<data name="Sky" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Sky.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="SkySphere" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\SkySphere.md3;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="zonebuilder" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\zonebuilder.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>

Binary file not shown.

View File

@ -84,7 +84,7 @@ namespace CodeImp.DoomBuilder.VisualModes
// Internal properties
public WorldVertex[] Vertices { get { return vertices; } } //mxd
internal int VertexOffset { get { return vertexoffset; } set { vertexoffset = value; } }
internal int Triangles { get { return triangles; } }
public int Triangles { get { return triangles; } }
//mxd
public Vector3D[] BoundingBox { get { return boundingBox; } }

View File

@ -158,6 +158,9 @@ namespace CodeImp.DoomBuilder.VisualModes
{
base.OnEngage();
//mxd. Sky texture may need recreating
General.Map.Data.UpdateSkybox();
// Update projection (mxd)
General.Map.CRenderer3D.CreateProjection();
@ -878,6 +881,9 @@ namespace CodeImp.DoomBuilder.VisualModes
// Make new blockmap
FillBlockMap();
//mxd. Sky texture may need recreating
General.Map.Data.UpdateSkybox();
// Visibility culling (this re-creates the needed resources)
DoCulling();
}

View File

@ -531,7 +531,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
protected void SelectNeighbours(long longtexture, bool select, bool withSameTexture, bool withSameHeight)
{
if(Sidedef.Sector == null || (!withSameTexture && !withSameHeight)) return;
if (Sidedef.Sector == null || Triangles < 1 || (!withSameTexture && !withSameHeight)) return;
Rectangle rect = BuilderModesTools.GetSidedefPartSize(this);
if(rect.Height == 0) return;