mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 14:31:50 +00:00
Changed, Visual mode: models and lights are much less prone to disappear when near the edges of the screen.
Fixed, Classic modes: MODELDEF model scale was not taken into account when calculating model visibility, which resulted in models with increased scaled disappearing when near screen edges.
This commit is contained in:
parent
e451d38986
commit
a523f7eb28
7 changed files with 46 additions and 138 deletions
|
@ -5,43 +5,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
{
|
||||
public struct BoundingBoxSizes
|
||||
{
|
||||
public short MinX;
|
||||
public short MaxX;
|
||||
public short MinY;
|
||||
public short MaxY;
|
||||
public short MinZ;
|
||||
public short MaxZ;
|
||||
public int MinX;
|
||||
public int MaxX;
|
||||
public int MinY;
|
||||
public int MaxY;
|
||||
public int MinZ;
|
||||
public int MaxZ;
|
||||
|
||||
//we need some reference here
|
||||
public BoundingBoxSizes(WorldVertex v)
|
||||
{
|
||||
MinX = MaxX = (short)v.x;
|
||||
MinY = MaxY = (short)v.y;
|
||||
MinZ = MaxZ = (short)v.z;
|
||||
MinX = MaxX = (int)v.x;
|
||||
MinY = MaxY = (int)v.y;
|
||||
MinZ = MaxZ = (int)v.z;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BoundingBoxTools
|
||||
{
|
||||
//this creates array of vectors resembling bounding box
|
||||
public static Vector3[] CalculateBoundingBox(BoundingBoxSizes bbs)
|
||||
{
|
||||
//center
|
||||
Vector3 v0 = new Vector3(bbs.MinX + (bbs.MaxX - bbs.MinX) / 2, bbs.MinY + (bbs.MaxY - bbs.MinY) / 2, bbs.MinZ + (bbs.MaxZ - bbs.MinZ) / 2);
|
||||
|
||||
//corners
|
||||
Vector3 v1 = new Vector3(bbs.MinX, bbs.MinY, bbs.MinZ);
|
||||
Vector3 v2 = new Vector3(bbs.MaxX, bbs.MinY, bbs.MinZ);
|
||||
Vector3 v3 = new Vector3(bbs.MinX, bbs.MaxY, bbs.MinZ);
|
||||
Vector3 v4 = new Vector3(bbs.MaxX, bbs.MaxY, bbs.MinZ);
|
||||
Vector3 v5 = new Vector3(bbs.MinX, bbs.MinY, bbs.MaxZ);
|
||||
Vector3 v6 = new Vector3(bbs.MaxX, bbs.MinY, bbs.MaxZ);
|
||||
Vector3 v7 = new Vector3(bbs.MinX, bbs.MaxY, bbs.MaxZ);
|
||||
Vector3 v8 = new Vector3(bbs.MaxX, bbs.MaxY, bbs.MaxZ);
|
||||
|
||||
return new[] { v0, v1, v2, v3, v4, v5, v6, v7, v8 };
|
||||
}
|
||||
|
||||
public static Vector3[] CalculateBoundingPlane(BoundingBoxSizes bbs)
|
||||
{
|
||||
//mxd. looks like I need only these 2 points, so...
|
||||
|
@ -53,14 +34,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
|
||||
public static void UpdateBoundingBoxSizes(ref BoundingBoxSizes bbs, WorldVertex v)
|
||||
{
|
||||
if (v.x < bbs.MinX) bbs.MinX = (short)v.x;
|
||||
else if (v.x > bbs.MaxX) bbs.MaxX = (short)v.x;
|
||||
if (v.x < bbs.MinX) bbs.MinX = (int)v.x;
|
||||
else if(v.x > bbs.MaxX) bbs.MaxX = (int)v.x;
|
||||
|
||||
if (v.z < bbs.MinZ) bbs.MinZ = (short)v.z;
|
||||
else if (v.z > bbs.MaxZ) bbs.MaxZ = (short)v.z;
|
||||
if(v.z < bbs.MinZ) bbs.MinZ = (int)v.z;
|
||||
else if(v.z > bbs.MaxZ) bbs.MaxZ = (int)v.z;
|
||||
|
||||
if (v.y < bbs.MinY) bbs.MinY = (short)v.y;
|
||||
else if (v.y > bbs.MaxY) bbs.MaxY = (short)v.y;
|
||||
if(v.y < bbs.MinY) bbs.MinY = (int)v.y;
|
||||
else if(v.y > bbs.MaxY) bbs.MaxY = (int)v.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
using SlimDX;
|
||||
using SlimDX.Direct3D9;
|
||||
|
||||
namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
||||
{
|
||||
internal class GZModel
|
||||
{
|
||||
internal List<Mesh> Meshes;
|
||||
internal List<Texture> Textures;
|
||||
internal Vector3[] BoundingBox;
|
||||
internal readonly List<Mesh> Meshes;
|
||||
internal readonly List<Texture> Textures;
|
||||
internal float Radius;
|
||||
|
||||
internal GZModel()
|
||||
{
|
||||
|
|
|
@ -219,7 +219,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
return;
|
||||
}
|
||||
|
||||
mde.Model.BoundingBox = BoundingBoxTools.CalculateBoundingBox(bbs);
|
||||
//scale bbs
|
||||
bbs.MaxX = (int)(bbs.MaxX * mde.Scale.X);
|
||||
bbs.MinX = (int)(bbs.MinX * mde.Scale.X);
|
||||
bbs.MaxY = (int)(bbs.MaxY * mde.Scale.Y);
|
||||
bbs.MinY = (int)(bbs.MinY * mde.Scale.Y);
|
||||
|
||||
//calculate model radius
|
||||
mde.Model.Radius = Math.Max(Math.Max(Math.Abs(bbs.MinY), Math.Abs(bbs.MaxY)), Math.Max(Math.Abs(bbs.MinX), Math.Abs(bbs.MaxX)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -720,16 +727,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
|
|||
}
|
||||
}
|
||||
|
||||
//create bounding box
|
||||
BoundingBoxSizes bbs = new BoundingBoxSizes();
|
||||
bbs.MinX = (short)((xsize / 2f - pivot.x) * mde.Scale.X);
|
||||
bbs.MaxX = (short)((xsize / 2f + pivot.x) * mde.Scale.X);
|
||||
bbs.MinZ = (short)((zsize / 2f - pivot.z) * mde.Scale.Z);
|
||||
bbs.MaxZ = (short)((zsize / 2f + pivot.z) * mde.Scale.Z);
|
||||
bbs.MinY = (short)((ysize / 2f - pivot.y) * mde.Scale.Y);
|
||||
bbs.MaxY = (short)((ysize / 2f + pivot.y) * mde.Scale.Y);
|
||||
|
||||
mde.Model.BoundingBox = BoundingBoxTools.CalculateBoundingBox(bbs);
|
||||
// get model extents
|
||||
int minX = (int)((xsize / 2f - pivot.x) * mde.Scale.X);
|
||||
int maxX = (int)((xsize / 2f + pivot.x) * mde.Scale.X);
|
||||
int minY = (int)((ysize / 2f - pivot.y) * mde.Scale.Y);
|
||||
int maxY = (int)((ysize / 2f + pivot.y) * mde.Scale.Y);
|
||||
|
||||
// calculate model radius
|
||||
mde.Model.Radius = Math.Max(Math.Max(Math.Abs(minY), Math.Abs(maxY)), Math.Max(Math.Abs(minX), Math.Abs(maxX)));
|
||||
|
||||
//create texture
|
||||
MemoryStream memstream = new MemoryStream((4096 * 4) + 4096);
|
||||
|
|
|
@ -1332,9 +1332,6 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
foreach(KeyValuePair<int, List<Thing>> group in modelsByType)
|
||||
{
|
||||
mde = General.Map.Data.ModeldefEntries[group.Key];
|
||||
float maxX = Math.Max(Math.Abs(mde.Model.BoundingBox[4].X), Math.Abs(mde.Model.BoundingBox[1].X));
|
||||
float maxY = Math.Max(Math.Abs(mde.Model.BoundingBox[4].Y), Math.Abs(mde.Model.BoundingBox[1].Y));
|
||||
float maxSize = Math.Max(maxX, maxY);
|
||||
|
||||
foreach(Thing t in group.Value)
|
||||
{
|
||||
|
@ -1343,8 +1340,8 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
float modelScale = scale * t.ActorScale.Width * t.ScaleX;
|
||||
|
||||
//should we render this model?
|
||||
if(((screenpos.x + maxSize * modelScale) <= 0.0f) || ((screenpos.x - maxSize * modelScale) >= windowsize.Width) ||
|
||||
((screenpos.y + maxSize * modelScale) <= 0.0f) || ((screenpos.y - maxSize * modelScale) >= windowsize.Height))
|
||||
if(((screenpos.x + mde.Model.Radius * modelScale) <= 0.0f) || ((screenpos.x - mde.Model.Radius * modelScale) >= windowsize.Width) ||
|
||||
((screenpos.y + mde.Model.Radius * modelScale) <= 0.0f) || ((screenpos.y - mde.Model.Radius * modelScale) >= windowsize.Height))
|
||||
continue;
|
||||
|
||||
graphics.Shaders.Things2D.FillColor = t.Selected ? cHighlight : cWire;
|
||||
|
|
|
@ -1241,25 +1241,19 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
public void AddThingGeometry(VisualThing t)
|
||||
{
|
||||
//mxd. gater lights
|
||||
if (General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && t.LightType != DynamicLightType.NONE)
|
||||
if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && t.LightType != DynamicLightType.NONE)
|
||||
{
|
||||
t.UpdateLightRadius();
|
||||
|
||||
if (t.LightRadius > 0)
|
||||
if(t.LightRadius > 0)
|
||||
{
|
||||
t.CalculateCameraDistance3D(D3DDevice.V3(cameraposition));
|
||||
//t.CameraDistance3D is actually squared distance, hence (t.LightRadius * t.LightRadius)
|
||||
if(t.CameraDistance3D < (t.LightRadius * t.LightRadius) || IsThingOnScreen(t.BoundingBox)) //always render light if camera is within it's radius
|
||||
{
|
||||
if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1)
|
||||
t.UpdateBoundingBox();
|
||||
thingsWithLight.Add(t);
|
||||
}
|
||||
if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1)
|
||||
t.UpdateBoundingBox();
|
||||
thingsWithLight.Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsThingOnScreen(t.BoundingBox)) return;
|
||||
|
||||
//mxd. gather models
|
||||
if(t.Thing.IsModel && General.Settings.GZDrawModelsMode != ModelRenderMode.NONE && (General.Settings.GZDrawModelsMode == ModelRenderMode.ALL || t.Selected))
|
||||
{
|
||||
|
@ -1295,46 +1289,6 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
visualvertices = verts;
|
||||
}
|
||||
|
||||
//mxd
|
||||
private bool IsThingOnScreen(Vector3[] bbox)
|
||||
{
|
||||
Vector3D camNormal = Vector3D.FromAngleXYZ(General.Map.VisualCamera.AngleXY, General.Map.VisualCamera.AngleZ);
|
||||
Vector3D thingNormal = D3DDevice.V3D(bbox[0]) - cameraposition; //bbox[0] is always thing center
|
||||
|
||||
if (Vector3D.DotProduct(camNormal, thingNormal) < 0) return false; //behind camera plane
|
||||
|
||||
int len = bbox.Length;
|
||||
Vector3 screenPos;
|
||||
int behindCount = 0;
|
||||
int leftCount = 0;
|
||||
int rightCount = 0;
|
||||
int topCount = 0;
|
||||
int bottomCount = 0;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
//check visibility
|
||||
screenPos = Vector3.Project(bbox[i], 0, 0, 1, 1, PROJ_NEAR_PLANE, General.Settings.ViewDistance, worldviewproj);
|
||||
|
||||
if (screenPos.X > 0 && screenPos.X < 1 && screenPos.Y > 0 && screenPos.Y < 1)
|
||||
return true;
|
||||
|
||||
if (screenPos.Z < 0) behindCount++;
|
||||
|
||||
if (screenPos.X < 0)
|
||||
leftCount++;
|
||||
else if (screenPos.X > 1)
|
||||
rightCount++;
|
||||
if (screenPos.Y < 0)
|
||||
topCount++;
|
||||
else if (screenPos.Y > 1)
|
||||
bottomCount++;
|
||||
}
|
||||
|
||||
bool notOnScreen = (behindCount == len || leftCount == len || rightCount == len || topCount == len || bottomCount == len);
|
||||
return !notOnScreen;
|
||||
}
|
||||
|
||||
//mxd
|
||||
private static bool BoundingBoxesIntersect(Vector3[] bbox1, Vector3[] bbox2)
|
||||
{
|
||||
|
|
|
@ -494,7 +494,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
if (target.picked is VisualThing)
|
||||
{
|
||||
VisualThing vt = target.picked as VisualThing;
|
||||
return GetIntersection(start, start + delta, new Vector3D(vt.BoundingBox[0].X, vt.BoundingBox[0].Y, vt.BoundingBox[0].Z), D3DDevice.V3D(vt.Center - vt.PositionV3));
|
||||
return GetIntersection(start, start + delta, vt.CenterV3D, D3DDevice.V3D(vt.Center - vt.PositionV3));
|
||||
}
|
||||
|
||||
return new Vector2D(float.NaN, float.NaN);
|
||||
|
|
|
@ -248,19 +248,11 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
position_v3 = D3DDevice.V3(pos); //mxd
|
||||
position = Matrix.Translation(position_v3);
|
||||
|
||||
//mxd. update bounding box
|
||||
if (thing.IsModel)
|
||||
{
|
||||
UpdateBoundingBoxForModel();
|
||||
}
|
||||
else if (lightType != DynamicLightType.NONE && lightRadius > thing.Size)
|
||||
//mxd. update bounding box?
|
||||
if(lightType != DynamicLightType.NONE && lightRadius > thing.Size)
|
||||
{
|
||||
UpdateBoundingBox(lightRadius, lightRadius * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateBoundingBox((int)thing.Size, thingHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// This sets the vertices for the thing sprite
|
||||
|
@ -326,10 +318,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
}
|
||||
else
|
||||
{
|
||||
if (thing.IsModel)
|
||||
UpdateBoundingBoxForModel();
|
||||
else
|
||||
UpdateBoundingBox((int)thing.Size, thingHeight);
|
||||
UpdateBoundingBox((int)thing.Size, thingHeight);
|
||||
|
||||
lightType = DynamicLightType.NONE;
|
||||
lightRadius = -1;
|
||||
|
@ -494,12 +483,8 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
//mxd. update bounding box
|
||||
public void UpdateBoundingBox()
|
||||
{
|
||||
if (thing.IsModel)
|
||||
UpdateBoundingBoxForModel();
|
||||
else if (lightType != DynamicLightType.NONE && lightRadius > thing.Size)
|
||||
if(lightType != DynamicLightType.NONE && lightRadius > thing.Size)
|
||||
UpdateBoundingBox(lightRadius, lightRadius * 2);
|
||||
else
|
||||
UpdateBoundingBox((int)thing.Size, thingHeight);
|
||||
}
|
||||
|
||||
private void UpdateBoundingBox(float width, float height)
|
||||
|
@ -518,19 +503,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
boundingBox[7] = new Vector3(position_v3.X - width, position_v3.Y + width, Center.Z + h2);
|
||||
boundingBox[8] = new Vector3(position_v3.X + width, position_v3.Y + width, Center.Z + h2);
|
||||
}
|
||||
|
||||
//mxd. update bounding box from model bounding box
|
||||
private void UpdateBoundingBoxForModel()
|
||||
{
|
||||
ModelData mde = General.Map.Data.ModeldefEntries[thing.Type];
|
||||
int len = mde.Model.BoundingBox.Length;
|
||||
boundingBox = new Vector3[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Vector3 v = mde.Model.BoundingBox[i];
|
||||
boundingBox[i] = new Vector3(v.X + position_v3.X, v.Y + position_v3.Y, v.Z + position_v3.Z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the thing must be tested for line intersection. This should reject
|
||||
|
|
Loading…
Reference in a new issue