working on visual mode

This commit is contained in:
codeimp 2008-12-10 16:00:34 +00:00
parent 22d5b88baf
commit 5db0757020
6 changed files with 205 additions and 64 deletions

View file

@ -97,13 +97,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This creates a visual sector // This creates a visual sector
protected override VisualSector CreateVisualSector(Sector s) protected override VisualSector CreateVisualSector(Sector s)
{ {
return new BaseVisualSector(s); BaseVisualSector vs = new BaseVisualSector(s);
return vs;
} }
// This creates a visual thing // This creates a visual thing
protected override VisualThing CreateVisualThing(Thing t) protected override VisualThing CreateVisualThing(Thing t)
{ {
return new BaseVisualThing(t); BaseVisualThing vt = new BaseVisualThing(t);
if(vt.Setup()) return vt; else return null;
} }
// This locks the target so that it isn't changed until unlocked // This locks the target so that it isn't changed until unlocked
@ -167,7 +169,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply new target // Apply new target
target = newtarget; target = newtarget;
} }
// This changes the target's height // This changes the target's height
private void ChangeTargetHeight(int amount) private void ChangeTargetHeight(int amount)
{ {

View file

@ -31,6 +31,8 @@ using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Editing; using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion #endregion
@ -39,29 +41,139 @@ namespace CodeImp.DoomBuilder.BuilderModes
internal class BaseVisualThing : VisualThing internal class BaseVisualThing : VisualThing
{ {
#region ================== Constants #region ================== Constants
#endregion #endregion
#region ================== Variables #region ================== Variables
private ThingTypeInfo info;
private bool isloaded;
private ImageData sprite;
#endregion #endregion
#region ================== Properties #region ================== Properties
#endregion #endregion
#region ================== Constructor / Disposer #region ================== Constructor / Disposer
// Constructor // Constructor
public BaseVisualThing(Thing t) : base(t) public BaseVisualThing(Thing t) : base(t)
{ {
// Find thing information
info = General.Map.Config.GetThingInfo(Thing.Type);
// Find sprite texture
if(info.Sprite.Length > 0)
{
sprite = General.Map.Data.GetSpriteImage(info.Sprite);
if(sprite != null) sprite.AddReference();
}
// We have no destructor
GC.SuppressFinalize(this);
} }
// This builds the thing geometry. Returns false when nothing was created.
public virtual bool Setup()
{
if(sprite != null)
{
// Color to modulate sprite with (god knows what we could use this for)
PixelColor pc = new PixelColor(255, 255, 255, 255);
// Find the sector in which the thing resides
Thing.DetermineSector();
// Check if the texture is loaded
isloaded = sprite.IsImageLoaded;
if(isloaded)
{
base.Texture = sprite;
// Determine sprite size
float radius = sprite.ScaledWidth * 0.5f;
float height = sprite.ScaledHeight;
// Determine texture coordinates
Vector2D t1 = new Vector2D(1.0f / sprite.ScaledWidth, 1.0f / sprite.ScaledHeight);
Vector2D t2 = new Vector2D(1.0f - t1.x, 1.0f - t1.y);
// Make vertices
WorldVertex[] verts = new WorldVertex[6];
verts[0] = new WorldVertex(-radius, 0.0f, 0.0f, pc.ToInt(), t1.x, t2.y);
verts[1] = new WorldVertex(-radius, 0.0f, height, pc.ToInt(), t1.x, t1.y);
verts[2] = new WorldVertex(+radius, 0.0f, height, pc.ToInt(), t2.x, t1.y);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(+radius, 0.0f, 0.0f, pc.ToInt(), t2.x, t2.y);
SetVertices(verts);
}
else
{
base.Texture = General.Map.Data.Hourglass3D;
// Determine sprite size
float radius = info.Width * 0.5f;
float height = info.Height;
// Determine texture coordinates
Vector2D t1 = new Vector2D(1.0f / base.Texture.ScaledWidth, 1.0f / base.Texture.ScaledHeight);
Vector2D t2 = new Vector2D(1.0f - t1.x, 1.0f - t1.y);
// Make vertices
WorldVertex[] verts = new WorldVertex[6];
verts[0] = new WorldVertex(-radius, 0.0f, 0.0f, pc.ToInt(), t1.x, t2.y);
verts[1] = new WorldVertex(-radius, 0.0f, height, pc.ToInt(), t1.x, t1.y);
verts[2] = new WorldVertex(+radius, 0.0f, height, pc.ToInt(), t2.x, t1.y);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(+radius, 0.0f, 0.0f, pc.ToInt(), t2.x, t2.y);
SetVertices(verts);
}
}
// Setup position
Vector3D pos = Thing.Position;
if(Thing.Sector != null) pos.z += Thing.Sector.FloorHeight;
SetPosition(pos);
// Done
return true;
}
// Disposing
public override void Dispose()
{
if(!IsDisposed)
{
if(sprite != null) sprite.RemoveReference();
}
base.Dispose();
}
#endregion #endregion
#region ================== Methods #region ================== Methods
// This updates the thing when needed
public override void Update()
{
if(!isloaded)
{
// Rebuild sprite geometry when sprite is loaded
if(sprite.IsImageLoaded)
{
Setup();
}
}
// Let the base update
base.Update();
}
#endregion #endregion
} }
} }

View file

@ -72,7 +72,7 @@ namespace CodeImp.DoomBuilder.Data
lumpdata.Read(membytes, 0, (int)lumpdata.Length); lumpdata.Read(membytes, 0, (int)lumpdata.Length);
mem = new MemoryStream(membytes); mem = new MemoryStream(membytes);
mem.Seek(0, SeekOrigin.Begin); mem.Seek(0, SeekOrigin.Begin);
// Get a reader for the data // Get a reader for the data
reader = ImageDataFormat.GetImageReader(mem, ImageDataFormat.DOOMPICTURE, General.Map.Data.Palette); reader = ImageDataFormat.GetImageReader(mem, ImageDataFormat.DOOMPICTURE, General.Map.Data.Palette);
if(reader is UnknownImageReader) if(reader is UnknownImageReader)
@ -80,19 +80,21 @@ namespace CodeImp.DoomBuilder.Data
// Data is in an unknown format! // Data is in an unknown format!
General.WriteLogLine("WARNING: Sprite lump '" + Name + "' data format could not be read!"); General.WriteLogLine("WARNING: Sprite lump '" + Name + "' data format could not be read!");
} }
// Read data as bitmap // Read data as bitmap
mem.Seek(0, SeekOrigin.Begin); mem.Seek(0, SeekOrigin.Begin);
if(bitmap != null) bitmap.Dispose(); if(bitmap != null) bitmap.Dispose();
bitmap = reader.ReadAsBitmap(mem); bitmap = reader.ReadAsBitmap(mem);
if(bitmap == null) return; if(bitmap == null) return;
// Done // Done
mem.Dispose(); mem.Dispose();
// Get width and height from image // Get width and height from image
width = bitmap.Size.Width; width = bitmap.Size.Width;
height = bitmap.Size.Height; height = bitmap.Size.Height;
scaledwidth = (float)bitmap.Size.Width;
scaledheight = (float)bitmap.Size.Height;
} }
else else
{ {

View file

@ -54,8 +54,9 @@ namespace CodeImp.DoomBuilder.Rendering
private Matrix projection; private Matrix projection;
private Matrix view3d; private Matrix view3d;
private Matrix billboard; private Matrix billboard;
private Matrix viewproj; private Matrix worldviewproj;
private Matrix view2d; private Matrix view2d;
private Matrix world;
// Window size // Window size
private Size windowsize; private Size windowsize;
@ -213,12 +214,9 @@ namespace CodeImp.DoomBuilder.Rendering
// Make the view matrix // Make the view matrix
view3d = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f)); view3d = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f));
// Make the billboard matrix // Make the billboard matrix
Vector3D lookat2d = new Vector3D(lookat.x, lookat.y, 0.0f); billboard = Matrix.RotationZ(anglexy + Angle2D.PI);
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 // This creates 2D view matrix
@ -233,8 +231,9 @@ namespace CodeImp.DoomBuilder.Rendering
// This applies the matrices // This applies the matrices
private void ApplyMatrices3D() private void ApplyMatrices3D()
{ {
viewproj = view3d * projection; worldviewproj = world * view3d * projection;
graphics.Device.SetTransform(TransformState.World, Matrix.Identity); graphics.Shaders.World3D.WorldViewProj = worldviewproj;
graphics.Device.SetTransform(TransformState.World, world);
graphics.Device.SetTransform(TransformState.Projection, projection); graphics.Device.SetTransform(TransformState.Projection, projection);
graphics.Device.SetTransform(TransformState.View, view3d); graphics.Device.SetTransform(TransformState.View, view3d);
} }
@ -242,7 +241,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This sets the appropriate view matrix // This sets the appropriate view matrix
public void ApplyMatrices2D() public void ApplyMatrices2D()
{ {
graphics.Device.SetTransform(TransformState.World, Matrix.Identity); graphics.Device.SetTransform(TransformState.World, world);
graphics.Device.SetTransform(TransformState.Projection, Matrix.Identity); graphics.Device.SetTransform(TransformState.Projection, Matrix.Identity);
graphics.Device.SetTransform(TransformState.View, view2d); graphics.Device.SetTransform(TransformState.View, view2d);
} }
@ -274,6 +273,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Device.SetRenderState(RenderState.RangeFogEnable, false); graphics.Device.SetRenderState(RenderState.RangeFogEnable, false);
// Matrices // Matrices
world = Matrix.Identity;
ApplyMatrices3D(); ApplyMatrices3D();
// Create crosshair vertices // Create crosshair vertices
@ -314,26 +314,25 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false); graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
graphics.Shaders.World3D.Begin(); graphics.Shaders.World3D.Begin();
graphics.Shaders.World3D.WorldViewProj = viewproj;
// Matrices
ApplyMatrices3D();
// SOLID PASS // SOLID PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity); world = Matrix.Identity;
ApplyMatrices3D();
graphics.Shaders.World3D.BeginPass(0); graphics.Shaders.World3D.BeginPass(0);
RenderSinglePass((int)RenderPass.Solid); RenderSinglePass((int)RenderPass.Solid);
graphics.Shaders.World3D.EndPass(); graphics.Shaders.World3D.EndPass();
// MASK PASS // MASK PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity); world = Matrix.Identity;
ApplyMatrices3D();
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, true); graphics.Device.SetRenderState(RenderState.AlphaTestEnable, true);
graphics.Shaders.World3D.BeginPass(0); graphics.Shaders.World3D.BeginPass(0);
RenderSinglePass((int)RenderPass.Mask); RenderSinglePass((int)RenderPass.Mask);
graphics.Shaders.World3D.EndPass(); graphics.Shaders.World3D.EndPass();
// ALPHA PASS // ALPHA PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity); world = Matrix.Identity;
ApplyMatrices3D();
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, true); graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, true);
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false); graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
graphics.Device.SetRenderState(RenderState.ZWriteEnable, false); graphics.Device.SetRenderState(RenderState.ZWriteEnable, false);
@ -344,7 +343,8 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.World3D.EndPass(); graphics.Shaders.World3D.EndPass();
// ADDITIVE PASS // ADDITIVE PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity); world = Matrix.Identity;
ApplyMatrices3D();
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One); graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
graphics.Shaders.World3D.BeginPass(0); graphics.Shaders.World3D.BeginPass(0);
RenderSinglePass((int)RenderPass.Additive); RenderSinglePass((int)RenderPass.Additive);
@ -424,41 +424,41 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(KeyValuePair<ImageData, List<VisualThing>> group in thingspass) foreach(KeyValuePair<ImageData, List<VisualThing>> group in thingspass)
{ {
ImageData curtexture; ImageData curtexture;
// What texture to use? // What texture to use?
if((group.Key != null) && group.Key.IsImageLoaded && !group.Key.IsDisposed) if((group.Key != null) && group.Key.IsImageLoaded && !group.Key.IsDisposed)
curtexture = group.Key; curtexture = group.Key;
else else
curtexture = General.Map.Data.Hourglass3D; curtexture = General.Map.Data.Hourglass3D;
// Create Direct3D texture if still needed // Create Direct3D texture if still needed
if((curtexture.Texture == null) || curtexture.Texture.Disposed) if((curtexture.Texture == null) || curtexture.Texture.Disposed)
curtexture.CreateTexture(); curtexture.CreateTexture();
// Apply texture // Apply texture
graphics.Device.SetTexture(0, curtexture.Texture); graphics.Device.SetTexture(0, curtexture.Texture);
graphics.Shaders.World3D.Texture1 = curtexture.Texture; graphics.Shaders.World3D.Texture1 = curtexture.Texture;
graphics.Shaders.World3D.ApplySettings(); graphics.Shaders.World3D.ApplySettings();
// Render all things with this texture // Render all things with this texture
foreach(VisualThing t in group.Value) foreach(VisualThing t in group.Value)
{ {
// Update buffer if needed // Update buffer if needed
if(t.NeedsUpdateGeo) t.Update(); if(t.NeedsUpdateGeo) t.Update();
// Only do this sector when a vertexbuffer is created // Only do this sector when a vertexbuffer is created
if(t.GeometryBuffer != null) if(t.GeometryBuffer != null)
{ {
// Create the matrix for positioning / rotation // Create the matrix for positioning / rotation
Matrix transform = t.Orientation; world = t.Orientation;
if(t.Billboard) transform = Matrix.Multiply(transform, billboard); if(t.Billboard) world = Matrix.Multiply(world, billboard);
transform = Matrix.Multiply(transform, t.Position); world = Matrix.Multiply(world, t.Position);
graphics.Device.SetTransform(TransformState.World, transform); ApplyMatrices3D();
graphics.Shaders.World3D.ApplySettings(); graphics.Shaders.World3D.ApplySettings();
// Apply buffer // Apply buffer
graphics.Device.SetStreamSource(0, t.GeometryBuffer, 0, WorldVertex.Stride); graphics.Device.SetStreamSource(0, t.GeometryBuffer, 0, WorldVertex.Stride);
// Render! // Render!
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, t.Triangles); graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, t.Triangles);
} }

View file

@ -174,7 +174,8 @@ namespace CodeImp.DoomBuilder.VisualModes
public override void OnDisengage() public override void OnDisengage()
{ {
base.OnDisengage(); base.OnDisengage();
DisposeVisuals();
// Do we have a 3D Mode thing? // Do we have a 3D Mode thing?
if(modething != null) if(modething != null)
{ {
@ -203,9 +204,8 @@ namespace CodeImp.DoomBuilder.VisualModes
public override void OnUndoEnd() public override void OnUndoEnd()
{ {
base.OnUndoEnd(); base.OnUndoEnd();
allsectors.Clear(); DisposeVisuals();
allthings.Clear();
visiblesectors.Clear(); visiblesectors.Clear();
visibleblocks.Clear(); visibleblocks.Clear();
visiblegeometry.Clear(); visiblegeometry.Clear();
@ -236,9 +236,8 @@ namespace CodeImp.DoomBuilder.VisualModes
public override void OnRedoEnd() public override void OnRedoEnd()
{ {
base.OnRedoEnd(); base.OnRedoEnd();
allsectors.Clear(); DisposeVisuals();
allthings.Clear();
visiblesectors.Clear(); visiblesectors.Clear();
visibleblocks.Clear(); visibleblocks.Clear();
visiblegeometry.Clear(); visiblegeometry.Clear();
@ -398,10 +397,13 @@ namespace CodeImp.DoomBuilder.VisualModes
{ {
// Create new visual thing // Create new visual thing
vt = CreateVisualThing(t); vt = CreateVisualThing(t);
allthings.Add(t, vt); if(vt != null) allthings.Add(t, vt);
} }
visiblethings.Add(vt); if(vt != null)
{
visiblethings.Add(vt);
}
} }
} }
@ -461,18 +463,21 @@ namespace CodeImp.DoomBuilder.VisualModes
{ {
// Make new visualsector // Make new visualsector
vs = CreateVisualSector(sd.Sector); vs = CreateVisualSector(sd.Sector);
allsectors.Add(sd.Sector, vs); if(vs != null) allsectors.Add(sd.Sector, vs);
} }
// Add to visible sectors if not added yet if(vs != null)
if(!visiblesectors.ContainsKey(sd.Sector))
{ {
visiblesectors.Add(sd.Sector, vs); // Add to visible sectors if not added yet
visiblegeometry.AddRange(vs.FixedGeometry); if(!visiblesectors.ContainsKey(sd.Sector))
{
visiblesectors.Add(sd.Sector, vs);
visiblegeometry.AddRange(vs.FixedGeometry);
}
// Add sidedef geometry
visiblegeometry.AddRange(vs.GetSidedefGeometry(sd));
} }
// Add sidedef geometry
visiblegeometry.AddRange(vs.GetSidedefGeometry(sd));
} }
// This returns the camera sector from linedef // This returns the camera sector from linedef
@ -647,7 +652,20 @@ namespace CodeImp.DoomBuilder.VisualModes
#endregion #endregion
#region ================== Processing #region ================== Processing
// This disposes all visual sectors and things
private void DisposeVisuals()
{
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
vs.Value.Dispose();
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
vt.Value.Dispose();
allsectors.Clear();
allthings.Clear();
}
/// <summary> /// <summary>
/// Implement this to create an instance of your VisualSector implementation. /// Implement this to create an instance of your VisualSector implementation.
/// </summary> /// </summary>
@ -744,6 +762,12 @@ namespace CodeImp.DoomBuilder.VisualModes
// Render all visible sectors // Render all visible sectors
foreach(VisualGeometry g in visiblegeometry) foreach(VisualGeometry g in visiblegeometry)
renderer.AddSectorGeometry(g); renderer.AddSectorGeometry(g);
// Render all visible things
foreach(VisualThing t in visiblethings)
renderer.AddThingGeometry(t);
General.WriteLogLine("Things: " + visiblethings.Count);
} }
#endregion #endregion

View file

@ -118,6 +118,7 @@ namespace CodeImp.DoomBuilder.VisualModes
this.renderpass = (int)RenderPass.Mask; this.renderpass = (int)RenderPass.Mask;
this.billboard = true; this.billboard = true;
this.orientation = Matrix.Identity; this.orientation = Matrix.Identity;
this.position = Matrix.Identity;
// Register as resource // Register as resource
General.Map.Graphics.RegisterResource(this); General.Map.Graphics.RegisterResource(this);
@ -188,9 +189,9 @@ namespace CodeImp.DoomBuilder.VisualModes
triangles = vertices.Length / 3; triangles = vertices.Length / 3;
updategeo = true; updategeo = true;
} }
// This updates the visual sector // This updates the visual thing
public void Update() public virtual void Update()
{ {
// Trash geometry buffer // Trash geometry buffer
if(geobuffer != null) geobuffer.Dispose(); if(geobuffer != null) geobuffer.Dispose();