diff --git a/Sledge.DataStructures.Rendering/SolidVertexArray.cs b/Sledge.DataStructures.Rendering/SolidVertexArray.cs
index ee767f3a9..8da5a9d19 100644
--- a/Sledge.DataStructures.Rendering/SolidVertexArray.cs
+++ b/Sledge.DataStructures.Rendering/SolidVertexArray.cs
@@ -8,8 +8,8 @@
namespace Sledge.DataStructures.Rendering
{
///
- /// A solid vertex array collects and stores a VBO for a single soll solids in the map.
- /// Faces are grouped by texture and then split into optimised rendering later on.
+ /// A solid vertex array collects and stores a VBO for all solids in the map.
+ /// Faces are grouped by texture and then split into subsets for optimised rendering later on.
///
public class SolidVertexArray
{
@@ -33,7 +33,8 @@ static SolidVertexArray()
public List> TextureSubsets { get; private set; }
public List> WireframeSubsets { get; private set; }
public Dictionary FaceOffsets { get; private set; }
- private readonly Dictionary Entity private readonly Dictionary> _arrays;
+ public Dictionary EntityOffsets { get; private set; }
+ private readonly Dictionary> _arrays;
public void Bind(object context, int index)
{
@@ -64,10 +65,10 @@ public SolidVertexArray(IEnumerable objects)
TextureSubsets = new List>();
WireframeSubsets = new List>();
FaceOffsets = new Dictionary();
- GetArrayData(objects, out count, out array, out indices, out wirefrEntityOffsets = new DictionaryeIndices, TextureSubsets, WireframeSubsets, FaceOffsets);
+ EntityOffsets = new Dictionary();
+ GetArrayData(objects, out count, out array, out indices, out wireframeIndices, TextureSubsets, WireframeSubsets, FaceOffsets, EntityOffsets);
- Array.Update(count, array, new[] {indices, wireframeIndices});
- , Entityn, Modes, count, sizeof(float), array, new[] { indices, wireframeIndices});
+ Array = new VertexBuffer(Specification, Modes, count, sizeof(float), array, new[] { indices, wireframeIndices});
}
///
@@ -84,19 +85,21 @@ public void Update(IEnumerable objects)
TextureSubsets.Clear();
WireframeSubsets.Clear();
FaceOffsets.Clear();
- GetArrayData(objects, out count, out array, out indices, out wireframeIndices, TextureEntity out wireframeIndices, TextureSubsets, WireframeSubsets, FaceOffsets);
+ EntityOffsets.Clear();
+ GetArrayData(objects, out count, out array, out indices, out wireframeIndices, TextureSubsets, WireframeSubsets, FaceOffsets, EntityOffsets);
Array.Update(count, array, new[] {indices, wireframeIndices});
- , Entity }
+ }
public void UpdatePartial(IEnumerable objects)
{
UpdatePartial(objects.OfType().SelectMany(x => x.Faces));
+ UpdatePartial(objects.OfType().Where(x => x.Children.Count == 0));
}
public void UpdatePartial(IEnumerable faces)
{
- var list = UpdatePartial(objects.OfType().Where(x => x.Children.Count == 0 var list = new float[128]; // 128 is large enough for most faces (up to 11 faces)
+ var list = new float[128]; // 128 is large enough for most faces (up to 11 faces)
foreach (var face in faces)
{
if (!FaceOffsets.ContainsKey(face)) continue;
@@ -108,9 +111,7 @@ public void UpdatePartial(IEnumerable faces)
}
}
- ///
- /// Does a loop around the map objects and calculates array data and the subsets
- public void UpdatePartial(IEnumerable entities)
+ public void UpdatePartial(IEnumerable entities)
{
var list = new float[6 * 4 * SpecSize];
foreach (var entity in entities)
@@ -122,7 +123,12 @@ public void UpdatePartial(IEnumerable entities)
{
idx = WriteFace(list, idx, face);
}
- Array.UpdatePartial(offset, list.Length calculates array data and the subsets
+ Array.UpdatePartial(offset, list.Length, list);
+ }
+ }
+
+ ///
+ /// Does a loop around the map objects and calculates array data and the subsets
///
/// The objects in the array
/// Outputs the number of verts in the array
@@ -132,19 +138,21 @@ public void UpdatePartial(IEnumerable entities)
/// The collection of textured subsets to populate
/// The collection of wireframe subsets to populate
///
- private static void GetArrayData(IEnumerable objects, out int count, out float[] array, out uint[] indices, ou///
+ private static void GetArrayData(IEnumerable objects, out int count, out float[] array, out uint[] indices, out uint[] wireframeIndices, ICollection> subsets, ICollection> wireframeSubsets, Dictionary faceOffsets, Dictionary entityOffsets)
{
var obj = objects.Where(x => !x.IsVisgroupHidden && !x.IsCodeHidden).ToList();
var faces = obj.OfType().SelectMany(x => x.Faces).ToList();
- var entities = obj.OfType().Where(x => x.Children.Count == 0 uint index = 0;
+ var entities = obj.OfType().Where(x => x.Children.Count == 0).ToList();
+ var indexList = new List();
+ var wireframeIndexList = new List();
+ uint index = 0;
var idx = 0;
- array = new float[SpecSize * faces.Sum(x => x.Vertices.Count)];
+ var numVerts = faces.Sum(x => x.Vertices.Count) + entities.Count * 6 * 4; // Entity is always a rec. prism (6 sides, quads)
+ array = new float[SpecSize * numVerts];
var subsetStart = 0;
- var wireframeSubsetvar numVerts = faces.Sum(x => x.Vertices.Count) + entities.Count * 6 * 4; // Entity is always a rec. prism (6 sides, quads)
- array = new float[SpecSize * numVerts=> new { x.Texture.Texture }))
+ var wireframeSubsetStart = 0;
+ foreach (var group in faces.GroupBy(x => new { x.Texture.Texture }))
{
foreach (var face in group)
{
@@ -171,12 +179,7 @@ private static void GetArrayData(IEnumerable objects, out int count,
wireframeSubsets.Add(new VertexArraySubset(null, wireframeSubsetStart, wireframeIndexList.Count - wireframeSubsetStart));
wireframeSubsetStart = wireframeIndexList.Count;
}
- indices = indexList.ToArray();
- wireframeIndices = wireframeIndexList.ToArray();
- count = indices.Length;
- }
-
- private staforeach (var entity in entities)
+ foreach (var entity in entities)
{
entityOffsets.Add(entity, idx);
foreach (var face in entity.GetFaces())
@@ -189,22 +192,28 @@ private staforeach (var entity in entities)
indexList.Add(index);
indexList.Add(index + i);
indexList.Add(index + i + 1);
- }i = (uint) ((i + 1) % face.Vertices.Count);
+ }
+ }
+ for (uint i = 0; i < face.Vertices.Count; i++)
+ {
+ var ni = (uint)((i + 1) % face.Vertices.Count);
wireframeIndexList.Add(index + i);
- wireframeIndexList.Add(index+ ni);
+ wireframeIndexList.Add(index + ni);
}
- index += (uint) face.Vertices.Count;
- }
-
- subsets.Add(new VertexArraySubset(group.Key.Texture, subsetStart, indexList.Count face.Vertices.Count;
+ index += (uint)face.Vertices.Count;
}
}
if (entities.Any())
{
- subsets.Add(new VertexArraySubset(null, subsetStart, indexList.Count - subsetStart)); wireframeSubsetStart = wireframeIndexList.Count;
+ subsets.Add(new VertexArraySubset(null, subsetStart, indexList.Count - subsetStart));
+ wireframeSubsets.Add(new VertexArraySubset(null, wireframeSubsetStart, wireframeIndexList.Count - wireframeSubsetStart));
}
indices = indexList.ToArray();
- wireframeIndices = wireframeIndexL private static int WriteFace(float[] array, int idx, Face face)
+ wireframeIndices = wireframeIndexList.ToArray();
+ count = indices.Length;
+ }
+
+ private static int WriteFace(float[] array, int idx, Face face)
{
float nx = (float) face.Plane.Normal.DX,
ny = (float) face.Plane.Normal.DY,
@@ -225,12 +234,7 @@ private staforeach (var entity in entities)
array[idx++] = (r);
array[idx++] = (g);
array[idx++] = (b);
- array[idx++] = (face.IsSelected || face.Parent.IsSelected ? 1 : 0);
- }
- return idx;
- }
- }
-}(face.Parent != null && face.Parent.IsSelected) ? 1 : 0);
+ array[idx++] = (face.IsSelected || (face.Parent != null && face.Parent.IsSelected) ? 1 : 0);
}
return idx;
}
diff --git a/Sledge.DataStructures/MapObjects/Entity.cs b/Sledge.DataStructures/MapObjects/Entity.cs
index eeb02e8d4..f55e979f5 100644
--- a/Sledge.DataStructures/MapObjects/Entity.cs
+++ b/Sledge.DataStructures/MapObjects/Entity.cs
@@ -1,7 +1,8 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
-using Sledge.DatCommonusing Sledge.DataStructures.GameData;
+using Sledge.Common;
+using Sledge.DataStructures.GameData;
using Sledge.DataStructures.Geometric;
using Sledge.DataStructures.Transformations;
@@ -12,8 +13,7 @@ public class Entity : MapObject
public GameDataObject GameData { get; set; }
public EntityData EntityData { get; set; }
public Coordinate Origin { get; set; }
-
- publi public ITexture Sprite}
+ public ITexture Sprite { get; set; }
public Entity(long id) : base(id)
{
diff --git a/Sledge.DataStructures/MapObjects/Map.cs b/Sledge.DataStructures/MapObjects/Map.cs
index d6f39b840..0f2d69172 100644
--- a/Sledge.DataStructures/MapObjects/Map.cs
+++ b/Sledge.DataStructures/MapObjects/Map.cs
@@ -58,9 +58,10 @@ public void PostLoadProcess(GameData.GameData gameData, Func t
IDGenerator.Reset(maxObjectId, maxFaceId);
// todo visgroups
+ // WorldSpawn.ForEach(x => x.IsVisgroupHidden, x => x.IsVisgroupHidden = true, true);
// Purge empty groups
- foreach (var // WorldSpawn.ForEach(x => x.IsVisgroupHidden, x => x.IsVisgroupHidden = true, true);r emptyGroup in WorldSpawn.Find(x => x is Group && !x.Children.Any()))
+ foreach (var emptyGroup in WorldSpawn.Find(x => x is Group && !x.Children.Any()))
{
emptyGroup.Parent.Children.Remove(emptyGroup);
}
@@ -78,12 +79,15 @@ public void PartialPostLoadProcess(Predicate matcher, GameData.GameDa
{
if (obj is Entity)
{
- ((Entity)obj).GameData = gameData.Classes.FirstOrDefault(x => x.Name == ((Entityvar gd = gameData.Classes.FirstOrDefault(x => x.Name == ((Entity) obj).EntityData.Name);
+ var gd = gameData.Classes.FirstOrDefault(x => x.Name == ((Entity) obj).EntityData.Name);
var t = gd != null && gd.Behaviours.Any(x => x.Name == "iconsprite" && x.Values.Count == 1)
? textureAccessor(gd.Behaviours.First(x => x.Name == "iconsprite").Values[0])
: null;
((Entity) obj).GameData = gd;
- ((Entity) obj).Sprite = t else if (obj is Solid)
+ ((Entity) obj).Sprite = t;
+ obj.UpdateBoundingBox();
+ }
+ else if (obj is Solid)
{
((Solid)obj).Faces.ForEach(f =>
{
diff --git a/Sledge.Editor/Documents/Document.cs b/Sledge.Editor/Documents/Document.cs
index 04c6cd79d..a78f90a59 100644
--- a/Sledge.Editor/Documents/Document.cs
+++ b/Sledge.Editor/Documents/Document.cs
@@ -12,13 +12,14 @@
using Sledge.Editor.Tools;
using Sledge.Editor.UI;
using Sledge.Editor.Visgroups;
+using Sledge.Graphics;
using Sledge.Graphics.Helpers;
-usine.Graphics.Helpers;
using Sledge.Providers;
using Sledge.Providers.GameData;
using Sledge.Providers.Texture;
using Sledge.Settings;
-using Path = System.IO.PaSledge.UItem.IO.Path;
+using Sledge.UI;
+using Path = System.IO.Path;
namespace Sledge.Editor.Documents
{
@@ -33,7 +34,9 @@ public class Document
public bool HideFaceMask { get; set; }
- private RenderManager Renderer { geublic RenderManager Renderer { get; privateanager Selection { get; private set; }
+ public RenderManager Renderer { get; private set; }
+
+ public SelectionManager Selection { get; private set; }
public HistoryManager History { get; private set; }
private readonly DocumentSubscriptions _subscriptions;
diff --git a/Sledge.Editor/Sledge.Editor.csproj b/Sledge.Editor/Sledge.Editor.csproj
index 4aeaf6bbf..78008ea1e 100644
--- a/Sledge.Editor/Sledge.Editor.csproj
+++ b/Sledge.Editor/Sledge.Editor.csproj
@@ -107,14 +107,14 @@
-
-
-
+
-
+
+
+
@@ -143,11 +143,11 @@
Code
+
Code
- RenderManagerRenderableansformedDisplayListRenderable.cs" />
@@ -326,6 +326,12 @@
Settings.settings
True
+
+ PreserveNewest
+
+
+ PreserveNewest
+
@@ -333,12 +339,7 @@
Sledge.Common
- {FC8A5448-0F8
- PreserveNewest
-
-
- PreserveNewest
-
+ {FC8A5448-0F8B-4828-AC49-8D6138E20254}
Sledge.Database
diff --git a/Sledge.Providers/Texture/TexturePackage.cs b/Sledge.Providers/Texture/TexturePackage.cs
index f9d36ec88..d0b80af56 100644
--- a/Sledge.Providers/Texture/TexturePackage.cs
+++ b/Sledge.Providers/Texture/TexturePackage.cs
@@ -1,88 +1,87 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO;
-using Sledge.Graphics;
-using Sledge.Graphics.Helpers;
-
-namespace Sledge.Providers.Texture
-{
- public class TexturePackage
- {
- private static readonly Dictionary LoadedPackages = new Dictionary();
- private static readonly Dictionary LoadedItems = new Dictionary();
-
- public static void ClearLoadedPackages()
- {
- LoadedPackages.Clear();
- LoadedItems.Clear();
- TextureHelper.ClearLoadedTextures();
- }
-
- public static void LoadTextureData(string name)
- {
- if (TextureHelper.Exists(name)) return;
- var item = LoadedItems[name];
- if (item != null)
- {
- TextureProvider.LoadTextureFromPackage(item.Package, item.Name);
- }
- }
-
- public static void LoadTextureData(IEnumerable names)
- {
- var texes = names.Where(x => !TextureHelper.Exists(x));
- TextureProvider.LoadTexturesFromPackages(LoadedPackages.Values, texes);
- }
-
- public static IEnumerable GetLoadedPackages()
- {
- return LoadedPackages.Values;
- }
-
- public static IEnumerable GetLoadedItems()
- {
- return LoadedItems.Values;
- }
-
- public static TextureItem GetItem(string name)
- {
- return LoadedItems.ContainsKey(name) ? LoadedItems[name] : null;
- }
-
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Sledge.Graphics;
+using Sledge.Graphics.Helpers;
+
+namespace Sledge.Providers.Texture
+{
+ public class TexturePackage
+ {
+ private static readonly Dictionary LoadedPackages = new Dictionary();
+ private static readonly Dictionary LoadedItems = new Dictionary();
+
+ public static void ClearLoadedPackages()
+ {
+ LoadedPackages.Clear();
+ LoadedItems.Clear();
+ TextureHelper.ClearLoadedTextures();
+ }
+
+ public static void LoadTextureData(string name)
+ {
+ if (TextureHelper.Exists(name)) return;
+ var item = LoadedItems[name];
+ if (item != null)
+ {
+ TextureProvider.LoadTextureFromPackage(item.Package, item.Name);
+ }
+ }
+
+ public static void LoadTextureData(IEnumerable names)
+ {
+ var texes = names.Where(x => !TextureHelper.Exists(x));
+ TextureProvider.LoadTexturesFromPackages(LoadedPackages.Values, texes);
+ }
+
+ public static IEnumerable GetLoadedPackages()
+ {
+ return LoadedPackages.Values;
+ }
+
+ public static IEnumerable GetLoadedItems()
+ {
+ return LoadedItems.Values;
+ }
+
+ public static TextureItem GetItem(string name)
+ {
+ return LoadedItems.ContainsKey(name) ? LoadedItems[name] : null;
+ }
+
public static void Load(string file)
{
file = file.ToLower();
-
- if (!(File.Exists(file) || Directory.Exists(file)) || LoadedPackages.ContainsKey(file)) return;
- var tp = new TexturePackage(file);
- tp.LoadAllTextureItems();
- LoadedPackages.Add(file, tp);
- }
-
- public string PackageFile { get; private set; }
- public Dictionary Items { get; private set; }
-
- private TexturePackage(string packageFile)
- {
- PackageFile = packageFile;
- Items = new Dictionary();
- }
-
- ///
- /// Tells this package to retrieve all the texture names from the file.
/// This will not get the actual texture data, but it will get some metadata
-
- /// like name, width, height, and so on.
- ///
- public void LoadAllTextureItems()
- {
- foreach (var ti in TextureProvider.GetAllTextureItemsFromPackage(this))
- {
- if (LoadedItems.ContainsKey(ti.Name)) continue;
- Items.Add(ti.Name, ti);
- LoadedItems.Add(ti.Name, ti);
- }
- }
- }
-}
+ if (!(File.Exists(file) || Directory.Exists(file)) || LoadedPackages.ContainsKey(file)) return;
+ var tp = new TexturePackage(file);
+ tp.LoadAllTextureItems();
+ LoadedPackages.Add(file, tp);
+ }
+
+ public string PackageFile { get; private set; }
+ public Dictionary Items { get; private set; }
+
+ private TexturePackage(string packageFile)
+ {
+ PackageFile = packageFile;
+ Items = new Dictionary();
+ }
+
+ ///
+ /// Tells this package to retrieve all the texture names from the file.
+ /// This will not get the actual texture data, but it will get some metadata
+ /// like name, width, height, and so on.
+ ///
+ public void LoadAllTextureItems()
+ {
+ foreach (var ti in TextureProvider.GetAllTextureItemsFromPackage(this))
+ {
+ if (LoadedItems.ContainsKey(ti.Name)) continue;
+ Items.Add(ti.Name, ti);
+ LoadedItems.Add(ti.Name, ti);
+ }
+ }
+ }
+}
diff --git a/Sledge.UI/Viewport2D.cs b/Sledge.UI/Viewport2D.cs
index 7a90598aa..ad2aa6404 100644
--- a/Sledge.UI/Viewport2D.cs
+++ b/Sledge.UI/Viewport2D.cs
@@ -178,13 +178,13 @@ public Coordinate ZeroUnusedCoordinate(Coordinate c)
public override void SetViewport()
{
base.SetViewport();
- //Viewport.Orthographic(0, 0, Width, Height, -50000, 50000);
+ Viewport.Orthographic(0, 0, Width, Height, -50000, 50000);
}
public override Matrix4 GetViewportMatrix()
{
const float near = -1000000;
- const float far = 1000000;
+ const float far = 1000000;
return Matrix4.CreateOrthographic(Width, Height, near, far);
}
diff --git a/Sledge.UI/Viewport3D.cs b/Sledge.UI/Viewport3D.cs
index 5691a654c..8fa9dfec8 100644
--- a/Sledge.UI/Viewport3D.cs
+++ b/Sledge.UI/Viewport3D.cs
@@ -1,23 +1,23 @@
-using OpenTK.Graphics.OpenGL;
-using Sledge.Graphics;
-using Sledge.DataStructures.Geometric;
-using OpenTK;
-using Sledge.Graphics.Helpers;
-using Matrix = Sledge.Graphics.Helpers.Matrix;
-
-namespace Sledge.UI
-{
- public class Viewport3D : ViewportBase
- {
- public Camera Camera { get; set; }
-
- public Viewport3D()
- {
- Camera = new Camera();
- }
-
- public Viewport3D(RenderContext context) : base(context)
- {
+using OpenTK.Graphics.OpenGL;
+using Sledge.Graphics;
+using Sledge.DataStructures.Geometric;
+using OpenTK;
+using Sledge.Graphics.Helpers;
+using Matrix = Sledge.Graphics.Helpers.Matrix;
+
+namespace Sledge.UI
+{
+ public class Viewport3D : ViewportBase
+ {
+ public Camera Camera { get; set; }
+
+ public Viewport3D()
+ {
+ Camera = new Camera();
+ }
+
+ public Viewport3D(RenderContext context) : base(context)
+ {
Camera = new Camera();
}
@@ -40,88 +40,86 @@ public override Matrix4 GetCameraMatrix()
return cameraMatrix;
}
- public ove
-
- public override void SetViewport()
- {
- base.SetViewport();
- Viewport.Perspective(0, 0, Width, Height);
- }
-
- protected override void UpdateBeforeClearViewport()
- {
- Camera.Position();
- base.UpdateBeforeClearViewport();
- }
-
- protected override void UpdateAfterRender()
- {
- base.UpdateAfterRender();
- Listeners.ForEach(x => x.Render3D());
-
- Matrix.Set(MatrixMode.Modelview);
- Matrix.Identity();
- Viewport.Orthographic(0, 0, Width, Height);
- Listeners.ForEach(x => x.Render2D());
- }
-
- ///
- /// Convert a screen space coordinate into a world space coordinate.
- /// The resulting coordinate will be quite a long way from the camera.
- ///
- /// The screen coordinate (with Y in OpenGL space)
- /// The world coordinate
- public Coordinate ScreenToWorld(Coordinate screen)
- {
- screen = new Coordinate(screen.X, screen.Y, 1);
- var viewport = new[] { 0, 0, Width, Height };
= Matrix4d.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60), Width / (float)Height, 0.1f, 50000);
- var vm
- var vm = Matrix4d.LookAt(
Vector3d(Camera.Location.X, Camera.Location.Y, Camera.Location.Z),
- new
Vector3d(Camera.LookAt.X, Camera.LookAt.Y, Camera.LookAt.Z),
- Vec
- Vector3d.UnitZ);
- return MathFunctions.Unproject(screen, viewport, pm, vm);
- }
-
- ///
- /// Convert a world space coordinate into a screen space coordinate.
- ///
- /// The world coordinate
- /// The screen coordinate
- public Coordinate WorldToScreen(Coordinate world)
- {
- var viewport = new[] { 0, 0, Width, Height };
= Matrix4d.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60), Width / (float)Height, 0.1f, 50000);
- var vm
- var vm = Matrix4d.LookAt(
Vector3d(Camera.Location.X, Camera.Location.Y, Camera.Location.Z),
- new
Vector3d(Camera.LookAt.X, Camera.LookAt.Y, Camera.LookAt.Z),
- Vec
- Vector3d.UnitZ);
- return MathFunctions.Project(world, viewport, pm, vm);
- }
-
- ///
- /// Project the 2D coordinates from the screen coordinates outwards
- /// from the camera along the lookat vector, taking the frustrum
- /// into account. The resulting line will be run from the camera
- /// position along the view axis and end at the back clipping pane.
- ///
- /// The X coordinate on screen
- /// The Y coordinate on screen
- /// A line beginning at the camera location and tracing
- /// along the 3D projection for at least 1,000,000 units.
- public Line CastRayFromScreen(int x, int y)
- {
- var near = new Coordinate(x, Height - y, 0);
- var far = new Coordinate(x, Height - y, 1);
= Matrix4d.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60), Width / (float)Height, 0.1f, 50000);
- var vm
- var vm = Matrix4d.LookAt(
Vector3d(Camera.Location.X, Camera.Location.Y, Camera.Location.Z),
- new
Vector3d(Camera.LookAt.X, Camera.LookAt.Y, Camera.LookAt.Z),
- Vec
- Vector3d.UnitZ);
- var viewport = new[] { 0, 0, Width, Height };
- var un = MathFunctions.Unproject(near, viewport, pm, vm);
- var uf = MathFunctions.Unproject(far, viewport, pm, vm);
- return (un == null || uf == null) ? null : new Line(un, uf);
- }
- }
-}
+ public override void SetViewport()
+ {
+ base.SetViewport();
+ Viewport.Perspective(0, 0, Width, Height);
+ }
+
+ protected override void UpdateBeforeClearViewport()
+ {
+ Camera.Position();
+ base.UpdateBeforeClearViewport();
+ }
+
+ protected override void UpdateAfterRender()
+ {
+ base.UpdateAfterRender();
+ Listeners.ForEach(x => x.Render3D());
+
+ Matrix.Set(MatrixMode.Modelview);
+ Matrix.Identity();
+ Viewport.Orthographic(0, 0, Width, Height);
+ Listeners.ForEach(x => x.Render2D());
+ }
+
+ ///
+ /// Convert a screen space coordinate into a world space coordinate.
+ /// The resulting coordinate will be quite a long way from the camera.
+ ///
+ /// The screen coordinate (with Y in OpenGL space)
+ /// The world coordinate
+ public Coordinate ScreenToWorld(Coordinate screen)
+ {
+ screen = new Coordinate(screen.X, screen.Y, 1);
+ var viewport = new[] { 0, 0, Width, Height };
+ var pm = Matrix4d.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60), Width / (float)Height, 0.1f, 50000);
+ var vm = Matrix4d.LookAt(
+ new Vector3d(Camera.Location.X, Camera.Location.Y, Camera.Location.Z),
+ new Vector3d(Camera.LookAt.X, Camera.LookAt.Y, Camera.LookAt.Z),
+ Vector3d.UnitZ);
+ return MathFunctions.Unproject(screen, viewport, pm, vm);
+ }
+
+ ///
+ /// Convert a world space coordinate into a screen space coordinate.
+ ///
+ /// The world coordinate
+ /// The screen coordinate
+ public Coordinate WorldToScreen(Coordinate world)
+ {
+ var viewport = new[] { 0, 0, Width, Height };
+ var pm = Matrix4d.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60), Width / (float)Height, 0.1f, 50000);
+ var vm = Matrix4d.LookAt(
+ new Vector3d(Camera.Location.X, Camera.Location.Y, Camera.Location.Z),
+ new Vector3d(Camera.LookAt.X, Camera.LookAt.Y, Camera.LookAt.Z),
+ Vector3d.UnitZ);
+ return MathFunctions.Project(world, viewport, pm, vm);
+ }
+
+ ///
+ /// Project the 2D coordinates from the screen coordinates outwards
+ /// from the camera along the lookat vector, taking the frustrum
+ /// into account. The resulting line will be run from the camera
+ /// position along the view axis and end at the back clipping pane.
+ ///
+ /// The X coordinate on screen
+ /// The Y coordinate on screen
+ /// A line beginning at the camera location and tracing
+ /// along the 3D projection for at least 1,000,000 units.
+ public Line CastRayFromScreen(int x, int y)
+ {
+ var near = new Coordinate(x, Height - y, 0);
+ var far = new Coordinate(x, Height - y, 1);
+ var pm = Matrix4d.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60), Width / (float)Height, 0.1f, 50000);
+ var vm = Matrix4d.LookAt(
+ new Vector3d(Camera.Location.X, Camera.Location.Y, Camera.Location.Z),
+ new Vector3d(Camera.LookAt.X, Camera.LookAt.Y, Camera.LookAt.Z),
+ Vector3d.UnitZ);
+ var viewport = new[] { 0, 0, Width, Height };
+ var un = MathFunctions.Unproject(near, viewport, pm, vm);
+ var uf = MathFunctions.Unproject(far, viewport, pm, vm);
+ return (un == null || uf == null) ? null : new Line(un, uf);
+ }
+ }
+}