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
protected override VisualSector CreateVisualSector(Sector s)
{
return new BaseVisualSector(s);
BaseVisualSector vs = new BaseVisualSector(s);
return vs;
}
// This creates a visual thing
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
@ -167,7 +169,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply new target
target = newtarget;
}
// This changes the target's height
private void ChangeTargetHeight(int amount)
{

View file

@ -31,6 +31,8 @@ using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion
@ -39,29 +41,139 @@ namespace CodeImp.DoomBuilder.BuilderModes
internal class BaseVisualThing : VisualThing
{
#region ================== Constants
#endregion
#region ================== Variables
private ThingTypeInfo info;
private bool isloaded;
private ImageData sprite;
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
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
#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
}
}

View file

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

View file

@ -54,8 +54,9 @@ namespace CodeImp.DoomBuilder.Rendering
private Matrix projection;
private Matrix view3d;
private Matrix billboard;
private Matrix viewproj;
private Matrix worldviewproj;
private Matrix view2d;
private Matrix world;
// Window size
private Size windowsize;
@ -213,12 +214,9 @@ namespace CodeImp.DoomBuilder.Rendering
// Make the view matrix
view3d = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f));
// Make the billboard matrix
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()));
billboard = Matrix.RotationZ(anglexy + Angle2D.PI);
}
// This creates 2D view matrix
@ -233,8 +231,9 @@ namespace CodeImp.DoomBuilder.Rendering
// This applies the matrices
private void ApplyMatrices3D()
{
viewproj = view3d * projection;
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
worldviewproj = world * view3d * projection;
graphics.Shaders.World3D.WorldViewProj = worldviewproj;
graphics.Device.SetTransform(TransformState.World, world);
graphics.Device.SetTransform(TransformState.Projection, projection);
graphics.Device.SetTransform(TransformState.View, view3d);
}
@ -242,7 +241,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This sets the appropriate view matrix
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.View, view2d);
}
@ -274,6 +273,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Device.SetRenderState(RenderState.RangeFogEnable, false);
// Matrices
world = Matrix.Identity;
ApplyMatrices3D();
// Create crosshair vertices
@ -314,26 +314,25 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
graphics.Shaders.World3D.Begin();
graphics.Shaders.World3D.WorldViewProj = viewproj;
// Matrices
ApplyMatrices3D();
// SOLID PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
world = Matrix.Identity;
ApplyMatrices3D();
graphics.Shaders.World3D.BeginPass(0);
RenderSinglePass((int)RenderPass.Solid);
graphics.Shaders.World3D.EndPass();
// MASK PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
world = Matrix.Identity;
ApplyMatrices3D();
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);
world = Matrix.Identity;
ApplyMatrices3D();
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, true);
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, false);
graphics.Device.SetRenderState(RenderState.ZWriteEnable, false);
@ -344,7 +343,8 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.World3D.EndPass();
// ADDITIVE PASS
graphics.Device.SetTransform(TransformState.World, Matrix.Identity);
world = Matrix.Identity;
ApplyMatrices3D();
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
graphics.Shaders.World3D.BeginPass(0);
RenderSinglePass((int)RenderPass.Additive);
@ -424,41 +424,41 @@ namespace CodeImp.DoomBuilder.Rendering
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);
world = t.Orientation;
if(t.Billboard) world = Matrix.Multiply(world, billboard);
world = Matrix.Multiply(world, t.Position);
ApplyMatrices3D();
graphics.Shaders.World3D.ApplySettings();
// Apply buffer
graphics.Device.SetStreamSource(0, t.GeometryBuffer, 0, WorldVertex.Stride);
// Render!
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, t.Triangles);
}

View file

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

View file

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