mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-23 12:22:35 +00:00
visual mode extreme makeover! (internally at least) now using proper view frustum for culling and lots of other improvements to render the map more efficiently
This commit is contained in:
parent
5dcc9d584d
commit
43a0e69de7
23 changed files with 587 additions and 234 deletions
|
@ -650,8 +650,10 @@
|
|||
<None Include="Resources\Close.png" />
|
||||
<Compile Include="Editing\EditingManager.cs" />
|
||||
<Content Include="Resources\DB2.ico" />
|
||||
<Compile Include="Geometry\ProjectedFrustum2D.cs" />
|
||||
<Compile Include="VisualModes\Clipper.cs" />
|
||||
<Compile Include="VisualModes\VisualBlockEntry.cs" />
|
||||
<Compile Include="VisualModes\VisualSidedef.cs" />
|
||||
<None Include="Resources\Script2.png" />
|
||||
<None Include="Resources\ScriptCompile.png" />
|
||||
<None Include="Resources\ScriptConstant.xpm" />
|
||||
|
|
|
@ -217,8 +217,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// Go for all drawn points
|
||||
foreach(DrawnVertex v in points)
|
||||
{
|
||||
Vector2D delta = mousemappos - v.pos;
|
||||
if(delta.GetLengthSq() < (vrange * vrange))
|
||||
if(Vector2D.DistanceSq(mousemappos, v.pos) < (vrange * vrange))
|
||||
{
|
||||
p.pos = v.pos;
|
||||
p.stitch = true;
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
// Load floor texture
|
||||
base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
|
||||
if(base.Texture == null) base.Texture = General.Map.Data.MissingTexture3D;
|
||||
|
||||
// Make vertices
|
||||
verts = new WorldVertex[s.Triangles.Vertices.Count];
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
// Load floor texture
|
||||
base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
|
||||
if(base.Texture == null) base.Texture = General.Map.Data.MissingTexture3D;
|
||||
|
||||
// Make vertices
|
||||
verts = new WorldVertex[s.Triangles.Vertices.Count];
|
||||
|
|
|
@ -39,7 +39,7 @@ using CodeImp.DoomBuilder.VisualModes;
|
|||
|
||||
namespace CodeImp.DoomBuilder.BuilderModes
|
||||
{
|
||||
internal class VisualLower : VisualGeometry
|
||||
internal class VisualLower : VisualSidedef
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public VisualLower(Sidedef s)
|
||||
public VisualLower(Sidedef s) : base(s)
|
||||
{
|
||||
WorldVertex[] verts;
|
||||
float geotop;
|
||||
|
@ -75,6 +75,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
// Load texture
|
||||
base.Texture = General.Map.Data.GetTextureImage(s.LongLowTexture);
|
||||
if(base.Texture == null) base.Texture = General.Map.Data.MissingTexture3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ using CodeImp.DoomBuilder.VisualModes;
|
|||
|
||||
namespace CodeImp.DoomBuilder.BuilderModes
|
||||
{
|
||||
internal class VisualMiddle : VisualGeometry
|
||||
internal class VisualMiddle : VisualSidedef
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public VisualMiddle(Sidedef s)
|
||||
public VisualMiddle(Sidedef s) : base(s)
|
||||
{
|
||||
WorldVertex[] verts;
|
||||
float geotop;
|
||||
|
@ -84,6 +84,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
// Load texture
|
||||
base.Texture = General.Map.Data.GetTextureImage(s.LongMiddleTexture);
|
||||
if(base.Texture == null) base.Texture = General.Map.Data.MissingTexture3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ using CodeImp.DoomBuilder.VisualModes;
|
|||
|
||||
namespace CodeImp.DoomBuilder.BuilderModes
|
||||
{
|
||||
internal class VisualUpper : VisualGeometry
|
||||
internal class VisualUpper : VisualSidedef
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public VisualUpper(Sidedef s)
|
||||
public VisualUpper(Sidedef s) : base(s)
|
||||
{
|
||||
WorldVertex[] verts;
|
||||
float geotop;
|
||||
|
@ -75,6 +75,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
// Load texture
|
||||
base.Texture = General.Map.Data.GetTextureImage(s.LongHighTexture);
|
||||
if(base.Texture == null) base.Texture = General.Map.Data.MissingTexture3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1208,6 +1208,16 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
#region ================== Methods
|
||||
|
||||
// This updates everything after the configuration or settings have been changed
|
||||
internal void UpdateConfiguration()
|
||||
{
|
||||
// Update map
|
||||
map.UpdateConfiguration();
|
||||
|
||||
// Update settings
|
||||
renderer3d.CreateProjection();
|
||||
}
|
||||
|
||||
// This changes thing filter
|
||||
internal void ChangeThingFilter(ThingsFilter newfilter)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
|
@ -34,7 +34,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
public const float PIHALF = (float)Math.PI * 0.5f;
|
||||
public const float PI2 = (float)Math.PI * 2f;
|
||||
public const float PIDEG = 57.295779513082320876798154814105f;
|
||||
|
||||
public const float SQRT2 = 1.4142135623730950488016887242097f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
|
|
@ -215,6 +215,12 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
public float GetLength() { return Line2D.GetLength(v2.x - v1.x, v2.y - v1.y); }
|
||||
public float GetLengthSq() { return Line2D.GetLengthSq(v2.x - v1.x, v2.y - v1.y); }
|
||||
|
||||
// Output
|
||||
public override string ToString()
|
||||
{
|
||||
return "(" + v1 + ") - (" + v2 + ")";
|
||||
}
|
||||
|
||||
public bool GetIntersection(float x3, float y3, float x4, float y4)
|
||||
{
|
||||
return Line2D.GetIntersection(v1, v2, x3, y3, x4, y4);
|
||||
|
|
156
Source/Geometry/ProjectedFrustum2D.cs
Normal file
156
Source/Geometry/ProjectedFrustum2D.cs
Normal file
|
@ -0,0 +1,156 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using CodeImp.DoomBuilder.VisualModes;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Geometry
|
||||
{
|
||||
public class ProjectedFrustum2D
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
// Frustum settings
|
||||
private float near;
|
||||
private float far;
|
||||
private float fov;
|
||||
private Vector2D pos;
|
||||
private float xyangle;
|
||||
private float zangle;
|
||||
|
||||
// Frustum lines
|
||||
private Line2D[] lines;
|
||||
|
||||
// Circle
|
||||
private Vector2D center;
|
||||
private float radius;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public float Near { get { return near; } }
|
||||
public float Far { get { return far; } }
|
||||
public float Fov { get { return fov; } }
|
||||
public Vector2D Position { get { return pos; } }
|
||||
public float XYAngle { get { return xyangle; } }
|
||||
public float ZAngle { get { return zangle; } }
|
||||
public Line2D[] Lines { get { return lines; } }
|
||||
public Vector2D Center { get { return center; } }
|
||||
public float Radius { get { return radius; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Destructor
|
||||
|
||||
// Constructor
|
||||
public ProjectedFrustum2D(Vector2D pos, float xyangle, float zangle, float near, float far, float fov)
|
||||
{
|
||||
Vector2D[] forwards = new Vector2D[4];
|
||||
Vector2D[] downwards = new Vector2D[4];
|
||||
Vector2D[] corners = new Vector2D[4];
|
||||
|
||||
// Initialize
|
||||
this.pos = pos;
|
||||
this.xyangle = xyangle;
|
||||
this.zangle = zangle;
|
||||
this.near = near;
|
||||
this.far = far;
|
||||
this.fov = fov;
|
||||
|
||||
// Make the corners for a forward frustum
|
||||
// The corners are in this order: Left-Far, Right-Far, Left-Near, Right-Near
|
||||
float fovhalf = fov * 0.5f;
|
||||
float fovhalfcos = (float)Math.Cos(fovhalf);
|
||||
float farsidelength = far / fovhalfcos;
|
||||
float nearsidelength = near / fovhalfcos;
|
||||
forwards[0] = pos + Vector2D.FromAngle(xyangle - fovhalf, farsidelength);
|
||||
forwards[1] = pos + Vector2D.FromAngle(xyangle + fovhalf, farsidelength);
|
||||
forwards[2] = pos + Vector2D.FromAngle(xyangle - fovhalf, nearsidelength);
|
||||
forwards[3] = pos + Vector2D.FromAngle(xyangle + fovhalf, nearsidelength);
|
||||
|
||||
// Make the corners for a downward frustum
|
||||
// The corners are in the same order as above
|
||||
//float farradius = far * (float)Math.Tan(fovhalf) * Angle2D.SQRT2;
|
||||
float farradius = far * 0.5f * Angle2D.SQRT2;
|
||||
downwards[0] = pos + Vector2D.FromAngle(xyangle - Angle2D.PI * 0.25f, farradius);
|
||||
downwards[1] = pos + Vector2D.FromAngle(xyangle + Angle2D.PI * 0.25f, farradius);
|
||||
downwards[2] = pos + Vector2D.FromAngle(xyangle - Angle2D.PI * 0.75f, farradius);
|
||||
downwards[3] = pos + Vector2D.FromAngle(xyangle + Angle2D.PI * 0.75f, farradius);
|
||||
|
||||
// Interpolate between the two to make the final corners depending on the z angle
|
||||
float d = Math.Abs((float)Math.Sin(zangle));
|
||||
corners[0] = forwards[0] * (1.0f - d) + downwards[0] * d;
|
||||
corners[1] = forwards[1] * (1.0f - d) + downwards[1] * d;
|
||||
corners[2] = forwards[2] * (1.0f - d) + downwards[2] * d;
|
||||
corners[3] = forwards[3] * (1.0f - d) + downwards[3] * d;
|
||||
|
||||
// Make the frustum lines
|
||||
// Note that the lines all have their right side inside the frustum!
|
||||
lines = new Line2D[4];
|
||||
lines[0] = new Line2D(corners[2], corners[0]);
|
||||
lines[1] = new Line2D(corners[1], corners[3]);
|
||||
lines[2] = new Line2D(corners[3], corners[2]);
|
||||
lines[3] = new Line2D(corners[0], corners[1]);
|
||||
|
||||
// Calculate the circle center
|
||||
center = (corners[0] + corners[1] + corners[2] + corners[3]) * 0.25f;
|
||||
|
||||
// Calculate the radius from the center to the farthest corner
|
||||
float radius2 = 0.0f;
|
||||
for(int i = 0; i < corners.Length; i++)
|
||||
{
|
||||
float distance2 = Vector2D.DistanceSq(center, corners[i]);
|
||||
if(distance2 > radius2) radius2 = distance2;
|
||||
}
|
||||
radius = (float)Math.Sqrt(radius2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// This checks if a specified circle is intersecting the frustum
|
||||
// NOTE: This checks only against the actual frustum and does not use the frustum circle!
|
||||
public bool IntersectCircle(Vector2D circlecenter, float circleradius)
|
||||
{
|
||||
// Go for all frustum lines
|
||||
for(int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
// Check on which side the circle center lies
|
||||
if(lines[i].GetSideOfLine(circlecenter) < 0)
|
||||
{
|
||||
// Center is outside the frustum
|
||||
// If the circle is not overlapping, it is not intersecting.
|
||||
if(lines[i].GetDistanceToLineSq(circlecenter, false) > (circleradius * circleradius)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Intersecting!
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -221,6 +221,20 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
return -(float)Math.Atan2(-(a.y - b.y), (a.x - b.x)) + (float)Math.PI * 0.5f;
|
||||
}
|
||||
|
||||
// This returns the square distance between two points
|
||||
public static float DistanceSq(Vector2D a, Vector2D b)
|
||||
{
|
||||
Vector2D d = a - b;
|
||||
return d.GetLengthSq();
|
||||
}
|
||||
|
||||
// This returns the distance between two points
|
||||
public static float Distance(Vector2D a, Vector2D b)
|
||||
{
|
||||
Vector2D d = a - b;
|
||||
return d.GetLength();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
|
|
@ -217,8 +217,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
Vector2D xy = new Vector2D(x, y);
|
||||
|
||||
// Calculate and return the angle
|
||||
return -(float)Math.Atan2(xy.GetLength(), z) + (float)Math.PI * 0.5f;
|
||||
//return -(float)Math.Atan2(xy.GetLength(), z) - (float)Math.PI * 0.5f;
|
||||
return (float)Math.Atan2(xy.GetLength(), z) + (float)Math.PI * 0.5f;
|
||||
}
|
||||
|
||||
// This calculates the length
|
||||
|
|
|
@ -243,14 +243,11 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// This updates the line when changes have been made
|
||||
public void UpdateCache()
|
||||
{
|
||||
Vector2D delta;
|
||||
float l, t, r, b;
|
||||
|
||||
// Update if needed
|
||||
if(updateneeded)
|
||||
{
|
||||
// Delta vector
|
||||
delta = end.Position - start.Position;
|
||||
Vector2D delta = end.Position - start.Position;
|
||||
|
||||
// Recalculate values
|
||||
lengthsq = delta.GetLengthSq();
|
||||
|
@ -258,10 +255,10 @@ namespace CodeImp.DoomBuilder.Map
|
|||
if(length > 0f) lengthinv = 1f / length; else lengthinv = 1f / 0.0000000001f;
|
||||
if(lengthsq > 0f) lengthsqinv = 1f / lengthsq; else lengthsqinv = 1f / 0.0000000001f;
|
||||
angle = delta.GetAngle();
|
||||
l = Math.Min(start.Position.x, end.Position.x);
|
||||
t = Math.Min(start.Position.y, end.Position.y);
|
||||
r = Math.Max(start.Position.x, end.Position.x);
|
||||
b = Math.Max(start.Position.y, end.Position.y);
|
||||
float l = Math.Min(start.Position.x, end.Position.x);
|
||||
float t = Math.Min(start.Position.y, end.Position.y);
|
||||
float r = Math.Max(start.Position.x, end.Position.x);
|
||||
float b = Math.Max(start.Position.y, end.Position.y);
|
||||
rect = new RectangleF(l, t, r - l, b - t);
|
||||
|
||||
// Updated
|
||||
|
|
|
@ -296,15 +296,13 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// This returns the distance from given coordinates
|
||||
public float DistanceToSq(Vector2D p)
|
||||
{
|
||||
Vector2D delta = p - (Vector2D)pos;
|
||||
return delta.GetLengthSq();
|
||||
return Vector2D.DistanceSq(p, pos);
|
||||
}
|
||||
|
||||
// This returns the distance from given coordinates
|
||||
public float DistanceTo(Vector2D p)
|
||||
{
|
||||
Vector2D delta = p - (Vector2D)pos;
|
||||
return delta.GetLength();
|
||||
return Vector2D.Distance(p, pos);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -154,8 +154,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// This returns the distance from given coordinates
|
||||
public float DistanceTo(Vector2D p)
|
||||
{
|
||||
Vector2D delta = p - pos;
|
||||
return delta.GetLength();
|
||||
return Vector2D.Distance(p, pos);
|
||||
}
|
||||
|
||||
// This finds the line closest to the specified position
|
||||
|
|
|
@ -41,11 +41,19 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
{
|
||||
public interface IRenderer3D
|
||||
{
|
||||
// Properties
|
||||
ProjectedFrustum2D Frustum2D { get; }
|
||||
|
||||
// General methods
|
||||
void PositionAndLookAt(Vector3D pos, Vector3D lookat);
|
||||
|
||||
// Presenting methods
|
||||
void Finish();
|
||||
bool Start();
|
||||
void StartGeometry();
|
||||
void FinishGeometry();
|
||||
void RenderGeometry(VisualSector s);
|
||||
void PositionAndLookAt(Vector3D pos, Vector3D lookat);
|
||||
|
||||
// Rendering methods
|
||||
void RenderGeometry(VisualGeometry g);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
#region ================== Constants
|
||||
|
||||
private const float PROJ_NEAR_PLANE = 1f;
|
||||
private const float PROJ_FAR_PLANE = 5000f;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -53,10 +52,18 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
private Matrix billboard;
|
||||
private Matrix viewproj;
|
||||
|
||||
// Frustum
|
||||
private ProjectedFrustum2D frustum;
|
||||
|
||||
// Geometry, grouped by texture
|
||||
private Dictionary<ImageData, List<VisualGeometry>> geometry;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public ProjectedFrustum2D Frustum2D { get { return frustum; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
@ -66,6 +73,10 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
{
|
||||
// Initialize
|
||||
CreateProjection();
|
||||
|
||||
// Dummy frustum
|
||||
frustum = new ProjectedFrustum2D(new Vector2D(), 0.0f, 0.0f, PROJ_NEAR_PLANE,
|
||||
General.Settings.ViewDistance, Angle2D.DegToRad((float)General.Settings.VisualFOV));
|
||||
|
||||
// We have no destructor
|
||||
GC.SuppressFinalize(this);
|
||||
|
@ -107,15 +118,22 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
// This creates the projection
|
||||
internal void CreateProjection()
|
||||
{
|
||||
// Calculate FOV
|
||||
float fov = Angle2D.DegToRad((float)General.Settings.VisualFOV);
|
||||
|
||||
// Calculate aspect
|
||||
float aspect = (float)General.Map.Graphics.RenderTarget.ClientSize.Width /
|
||||
(float)General.Map.Graphics.RenderTarget.ClientSize.Height;
|
||||
|
||||
// The DirectX PerspectiveFovRH matrix method calculates the scaling in X and Y as follows:
|
||||
// yscale = 1 / tan(fovY / 2)
|
||||
// xscale = yscale / aspect
|
||||
// The fov specified in the method is the FOV over Y, but we want the user to specify the FOV
|
||||
// over X, so calculate what it would be over Y first;
|
||||
float fov = Angle2D.DegToRad((float)General.Settings.VisualFOV);
|
||||
float reversefov = 1.0f / (float)Math.Tan(fov / 2.0f);
|
||||
float reversefovy = reversefov * aspect;
|
||||
float fovy = (float)Math.Atan(1.0f / reversefovy) * 2.0f;
|
||||
|
||||
// Make the projection matrix
|
||||
projection = Matrix.PerspectiveFovRH(fov, aspect, PROJ_NEAR_PLANE, PROJ_FAR_PLANE);
|
||||
projection = Matrix.PerspectiveFovRH(fovy, aspect, PROJ_NEAR_PLANE, General.Settings.ViewDistance);
|
||||
|
||||
// Apply matrices
|
||||
ApplyMatrices();
|
||||
|
@ -131,12 +149,16 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
delta = lookat - pos;
|
||||
anglexy = delta.GetAngleXY();
|
||||
anglez = delta.GetAngleZ();
|
||||
|
||||
// Create frustum
|
||||
frustum = new ProjectedFrustum2D(pos, anglexy, anglez, PROJ_NEAR_PLANE,
|
||||
General.Settings.ViewDistance, Angle2D.DegToRad((float)General.Settings.VisualFOV));
|
||||
|
||||
// Make the view matrix
|
||||
view = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f));
|
||||
|
||||
// Make the billboard matrix
|
||||
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PIHALF);
|
||||
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PI);
|
||||
}
|
||||
|
||||
// This applies the matrices
|
||||
|
@ -195,14 +217,57 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
graphics.Shaders.World3D.Begin();
|
||||
graphics.Shaders.World3D.WorldViewProj = viewproj;
|
||||
graphics.Shaders.World3D.BeginPass(0);
|
||||
|
||||
// Make collection
|
||||
geometry = new Dictionary<ImageData, List<VisualGeometry>>();
|
||||
}
|
||||
|
||||
// This ends rendering world geometry
|
||||
public void FinishGeometry()
|
||||
{
|
||||
// We now render the actual geometry collected
|
||||
foreach(KeyValuePair<ImageData, List<VisualGeometry>> group in geometry)
|
||||
{
|
||||
ImageData curtexture;
|
||||
|
||||
// What texture to use?
|
||||
if((group.Key != null) && group.Key.IsImageLoaded && !group.Key.IsDisposed)
|
||||
curtexture = group.Key;
|
||||
else
|
||||
curtexture = General.Map.Data.Hourglass3D;
|
||||
|
||||
// Create Direct3D texture if still needed
|
||||
if((curtexture.Texture == null) || curtexture.Texture.Disposed)
|
||||
curtexture.CreateTexture();
|
||||
|
||||
// Apply texture
|
||||
graphics.Device.SetTexture(0, curtexture.Texture);
|
||||
graphics.Shaders.World3D.Texture1 = curtexture.Texture;
|
||||
graphics.Shaders.World3D.ApplySettings();
|
||||
|
||||
// Go for all geometry that uses this texture
|
||||
foreach(VisualGeometry g in group.Value)
|
||||
{
|
||||
// Update the sector if needed
|
||||
if(g.Sector.NeedsUpdateGeo) g.Sector.Update();
|
||||
|
||||
// Only render when a vertexbuffer exists
|
||||
if(g.Sector.GeometryBuffer != null)
|
||||
{
|
||||
// Render!
|
||||
graphics.Device.SetStreamSource(0, g.Sector.GeometryBuffer, 0, WorldVertex.Stride);
|
||||
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove references
|
||||
graphics.Shaders.World3D.Texture1 = null;
|
||||
|
||||
// Done
|
||||
graphics.Shaders.World3D.EndPass();
|
||||
graphics.Shaders.World3D.End();
|
||||
geometry = null;
|
||||
}
|
||||
|
||||
// This finishes rendering
|
||||
|
@ -218,52 +283,20 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
#region ================== Geometry
|
||||
|
||||
// This renders a visual sector's geometry
|
||||
public void RenderGeometry(VisualSector s)
|
||||
public void RenderGeometry(VisualGeometry g)
|
||||
{
|
||||
ImageData lasttexture = null;
|
||||
|
||||
// Update the sector if needed
|
||||
if(s.NeedsUpdateGeo) s.Update();
|
||||
|
||||
// Only render when a vertexbuffer exists
|
||||
if(s.GeometryBuffer != null)
|
||||
// Must have a texture!
|
||||
if(g.Texture != null)
|
||||
{
|
||||
// Set the buffer
|
||||
graphics.Device.SetStreamSource(0, s.GeometryBuffer, 0, WorldVertex.Stride);
|
||||
|
||||
// Go for all geometry in this sector
|
||||
foreach(VisualGeometry g in s.GeometryList)
|
||||
// Texture group not yet collected?
|
||||
if(!geometry.ContainsKey(g.Texture))
|
||||
{
|
||||
ImageData curtexture;
|
||||
|
||||
// What texture to use?
|
||||
if((g.Texture != null) && g.Texture.IsImageLoaded && !g.Texture.IsDisposed)
|
||||
curtexture = g.Texture;
|
||||
else
|
||||
curtexture = General.Map.Data.Hourglass3D;
|
||||
|
||||
// Change texture?
|
||||
if(curtexture != lasttexture)
|
||||
{
|
||||
// Now using this texture
|
||||
lasttexture = curtexture;
|
||||
|
||||
// Create Direct3D texture if still needed
|
||||
if((curtexture.Texture == null) || curtexture.Texture.Disposed)
|
||||
curtexture.CreateTexture();
|
||||
|
||||
// Apply texture
|
||||
graphics.Device.SetTexture(0, curtexture.Texture);
|
||||
graphics.Shaders.World3D.Texture1 = curtexture.Texture;
|
||||
graphics.Shaders.World3D.ApplySettings();
|
||||
}
|
||||
|
||||
// Render it!
|
||||
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles);
|
||||
// Create texture group
|
||||
geometry.Add(g.Texture, new List<VisualGeometry>());
|
||||
}
|
||||
|
||||
// Remove references
|
||||
graphics.Shaders.World3D.Texture1 = null;
|
||||
// Add geometry to texture group
|
||||
geometry[g.Texture].Add(g);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
|
||||
public const int BLOCK_SIZE_SHIFT = 7;
|
||||
public const int BLOCK_SIZE = 1 << BLOCK_SIZE_SHIFT;
|
||||
public const float BLOCK_RADIUS = BLOCK_SIZE * Angle2D.SQRT2;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -96,8 +97,16 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
return new Point((int)v.x >> BLOCK_SIZE_SHIFT,
|
||||
(int)v.y >> BLOCK_SIZE_SHIFT);
|
||||
}
|
||||
|
||||
|
||||
// This returns the block center in world coordinates
|
||||
public Vector2D GetBlockCenter(Point p)
|
||||
{
|
||||
return new Vector2D((float)((p.X << BLOCK_SIZE_SHIFT) + (BLOCK_SIZE >> 1)),
|
||||
(float)((p.Y << BLOCK_SIZE_SHIFT) + (BLOCK_SIZE >> 1)));
|
||||
}
|
||||
|
||||
// This returns the key for a block at the given coordinates
|
||||
// TODO: Could we just use the Point struct as key?
|
||||
private ulong GetBlockKey(Point p)
|
||||
{
|
||||
return unchecked( ((ulong)(uint)p.X << 32) + (ulong)(uint)p.Y );
|
||||
|
@ -146,6 +155,39 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
return entries;
|
||||
}
|
||||
|
||||
// This returns a range of blocks in a frustum
|
||||
public List<VisualBlockEntry> GetFrustumRange(ProjectedFrustum2D frustum)
|
||||
{
|
||||
// Make square range from frustum circle
|
||||
// This will be the range in which we will test blocks
|
||||
Point lt = GetBlockCoordinates(frustum.Center - frustum.Radius);
|
||||
Point rb = GetBlockCoordinates(frustum.Center + frustum.Radius);
|
||||
|
||||
// Constants we need
|
||||
float blockfrustumdistance2 = (frustum.Radius * frustum.Radius) + (BLOCK_RADIUS * BLOCK_RADIUS);
|
||||
|
||||
// Go through the range to make a list
|
||||
int entriescount = (rb.X - lt.X) * (rb.Y - lt.Y);
|
||||
List<VisualBlockEntry> entries = new List<VisualBlockEntry>(entriescount);
|
||||
for(int x = lt.X; x <= rb.X; x++)
|
||||
{
|
||||
for(int y = lt.Y; y <= rb.Y; y++)
|
||||
{
|
||||
// First check if the block circle is intersecting the frustum circle
|
||||
Point block = new Point(x, y);
|
||||
Vector2D blockcenter = GetBlockCenter(block);
|
||||
if(Vector2D.DistanceSq(frustum.Center, blockcenter) < blockfrustumdistance2)
|
||||
{
|
||||
// Add the block if the block circle is inside the frustum
|
||||
if(frustum.IntersectCircle(blockcenter, BLOCK_RADIUS)) entries.Add(GetBlock(block));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return list
|
||||
return entries;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Advanced Methods
|
||||
|
|
|
@ -46,10 +46,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
#region ================== Constants
|
||||
|
||||
private const float ANGLE_FROM_MOUSE = 0.0001f;
|
||||
private const float MAX_ANGLEZ_LOW = 100f / Angle2D.PIDEG;
|
||||
private const float MAX_ANGLEZ_HIGH = (360f - 100f) / Angle2D.PIDEG;
|
||||
public const float MAX_ANGLEZ_LOW = 100f / Angle2D.PIDEG;
|
||||
public const float MAX_ANGLEZ_HIGH = (360f - 100f) / Angle2D.PIDEG;
|
||||
private const float CAMERA_SPEED = 6f;
|
||||
private const double SECTOR_UPDATE_INTERVAL = 100d;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -66,10 +65,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
private Vector3D campos;
|
||||
private Vector3D camtarget;
|
||||
private float camanglexy, camanglez;
|
||||
|
||||
// Processing
|
||||
private double lastsectorupdatetime;
|
||||
private Sector viewstartsector;
|
||||
private Sector camsector;
|
||||
|
||||
// Input
|
||||
private bool keyforward;
|
||||
|
@ -80,7 +76,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
// Map
|
||||
protected VisualBlockMap blockmap;
|
||||
protected Dictionary<Sector, VisualSector> allsectors;
|
||||
protected List<VisualBlockEntry> visibleblocks;
|
||||
protected Dictionary<Sector, VisualSector> visiblesectors;
|
||||
protected List<VisualGeometry> visiblegeometry;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -88,6 +86,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
|
||||
public Vector3D CameraPosition { get { return campos; } set { campos = value; } }
|
||||
public Vector3D CameraTarget { get { return camtarget; } }
|
||||
public Sector CameraSector { get { return camsector; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -105,7 +104,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
this.camanglez = Angle2D.PI;
|
||||
this.blockmap = new VisualBlockMap();
|
||||
this.allsectors = new Dictionary<Sector, VisualSector>(General.Map.Map.Sectors.Count);
|
||||
this.visibleblocks = new List<VisualBlockEntry>();
|
||||
this.visiblesectors = new Dictionary<Sector, VisualSector>(50);
|
||||
this.visiblegeometry = new List<VisualGeometry>(200);
|
||||
}
|
||||
|
||||
// Disposer
|
||||
|
@ -118,6 +119,8 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
foreach(KeyValuePair<Sector, VisualSector> s in allsectors) s.Value.Dispose();
|
||||
blockmap.Dispose();
|
||||
visiblesectors = null;
|
||||
visiblegeometry = null;
|
||||
visibleblocks = null;
|
||||
allsectors = null;
|
||||
blockmap = null;
|
||||
|
||||
|
@ -274,152 +277,126 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
// This preforms visibility culling
|
||||
private void DoCulling()
|
||||
{
|
||||
Dictionary<Linedef, Linedef> visiblelines = new Dictionary<Linedef, Linedef>(200);
|
||||
Vector2D campos2d = (Vector2D)campos;
|
||||
float viewdist = General.Settings.ViewDistance;
|
||||
|
||||
// Get the blocks within view range and make a collection of all nearby linedefs
|
||||
RectangleF viewrect = new RectangleF(campos.x - viewdist, campos.y - viewdist, viewdist * 2, viewdist * 2);
|
||||
List<VisualBlockEntry> blocks = blockmap.GetSquareRange(viewrect);
|
||||
List<Linedef> nearbylines = new List<Linedef>(blocks.Count);
|
||||
foreach(VisualBlockEntry b in blocks) nearbylines.AddRange(b.Lines);
|
||||
// Get the blocks within view range
|
||||
visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D);
|
||||
|
||||
// Find the sector to begin with
|
||||
if(General.Clock.CurrentTime > (lastsectorupdatetime + SECTOR_UPDATE_INTERVAL))
|
||||
{
|
||||
lastsectorupdatetime = General.Clock.CurrentTime;
|
||||
viewstartsector = FindStartSector((Vector2D)campos, nearbylines);
|
||||
}
|
||||
|
||||
// Find visible sectors
|
||||
// Fill visiblity collections
|
||||
visiblesectors = new Dictionary<Sector, VisualSector>(visiblesectors.Count);
|
||||
if(viewstartsector != null) ProcessVisibleSectors(viewstartsector, (Vector2D)campos);
|
||||
visiblegeometry = new List<VisualGeometry>(visiblegeometry.Capacity);
|
||||
foreach(VisualBlockEntry block in visibleblocks)
|
||||
{
|
||||
foreach(Linedef ld in block.Lines)
|
||||
{
|
||||
// Add line if not added yet
|
||||
visiblelines[ld] = ld;
|
||||
|
||||
// Which side of the line is the camera on?
|
||||
if(ld.SideOfLine(campos2d) < 0)
|
||||
{
|
||||
// Do front of line
|
||||
if(ld.Front != null) ProcessSidedef(ld.Front);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do back of line
|
||||
if(ld.Back != null) ProcessSidedef(ld.Back);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find camera sector
|
||||
Linedef nld = MapSet.NearestLinedef(visiblelines.Values, campos2d);
|
||||
if(nld != null)
|
||||
{
|
||||
camsector = GetCameraSectorFromLinedef(nld);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exceptional case: no lines found in any nearby blocks!
|
||||
// This could happen in the middle of an extremely large sector and in this case
|
||||
// the above code will not have found any sectors/sidedefs for rendering.
|
||||
// Here we handle this special case with brute-force. Let's find the sector
|
||||
// the camera is in by searching the entire map and render that sector only.
|
||||
nld = General.Map.Map.NearestLinedef(campos2d);
|
||||
if(nld != null)
|
||||
{
|
||||
camsector = GetCameraSectorFromLinedef(nld);
|
||||
if(camsector != null)
|
||||
{
|
||||
foreach(Sidedef sd in camsector.Sidedefs)
|
||||
{
|
||||
float side = sd.Line.SideOfLine(campos2d);
|
||||
if(((side < 0) && sd.IsFront) ||
|
||||
((side > 0) && !sd.IsFront))
|
||||
ProcessSidedef(sd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Too far away from the map to see anything
|
||||
camsector = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Map is empty
|
||||
camsector = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This finds and adds visible sectors
|
||||
private void ProcessVisibleSectors(Sector start, Vector2D campos)
|
||||
private void ProcessSidedef(Sidedef sd)
|
||||
{
|
||||
Stack<Sector> todo = new Stack<Sector>(50);
|
||||
Dictionary<Sector, Sector> stackedsectors = new Dictionary<Sector, Sector>(50);
|
||||
Clipper clipper = new Clipper(campos);
|
||||
float viewdist2 = General.Settings.ViewDistance * General.Settings.ViewDistance;
|
||||
|
||||
// TODO: Use sector markings instead of the stackedsectors dictionary?
|
||||
|
||||
// This algorithm uses a breadth-first search for visible sectors
|
||||
|
||||
// Continue until no more sectors to process
|
||||
todo.Push(start);
|
||||
stackedsectors.Add(start, start);
|
||||
while(todo.Count > 0)
|
||||
VisualSector vs;
|
||||
|
||||
// Find the visualsector and make it if needed
|
||||
if(allsectors.ContainsKey(sd.Sector))
|
||||
{
|
||||
Sector s = todo.Pop();
|
||||
VisualSector vs;
|
||||
|
||||
// Find the basesector and make it if needed
|
||||
if(allsectors.ContainsKey(s))
|
||||
{
|
||||
// Take existing visualsector
|
||||
vs = allsectors[s];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make new visualsector
|
||||
vs = CreateVisualSector(s);
|
||||
allsectors.Add(s, vs);
|
||||
}
|
||||
|
||||
// Add sector to visibility list
|
||||
visiblesectors.Add(s, vs);
|
||||
|
||||
// Go for all sidedefs in the sector
|
||||
foreach(Sidedef sd in s.Sidedefs)
|
||||
{
|
||||
// Camera on the front of this side?
|
||||
float side = sd.Line.SideOfLine(campos);
|
||||
if(((side > 0) && sd.IsFront) ||
|
||||
((side < 0) && !sd.IsFront))
|
||||
{
|
||||
// Sidedef blocking the view?
|
||||
if((sd.Other == null) ||
|
||||
(sd.Other.Sector.FloorHeight >= (sd.Sector.CeilHeight - 0.0001f)) ||
|
||||
(sd.Other.Sector.CeilHeight <= (sd.Sector.FloorHeight + 0.0001f)) ||
|
||||
(sd.Other.Sector.FloorHeight >= (sd.Other.Sector.CeilHeight - 0.0001f)))
|
||||
{
|
||||
// This blocks the view
|
||||
//clipper.InsertRange(sd.Line.Start.Position, sd.Line.End.Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go for all sidedefs in the sector
|
||||
foreach(Sidedef sd in s.Sidedefs)
|
||||
{
|
||||
// Doublesided and not referring to same sector?
|
||||
if((sd.Other != null) && (sd.Other.Sector != sd.Sector))
|
||||
{
|
||||
// Get the other sector
|
||||
Sector os = sd.Other.Sector;
|
||||
|
||||
// Sector not added yet?
|
||||
if(!stackedsectors.ContainsKey(os))
|
||||
{
|
||||
// Within view range?
|
||||
if(sd.Line.DistanceToSq(campos, true) < viewdist2)
|
||||
{
|
||||
// Can we see this sector?
|
||||
//if(clipper.TestRange(sd.Line.Start.Position, sd.Line.End.Position))
|
||||
{
|
||||
// Process this sector as well
|
||||
todo.Push(os);
|
||||
stackedsectors.Add(os, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done
|
||||
clipper.Dispose();
|
||||
}
|
||||
|
||||
// This finds the nearest sector to the camera
|
||||
private Sector FindStartSector(Vector2D campos, List<Linedef> lines)
|
||||
{
|
||||
float side;
|
||||
Linedef l;
|
||||
|
||||
// Get nearest linedef
|
||||
l = MapSet.NearestLinedef(lines, campos);
|
||||
if(l != null)
|
||||
{
|
||||
// Check if we are on front or back side
|
||||
side = l.SideOfLine(campos);
|
||||
if(side > 0)
|
||||
{
|
||||
// Is there a sidedef here?
|
||||
if(l.Back != null)
|
||||
return l.Back.Sector;
|
||||
else if(l.Front != null)
|
||||
return l.Front.Sector;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Is there a sidedef here?
|
||||
if(l.Front != null)
|
||||
return l.Front.Sector;
|
||||
else if(l.Back != null)
|
||||
return l.Back.Sector;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
// Take existing visualsector
|
||||
vs = allsectors[sd.Sector];
|
||||
}
|
||||
else
|
||||
return null;
|
||||
{
|
||||
// Make new visualsector
|
||||
vs = CreateVisualSector(sd.Sector);
|
||||
allsectors.Add(sd.Sector, vs);
|
||||
}
|
||||
|
||||
// Add to visible sectors if not added yet
|
||||
if(!visiblesectors.ContainsKey(sd.Sector))
|
||||
{
|
||||
visiblesectors.Add(sd.Sector, vs);
|
||||
visiblegeometry.AddRange(vs.FixedGeometry);
|
||||
}
|
||||
|
||||
// Add sidedef geometry
|
||||
visiblegeometry.AddRange(vs.GetSidedefGeometry(sd));
|
||||
}
|
||||
|
||||
// This returns the camera sector from linedef
|
||||
private Sector GetCameraSectorFromLinedef(Linedef ld)
|
||||
{
|
||||
if(ld.SideOfLine(campos) < 0)
|
||||
{
|
||||
if(ld.Front != null)
|
||||
return ld.Front.Sector;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ld.Back != null)
|
||||
return ld.Back.Sector;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Processing
|
||||
|
@ -472,8 +449,8 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
public override void OnRedrawDisplay()
|
||||
{
|
||||
// Render all visible sectors
|
||||
foreach(KeyValuePair<Sector, VisualSector> vs in visiblesectors)
|
||||
renderer.RenderGeometry(vs.Value);
|
||||
foreach(VisualGeometry g in visiblegeometry)
|
||||
renderer.RenderGeometry(g);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -487,6 +464,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
foreach(KeyValuePair<Sector, VisualSector> s in allsectors) s.Value.Dispose();
|
||||
allsectors.Clear();
|
||||
visiblesectors.Clear();
|
||||
visiblegeometry.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -49,7 +49,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
#region ================== Variables
|
||||
|
||||
// Geometry
|
||||
private List<VisualGeometry> geolist;
|
||||
private List<VisualGeometry> fixedgeometry;
|
||||
private List<VisualGeometry> allgeometry;
|
||||
private Dictionary<Sidedef, List<VisualGeometry>> sidedefgeometry;
|
||||
private VertexBuffer geobuffer;
|
||||
private bool updategeo;
|
||||
|
||||
|
@ -63,7 +65,8 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
|
||||
#region ================== Properties
|
||||
|
||||
internal List<VisualGeometry> GeometryList { get { return geolist; } }
|
||||
internal List<VisualGeometry> FixedGeometry { get { return fixedgeometry; } }
|
||||
internal List<VisualGeometry> AllGeometry { get { return allgeometry; } }
|
||||
internal VertexBuffer GeometryBuffer { get { return geobuffer; } }
|
||||
internal bool NeedsUpdateGeo { get { return updategeo; } set { updategeo |= value; } }
|
||||
public bool IsDisposed { get { return isdisposed; } }
|
||||
|
@ -78,7 +81,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
{
|
||||
// Initialize
|
||||
this.sector = s;
|
||||
geolist = new List<VisualGeometry>();
|
||||
allgeometry = new List<VisualGeometry>();
|
||||
fixedgeometry = new List<VisualGeometry>();
|
||||
sidedefgeometry = new Dictionary<Sidedef, List<VisualGeometry>>();
|
||||
|
||||
// Register as resource
|
||||
General.Map.Graphics.RegisterResource(this);
|
||||
|
@ -91,7 +96,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
if(!isdisposed)
|
||||
{
|
||||
// Clean up
|
||||
foreach(VisualGeometry g in geolist) g.Sector = null;
|
||||
foreach(VisualGeometry g in allgeometry) g.Sector = null;
|
||||
if(geobuffer != null) geobuffer.Dispose();
|
||||
geobuffer = null;
|
||||
|
||||
|
@ -136,11 +141,8 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
if(geobuffer != null) geobuffer.Dispose();
|
||||
geobuffer = null;
|
||||
|
||||
// Sort the geo list by texture
|
||||
geolist.Sort();
|
||||
|
||||
// Count the number of vertices there are
|
||||
foreach(VisualGeometry g in geolist) if(g.Vertices != null) numverts += g.Vertices.Length;
|
||||
foreach(VisualGeometry g in allgeometry) if(g.Vertices != null) numverts += g.Vertices.Length;
|
||||
|
||||
// Any vertics?
|
||||
if(numverts > 0)
|
||||
|
@ -151,7 +153,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
|
||||
// Fill the buffer
|
||||
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
|
||||
foreach(VisualGeometry g in geolist)
|
||||
foreach(VisualGeometry g in allgeometry)
|
||||
{
|
||||
if((g.Vertices != null) && (g.Vertices.Length > 0))
|
||||
{
|
||||
|
@ -168,20 +170,47 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
updategeo = false;
|
||||
}
|
||||
|
||||
// This adds geometry
|
||||
/// <summary>
|
||||
/// This adds geometry for this sector. If the geometry inherits from VisualSidedef then it
|
||||
/// will be added to the SidedefGeometry, otherwise it will be added as FixedGeometry.
|
||||
/// </summary>
|
||||
public void AddGeometry(VisualGeometry geo)
|
||||
{
|
||||
updategeo = true;
|
||||
geo.Sector = this;
|
||||
geolist.Add(geo);
|
||||
allgeometry.Add(geo);
|
||||
if(geo is VisualSidedef)
|
||||
{
|
||||
VisualSidedef geoside = (geo as VisualSidedef);
|
||||
if(!sidedefgeometry.ContainsKey(geoside.Sidedef))
|
||||
sidedefgeometry[geoside.Sidedef] = new List<VisualGeometry>(3);
|
||||
sidedefgeometry[geoside.Sidedef].Add(geoside);
|
||||
}
|
||||
else
|
||||
{
|
||||
fixedgeometry.Add(geo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This removes all geometry.
|
||||
/// </summary>
|
||||
public void ClearGeometry()
|
||||
{
|
||||
foreach(VisualGeometry g in allgeometry) g.Sector = null;
|
||||
allgeometry.Clear();
|
||||
fixedgeometry.Clear();
|
||||
sidedefgeometry.Clear();
|
||||
updategeo = true;
|
||||
}
|
||||
|
||||
// This removes all geometry
|
||||
public void ClearGeometry()
|
||||
// This gets the geometry list for the specified sidedef
|
||||
public List<VisualGeometry> GetSidedefGeometry(Sidedef sd)
|
||||
{
|
||||
foreach(VisualGeometry g in geolist) g.Sector = null;
|
||||
geolist.Clear();
|
||||
updategeo = true;
|
||||
if(sidedefgeometry.ContainsKey(sd))
|
||||
return sidedefgeometry[sd];
|
||||
else
|
||||
return new List<VisualGeometry>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
77
Source/VisualModes/VisualSidedef.cs
Normal file
77
Source/VisualModes/VisualSidedef.cs
Normal file
|
@ -0,0 +1,77 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Drawing;
|
||||
using System.ComponentModel;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
using SlimDX.Direct3D9;
|
||||
using SlimDX;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using System.Drawing.Imaging;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
using CodeImp.DoomBuilder.Editing;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.VisualModes
|
||||
{
|
||||
public abstract class VisualSidedef : VisualGeometry
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Variables
|
||||
|
||||
// Original sidedef
|
||||
private Sidedef sidedef;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public Sidedef Sidedef { get { return sidedef; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public VisualSidedef(Sidedef sd)
|
||||
{
|
||||
// Initialize
|
||||
this.sidedef = sd;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -1820,7 +1820,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// Setup and reload stuff
|
||||
if(General.Map.ScriptEditor != null) General.Map.ScriptEditor.Editor.RefreshSettings();
|
||||
General.Map.Graphics.SetupSettings();
|
||||
General.Map.Map.UpdateConfiguration();
|
||||
General.Map.UpdateConfiguration();
|
||||
General.Map.ReloadResources();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue