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:
MaxED 2015-06-22 19:52:23 +00:00
parent e451d38986
commit a523f7eb28
7 changed files with 46 additions and 138 deletions

View file

@ -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;
}
}
}

View file

@ -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()
{

View file

@ -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);

View file

@ -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;

View file

@ -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)
{

View file

@ -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);

View file

@ -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