changing 2D renderer from D3D to software rendering

This commit is contained in:
codeimp 2007-09-17 21:22:46 +00:00
parent 2d10662dcb
commit a6f39c05ad
15 changed files with 237 additions and 624 deletions

View file

@ -14,10 +14,10 @@ shortcuts
mainwindow
{
positionx = 378;
positionx = 245;
sizewidth = 739;
sizeheight = 572;
windowstate = 2;
sizewidth = 739;
positiony = 175;
positiony = 273;
}

View file

@ -22,7 +22,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -33,7 +33,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@ -112,9 +112,9 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Rendering\Graphics.cs" />
<Compile Include="Rendering\D3DGraphics.cs" />
<Compile Include="Rendering\IResource.cs" />
<Compile Include="Rendering\ManagedVertexBuffer.cs" />
<Compile Include="Rendering\PixelColor.cs" />
<Compile Include="Rendering\PTVertex.cs" />
<Compile Include="Rendering\ReloadResourceDelegate.cs" />
<Compile Include="Rendering\Renderer2D.cs" />
@ -170,7 +170,7 @@
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>aximp</WrapperTool>
<Isolated>False</Isolated>
<Isolated>True</Isolated>
</COMReference>
<COMReference Include="CodeSense">
<Guid>{665BF2B8-F41F-4EF4-A8D0-303FBFFC475E}</Guid>
@ -178,7 +178,7 @@
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<Isolated>True</Isolated>
</COMReference>
<COMReference Include="stdole">
<Guid>{00020430-0000-0000-C000-000000000046}</Guid>

View file

@ -44,7 +44,7 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Variables
// Graphics
protected Graphics graphics;
protected D3DGraphics graphics;
// Disposing
protected bool isdisposed = false;

View file

@ -42,6 +42,9 @@ namespace CodeImp.DoomBuilder
[DllImport("user32.dll")]
public static extern int LockWindowUpdate(IntPtr hwnd);
[DllImport("kernel32.dll", EntryPoint="RtlZeroMemory", SetLastError=false)]
public static extern void ZeroMemory(IntPtr dest, int size);
#endregion
#region ================== Constants

View file

@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder
private MapOptions options;
private Configuration config;
private EditMode mode;
private Graphics graphics;
private D3DGraphics graphics;
private WAD tempwad;
// Disposing
@ -72,7 +72,7 @@ namespace CodeImp.DoomBuilder
public EditMode Mode { get { return mode; } }
public bool IsChanged { get { return changed; } set { changed = value; } }
public bool IsDisposed { get { return isdisposed; } }
public Graphics Graphics { get { return graphics; } }
public D3DGraphics Graphics { get { return graphics; } }
#endregion
@ -122,7 +122,7 @@ namespace CodeImp.DoomBuilder
this.options = options;
// Initiate graphics
graphics = new Graphics(General.MainWindow.Display);
graphics = new D3DGraphics(General.MainWindow.Display);
if(!graphics.Initialize()) return false;
// Load game configuration
@ -130,7 +130,6 @@ namespace CodeImp.DoomBuilder
// Create map data
data = new MapSet();
data.EnableRendering();
// Create temp wadfile
tempwad = new WAD(General.MakeTempFilename());
@ -155,7 +154,7 @@ namespace CodeImp.DoomBuilder
this.options = options;
// Initiate graphics
graphics = new Graphics(General.MainWindow.Display);
graphics = new D3DGraphics(General.MainWindow.Display);
if(!graphics.Initialize()) return false;
// Load game configuration
@ -163,7 +162,6 @@ namespace CodeImp.DoomBuilder
// Create map data
data = new MapSet();
data.EnableRendering();
// Create temp wadfile
tempwad = new WAD(General.MakeTempFilename());

View file

@ -260,6 +260,14 @@ namespace CodeImp.DoomBuilder.Geometry
return x + ", " + y;
}
// Transform
public void Transform(Vector2D offset, Vector2D scale)
{
// Transform
x = (x + offset.x) * scale.x;
y = (y + offset.y) * scale.y;
}
#endregion
}
}

View file

@ -140,7 +140,7 @@ namespace CodeImp.DoomBuilder.IO
y = reader.ReadInt16();
// Create new item
v = map.CreateVertex(new Vector2D(x, y));
v = map.CreateVertex(x, y);
// Add it to the lookup table
link.Add(i, v);

View file

@ -69,9 +69,6 @@ namespace CodeImp.DoomBuilder.Map
private int action;
private int tag;
private byte[] args;
// Rendering
private int bufferindex;
// Disposing
private bool isdisposed = false;
@ -85,7 +82,6 @@ namespace CodeImp.DoomBuilder.Map
public Vertex End { get { return end; } }
public Sidedef Front { get { return front; } }
public Sidedef Back { get { return back; } }
public int BufferIndex { get { return bufferindex; } set { bufferindex = value; } }
public bool IsDisposed { get { return isdisposed; } }
#endregion
@ -122,9 +118,6 @@ namespace CodeImp.DoomBuilder.Map
// Remove from main list
mainlistitem.List.Remove(mainlistitem);
// Remove from rendering buffer
if(map.IsRenderEnabled) map.LinedefsBuffer.FreeItem(bufferindex);
// Detach from vertices
start.DetachLinedef(startvertexlistitem);
end.DetachLinedef(endvertexlistitem);
@ -213,9 +206,6 @@ namespace CodeImp.DoomBuilder.Map
// Updated
updateneeded = false;
// If rendering is enabled, then update to buffer as well
if(map.IsRenderEnabled && map.IsUpdating) UpdateToBuffer();
}
}
@ -236,72 +226,6 @@ namespace CodeImp.DoomBuilder.Map
l.updateneeded = true;
}
#endregion
#region ================== Rendering
// This writes the vertex to buffer
public void UpdateToBuffer()
{
PTVertex[] lineverts = new PTVertex[4];
Vector2D delta;
Vector2D normal;
int color;
float normallength;
// Not up to date? Then do that first (Update will call this method again)
if(updateneeded) { Update(); return; }
// Delta vector
delta = end.Position - start.Position;
// Recalculate values
normal = new Vector2D(delta.x / length, delta.y / length);
// Single sided?
if((front == null) || (back == null))
{
// Line has an action?
if(action != 0)
color = Graphics.RGB(140, 255, 140);
else
color = Graphics.RGB(255, 255, 255);
}
else
{
// Line has an action?
if(action != 0)
color = Graphics.RGB(50, 140, 50);
else
color = Graphics.RGB(140, 140, 140);
}
// Calculate normal length
normallength = NORMAL_LENGTH / General.Map.Graphics.Renderer2D.Scale;
// Create line normal
lineverts[0].x = start.Position.x + delta.x * 0.5f;
lineverts[0].y = start.Position.y + delta.y * 0.5f;
lineverts[1].x = lineverts[0].x + normal.y * normallength;
lineverts[1].y = lineverts[0].y - normal.x * normallength;
lineverts[0].c = color;
lineverts[1].c = color;
// Create line vertices
lineverts[2].x = start.Position.x;
lineverts[2].y = start.Position.y;
lineverts[3].x = end.Position.x;
lineverts[3].y = end.Position.y;
lineverts[2].c = color;
lineverts[3].c = color;
// Seek to start of item
map.LinedefsBuffer.SeekToItem(bufferindex);
// Write vertices to buffer
foreach(PTVertex v in lineverts) map.LinedefsBuffer.WriteItem(v);
}
#endregion
#region ================== Methods

View file

@ -32,14 +32,6 @@ namespace CodeImp.DoomBuilder.Map
{
internal class MapSet : IDisposable
{
#region ================== Constants
// Minimum size for primitives in buffers
private const int MIN_PRIMITIVE_COUNT = 500;
private const int VERTS_PER_LINEDEF = 2;
#endregion
#region ================== Variables
// Map structures
@ -48,12 +40,6 @@ namespace CodeImp.DoomBuilder.Map
private LinkedList<Sidedef> sidedefs;
private LinkedList<Sector> sectors;
private LinkedList<Thing> things;
// Rendering
private bool renderenabled = false;
private int updating = 0;
private ManagedVertexBuffer verts;
private ManagedVertexBuffer lines;
// Disposing
private bool isdisposed = false;
@ -68,10 +54,6 @@ namespace CodeImp.DoomBuilder.Map
public ICollection<Sector> Sectors { get { return sectors; } }
public ICollection<Thing> Things { get { return things; } }
public bool IsDisposed { get { return isdisposed; } }
public bool IsRenderEnabled { get { return renderenabled; } }
public bool IsUpdating { get { return updating > 0; } }
public ManagedVertexBuffer VerticesBuffer { get { return verts; } }
public ManagedVertexBuffer LinedefsBuffer { get { return lines; } }
#endregion
@ -102,10 +84,6 @@ namespace CodeImp.DoomBuilder.Map
// Already set isdisposed so that changes can be prohibited
isdisposed = true;
// No more rendering
DisableRendering();
updating = 0;
// Dispose all things
list = new ArrayList(things);
foreach(Thing t in list) t.Dispose();
@ -159,7 +137,7 @@ namespace CodeImp.DoomBuilder.Map
foreach(Vertex v in vertices)
{
// Make new vertex
Vertex nv = newset.CreateVertex(v.Position);
Vertex nv = newset.CreateVertex(v.X, v.Y);
vertexlink.Add(v, nv);
}
@ -213,7 +191,7 @@ namespace CodeImp.DoomBuilder.Map
}
// This creates a new vertex
public Vertex CreateVertex(Vector2D pos)
public Vertex CreateVertex(int x, int y)
{
LinkedListNode<Vertex> listitem;
Vertex v;
@ -222,15 +200,12 @@ namespace CodeImp.DoomBuilder.Map
listitem = new LinkedListNode<Vertex>(null);
// Make the vertex
v = new Vertex(this, listitem, pos);
v = new Vertex(this, listitem, x, y);
listitem.Value = v;
// Add vertex to the list
vertices.AddLast(listitem);
// Add vertex to rendering bufer
if(renderenabled) v.BufferIndex = verts.AddItem();
// Return result
return v;
}
@ -251,9 +226,6 @@ namespace CodeImp.DoomBuilder.Map
// Add linedef to the list
linedefs.AddLast(listitem);
// Add linedef to rendering bufer
if(renderenabled) l.BufferIndex = lines.AddItem();
// Return result
return l;
}
@ -317,118 +289,16 @@ namespace CodeImp.DoomBuilder.Map
// Return result
return t;
}
#endregion
#region ================== Resources
// This reloads vertices into rendering buffer
private void ReloadVertices()
{
// Update all vertices to buffer
foreach(Vertex v in vertices) v.UpdateToBuffer();
}
// This reloads linedefs into rendering buffer
private void ReloadLinedefs()
{
// Update all linedefs to buffer
foreach(Linedef l in linedefs) l.UpdateToBuffer();
}
#endregion
#region ================== Rendering
// This enables rendering of map structures
public void EnableRendering()
{
// Not already enabled?
if(!renderenabled)
{
// Enable rendering
renderenabled = true;
// Create buffers
verts = new ManagedVertexBuffer(PTVertex.Stride * Vertex.BUFFERVERTICES, vertices.Count);
lines = new ManagedVertexBuffer(PTVertex.Stride * Linedef.BUFFERVERTICES, linedefs.Count);
#region ================== Updating
// Go for all vertices to add to the buffer
foreach(Vertex v in vertices) v.BufferIndex = verts.AddItem();
// Go for all linedefs to add to the buffer
foreach(Linedef l in linedefs) l.BufferIndex = lines.AddItem();
// Attach events
verts.ReloadResources += new ReloadResourceDelegate(ReloadVertices);
lines.ReloadResources += new ReloadResourceDelegate(ReloadLinedefs);
}
}
// This disables rendering of map structures
public void DisableRendering()
{
// Disable rendering
renderenabled = false;
// Stop any updating
while(updating > 0) EndUpdate();
// Trash buffers
if(verts != null) verts.Dispose();
if(lines != null) lines.Dispose();
verts = null;
lines = null;
}
// This locks the buffers for updates
public void BeginUpdate()
{
// Not already updating
if(updating == 0)
{
// Lock buffers for updating
verts.BeginUpdate();
lines.BeginUpdate();
}
// Now updating
updating++;
}
// This unlocks the buffers
public void EndUpdate()
{
// Updating?
if(updating > 0)
{
// No longer updating
updating--;
// Done updating?
if(updating == 0)
{
// Unlock buffers
verts.EndUpdate();
lines.EndUpdate();
}
}
}
// This updates all structures if needed
public void Update()
{
// Updating begins now
BeginUpdate();
// Update all vertices
foreach(Vertex v in vertices) v.Update();
// Update all linedefs
foreach(Linedef l in linedefs) l.Update();
// Updating has finished
EndUpdate();
}
#endregion

View file

@ -48,14 +48,11 @@ namespace CodeImp.DoomBuilder.Map
private LinkedListNode<Vertex> mainlistitem;
// Position
private int x, y;
private Vector2D pos;
// References
private LinkedList<Linedef> linedefs;
// Rendering
private bool updateneeded;
private int bufferindex;
// Disposing
private bool isdisposed = false;
@ -67,7 +64,8 @@ namespace CodeImp.DoomBuilder.Map
public MapSet Map { get { return map; } }
public ICollection<Linedef> Linedefs { get { return linedefs; } }
public Vector2D Position { get { return pos; } }
public int BufferIndex { get { return bufferindex; } set { bufferindex = value; } }
public int X { get { return x; } }
public int Y { get { return y; } }
public bool IsDisposed { get { return isdisposed; } }
#endregion
@ -75,14 +73,15 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Constructor / Disposer
// Constructor
public Vertex(MapSet map, LinkedListNode<Vertex> listitem, Vector2D pos)
public Vertex(MapSet map, LinkedListNode<Vertex> listitem, int x, int y)
{
// Initialize
this.map = map;
this.linedefs = new LinkedList<Linedef>();
this.mainlistitem = listitem;
this.pos = pos;
this.updateneeded = true;
this.pos = new Vector2D(x, y);
this.x = x;
this.y = y;
// We have no destructor
GC.SuppressFinalize(this);
@ -100,9 +99,6 @@ namespace CodeImp.DoomBuilder.Map
// Remove from main list
mainlistitem.List.Remove(mainlistitem);
// Remove from rendering buffer
if(map.IsRenderEnabled) map.VerticesBuffer.FreeItem(bufferindex);
// Dispose the lines that are attached to this vertex
// because a linedef cannot exist without 2 vertices.
foreach(Linedef l in linedefs) l.Dispose();
@ -138,55 +134,9 @@ namespace CodeImp.DoomBuilder.Map
}
}
}
// This rounds the coordinates to integrals
public void Round()
{
// Round to integrals
pos.x = (float)Math.Round(pos.x);
pos.y = (float)Math.Round(pos.y);
updateneeded = true;
}
// This updates the vertex when changes have been made
public void Update()
{
// Update if needed
if(updateneeded)
{
// Updated
updateneeded = false;
// If rendering is enabled, then update to buffer as well
if(map.IsRenderEnabled && map.IsUpdating) UpdateToBuffer();
}
}
#endregion
#region ================== Rendering
// This writes the vertex to buffer
public void UpdateToBuffer()
{
PTVertex v = new PTVertex();
// Not up to date? Then do that first (Update will call this method again)
if(updateneeded) { Update(); return; }
// Seek to start of item
map.VerticesBuffer.SeekToItem(bufferindex);
// Write vertices to buffer
v.x = pos.x;
v.y = pos.y;
v.z = 0f;
v.c = Color.SlateBlue.ToArgb();
map.VerticesBuffer.WriteItem(v);
}
#endregion
#region ================== Methods
// This returns the distance from given coordinates
@ -211,11 +161,12 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Changes
// This moves the vertex
public void Move(Vector2D newpos)
public void Move(int newx, int newy)
{
// Change position
pos = newpos;
updateneeded = true;
x = newx;
y = newy;
pos = new Vector2D(newx, newy);
// Let all lines know they need an update
foreach(Linedef l in linedefs) l.NeedUpdate();

View file

@ -35,7 +35,7 @@ using SlimDX;
namespace CodeImp.DoomBuilder.Rendering
{
internal class Graphics : IDisposable
internal class D3DGraphics : IDisposable
{
#region ================== Constants
@ -50,7 +50,7 @@ namespace CodeImp.DoomBuilder.Rendering
private int adapter;
// Main objects
private Control rendertarget;
private Panel rendertarget;
private Capabilities devicecaps;
private Device device;
private Renderer2D renderer2d;
@ -68,7 +68,7 @@ namespace CodeImp.DoomBuilder.Rendering
public bool IsDisposed { get { return isdisposed; } }
public Renderer2D Renderer2D { get { return renderer2d; } }
public Renderer3D Renderer3D { get { return renderer3d; } }
public Control RenderTarget { get { return rendertarget; } }
public Panel RenderTarget { get { return rendertarget; } }
public Viewport Viewport { get { return viewport; } }
#endregion
@ -76,7 +76,7 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Constructor / Disposer
// Constructor
public Graphics(Control rendertarget)
public D3DGraphics(Panel rendertarget)
{
// Set render target
this.rendertarget = rendertarget;

View file

@ -1,266 +0,0 @@
#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 SlimDX.Direct3D9;
using System.ComponentModel;
using CodeImp.DoomBuilder.Geometry;
using SlimDX;
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
internal class ManagedVertexBuffer : IDisposable, IResource
{
#region ================== Constants
// Minimum items
private const int MIN_ITEMS = 500;
#endregion
#region ================== Events / Delegates
public event ReloadResourceDelegate ReloadResources;
#endregion
#region ================== Variables
// Buffer info
private int bytesperitem;
private int maxitems;
private LinkedList<int> freeitems;
// The vertexbuffer
private VertexBuffer buffer;
// The stream for updating
private GraphicsStream stream;
// Disposing
private bool isdisposed = false;
#endregion
#region ================== Properties
public VertexBuffer VertexBuffer { get { return buffer; } }
public int ItemCapacity { get { return maxitems; } }
public int ItemCount { get { return maxitems - freeitems.Count; } }
public bool IsDisposed { get { return isdisposed; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public ManagedVertexBuffer(int bytesperitem, int initialsize)
{
// Initialize
this.bytesperitem = bytesperitem;
this.maxitems = initialsize;
if(this.maxitems < MIN_ITEMS) this.maxitems = MIN_ITEMS;
this.freeitems = new LinkedList<int>();
// Add free items to list
for(int i = 0; i < maxitems; i++) freeitems.AddLast(i);
// Create the buffer
CreateBuffer();
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
public void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
UnloadResource();
freeitems = null;
// Done
isdisposed = true;
}
}
#endregion
#region ================== Buffer
// This unloads the vertex buffer
public void UnloadResource()
{
// Clean up
if(stream != null) EndUpdate();
if(buffer != null) buffer.Dispose();
// Done
buffer = null;
}
// This reloads the vertex buffer
public void ReloadResource()
{
// Create the buffer
CreateBuffer();
// Signal that the buffer needs to be rebuild
if(ReloadResources != null) ReloadResources();
}
// This creates the buffer according to settings
private void CreateBuffer()
{
// Create the buffer
buffer = new VertexBuffer(General.Map.Graphics.Device, maxitems * bytesperitem,
Usage.WriteOnly, PTVertex.Format, Pool.Managed);
}
// This starts an update session
public void BeginUpdate()
{
// Lock the buffer and get the stream
stream = buffer.Lock(0, LockFlags.None);
}
// This stops an update session
public void EndUpdate()
{
// Unlock the buffer
buffer.Unlock();
stream.Dispose();
stream = null;
}
// This doubles the buffer size
private void DoubleBuffer()
{
VertexBuffer newbuf;
GraphicsStream newstream;
byte[] copybuf;
int newmaxitems;
bool updating;
// Not in an updating session yet?
if(stream == null)
{
// Start updating
BeginUpdate();
// Remember to stop updating when done
updating = false;
}
else
{
// Remember we want to keep the updating session open
updating = true;
}
// Increase size
newmaxitems = maxitems * 2;
// Add free items to list
for(int i = maxitems; i < newmaxitems; i++) freeitems.AddLast(i);
// Create a new buffer
newbuf = new VertexBuffer(General.Map.Graphics.Device, newmaxitems * bytesperitem,
Usage.WriteOnly, PTVertex.Format, Pool.Managed);
// Copy old data to new buffer
newstream = newbuf.Lock(0, LockFlags.None);
stream.Seek(0, SeekOrigin.Begin);
copybuf = new byte[maxitems * bytesperitem];
stream.Read(copybuf, 0, copybuf.Length);
newstream.Write(copybuf, 0, copybuf.Length);
// Dispose old buffer
buffer.Unlock();
stream.Dispose();
buffer.Dispose();
// Switch to new buffer
maxitems = newmaxitems;
buffer = newbuf;
stream = newstream;
// Stop updating session?
if(!updating)
{
// Stop updating now
EndUpdate();
}
}
#endregion
#region ================== Items
// This adds an item to the buffer and returns its unique index
public int AddItem()
{
int itemindex;
// Double the buffer for more items when none are available
if(freeitems.Count == 0) DoubleBuffer();
// Fetch the first free index from the list
itemindex = freeitems.First.Value;
freeitems.RemoveFirst();
// Return result
return itemindex;
}
// This frees an item
public void FreeItem(int index)
{
// Add item back into the list
freeitems.AddLast(index);
}
// This seeks the stream to the position for a specific item
public void SeekToItem(int index)
{
// Seek to item start position
stream.Seek(index * bytesperitem, SeekOrigin.Begin);
}
// This allows writing to the stream
public void WriteItem<T>(T item) where T : struct
{
// Write the item
stream.Write(item);
}
#endregion
}
}

View file

@ -0,0 +1,56 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Drawing;
namespace CodeImp.DoomBuilder.Rendering
{
public struct PixelColor
{
#region ================== Variables
// Members
public byte b;
public byte g;
public byte r;
public byte a;
#endregion
#region ================== Constructors
// Constructor
public PixelColor(byte a, byte r, byte g, byte b)
{
// Initialize
this.a = a;
this.r = r;
this.g = g;
this.b = b;
}
#endregion
#region ================== Static Methods
// Construct from color
public static PixelColor FromColor(Color c)
{
return new PixelColor(c.A, c.R, c.G, c.B);
}
// Construct from int
public static PixelColor FromInt(int c)
{
return FromColor(Color.FromArgb(c));
}
#endregion
#region ================== Methods
#endregion
}
}

View file

@ -31,12 +31,13 @@ using SlimDX.Direct3D;
using SlimDX.Direct3D9;
using SlimDX;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing.Imaging;
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
internal class Renderer2D : IDisposable
internal unsafe class Renderer2D : IDisposable
{
#region ================== Constants
@ -45,16 +46,20 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Variables
// Owner
private Graphics graphics;
private D3DGraphics graphics;
// Rendering memory
private Bitmap image;
private BitmapData pixeldata;
private PixelColor* pixels;
private int width;
private int height;
// View settings (world coordinates)
private float scale;
private float offsetx;
private float offsety;
// Matrices
private Matrix matproj, matview, matworld;
// Disposing
private bool isdisposed = false;
@ -70,13 +75,16 @@ namespace CodeImp.DoomBuilder.Rendering
#endregion
#region ================== Constructor / Disposer
// Constructor
public Renderer2D(Graphics graphics)
public Renderer2D(D3DGraphics graphics)
{
// Initialize
this.graphics = graphics;
// Create image memory
CreateMemory();
// We have no destructor
GC.SuppressFinalize(this);
}
@ -88,6 +96,9 @@ namespace CodeImp.DoomBuilder.Rendering
if(!isdisposed)
{
// Clean up
graphics.RenderTarget.BackgroundImage = null;
if(image != null) image.Dispose();
pixels = null;
// Done
isdisposed = true;
@ -98,51 +109,52 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Control
// This rebuilds matrices according to view settings
private void SetupMatrices()
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public void Reset()
{
float width, height, left, top, right, bottom;
// Build projection matrix
width = (float)graphics.RenderTarget.ClientSize.Width / scale;
height = (float)graphics.RenderTarget.ClientSize.Height / scale;
left = offsetx - width * 0.5f;
top = offsety - height * 0.5f;
right = offsetx + width * 0.5f;
bottom = offsety + height * 0.5f;
matproj = Matrix.OrthoOffCenterLH(left, right, top, bottom, -1f, 1f);
// World and view are fixed
matview = Matrix.Identity;
matworld = Matrix.Identity;
// Re-create image memory
CreateMemory();
}
// This begins a drawing session
public bool StartRendering()
{
// Can we render?
if(graphics.StartRendering())
{
// Apply matrices
graphics.Device.SetTransform(TransformState.Projection, matproj);
graphics.Device.SetTransform(TransformState.View, matview);
graphics.Device.SetTransform(TransformState.World, matworld);
// Success
return true;
}
else
{
// Cannot render
return false;
}
// Allocates new image memory to render on
public void CreateMemory()
{
// Get new width and height
width = graphics.RenderTarget.ClientSize.Width;
height = graphics.RenderTarget.ClientSize.Height;
// Trash old image
graphics.RenderTarget.BackgroundImage = null;
if(image != null) image.Dispose();
// Allocate memory
image = new Bitmap(width, height, PixelFormat.Format32bppArgb);
graphics.RenderTarget.BackgroundImage = image;
}
// This begins a drawing session
public unsafe bool StartRendering()
{
// Lock memory
pixeldata = image.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
pixels = (PixelColor*)pixeldata.Scan0.ToPointer();
// Erase image
General.ZeroMemory(pixeldata.Scan0, width * height * 4);
// Ready for rendering
return true;
}
// This ends a drawing session
public void FinishRendering()
{
// Finish and present our drawing
graphics.FinishRendering();
// Unlock memory
image.UnlockBits(pixeldata);
// Refresh
graphics.RenderTarget.Invalidate();
}
// This changes view position
@ -151,9 +163,6 @@ namespace CodeImp.DoomBuilder.Rendering
// Change position in world coordinates
offsetx = x;
offsety = y;
// Setup new matrices
SetupMatrices();
}
// This changes zoom
@ -161,9 +170,6 @@ namespace CodeImp.DoomBuilder.Rendering
{
// Change zoom scale
this.scale = scale;
// Setup new matrices
SetupMatrices();
// Recalculate linedefs (normal lengths must be adjusted)
foreach(Linedef l in General.Map.Data.Linedefs) l.NeedUpdate();
@ -174,39 +180,102 @@ namespace CodeImp.DoomBuilder.Rendering
{
Vector3 mp, res;
// FIXME!
// Get mouse position in Vector3
mp = new Vector3(mousepos.x, mousepos.y, 1f);
//mp = new Vector3(mousepos.x, mousepos.y, 1f);
// Unproject
res = mp.Unproject(graphics.Viewport, matproj, matview, matworld);
//res = mp.Unproject(graphics.Viewport, matproj, matview, matworld);
// Return result
return new Vector2D(res.X, res.Y);
//return new Vector2D(res.X, res.Y);
return new Vector2D();
}
#endregion
#region ================== Pixel Rendering
// This draws a pixel normally
private void DrawPixelSolid(int x, int y, PixelColor c)
{
// Draw pixel when within range
if((x >= 0) && (x < width) && (y >= 0) && (y < height))
pixels[y * width + x] = c;
}
// This draws a pixel alpha blended
private void DrawPixelAlpha(int x, int y, PixelColor c)
{
// Draw only when within range
if((x >= 0) && (x < width) && (y >= 0) && (y < height))
{
// Get the target pixel
PixelColor* p = pixels + (y * width + x);
// Not drawn on target yet?
if(*(int*)p == 0)
{
// Simply apply color to pixel
*p = c;
}
else
{
// Blend with pixel
if((int)p->a + (int)c.a > 255) p->a = 255; else p->a += c.a;
p->r = (byte)((float)p->r * (1f - c.a) + (float)c.r * c.a);
p->g = (byte)((float)p->g * (1f - c.a) + (float)c.g * c.a);
p->b = (byte)((float)p->b * (1f - c.a) + (float)c.b * c.a);
}
}
}
#endregion
// This draws a line normally
private void DrawLineSolid(int x0, int y0, int x1, int y1, PixelColor c)
{
// TODO: See http://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm
}
#region ================== Map Rendering
// This renders a set of Linedefs
public void RenderLinedefs(MapSet map, ICollection<Linedef> linedefs)
public unsafe void RenderLinedefs(MapSet map, ICollection<Linedef> linedefs)
{
// Any linedefs?
if(linedefs.Count > 0)
{
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
graphics.Device.SetStreamSource(0, map.LinedefsBuffer.VertexBuffer, 0, PTVertex.Stride);
foreach(Linedef l in linedefs)
{
graphics.Device.DrawPrimitives(PrimitiveType.LineList, l.BufferIndex * Linedef.BUFFERVERTICES, Linedef.RENDERPRIMITIVES);
}
}
// TODO
}
// This renders a set of Linedefs
public void RenderVertices(MapSet map, ICollection<Vertex> vertices)
{
Vector2D nv;
Vector2D voffset = new Vector2D(-offsetx + (width * 0.5f) / scale, -offsety - (height * 0.5f) / scale);
Vector2D vscale = new Vector2D(scale, -scale);
PixelColor c = PixelColor.FromInt(-1);
int x, y;
// Go for all vertices
foreach(Vertex v in vertices)
{
// Transform vertex coordinates
nv = v.Position;
nv.Transform(voffset, vscale);
x = (int)nv.x;
y = (int)nv.y;
// Draw pixel here
DrawPixelSolid(x, y, c);
DrawPixelSolid(x + 1, y, c);
DrawPixelSolid(x, y + 1, c);
DrawPixelSolid(x - 1, y, c);
DrawPixelSolid(x, y - 1, c);
DrawPixelSolid(x + 1, y - 1, c);
DrawPixelSolid(x + 1, y + 1, c);
DrawPixelSolid(x - 1, y - 1, c);
DrawPixelSolid(x - 1, y + 1, c);
}
}
#endregion

View file

@ -41,7 +41,7 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Variables
// Owner
private Graphics graphics;
private D3DGraphics graphics;
// Disposing
private bool isdisposed = false;
@ -58,7 +58,7 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Constructor / Disposer
// Constructor
public Renderer3D(Graphics graphics)
public Renderer3D(D3DGraphics graphics)
{
// Initialize
this.graphics = graphics;