mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 14:31:50 +00:00
working on visual mode
This commit is contained in:
parent
fe5d5a2001
commit
22d5b88baf
4 changed files with 194 additions and 55 deletions
|
@ -54,7 +54,8 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
void FinishGeometry();
|
||||
|
||||
// Rendering methods
|
||||
void AddGeometry(VisualGeometry g);
|
||||
void AddSectorGeometry(VisualGeometry g);
|
||||
void AddThingGeometry(VisualThing t);
|
||||
void RenderCrosshair();
|
||||
void SetFogMode(bool usefog);
|
||||
void SetCrosshairBusy(bool busy);
|
||||
|
|
|
@ -73,7 +73,12 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
// to be rendered with the associated ImageData.
|
||||
// The BinaryHeap sorts the geometry by sector to minimize stream switchs.
|
||||
private Dictionary<ImageData, BinaryHeap<VisualGeometry>>[] geometry;
|
||||
|
||||
|
||||
// Things to be rendered.
|
||||
// Each Dictionary in the array is a render pass.
|
||||
// Each VisualThing is inserted in the Dictionary by their texture image.
|
||||
private Dictionary<ImageData, List<VisualThing>>[] things;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
@ -210,9 +215,12 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
view3d = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f));
|
||||
|
||||
// Make the billboard matrix
|
||||
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PI);
|
||||
Vector3D lookat2d = new Vector3D(lookat.x, lookat.y, 0.0f);
|
||||
Vector3D campos2d = new Vector3D(pos.x, pos.y, 0.0f);
|
||||
Vector3D delta2d = lookat2d - campos2d;
|
||||
billboard = Matrix.Billboard(D3DDevice.V3(lookat2d), D3DDevice.V3(campos2d), new Vector3(0f, 0f, 1f), D3DDevice.V3(delta2d.GetNormal()));
|
||||
}
|
||||
|
||||
|
||||
// This creates 2D view matrix
|
||||
private void CreateMatrices2D()
|
||||
{
|
||||
|
@ -287,7 +295,12 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
{
|
||||
// Make collection
|
||||
geometry = new Dictionary<ImageData, BinaryHeap<VisualGeometry>>[RENDER_PASSES];
|
||||
for(int i = 0; i < RENDER_PASSES; i++) geometry[i] = new Dictionary<ImageData, BinaryHeap<VisualGeometry>>();
|
||||
things = new Dictionary<ImageData, List<VisualThing>>[RENDER_PASSES];
|
||||
for(int i = 0; i < RENDER_PASSES; i++)
|
||||
{
|
||||
geometry[i] = new Dictionary<ImageData, BinaryHeap<VisualGeometry>>();
|
||||
things[i] = new Dictionary<ImageData, List<VisualThing>>();
|
||||
}
|
||||
}
|
||||
|
||||
// This ends rendering world geometry
|
||||
|
@ -307,17 +320,20 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
ApplyMatrices3D();
|
||||
|
||||
// SOLID PASS
|
||||
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
|
||||
graphics.Shaders.World3D.BeginPass(0);
|
||||
RenderSinglePass((int)RenderPass.Solid);
|
||||
graphics.Shaders.World3D.EndPass();
|
||||
|
||||
// MASK PASS
|
||||
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
|
||||
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, true);
|
||||
graphics.Shaders.World3D.BeginPass(0);
|
||||
RenderSinglePass((int)RenderPass.Mask);
|
||||
graphics.Shaders.World3D.EndPass();
|
||||
|
||||
// ALPHA PASS
|
||||
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
|
||||
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, true);
|
||||
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
|
||||
graphics.Device.SetRenderState(RenderState.ZWriteEnable, false);
|
||||
|
@ -328,6 +344,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
graphics.Shaders.World3D.EndPass();
|
||||
|
||||
// ADDITIVE PASS
|
||||
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
|
||||
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
|
||||
graphics.Shaders.World3D.BeginPass(0);
|
||||
RenderSinglePass((int)RenderPass.Additive);
|
||||
|
@ -345,10 +362,10 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
private void RenderSinglePass(int pass)
|
||||
{
|
||||
// Get geometry for this pass
|
||||
Dictionary<ImageData, BinaryHeap<VisualGeometry>> geo = geometry[pass];
|
||||
Dictionary<ImageData, BinaryHeap<VisualGeometry>> geopass = geometry[pass];
|
||||
|
||||
// Render the geometry collected
|
||||
foreach(KeyValuePair<ImageData, BinaryHeap<VisualGeometry>> group in geo)
|
||||
foreach(KeyValuePair<ImageData, BinaryHeap<VisualGeometry>> group in geopass)
|
||||
{
|
||||
ImageData curtexture;
|
||||
|
||||
|
@ -399,6 +416,54 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get things for this pass
|
||||
Dictionary<ImageData, List<VisualThing>> thingspass = things[pass];
|
||||
|
||||
// Render things collected
|
||||
foreach(KeyValuePair<ImageData, List<VisualThing>> group in thingspass)
|
||||
{
|
||||
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();
|
||||
|
||||
// Render all things with this texture
|
||||
foreach(VisualThing t in group.Value)
|
||||
{
|
||||
// Update buffer if needed
|
||||
if(t.NeedsUpdateGeo) t.Update();
|
||||
|
||||
// Only do this sector when a vertexbuffer is created
|
||||
if(t.GeometryBuffer != null)
|
||||
{
|
||||
// Create the matrix for positioning / rotation
|
||||
Matrix transform = t.Orientation;
|
||||
if(t.Billboard) transform = Matrix.Multiply(transform, billboard);
|
||||
transform = Matrix.Multiply(transform, t.Position);
|
||||
graphics.Device.SetTransform(TransformState.World, transform);
|
||||
graphics.Shaders.World3D.ApplySettings();
|
||||
|
||||
// Apply buffer
|
||||
graphics.Device.SetStreamSource(0, t.GeometryBuffer, 0, WorldVertex.Stride);
|
||||
|
||||
// Render!
|
||||
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, t.Triangles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This finishes rendering
|
||||
|
@ -414,7 +479,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
#region ================== Rendering
|
||||
|
||||
// This collects a visual sector's geometry for rendering
|
||||
public void AddGeometry(VisualGeometry g)
|
||||
public void AddSectorGeometry(VisualGeometry g)
|
||||
{
|
||||
// Must have a texture!
|
||||
if(g.Texture != null)
|
||||
|
@ -425,12 +490,30 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
// Create texture group
|
||||
geometry[g.RenderPassInt].Add(g.Texture, new BinaryHeap<VisualGeometry>());
|
||||
}
|
||||
|
||||
|
||||
// Add geometry to texture group
|
||||
geometry[g.RenderPassInt][g.Texture].Add(g);
|
||||
}
|
||||
}
|
||||
|
||||
// This collects a visual sector's geometry for rendering
|
||||
public void AddThingGeometry(VisualThing t)
|
||||
{
|
||||
// Must have a texture!
|
||||
if(t.Texture != null)
|
||||
{
|
||||
// Texture group not yet collected?
|
||||
if(!things[t.RenderPassInt].ContainsKey(t.Texture))
|
||||
{
|
||||
// Create texture group
|
||||
things[t.RenderPassInt].Add(t.Texture, new List<VisualThing>());
|
||||
}
|
||||
|
||||
// Add geometry to texture group
|
||||
things[t.RenderPassInt][t.Texture].Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
// This renders the crosshair
|
||||
public void RenderCrosshair()
|
||||
{
|
||||
|
|
|
@ -648,43 +648,71 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
|
||||
#region ================== Processing
|
||||
|
||||
// This creates a visual sector
|
||||
/// <summary>
|
||||
/// Implement this to create an instance of your VisualSector implementation.
|
||||
/// </summary>
|
||||
protected abstract VisualSector CreateVisualSector(Sector s);
|
||||
|
||||
// This creates a visual thing
|
||||
/// <summary>
|
||||
/// Implement this to create an instance of your VisualThing implementation.
|
||||
/// </summary>
|
||||
protected abstract VisualThing CreateVisualThing(Thing t);
|
||||
|
||||
// This returns a visual sector
|
||||
/// <summary>
|
||||
/// This returns the VisualSector for the given Sector.
|
||||
/// </summary>
|
||||
protected VisualSector GetVisualSector(Sector s)
|
||||
{
|
||||
return allsectors[s];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This returns the VisualThing for the given Thing.
|
||||
/// </summary>
|
||||
protected VisualThing GetVisualThing(Thing t)
|
||||
{
|
||||
return allthings[t];
|
||||
}
|
||||
|
||||
// This returns true when a visual sector has been created for the specified sector
|
||||
/// <summary>
|
||||
/// Returns True when a VisualSector has been created for the specified Sector.
|
||||
/// </summary>
|
||||
protected bool VisualSectorExists(Sector s)
|
||||
{
|
||||
return allsectors.ContainsKey(s);
|
||||
}
|
||||
|
||||
// This fills the blockmap
|
||||
/// <summary>
|
||||
/// Returns True when a VisualThing has been created for the specified Thing.
|
||||
/// </summary>
|
||||
protected bool VisualThingExists(Thing t)
|
||||
{
|
||||
return allthings.ContainsKey(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the blockmap needs to be refilled, because it was invalidated.
|
||||
/// This usually happens when geometry is changed by undo, redo, cut or paste actions.
|
||||
/// Lines and Things are added to the block map by the base implementation.
|
||||
/// </summary>
|
||||
protected virtual void FillBlockMap()
|
||||
{
|
||||
blockmap.AddLinedefsSet(General.Map.Map.Linedefs);
|
||||
blockmap.AddThingsSet(General.Map.Map.Things);
|
||||
}
|
||||
|
||||
// Processing
|
||||
/// <summary>
|
||||
/// While this mode is active, this is called continuously to process whatever needs processing.
|
||||
/// </summary>
|
||||
public override void OnProcess(double deltatime)
|
||||
{
|
||||
Vector3D camvec;
|
||||
Vector3D camvecstrafe;
|
||||
double multiplier;
|
||||
|
||||
base.OnProcess(deltatime);
|
||||
|
||||
// Calculate camera direction vectors
|
||||
camvec = Vector3D.FromAngleXYZ(camanglexy, camanglez);
|
||||
camvecstrafe = Vector3D.FromAngleXY(camanglexy + Angle2D.PIHALF);
|
||||
Vector3D camvec = Vector3D.FromAngleXYZ(camanglexy, camanglez);
|
||||
Vector3D camvecstrafe = Vector3D.FromAngleXY(camanglexy + Angle2D.PIHALF);
|
||||
|
||||
// Move the camera
|
||||
if(doublespeed) multiplier = MOVE_SPEED_MULTIPLIER * 2.0f; else multiplier = MOVE_SPEED_MULTIPLIER;
|
||||
|
@ -715,7 +743,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
{
|
||||
// Render all visible sectors
|
||||
foreach(VisualGeometry g in visiblegeometry)
|
||||
renderer.AddGeometry(g);
|
||||
renderer.AddSectorGeometry(g);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -40,7 +40,7 @@ using CodeImp.DoomBuilder.Rendering;
|
|||
|
||||
namespace CodeImp.DoomBuilder.VisualModes
|
||||
{
|
||||
public abstract class VisualThing : IVisualPickable, ID3DResource, IComparable<VisualThing>
|
||||
public abstract class VisualThing : IVisualPickable, ID3DResource
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
|
@ -55,12 +55,16 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
private ImageData texture;
|
||||
|
||||
// Geometry
|
||||
private WorldVertex[] spritevertices;
|
||||
private WorldVertex[] cagevertices;
|
||||
private WorldVertex[] vertices;
|
||||
private VertexBuffer geobuffer;
|
||||
private bool updategeo;
|
||||
private int spritetriangles;
|
||||
private int cagetriangles;
|
||||
private int triangles;
|
||||
|
||||
// Rendering
|
||||
private int renderpass;
|
||||
private Matrix orientation;
|
||||
private Matrix position;
|
||||
private bool billboard;
|
||||
|
||||
// Disposing
|
||||
private bool isdisposed = false;
|
||||
|
@ -71,11 +75,35 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
|
||||
internal VertexBuffer GeometryBuffer { get { return geobuffer; } }
|
||||
internal bool NeedsUpdateGeo { get { return updategeo; } }
|
||||
internal int SpriteTriangles { get { return spritetriangles; } }
|
||||
internal int CageTriangles { get { return cagetriangles; } }
|
||||
internal int CageOffset { get { return spritevertices.Length; } }
|
||||
|
||||
internal int Triangles { get { return triangles; } }
|
||||
internal int RenderPassInt { get { return renderpass; } }
|
||||
internal Matrix Orientation { get { return orientation; } }
|
||||
internal Matrix Position { get { return position; } }
|
||||
|
||||
/// <summary>
|
||||
/// Set to True to use billboarding for this thing. When using billboarding,
|
||||
/// the geometry will be rotated on the XY plane to face the camera.
|
||||
/// </summary>
|
||||
public bool Billboard { get { return billboard; } set { billboard = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Thing that this VisualThing is created for.
|
||||
/// </summary>
|
||||
public Thing Thing { get { return thing; } }
|
||||
|
||||
/// <summary>
|
||||
/// Render pass in which this geometry must be rendered. Default is Solid.
|
||||
/// </summary>
|
||||
public RenderPass RenderPass { get { return (RenderPass)renderpass; } set { renderpass = (int)value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Image to use as texture on the geometry.
|
||||
/// </summary>
|
||||
public ImageData Texture { get { return texture; } set { texture = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Disposed or not?
|
||||
/// </summary>
|
||||
public bool IsDisposed { get { return isdisposed; } }
|
||||
|
||||
#endregion
|
||||
|
@ -87,6 +115,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
{
|
||||
// Initialize
|
||||
this.thing = t;
|
||||
this.renderpass = (int)RenderPass.Mask;
|
||||
this.billboard = true;
|
||||
this.orientation = Matrix.Identity;
|
||||
|
||||
// Register as resource
|
||||
General.Map.Graphics.RegisterResource(this);
|
||||
|
@ -131,30 +162,30 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
// Make new geometry
|
||||
//Update();
|
||||
}
|
||||
|
||||
// This compares for sorting by sprite
|
||||
public int CompareTo(VisualThing other)
|
||||
|
||||
/// <summary>
|
||||
/// This sets the position to use for the thing geometry.
|
||||
/// </summary>
|
||||
public void SetPosition(Vector3D pos)
|
||||
{
|
||||
return Math.Sign(this.texture.LongName - other.texture.LongName);
|
||||
position = Matrix.Translation(D3DDevice.V3(pos));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This sets the orientation to use for the thing geometry. When using this, you may want to turn off billboarding.
|
||||
/// </summary>
|
||||
public void SetOrientation(Vector3D angles)
|
||||
{
|
||||
orientation = Matrix.RotationYawPitchRoll(angles.z, angles.y, angles.x);
|
||||
}
|
||||
|
||||
// This sets the vertices for the thing sprite
|
||||
protected void SetSpriteVertices(ICollection<WorldVertex> verts)
|
||||
protected void SetVertices(ICollection<WorldVertex> verts)
|
||||
{
|
||||
// Copy vertices
|
||||
spritevertices = new WorldVertex[verts.Count];
|
||||
verts.CopyTo(spritevertices, 0);
|
||||
spritetriangles = spritevertices.Length / 3;
|
||||
updategeo = true;
|
||||
}
|
||||
|
||||
// This sets the vertices for the thing cage
|
||||
protected void SetCageVertices(ICollection<WorldVertex> verts)
|
||||
{
|
||||
// Copy vertices
|
||||
cagevertices = new WorldVertex[verts.Count];
|
||||
verts.CopyTo(cagevertices, 0);
|
||||
cagetriangles = cagevertices.Length / 3;
|
||||
vertices = new WorldVertex[verts.Count];
|
||||
verts.CopyTo(vertices, 0);
|
||||
triangles = vertices.Length / 3;
|
||||
updategeo = true;
|
||||
}
|
||||
|
||||
|
@ -165,20 +196,16 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
if(geobuffer != null) geobuffer.Dispose();
|
||||
geobuffer = null;
|
||||
|
||||
// Count the number of vertices there are
|
||||
int numverts = spritevertices.Length + cagevertices.Length;
|
||||
|
||||
// Any vertics?
|
||||
if(numverts > 0)
|
||||
if(vertices.Length > 0)
|
||||
{
|
||||
// Make a new buffer
|
||||
geobuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * numverts,
|
||||
geobuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * vertices.Length,
|
||||
Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
|
||||
|
||||
// Fill the buffer
|
||||
DataStream bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
|
||||
bufferstream.WriteRange<WorldVertex>(spritevertices);
|
||||
bufferstream.WriteRange<WorldVertex>(cagevertices);
|
||||
DataStream bufferstream = geobuffer.Lock(0, WorldVertex.Stride * vertices.Length, LockFlags.Discard);
|
||||
bufferstream.WriteRange<WorldVertex>(vertices);
|
||||
geobuffer.Unlock();
|
||||
bufferstream.Dispose();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue