diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
index 2a62797602..a9e451eda0 100644
--- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
+++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
@@ -378,8 +378,10 @@
-
-
+
+
+
+
@@ -1159,6 +1161,7 @@
ToolBox.cs
+
@@ -1181,6 +1184,14 @@
{f51946ea-827f-4d82-b841-1f2f6d060312}
BizHawk.Emulation.DiscSystem
+
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}
+ BizHawk.Bizware.BizwareGL.OpenTK
+
+
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}
+ BizHawk.Bizware.BizwareGL
+
@@ -1262,6 +1273,7 @@
+
@@ -1401,7 +1413,7 @@
-
+
+
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/Enums.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/Enums.cs
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs
new file mode 100644
index 0000000000..6b853f1414
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs
@@ -0,0 +1,503 @@
+//regarding binding and vertex arrays:
+//http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification
+//http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state
+//http://www.opengl.org/wiki/Vertex_Specification
+
+//etc
+//glBindAttribLocation (programID, 0, "vertexPosition_modelspace");
+
+//for future reference: c# tesselators
+//http://www.opentk.com/node/437 (AGG#, codes on Tao forums)
+
+using System;
+using System.Threading;
+using System.IO;
+using System.Collections.Generic;
+using sd = System.Drawing;
+using sdi = System.Drawing.Imaging;
+using swf=System.Windows.Forms;
+
+using BizHawk.Bizware.BizwareGL;
+
+using OpenTK;
+using OpenTK.Graphics;
+using OpenTK.Graphics.OpenGL;
+
+namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
+{
+ ///
+ /// OpenTK implementation of the BizwareGL.IGL interface.
+ /// TODO - can we have more than one of these? could be dangerous. such dangerous things to be possibly reconsidered are marked with HAMNUTS
+ /// TODO - if we have any way of making contexts, we also need a way of freeing it, and then we can cleanup our dictionaries
+ ///
+ public class IGL_TK : IGL
+ {
+ static IGL_TK()
+ {
+ //make sure OpenTK initializes without getting wrecked on the SDL check and throwing an exception to annoy our MDA's
+ var toolkitOptions = global::OpenTK.ToolkitOptions.Default;
+ toolkitOptions.Backend = PlatformBackend.PreferNative;
+ global::OpenTK.Toolkit.Init(toolkitOptions);
+ //NOTE: this throws EGL exceptions anyway. I'm going to ignore it and whine about it later
+ }
+
+ public IGL_TK()
+ {
+ OffscreenNativeWindow = new NativeWindow();
+ OffscreenNativeWindow.ClientSize = new sd.Size(8, 8);
+ this.GraphicsContext = new GraphicsContext(GraphicsMode.Default, OffscreenNativeWindow.WindowInfo, 2, 0, GraphicsContextFlags.Default);
+ MakeDefaultCurrent();
+ this.GraphicsContext.LoadAll(); //this is important for reasons unknown
+ CreateRenderStates();
+ }
+
+ void IGL.Clear(ClearBufferMask mask)
+ {
+ GL.Clear((global::OpenTK.Graphics.OpenGL.ClearBufferMask)mask);
+ }
+ void IGL.ClearColor(sd.Color color)
+ {
+ GL.ClearColor(color);
+ }
+
+ class GLControlWrapper : GraphicsControl
+ {
+ //Note: In order to work around bugs in OpenTK which sometimes do things to a context without making that context active first...
+ //we are going to push and pop the context before doing stuff
+
+ public GLControlWrapper(IGL_TK owner)
+ {
+ Owner = owner;
+ }
+
+ IGL_TK Owner;
+
+ public override swf.Control Control { get { return MyControl; } }
+
+ public override void SetVsync(bool state)
+ {
+ //IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
+ MyControl.MakeCurrent();
+ MyControl.VSync = state;
+ //Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
+ }
+
+ public override void Begin()
+ {
+ Owner.MakeContextCurrent(MyControl.Context, MyControl.WindowInfo);
+ }
+
+ public override void End()
+ {
+ //this slows things down too much
+ //Owner.MakeDefaultCurrent();
+ }
+
+ public override void SwapBuffers()
+ {
+ //IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
+ MyControl.MakeCurrent();
+ MyControl.SwapBuffers();
+ //Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
+ }
+
+ public override void Dispose()
+ {
+ //TODO - what happens if this context was current?
+ MyControl.Dispose();
+ MyControl = null;
+ }
+
+ public GLControl MyControl;
+ }
+
+ GraphicsControl IGL.CreateGraphicsControl()
+ {
+ var glc = new GLControl(GraphicsMode.Default, 2, 0, GraphicsContextFlags.Default);
+ glc.CreateControl();
+
+ //now the control's context will be current. annoying! fix it.
+ MakeDefaultCurrent();
+
+ GLControlWrapper wrapper = new GLControlWrapper(this);
+ wrapper.MyControl = glc;
+ return wrapper;
+ }
+
+ IntPtr IGL.GenTexture() { return new IntPtr(GL.GenTexture()); }
+ void IGL.FreeTexture(IntPtr texHandle) { GL.DeleteTexture(texHandle.ToInt32()); }
+ IntPtr IGL.GetEmptyHandle() { return new IntPtr(0); }
+ IntPtr IGL.GetEmptyUniformHandle() { return new IntPtr(-1); }
+
+ Shader IGL.CreateFragmentShader(string source)
+ {
+ int sid = GL.CreateShader(ShaderType.FragmentShader);
+ CompileShaderSimple(sid,source);
+ return new Shader(this,new IntPtr(sid));
+ }
+ Shader IGL.CreateVertexShader(string source)
+ {
+ int sid = GL.CreateShader(ShaderType.VertexShader);
+ CompileShaderSimple(sid, source);
+ return new Shader(this, new IntPtr(sid));
+ }
+
+ void IGL.FreeShader(IntPtr shader) { GL.DeleteShader(shader.ToInt32()); }
+
+ class MyBlendState : IBlendState
+ {
+ public bool enabled;
+ public global::OpenTK.Graphics.OpenGL.BlendingFactorSrc colorSource;
+ public global::OpenTK.Graphics.OpenGL.BlendEquationMode colorEquation;
+ public global::OpenTK.Graphics.OpenGL.BlendingFactorDest colorDest;
+ public global::OpenTK.Graphics.OpenGL.BlendingFactorSrc alphaSource;
+ public global::OpenTK.Graphics.OpenGL.BlendEquationMode alphaEquation;
+ public global::OpenTK.Graphics.OpenGL.BlendingFactorDest alphaDest;
+ public MyBlendState(bool enabled, BlendingFactor colorSource, BlendEquationMode colorEquation, BlendingFactor colorDest,
+ BlendingFactor alphaSource, BlendEquationMode alphaEquation, BlendingFactor alphaDest)
+ {
+ this.enabled = enabled;
+ this.colorSource = (global::OpenTK.Graphics.OpenGL.BlendingFactorSrc)colorSource;
+ this.colorEquation = (global::OpenTK.Graphics.OpenGL.BlendEquationMode)colorEquation;
+ this.colorDest = (global::OpenTK.Graphics.OpenGL.BlendingFactorDest)colorDest;
+ this.alphaSource = (global::OpenTK.Graphics.OpenGL.BlendingFactorSrc)alphaSource;
+ this.alphaEquation = (global::OpenTK.Graphics.OpenGL.BlendEquationMode)alphaEquation;
+ this.alphaDest = (global::OpenTK.Graphics.OpenGL.BlendingFactorDest)alphaDest;
+ }
+ }
+ IBlendState IGL.CreateBlendState(BlendingFactor colorSource, BlendEquationMode colorEquation, BlendingFactor colorDest,
+ BlendingFactor alphaSource, BlendEquationMode alphaEquation, BlendingFactor alphaDest)
+ {
+ return new MyBlendState(true, colorSource, colorEquation, colorDest, alphaSource, alphaEquation, alphaDest);
+ }
+
+ void IGL.SetBlendState(IBlendState rsBlend)
+ {
+ var mybs = rsBlend as MyBlendState;
+ if (mybs.enabled)
+ {
+ GL.Enable(EnableCap.Blend);
+ GL.BlendEquationSeparate(mybs.colorEquation, mybs.alphaEquation);
+ GL.BlendFuncSeparate(mybs.colorSource, mybs.colorDest, mybs.alphaSource, mybs.alphaDest);
+ }
+ else GL.Disable(EnableCap.Blend);
+ }
+
+ IBlendState IGL.BlendNone { get { return _rsBlendNone; } }
+ IBlendState IGL.BlendNormal { get { return _rsBlendNormal; } }
+
+ Pipeline IGL.CreatePipeline(Shader vertexShader, Shader fragmentShader)
+ {
+ ErrorCode errcode;
+ int pid = GL.CreateProgram();
+ GL.AttachShader(pid, vertexShader.Id.ToInt32());
+ errcode = GL.GetError();
+ GL.AttachShader(pid, fragmentShader.Id.ToInt32());
+ errcode = GL.GetError();
+ GL.LinkProgram(pid);
+ errcode = GL.GetError();
+ int n;
+ GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out n);
+
+ string result = GL.GetProgramInfoLog(pid);
+ if (result != "")
+ throw new InvalidOperationException("Error creating pipeline (program link step):\r\n\r\n" + result);
+
+ GL.ValidateProgram(pid);
+ errcode = GL.GetError();
+
+ result = GL.GetProgramInfoLog(pid);
+ if (result != "")
+ throw new InvalidOperationException("Error creating pipeline (program validate step):\r\n\r\n" + result);
+
+ //get all the uniforms
+ List uniforms = new List();
+ int nUniforms;
+ int nSamplers = 0;
+ GL.GetProgram(pid,GetProgramParameterName.ActiveUniforms,out nUniforms);
+ for (int i = 0; i < nUniforms; i++)
+ {
+ int size, length;
+ ActiveUniformType type;
+ var sbName = new System.Text.StringBuilder();
+ GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, sbName);
+ string name = sbName.ToString();
+ int loc = GL.GetUniformLocation(pid, name);
+ var ui = new UniformInfo();
+ ui.Name = name;
+ ui.Handle = new IntPtr(loc);
+
+ //automatically assign sampler uniforms to texture units (and bind them)
+ bool isSampler = (type == ActiveUniformType.Sampler2D);
+ if (isSampler)
+ {
+ ui.SamplerIndex = nSamplers;
+ GL.Uniform1(loc, nSamplers);
+ nSamplers++;
+ }
+
+ uniforms.Add(ui);
+ }
+
+
+ return new Pipeline(this, new IntPtr(pid), uniforms);
+ }
+
+ VertexLayout IGL.CreateVertexLayout() { return new VertexLayout(this,new IntPtr(0)); }
+
+ void IGL.BindTexture2d(Texture2d tex)
+ {
+ GL.BindTexture(TextureTarget.Texture2D, tex.Id.ToInt32());
+ }
+
+ unsafe void IGL.BindVertexLayout(VertexLayout layout)
+ {
+ StatePendingVertexLayouts[CurrentContext] = layout;
+ }
+
+ unsafe void IGL.BindArrayData(void* pData)
+ {
+ MyBindArrayData(StatePendingVertexLayouts[CurrentContext], pData);
+ }
+
+ void IGL.DrawArrays(PrimitiveType mode, int first, int count)
+ {
+ GL.DrawArrays((global::OpenTK.Graphics.OpenGL.PrimitiveType)mode, first, count);
+ }
+
+ void IGL.BindPipeline(Pipeline pipeline)
+ {
+ GL.UseProgram(pipeline.Id.ToInt32());
+ }
+
+ unsafe void IGL.SetPipelineUniformMatrix(PipelineUniform uniform, Matrix mat, bool transpose)
+ {
+ GL.UniformMatrix4(uniform.Id.ToInt32(), 1, transpose, (float*)&mat);
+ }
+
+ unsafe void IGL.SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix mat, bool transpose)
+ {
+ fixed(Matrix* pMat = &mat)
+ GL.UniformMatrix4(uniform.Id.ToInt32(), 1, transpose, (float*)pMat);
+ }
+
+ void IGL.SetPipelineUniform(PipelineUniform uniform, Vector4 value)
+ {
+ GL.Uniform4(uniform.Id.ToInt32(), value.X, value.Y, value.Z, value.W);
+ }
+
+ void IGL.SetPipelineUniformSampler(PipelineUniform uniform, IntPtr texHandle)
+ {
+ //set the sampler index into the uniform first
+ GL.Uniform1(uniform.Id.ToInt32(), uniform.SamplerIndex);
+ //now bind the texture
+ GL.ActiveTexture((TextureUnit)((int)TextureUnit.Texture0 + uniform.SamplerIndex));
+ GL.BindTexture(TextureTarget.Texture2D, texHandle.ToInt32());
+ }
+
+ void IGL.TexParameter2d(TextureParameterName pname, int param)
+ {
+ GL.TexParameter(TextureTarget.Texture2D, (global::OpenTK.Graphics.OpenGL.TextureParameterName)pname, param);
+ }
+
+ Texture2d IGL.LoadTexture(sd.Bitmap bitmap)
+ {
+ using (var bmp = new BitmapBuffer(bitmap, new BitmapLoadOptions()))
+ return (this as IGL).LoadTexture(bmp);
+ }
+
+ Texture2d IGL.LoadTexture(Stream stream)
+ {
+ using(var bmp = new BitmapBuffer(stream,new BitmapLoadOptions()))
+ return (this as IGL).LoadTexture(bmp);
+ }
+
+ Texture2d IGL.CreateTexture(int width, int height)
+ {
+ IntPtr id = (this as IGL).GenTexture();
+ return new Texture2d(this, id, width, height);
+ }
+
+ void IGL.LoadTextureData(Texture2d tex, BitmapBuffer bmp)
+ {
+ sdi.BitmapData bmp_data = bmp.LockBits();
+ try
+ {
+ GL.BindTexture(TextureTarget.Texture2D, tex.Id.ToInt32());
+ GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
+ }
+ finally
+ {
+ bmp.UnlockBits(bmp_data);
+ }
+ }
+
+ Texture2d IGL.LoadTexture(BitmapBuffer bmp)
+ {
+ Texture2d ret = null;
+ IntPtr id = (this as IGL).GenTexture();
+ try
+ {
+ ret = new Texture2d(this, id, bmp.Width, bmp.Height);
+ GL.BindTexture(TextureTarget.Texture2D, id.ToInt32());
+ //picking a color order that matches doesnt seem to help, any. maybe my driver is accelerating it, or maybe it isnt a big deal. but its something to study on another day
+ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
+ (this as IGL).LoadTextureData(ret, bmp);
+ }
+ catch
+ {
+ (this as IGL).FreeTexture(id);
+ throw;
+ }
+
+ //set default filtering.. its safest to do this always
+ ret.SetFilterNearest();
+
+ return ret;
+ }
+
+ Texture2d IGL.LoadTexture(string path)
+ {
+ using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ return (this as IGL).LoadTexture(fs);
+ }
+
+ Matrix IGL.CreateGuiProjectionMatrix(int w, int h)
+ {
+ Matrix ret = Matrix.Identity;
+ ret.M11 = 2.0f / (float)w;
+ ret.M22 = 2.0f / (float)h;
+ return ret;
+ }
+
+ Matrix IGL.CreateGuiViewMatrix(int w, int h)
+ {
+ Matrix ret = Matrix.Identity;
+ ret.M22 = -1.0f;
+ ret.M41 = -w * 0.5f; // -0.5f;
+ ret.M42 = h * 0.5f; // +0.5f;
+ return ret;
+ }
+
+ void IGL.SetViewport(int x, int y, int width, int height)
+ {
+ ErrorCode errcode;
+ GL.Viewport(x, y, width, height);
+ errcode = GL.GetError();
+ }
+
+ void IGL.SetViewport(swf.Control control)
+ {
+ ErrorCode errcode;
+ var r = control.ClientRectangle;
+ errcode = GL.GetError();
+ GL.Viewport(r.Left, r.Top, r.Width, r.Height);
+ }
+
+ //------------------
+
+ INativeWindow OffscreenNativeWindow;
+ IGraphicsContext GraphicsContext;
+
+ //---------------
+ //my utility methods
+
+ global::OpenTK.Graphics.IGraphicsContext CurrentContext { get { return global::OpenTK.Graphics.GraphicsContext.CurrentContext; } }
+
+ GLControl CastControl(swf.Control swfControl)
+ {
+ GLControl glc = swfControl as GLControl;
+ if (glc == null)
+ throw new ArgumentException("Argument isn't a control created by the IGL interface", "glControl");
+ return glc;
+ }
+
+ void CompileShaderSimple(int sid, string source)
+ {
+ GL.ShaderSource(sid, source);
+ ErrorCode errcode = GL.GetError();
+ GL.CompileShader(sid);
+ errcode = GL.GetError();
+ int n;
+ GL.GetShader(sid, ShaderParameter.CompileStatus, out n);
+ string result = GL.GetShaderInfoLog(sid);
+ if (result != "")
+ throw new InvalidOperationException("Error compiling shader:\r\n\r\n" + result);
+
+ //HAX???
+ GL.Enable(EnableCap.Texture2D);
+ //GL.PolygonMode(MaterialFace.Back, PolygonMode.Line); //??
+ //GL.PolygonMode(MaterialFace.Front, PolygonMode.Line); //??
+ }
+
+ Dictionary StateCurrentVertexLayouts = new Dictionary();
+ Dictionary StatePendingVertexLayouts = new Dictionary();
+ WorkingDictionary> VertexAttribEnables = new WorkingDictionary>();
+ void UnbindVertexAttributes()
+ {
+ //HAMNUTS:
+ //its not clear how many bindings we'll have to disable before we can enable the ones we need..
+ //so lets just disable the ones we remember we have bound
+ var currBindings = VertexAttribEnables[CurrentContext];
+ foreach (var index in currBindings)
+ GL.DisableVertexAttribArray(index);
+ currBindings.Clear();
+ }
+
+ unsafe void MyBindArrayData(VertexLayout layout, void* pData)
+ {
+ ErrorCode errcode;
+
+ UnbindVertexAttributes();
+
+ //HAMNUTS (continued)
+ var currBindings = VertexAttribEnables[CurrentContext];
+ StateCurrentVertexLayouts[CurrentContext] = StatePendingVertexLayouts[CurrentContext];
+
+ foreach (var kvp in layout.Items)
+ {
+ GL.VertexAttribPointer(kvp.Key, kvp.Value.Components, (VertexAttribPointerType)kvp.Value.AttribType, kvp.Value.Normalized, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
+ errcode = GL.GetError();
+ GL.EnableVertexAttribArray(kvp.Key);
+ errcode = GL.GetError();
+ currBindings.Add(kvp.Key);
+ }
+ }
+
+ void MakeDefaultCurrent()
+ {
+ MakeContextCurrent(this.GraphicsContext, OffscreenNativeWindow.WindowInfo);
+ }
+
+ void MakeContextCurrent(IGraphicsContext context, global::OpenTK.Platform.IWindowInfo windowInfo)
+ {
+ //TODO - if we're churning through contexts quickly, this will sort of be a memory leak, since they'll be memoized forever in here
+ //maybe make it a weakptr or something
+
+ //dont do anything if we're already current
+ IGraphicsContext currentForThread = null;
+ if (ThreadsForContexts.TryGetValue(Thread.CurrentThread, out currentForThread))
+ if (currentForThread == context)
+ return;
+
+ NativeWindowsForContexts[context] = windowInfo;
+ context.MakeCurrent(windowInfo);
+ ThreadsForContexts[Thread.CurrentThread] = context;
+ }
+
+ Dictionary ThreadsForContexts = new Dictionary();
+ Dictionary NativeWindowsForContexts = new Dictionary();
+
+ void CreateRenderStates()
+ {
+ _rsBlendNone = new MyBlendState(false, BlendingFactor.One, BlendEquationMode.FuncAdd, BlendingFactor.Zero, BlendingFactor.One, BlendEquationMode.FuncAdd, BlendingFactor.Zero);
+ _rsBlendNormal = new MyBlendState(true,
+ BlendingFactor.SrcAlpha, BlendEquationMode.FuncAdd, BlendingFactor.OneMinusSrcAlpha,
+ BlendingFactor.One, BlendEquationMode.FuncAdd, BlendingFactor.Zero);
+ }
+
+ MyBlendState _rsBlendNone, _rsBlendNormal;
+
+ } //class IGL_TK
+
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Art.cs b/Bizware/BizHawk.Bizware.BizwareGL/Art.cs
new file mode 100644
index 0000000000..5992872e23
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Art.cs
@@ -0,0 +1,24 @@
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// Represents a piece of 2d art. Not as versatile as a texture.. could have come from an atlas. So it comes with a boatload of constraints
+ ///
+ public class Art
+ {
+ internal Art(ArtManager owner)
+ {
+ Owner = owner;
+ }
+
+ public ArtManager Owner { get; private set; }
+ public Texture2d BaseTexture { get; internal set; }
+
+ public float Width, Height;
+ public float u0, v0, u1, v1;
+
+ internal void Initialize()
+ {
+ //TBD
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/ArtManager.cs b/Bizware/BizHawk.Bizware.BizwareGL/ArtManager.cs
new file mode 100644
index 0000000000..0f5e32f5be
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/ArtManager.cs
@@ -0,0 +1,165 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// Load resources through here, and they can be grouped together, for purposes of batching and whatnot.
+ /// You can't use any of the returned Art resources until calling Close on the ArtManager
+ ///
+ public class ArtManager : IDisposable
+ {
+ public ArtManager(IGL owner)
+ {
+ Owner = owner;
+ Open();
+ }
+
+ public void Dispose()
+ {
+ //todo
+ }
+
+ ///
+ /// Reopens this instance for further resource loading. Fails if it has been closed forever.
+ ///
+ public void Open()
+ {
+ AssertIsOpen(false);
+ if (IsClosedForever) throw new InvalidOperationException("ArtManager instance has been closed forever!");
+ IsOpened = true;
+ }
+
+ ///
+ /// Loads the given stream as an Art instance
+ ///
+ public Art LoadArt(Stream stream)
+ {
+ return LoadArtInternal(new BitmapBuffer(stream, new BitmapLoadOptions()));
+ }
+
+ ///
+ /// Loads the given path as an Art instance.
+ ///
+ public Art LoadArt(string path)
+ {
+ using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ return LoadArtInternal(new BitmapBuffer(path, new BitmapLoadOptions()));
+ }
+
+ Art LoadArtInternal(BitmapBuffer tex)
+ {
+ AssertIsOpen(true);
+
+ Art a = new Art(this);
+ ArtLooseTextureAssociation[a] = tex;
+ ManagedArts.Add(a);
+
+ return a;
+ }
+
+ ///
+ /// Closes this instance for for further resource loading. Will result in a texture atlasing operation.
+ /// If the close operation is forever, then internal backup copies of resources will be freed, but it can never be reopened.
+ /// This function may take some time to run, as it is
+ ///
+ public unsafe void Close(bool forever = true)
+ {
+ AssertIsOpen(true);
+ IsOpened = false;
+ IsClosedForever = forever;
+
+ //first, cleanup old stuff
+ foreach (var tex in ManagedTextures)
+ tex.Dispose();
+ ManagedTextures.Clear();
+
+ //prepare input for atlas process and perform atlas
+ //add 2 extra pixels for padding on all sides
+ List atlasItems = new List();
+ foreach (var kvp in ArtLooseTextureAssociation)
+ atlasItems.Add(new TexAtlas.RectItem(kvp.Value.Width+2, kvp.Value.Height+2, kvp));
+ var results = TexAtlas.PackAtlas(atlasItems);
+
+ //this isnt supported yet:
+ if (results.Atlases.Count > 1)
+ throw new InvalidOperationException("Art files too big for atlas");
+
+ //prepare the output buffer
+ BitmapBuffer bmpResult = new BitmapBuffer(results.Atlases[0].Size);
+
+ //for each item, copy it into the output buffer and set the tex parameters on them
+ for (int i = 0; i < atlasItems.Count; i++)
+ {
+ var item = results.Atlases[0].Items[i];
+ var artAndBitmap = (KeyValuePair)item.Item;
+ var art = artAndBitmap.Key;
+ var bitmap = artAndBitmap.Value;
+
+ int w = bitmap.Width;
+ int h = bitmap.Height;
+ int dx = item.X + 1;
+ int dy = item.Y + 1;
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ int pixel = bitmap.GetPixel(x, y);
+ bmpResult.SetPixel(x+dx,y+dy,pixel);
+ }
+
+ var myDestBitmap = bmpResult;
+ float myDestWidth = (float)myDestBitmap.Width;
+ float myDestHeight = (float)myDestBitmap.Height;
+
+ art.u0 = dx / myDestWidth;
+ art.v0 = dy / myDestHeight;
+ art.u1 = (dx + w) / myDestWidth;
+ art.v1 = (dy + h) / myDestHeight;
+ art.Width = w;
+ art.Height = h;
+ }
+
+ //if we're closed forever, then forget all the original bitmaps
+ if (forever)
+ {
+ foreach (var kvp in ArtLooseTextureAssociation)
+ kvp.Value.Dispose();
+ ArtLooseTextureAssociation.Clear();
+ }
+
+ //create a physical texture
+ var texture = Owner.LoadTexture(bmpResult);
+ ManagedTextures.Add(texture);
+
+ //oops, we couldn't do this earlier.
+ foreach (var art in ManagedArts)
+ art.BaseTexture = texture;
+ }
+
+ ///
+ /// Throws an exception if the instance is not open
+ ///
+ private void AssertIsOpen(bool state) { if (IsOpened != state) throw new InvalidOperationException("ArtManager instance is not open!"); }
+
+ public IGL Owner { get; private set; }
+
+ public bool IsOpened { get; private set; }
+ public bool IsClosedForever { get; private set; }
+
+ ///
+ /// This is used to remember the original bitmap sources for art files. Once the ArtManager is closed forever, this will be purged
+ ///
+ Dictionary ArtLooseTextureAssociation = new Dictionary();
+
+ ///
+ /// Physical texture resources, which exist after this ArtManager has been closed
+ ///
+ List ManagedTextures = new List();
+
+ ///
+ /// All the Arts managed by this instance
+ ///
+ List ManagedArts = new List();
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs b/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs
new file mode 100644
index 0000000000..6588ea8f56
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs
@@ -0,0 +1,444 @@
+//TODO - introduce Trim for ArtManager
+//TODO - add a small buffer reuse manager.. small images can be stored in larger buffers which we happen to have held. use a timer to wait to free it until some time has passed
+
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using System.Runtime.InteropServices;
+using sd = System.Drawing;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Drawing;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// a software-based bitmap, way easier (and faster) to use than .net's built-in bitmap.
+ /// Only supports a fixed rgba format
+ /// Even though this is IDisposable, you dont have to worry about disposing it normally (that's only for the Bitmap-mimicking)
+ /// But you know you can't resist.
+ ///
+ public unsafe class BitmapBuffer : IDisposable
+ {
+ public int Width, Height;
+ public int[] Pixels;
+
+ sd.Bitmap WrappedBitmap;
+ GCHandle CurrLockHandle;
+ BitmapData CurrLock;
+ public BitmapData LockBits() //TODO - add read/write semantic, for wraps
+ {
+ if(CurrLock != null)
+ throw new InvalidOperationException("BitmapBuffer can only be locked once!");
+
+ if (WrappedBitmap != null)
+ {
+ CurrLock = WrappedBitmap.LockBits(new sd.Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ return CurrLock;
+ }
+
+ CurrLockHandle = GCHandle.Alloc(Pixels, GCHandleType.Pinned);
+ CurrLock = new BitmapData();
+ CurrLock.Height = Height;
+ CurrLock.Width = Width;
+ CurrLock.Stride = Width * 4;
+ CurrLock.Scan0 = CurrLockHandle.AddrOfPinnedObject();
+
+ return CurrLock;
+ }
+
+ public void UnlockBits(BitmapData bmpd)
+ {
+ Debug.Assert(CurrLock == bmpd);
+
+ if (WrappedBitmap != null)
+ {
+ WrappedBitmap.UnlockBits(CurrLock);
+ CurrLock = null;
+ return;
+ }
+
+ CurrLockHandle.Free();
+ CurrLock = null;
+ }
+
+ public void Dispose()
+ {
+ if (CurrLock == null) return;
+ UnlockBits(CurrLock);
+ }
+
+ public int GetPixel(int x, int y) { return Pixels[Width * y + x]; }
+ public void SetPixel(int x, int y, int value) { Pixels[Width * y + x] = value; }
+ public Color GetPixelAsColor(int x, int y)
+ {
+ int c = Pixels[Width * y + x];
+ return Color.FromArgb(c);
+ }
+
+ ///
+ /// transforms tcol to 0,0,0,0
+ ///
+ public void Alphafy(int tcol)
+ {
+ for (int y = 0, idx = 0; y < Height; y++)
+ for (int x = 0; x < Width; x++, idx++)
+ {
+ if (Pixels[idx] == tcol)
+ Pixels[idx] = 0;
+ }
+ }
+
+ ///
+ /// copies this bitmap and trims out transparent pixels, returning the offset to the topleft pixel
+ ///
+ public BitmapBuffer Trim()
+ {
+ int x, y;
+ return Trim(out x, out y);
+ }
+
+ ///
+ /// copies this bitmap and trims out transparent pixels, returning the offset to the topleft pixel
+ ///
+ public BitmapBuffer Trim(out int xofs, out int yofs)
+ {
+ int minx = int.MaxValue;
+ int maxx = int.MinValue;
+ int miny = int.MaxValue;
+ int maxy = int.MinValue;
+ for (int y = 0; y < Height; y++)
+ for (int x = 0; x < Width; x++)
+ {
+ int pixel = GetPixel(x, y);
+ int a = (pixel >> 24) & 0xFF;
+ if (a != 0)
+ {
+ minx = Math.Min(minx, x);
+ maxx = Math.Max(maxx, x);
+ miny = Math.Min(miny, y);
+ maxy = Math.Max(maxy, y);
+ }
+ }
+
+ if (minx == int.MaxValue || maxx == int.MinValue || miny == int.MaxValue || minx == int.MinValue)
+ {
+ xofs = yofs = 0;
+ return new BitmapBuffer(0, 0);
+ }
+
+ int w = maxx - minx + 1;
+ int h = maxy - miny + 1;
+ BitmapBuffer bbRet = new BitmapBuffer(w, h);
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ bbRet.SetPixel(x, y, GetPixel(x + minx, y + miny));
+ }
+
+ xofs = minx;
+ yofs = miny;
+ return bbRet;
+ }
+
+ ///
+ /// increases dimensions of this bitmap to the next higher power of 2
+ ///
+ public void Pad()
+ {
+ int widthRound = nexthigher(Width);
+ int heightRound = nexthigher(Height);
+ if (widthRound == Width && heightRound == Height) return;
+ int[] NewPixels = new int[heightRound * widthRound];
+
+ for (int y = 0, sptr = 0, dptr = 0; y < Height; y++)
+ {
+ for (int x = 0; x < Width; x++)
+ NewPixels[dptr++] = Pixels[sptr++];
+ dptr += (widthRound - Width);
+ }
+
+ Pixels = NewPixels;
+ Width = widthRound;
+ Height = heightRound;
+ }
+
+ ///
+ /// Creates a BitmapBuffer image from the specified filename
+ ///
+ public BitmapBuffer(string fname, BitmapLoadOptions options)
+ {
+ using (var fs = new FileStream(fname, FileMode.Open, FileAccess.Read, FileShare.Read))
+ LoadInternal(fs, null, options);
+ }
+
+ ///
+ /// loads an image from the specified stream
+ ///
+ public BitmapBuffer(Stream stream, BitmapLoadOptions options)
+ {
+ LoadInternal(stream, null, options);
+ }
+
+ ///
+ /// Initializes the BitmapBuffer from a System.Drawing.Bitmap
+ ///
+ public BitmapBuffer(sd.Bitmap bitmap, BitmapLoadOptions options)
+ {
+ if (options.AllowWrap && bitmap.PixelFormat == PixelFormat.Format32bppArgb)
+ {
+ Width = bitmap.Width;
+ Height = bitmap.Height;
+ WrappedBitmap = bitmap;
+ }
+ else LoadInternal(null, bitmap, options);
+ }
+
+ void LoadInternal(Stream stream, sd.Bitmap bitmap, BitmapLoadOptions options)
+ {
+ bool cleanup = options.CleanupAlpha0;
+ bool needsPad = true;
+
+ var colorKey24bpp = options.ColorKey24bpp;
+ using (Bitmap loadedBmp = bitmap == null ? new Bitmap(stream) : null) //sneaky!
+ {
+ Bitmap bmp = loadedBmp;
+ if (bmp == null)
+ bmp = bitmap;
+
+ //if we have a 24bpp image and a colorkey callback, the callback can choose a colorkey color and we'll use that
+ if (bmp.PixelFormat == PixelFormat.Format24bppRgb && colorKey24bpp != null)
+ {
+ int colorKey = colorKey24bpp(bmp);
+ int w = bmp.Width;
+ int h = bmp.Height;
+ InitSize(w, h);
+ BitmapData bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ Color[] palette = bmp.Palette.Entries;
+ int* ptr = (int*)bmpdata.Scan0.ToPointer();
+ int stride = bmpdata.Stride;
+ fixed (int* pPtr = &Pixels[0])
+ {
+ for (int idx = 0, y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ int srcPixel = ptr[idx];
+ if (srcPixel == colorKey)
+ srcPixel = 0;
+ pPtr[idx++] = srcPixel;
+ }
+ }
+
+ bmp.UnlockBits(bmpdata);
+ }
+ if (bmp.PixelFormat == PixelFormat.Format8bppIndexed || bmp.PixelFormat == PixelFormat.Format4bppIndexed)
+ {
+ int w = bmp.Width;
+ int h = bmp.Height;
+ InitSize(w, h);
+ BitmapData bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
+ Color[] palette = bmp.Palette.Entries;
+ byte* ptr = (byte*)bmpdata.Scan0.ToPointer();
+ int stride = bmpdata.Stride;
+ fixed (int* pPtr = &Pixels[0])
+ {
+ for (int idx = 0, y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ int srcPixel = ptr[idx];
+ if (srcPixel != 0)
+ {
+ int color = palette[srcPixel].ToArgb();
+
+ //make transparent pixels turn into black to avoid filtering issues and other annoying issues with stray junk in transparent pixels.
+ //(yes, we can have palette entries with transparency in them (PNGs support this, annoyingly))
+ if (cleanup)
+ {
+ if ((color & 0xFF000000) == 0) color = 0;
+ pPtr[idx] = color;
+ }
+ }
+ idx++;
+ }
+ }
+
+ bmp.UnlockBits(bmpdata);
+ }
+ else
+ {
+ //dump the supplied bitmap into our pixels array
+ int width = bmp.Width;
+ int height = bmp.Height;
+ InitSize(width, height);
+ BitmapData bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ int* ptr = (int*)bmpdata.Scan0.ToInt32();
+ int stride = bmpdata.Stride / 4;
+ LoadFrom(width, stride, height, (byte*)ptr, options);
+ bmp.UnlockBits(bmpdata);
+ needsPad = false;
+ }
+ }
+
+ if (needsPad && options.Pad)
+ Pad();
+ }
+
+
+ ///
+ /// Loads the BitmapBuffer from a source buffer, which is expected to be the right pixel format
+ ///
+ public unsafe void LoadFrom(int width, int stride, int height, byte* data, BitmapLoadOptions options)
+ {
+ bool cleanup = options.CleanupAlpha0;
+ Width = width;
+ Height = height;
+ Pixels = new int[width * height];
+ fixed (int* pPtr = &Pixels[0])
+ {
+ for (int idx = 0, y = 0; y < Height; y++)
+ for (int x = 0; x < Width; x++)
+ {
+ int src = y * stride + x;
+ int srcVal = ((int*)data)[src];
+
+ //make transparent pixels turn into black to avoid filtering issues and other annoying issues with stray junk in transparent pixels
+ if (cleanup)
+ {
+ if ((srcVal & 0xFF000000) == 0) srcVal = 0;
+ pPtr[idx++] = srcVal;
+ }
+ }
+ }
+
+ if (options.Pad)
+ Pad();
+ }
+
+ ///
+ /// premultiplies a color
+ ///
+ public static int PremultiplyColor(int srcVal)
+ {
+ int b = (srcVal >> 0) & 0xFF;
+ int g = (srcVal >> 8) & 0xFF;
+ int r = (srcVal >> 16) & 0xFF;
+ int a = (srcVal >> 24) & 0xFF;
+ r = (r * a) >> 8;
+ g = (g * a) >> 8;
+ b = (b * a) >> 8;
+ srcVal = b | (g << 8) | (r << 16) | (a << 24);
+ return srcVal;
+ }
+
+ ///
+ /// initializes an empty BitmapBuffer, cleared to all 0
+ ///
+ public BitmapBuffer(int width, int height)
+ {
+ InitSize(width, height);
+ }
+
+ public BitmapBuffer() { }
+
+ ///
+ /// clears this instance to (0,0,0,0) -- without allocating a new array (to avoid GC churn)
+ ///
+ public unsafe void ClearWithoutAlloc()
+ {
+ //http://techmikael.blogspot.com/2009/12/filling-array-with-default-value.html
+ //this guy says its faster
+
+ int size = Width * Height;
+ byte fillValue = 0;
+ ulong fillValueLong = 0;
+
+ fixed (int* ptr = &Pixels[0])
+ {
+ ulong* dest = (ulong*)ptr;
+ int length = size;
+ while (length >= 8)
+ {
+ *dest = fillValueLong;
+ dest++;
+ length -= 8;
+ }
+ byte* bDest = (byte*)dest;
+ for (byte i = 0; i < length; i++)
+ {
+ *bDest = fillValue;
+ bDest++;
+ }
+ }
+ }
+
+ ///
+ /// just a temporary measure while refactoring emuhawk
+ ///
+ public void AcceptIntArray(int[] arr)
+ {
+ //should these be copied?
+ Pixels = arr;
+ }
+
+ ///
+ /// initializes an empty BitmapBuffer, cleared to all 0
+ ///
+ public BitmapBuffer(Size size)
+ {
+ InitSize(size.Width, size.Height);
+ }
+
+ void InitSize(int width, int height)
+ {
+ Pixels = new int[width * height];
+ Width = width;
+ Height = height;
+ }
+
+ ///
+ /// returns the next higher power of 2 than the provided value, for rounding up POW2 textures.
+ ///
+ int nexthigher(int k)
+ {
+ k--;
+ for (int i = 1; i < 32; i <<= 1)
+ k = k | k >> i;
+ int candidate = k + 1;
+ return candidate;
+ }
+
+
+ ///
+ /// Dumps this BitmapBuffer to a System.Drawing.Bitmap
+ ///
+ public unsafe Bitmap ToSysdrawingBitmap()
+ {
+ Bitmap bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
+ var bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+
+ int* ptr = (int*)bmpdata.Scan0.ToPointer();
+ int stride = bmpdata.Stride;
+ fixed (int* pPtr = &Pixels[0])
+ {
+ for (int idx = 0, y = 0; y < Height; y++)
+ for (int x = 0; x < Width; x++)
+ {
+ int srcPixel = pPtr[idx];
+ ptr[idx] = srcPixel;
+ idx++;
+ }
+ }
+
+ bmp.UnlockBits(bmpdata);
+ return bmp;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/BitmapLoadOptions.cs b/Bizware/BizHawk.Bizware.BizwareGL/BitmapLoadOptions.cs
new file mode 100644
index 0000000000..f0c2712ed8
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/BitmapLoadOptions.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Drawing;
+using System.Text;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class BitmapLoadOptions
+ {
+ ///
+ /// A callback to be issued when a 24bpp image is detected, which will allow you to return a colorkey
+ ///
+ public Func ColorKey24bpp;
+
+ ///
+ /// Specifies whether palette entry 0 (if there is a palette) shall represent transparent (Alpha=0)
+ ///
+ public bool TransparentPalette0 = true;
+
+ ///
+ /// Specifies whether (r,g,b,0) pixels shall be turned into (0,0,0,0).
+ /// This is useful for cleaning up junk which you might not know you had littering purely transparent areas, which can mess up a lot of stuff during rendering.
+ ///
+ public bool CleanupAlpha0 = true;
+
+ ///
+ /// Applies the Premultiply post-process (not supported yet; and anyway it could be done as it loads for a little speedup, in many cases)
+ ///
+ public bool Premultiply = false;
+
+ ///
+ /// Applies Pad() post-process
+ ///
+ public bool Pad = false;
+
+ ///
+ /// Allows the BitmapBuffer to wrap a System.Drawing.Bitmap, if one is provided for loading.
+ /// This System.Drawing.Bitmap must be 32bpp and these other options may be valid (since this approach is designed for quickly getting things into textures)
+ /// Ownership of the bitmap remains with the user.
+ ///
+ public bool AllowWrap = true;
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj b/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj
new file mode 100644
index 0000000000..cb2da100f7
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj
@@ -0,0 +1,104 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}
+ Library
+ Properties
+ BizHawk.Bizware.BizwareGL
+ BizHawk.Bizware.BizwareGL
+ v4.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+ x86
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/BitmapFont.cs b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/BitmapFont.cs
new file mode 100644
index 0000000000..1adde4cdec
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/BitmapFont.cs
@@ -0,0 +1,184 @@
+//public domain assumed from cyotek.com
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace Cyotek.Drawing.BitmapFont
+{
+ public class BitmapFont : IEnumerable
+ {
+ #region Public Member Declarations
+
+ public const int NoMaxWidth = -1;
+
+ #endregion Public Member Declarations
+
+ #region Public Constructors
+
+ public BitmapFont()
+ { }
+
+ #endregion Public Constructors
+
+ #region Public Methods
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach (KeyValuePair pair in this.Characters)
+ yield return pair.Value;
+ }
+
+ public int GetKerning(char previous, char current)
+ {
+ Kerning key;
+ int result;
+
+ key = new Kerning(previous, current, 0);
+ if (!this.Kernings.TryGetValue(key, out result))
+ result = 0;
+
+ return result;
+ }
+
+ public Size MeasureFont(string text)
+ {
+ return this.MeasureFont(text, BitmapFont.NoMaxWidth);
+ }
+
+ public Size MeasureFont(string text, double maxWidth)
+ {
+ char previousCharacter;
+ string normalizedText;
+ int currentLineWidth;
+ int currentLineHeight;
+ int blockWidth;
+ int blockHeight;
+ List lineHeights;
+
+ previousCharacter = ' ';
+ normalizedText = this.NormalizeLineBreaks(text);
+ currentLineWidth = 0;
+ currentLineHeight = this.LineHeight;
+ blockWidth = 0;
+ blockHeight = 0;
+ lineHeights = new List();
+
+ foreach (char character in normalizedText)
+ {
+ switch (character)
+ {
+ case '\n':
+ lineHeights.Add(currentLineHeight);
+ blockWidth = Math.Max(blockWidth, currentLineWidth);
+ currentLineWidth = 0;
+ currentLineHeight = this.LineHeight;
+ break;
+ default:
+ Character data;
+ int width;
+
+ data = this[character];
+ width = data.XAdvance + this.GetKerning(previousCharacter, character);
+
+ if (maxWidth != BitmapFont.NoMaxWidth && currentLineWidth + width >= maxWidth)
+ {
+ lineHeights.Add(currentLineHeight);
+ blockWidth = Math.Max(blockWidth, currentLineWidth);
+ currentLineWidth = 0;
+ currentLineHeight = this.LineHeight;
+ }
+
+ currentLineWidth += width;
+ currentLineHeight = Math.Max(currentLineHeight, data.Bounds.Height + data.Offset.Y);
+ previousCharacter = character;
+ break;
+ }
+ }
+
+ // finish off the current line if required
+ if (currentLineHeight != 0)
+ lineHeights.Add(currentLineHeight);
+
+ // reduce any lines other than the last back to the base
+ for (int i = 0; i < lineHeights.Count - 1; i++)
+ lineHeights[i] = this.LineHeight;
+
+ // calculate the final block height
+ foreach (int lineHeight in lineHeights)
+ blockHeight += lineHeight;
+
+ return new Size(Math.Max(currentLineWidth, blockWidth), blockHeight);
+ }
+
+ public string NormalizeLineBreaks(string s)
+ {
+ return s.Replace("\r\n", "\n").Replace("\r", "\n");
+ }
+
+ #endregion Public Methods
+
+ #region Public Properties
+
+ public int AlphaChannel { get; set; }
+
+ public int BaseHeight { get; set; }
+
+ public int BlueChannel { get; set; }
+
+ public bool Bold { get; set; }
+
+ public IDictionary Characters { get; set; }
+
+ public string Charset { get; set; }
+
+ public string FamilyName { get; set; }
+
+ public int FontSize { get; set; }
+
+ public int GreenChannel { get; set; }
+
+ public bool Italic { get; set; }
+
+ public IDictionary Kernings { get; set; }
+
+ public int LineHeight { get; set; }
+
+ public int OutlineSize { get; set; }
+
+ public bool Packed { get; set; }
+
+ public Padding Padding { get; set; }
+
+ public Page[] Pages { get; set; }
+
+ public int RedChannel { get; set; }
+
+ public bool Smoothed { get; set; }
+
+ public Point Spacing { get; set; }
+
+ public int StretchedHeight { get; set; }
+
+ public int SuperSampling { get; set; }
+
+ public Size TextureSize { get; set; }
+
+ public Character this[char character]
+ { get { return this.Characters[character]; } }
+
+ public bool Unicode { get; set; }
+
+ #endregion Public Properties
+
+ #region Private Methods
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ #endregion Private Methods
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/BitmapFontLoader.cs b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/BitmapFontLoader.cs
new file mode 100644
index 0000000000..28e33ce7b2
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/BitmapFontLoader.cs
@@ -0,0 +1,457 @@
+//public domain assumed from cyotek.com
+
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Xml;
+
+namespace Cyotek.Drawing.BitmapFont
+{
+ // Parsing class for bitmap fonts generated by AngelCode BMFont
+ // http://www.angelcode.com/products/bmfont/
+
+ public static class BitmapFontLoader
+ {
+ #region Public Class Methods
+
+ /////
+ ///// Loads a bitmap font from a file, attempting to auto detect the file type
+ /////
+ ///// Name of the file to load.
+ /////
+ //public static BitmapFont LoadFontFromFile(string fileName)
+ //{
+ // BitmapFont result;
+
+ // if (string.IsNullOrEmpty(fileName))
+ // throw new ArgumentNullException("fileName", "File name not specified");
+ // else if (!File.Exists(fileName))
+ // throw new FileNotFoundException(string.Format("Cannot find file '{0}'", fileName), fileName);
+
+ // using (FileStream file = File.OpenRead(fileName))
+ // {
+ // using (TextReader reader = new StreamReader(file))
+ // {
+ // string line;
+
+ // line = reader.ReadLine();
+
+ // if (line.StartsWith("info "))
+ // result = BitmapFontLoader.LoadFontFromTextFile(fileName);
+ // else if (line.StartsWith("
+ /// Loads a bitmap font from a text file.
+ ///
+ /// Name of the file to load.
+ ///
+ public static BitmapFont LoadFontFromTextFile(string fileName)
+ {
+ BitmapFont font;
+ IDictionary pageData;
+ IDictionary kerningDictionary;
+ IDictionary charDictionary;
+ string resourcePath;
+ string[] lines;
+
+ if (string.IsNullOrEmpty(fileName))
+ throw new ArgumentNullException("fileName", "File name not specified");
+ else if (!File.Exists(fileName))
+ throw new FileNotFoundException(string.Format("Cannot find file '{0}'", fileName), fileName);
+
+ pageData = new SortedDictionary();
+ kerningDictionary = new Dictionary();
+ charDictionary = new Dictionary();
+ font = new BitmapFont();
+
+ resourcePath = Path.GetDirectoryName(fileName);
+ lines = File.ReadAllLines(fileName);
+
+ foreach (string line in lines)
+ {
+ string[] parts;
+
+ parts = BitmapFontLoader.Split(line, ' ');
+
+ if (parts.Length != 0)
+ {
+ switch (parts[0])
+ {
+ case "info":
+ font.FamilyName = BitmapFontLoader.GetNamedString(parts, "face");
+ font.FontSize = BitmapFontLoader.GetNamedInt(parts, "size");
+ font.Bold = BitmapFontLoader.GetNamedBool(parts, "bold");
+ font.Italic = BitmapFontLoader.GetNamedBool(parts, "italic");
+ font.Charset = BitmapFontLoader.GetNamedString(parts, "charset");
+ font.Unicode = BitmapFontLoader.GetNamedBool(parts, "unicode");
+ font.StretchedHeight = BitmapFontLoader.GetNamedInt(parts, "stretchH");
+ font.Smoothed = BitmapFontLoader.GetNamedBool(parts, "smooth");
+ font.SuperSampling = BitmapFontLoader.GetNamedInt(parts, "aa");
+ font.Padding = BitmapFontLoader.ParsePadding(BitmapFontLoader.GetNamedString(parts, "padding"));
+ font.Spacing = BitmapFontLoader.ParsePoint(BitmapFontLoader.GetNamedString(parts, "spacing"));
+ font.OutlineSize = BitmapFontLoader.GetNamedInt(parts, "outline");
+ break;
+ case "common":
+ font.LineHeight = BitmapFontLoader.GetNamedInt(parts, "lineHeight");
+ font.BaseHeight = BitmapFontLoader.GetNamedInt(parts, "base");
+ font.TextureSize = new Size
+ (
+ BitmapFontLoader.GetNamedInt(parts, "scaleW"),
+ BitmapFontLoader.GetNamedInt(parts, "scaleH")
+ );
+ font.Packed = BitmapFontLoader.GetNamedBool(parts, "packed");
+ font.AlphaChannel = BitmapFontLoader.GetNamedInt(parts, "alphaChnl");
+ font.RedChannel = BitmapFontLoader.GetNamedInt(parts, "redChnl");
+ font.GreenChannel = BitmapFontLoader.GetNamedInt(parts, "greenChnl");
+ font.BlueChannel = BitmapFontLoader.GetNamedInt(parts, "blueChnl");
+ break;
+ case "page":
+ int id;
+ string name;
+ string textureId;
+
+ id = BitmapFontLoader.GetNamedInt(parts, "id");
+ name = BitmapFontLoader.GetNamedString(parts, "file");
+ textureId = Path.GetFileNameWithoutExtension(name);
+
+ pageData.Add(id, new Page(id, Path.Combine(resourcePath, name)));
+ break;
+ case "char":
+ Character charData;
+
+ charData = new Character
+ {
+ Char = (char)BitmapFontLoader.GetNamedInt(parts, "id"),
+ Bounds = new Rectangle
+ (
+ BitmapFontLoader.GetNamedInt(parts, "x"),
+ BitmapFontLoader.GetNamedInt(parts, "y"),
+ BitmapFontLoader.GetNamedInt(parts, "width"),
+ BitmapFontLoader.GetNamedInt(parts, "height")
+ ),
+ Offset = new Point
+ (
+ BitmapFontLoader.GetNamedInt(parts, "xoffset"),
+ BitmapFontLoader.GetNamedInt(parts, "yoffset")
+ ),
+ XAdvance = BitmapFontLoader.GetNamedInt(parts, "xadvance"),
+ TexturePage = BitmapFontLoader.GetNamedInt(parts, "page"),
+ Channel = BitmapFontLoader.GetNamedInt(parts, "chnl")
+ };
+ charDictionary.Add(charData.Char, charData);
+ break;
+ case "kerning":
+ Kerning key;
+
+ key = new Kerning((char)BitmapFontLoader.GetNamedInt(parts, "first"), (char)BitmapFontLoader.GetNamedInt(parts, "second"), GetNamedInt(parts, "amount"));
+
+ if (!kerningDictionary.ContainsKey(key))
+ kerningDictionary.Add(key, key.Amount);
+ break;
+ }
+ }
+ }
+
+ font.Pages = BitmapFontLoader.ToArray(pageData.Values);
+ font.Characters = charDictionary;
+ font.Kernings = kerningDictionary;
+
+ return font;
+ }
+
+ ///
+ /// Loads a bitmap font from an XML file.
+ ///
+ /// Name of the file to load.
+ ///
+ public static BitmapFont LoadFontFromXmlFile(Stream stream)
+ {
+ XmlDocument document;
+ BitmapFont font;
+ IDictionary pageData;
+ IDictionary kerningDictionary;
+ IDictionary charDictionary;
+ XmlNode root;
+ XmlNode properties;
+
+ document = new XmlDocument();
+ pageData = new SortedDictionary();
+ kerningDictionary = new Dictionary();
+ charDictionary = new Dictionary();
+ font = new BitmapFont();
+
+ document.Load(stream);
+ root = document.DocumentElement;
+
+ // load the basic attributes
+ properties = root.SelectSingleNode("info");
+ font.FamilyName = properties.Attributes["face"].Value;
+ font.FontSize = Convert.ToInt32(properties.Attributes["size"].Value);
+ font.Bold = Convert.ToInt32(properties.Attributes["bold"].Value) != 0;
+ font.Italic = Convert.ToInt32(properties.Attributes["italic"].Value) != 0;
+ font.Unicode = Convert.ToInt32(properties.Attributes["unicode"].Value) != 0;
+ font.StretchedHeight = Convert.ToInt32(properties.Attributes["stretchH"].Value);
+ font.Charset = properties.Attributes["charset"].Value;
+ font.Smoothed = Convert.ToInt32(properties.Attributes["smooth"].Value) != 0;
+ font.SuperSampling = Convert.ToInt32(properties.Attributes["aa"].Value);
+ font.Padding = BitmapFontLoader.ParsePadding(properties.Attributes["padding"].Value);
+ font.Spacing = BitmapFontLoader.ParsePoint(properties.Attributes["spacing"].Value);
+ font.OutlineSize = Convert.ToInt32(properties.Attributes["outline"].Value);
+
+ // common attributes
+ properties = root.SelectSingleNode("common");
+ font.BaseHeight = Convert.ToInt32(properties.Attributes["lineHeight"].Value);
+ font.LineHeight = Convert.ToInt32(properties.Attributes["base"].Value);
+ font.TextureSize = new Size
+ (
+ Convert.ToInt32(properties.Attributes["scaleW"].Value),
+ Convert.ToInt32(properties.Attributes["scaleH"].Value)
+ );
+ font.Packed = Convert.ToInt32(properties.Attributes["packed"].Value) != 0;
+ font.AlphaChannel = Convert.ToInt32(properties.Attributes["alphaChnl"].Value);
+ font.RedChannel = Convert.ToInt32(properties.Attributes["redChnl"].Value);
+ font.GreenChannel = Convert.ToInt32(properties.Attributes["greenChnl"].Value);
+ font.BlueChannel = Convert.ToInt32(properties.Attributes["blueChnl"].Value);
+
+ // load texture information
+ foreach (XmlNode node in root.SelectNodes("pages/page"))
+ {
+ Page page;
+
+ page = new Page();
+ page.Id = Convert.ToInt32(node.Attributes["id"].Value);
+ page.FileName = node.Attributes["file"].Value;
+
+ pageData.Add(page.Id, page);
+ }
+ font.Pages = BitmapFontLoader.ToArray(pageData.Values);
+
+ // load character information
+ foreach (XmlNode node in root.SelectNodes("chars/char"))
+ {
+ Character character;
+
+ character = new Character();
+ character.Char = (char)Convert.ToInt32(node.Attributes["id"].Value);
+ character.Bounds = new Rectangle
+ (
+ Convert.ToInt32(node.Attributes["x"].Value),
+ Convert.ToInt32(node.Attributes["y"].Value),
+ Convert.ToInt32(node.Attributes["width"].Value),
+ Convert.ToInt32(node.Attributes["height"].Value)
+ );
+ character.Offset = new Point
+ (
+ Convert.ToInt32(node.Attributes["xoffset"].Value),
+ Convert.ToInt32(node.Attributes["yoffset"].Value)
+ );
+ character.XAdvance = Convert.ToInt32(node.Attributes["xadvance"].Value);
+ character.TexturePage = Convert.ToInt32(node.Attributes["page"].Value);
+ character.Channel = Convert.ToInt32(node.Attributes["chnl"].Value);
+
+ charDictionary.Add(character.Char, character);
+ }
+ font.Characters = charDictionary;
+
+ // loading kerning information
+ foreach (XmlNode node in root.SelectNodes("kernings/kerning"))
+ {
+ Kerning key;
+
+ key = new Kerning((char)Convert.ToInt32(node.Attributes["first"].Value), (char)Convert.ToInt32(node.Attributes["second"].Value), Convert.ToInt32(node.Attributes["amount"].Value));
+
+ if (!kerningDictionary.ContainsKey(key))
+ kerningDictionary.Add(key, key.Amount);
+ }
+ font.Kernings = kerningDictionary;
+
+ return font;
+ }
+
+ #endregion Public Class Methods
+
+ #region Private Class Methods
+
+ ///
+ /// Returns a boolean from an array of name/value pairs.
+ ///
+ /// The array of parts.
+ /// The name of the value to return.
+ ///
+ private static bool GetNamedBool(string[] parts, string name)
+ {
+ return BitmapFontLoader.GetNamedInt(parts, name) != 0;
+ }
+
+ ///
+ /// Returns an integer from an array of name/value pairs.
+ ///
+ /// The array of parts.
+ /// The name of the value to return.
+ ///
+ private static int GetNamedInt(string[] parts, string name)
+ {
+ return Convert.ToInt32(BitmapFontLoader.GetNamedString(parts, name));
+ }
+
+ ///
+ /// Returns a string from an array of name/value pairs.
+ ///
+ /// The array of parts.
+ /// The name of the value to return.
+ ///
+ private static string GetNamedString(string[] parts, string name)
+ {
+ string result;
+
+ result = string.Empty;
+ name = name.ToLowerInvariant();
+
+ foreach (string part in parts)
+ {
+ int nameEndIndex;
+
+ nameEndIndex = part.IndexOf("=");
+ if (nameEndIndex != -1)
+ {
+ string namePart;
+ string valuePart;
+
+ namePart = part.Substring(0, nameEndIndex).ToLowerInvariant();
+ valuePart = part.Substring(nameEndIndex + 1);
+
+ if (namePart == name)
+ {
+ if (valuePart.StartsWith("\"") && valuePart.EndsWith("\""))
+ valuePart = valuePart.Substring(1, valuePart.Length - 2);
+
+ result = valuePart;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Creates a Padding object from a string representation
+ ///
+ /// The string.
+ ///
+ private static Padding ParsePadding(string s)
+ {
+ string[] parts;
+
+ parts = s.Split(',');
+
+ return new Padding()
+ {
+ Left = Convert.ToInt32(parts[3].Trim()),
+ Top = Convert.ToInt32(parts[0].Trim()),
+ Right = Convert.ToInt32(parts[1].Trim()),
+ Bottom = Convert.ToInt32(parts[2].Trim())
+ };
+ }
+
+ ///
+ /// Creates a Point object from a string representation
+ ///
+ /// The string.
+ ///
+ private static Point ParsePoint(string s)
+ {
+ string[] parts;
+
+ parts = s.Split(',');
+
+ return new Point()
+ {
+ X = Convert.ToInt32(parts[0].Trim()),
+ Y = Convert.ToInt32(parts[1].Trim())
+ };
+ }
+
+ ///
+ /// Splits the specified string using a given delimiter, ignoring any instances of the delimiter as part of a quoted string.
+ ///
+ /// The string to split.
+ /// The delimiter.
+ ///
+ private static string[] Split(string s, char delimiter)
+ {
+ string[] results;
+
+ if (s.Contains("\""))
+ {
+ List parts;
+ int partStart;
+
+ partStart = -1;
+ parts = new List();
+
+ do
+ {
+ int partEnd;
+ int quoteStart;
+ int quoteEnd;
+ bool hasQuotes;
+
+ quoteStart = s.IndexOf("\"", partStart + 1);
+ quoteEnd = s.IndexOf("\"", quoteStart + 1);
+ partEnd = s.IndexOf(delimiter, partStart + 1);
+
+ if (partEnd == -1)
+ partEnd = s.Length;
+
+ hasQuotes = quoteStart != -1 && partEnd > quoteStart && partEnd < quoteEnd;
+ if (hasQuotes)
+ partEnd = s.IndexOf(delimiter, quoteEnd + 1);
+
+ parts.Add(s.Substring(partStart + 1, partEnd - partStart - 1));
+
+ if (hasQuotes)
+ partStart = partEnd - 1;
+
+ partStart = s.IndexOf(delimiter, partStart + 1);
+ } while (partStart != -1);
+
+ results = parts.ToArray();
+ }
+ else
+ results = s.Split(new char[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
+
+ return results;
+ }
+
+ ///
+ /// Converts the given collection into an array
+ ///
+ /// Type of the items in the array
+ /// The values.
+ ///
+ private static T[] ToArray(ICollection values)
+ {
+ T[] result;
+
+ // avoid a forced .NET 3 dependency just for one call to Linq
+
+ result = new T[values.Count];
+ values.CopyTo(result, 0);
+
+ return result;
+ }
+
+ #endregion Private Class Methods
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Character.cs b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Character.cs
new file mode 100644
index 0000000000..ce412a4bd2
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Character.cs
@@ -0,0 +1,34 @@
+//public domain assumed from cyotek.com
+
+using System.Drawing;
+
+namespace Cyotek.Drawing.BitmapFont
+{
+ public struct Character
+ {
+ #region Public Methods
+
+ public override string ToString()
+ {
+ return this.Char.ToString();
+ }
+
+ #endregion Public Methods
+
+ #region Public Properties
+
+ public int Channel { get; set; }
+
+ public Rectangle Bounds { get; set; }
+
+ public Point Offset { get; set; }
+
+ public char Char { get; set; }
+
+ public int TexturePage { get; set; }
+
+ public int XAdvance { get; set; }
+
+ #endregion Public Properties
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Kerning.cs b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Kerning.cs
new file mode 100644
index 0000000000..c831a67a1c
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Kerning.cs
@@ -0,0 +1,38 @@
+//public domain assumed from cyotek.com
+
+namespace Cyotek.Drawing.BitmapFont
+{
+ public struct Kerning
+ {
+ #region Public Constructors
+
+ public Kerning(char firstCharacter, char secondCharacter, int amount)
+ : this()
+ {
+ this.FirstCharacter = firstCharacter;
+ this.SecondCharacter = secondCharacter;
+ this.Amount = amount;
+ }
+
+ #endregion Public Constructors
+
+ #region Public Methods
+
+ public override string ToString()
+ {
+ return string.Format("{0} to {1} = {2}", this.FirstCharacter, this.SecondCharacter, this.Amount);
+ }
+
+ #endregion Public Methods
+
+ #region Public Properties
+
+ public char FirstCharacter { get; set; }
+
+ public char SecondCharacter { get; set; }
+
+ public int Amount { get; set; }
+
+ #endregion Public Properties
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Padding.cs b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Padding.cs
new file mode 100644
index 0000000000..20fab383d1
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Padding.cs
@@ -0,0 +1,41 @@
+//public domain assumed from cyotek.com
+
+namespace Cyotek.Drawing.BitmapFont
+{
+ public struct Padding
+ {
+ #region Public Constructors
+
+ public Padding(int left, int top, int right, int bottom)
+ : this()
+ {
+ this.Top = top;
+ this.Left = left;
+ this.Right = right;
+ this.Bottom = bottom;
+ }
+
+ #endregion Public Constructors
+
+ #region Public Methods
+
+ public override string ToString()
+ {
+ return string.Format("{0}, {1}, {2}, {3}", this.Left, this.Top, this.Right, this.Bottom);
+ }
+
+ #endregion Public Methods
+
+ #region Public Properties
+
+ public int Top { get; set; }
+
+ public int Left { get; set; }
+
+ public int Right { get; set; }
+
+ public int Bottom { get; set; }
+
+ #endregion Public Properties
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Page.cs b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Page.cs
new file mode 100644
index 0000000000..d18c45a39e
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/BitmapFontParser/Page.cs
@@ -0,0 +1,37 @@
+//public domain assumed from cyotek.com
+
+using System.IO;
+
+namespace Cyotek.Drawing.BitmapFont
+{
+ public struct Page
+ {
+ #region Public Constructors
+
+ public Page(int id, string fileName)
+ : this()
+ {
+ this.FileName = fileName;
+ this.Id = id;
+ }
+
+ #endregion Public Constructors
+
+ #region Public Methods
+
+ public override string ToString()
+ {
+ return string.Format("{0} ({1})", this.Id, Path.GetFileName(this.FileName));
+ }
+
+ #endregion Public Methods
+
+ #region Public Properties
+
+ public string FileName { get; set; }
+
+ public int Id { get; set; }
+
+ #endregion Public Properties
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/readme.txt b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/readme.txt
new file mode 100644
index 0000000000..15126b183e
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Borrowed/readme.txt
@@ -0,0 +1,4 @@
+BitmapFontParser
+http://cyotek.com/blog/angelcode-bitmap-font-parsing-using-csharp
+License not stated. I'm content with calling it public domain. As future work, the code could be replaced easily, so I dont consider this a big deal. It's most trivial code.
+It loads fonts created by http://www.angelcode.com/products/bmfont/
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Enums.cs b/Bizware/BizHawk.Bizware.BizwareGL/Enums.cs
new file mode 100644
index 0000000000..d19bab6379
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Enums.cs
@@ -0,0 +1,573 @@
+using System;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ // Summary:
+ // Used in GL.BlendFunc, GL.BlendFuncSeparate
+ public enum BlendingFactor
+ {
+ // Summary:
+ // Original was GL_ZERO = 0
+ Zero = 0,
+ //
+ // Summary:
+ // Original was GL_ONE = 1
+ One = 1,
+ //
+ // Summary:
+ // Original was GL_SRC_COLOR = 0x0300
+ SrcColor = 768,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_SRC_COLOR = 0x0301
+ OneMinusSrcColor = 769,
+ //
+ // Summary:
+ // Original was GL_SRC_ALPHA = 0x0302
+ SrcAlpha = 770,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_SRC_ALPHA = 0x0303
+ OneMinusSrcAlpha = 771,
+ //
+ // Summary:
+ // Original was GL_DST_ALPHA = 0x0304
+ DstAlpha = 772,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_DST_ALPHA = 0x0305
+ OneMinusDstAlpha = 773,
+ //
+ // Summary:
+ // Original was GL_DST_COLOR = 0x0306
+ DstColor = 774,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_DST_COLOR = 0x0307
+ OneMinusDstColor = 775,
+ //
+ // Summary:
+ // Original was GL_SRC_ALPHA_SATURATE = 0x0308
+ SrcAlphaSaturate = 776,
+ //
+ // Summary:
+ // Original was GL_CONSTANT_COLOR_EXT = 0x8001
+ ConstantColorExt = 32769,
+ //
+ // Summary:
+ // Original was GL_CONSTANT_COLOR = 0x8001
+ ConstantColor = 32769,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_CONSTANT_COLOR = 0x8002
+ OneMinusConstantColor = 32770,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_CONSTANT_COLOR_EXT = 0x8002
+ OneMinusConstantColorExt = 32770,
+ //
+ // Summary:
+ // Original was GL_CONSTANT_ALPHA = 0x8003
+ ConstantAlpha = 32771,
+ //
+ // Summary:
+ // Original was GL_CONSTANT_ALPHA_EXT = 0x8003
+ ConstantAlphaExt = 32771,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_CONSTANT_ALPHA_EXT = 0x8004
+ OneMinusConstantAlphaExt = 32772,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004
+ OneMinusConstantAlpha = 32772,
+ //
+ // Summary:
+ // Original was GL_SRC1_ALPHA = 0x8589
+ Src1Alpha = 34185,
+ //
+ // Summary:
+ // Original was GL_SRC1_COLOR = 0x88F9
+ Src1Color = 35065,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_SRC1_COLOR = 0x88FA
+ OneMinusSrc1Color = 35066,
+ //
+ // Summary:
+ // Original was GL_ONE_MINUS_SRC1_ALPHA = 0x88FB
+ OneMinusSrc1Alpha = 35067,
+ }
+
+ // Summary:
+ // Used in GL.Arb.BlendEquation, GL.BlendEquation and 2 other functions
+ public enum BlendEquationMode
+ {
+ // Summary:
+ // Original was GL_FUNC_ADD = 0x8006
+ FuncAdd = 32774,
+ //
+ // Summary:
+ // Original was GL_MIN = 0x8007
+ Min = 32775,
+ //
+ // Summary:
+ // Original was GL_MAX = 0x8008
+ Max = 32776,
+ //
+ // Summary:
+ // Original was GL_FUNC_SUBTRACT = 0x800A
+ FuncSubtract = 32778,
+ //
+ // Summary:
+ // Original was GL_FUNC_REVERSE_SUBTRACT = 0x800B
+ FuncReverseSubtract = 32779,
+ }
+
+ // Summary:
+ // Used in GL.BlitFramebuffer, GL.Clear and 1 other function
+ [Flags]
+ public enum ClearBufferMask
+ {
+ // Summary:
+ // Original was GL_NONE = 0
+ None = 0,
+ //
+ // Summary:
+ // Original was GL_DEPTH_BUFFER_BIT = 0x00000100
+ DepthBufferBit = 256,
+ //
+ // Summary:
+ // Original was GL_ACCUM_BUFFER_BIT = 0x00000200
+ AccumBufferBit = 512,
+ //
+ // Summary:
+ // Original was GL_STENCIL_BUFFER_BIT = 0x00000400
+ StencilBufferBit = 1024,
+ //
+ // Summary:
+ // Original was GL_COLOR_BUFFER_BIT = 0x00004000
+ ColorBufferBit = 16384,
+ //
+ // Summary:
+ // Original was GL_COVERAGE_BUFFER_BIT_NV = 0x00008000
+ CoverageBufferBitNv = 32768,
+ }
+
+ // Summary:
+ // Used in GL.TexParameter, GL.TexParameterI and 5 other functions
+ public enum TextureParameterName
+ {
+ // Summary:
+ // Original was GL_TEXTURE_BORDER_COLOR = 0x1004
+ TextureBorderColor = 4100,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MAG_FILTER = 0x2800
+ TextureMagFilter = 10240,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MIN_FILTER = 0x2801
+ TextureMinFilter = 10241,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_WRAP_S = 0x2802
+ TextureWrapS = 10242,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_WRAP_T = 0x2803
+ TextureWrapT = 10243,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_PRIORITY = 0x8066
+ TexturePriority = 32870,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_PRIORITY_EXT = 0x8066
+ TexturePriorityExt = 32870,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_DEPTH = 0x8071
+ TextureDepth = 32881,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_WRAP_R_EXT = 0x8072
+ TextureWrapRExt = 32882,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_WRAP_R_OES = 0x8072
+ TextureWrapROes = 32882,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_WRAP_R = 0x8072
+ TextureWrapR = 32882,
+ //
+ // Summary:
+ // Original was GL_DETAIL_TEXTURE_LEVEL_SGIS = 0x809A
+ DetailTextureLevelSgis = 32922,
+ //
+ // Summary:
+ // Original was GL_DETAIL_TEXTURE_MODE_SGIS = 0x809B
+ DetailTextureModeSgis = 32923,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_COMPARE_FAIL_VALUE = 0x80BF
+ TextureCompareFailValue = 32959,
+ //
+ // Summary:
+ // Original was GL_SHADOW_AMBIENT_SGIX = 0x80BF
+ ShadowAmbientSgix = 32959,
+ //
+ // Summary:
+ // Original was GL_DUAL_TEXTURE_SELECT_SGIS = 0x8124
+ DualTextureSelectSgis = 33060,
+ //
+ // Summary:
+ // Original was GL_QUAD_TEXTURE_SELECT_SGIS = 0x8125
+ QuadTextureSelectSgis = 33061,
+ //
+ // Summary:
+ // Original was GL_CLAMP_TO_BORDER = 0x812D
+ ClampToBorder = 33069,
+ //
+ // Summary:
+ // Original was GL_CLAMP_TO_EDGE = 0x812F
+ ClampToEdge = 33071,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_WRAP_Q_SGIS = 0x8137
+ TextureWrapQSgis = 33079,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MIN_LOD = 0x813A
+ TextureMinLod = 33082,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MAX_LOD = 0x813B
+ TextureMaxLod = 33083,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_BASE_LEVEL = 0x813C
+ TextureBaseLevel = 33084,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MAX_LEVEL = 0x813D
+ TextureMaxLevel = 33085,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_CLIPMAP_CENTER_SGIX = 0x8171
+ TextureClipmapCenterSgix = 33137,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_CLIPMAP_FRAME_SGIX = 0x8172
+ TextureClipmapFrameSgix = 33138,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_CLIPMAP_OFFSET_SGIX = 0x8173
+ TextureClipmapOffsetSgix = 33139,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX = 0x8174
+ TextureClipmapVirtualDepthSgix = 33140,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX = 0x8175
+ TextureClipmapLodOffsetSgix = 33141,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_CLIPMAP_DEPTH_SGIX = 0x8176
+ TextureClipmapDepthSgix = 33142,
+ //
+ // Summary:
+ // Original was GL_POST_TEXTURE_FILTER_BIAS_SGIX = 0x8179
+ PostTextureFilterBiasSgix = 33145,
+ //
+ // Summary:
+ // Original was GL_POST_TEXTURE_FILTER_SCALE_SGIX = 0x817A
+ PostTextureFilterScaleSgix = 33146,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_LOD_BIAS_S_SGIX = 0x818E
+ TextureLodBiasSSgix = 33166,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_LOD_BIAS_T_SGIX = 0x818F
+ TextureLodBiasTSgix = 33167,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_LOD_BIAS_R_SGIX = 0x8190
+ TextureLodBiasRSgix = 33168,
+ //
+ // Summary:
+ // Original was GL_GENERATE_MIPMAP = 0x8191
+ GenerateMipmap = 33169,
+ //
+ // Summary:
+ // Original was GL_GENERATE_MIPMAP_SGIS = 0x8191
+ GenerateMipmapSgis = 33169,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_COMPARE_SGIX = 0x819A
+ TextureCompareSgix = 33178,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MAX_CLAMP_S_SGIX = 0x8369
+ TextureMaxClampSSgix = 33641,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MAX_CLAMP_T_SGIX = 0x836A
+ TextureMaxClampTSgix = 33642,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_MAX_CLAMP_R_SGIX = 0x836B
+ TextureMaxClampRSgix = 33643,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_LOD_BIAS = 0x8501
+ TextureLodBias = 34049,
+ //
+ // Summary:
+ // Original was GL_DEPTH_TEXTURE_MODE = 0x884B
+ DepthTextureMode = 34891,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_COMPARE_MODE = 0x884C
+ TextureCompareMode = 34892,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_COMPARE_FUNC = 0x884D
+ TextureCompareFunc = 34893,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_SWIZZLE_R = 0x8E42
+ TextureSwizzleR = 36418,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_SWIZZLE_G = 0x8E43
+ TextureSwizzleG = 36419,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_SWIZZLE_B = 0x8E44
+ TextureSwizzleB = 36420,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_SWIZZLE_A = 0x8E45
+ TextureSwizzleA = 36421,
+ //
+ // Summary:
+ // Original was GL_TEXTURE_SWIZZLE_RGBA = 0x8E46
+ TextureSwizzleRgba = 36422,
+ }
+
+ // Summary:
+ // Not used directly.
+ public enum TextureMinFilter
+ {
+ // Summary:
+ // Original was GL_NEAREST = 0x2600
+ Nearest = 9728,
+ //
+ // Summary:
+ // Original was GL_LINEAR = 0x2601
+ Linear = 9729,
+ //
+ // Summary:
+ // Original was GL_NEAREST_MIPMAP_NEAREST = 0x2700
+ NearestMipmapNearest = 9984,
+ //
+ // Summary:
+ // Original was GL_LINEAR_MIPMAP_NEAREST = 0x2701
+ LinearMipmapNearest = 9985,
+ //
+ // Summary:
+ // Original was GL_NEAREST_MIPMAP_LINEAR = 0x2702
+ NearestMipmapLinear = 9986,
+ //
+ // Summary:
+ // Original was GL_LINEAR_MIPMAP_LINEAR = 0x2703
+ LinearMipmapLinear = 9987,
+ //
+ // Summary:
+ // Original was GL_FILTER4_SGIS = 0x8146
+ Filter4Sgis = 33094,
+ //
+ // Summary:
+ // Original was GL_LINEAR_CLIPMAP_LINEAR_SGIX = 0x8170
+ LinearClipmapLinearSgix = 33136,
+ //
+ // Summary:
+ // Original was GL_PIXEL_TEX_GEN_Q_CEILING_SGIX = 0x8184
+ PixelTexGenQCeilingSgix = 33156,
+ //
+ // Summary:
+ // Original was GL_PIXEL_TEX_GEN_Q_ROUND_SGIX = 0x8185
+ PixelTexGenQRoundSgix = 33157,
+ //
+ // Summary:
+ // Original was GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX = 0x8186
+ PixelTexGenQFloorSgix = 33158,
+ //
+ // Summary:
+ // Original was GL_NEAREST_CLIPMAP_NEAREST_SGIX = 0x844D
+ NearestClipmapNearestSgix = 33869,
+ //
+ // Summary:
+ // Original was GL_NEAREST_CLIPMAP_LINEAR_SGIX = 0x844E
+ NearestClipmapLinearSgix = 33870,
+ //
+ // Summary:
+ // Original was GL_LINEAR_CLIPMAP_NEAREST_SGIX = 0x844F
+ LinearClipmapNearestSgix = 33871,
+ }
+
+ // Summary:
+ // Not used directly.
+ public enum TextureMagFilter
+ {
+ // Summary:
+ // Original was GL_NEAREST = 0x2600
+ Nearest = 9728,
+ //
+ // Summary:
+ // Original was GL_LINEAR = 0x2601
+ Linear = 9729,
+ //
+ // Summary:
+ // Original was GL_LINEAR_DETAIL_SGIS = 0x8097
+ LinearDetailSgis = 32919,
+ //
+ // Summary:
+ // Original was GL_LINEAR_DETAIL_ALPHA_SGIS = 0x8098
+ LinearDetailAlphaSgis = 32920,
+ //
+ // Summary:
+ // Original was GL_LINEAR_DETAIL_COLOR_SGIS = 0x8099
+ LinearDetailColorSgis = 32921,
+ //
+ // Summary:
+ // Original was GL_LINEAR_SHARPEN_SGIS = 0x80AD
+ LinearSharpenSgis = 32941,
+ //
+ // Summary:
+ // Original was GL_LINEAR_SHARPEN_ALPHA_SGIS = 0x80AE
+ LinearSharpenAlphaSgis = 32942,
+ //
+ // Summary:
+ // Original was GL_LINEAR_SHARPEN_COLOR_SGIS = 0x80AF
+ LinearSharpenColorSgis = 32943,
+ //
+ // Summary:
+ // Original was GL_FILTER4_SGIS = 0x8146
+ Filter4Sgis = 33094,
+ //
+ // Summary:
+ // Original was GL_PIXEL_TEX_GEN_Q_CEILING_SGIX = 0x8184
+ PixelTexGenQCeilingSgix = 33156,
+ //
+ // Summary:
+ // Original was GL_PIXEL_TEX_GEN_Q_ROUND_SGIX = 0x8185
+ PixelTexGenQRoundSgix = 33157,
+ //
+ // Summary:
+ // Original was GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX = 0x8186
+ PixelTexGenQFloorSgix = 33158,
+ }
+
+ public enum VertexAttributeType
+ {
+ // Summary:
+ // Original was GL_BYTE = 0x1400
+ Byte = 5120,
+ //
+ // Summary:
+ // Original was GL_UNSIGNED_BYTE = 0x1401
+ UnsignedByte = 5121,
+ //
+ // Summary:
+ // Original was GL_SHORT = 0x1402
+ Short = 5122,
+ //
+ // Summary:
+ // Original was GL_UNSIGNED_SHORT = 0x1403
+ UnsignedShort = 5123,
+ //
+ // Summary:
+ // Original was GL_INT = 0x1404
+ Int = 5124,
+ //
+ // Summary:
+ // Original was GL_UNSIGNED_INT = 0x1405
+ UnsignedInt = 5125,
+ //
+ // Summary:
+ // Original was GL_FLOAT = 0x1406
+ Float = 5126,
+ //
+ // Summary:
+ // Original was GL_DOUBLE = 0x140A
+ Double = 5130,
+ //
+ // Summary:
+ // Original was GL_HALF_FLOAT = 0x140B
+ HalfFloat = 5131,
+ //
+ // Summary:
+ // Original was GL_FIXED = 0x140C
+ Fixed = 5132,
+ //
+ // Summary:
+ // Original was GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368
+ UnsignedInt2101010Rev = 33640,
+ //
+ // Summary:
+ // Original was GL_INT_2_10_10_10_REV = 0x8D9F
+ Int2101010Rev = 36255,
+ }
+
+ // Summary:
+ // Used in GL.Apple.DrawElementArray, GL.Apple.DrawRangeElementArray and 38
+ // other functions
+ public enum PrimitiveType
+ {
+ // Summary:
+ // Original was GL_POINTS = 0x0000
+ Points = 0,
+ //
+ // Summary:
+ // Original was GL_LINES = 0x0001
+ Lines = 1,
+ //
+ // Summary:
+ // Original was GL_LINE_LOOP = 0x0002
+ LineLoop = 2,
+ //
+ // Summary:
+ // Original was GL_LINE_STRIP = 0x0003
+ LineStrip = 3,
+ //
+ // Summary:
+ // Original was GL_TRIANGLES = 0x0004
+ Triangles = 4,
+ //
+ // Summary:
+ // Original was GL_TRIANGLE_STRIP = 0x0005
+ TriangleStrip = 5,
+ //
+ // Summary:
+ // Original was GL_TRIANGLE_FAN = 0x0006
+ TriangleFan = 6,
+ //
+ // Summary:
+ // Original was GL_QUADS = 0x0007
+ Quads = 7,
+ //
+ // Summary:
+ // Original was GL_QUAD_STRIP = 0x0008
+ QuadStrip = 8,
+ //
+ // Summary:
+ // Original was GL_POLYGON = 0x0009
+ Polygon = 9,
+ }
+
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/GraphicsControl.cs b/Bizware/BizHawk.Bizware.BizwareGL/GraphicsControl.cs
new file mode 100644
index 0000000000..3882501134
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/GraphicsControl.cs
@@ -0,0 +1,42 @@
+using System;
+using swf = System.Windows.Forms;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// Represents
+ ///
+ public abstract class GraphicsControl : IDisposable
+ {
+ ///
+ /// Gets the control that this interface is wrapping
+ ///
+ public abstract swf.Control Control { get; }
+
+ public static implicit operator swf.Control(GraphicsControl ctrl) { return ctrl.Control; }
+
+ ///
+ /// Sets whether presentation operations on this control will vsync
+ ///
+ public abstract void SetVsync(bool state);
+
+ ///
+ /// Swaps the buffers for this control
+ ///
+ public abstract void SwapBuffers();
+
+ ///
+ /// Makes this control current for rendering operations.
+ /// Note that at this time, the window size shouldnt change until End() or else something bad might happen
+ /// Please be aware that this might change the rendering context, meaning that some things you set without calling BeginControl/EndControl might not be affected
+ ///
+ public abstract void Begin();
+
+ ///
+ /// Ends rendering on the specified control.
+ ///
+ public abstract void End();
+
+ public abstract void Dispose();
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs b/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs
new file mode 100644
index 0000000000..98caddda1b
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs
@@ -0,0 +1,305 @@
+//http://stackoverflow.com/questions/6893302/decode-rgb-value-to-single-float-without-bit-shift-in-glsl
+
+using System;
+using sd=System.Drawing;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// A simple renderer useful for rendering GUI stuff.
+ /// When doing GUI rendering, run everything through here (if you need a GL feature not done through here, run it through here first)
+ /// Call Begin, then draw, then End, and dont use other Renderers or GL calls in the meantime, unless you know what youre doing.
+ /// This can perform batching (well.. maybe not yet), which is occasionally necessary for drawing large quantities of things.
+ ///
+ public class GuiRenderer : IDisposable
+ {
+ public GuiRenderer(IGL owner)
+ {
+ Owner = owner;
+
+ VertexLayout = owner.CreateVertexLayout();
+ VertexLayout.DefineVertexAttribute(0, 2, BizwareGL.VertexAttributeType.Float, false, 16, 0);
+ VertexLayout.DefineVertexAttribute(1, 2, BizwareGL.VertexAttributeType.Float, false, 16, 8);
+ VertexLayout.Close();
+
+ _Projection = new MatrixStack();
+ _Modelview = new MatrixStack();
+
+ var vs = Owner.CreateVertexShader(DefaultVertexShader);
+ var ps = Owner.CreateFragmentShader(DefaultPixelShader);
+ CurrPipeline = DefaultPipeline = Owner.CreatePipeline(vs, ps);
+ }
+
+ public void Dispose()
+ {
+ VertexLayout.Dispose();
+ VertexLayout = null;
+ DefaultPipeline.Dispose();
+ DefaultPipeline = null;
+ }
+
+ ///
+ /// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it.
+ /// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one
+ ///
+ public void SetPipeline(Pipeline pipeline)
+ {
+ if (IsActive)
+ throw new InvalidOperationException("Can't change pipeline while renderer is running!");
+
+ Flush();
+ CurrPipeline = pipeline;
+ }
+
+ ///
+ /// Restores the pipeline to the default
+ ///
+ public void SetDefaultPipeline()
+ {
+ SetPipeline(DefaultPipeline);
+ }
+
+ public void SetModulateColorWhite()
+ {
+ SetModulateColor(sd.Color.White);
+ }
+
+ public void SetModulateColor(sd.Color color)
+ {
+ Flush();
+ CurrPipeline["uModulateColor"].Set(new Vector4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f));
+ }
+
+ public void SetBlendState(IBlendState rsBlend)
+ {
+ Flush();
+ Owner.SetBlendState(rsBlend);
+ }
+
+ MatrixStack _Projection, _Modelview;
+ public MatrixStack Projection
+ {
+ get { return _Projection; }
+ set
+ {
+ _Projection = value;
+ _Projection.IsDirty = true;
+ }
+ }
+ public MatrixStack Modelview
+ {
+ get { return _Modelview; }
+ set
+ {
+ _Modelview = value;
+ _Modelview.IsDirty = true;
+ }
+ }
+
+ ///
+ /// begin rendering, initializing viewport and projections to the given dimensions
+ ///
+ public void Begin(int width, int height)
+ {
+ Begin();
+
+ Projection = Owner.CreateGuiProjectionMatrix(width, height);
+ Modelview = Owner.CreateGuiViewMatrix(width, height);
+ Owner.SetViewport(0, 0, width, height);
+ }
+
+ ///
+ /// Begins rendering
+ ///
+ public void Begin()
+ {
+ //uhhmmm I want to throw an exception if its already active, but its annoying.
+
+ if(CurrPipeline == null)
+ throw new InvalidOperationException("Pipeline hasn't been set!");
+
+ IsActive = true;
+ Owner.BindVertexLayout(VertexLayout);
+ Owner.BindPipeline(CurrPipeline);
+
+ //clear state cache
+ sTexture = null;
+ Modelview.Clear();
+ Projection.Clear();
+ SetModulateColorWhite();
+ }
+
+ ///
+ /// Use this, if you must do something sneaky to openGL without this GuiRenderer knowing.
+ /// It might be faster than End and Beginning again, and certainly prettier
+ ///
+ public void Flush()
+ {
+ //no batching, nothing to do here yet
+ }
+
+ ///
+ /// Ends rendering
+ ///
+ public void End()
+ {
+ if (!IsActive)
+ throw new InvalidOperationException("GuiRenderer is not active!");
+ IsActive = false;
+ }
+
+ ///
+ /// Draws a subrectangle from the provided texture. For advanced users only
+ ///
+ public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
+ {
+ DrawSubrectInternal(tex, x, y, w, h, u0, v0, u1, v1);
+ }
+
+ ///
+ /// draws the specified Art resource
+ ///
+ public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); }
+
+ ///
+ /// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
+ ///
+ public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); }
+
+ ///
+ /// draws the specified Art resource with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first.
+ ///
+ public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); }
+
+ ///
+ /// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
+ ///
+ public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); }
+
+ ///
+ /// draws the specified texture2d resource.
+ ///
+ public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); }
+
+ ///
+ /// draws the specified Art resource with the given flip flags
+ ///
+ public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); }
+
+ unsafe void DrawInternal(Texture2d tex, float x, float y, float w, float h)
+ {
+ Art art = new Art(null);
+ art.Width = w;
+ art.Height = h;
+ art.u0 = art.v0 = 0;
+ art.u1 = art.v1 = 1;
+ art.BaseTexture = tex;
+ DrawInternal(art,x,y,w,h,false,false);
+ }
+
+ unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy)
+ {
+ float u0,v0,u1,v1;
+ if(fx) { u0 = art.u1; u1 = art.u0; }
+ else { u0 = art.u0; u1 = art.u1; }
+ if(fy) { v0 = art.v1; v1 = art.v0; }
+ else { v0 = art.v0; v1 = art.v1; }
+
+ float[] data = new float[16] {
+ x,y, u0,v0,
+ x+art.Width,y, u1,v0,
+ x,y+art.Height, u0,v1,
+ x+art.Width,y+art.Height, u1,v1
+ };
+
+ Texture2d tex = art.BaseTexture;
+ if(sTexture != tex)
+ CurrPipeline["uSampler0"].Set(sTexture = tex);
+
+ if (_Projection.IsDirty)
+ {
+ CurrPipeline["um44Projection"].Set(ref _Projection.Top);
+ _Projection.IsDirty = false;
+ }
+ if (_Modelview.IsDirty)
+ {
+ CurrPipeline["um44Modelview"].Set(ref _Modelview.Top);
+ _Modelview.IsDirty = false;
+ }
+
+ fixed (float* pData = &data[0])
+ {
+ Owner.BindArrayData(pData);
+ Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
+ }
+ }
+
+ unsafe void DrawSubrectInternal(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
+ {
+ float[] data = new float[16] {
+ x,y, u0,v0,
+ x+w,y, u1,v0,
+ x,y+h, u0,v1,
+ x+w,y+h, u1,v1
+ };
+
+ if (sTexture != tex)
+ CurrPipeline["uSampler0"].Set(sTexture = tex);
+
+ if (_Projection.IsDirty)
+ {
+ CurrPipeline["um44Projection"].Set(ref _Projection.Top);
+ _Projection.IsDirty = false;
+ }
+ if (_Modelview.IsDirty)
+ {
+ CurrPipeline["um44Modelview"].Set(ref _Modelview.Top);
+ _Modelview.IsDirty = false;
+ }
+
+ fixed (float* pData = &data[0])
+ {
+ Owner.BindArrayData(pData);
+ Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
+ }
+ }
+
+ public bool IsActive { get; private set; }
+ public IGL Owner { get; private set; }
+
+ VertexLayout VertexLayout;
+ Pipeline CurrPipeline, DefaultPipeline;
+
+ //state cache
+ Texture2d sTexture;
+
+ public readonly string DefaultVertexShader = @"
+uniform mat4 um44Modelview, um44Projection;
+
+attribute vec2 aPosition;
+attribute vec2 aTexcoord;
+
+varying vec2 vTexcoord0;
+
+void main()
+{
+ vec4 temp = vec4(aPosition,0,1);
+ gl_Position = um44Projection * (um44Modelview * temp);
+ vTexcoord0 = aTexcoord;
+}";
+
+ public readonly string DefaultPixelShader = @"
+uniform sampler2D uSampler0;
+uniform vec4 uModulateColor;
+
+varying vec2 vTexcoord0;
+
+void main()
+{
+ vec4 temp = texture2D(uSampler0,vTexcoord0);
+ temp *= uModulateColor;
+ gl_FragColor = temp;
+}";
+
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs b/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs
new file mode 100644
index 0000000000..3e6f739d6f
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs
@@ -0,0 +1,204 @@
+using System;
+using System.IO;
+using sd=System.Drawing;
+using swf=System.Windows.Forms;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+
+ ///
+ /// This is a wrapper over hopefully any OpenGL bindings..
+ /// And possibly, quite possibly, Direct3d.. even though none of your shaders would work. (could use nvidia CG, native dlls in necessary since this would only be for windows)
+ /// TODO - This really needs to be split up into an internal and a user interface. so many of the functions are made to support the smart wrappers
+ /// Maybe make a method that returns an interface used for advanced methods (and IGL_TK could implement that as well and just "return this:")
+ ///
+ public interface IGL
+ {
+ ///
+ /// Returns an a control optimized for drawing onto the screen.
+ ///
+ GraphicsControl CreateGraphicsControl();
+
+ ///
+ /// Clears the specified buffer parts
+ ///
+ ///
+ void Clear(ClearBufferMask mask);
+
+ ///
+ /// Sets the current clear color
+ ///
+ void ClearColor(sd.Color color);
+
+ ///
+ /// generates a texture handle
+ ///
+ IntPtr GenTexture();
+
+ ///
+ /// returns an empty handle
+ ///
+ IntPtr GetEmptyHandle();
+
+ ///
+ /// returns an empty uniform handle
+ ///
+ IntPtr GetEmptyUniformHandle();
+
+ ///
+ /// compile a fragment shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
+ ///
+ Shader CreateFragmentShader(string source);
+
+ ///
+ /// compile a vertex shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
+ ///
+ Shader CreateVertexShader(string source);
+
+ ///
+ /// Creates a complete pipeline from the provided vertex and fragment shader handles
+ ///
+ Pipeline CreatePipeline(Shader vertexShader, Shader fragmentShader);
+
+ ///
+ /// Binds this pipeline as the current used for rendering
+ ///
+ void BindPipeline(Pipeline pipeline);
+
+ ///
+ /// Sets a uniform sampler to use use the provided texture handle
+ ///
+ void SetPipelineUniformSampler(PipelineUniform uniform, IntPtr texHandle);
+
+ ///
+ /// Sets a uniform value
+ ///
+ void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix mat, bool transpose);
+
+ ///
+ /// Sets a uniform value
+ ///
+ void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix mat, bool transpose);
+
+ ///
+ /// sets a uniform value
+ ///
+ void SetPipelineUniform(PipelineUniform uniform, Vector4 value);
+
+ ///
+ /// Binds this VertexLayout for use in rendering (in OpenGL's case, by glVertexAttribPointer calls)
+ ///
+ void BindVertexLayout(VertexLayout layout);
+
+ ///
+ /// Binds array data for use with the currently-bound VertexLayout
+ ///
+ unsafe void BindArrayData(void* pData);
+
+ ///
+ /// Draws based on the currently set VertexLayout and ArrayData
+ ///
+ void DrawArrays(PrimitiveType mode, int first, int count);
+
+ ///
+ /// Frees the provided shader handle
+ ///
+ void FreeShader(IntPtr shader);
+
+ ///
+ /// frees the provided texture handle
+ ///
+ void FreeTexture(IntPtr texHandle);
+
+ ///
+ /// Binds this texture as the current texture2d target for parameter-specification
+ ///
+ ///
+ void BindTexture2d(Texture2d texture);
+
+ ///
+ /// Sets a 2d texture parameter
+ ///
+ void TexParameter2d(TextureParameterName pname, int param);
+
+ ///
+ /// creates a vertex layout resource
+ ///
+ VertexLayout CreateVertexLayout();
+
+ ///
+ /// Creates a blending state object
+ ///
+ IBlendState CreateBlendState(BlendingFactor colorSource, BlendEquationMode colorEquation, BlendingFactor colorDest,
+ BlendingFactor alphaSource, BlendEquationMode alphaEquation, BlendingFactor alphaDest);
+
+ ///
+ /// retrieves a blend state for opaque rendering
+ /// Alpha values are copied from the source fragment.
+ ///
+ IBlendState BlendNone { get; }
+
+ ///
+ /// retrieves a blend state for normal (non-premultiplied) alpha blending.
+ /// Alpha values are copied from the source fragment.
+ ///
+ IBlendState BlendNormal { get; }
+
+ ///
+ /// Sets the current blending state object
+ ///
+ void SetBlendState(IBlendState rsBlend);
+
+ ///
+ /// Creates a texture with the specified dimensions
+ /// TODO - pass in specifications somehow
+ ///
+ Texture2d CreateTexture(int width, int height);
+
+ ///
+ /// Loads the texture with new data. This isnt supposed to be especially versatile, it just blasts a bitmap buffer into the texture
+ ///
+ void LoadTextureData(Texture2d tex, BitmapBuffer bmp);
+
+ ///
+ /// Loads a texture from disk
+ ///
+ Texture2d LoadTexture(string path);
+
+ ///
+ /// Loads a texture from the stream
+ ///
+ Texture2d LoadTexture(Stream stream);
+
+ ///
+ /// Loads a texture from the BitmapBuffer
+ ///
+ Texture2d LoadTexture(BitmapBuffer buffer);
+
+ ///
+ /// Loads a texture from the System.Drawing.Bitmap
+ ///
+ Texture2d LoadTexture(sd.Bitmap bitmap);
+
+ ///
+ /// sets the viewport according to the provided specifications
+ ///
+ void SetViewport(int x, int y, int width, int height);
+
+ ///
+ /// sets the viewport according to the client area of the provided control
+ ///
+ void SetViewport(swf.Control control);
+
+ ///
+ /// generates a proper 2d othographic projection for the given destination size, suitable for use in a GUI
+ ///
+ Matrix CreateGuiProjectionMatrix(int w, int h);
+
+ ///
+ /// generates a proper view transform for a standard 2d ortho projection, including half-pixel jitter if necessary and
+ /// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI
+ ///
+ Matrix CreateGuiViewMatrix(int w, int h);
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/MatrixStack.cs b/Bizware/BizHawk.Bizware.BizwareGL/MatrixStack.cs
new file mode 100644
index 0000000000..a24ee4c4e5
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/MatrixStack.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class MatrixStack
+ {
+ public MatrixStack()
+ {
+ LoadIdentity();
+ IsDirty = false;
+ }
+
+ public static implicit operator Matrix(MatrixStack ms) { return ms.Top; }
+ public static implicit operator MatrixStack(Matrix m) { return new MatrixStack(m); }
+
+ public MatrixStack(Matrix matrix) { LoadMatrix(matrix); }
+
+ public bool IsDirty;
+
+ Stack stack = new Stack();
+
+ ///
+ /// This is made public for performance reasons, to avoid lame copies of the matrix when necessary. Don't mess it up!
+ ///
+ public Matrix Top;
+
+ ///
+ /// Resets the matrix stack to an empty identity matrix stack
+ ///
+ public void Clear()
+ {
+ stack.Clear();
+ LoadIdentity();
+ IsDirty = true;
+ }
+
+ ///
+ /// Clears the matrix stack and loads the specified value
+ ///
+ public void Clear(Matrix value)
+ {
+ stack.Clear();
+ Top = value;
+ IsDirty = true;
+ }
+
+ public void LoadMatrix(Matrix value) { Top = value; IsDirty = true; }
+
+ public void LoadIdentity() { Top = Matrix.Identity; IsDirty = true; }
+
+ public void Pop() { Top = stack.Pop(); IsDirty = true; }
+ public void Push() { stack.Push(Top); IsDirty = true; }
+
+ public void RotateAxis(Vector3 axisRotation, float angle) { Top = Matrix.CreateFromAxisAngle(axisRotation, angle) * Top; IsDirty = true; }
+
+ public void Scale(Vector3 scale) { Top = Matrix.CreateScale(scale) * Top; IsDirty = true; }
+ public void Scale(Vector2 scale) { Top = Matrix.CreateScale(scale.X, scale.Y, 1) * Top; IsDirty = true; }
+ public void Scale(float x, float y, float z) { Top = Matrix.CreateScale(x, y, z) * Top; IsDirty = true; }
+ public void Scale(float ratio) { Scale(ratio, ratio, ratio); IsDirty = true; }
+ public void Scale(float x, float y) { Scale(x, y, 1); IsDirty = true; }
+
+ public void RotateAxis(float x, float y, float z, float degrees) { MultiplyMatrix(Matrix.CreateFromAxisAngle(new Vector3(x, y, z), degrees)); IsDirty = true; }
+ public void RotateY(float degrees) { MultiplyMatrix(Matrix.CreateRotationY(degrees)); IsDirty = true; }
+ public void RotateX(float degrees) { MultiplyMatrix(Matrix.CreateRotationX(degrees)); IsDirty = true; }
+ public void RotateZ(float degrees) { MultiplyMatrix(Matrix.CreateRotationZ(degrees)); IsDirty = true; }
+
+ public void Translate(Vector2 v) { Translate(v.X, v.Y, 0); IsDirty = true; }
+ public void Translate(Vector3 trans) { Top = Matrix.CreateTranslation(trans) * Top; IsDirty = true; }
+ public void Translate(float x, float y, float z) { Top = Matrix.CreateTranslation(x, y, z) * Top; IsDirty = true; }
+ public void Translate(float x, float y) { Translate(x, y, 0); IsDirty = true; }
+ public void Translate(Point pt) { Translate(pt.X, pt.Y, 0); IsDirty = true; }
+
+ public void MultiplyMatrix(MatrixStack ms) { MultiplyMatrix(ms.Top); IsDirty = true; }
+ public void MultiplyMatrix(Matrix value) { Top = value * Top; IsDirty = true; }
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Pipeline.cs b/Bizware/BizHawk.Bizware.BizwareGL/Pipeline.cs
new file mode 100644
index 0000000000..7131349800
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Pipeline.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class Pipeline : IDisposable
+ {
+ public Pipeline(IGL owner, IntPtr id, IEnumerable uniforms)
+ {
+ Owner = owner;
+ Id = id;
+
+ //create the uniforms from the info list we got
+ UniformsDictionary = new SpecialWorkingDictionary(this);
+ foreach(var ui in uniforms)
+ {
+ UniformsDictionary[ui.Name] = new PipelineUniform(this, ui);
+ }
+ }
+
+ ///
+ /// Allows us to create PipelineUniforms on the fly, in case a non-existing one has been requested.
+ /// GLSL will optimize out unused uniforms, and we wont have a record of it in the uniforms population loop
+ ///
+ class SpecialWorkingDictionary : Dictionary
+ {
+ public SpecialWorkingDictionary(Pipeline owner)
+ {
+ Owner = owner;
+ }
+
+ Pipeline Owner;
+ public new PipelineUniform this[string key]
+ {
+ get
+ {
+ PipelineUniform temp;
+ if (!TryGetValue(key, out temp))
+ {
+ var ui = new UniformInfo();
+ ui.Handle = Owner.Owner.GetEmptyUniformHandle();
+ temp = this[key] = new PipelineUniform(Owner,ui);
+ }
+
+ return temp;
+ }
+
+ internal set
+ {
+ base[key] = value;
+ }
+ }
+ }
+
+ SpecialWorkingDictionary UniformsDictionary;
+ IDictionary Uniforms { get { return UniformsDictionary; } }
+
+ public PipelineUniform this[string key]
+ {
+ get { return UniformsDictionary[key]; }
+ }
+
+ public IGL Owner { get; private set; }
+ public IntPtr Id { get; private set; }
+
+ /////
+ ///// Makes the pipeline current
+ /////
+ //public void BindData()
+ //{
+ // Owner.BindPipeline(this);
+ //}
+
+ public void Dispose()
+ {
+ //todo
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/PipelineUniform.cs b/Bizware/BizHawk.Bizware.BizwareGL/PipelineUniform.cs
new file mode 100644
index 0000000000..282b8144bc
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/PipelineUniform.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class PipelineUniform
+ {
+ internal PipelineUniform(Pipeline owner, UniformInfo info)
+ {
+ Owner = owner;
+ Id = info.Handle;
+ SamplerIndex = info.SamplerIndex;
+ }
+
+ public Pipeline Owner { get; private set; }
+ public IntPtr Id { get; private set; }
+ public int SamplerIndex { get; private set; }
+
+ public void Set(Matrix mat, bool transpose = false)
+ {
+ Owner.Owner.SetPipelineUniformMatrix(this, mat, transpose);
+ }
+
+ public void Set(Vector4 vec, bool transpose = false)
+ {
+ Owner.Owner.SetPipelineUniform(this, vec);
+ }
+
+ public void Set(ref Matrix mat, bool transpose = false)
+ {
+ Owner.Owner.SetPipelineUniformMatrix(this, ref mat, transpose);
+ }
+
+ public void Set(Texture2d tex)
+ {
+ Owner.Owner.SetPipelineUniformSampler(this, tex.Id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/RenderStates.cs b/Bizware/BizHawk.Bizware.BizwareGL/RenderStates.cs
new file mode 100644
index 0000000000..cb2ba8624e
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/RenderStates.cs
@@ -0,0 +1,7 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public interface IBlendState { }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Shader.cs b/Bizware/BizHawk.Bizware.BizwareGL/Shader.cs
new file mode 100644
index 0000000000..9dc8656a96
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Shader.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// Just a lifecycle-managed wrapper around shader handles
+ ///
+ public class Shader : IDisposable
+ {
+ public Shader(IGL owner, IntPtr id)
+ {
+ Owner = owner;
+ Id = id;
+ }
+
+ public IGL Owner { get; private set; }
+ public IntPtr Id { get; private set; }
+ public bool Disposed { get; private set; }
+
+ public void Dispose()
+ {
+ if (Disposed) return;
+ Disposed = true;
+ Owner.FreeShader(Id);
+ Id = Owner.GetEmptyHandle();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/StringRenderer.cs b/Bizware/BizHawk.Bizware.BizwareGL/StringRenderer.cs
new file mode 100644
index 0000000000..527863d43e
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/StringRenderer.cs
@@ -0,0 +1,80 @@
+//http://www.angelcode.com/products/bmfont/
+//http://cyotek.com/blog/angelcode-bitmap-font-parsing-using-csharp
+
+using System;
+using sd=System.Drawing;
+using System.Collections.Generic;
+using System.IO;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class StringRenderer : IDisposable
+ {
+ public StringRenderer(IGL owner, Stream xml, params Stream[] textures)
+ {
+ Owner = owner;
+ FontInfo = Cyotek.Drawing.BitmapFont.BitmapFontLoader.LoadFontFromXmlFile(xml);
+
+ //load textures
+ for(int i=0;i TexturePages = new List();
+
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/TexAtlas.cs b/Bizware/BizHawk.Bizware.BizwareGL/TexAtlas.cs
new file mode 100644
index 0000000000..9730b21d70
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/TexAtlas.cs
@@ -0,0 +1,325 @@
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.IO;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class TexAtlas
+ {
+ public class RectItem
+ {
+ public RectItem(int width, int height, object item)
+ {
+ Width = width;
+ Height = height;
+ Item = item;
+ }
+ public int X, Y;
+ public int Width, Height;
+ public int TexIndex;
+ public object Item;
+ }
+
+
+ class TryFitParam
+ {
+ public TryFitParam(int _w, int _h) { this.w = _w; this.h = _h; }
+ public int w, h;
+ public bool ok = true;
+ public RectangleBinPack rbp = new RectangleBinPack();
+ public List nodes = new List();
+ }
+
+ public class PackedAtlasResults
+ {
+ public class SingleAtlas
+ {
+ public Size Size;
+ public List Items;
+ }
+ public List Atlases = new List();
+ }
+
+ public static int MaxSizeBits = 16;
+
+ ///
+ /// packs the supplied RectItems into an atlas. Modifies the RectItems with x/y values of location in new atlas.
+ ///
+ public static PackedAtlasResults PackAtlas(IEnumerable items)
+ {
+ PackedAtlasResults ret = new PackedAtlasResults();
+ ret.Atlases.Add(new PackedAtlasResults.SingleAtlas());
+
+ //initially, we'll try all the items; none remain
+ List currentItems = new List(items);
+ List remainItems = new List();
+
+ RETRY:
+
+ //this is where the texture size range is determined.
+ //we run this every time we make an atlas, in case we want to variably control the maximum texture output size.
+ //ALSO - we accumulate data in there, so we need to refresh it each time. ... lame.
+ List todoSizes = new List();
+ for (int i = 3; i <= MaxSizeBits; i++)
+ {
+ for (int j = 3; j <= MaxSizeBits; j++)
+ {
+ int w = 1 << i;
+ int h = 1 << j;
+ TryFitParam tfp = new TryFitParam(w, h);
+ todoSizes.Add(tfp);
+ }
+ }
+
+ //run the packing algorithm on each potential size
+ Parallel.ForEach(todoSizes, (param) =>
+ {
+ var rbp = new RectangleBinPack();
+ rbp.Init(16384, 16384);
+ param.rbp.Init(param.w, param.h);
+
+ foreach (var ri in currentItems)
+ {
+ RectangleBinPack.Node node = param.rbp.Insert(ri.Width, ri.Height);
+ if (node == null)
+ {
+ param.ok = false;
+ }
+ else
+ {
+ node.ri = ri;
+ param.nodes.Add(node);
+ }
+ }
+ });
+
+ //find the best fit among the potential sizes that worked
+ long best = long.MaxValue;
+ TryFitParam tfpFinal = null;
+ foreach (TryFitParam tfp in todoSizes)
+ {
+ if (tfp.ok)
+ {
+ long area = (long)tfp.w * (long)tfp.h;
+ long perimeter = (long)tfp.w + (long)tfp.h;
+ if (area < best)
+ {
+ best = area;
+ tfpFinal = tfp;
+ }
+ else if (area == best)
+ {
+ //try to minimize perimeter (to create squares, which are nicer to look at)
+ if (tfpFinal == null)
+ { }
+ else if (perimeter < tfpFinal.w + tfpFinal.h)
+ {
+ best = area;
+ tfpFinal = tfp;
+ }
+ }
+ }
+ }
+
+ //did we find any fit?
+ if (best == long.MaxValue)
+ {
+ //nope - move an item to the remaining list and try again
+ remainItems.Add(currentItems[currentItems.Count - 1]);
+ currentItems.RemoveAt(currentItems.Count - 1);
+ goto RETRY;
+ }
+
+ //we found a fit. setup this atlas in the result and drop the items into it
+ var atlas = ret.Atlases[ret.Atlases.Count - 1];
+ atlas.Size.Width = tfpFinal.w;
+ atlas.Size.Height = tfpFinal.h;
+ atlas.Items = new List(items);
+ foreach (var item in currentItems)
+ {
+ object o = item.Item;
+ var node = tfpFinal.nodes.Find((x) => x.ri == item);
+ item.X = node.x;
+ item.Y = node.y;
+ item.TexIndex = ret.Atlases.Count - 1;
+ }
+
+ //if we have any items left, we've got to run this again
+ if (remainItems.Count > 0)
+ {
+ //move all remaining items into the clear list
+ currentItems.Clear();
+ currentItems.AddRange(remainItems);
+ remainItems.Clear();
+
+ ret.Atlases.Add(new PackedAtlasResults.SingleAtlas());
+ goto RETRY;
+ }
+
+ if (ret.Atlases.Count > 1)
+ Console.WriteLine("Created animset with >1 texture ({0} textures)", ret.Atlases.Count);
+
+ return ret;
+ }
+
+ //original file: RectangleBinPack.cpp
+ //author: Jukka Jylänki
+ class RectangleBinPack
+ {
+ /** A node of a binary tree. Each node represents a rectangular area of the texture
+ we surface. Internal nodes store rectangles of used data, whereas leaf nodes track
+ rectangles of free space. All the rectangles stored in the tree are disjoint. */
+ public class Node
+ {
+ // Left and right child. We don't really distinguish which is which, so these could
+ // as well be child1 and child2.
+ public Node left;
+ public Node right;
+
+ // The top-left coordinate of the rectangle.
+ public int x;
+ public int y;
+
+ // The dimension of the rectangle.
+ public int width;
+ public int height;
+
+ public RectItem ri;
+ };
+
+ /// Starts a new packing process to a bin of the given dimension.
+ public void Init(int width, int height)
+ {
+ binWidth = width;
+ binHeight = height;
+ root = new Node();
+ root.left = root.right = null;
+ root.x = root.y = 0;
+ root.width = width;
+ root.height = height;
+ }
+
+
+ /// Inserts a new rectangle of the given size into the bin.
+ /** Running time is linear to the number of rectangles that have been already packed.
+ @return A pointer to the node that stores the newly added rectangle, or 0
+ if it didn't fit. */
+ public Node Insert(int width, int height)
+ {
+ return Insert(root, width, height);
+ }
+
+ /// Computes the ratio of used surface area.
+ float Occupancy()
+ {
+ int totalSurfaceArea = binWidth * binHeight;
+ int usedSurfaceArea = UsedSurfaceArea(root);
+
+ return (float)usedSurfaceArea / totalSurfaceArea;
+ }
+
+ private Node root;
+
+ // The total size of the bin we started with.
+ private int binWidth;
+ private int binHeight;
+
+ /// @return The surface area used by the subtree rooted at node.
+ private int UsedSurfaceArea(Node node)
+ {
+ if (node.left != null || node.right != null)
+ {
+ int usedSurfaceArea = node.width * node.height;
+ if (node.left != null)
+ usedSurfaceArea += UsedSurfaceArea(node.left);
+ if (node.right != null)
+ usedSurfaceArea += UsedSurfaceArea(node.right);
+
+ return usedSurfaceArea;
+ }
+
+ // This is a leaf node, it doesn't constitute to the total surface area.
+ return 0;
+ }
+
+
+ /// Inserts a new rectangle in the subtree rooted at the given node.
+ private Node Insert(Node node, int width, int height)
+ {
+
+ // If this node is an internal node, try both leaves for possible space.
+ // (The rectangle in an internal node stores used space, the leaves store free space)
+ if (node.left != null || node.right != null)
+ {
+ if (node.left != null)
+ {
+ Node newNode = Insert(node.left, width, height);
+ if (newNode != null)
+ return newNode;
+ }
+ if (node.right != null)
+ {
+ Node newNode = Insert(node.right, width, height);
+ if (newNode != null)
+ return newNode;
+ }
+ return null; // Didn't fit into either subtree!
+ }
+
+ // This node is a leaf, but can we fit the new rectangle here?
+ if (width > node.width || height > node.height)
+ return null; // Too bad, no space.
+
+ // The new cell will fit, split the remaining space along the shorter axis,
+ // that is probably more optimal.
+ int w = node.width - width;
+ int h = node.height - height;
+ node.left = new Node();
+ node.right = new Node();
+ if (w <= h) // Split the remaining space in horizontal direction.
+ {
+ node.left.x = node.x + width;
+ node.left.y = node.y;
+ node.left.width = w;
+ node.left.height = height;
+
+ node.right.x = node.x;
+ node.right.y = node.y + height;
+ node.right.width = node.width;
+ node.right.height = h;
+ }
+ else // Split the remaining space in vertical direction.
+ {
+ node.left.x = node.x;
+ node.left.y = node.y + height;
+ node.left.width = width;
+ node.left.height = h;
+
+ node.right.x = node.x + width;
+ node.right.y = node.y;
+ node.right.width = w;
+ node.right.height = node.height;
+ }
+ // Note that as a result of the above, it can happen that node.left or node.right
+ // is now a degenerate (zero area) rectangle. No need to do anything about it,
+ // like remove the nodes as "unnecessary" since they need to exist as children of
+ // this node (this node can't be a leaf anymore).
+
+ // This node is now a non-leaf, so shrink its area - it now denotes
+ // *occupied* space instead of free space. Its children spawn the resulting
+ // area of free space.
+ node.width = width;
+ node.height = height;
+ return node;
+ }
+ };
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Texture2d.cs b/Bizware/BizHawk.Bizware.BizwareGL/Texture2d.cs
new file mode 100644
index 0000000000..7270c6f256
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Texture2d.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ ///
+ /// A full-scale 2D texture, with mip levels and everything.
+ /// In OpenGL tradition, this encapsulates the sampler state, as well, which is equal parts annoying and convenient
+ ///
+ public class Texture2d : IDisposable
+ {
+ //not sure if I need this idea.
+ //public class Maker
+ //{
+ // public Maker(Texture2d tex)
+ // {
+ // MyTexture = tex;
+ // }
+ // public void SetWidth(int width)
+ // {
+ // MyTexture.Width = width;
+ // }
+ // public void SetHeight(int width)
+ // {
+ // MyTexture.Height = height;
+ // }
+
+ // Texture2d MyTexture;
+ //}
+
+ public void Dispose()
+ {
+ Owner.FreeTexture(Id);
+ Id = Owner.GetEmptyHandle();
+ }
+
+ public Texture2d(IGL owner, IntPtr id, int width, int height)
+ {
+ Owner = owner;
+ Id = id;
+ Width = width;
+ Height = height;
+ }
+
+ public void LoadFrom(BitmapBuffer buffer)
+ {
+ }
+
+ public void SetMinFilter(TextureMinFilter minFilter)
+ {
+ Owner.BindTexture2d(this);
+ Owner.TexParameter2d(TextureParameterName.TextureMinFilter, (int)minFilter);
+ }
+
+ public void SetMagFilter(TextureMagFilter magFilter)
+ {
+ Owner.BindTexture2d(this);
+ Owner.TexParameter2d(TextureParameterName.TextureMagFilter, (int)magFilter);
+ }
+
+ public void SetFilterLinear()
+ {
+ SetMinFilter(TextureMinFilter.Linear);
+ SetMagFilter(TextureMagFilter.Linear);
+ }
+
+ public void SetFilterNearest()
+ {
+ SetMinFilter(TextureMinFilter.Nearest);
+ SetMagFilter(TextureMagFilter.Nearest);
+ }
+
+ public IGL Owner { get; private set; }
+ public IntPtr Id { get; private set; }
+
+ //note.. it is commonly helpful to have these as floats, since we're more often using them for rendering than for raster logic
+ public float Width { get; private set; }
+ public float Height { get; private set; }
+
+ public int IntWidth { get { return (int)Width; } }
+ public int IntHeight { get { return (int)Height; } }
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingBox.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingBox.cs
new file mode 100644
index 0000000000..cf917f3ee4
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingBox.cs
@@ -0,0 +1,426 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Authors:
+Olivier Dufour (Duff)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public struct BoundingBox : IEquatable
+ {
+
+ #region Public Fields
+
+ public Vector3 Min;
+ public Vector3 Max;
+ public const int CornerCount = 8;
+
+ #endregion Public Fields
+
+
+ #region Public Constructors
+
+ public BoundingBox(Vector3 min, Vector3 max)
+ {
+ this.Min = min;
+ this.Max = max;
+ }
+
+ #endregion Public Constructors
+
+
+ #region Public Methods
+
+ public ContainmentType Contains(BoundingBox box)
+ {
+ //test if all corner is in the same side of a face by just checking min and max
+ if (box.Max.X < Min.X
+ || box.Min.X > Max.X
+ || box.Max.Y < Min.Y
+ || box.Min.Y > Max.Y
+ || box.Max.Z < Min.Z
+ || box.Min.Z > Max.Z)
+ return ContainmentType.Disjoint;
+
+
+ if (box.Min.X >= Min.X
+ && box.Max.X <= Max.X
+ && box.Min.Y >= Min.Y
+ && box.Max.Y <= Max.Y
+ && box.Min.Z >= Min.Z
+ && box.Max.Z <= Max.Z)
+ return ContainmentType.Contains;
+
+ return ContainmentType.Intersects;
+ }
+
+ public void Contains(ref BoundingBox box, out ContainmentType result)
+ {
+ result = Contains(box);
+ }
+
+ public ContainmentType Contains(BoundingFrustum frustum)
+ {
+ //TODO: bad done here need a fix.
+ //Because question is not frustum contain box but reverse and this is not the same
+ int i;
+ ContainmentType contained;
+ Vector3[] corners = frustum.GetCorners();
+
+ // First we check if frustum is in box
+ for (i = 0; i < corners.Length; i++)
+ {
+ this.Contains(ref corners[i], out contained);
+ if (contained == ContainmentType.Disjoint)
+ break;
+ }
+
+ if (i == corners.Length) // This means we checked all the corners and they were all contain or instersect
+ return ContainmentType.Contains;
+
+ if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects
+ return ContainmentType.Intersects;
+
+
+ // If we get here, it means the first (and only) point we checked was actually contained in the frustum.
+ // So we assume that all other points will also be contained. If one of the points is disjoint, we can
+ // exit immediately saying that the result is Intersects
+ i++;
+ for (; i < corners.Length; i++)
+ {
+ this.Contains(ref corners[i], out contained);
+ if (contained != ContainmentType.Contains)
+ return ContainmentType.Intersects;
+
+ }
+
+ // If we get here, then we know all the points were actually contained, therefore result is Contains
+ return ContainmentType.Contains;
+ }
+
+ public ContainmentType Contains(BoundingSphere sphere)
+ {
+ if (sphere.Center.X - Min.X > sphere.Radius
+ && sphere.Center.Y - Min.Y > sphere.Radius
+ && sphere.Center.Z - Min.Z > sphere.Radius
+ && Max.X - sphere.Center.X > sphere.Radius
+ && Max.Y - sphere.Center.Y > sphere.Radius
+ && Max.Z - sphere.Center.Z > sphere.Radius)
+ return ContainmentType.Contains;
+
+ double dmin = 0;
+
+ if (sphere.Center.X - Min.X <= sphere.Radius)
+ dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
+ else if (Max.X - sphere.Center.X <= sphere.Radius)
+ dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
+ if (sphere.Center.Y - Min.Y <= sphere.Radius)
+ dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
+ else if (Max.Y - sphere.Center.Y <= sphere.Radius)
+ dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
+ if (sphere.Center.Z - Min.Z <= sphere.Radius)
+ dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
+ else if (Max.Z - sphere.Center.Z <= sphere.Radius)
+ dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
+
+ if (dmin <= sphere.Radius * sphere.Radius)
+ return ContainmentType.Intersects;
+
+ return ContainmentType.Disjoint;
+ }
+
+ public void Contains(ref BoundingSphere sphere, out ContainmentType result)
+ {
+ result = this.Contains(sphere);
+ }
+
+ public ContainmentType Contains(Vector3 point)
+ {
+ ContainmentType result;
+ this.Contains(ref point, out result);
+ return result;
+ }
+
+ public void Contains(ref Vector3 point, out ContainmentType result)
+ {
+ //first we get if point is out of box
+ if (point.X < this.Min.X
+ || point.X > this.Max.X
+ || point.Y < this.Min.Y
+ || point.Y > this.Max.Y
+ || point.Z < this.Min.Z
+ || point.Z > this.Max.Z)
+ {
+ result = ContainmentType.Disjoint;
+ }//or if point is on box because coordonate of point is lesser or equal
+ else if (point.X == this.Min.X
+ || point.X == this.Max.X
+ || point.Y == this.Min.Y
+ || point.Y == this.Max.Y
+ || point.Z == this.Min.Z
+ || point.Z == this.Max.Z)
+ result = ContainmentType.Intersects;
+ else
+ result = ContainmentType.Contains;
+
+
+ }
+
+ public static BoundingBox CreateFromPoints(IEnumerable points)
+ {
+ if (points == null)
+ throw new ArgumentNullException();
+
+ // TODO: Just check that Count > 0
+ bool empty = true;
+ Vector3 vector2 = new Vector3(float.MaxValue);
+ Vector3 vector1 = new Vector3(float.MinValue);
+ foreach (Vector3 vector3 in points)
+ {
+ vector2 = Vector3.Min(vector2, vector3);
+ vector1 = Vector3.Max(vector1, vector3);
+ empty = false;
+ }
+ if (empty)
+ throw new ArgumentException();
+
+ return new BoundingBox(vector2, vector1);
+ }
+
+ public static BoundingBox CreateFromSphere(BoundingSphere sphere)
+ {
+ Vector3 vector1 = new Vector3(sphere.Radius);
+ return new BoundingBox(sphere.Center - vector1, sphere.Center + vector1);
+ }
+
+ public static void CreateFromSphere(ref BoundingSphere sphere, out BoundingBox result)
+ {
+ result = BoundingBox.CreateFromSphere(sphere);
+ }
+
+ public static BoundingBox CreateMerged(BoundingBox original, BoundingBox additional)
+ {
+ return new BoundingBox(
+ Vector3.Min(original.Min, additional.Min), Vector3.Max(original.Max, additional.Max));
+ }
+
+ public static void CreateMerged(ref BoundingBox original, ref BoundingBox additional, out BoundingBox result)
+ {
+ result = BoundingBox.CreateMerged(original, additional);
+ }
+
+ public bool Equals(BoundingBox other)
+ {
+ return (this.Min == other.Min) && (this.Max == other.Max);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return (obj is BoundingBox) ? this.Equals((BoundingBox)obj) : false;
+ }
+
+ public Vector3[] GetCorners()
+ {
+ return new Vector3[] {
+ new Vector3(this.Min.X, this.Max.Y, this.Max.Z),
+ new Vector3(this.Max.X, this.Max.Y, this.Max.Z),
+ new Vector3(this.Max.X, this.Min.Y, this.Max.Z),
+ new Vector3(this.Min.X, this.Min.Y, this.Max.Z),
+ new Vector3(this.Min.X, this.Max.Y, this.Min.Z),
+ new Vector3(this.Max.X, this.Max.Y, this.Min.Z),
+ new Vector3(this.Max.X, this.Min.Y, this.Min.Z),
+ new Vector3(this.Min.X, this.Min.Y, this.Min.Z)
+ };
+ }
+
+ public void GetCorners(Vector3[] corners)
+ {
+ if (corners == null)
+ {
+ throw new ArgumentNullException("corners");
+ }
+ if (corners.Length < 8)
+ {
+ throw new ArgumentOutOfRangeException("corners", "Not Enought Corners");
+ }
+ corners[0].X = this.Min.X;
+ corners[0].Y = this.Max.Y;
+ corners[0].Z = this.Max.Z;
+ corners[1].X = this.Max.X;
+ corners[1].Y = this.Max.Y;
+ corners[1].Z = this.Max.Z;
+ corners[2].X = this.Max.X;
+ corners[2].Y = this.Min.Y;
+ corners[2].Z = this.Max.Z;
+ corners[3].X = this.Min.X;
+ corners[3].Y = this.Min.Y;
+ corners[3].Z = this.Max.Z;
+ corners[4].X = this.Min.X;
+ corners[4].Y = this.Max.Y;
+ corners[4].Z = this.Min.Z;
+ corners[5].X = this.Max.X;
+ corners[5].Y = this.Max.Y;
+ corners[5].Z = this.Min.Z;
+ corners[6].X = this.Max.X;
+ corners[6].Y = this.Min.Y;
+ corners[6].Z = this.Min.Z;
+ corners[7].X = this.Min.X;
+ corners[7].Y = this.Min.Y;
+ corners[7].Z = this.Min.Z;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.Min.GetHashCode() + this.Max.GetHashCode();
+ }
+
+ public bool Intersects(BoundingBox box)
+ {
+ bool result;
+ Intersects(ref box, out result);
+ return result;
+ }
+
+ public void Intersects(ref BoundingBox box, out bool result)
+ {
+ if ((this.Max.X >= box.Min.X) && (this.Min.X <= box.Max.X))
+ {
+ if ((this.Max.Y < box.Min.Y) || (this.Min.Y > box.Max.Y))
+ {
+ result = false;
+ return;
+ }
+
+ result = (this.Max.Z >= box.Min.Z) && (this.Min.Z <= box.Max.Z);
+ return;
+ }
+
+ result = false;
+ return;
+ }
+
+ public bool Intersects(BoundingFrustum frustum)
+ {
+ return frustum.Intersects(this);
+ }
+
+ public bool Intersects(BoundingSphere sphere)
+ {
+ if (sphere.Center.X - Min.X > sphere.Radius
+ && sphere.Center.Y - Min.Y > sphere.Radius
+ && sphere.Center.Z - Min.Z > sphere.Radius
+ && Max.X - sphere.Center.X > sphere.Radius
+ && Max.Y - sphere.Center.Y > sphere.Radius
+ && Max.Z - sphere.Center.Z > sphere.Radius)
+ return true;
+
+ double dmin = 0;
+
+ if (sphere.Center.X - Min.X <= sphere.Radius)
+ dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
+ else if (Max.X - sphere.Center.X <= sphere.Radius)
+ dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
+
+ if (sphere.Center.Y - Min.Y <= sphere.Radius)
+ dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
+ else if (Max.Y - sphere.Center.Y <= sphere.Radius)
+ dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
+
+ if (sphere.Center.Z - Min.Z <= sphere.Radius)
+ dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
+ else if (Max.Z - sphere.Center.Z <= sphere.Radius)
+ dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
+
+ if (dmin <= sphere.Radius * sphere.Radius)
+ return true;
+
+ return false;
+ }
+
+ public void Intersects(ref BoundingSphere sphere, out bool result)
+ {
+ result = Intersects(sphere);
+ }
+
+ public PlaneIntersectionType Intersects(Plane plane)
+ {
+ //check all corner side of plane
+ Vector3[] corners = this.GetCorners();
+ float lastdistance = Vector3.Dot(plane.Normal, corners[0]) + plane.D;
+
+ for (int i = 1; i < corners.Length; i++)
+ {
+ float distance = Vector3.Dot(plane.Normal, corners[i]) + plane.D;
+ if ((distance <= 0.0f && lastdistance > 0.0f) || (distance >= 0.0f && lastdistance < 0.0f))
+ return PlaneIntersectionType.Intersecting;
+ lastdistance = distance;
+ }
+
+ if (lastdistance > 0.0f)
+ return PlaneIntersectionType.Front;
+
+ return PlaneIntersectionType.Back;
+
+ }
+
+ public void Intersects(ref Plane plane, out PlaneIntersectionType result)
+ {
+ result = Intersects(plane);
+ }
+
+ public Nullable Intersects(Ray ray)
+ {
+ return ray.Intersects(this);
+ }
+
+ public void Intersects(ref Ray ray, out Nullable result)
+ {
+ result = Intersects(ray);
+ }
+
+ public static bool operator ==(BoundingBox a, BoundingBox b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(BoundingBox a, BoundingBox b)
+ {
+ return !a.Equals(b);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{{Min:{0} Max:{1}}}", this.Min.ToString(), this.Max.ToString());
+ }
+
+ #endregion Public Methods
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingFrustum.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingFrustum.cs
new file mode 100644
index 0000000000..463bfc0b9a
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingFrustum.cs
@@ -0,0 +1,513 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Authors:
+Olivier Dufour (Duff)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable, TypeConverter(typeof(ExpandableObjectConverter))]
+ public class BoundingFrustum : IEquatable
+ {
+ #region Private Fields
+
+ private Matrix matrix;
+ private Plane bottom;
+ private Plane far;
+ private Plane left;
+ private Plane right;
+ private Plane near;
+ private Plane top;
+ private Vector3[] corners;
+
+ #endregion Private Fields
+
+ #region Public Fields
+ public const int CornerCount = 8;
+ #endregion
+
+ #region Public Constructors
+
+ public BoundingFrustum(Matrix value)
+ {
+ this.matrix = value;
+ CreatePlanes();
+ CreateCorners();
+ }
+
+ #endregion Public Constructors
+
+
+ #region Public Properties
+
+ public Plane Bottom
+ {
+ get { return this.bottom; }
+ }
+
+ public Plane Far
+ {
+ get { return this.far; }
+ }
+
+ public Plane Left
+ {
+ get { return this.left; }
+ }
+
+ public Matrix Matrix
+ {
+ get { return this.matrix; }
+ set
+ {
+ this.matrix = value;
+ this.CreatePlanes(); // FIXME: The odds are the planes will be used a lot more often than the matrix
+ this.CreateCorners(); // is updated, so this should help performance. I hope ;)
+ }
+ }
+
+ public Plane Near
+ {
+ get { return this.near; }
+ }
+
+ public Plane Right
+ {
+ get { return this.right; }
+ }
+
+ public Plane Top
+ {
+ get { return this.top; }
+ }
+
+ #endregion Public Properties
+
+
+ #region Public Methods
+
+ public static bool operator ==(BoundingFrustum a, BoundingFrustum b)
+ {
+ if (object.Equals(a, null))
+ return (object.Equals(b, null));
+
+ if (object.Equals(b, null))
+ return (object.Equals(a, null));
+
+ return a.matrix == (b.matrix);
+ }
+
+ public static bool operator !=(BoundingFrustum a, BoundingFrustum b)
+ {
+ return !(a == b);
+ }
+
+ public ContainmentType Contains(BoundingBox box)
+ {
+ ContainmentType result;
+ this.Contains(ref box, out result);
+ return result;
+ }
+
+ public void GetCorners(Vector3[] corners)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Contains(ref BoundingBox box, out ContainmentType result)
+ {
+ // FIXME: Is this a bug?
+ // If the bounding box is of W * D * H = 0, then return disjoint
+ if (box.Min == box.Max)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ int i;
+ ContainmentType contained;
+ Vector3[] corners = box.GetCorners();
+
+ // First we assume completely disjoint. So if we find a point that is contained, we break out of this loop
+ for (i = 0; i < corners.Length; i++)
+ {
+ this.Contains(ref corners[i], out contained);
+ if (contained != ContainmentType.Disjoint)
+ break;
+ }
+
+ if (i == corners.Length) // This means we checked all the corners and they were all disjoint
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects
+ { // because we know at least one point is outside and one is inside.
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ // If we get here, it means the first (and only) point we checked was actually contained in the frustum.
+ // So we assume that all other points will also be contained. If one of the points is disjoint, we can
+ // exit immediately saying that the result is Intersects
+ i++;
+ for (; i < corners.Length; i++)
+ {
+ this.Contains(ref corners[i], out contained);
+ if (contained != ContainmentType.Contains)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+ }
+
+ // If we get here, then we know all the points were actually contained, therefore result is Contains
+ result = ContainmentType.Contains;
+ return;
+ }
+
+ // TODO: Implement this
+ public ContainmentType Contains(BoundingFrustum frustum)
+ {
+ if (this == frustum) // We check to see if the two frustums are equal
+ return ContainmentType.Contains;// If they are, there's no need to go any further.
+
+ throw new NotImplementedException();
+ }
+
+ public ContainmentType Contains(BoundingSphere sphere)
+ {
+ ContainmentType result;
+ this.Contains(ref sphere, out result);
+ return result;
+ }
+
+ public void Contains(ref BoundingSphere sphere, out ContainmentType result)
+ {
+ float val;
+ ContainmentType contained;
+
+ // We first check if the sphere is inside the frustum
+ this.Contains(ref sphere.Center, out contained);
+
+ // The sphere is inside. Now we need to check if it's fully contained or not
+ // So we see if the perpendicular distance to each plane is less than or equal to the sphere's radius.
+ // If the perpendicular distance is less, just return Intersects.
+ if (contained == ContainmentType.Contains)
+ {
+ val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.bottom);
+ if (val < sphere.Radius)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.far);
+ if (val < sphere.Radius)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.left);
+ if (val < sphere.Radius)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.near);
+ if (val < sphere.Radius)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.right);
+ if (val < sphere.Radius)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ val = PlaneHelper.PerpendicularDistance(ref sphere.Center, ref this.top);
+ if (val < sphere.Radius)
+ {
+ result = ContainmentType.Intersects;
+ return;
+ }
+
+ // If we get here, the sphere is fully contained
+ result = ContainmentType.Contains;
+ return;
+ }
+ //duff idea : test if all corner is in same side of a plane if yes and outside it is disjoint else intersect
+ // issue is that we can have some times when really close aabb
+
+
+
+ // If we're here, the the sphere's centre was outside of the frustum. This makes things hard :(
+ // We can't use perpendicular distance anymore. I'm not sure how to code this.
+ throw new NotImplementedException();
+ }
+
+ public ContainmentType Contains(Vector3 point)
+ {
+ ContainmentType result;
+ this.Contains(ref point, out result);
+ return result;
+ }
+
+ public void Contains(ref Vector3 point, out ContainmentType result)
+ {
+ float val;
+ // If a point is on the POSITIVE side of the plane, then the point is not contained within the frustum
+
+ // Check the top
+ val = PlaneHelper.ClassifyPoint(ref point, ref this.top);
+ if (val > 0)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ // Check the bottom
+ val = PlaneHelper.ClassifyPoint(ref point, ref this.bottom);
+ if (val > 0)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ // Check the left
+ val = PlaneHelper.ClassifyPoint(ref point, ref this.left);
+ if (val > 0)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ // Check the right
+ val = PlaneHelper.ClassifyPoint(ref point, ref this.right);
+ if (val > 0)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ // Check the near
+ val = PlaneHelper.ClassifyPoint(ref point, ref this.near);
+ if (val > 0)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ // Check the far
+ val = PlaneHelper.ClassifyPoint(ref point, ref this.far);
+ if (val > 0)
+ {
+ result = ContainmentType.Disjoint;
+ return;
+ }
+
+ // If we get here, it means that the point was on the correct side of each plane to be
+ // contained. Therefore this point is contained
+ result = ContainmentType.Contains;
+ }
+
+ public bool Equals(BoundingFrustum other)
+ {
+ return (this == other);
+ }
+
+ public override bool Equals(object obj)
+ {
+ BoundingFrustum f = obj as BoundingFrustum;
+ return (object.Equals(f, null)) ? false : (this == f);
+ }
+
+ public Vector3[] GetCorners()
+ {
+ return corners;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.matrix.GetHashCode();
+ }
+
+ public bool Intersects(BoundingBox box)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref BoundingBox box, out bool result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Intersects(BoundingFrustum frustum)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Intersects(BoundingSphere sphere)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref BoundingSphere sphere, out bool result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public PlaneIntersectionType Intersects(Plane plane)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref Plane plane, out PlaneIntersectionType result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Nullable Intersects(Ray ray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref Ray ray, out Nullable result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(256);
+ sb.Append("{Near:");
+ sb.Append(this.near.ToString());
+ sb.Append(" Far:");
+ sb.Append(this.far.ToString());
+ sb.Append(" Left:");
+ sb.Append(this.left.ToString());
+ sb.Append(" Right:");
+ sb.Append(this.right.ToString());
+ sb.Append(" Top:");
+ sb.Append(this.top.ToString());
+ sb.Append(" Bottom:");
+ sb.Append(this.bottom.ToString());
+ sb.Append("}");
+ return sb.ToString();
+ }
+
+ #endregion Public Methods
+
+
+ #region Private Methods
+
+ private void CreateCorners()
+ {
+ this.corners = new Vector3[8];
+ this.corners[0] = IntersectionPoint(ref this.near, ref this.left, ref this.top);
+ this.corners[1] = IntersectionPoint(ref this.near, ref this.right, ref this.top);
+ this.corners[2] = IntersectionPoint(ref this.near, ref this.right, ref this.bottom);
+ this.corners[3] = IntersectionPoint(ref this.near, ref this.left, ref this.bottom);
+ this.corners[4] = IntersectionPoint(ref this.far, ref this.left, ref this.top);
+ this.corners[5] = IntersectionPoint(ref this.far, ref this.right, ref this.top);
+ this.corners[6] = IntersectionPoint(ref this.far, ref this.right, ref this.bottom);
+ this.corners[7] = IntersectionPoint(ref this.far, ref this.left, ref this.bottom);
+ }
+
+ private void CreatePlanes()
+ {
+ // Pre-calculate the different planes needed
+ this.left = new Plane(-this.matrix.M14 - this.matrix.M11, -this.matrix.M24 - this.matrix.M21,
+ -this.matrix.M34 - this.matrix.M31, -this.matrix.M44 - this.matrix.M41);
+
+ this.right = new Plane(this.matrix.M11 - this.matrix.M14, this.matrix.M21 - this.matrix.M24,
+ this.matrix.M31 - this.matrix.M34, this.matrix.M41 - this.matrix.M44);
+
+ this.top = new Plane(this.matrix.M12 - this.matrix.M14, this.matrix.M22 - this.matrix.M24,
+ this.matrix.M32 - this.matrix.M34, this.matrix.M42 - this.matrix.M44);
+
+ this.bottom = new Plane(-this.matrix.M14 - this.matrix.M12, -this.matrix.M24 - this.matrix.M22,
+ -this.matrix.M34 - this.matrix.M32, -this.matrix.M44 - this.matrix.M42);
+
+ this.near = new Plane(-this.matrix.M13, -this.matrix.M23, -this.matrix.M33, -this.matrix.M43);
+
+
+ this.far = new Plane(this.matrix.M13 - this.matrix.M14, this.matrix.M23 - this.matrix.M24,
+ this.matrix.M33 - this.matrix.M34, this.matrix.M43 - this.matrix.M44);
+
+ this.NormalizePlane(ref this.left);
+ this.NormalizePlane(ref this.right);
+ this.NormalizePlane(ref this.top);
+ this.NormalizePlane(ref this.bottom);
+ this.NormalizePlane(ref this.near);
+ this.NormalizePlane(ref this.far);
+ }
+
+ private static Vector3 IntersectionPoint(ref Plane a, ref Plane b, ref Plane c)
+ {
+ // Formula used
+ // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+ //P = -------------------------------------------------------------------------
+ // N1 . ( N2 * N3 )
+ //
+ // Note: N refers to the normal, d refers to the displacement. '.' means dot product. '*' means cross product
+
+ Vector3 v1, v2, v3;
+ float f = -Vector3.Dot(a.Normal, Vector3.Cross(b.Normal, c.Normal));
+
+ v1 = (a.D * (Vector3.Cross(b.Normal, c.Normal)));
+ v2 = (b.D * (Vector3.Cross(c.Normal, a.Normal)));
+ v3 = (c.D * (Vector3.Cross(a.Normal, b.Normal)));
+
+ Vector3 vec = new Vector3(v1.X + v2.X + v3.X, v1.Y + v2.Y + v3.Y, v1.Z + v2.Z + v3.Z);
+ return vec / f;
+ }
+
+ private void NormalizePlane(ref Plane p)
+ {
+ float factor = 1f / p.Normal.Length();
+ p.Normal.X *= factor;
+ p.Normal.Y *= factor;
+ p.Normal.Z *= factor;
+ p.D *= factor;
+ }
+
+ #endregion
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingSphere.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingSphere.cs
new file mode 100644
index 0000000000..b1895286db
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/BoundingSphere.cs
@@ -0,0 +1,363 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Authors:
+Olivier Dufour (Duff)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.ComponentModel;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public struct BoundingSphere : IEquatable
+ {
+ #region Public Fields
+
+ public Vector3 Center;
+ public float Radius;
+
+ #endregion Public Fields
+
+
+ #region Constructors
+
+ public BoundingSphere(Vector3 center, float radius)
+ {
+ this.Center = center;
+ this.Radius = radius;
+ }
+
+ #endregion Constructors
+
+
+ #region Public Methods
+
+ public BoundingSphere Transform(Matrix matrix)
+ {
+ BoundingSphere sphere = new BoundingSphere();
+ sphere.Center = Vector3.Transform(this.Center, matrix);
+ sphere.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
+ return sphere;
+ }
+
+ public void Transform(ref Matrix matrix, out BoundingSphere result)
+ {
+ result.Center = Vector3.Transform(this.Center, matrix);
+ result.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
+ }
+
+ public ContainmentType Contains(BoundingBox box)
+ {
+ //check if all corner is in sphere
+ bool inside = true;
+ foreach (Vector3 corner in box.GetCorners())
+ {
+ if (this.Contains(corner) == ContainmentType.Disjoint)
+ {
+ inside = false;
+ break;
+ }
+ }
+
+ if (inside)
+ return ContainmentType.Contains;
+
+ //check if the distance from sphere center to cube face < radius
+ double dmin = 0;
+
+ if (Center.X < box.Min.X)
+ dmin += (Center.X - box.Min.X) * (Center.X - box.Min.X);
+
+ else if (Center.X > box.Max.X)
+ dmin += (Center.X - box.Max.X) * (Center.X - box.Max.X);
+
+ if (Center.Y < box.Min.Y)
+ dmin += (Center.Y - box.Min.Y) * (Center.Y - box.Min.Y);
+
+ else if (Center.Y > box.Max.Y)
+ dmin += (Center.Y - box.Max.Y) * (Center.Y - box.Max.Y);
+
+ if (Center.Z < box.Min.Z)
+ dmin += (Center.Z - box.Min.Z) * (Center.Z - box.Min.Z);
+
+ else if (Center.Z > box.Max.Z)
+ dmin += (Center.Z - box.Max.Z) * (Center.Z - box.Max.Z);
+
+ if (dmin <= Radius * Radius)
+ return ContainmentType.Intersects;
+
+ //else disjoint
+ return ContainmentType.Disjoint;
+
+ }
+
+ public void Contains(ref BoundingBox box, out ContainmentType result)
+ {
+ result = this.Contains(box);
+ }
+
+ public ContainmentType Contains(BoundingFrustum frustum)
+ {
+ //check if all corner is in sphere
+ bool inside = true;
+
+ Vector3[] corners = frustum.GetCorners();
+ foreach (Vector3 corner in corners)
+ {
+ if (this.Contains(corner) == ContainmentType.Disjoint)
+ {
+ inside = false;
+ break;
+ }
+ }
+ if (inside)
+ return ContainmentType.Contains;
+
+ //check if the distance from sphere center to frustrum face < radius
+ double dmin = 0;
+ //TODO : calcul dmin
+
+ if (dmin <= Radius * Radius)
+ return ContainmentType.Intersects;
+
+ //else disjoint
+ return ContainmentType.Disjoint;
+ }
+
+ public ContainmentType Contains(BoundingSphere sphere)
+ {
+ float val = Vector3.Distance(sphere.Center, Center);
+
+ if (val > sphere.Radius + Radius)
+ return ContainmentType.Disjoint;
+
+ else if (val <= Radius - sphere.Radius)
+ return ContainmentType.Contains;
+
+ else
+ return ContainmentType.Intersects;
+ }
+
+ public void Contains(ref BoundingSphere sphere, out ContainmentType result)
+ {
+ result = Contains(sphere);
+ }
+
+ public ContainmentType Contains(Vector3 point)
+ {
+ float distance = Vector3.Distance(point, Center);
+
+ if (distance > this.Radius)
+ return ContainmentType.Disjoint;
+
+ else if (distance < this.Radius)
+ return ContainmentType.Contains;
+
+ return ContainmentType.Intersects;
+ }
+
+ public void Contains(ref Vector3 point, out ContainmentType result)
+ {
+ result = Contains(point);
+ }
+
+ public static BoundingSphere CreateFromBoundingBox(BoundingBox box)
+ {
+ // Find the center of the box.
+ Vector3 center = new Vector3((box.Min.X + box.Max.X) / 2.0f,
+ (box.Min.Y + box.Max.Y) / 2.0f,
+ (box.Min.Z + box.Max.Z) / 2.0f);
+
+ // Find the distance between the center and one of the corners of the box.
+ float radius = Vector3.Distance(center, box.Max);
+
+ return new BoundingSphere(center, radius);
+ }
+
+ public static void CreateFromBoundingBox(ref BoundingBox box, out BoundingSphere result)
+ {
+ result = CreateFromBoundingBox(box);
+ }
+
+ public static BoundingSphere CreateFromFrustum(BoundingFrustum frustum)
+ {
+ return BoundingSphere.CreateFromPoints(frustum.GetCorners());
+ }
+
+ public static BoundingSphere CreateFromPoints(IEnumerable points)
+ {
+ if (points == null)
+ throw new ArgumentNullException("points");
+
+ float radius = 0;
+ Vector3 center = new Vector3();
+ // First, we'll find the center of gravity for the point 'cloud'.
+ int num_points = 0; // The number of points (there MUST be a better way to get this instead of counting the number of points one by one?)
+
+ foreach (Vector3 v in points)
+ {
+ center += v; // If we actually knew the number of points, we'd get better accuracy by adding v / num_points.
+ ++num_points;
+ }
+
+ center /= (float)num_points;
+
+ // Calculate the radius of the needed sphere (it equals the distance between the center and the point further away).
+ foreach (Vector3 v in points)
+ {
+ float distance = ((Vector3)(v - center)).Length();
+
+ if (distance > radius)
+ radius = distance;
+ }
+
+ return new BoundingSphere(center, radius);
+ }
+
+ public static BoundingSphere CreateMerged(BoundingSphere original, BoundingSphere additional)
+ {
+ Vector3 ocenterToaCenter = Vector3.Subtract(additional.Center, original.Center);
+ float distance = ocenterToaCenter.Length();
+ if (distance <= original.Radius + additional.Radius)//intersect
+ {
+ if (distance <= original.Radius - additional.Radius)//original contain additional
+ return original;
+ if (distance <= additional.Radius - original.Radius)//additional contain original
+ return additional;
+ }
+
+ //else find center of new sphere and radius
+ float leftRadius = Math.Max(original.Radius - distance, additional.Radius);
+ float Rightradius = Math.Max(original.Radius + distance, additional.Radius);
+ ocenterToaCenter = ocenterToaCenter + (((leftRadius - Rightradius) / (2 * ocenterToaCenter.Length())) * ocenterToaCenter);//oCenterToResultCenter
+
+ BoundingSphere result = new BoundingSphere();
+ result.Center = original.Center + ocenterToaCenter;
+ result.Radius = (leftRadius + Rightradius) / 2;
+ return result;
+ }
+
+ public static void CreateMerged(ref BoundingSphere original, ref BoundingSphere additional, out BoundingSphere result)
+ {
+ result = BoundingSphere.CreateMerged(original, additional);
+ }
+
+ public bool Equals(BoundingSphere other)
+ {
+ return this.Center == other.Center && this.Radius == other.Radius;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is BoundingSphere)
+ return this.Equals((BoundingSphere)obj);
+
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.Center.GetHashCode() + this.Radius.GetHashCode();
+ }
+
+ public bool Intersects(BoundingBox box)
+ {
+ return box.Intersects(this);
+ }
+
+ public void Intersects(ref BoundingBox box, out bool result)
+ {
+ result = Intersects(box);
+ }
+
+ public bool Intersects(BoundingFrustum frustum)
+ {
+ if (frustum == null)
+ throw new NullReferenceException();
+
+ throw new NotImplementedException();
+ }
+
+ public bool Intersects(BoundingSphere sphere)
+ {
+ float val = Vector3.Distance(sphere.Center, Center);
+ if (val > sphere.Radius + Radius)
+ return false;
+ return true;
+ }
+
+ public void Intersects(ref BoundingSphere sphere, out bool result)
+ {
+ result = Intersects(sphere);
+ }
+
+ public PlaneIntersectionType Intersects(Plane plane)
+ {
+ float distance = Vector3.Dot(plane.Normal, this.Center) + plane.D;
+ if (distance > this.Radius)
+ return PlaneIntersectionType.Front;
+ if (distance < -this.Radius)
+ return PlaneIntersectionType.Back;
+ //else it intersect
+ return PlaneIntersectionType.Intersecting;
+ }
+
+ public void Intersects(ref Plane plane, out PlaneIntersectionType result)
+ {
+ result = Intersects(plane);
+ }
+
+ public Nullable Intersects(Ray ray)
+ {
+ return ray.Intersects(this);
+ }
+
+ public void Intersects(ref Ray ray, out Nullable result)
+ {
+ result = Intersects(ray);
+ }
+
+ public static bool operator == (BoundingSphere a, BoundingSphere b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator != (BoundingSphere a, BoundingSphere b)
+ {
+ return !a.Equals(b);
+ }
+
+ public override string ToString()
+ {
+ return string.Format(CultureInfo.CurrentCulture, "{{Center:{0} Radius:{1}}}", this.Center.ToString(), this.Radius.ToString());
+ }
+
+ #endregion Public Methods
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Enums.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Enums.cs
new file mode 100644
index 0000000000..493e3abf00
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Enums.cs
@@ -0,0 +1,76 @@
+#region License
+/*
+MIT License
+Copyright © 2006 - 2007 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+
+ public enum CurveLoopType
+ {
+ Constant,
+ Cycle,
+ CycleOffset,
+ Oscillate,
+ Linear
+ }
+
+ public enum CurveContinuity
+ {
+ Smooth,
+ Step
+ }
+
+ public enum CurveTangent
+ {
+ Flat,
+ Linear,
+ Smooth
+ }
+
+ public enum TargetPlatform
+ {
+ Unknown,
+ Windows,
+ Xbox360,
+ Zune
+ }
+
+ public enum PlaneIntersectionType
+ {
+ Front,
+ Back,
+ Intersecting
+ }
+
+ public enum ContainmentType
+ {
+ Disjoint,
+ Contains,
+ Intersects
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/MathHelper.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/MathHelper.cs
new file mode 100644
index 0000000000..2b5022292d
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/MathHelper.cs
@@ -0,0 +1,150 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public static class MathHelper
+ {
+ public const float E = (float)Math.E;
+ public const float Log10E = 0.4342945f;
+ public const float Log2E = 1.442695f;
+ public const float Pi = (float)Math.PI;
+ public const float PiOver2 = (float)(Math.PI / 2.0);
+ public const float PiOver4 = (float)(Math.PI / 4.0);
+ public const float TwoPi = (float)(Math.PI * 2.0);
+
+ public static float Barycentric(float value1, float value2, float value3, float amount1, float amount2)
+ {
+ return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2;
+ }
+
+ public static float CatmullRom(float value1, float value2, float value3, float value4, float amount)
+ {
+ // Using formula from http://www.mvps.org/directx/articles/catmull/
+ // Internally using doubles not to lose precission
+ double amountSquared = amount * amount;
+ double amountCubed = amountSquared * amount;
+ return (float)(0.5f * (2.0f * value2 +
+ (value3 - value1) * amount +
+ (2.0f * value1 - 5.0f * value2 + 4.0f * value3 - value4) * amountSquared +
+ (3.0f * value2 - value1 - 3.0f * value3 + value4) * amountCubed));
+ }
+
+ public static float Clamp(float value, float min, float max)
+ {
+ return value > max ? max : (value < min ? min : value);
+ }
+
+ public static float Distance(float value1, float value2)
+ {
+ return Math.Abs(value1 - value2);
+ }
+
+ public static float Hermite(float value1, float tangent1, float value2, float tangent2, float amount)
+ {
+ // All transformed to double not to lose precission
+ // Otherwise, for high numbers of param:amount the result is NaN instead of Infinity
+ double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
+ double sCubed = s * s * s;
+ double sSquared = s * s;
+
+ if (amount == 0f)
+ result = value1;
+ else if (amount == 1f)
+ result = value2;
+ else
+ result = (2.0f * v1 - 2.0f * v2 + t2 + t1) * sCubed +
+ (3.0f * v2 - 3.0f * v1 - 2.0f * t1 - t2) * sSquared +
+ t1 * s +
+ v1;
+ return (float)result;
+ }
+
+
+ public static float Lerp(float value1, float value2, float amount)
+ {
+ return value1 + (value2 - value1) * amount;
+ }
+
+ public static float Max(float value1, float value2)
+ {
+ return Math.Max(value1, value2);
+ }
+
+ public static float Min(float value1, float value2)
+ {
+ return Math.Min(value1, value2);
+ }
+
+ public static float SmoothStep(float value1, float value2, float amount)
+ {
+ // It is expected that 0 < amount < 1
+ // If amount < 0, return value1
+ // If amount > 1, return value2
+ float result = MathHelper.Clamp(amount, 0f, 1f);
+ result = MathHelper.Hermite(value1, 0f, value2, 0f, result);
+ return result;
+ }
+
+ public static float ToDegrees(float radians)
+ {
+ // This method uses double precission internally,
+ // though it returns single float
+ // Factor = 180 / pi
+ return (float)(radians * 57.295779513082320876798154814105);
+ }
+
+ public static float ToRadians(float degrees)
+ {
+ // This method uses double precission internally,
+ // though it returns single float
+ // Factor = pi / 180
+ return (float)(degrees * 0.017453292519943295769236907684886);
+ }
+
+
+ public static float WrapAngle(float angle)
+ {
+ angle = (float)Math.IEEERemainder((double)angle, 6.2831854820251465); //2xPi precission is double
+ if (angle <= -3.141593f)
+ {
+ angle += 6.283185f;
+ return angle;
+ }
+ if (angle > 3.141593f)
+ {
+ angle -= 6.283185f;
+ }
+ return angle;
+ }
+
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Matrix.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Matrix.cs
new file mode 100644
index 0000000000..9238029847
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Matrix.cs
@@ -0,0 +1,1515 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct Matrix : IEquatable
+ {
+ #region Public Fields
+
+ public float M11;
+ public float M12;
+ public float M13;
+ public float M14;
+ public float M21;
+ public float M22;
+ public float M23;
+ public float M24;
+ public float M31;
+ public float M32;
+ public float M33;
+ public float M34;
+ public float M41;
+ public float M42;
+ public float M43;
+ public float M44;
+
+ #endregion Public Fields
+
+
+ #region Static Properties
+
+ private static Matrix identity = new Matrix(1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f);
+ public static Matrix Identity {
+ get { return identity; }
+ }
+
+ #endregion Static Properties
+
+
+ #region Public Properties
+
+ public Vector3 Backward {
+ get { return new Vector3(this.M31, this.M32, this.M33); }
+ set {
+ this.M31 = value.X;
+ this.M32 = value.Y;
+ this.M33 = value.Z;
+ }
+ }
+
+ public Vector3 Down {
+ get { return new Vector3(-this.M21, -this.M22, -this.M23); }
+ set {
+ this.M21 = -value.X;
+ this.M22 = -value.Y;
+ this.M23 = -value.Z;
+ }
+ }
+
+ public Vector3 Forward {
+ get { return new Vector3(-this.M31, -this.M32, -this.M33); }
+ set {
+ this.M31 = -value.X;
+ this.M32 = -value.Y;
+ this.M33 = -value.Z;
+ }
+ }
+
+ public Vector3 Left {
+ get { return new Vector3(-this.M11, -this.M12, -this.M13); }
+ set {
+ this.M11 = -value.X;
+ this.M12 = -value.Y;
+ this.M13 = -value.Z;
+ }
+ }
+
+ public Vector3 Right {
+ get { return new Vector3(this.M11, this.M12, this.M13); }
+ set {
+ this.M11 = value.X;
+ this.M12 = value.Y;
+ this.M13 = value.Z;
+ }
+ }
+
+ public Vector3 Translation {
+ get { return new Vector3(this.M41, this.M42, this.M43); }
+ set {
+ this.M41 = value.X;
+ this.M42 = value.Y;
+ this.M43 = value.Z;
+ }
+ }
+
+ public Vector3 Up {
+ get { return new Vector3(this.M21, this.M22, this.M23); }
+ set {
+ this.M21 = value.X;
+ this.M22 = value.Y;
+ this.M23 = value.Z;
+ }
+ }
+
+ #endregion Public Properties
+
+
+ #region Constructors
+ ///
+ /// Constructor for 4x4 Matrix
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public Matrix(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
+ float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
+ {
+ this.M11 = m11;
+ this.M12 = m12;
+ this.M13 = m13;
+ this.M14 = m14;
+ this.M21 = m21;
+ this.M22 = m22;
+ this.M23 = m23;
+ this.M24 = m24;
+ this.M31 = m31;
+ this.M32 = m32;
+ this.M33 = m33;
+ this.M34 = m34;
+ this.M41 = m41;
+ this.M42 = m42;
+ this.M43 = m43;
+ this.M44 = m44;
+ }
+
+ #endregion Constructors
+
+ #region Public Static Methods
+
+ public static Matrix CreateWorld(Vector3 position, Vector3 forward, Vector3 up)
+ {
+ Matrix ret;
+ CreateWorld(ref position, ref forward, ref up, out ret);
+ return ret;
+ }
+
+ public static void CreateWorld(ref Vector3 position, ref Vector3 forward, ref Vector3 up, out Matrix result)
+ {
+ Vector3 x, y, z;
+ Vector3.Normalize(ref forward, out z);
+ Vector3.Cross(ref forward, ref up, out x);
+ Vector3.Cross(ref x, ref forward, out y);
+ x.Normalize();
+ y.Normalize();
+
+ result = new Matrix();
+ result.Right = x;
+ result.Up = y;
+ result.Forward = z;
+ result.Translation = position;
+ result.M44 = 1f;
+ }
+
+ public static Matrix CreateShadow(Vector3 lightDirection, Plane plane)
+ {
+ Matrix ret;
+ CreateShadow(ref lightDirection, ref plane, out ret);
+ return ret;
+ }
+
+ public static void CreateShadow(ref Vector3 lightDirection, ref Plane plane, out Matrix result)
+ {
+ // Formula:
+ // http://msdn.microsoft.com/en-us/library/bb205364(v=VS.85).aspx
+
+ Plane p = Plane.Normalize(plane);
+ float d = Vector3.Dot(p.Normal, lightDirection);
+
+ result.M11 = -1 * p.Normal.X * lightDirection.X + d;
+ result.M12 = -1 * p.Normal.X * lightDirection.Y;
+ result.M13 = -1 * p.Normal.X * lightDirection.Z;
+ result.M14 = 0;
+ result.M21 = -1 * p.Normal.Y * lightDirection.X;
+ result.M22 = -1 * p.Normal.Y * lightDirection.Y + d;
+ result.M23 = -1 * p.Normal.Y * lightDirection.Z;
+ result.M24 = 0;
+ result.M31 = -1 * p.Normal.Z * lightDirection.X;
+ result.M32 = -1 * p.Normal.Z * lightDirection.Y;
+ result.M33 = -1 * p.Normal.Z * lightDirection.Z + d;
+ result.M34 = 0;
+ result.M41 = -1 * p.D * lightDirection.X;
+ result.M42 = -1 * p.D * lightDirection.Y;
+ result.M43 = -1 * p.D * lightDirection.Z;
+ result.M44 = d;
+ }
+
+ public static void CreateReflection(ref Plane value, out Matrix result)
+ {
+ // Formula:
+ // http://msdn.microsoft.com/en-us/library/bb205356(v=VS.85).aspx
+
+ Plane p = Plane.Normalize(value);
+
+ result.M11 = -2 * p.Normal.X * p.Normal.X + 1;
+ result.M12 = -2 * p.Normal.X * p.Normal.Y;
+ result.M13 = -2 * p.Normal.X * p.Normal.Z;
+ result.M14 = 0;
+ result.M21 = -2 * p.Normal.Y * p.Normal.X;
+ result.M22 = -2 * p.Normal.Y * p.Normal.Y + 1;
+ result.M23 = -2 * p.Normal.Y * p.Normal.Z;
+ result.M24 = 0;
+ result.M31 = -2 * p.Normal.Z * p.Normal.X;
+ result.M32 = -2 * p.Normal.Z * p.Normal.Y;
+ result.M33 = -2 * p.Normal.Z * p.Normal.Z + 1;
+ result.M34 = 0;
+ result.M41 = -2 * p.D * p.Normal.X;
+ result.M42 = -2 * p.D * p.Normal.Y;
+ result.M43 = -2 * p.D * p.Normal.Z;
+ result.M44 = 1;
+ }
+
+ public static Matrix CreateReflection(Plane value)
+ {
+ Matrix ret;
+ CreateReflection(ref value, out ret);
+ return ret;
+ }
+
+ public static Matrix CreateFromYawPitchRoll(float yaw, float pitch, float roll)
+ {
+ Matrix matrix;
+ Quaternion quaternion;
+ Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll, out quaternion);
+ CreateFromQuaternion(ref quaternion, out matrix);
+ return matrix;
+ }
+
+ public static void CreateFromYawPitchRoll(float yaw, float pitch, float roll, out Matrix result)
+ {
+ Quaternion quaternion;
+ Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll, out quaternion);
+ CreateFromQuaternion(ref quaternion, out result);
+ }
+
+ public static void Transform(ref Matrix value, ref Quaternion rotation, out Matrix result)
+ {
+ Matrix matrix = CreateFromQuaternion(rotation);
+ Matrix.Multiply(ref value, ref matrix, out result);
+ }
+
+ public static Matrix Transform(Matrix value, Quaternion rotation)
+ {
+ Matrix ret;
+ Transform(ref value, ref rotation, out ret);
+ return ret;
+ }
+
+ public bool Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation)
+ {
+ translation.X = this.M41;
+ translation.Y = this.M42;
+ translation.Z = this.M43;
+ float xs, ys, zs;
+
+ if (Math.Sign(M11 * M12 * M13 * M14) < 0)
+ xs = -1f;
+ else
+ xs = 1f;
+
+ if (Math.Sign(M21 * M22 * M23 * M24) < 0)
+ ys = -1f;
+ else
+ ys = 1f;
+
+ if (Math.Sign(M31 * M32 * M33 * M34) < 0)
+ zs = -1f;
+ else
+ zs = 1f;
+
+ scale.X = xs * (float)Math.Sqrt(this.M11 * this.M11 + this.M12 * this.M12 + this.M13 * this.M13);
+ scale.Y = ys * (float)Math.Sqrt(this.M21 * this.M21 + this.M22 * this.M22 + this.M23 * this.M23);
+ scale.Z = zs * (float)Math.Sqrt(this.M31 * this.M31 + this.M32 * this.M32 + this.M33 * this.M33);
+
+ if (scale.X == 0.0 || scale.Y == 0.0 || scale.Z == 0.0)
+ {
+ rotation = Quaternion.Identity;
+ return false;
+ }
+
+ Matrix m1 = new Matrix(this.M11/scale.X, M12/scale.X, M13/scale.X, 0,
+ this.M21/scale.Y, M22/scale.Y, M23/scale.Y, 0,
+ this.M31/scale.Z, M32/scale.Z, M33/scale.Z, 0,
+ 0, 0, 0, 1);
+
+ rotation = Quaternion.CreateFromRotationMatrix(m1);
+ return true;
+ }
+
+ ///
+ /// Adds second matrix to the first.
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public static Matrix Add(Matrix matrix1, Matrix matrix2)
+ {
+ matrix1.M11 += matrix2.M11;
+ matrix1.M12 += matrix2.M12;
+ matrix1.M13 += matrix2.M13;
+ matrix1.M14 += matrix2.M14;
+ matrix1.M21 += matrix2.M21;
+ matrix1.M22 += matrix2.M22;
+ matrix1.M23 += matrix2.M23;
+ matrix1.M24 += matrix2.M24;
+ matrix1.M31 += matrix2.M31;
+ matrix1.M32 += matrix2.M32;
+ matrix1.M33 += matrix2.M33;
+ matrix1.M34 += matrix2.M34;
+ matrix1.M41 += matrix2.M41;
+ matrix1.M42 += matrix2.M42;
+ matrix1.M43 += matrix2.M43;
+ matrix1.M44 += matrix2.M44;
+ return matrix1;
+ }
+
+
+ ///
+ /// Adds two Matrix and save to the result Matrix
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public static void Add(ref Matrix matrix1, ref Matrix matrix2, out Matrix result)
+ {
+ result.M11 = matrix1.M11 + matrix2.M11;
+ result.M12 = matrix1.M12 + matrix2.M12;
+ result.M13 = matrix1.M13 + matrix2.M13;
+ result.M14 = matrix1.M14 + matrix2.M14;
+ result.M21 = matrix1.M21 + matrix2.M21;
+ result.M22 = matrix1.M22 + matrix2.M22;
+ result.M23 = matrix1.M23 + matrix2.M23;
+ result.M24 = matrix1.M24 + matrix2.M24;
+ result.M31 = matrix1.M31 + matrix2.M31;
+ result.M32 = matrix1.M32 + matrix2.M32;
+ result.M33 = matrix1.M33 + matrix2.M33;
+ result.M34 = matrix1.M34 + matrix2.M34;
+ result.M41 = matrix1.M41 + matrix2.M41;
+ result.M42 = matrix1.M42 + matrix2.M42;
+ result.M43 = matrix1.M43 + matrix2.M43;
+ result.M44 = matrix1.M44 + matrix2.M44;
+ }
+
+
+ public static Matrix CreateBillboard(Vector3 objectPosition, Vector3 cameraPosition,
+ Vector3 cameraUpVector, Nullable cameraForwardVector)
+ {
+ Matrix ret;
+ CreateBillboard(ref objectPosition, ref cameraPosition, ref cameraUpVector, cameraForwardVector, out ret);
+ return ret;
+ }
+
+ public static void CreateBillboard(ref Vector3 objectPosition, ref Vector3 cameraPosition,
+ ref Vector3 cameraUpVector, Vector3? cameraForwardVector, out Matrix result)
+ {
+ Vector3 translation = objectPosition - cameraPosition;
+ Vector3 backwards, right, up;
+ Vector3.Normalize(ref translation, out backwards);
+ Vector3.Normalize(ref cameraUpVector, out up);
+ Vector3.Cross(ref backwards, ref up, out right);
+ Vector3.Cross(ref backwards, ref right, out up);
+ result = Matrix.Identity;
+ result.Backward = backwards;
+ result.Right = right;
+ result.Up = up;
+ result.Translation = translation;
+ }
+
+ public static Matrix CreateConstrainedBillboard(Vector3 objectPosition, Vector3 cameraPosition,
+ Vector3 rotateAxis, Nullable cameraForwardVector, Nullable objectForwardVector)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static void CreateConstrainedBillboard(ref Vector3 objectPosition, ref Vector3 cameraPosition,
+ ref Vector3 rotateAxis, Vector3? cameraForwardVector, Vector3? objectForwardVector, out Matrix result)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static Matrix CreateFromAxisAngle(Vector3 axis, float angle)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static void CreateFromAxisAngle(ref Vector3 axis, float angle, out Matrix result)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static Matrix CreateFromQuaternion(Quaternion quaternion)
+ {
+ Matrix ret;
+ CreateFromQuaternion(ref quaternion, out ret);
+ return ret;
+ }
+
+
+ public static void CreateFromQuaternion(ref Quaternion quaternion, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M11 = 1 - 2 * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
+ result.M12 = 2 * (quaternion.X * quaternion.Y + quaternion.W * quaternion.Z);
+ result.M13 = 2 * (quaternion.X * quaternion.Z - quaternion.W * quaternion.Y);
+ result.M21 = 2 * (quaternion.X * quaternion.Y - quaternion.W * quaternion.Z);
+ result.M22 = 1 - 2 * (quaternion.X * quaternion.X + quaternion.Z * quaternion.Z);
+ result.M23 = 2 * (quaternion.Y * quaternion.Z + quaternion.W * quaternion.X);
+ result.M31 = 2 * (quaternion.X * quaternion.Z + quaternion.W * quaternion.Y);
+ result.M32 = 2 * (quaternion.Y * quaternion.Z - quaternion.W * quaternion.X);
+ result.M33 = 1 - 2 * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y);
+ }
+
+
+ public static Matrix CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector)
+ {
+ Matrix ret;
+ CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector, out ret);
+ return ret;
+ }
+
+
+ public static void CreateLookAt(ref Vector3 cameraPosition, ref Vector3 cameraTarget, ref Vector3 cameraUpVector, out Matrix result)
+ {
+ // http://msdn.microsoft.com/en-us/library/bb205343(v=VS.85).aspx
+
+ Vector3 vz = Vector3.Normalize(cameraPosition - cameraTarget);
+ Vector3 vx = Vector3.Normalize(Vector3.Cross(cameraUpVector, vz));
+ Vector3 vy = Vector3.Cross(vz, vx);
+ result = Matrix.Identity;
+ result.M11 = vx.X;
+ result.M12 = vy.X;
+ result.M13 = vz.X;
+ result.M21 = vx.Y;
+ result.M22 = vy.Y;
+ result.M23 = vz.Y;
+ result.M31 = vx.Z;
+ result.M32 = vy.Z;
+ result.M33 = vz.Z;
+ result.M41 = -Vector3.Dot(vx, cameraPosition);
+ result.M42 = -Vector3.Dot(vy, cameraPosition);
+ result.M43 = -Vector3.Dot(vz, cameraPosition);
+ }
+
+ public static Matrix CreateOrthographic(float width, float height, float zNearPlane, float zFarPlane)
+ {
+ Matrix ret;
+ CreateOrthographic(width, height, zNearPlane, zFarPlane, out ret);
+ return ret;
+ }
+
+
+ public static void CreateOrthographic(float width, float height, float zNearPlane, float zFarPlane, out Matrix result)
+ {
+ result.M11 = 2 / width;
+ result.M12 = 0;
+ result.M13 = 0;
+ result.M14 = 0;
+ result.M21 = 0;
+ result.M22 = 2 / height;
+ result.M23 = 0;
+ result.M24 = 0;
+ result.M31 = 0;
+ result.M32 = 0;
+ result.M33 = 1 / (zNearPlane - zFarPlane);
+ result.M34 = 0;
+ result.M41 = 0;
+ result.M42 = 0;
+ result.M43 = zNearPlane / (zNearPlane - zFarPlane);
+ result.M44 = 1;
+ }
+
+
+ public static Matrix CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNearPlane, float zFarPlane)
+ {
+ Matrix ret;
+ CreateOrthographicOffCenter(left, right, bottom, top, zNearPlane, zFarPlane, out ret);
+ return ret;
+ }
+
+
+ public static void CreateOrthographicOffCenter(float left, float right, float bottom, float top,
+ float zNearPlane, float zFarPlane, out Matrix result)
+ {
+ result.M11 = 2 / (right - left);
+ result.M12 = 0;
+ result.M13 = 0;
+ result.M14 = 0;
+ result.M21 = 0;
+ result.M22 = 2 / (top - bottom);
+ result.M23 = 0;
+ result.M24 = 0;
+ result.M31 = 0;
+ result.M32 = 0;
+ result.M33 = 1 / (zNearPlane - zFarPlane);
+ result.M34 = 0;
+ result.M41 = (left + right) / (left - right);
+ result.M42 = (bottom + top) / (bottom - top);
+ result.M43 = zNearPlane / (zNearPlane - zFarPlane);
+ result.M44 = 1;
+ }
+
+
+ public static Matrix CreatePerspective(float width, float height, float zNearPlane, float zFarPlane)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static void CreatePerspective(float width, float height, float zNearPlane, float zFarPlane, out Matrix result)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static Matrix CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
+ {
+ Matrix ret;
+ CreatePerspectiveFieldOfView(fieldOfView, aspectRatio, nearPlaneDistance, farPlaneDistance, out ret);
+ return ret;
+ }
+
+
+ public static void CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance, out Matrix result)
+ {
+ // http://msdn.microsoft.com/en-us/library/bb205351(v=VS.85).aspx
+ // http://msdn.microsoft.com/en-us/library/bb195665.aspx
+
+ result = new Matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ if (fieldOfView < 0 || fieldOfView > 3.14159262f)
+ throw new ArgumentOutOfRangeException("fieldOfView", "fieldOfView takes a value between 0 and Pi (180 degrees) in radians.");
+
+ if (nearPlaneDistance <= 0.0f)
+ throw new ArgumentOutOfRangeException("nearPlaneDistance", "You should specify positive value for nearPlaneDistance.");
+
+ if (farPlaneDistance <= 0.0f)
+ throw new ArgumentOutOfRangeException("farPlaneDistance", "You should specify positive value for farPlaneDistance.");
+
+ if (farPlaneDistance <= nearPlaneDistance)
+ throw new ArgumentOutOfRangeException("nearPlaneDistance", "Near plane distance is larger than Far plane distance. Near plane distance must be smaller than Far plane distance.");
+
+ float yscale = (float)1 / (float)Math.Tan(fieldOfView / 2);
+ float xscale = yscale / aspectRatio;
+
+ result.M11 = xscale;
+ result.M22 = yscale;
+ result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
+ result.M34 = -1;
+ result.M43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
+ }
+
+
+ public static Matrix CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float zNearPlane, float zFarPlane)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static void CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float nearPlaneDistance, float farPlaneDistance, out Matrix result)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static Matrix CreateRotationX(float radians)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M22 = (float)Math.Cos(radians);
+ returnMatrix.M23 = (float)Math.Sin(radians);
+ returnMatrix.M32 = -returnMatrix.M23;
+ returnMatrix.M33 = returnMatrix.M22;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateRotationX(float radians, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M22 = (float)Math.Cos(radians);
+ result.M23 = (float)Math.Sin(radians);
+ result.M32 = -result.M23;
+ result.M33 = result.M22;
+ }
+
+
+ public static Matrix CreateRotationY(float radians)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M11 = (float)Math.Cos(radians);
+ returnMatrix.M13 = (float)Math.Sin(radians);
+ returnMatrix.M31 = -returnMatrix.M13;
+ returnMatrix.M33 = returnMatrix.M11;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateRotationY(float radians, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M11 = (float)Math.Cos(radians);
+ result.M13 = (float)Math.Sin(radians);
+ result.M31 = -result.M13;
+ result.M33 = result.M11;
+ }
+
+
+ public static Matrix CreateRotationZ(float radians)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M11 = (float)Math.Cos(radians);
+ returnMatrix.M12 = (float)Math.Sin(radians);
+ returnMatrix.M21 = -returnMatrix.M12;
+ returnMatrix.M22 = returnMatrix.M11;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateRotationZ(float radians, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M11 = (float)Math.Cos(radians);
+ result.M12 = (float)Math.Sin(radians);
+ result.M21 = -result.M12;
+ result.M22 = result.M11;
+ }
+
+
+ public static Matrix CreateScale(float scale)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M11 = scale;
+ returnMatrix.M22 = scale;
+ returnMatrix.M33 = scale;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateScale(float scale, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M11 = scale;
+ result.M22 = scale;
+ result.M33 = scale;
+ }
+
+
+ public static Matrix CreateScale(float xScale, float yScale, float zScale)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M11 = xScale;
+ returnMatrix.M22 = yScale;
+ returnMatrix.M33 = zScale;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateScale(float xScale, float yScale, float zScale, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M11 = xScale;
+ result.M22 = yScale;
+ result.M33 = zScale;
+ }
+
+
+ public static Matrix CreateScale(Vector3 scales)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M11 = scales.X;
+ returnMatrix.M22 = scales.Y;
+ returnMatrix.M33 = scales.Z;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateScale(ref Vector3 scales, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M11 = scales.X;
+ result.M22 = scales.Y;
+ result.M33 = scales.Z;
+ }
+
+
+ public static Matrix CreateTranslation(float xPosition, float yPosition, float zPosition)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M41 = xPosition;
+ returnMatrix.M42 = yPosition;
+ returnMatrix.M43 = zPosition;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateTranslation(float xPosition, float yPosition, float zPosition, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M41 = xPosition;
+ result.M42 = yPosition;
+ result.M43 = zPosition;
+ }
+
+
+ public static Matrix CreateTranslation(Vector3 position)
+ {
+ Matrix returnMatrix = Matrix.Identity;
+
+ returnMatrix.M41 = position.X;
+ returnMatrix.M42 = position.Y;
+ returnMatrix.M43 = position.Z;
+
+ return returnMatrix;
+ }
+
+
+ public static void CreateTranslation(ref Vector3 position, out Matrix result)
+ {
+ result = Matrix.Identity;
+
+ result.M41 = position.X;
+ result.M42 = position.Y;
+ result.M43 = position.Z;
+ }
+
+ public static Matrix Divide(Matrix matrix1, Matrix matrix2)
+ {
+ Matrix inverse = Matrix.Invert(matrix2), result;
+
+ result.M11 = matrix1.M11 * inverse.M11 + matrix1.M12 * inverse.M21 + matrix1.M13 * inverse.M31 + matrix1.M14 * inverse.M41;
+ result.M12 = matrix1.M11 * inverse.M12 + matrix1.M12 * inverse.M22 + matrix1.M13 * inverse.M32 + matrix1.M14 * inverse.M42;
+ result.M13 = matrix1.M11 * inverse.M13 + matrix1.M12 * inverse.M23 + matrix1.M13 * inverse.M33 + matrix1.M14 * inverse.M43;
+ result.M14 = matrix1.M11 * inverse.M14 + matrix1.M12 * inverse.M24 + matrix1.M13 * inverse.M34 + matrix1.M14 * inverse.M44;
+
+ result.M21 = matrix1.M21 * inverse.M11 + matrix1.M22 * inverse.M21 + matrix1.M23 * inverse.M31 + matrix1.M24 * inverse.M41;
+ result.M22 = matrix1.M21 * inverse.M12 + matrix1.M22 * inverse.M22 + matrix1.M23 * inverse.M32 + matrix1.M24 * inverse.M42;
+ result.M23 = matrix1.M21 * inverse.M13 + matrix1.M22 * inverse.M23 + matrix1.M23 * inverse.M33 + matrix1.M24 * inverse.M43;
+ result.M24 = matrix1.M21 * inverse.M14 + matrix1.M22 * inverse.M24 + matrix1.M23 * inverse.M34 + matrix1.M24 * inverse.M44;
+
+ result.M31 = matrix1.M31 * inverse.M11 + matrix1.M32 * inverse.M21 + matrix1.M33 * inverse.M31 + matrix1.M34 * inverse.M41;
+ result.M32 = matrix1.M31 * inverse.M12 + matrix1.M32 * inverse.M22 + matrix1.M33 * inverse.M32 + matrix1.M34 * inverse.M42;
+ result.M33 = matrix1.M31 * inverse.M13 + matrix1.M32 * inverse.M23 + matrix1.M33 * inverse.M33 + matrix1.M34 * inverse.M43;
+ result.M34 = matrix1.M31 * inverse.M14 + matrix1.M32 * inverse.M24 + matrix1.M33 * inverse.M34 + matrix1.M34 * inverse.M44;
+
+ result.M41 = matrix1.M41 * inverse.M11 + matrix1.M42 * inverse.M21 + matrix1.M43 * inverse.M31 + matrix1.M44 * inverse.M41;
+ result.M42 = matrix1.M41 * inverse.M12 + matrix1.M42 * inverse.M22 + matrix1.M43 * inverse.M32 + matrix1.M44 * inverse.M42;
+ result.M43 = matrix1.M41 * inverse.M13 + matrix1.M42 * inverse.M23 + matrix1.M43 * inverse.M33 + matrix1.M44 * inverse.M43;
+ result.M44 = matrix1.M41 * inverse.M14 + matrix1.M42 * inverse.M24 + matrix1.M43 * inverse.M34 + matrix1.M44 * inverse.M44;
+
+ return result;
+ }
+
+
+ public static void Divide(ref Matrix matrix1, ref Matrix matrix2, out Matrix result)
+ {
+ Matrix inverse = Matrix.Invert(matrix2);
+ result.M11 = matrix1.M11 * inverse.M11 + matrix1.M12 * inverse.M21 + matrix1.M13 * inverse.M31 + matrix1.M14 * inverse.M41;
+ result.M12 = matrix1.M11 * inverse.M12 + matrix1.M12 * inverse.M22 + matrix1.M13 * inverse.M32 + matrix1.M14 * inverse.M42;
+ result.M13 = matrix1.M11 * inverse.M13 + matrix1.M12 * inverse.M23 + matrix1.M13 * inverse.M33 + matrix1.M14 * inverse.M43;
+ result.M14 = matrix1.M11 * inverse.M14 + matrix1.M12 * inverse.M24 + matrix1.M13 * inverse.M34 + matrix1.M14 * inverse.M44;
+
+ result.M21 = matrix1.M21 * inverse.M11 + matrix1.M22 * inverse.M21 + matrix1.M23 * inverse.M31 + matrix1.M24 * inverse.M41;
+ result.M22 = matrix1.M21 * inverse.M12 + matrix1.M22 * inverse.M22 + matrix1.M23 * inverse.M32 + matrix1.M24 * inverse.M42;
+ result.M23 = matrix1.M21 * inverse.M13 + matrix1.M22 * inverse.M23 + matrix1.M23 * inverse.M33 + matrix1.M24 * inverse.M43;
+ result.M24 = matrix1.M21 * inverse.M14 + matrix1.M22 * inverse.M24 + matrix1.M23 * inverse.M34 + matrix1.M24 * inverse.M44;
+
+ result.M31 = matrix1.M31 * inverse.M11 + matrix1.M32 * inverse.M21 + matrix1.M33 * inverse.M31 + matrix1.M34 * inverse.M41;
+ result.M32 = matrix1.M31 * inverse.M12 + matrix1.M32 * inverse.M22 + matrix1.M33 * inverse.M32 + matrix1.M34 * inverse.M42;
+ result.M33 = matrix1.M31 * inverse.M13 + matrix1.M32 * inverse.M23 + matrix1.M33 * inverse.M33 + matrix1.M34 * inverse.M43;
+ result.M34 = matrix1.M31 * inverse.M14 + matrix1.M32 * inverse.M24 + matrix1.M33 * inverse.M34 + matrix1.M34 * inverse.M44;
+
+ result.M41 = matrix1.M41 * inverse.M11 + matrix1.M42 * inverse.M21 + matrix1.M43 * inverse.M31 + matrix1.M44 * inverse.M41;
+ result.M42 = matrix1.M41 * inverse.M12 + matrix1.M42 * inverse.M22 + matrix1.M43 * inverse.M32 + matrix1.M44 * inverse.M42;
+ result.M43 = matrix1.M41 * inverse.M13 + matrix1.M42 * inverse.M23 + matrix1.M43 * inverse.M33 + matrix1.M44 * inverse.M43;
+ result.M44 = matrix1.M41 * inverse.M14 + matrix1.M42 * inverse.M24 + matrix1.M43 * inverse.M34 + matrix1.M44 * inverse.M44;
+ }
+
+
+ public static Matrix Divide(Matrix matrix1, float divider)
+ {
+ float inverseDivider = 1.0f / divider;
+
+ matrix1.M11 = matrix1.M11 * inverseDivider;
+ matrix1.M12 = matrix1.M12 * inverseDivider;
+ matrix1.M13 = matrix1.M13 * inverseDivider;
+ matrix1.M14 = matrix1.M14 * inverseDivider;
+ matrix1.M21 = matrix1.M21 * inverseDivider;
+ matrix1.M22 = matrix1.M22 * inverseDivider;
+ matrix1.M23 = matrix1.M23 * inverseDivider;
+ matrix1.M24 = matrix1.M24 * inverseDivider;
+ matrix1.M31 = matrix1.M31 * inverseDivider;
+ matrix1.M32 = matrix1.M32 * inverseDivider;
+ matrix1.M33 = matrix1.M33 * inverseDivider;
+ matrix1.M34 = matrix1.M34 * inverseDivider;
+ matrix1.M41 = matrix1.M41 * inverseDivider;
+ matrix1.M42 = matrix1.M42 * inverseDivider;
+ matrix1.M43 = matrix1.M43 * inverseDivider;
+ matrix1.M44 = matrix1.M44 * inverseDivider;
+
+ return matrix1;
+ }
+
+
+ public static void Divide(ref Matrix matrix1, float divider, out Matrix result)
+ {
+ float inverseDivider = 1.0f / divider;
+ result.M11 = matrix1.M11 * inverseDivider;
+ result.M12 = matrix1.M12 * inverseDivider;
+ result.M13 = matrix1.M13 * inverseDivider;
+ result.M14 = matrix1.M14 * inverseDivider;
+ result.M21 = matrix1.M21 * inverseDivider;
+ result.M22 = matrix1.M22 * inverseDivider;
+ result.M23 = matrix1.M23 * inverseDivider;
+ result.M24 = matrix1.M24 * inverseDivider;
+ result.M31 = matrix1.M31 * inverseDivider;
+ result.M32 = matrix1.M32 * inverseDivider;
+ result.M33 = matrix1.M33 * inverseDivider;
+ result.M34 = matrix1.M34 * inverseDivider;
+ result.M41 = matrix1.M41 * inverseDivider;
+ result.M42 = matrix1.M42 * inverseDivider;
+ result.M43 = matrix1.M43 * inverseDivider;
+ result.M44 = matrix1.M44 * inverseDivider;
+ }
+
+ public static Matrix Invert(Matrix matrix)
+ {
+ Invert(ref matrix, out matrix);
+ return matrix;
+ }
+
+
+ public static void Invert(ref Matrix matrix, out Matrix result)
+ {
+ //
+ // Use Laplace expansion theorem to calculate the inverse of a 4x4 matrix
+ //
+ // 1. Calculate the 2x2 determinants needed and the 4x4 determinant based on the 2x2 determinants
+ // 2. Create the adjugate matrix, which satisfies: A * adj(A) = det(A) * I
+ // 3. Divide adjugate matrix with the determinant to find the inverse
+
+ float det1 = matrix.M11 * matrix.M22 - matrix.M12 * matrix.M21;
+ float det2 = matrix.M11 * matrix.M23 - matrix.M13 * matrix.M21;
+ float det3 = matrix.M11 * matrix.M24 - matrix.M14 * matrix.M21;
+ float det4 = matrix.M12 * matrix.M23 - matrix.M13 * matrix.M22;
+ float det5 = matrix.M12 * matrix.M24 - matrix.M14 * matrix.M22;
+ float det6 = matrix.M13 * matrix.M24 - matrix.M14 * matrix.M23;
+ float det7 = matrix.M31 * matrix.M42 - matrix.M32 * matrix.M41;
+ float det8 = matrix.M31 * matrix.M43 - matrix.M33 * matrix.M41;
+ float det9 = matrix.M31 * matrix.M44 - matrix.M34 * matrix.M41;
+ float det10 = matrix.M32 * matrix.M43 - matrix.M33 * matrix.M42;
+ float det11 = matrix.M32 * matrix.M44 - matrix.M34 * matrix.M42;
+ float det12 = matrix.M33 * matrix.M44 - matrix.M34 * matrix.M43;
+
+ float detMatrix = (float)(det1*det12 - det2*det11 + det3*det10 + det4*det9 - det5*det8 + det6*det7);
+
+ float invDetMatrix = 1f / detMatrix;
+
+ Matrix ret; // Allow for matrix and result to point to the same structure
+
+ ret.M11 = (matrix.M22*det12 - matrix.M23*det11 + matrix.M24*det10) * invDetMatrix;
+ ret.M12 = (-matrix.M12*det12 + matrix.M13*det11 - matrix.M14*det10) * invDetMatrix;
+ ret.M13 = (matrix.M42*det6 - matrix.M43*det5 + matrix.M44*det4) * invDetMatrix;
+ ret.M14 = (-matrix.M32*det6 + matrix.M33*det5 - matrix.M34*det4) * invDetMatrix;
+ ret.M21 = (-matrix.M21*det12 + matrix.M23*det9 - matrix.M24*det8) * invDetMatrix;
+ ret.M22 = (matrix.M11*det12 - matrix.M13*det9 + matrix.M14*det8) * invDetMatrix;
+ ret.M23 = (-matrix.M41*det6 + matrix.M43*det3 - matrix.M44*det2) * invDetMatrix;
+ ret.M24 = (matrix.M31*det6 - matrix.M33*det3 + matrix.M34*det2) * invDetMatrix;
+ ret.M31 = (matrix.M21*det11 - matrix.M22*det9 + matrix.M24*det7) * invDetMatrix;
+ ret.M32 = (-matrix.M11*det11 + matrix.M12*det9 - matrix.M14*det7) * invDetMatrix;
+ ret.M33 = (matrix.M41*det5 - matrix.M42*det3 + matrix.M44*det1) * invDetMatrix;
+ ret.M34 = (-matrix.M31*det5 + matrix.M32*det3 - matrix.M34*det1) * invDetMatrix;
+ ret.M41 = (-matrix.M21*det10 + matrix.M22*det8 - matrix.M23*det7) * invDetMatrix;
+ ret.M42 = (matrix.M11*det10 - matrix.M12*det8 + matrix.M13*det7) * invDetMatrix;
+ ret.M43 = (-matrix.M41*det4 + matrix.M42*det2 - matrix.M43*det1) * invDetMatrix;
+ ret.M44 = (matrix.M31*det4 - matrix.M32*det2 + matrix.M33*det1) * invDetMatrix;
+
+ result = ret;
+ }
+
+
+ public static Matrix Lerp(Matrix matrix1, Matrix matrix2, float amount)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public static void Lerp(ref Matrix matrix1, ref Matrix matrix2, float amount, out Matrix result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Matrix Multiply(Matrix matrix1, Matrix matrix2)
+ {
+ Matrix result;
+
+ result.M11 = matrix1.M11 * matrix2.M11 + matrix1.M12 * matrix2.M21 + matrix1.M13 * matrix2.M31 + matrix1.M14 * matrix2.M41;
+ result.M12 = matrix1.M11 * matrix2.M12 + matrix1.M12 * matrix2.M22 + matrix1.M13 * matrix2.M32 + matrix1.M14 * matrix2.M42;
+ result.M13 = matrix1.M11 * matrix2.M13 + matrix1.M12 * matrix2.M23 + matrix1.M13 * matrix2.M33 + matrix1.M14 * matrix2.M43;
+ result.M14 = matrix1.M11 * matrix2.M14 + matrix1.M12 * matrix2.M24 + matrix1.M13 * matrix2.M34 + matrix1.M14 * matrix2.M44;
+
+ result.M21 = matrix1.M21 * matrix2.M11 + matrix1.M22 * matrix2.M21 + matrix1.M23 * matrix2.M31 + matrix1.M24 * matrix2.M41;
+ result.M22 = matrix1.M21 * matrix2.M12 + matrix1.M22 * matrix2.M22 + matrix1.M23 * matrix2.M32 + matrix1.M24 * matrix2.M42;
+ result.M23 = matrix1.M21 * matrix2.M13 + matrix1.M22 * matrix2.M23 + matrix1.M23 * matrix2.M33 + matrix1.M24 * matrix2.M43;
+ result.M24 = matrix1.M21 * matrix2.M14 + matrix1.M22 * matrix2.M24 + matrix1.M23 * matrix2.M34 + matrix1.M24 * matrix2.M44;
+
+ result.M31 = matrix1.M31 * matrix2.M11 + matrix1.M32 * matrix2.M21 + matrix1.M33 * matrix2.M31 + matrix1.M34 * matrix2.M41;
+ result.M32 = matrix1.M31 * matrix2.M12 + matrix1.M32 * matrix2.M22 + matrix1.M33 * matrix2.M32 + matrix1.M34 * matrix2.M42;
+ result.M33 = matrix1.M31 * matrix2.M13 + matrix1.M32 * matrix2.M23 + matrix1.M33 * matrix2.M33 + matrix1.M34 * matrix2.M43;
+ result.M34 = matrix1.M31 * matrix2.M14 + matrix1.M32 * matrix2.M24 + matrix1.M33 * matrix2.M34 + matrix1.M34 * matrix2.M44;
+
+ result.M41 = matrix1.M41 * matrix2.M11 + matrix1.M42 * matrix2.M21 + matrix1.M43 * matrix2.M31 + matrix1.M44 * matrix2.M41;
+ result.M42 = matrix1.M41 * matrix2.M12 + matrix1.M42 * matrix2.M22 + matrix1.M43 * matrix2.M32 + matrix1.M44 * matrix2.M42;
+ result.M43 = matrix1.M41 * matrix2.M13 + matrix1.M42 * matrix2.M23 + matrix1.M43 * matrix2.M33 + matrix1.M44 * matrix2.M43;
+ result.M44 = matrix1.M41 * matrix2.M14 + matrix1.M42 * matrix2.M24 + matrix1.M43 * matrix2.M34 + matrix1.M44 * matrix2.M44;
+
+ return result;
+ }
+
+
+ public static void Multiply(ref Matrix matrix1, ref Matrix matrix2, out Matrix result)
+ {
+ result.M11 = matrix1.M11 * matrix2.M11 + matrix1.M12 * matrix2.M21 + matrix1.M13 * matrix2.M31 + matrix1.M14 * matrix2.M41;
+ result.M12 = matrix1.M11 * matrix2.M12 + matrix1.M12 * matrix2.M22 + matrix1.M13 * matrix2.M32 + matrix1.M14 * matrix2.M42;
+ result.M13 = matrix1.M11 * matrix2.M13 + matrix1.M12 * matrix2.M23 + matrix1.M13 * matrix2.M33 + matrix1.M14 * matrix2.M43;
+ result.M14 = matrix1.M11 * matrix2.M14 + matrix1.M12 * matrix2.M24 + matrix1.M13 * matrix2.M34 + matrix1.M14 * matrix2.M44;
+
+ result.M21 = matrix1.M21 * matrix2.M11 + matrix1.M22 * matrix2.M21 + matrix1.M23 * matrix2.M31 + matrix1.M24 * matrix2.M41;
+ result.M22 = matrix1.M21 * matrix2.M12 + matrix1.M22 * matrix2.M22 + matrix1.M23 * matrix2.M32 + matrix1.M24 * matrix2.M42;
+ result.M23 = matrix1.M21 * matrix2.M13 + matrix1.M22 * matrix2.M23 + matrix1.M23 * matrix2.M33 + matrix1.M24 * matrix2.M43;
+ result.M24 = matrix1.M21 * matrix2.M14 + matrix1.M22 * matrix2.M24 + matrix1.M23 * matrix2.M34 + matrix1.M24 * matrix2.M44;
+
+ result.M31 = matrix1.M31 * matrix2.M11 + matrix1.M32 * matrix2.M21 + matrix1.M33 * matrix2.M31 + matrix1.M34 * matrix2.M41;
+ result.M32 = matrix1.M31 * matrix2.M12 + matrix1.M32 * matrix2.M22 + matrix1.M33 * matrix2.M32 + matrix1.M34 * matrix2.M42;
+ result.M33 = matrix1.M31 * matrix2.M13 + matrix1.M32 * matrix2.M23 + matrix1.M33 * matrix2.M33 + matrix1.M34 * matrix2.M43;
+ result.M34 = matrix1.M31 * matrix2.M14 + matrix1.M32 * matrix2.M24 + matrix1.M33 * matrix2.M34 + matrix1.M34 * matrix2.M44;
+
+ result.M41 = matrix1.M41 * matrix2.M11 + matrix1.M42 * matrix2.M21 + matrix1.M43 * matrix2.M31 + matrix1.M44 * matrix2.M41;
+ result.M42 = matrix1.M41 * matrix2.M12 + matrix1.M42 * matrix2.M22 + matrix1.M43 * matrix2.M32 + matrix1.M44 * matrix2.M42;
+ result.M43 = matrix1.M41 * matrix2.M13 + matrix1.M42 * matrix2.M23 + matrix1.M43 * matrix2.M33 + matrix1.M44 * matrix2.M43;
+ result.M44 = matrix1.M41 * matrix2.M14 + matrix1.M42 * matrix2.M24 + matrix1.M43 * matrix2.M34 + matrix1.M44 * matrix2.M44;
+ }
+
+
+ public static Matrix Multiply(Matrix matrix1, float factor)
+ {
+ matrix1.M11 *= factor;
+ matrix1.M12 *= factor;
+ matrix1.M13 *= factor;
+ matrix1.M14 *= factor;
+ matrix1.M21 *= factor;
+ matrix1.M22 *= factor;
+ matrix1.M23 *= factor;
+ matrix1.M24 *= factor;
+ matrix1.M31 *= factor;
+ matrix1.M32 *= factor;
+ matrix1.M33 *= factor;
+ matrix1.M34 *= factor;
+ matrix1.M41 *= factor;
+ matrix1.M42 *= factor;
+ matrix1.M43 *= factor;
+ matrix1.M44 *= factor;
+ return matrix1;
+ }
+
+
+ public static void Multiply(ref Matrix matrix1, float factor, out Matrix result)
+ {
+ result.M11 = matrix1.M11 * factor;
+ result.M12 = matrix1.M12 * factor;
+ result.M13 = matrix1.M13 * factor;
+ result.M14 = matrix1.M14 * factor;
+ result.M21 = matrix1.M21 * factor;
+ result.M22 = matrix1.M22 * factor;
+ result.M23 = matrix1.M23 * factor;
+ result.M24 = matrix1.M24 * factor;
+ result.M31 = matrix1.M31 * factor;
+ result.M32 = matrix1.M32 * factor;
+ result.M33 = matrix1.M33 * factor;
+ result.M34 = matrix1.M34 * factor;
+ result.M41 = matrix1.M41 * factor;
+ result.M42 = matrix1.M42 * factor;
+ result.M43 = matrix1.M43 * factor;
+ result.M44 = matrix1.M44 * factor;
+ }
+
+
+ public static Matrix Negate(Matrix matrix)
+ {
+ matrix.M11 = -matrix.M11;
+ matrix.M12 = -matrix.M12;
+ matrix.M13 = -matrix.M13;
+ matrix.M14 = -matrix.M14;
+ matrix.M21 = -matrix.M21;
+ matrix.M22 = -matrix.M22;
+ matrix.M23 = -matrix.M23;
+ matrix.M24 = -matrix.M24;
+ matrix.M31 = -matrix.M31;
+ matrix.M32 = -matrix.M32;
+ matrix.M33 = -matrix.M33;
+ matrix.M34 = -matrix.M34;
+ matrix.M41 = -matrix.M41;
+ matrix.M42 = -matrix.M42;
+ matrix.M43 = -matrix.M43;
+ matrix.M44 = -matrix.M44;
+ return matrix;
+ }
+
+
+ public static void Negate(ref Matrix matrix, out Matrix result)
+ {
+ result.M11 = matrix.M11;
+ result.M12 = matrix.M12;
+ result.M13 = matrix.M13;
+ result.M14 = matrix.M14;
+ result.M21 = matrix.M21;
+ result.M22 = matrix.M22;
+ result.M23 = matrix.M23;
+ result.M24 = matrix.M24;
+ result.M31 = matrix.M31;
+ result.M32 = matrix.M32;
+ result.M33 = matrix.M33;
+ result.M34 = matrix.M34;
+ result.M41 = matrix.M41;
+ result.M42 = matrix.M42;
+ result.M43 = matrix.M43;
+ result.M44 = matrix.M44;
+ }
+
+ public static Matrix Subtract(Matrix matrix1, Matrix matrix2)
+ {
+ matrix1.M11 -= matrix2.M11;
+ matrix1.M12 -= matrix2.M12;
+ matrix1.M13 -= matrix2.M13;
+ matrix1.M14 -= matrix2.M14;
+ matrix1.M21 -= matrix2.M21;
+ matrix1.M22 -= matrix2.M22;
+ matrix1.M23 -= matrix2.M23;
+ matrix1.M24 -= matrix2.M24;
+ matrix1.M31 -= matrix2.M31;
+ matrix1.M32 -= matrix2.M32;
+ matrix1.M33 -= matrix2.M33;
+ matrix1.M34 -= matrix2.M34;
+ matrix1.M41 -= matrix2.M41;
+ matrix1.M42 -= matrix2.M42;
+ matrix1.M43 -= matrix2.M43;
+ matrix1.M44 -= matrix2.M44;
+ return matrix1;
+ }
+
+ public static void Subtract(ref Matrix matrix1, ref Matrix matrix2, out Matrix result)
+ {
+ result.M11 = matrix1.M11 - matrix2.M11;
+ result.M12 = matrix1.M12 - matrix2.M12;
+ result.M13 = matrix1.M13 - matrix2.M13;
+ result.M14 = matrix1.M14 - matrix2.M14;
+ result.M21 = matrix1.M21 - matrix2.M21;
+ result.M22 = matrix1.M22 - matrix2.M22;
+ result.M23 = matrix1.M23 - matrix2.M23;
+ result.M24 = matrix1.M24 - matrix2.M24;
+ result.M31 = matrix1.M31 - matrix2.M31;
+ result.M32 = matrix1.M32 - matrix2.M32;
+ result.M33 = matrix1.M33 - matrix2.M33;
+ result.M34 = matrix1.M34 - matrix2.M34;
+ result.M41 = matrix1.M41 - matrix2.M41;
+ result.M42 = matrix1.M42 - matrix2.M42;
+ result.M43 = matrix1.M43 - matrix2.M43;
+ result.M44 = matrix1.M44 - matrix2.M44;
+ }
+
+ public static Matrix Transpose(Matrix matrix)
+ {
+ Matrix result;
+
+ result.M11 = matrix.M11;
+ result.M12 = matrix.M21;
+ result.M13 = matrix.M31;
+ result.M14 = matrix.M41;
+
+ result.M21 = matrix.M12;
+ result.M22 = matrix.M22;
+ result.M23 = matrix.M32;
+ result.M24 = matrix.M42;
+
+ result.M31 = matrix.M13;
+ result.M32 = matrix.M23;
+ result.M33 = matrix.M33;
+ result.M34 = matrix.M43;
+
+ result.M41 = matrix.M14;
+ result.M42 = matrix.M24;
+ result.M43 = matrix.M34;
+ result.M44 = matrix.M44;
+
+ return result;
+ }
+
+
+ public static void Transpose(ref Matrix matrix, out Matrix result)
+ {
+ result.M11 = matrix.M11;
+ result.M12 = matrix.M21;
+ result.M13 = matrix.M31;
+ result.M14 = matrix.M41;
+
+ result.M21 = matrix.M12;
+ result.M22 = matrix.M22;
+ result.M23 = matrix.M32;
+ result.M24 = matrix.M42;
+
+ result.M31 = matrix.M13;
+ result.M32 = matrix.M23;
+ result.M33 = matrix.M33;
+ result.M34 = matrix.M43;
+
+ result.M41 = matrix.M14;
+ result.M42 = matrix.M24;
+ result.M43 = matrix.M34;
+ result.M44 = matrix.M44;
+ }
+
+ #endregion Public Static Methods
+
+ #region Public Methods
+
+ public float Determinant()
+ {
+ float minor1, minor2, minor3, minor4, minor5, minor6;
+
+ minor1 = M31 * M42 - M32 * M41;
+ minor2 = M31 * M43 - M33 * M41;
+ minor3 = M31 * M44 - M34 * M41;
+ minor4 = M32 * M43 - M33 * M42;
+ minor5 = M32 * M44 - M34 * M42;
+ minor6 = M33 * M44 - M34 * M43;
+
+ return M11 * (M22 * minor6 - M23 * minor5 + M24 * minor4) -
+ M12 * (M21 * minor6 - M23 * minor3 + M24 * minor2) +
+ M13 * (M21 * minor5 - M22 * minor3 + M24 * minor1) -
+ M14 * (M21 * minor4 - M22 * minor2 + M23 * minor1);
+ }
+
+ public bool Equals(Matrix other)
+ {
+ return (this.M11 == other.M11) && (this.M12 == other.M12) &&
+ (this.M13 == other.M13) && (this.M14 == other.M14) &&
+ (this.M21 == other.M21) && (this.M22 == other.M22) &&
+ (this.M23 == other.M23) && (this.M24 == other.M24) &&
+ (this.M31 == other.M31) && (this.M32 == other.M32) &&
+ (this.M33 == other.M33) && (this.M34 == other.M34) &&
+ (this.M41 == other.M41) && (this.M42 == other.M42) &&
+ (this.M43 == other.M43) && (this.M44 == other.M44);
+ }
+
+ #endregion Public Methods
+
+ #region Operators
+
+ public static Matrix operator +(Matrix matrix1, Matrix matrix2)
+ {
+ matrix1.M11 += matrix2.M11;
+ matrix1.M12 += matrix2.M12;
+ matrix1.M13 += matrix2.M13;
+ matrix1.M14 += matrix2.M14;
+ matrix1.M21 += matrix2.M21;
+ matrix1.M22 += matrix2.M22;
+ matrix1.M23 += matrix2.M23;
+ matrix1.M24 += matrix2.M24;
+ matrix1.M31 += matrix2.M31;
+ matrix1.M32 += matrix2.M32;
+ matrix1.M33 += matrix2.M33;
+ matrix1.M34 += matrix2.M34;
+ matrix1.M41 += matrix2.M41;
+ matrix1.M42 += matrix2.M42;
+ matrix1.M43 += matrix2.M43;
+ matrix1.M44 += matrix2.M44;
+ return matrix1;
+ }
+
+ public static Matrix operator /(Matrix matrix1, Matrix matrix2)
+ {
+ Matrix inverse = Matrix.Invert(matrix2), result;
+
+ result.M11 = matrix1.M11 * inverse.M11 + matrix1.M12 * inverse.M21 + matrix1.M13 * inverse.M31 + matrix1.M14 * inverse.M41;
+ result.M12 = matrix1.M11 * inverse.M12 + matrix1.M12 * inverse.M22 + matrix1.M13 * inverse.M32 + matrix1.M14 * inverse.M42;
+ result.M13 = matrix1.M11 * inverse.M13 + matrix1.M12 * inverse.M23 + matrix1.M13 * inverse.M33 + matrix1.M14 * inverse.M43;
+ result.M14 = matrix1.M11 * inverse.M14 + matrix1.M12 * inverse.M24 + matrix1.M13 * inverse.M34 + matrix1.M14 * inverse.M44;
+
+ result.M21 = matrix1.M21 * inverse.M11 + matrix1.M22 * inverse.M21 + matrix1.M23 * inverse.M31 + matrix1.M24 * inverse.M41;
+ result.M22 = matrix1.M21 * inverse.M12 + matrix1.M22 * inverse.M22 + matrix1.M23 * inverse.M32 + matrix1.M24 * inverse.M42;
+ result.M23 = matrix1.M21 * inverse.M13 + matrix1.M22 * inverse.M23 + matrix1.M23 * inverse.M33 + matrix1.M24 * inverse.M43;
+ result.M24 = matrix1.M21 * inverse.M14 + matrix1.M22 * inverse.M24 + matrix1.M23 * inverse.M34 + matrix1.M24 * inverse.M44;
+
+ result.M31 = matrix1.M31 * inverse.M11 + matrix1.M32 * inverse.M21 + matrix1.M33 * inverse.M31 + matrix1.M34 * inverse.M41;
+ result.M32 = matrix1.M31 * inverse.M12 + matrix1.M32 * inverse.M22 + matrix1.M33 * inverse.M32 + matrix1.M34 * inverse.M42;
+ result.M33 = matrix1.M31 * inverse.M13 + matrix1.M32 * inverse.M23 + matrix1.M33 * inverse.M33 + matrix1.M34 * inverse.M43;
+ result.M34 = matrix1.M31 * inverse.M14 + matrix1.M32 * inverse.M24 + matrix1.M33 * inverse.M34 + matrix1.M34 * inverse.M44;
+
+ result.M41 = matrix1.M41 * inverse.M11 + matrix1.M42 * inverse.M21 + matrix1.M43 * inverse.M31 + matrix1.M44 * inverse.M41;
+ result.M42 = matrix1.M41 * inverse.M12 + matrix1.M42 * inverse.M22 + matrix1.M43 * inverse.M32 + matrix1.M44 * inverse.M42;
+ result.M43 = matrix1.M41 * inverse.M13 + matrix1.M42 * inverse.M23 + matrix1.M43 * inverse.M33 + matrix1.M44 * inverse.M43;
+ result.M44 = matrix1.M41 * inverse.M14 + matrix1.M42 * inverse.M24 + matrix1.M43 * inverse.M34 + matrix1.M44 * inverse.M44;
+
+ return result;
+ }
+
+ public static Matrix operator /(Matrix matrix1, float divider)
+ {
+ float inverseDivider = 1.0f / divider;
+
+ matrix1.M11 = matrix1.M11 * inverseDivider;
+ matrix1.M12 = matrix1.M12 * inverseDivider;
+ matrix1.M13 = matrix1.M13 * inverseDivider;
+ matrix1.M14 = matrix1.M14 * inverseDivider;
+ matrix1.M21 = matrix1.M21 * inverseDivider;
+ matrix1.M22 = matrix1.M22 * inverseDivider;
+ matrix1.M23 = matrix1.M23 * inverseDivider;
+ matrix1.M24 = matrix1.M24 * inverseDivider;
+ matrix1.M31 = matrix1.M31 * inverseDivider;
+ matrix1.M32 = matrix1.M32 * inverseDivider;
+ matrix1.M33 = matrix1.M33 * inverseDivider;
+ matrix1.M34 = matrix1.M34 * inverseDivider;
+ matrix1.M41 = matrix1.M41 * inverseDivider;
+ matrix1.M42 = matrix1.M42 * inverseDivider;
+ matrix1.M43 = matrix1.M43 * inverseDivider;
+ matrix1.M44 = matrix1.M44 * inverseDivider;
+
+ return matrix1;
+ }
+
+ public static bool operator ==(Matrix matrix1, Matrix matrix2)
+ {
+ return (matrix1.M11 == matrix2.M11) && (matrix1.M12 == matrix2.M12) &&
+ (matrix1.M13 == matrix2.M13) && (matrix1.M14 == matrix2.M14) &&
+ (matrix1.M21 == matrix2.M21) && (matrix1.M22 == matrix2.M22) &&
+ (matrix1.M23 == matrix2.M23) && (matrix1.M24 == matrix2.M24) &&
+ (matrix1.M31 == matrix2.M31) && (matrix1.M32 == matrix2.M32) &&
+ (matrix1.M33 == matrix2.M33) && (matrix1.M34 == matrix2.M34) &&
+ (matrix1.M41 == matrix2.M41) && (matrix1.M42 == matrix2.M42) &&
+ (matrix1.M43 == matrix2.M43) && (matrix1.M44 == matrix2.M44);
+ }
+
+ public static bool operator !=(Matrix matrix1, Matrix matrix2)
+ {
+ return (matrix1.M11 != matrix2.M11) || (matrix1.M12 != matrix2.M12) ||
+ (matrix1.M13 != matrix2.M13) || (matrix1.M14 != matrix2.M14) ||
+ (matrix1.M21 != matrix2.M21) || (matrix1.M22 != matrix2.M22) ||
+ (matrix1.M23 != matrix2.M23) || (matrix1.M24 != matrix2.M24) ||
+ (matrix1.M31 != matrix2.M31) || (matrix1.M32 != matrix2.M32) ||
+ (matrix1.M33 != matrix2.M33) || (matrix1.M34 != matrix2.M34) ||
+ (matrix1.M41 != matrix2.M41) || (matrix1.M42 != matrix2.M42) ||
+ (matrix1.M43 != matrix2.M43) || (matrix1.M44 != matrix2.M44);
+ }
+
+ public static Matrix operator *(Matrix matrix1, Matrix matrix2)
+ {
+ Matrix result;
+
+ result.M11 = matrix1.M11 * matrix2.M11 + matrix1.M12 * matrix2.M21 + matrix1.M13 * matrix2.M31 + matrix1.M14 * matrix2.M41;
+ result.M12 = matrix1.M11 * matrix2.M12 + matrix1.M12 * matrix2.M22 + matrix1.M13 * matrix2.M32 + matrix1.M14 * matrix2.M42;
+ result.M13 = matrix1.M11 * matrix2.M13 + matrix1.M12 * matrix2.M23 + matrix1.M13 * matrix2.M33 + matrix1.M14 * matrix2.M43;
+ result.M14 = matrix1.M11 * matrix2.M14 + matrix1.M12 * matrix2.M24 + matrix1.M13 * matrix2.M34 + matrix1.M14 * matrix2.M44;
+
+ result.M21 = matrix1.M21 * matrix2.M11 + matrix1.M22 * matrix2.M21 + matrix1.M23 * matrix2.M31 + matrix1.M24 * matrix2.M41;
+ result.M22 = matrix1.M21 * matrix2.M12 + matrix1.M22 * matrix2.M22 + matrix1.M23 * matrix2.M32 + matrix1.M24 * matrix2.M42;
+ result.M23 = matrix1.M21 * matrix2.M13 + matrix1.M22 * matrix2.M23 + matrix1.M23 * matrix2.M33 + matrix1.M24 * matrix2.M43;
+ result.M24 = matrix1.M21 * matrix2.M14 + matrix1.M22 * matrix2.M24 + matrix1.M23 * matrix2.M34 + matrix1.M24 * matrix2.M44;
+
+ result.M31 = matrix1.M31 * matrix2.M11 + matrix1.M32 * matrix2.M21 + matrix1.M33 * matrix2.M31 + matrix1.M34 * matrix2.M41;
+ result.M32 = matrix1.M31 * matrix2.M12 + matrix1.M32 * matrix2.M22 + matrix1.M33 * matrix2.M32 + matrix1.M34 * matrix2.M42;
+ result.M33 = matrix1.M31 * matrix2.M13 + matrix1.M32 * matrix2.M23 + matrix1.M33 * matrix2.M33 + matrix1.M34 * matrix2.M43;
+ result.M34 = matrix1.M31 * matrix2.M14 + matrix1.M32 * matrix2.M24 + matrix1.M33 * matrix2.M34 + matrix1.M34 * matrix2.M44;
+
+ result.M41 = matrix1.M41 * matrix2.M11 + matrix1.M42 * matrix2.M21 + matrix1.M43 * matrix2.M31 + matrix1.M44 * matrix2.M41;
+ result.M42 = matrix1.M41 * matrix2.M12 + matrix1.M42 * matrix2.M22 + matrix1.M43 * matrix2.M32 + matrix1.M44 * matrix2.M42;
+ result.M43 = matrix1.M41 * matrix2.M13 + matrix1.M42 * matrix2.M23 + matrix1.M43 * matrix2.M33 + matrix1.M44 * matrix2.M43;
+ result.M44 = matrix1.M41 * matrix2.M14 + matrix1.M42 * matrix2.M24 + matrix1.M43 * matrix2.M34 + matrix1.M44 * matrix2.M44;
+
+ return result;
+ }
+
+ public static Matrix operator *(Matrix matrix, float scaleFactor)
+ {
+ matrix.M11 = matrix.M11 * scaleFactor;
+ matrix.M12 = matrix.M12 * scaleFactor;
+ matrix.M13 = matrix.M13 * scaleFactor;
+ matrix.M14 = matrix.M14 * scaleFactor;
+ matrix.M21 = matrix.M21 * scaleFactor;
+ matrix.M22 = matrix.M22 * scaleFactor;
+ matrix.M23 = matrix.M23 * scaleFactor;
+ matrix.M24 = matrix.M24 * scaleFactor;
+ matrix.M31 = matrix.M31 * scaleFactor;
+ matrix.M32 = matrix.M32 * scaleFactor;
+ matrix.M33 = matrix.M33 * scaleFactor;
+ matrix.M34 = matrix.M34 * scaleFactor;
+ matrix.M41 = matrix.M41 * scaleFactor;
+ matrix.M42 = matrix.M42 * scaleFactor;
+ matrix.M43 = matrix.M43 * scaleFactor;
+ matrix.M44 = matrix.M44 * scaleFactor;
+ return matrix;
+ }
+
+ public static Matrix operator *(float scaleFactor, Matrix matrix)
+ {
+ matrix.M11 = matrix.M11 * scaleFactor;
+ matrix.M12 = matrix.M12 * scaleFactor;
+ matrix.M13 = matrix.M13 * scaleFactor;
+ matrix.M14 = matrix.M14 * scaleFactor;
+ matrix.M21 = matrix.M21 * scaleFactor;
+ matrix.M22 = matrix.M22 * scaleFactor;
+ matrix.M23 = matrix.M23 * scaleFactor;
+ matrix.M24 = matrix.M24 * scaleFactor;
+ matrix.M31 = matrix.M31 * scaleFactor;
+ matrix.M32 = matrix.M32 * scaleFactor;
+ matrix.M33 = matrix.M33 * scaleFactor;
+ matrix.M34 = matrix.M34 * scaleFactor;
+ matrix.M41 = matrix.M41 * scaleFactor;
+ matrix.M42 = matrix.M42 * scaleFactor;
+ matrix.M43 = matrix.M43 * scaleFactor;
+ matrix.M44 = matrix.M44 * scaleFactor;
+ return matrix;
+ }
+
+ public static Matrix operator -(Matrix matrix1, Matrix matrix2)
+ {
+ matrix1.M11 -= matrix2.M11;
+ matrix1.M12 -= matrix2.M12;
+ matrix1.M13 -= matrix2.M13;
+ matrix1.M14 -= matrix2.M14;
+ matrix1.M21 -= matrix2.M21;
+ matrix1.M22 -= matrix2.M22;
+ matrix1.M23 -= matrix2.M23;
+ matrix1.M24 -= matrix2.M24;
+ matrix1.M31 -= matrix2.M31;
+ matrix1.M32 -= matrix2.M32;
+ matrix1.M33 -= matrix2.M33;
+ matrix1.M34 -= matrix2.M34;
+ matrix1.M41 -= matrix2.M41;
+ matrix1.M42 -= matrix2.M42;
+ matrix1.M43 -= matrix2.M43;
+ matrix1.M44 -= matrix2.M44;
+ return matrix1;
+ }
+
+
+ public static Matrix operator -(Matrix matrix)
+ {
+ matrix.M11 = -matrix.M11;
+ matrix.M12 = -matrix.M12;
+ matrix.M13 = -matrix.M13;
+ matrix.M14 = -matrix.M14;
+ matrix.M21 = -matrix.M21;
+ matrix.M22 = -matrix.M22;
+ matrix.M23 = -matrix.M23;
+ matrix.M24 = -matrix.M24;
+ matrix.M31 = -matrix.M31;
+ matrix.M32 = -matrix.M32;
+ matrix.M33 = -matrix.M33;
+ matrix.M34 = -matrix.M34;
+ matrix.M41 = -matrix.M41;
+ matrix.M42 = -matrix.M42;
+ matrix.M43 = -matrix.M43;
+ matrix.M44 = -matrix.M44;
+ return matrix;
+ }
+
+ #endregion
+
+ #region Object Overrides
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Matrix)
+ return this == (Matrix)obj;
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ToString()
+ {
+ return "{ {M11:" + M11 + " M12:" + M12 + " M13:" + M13 + " M14:" + M14 + "}" +
+ " {M21:" + M21 + " M22:" + M22 + " M23:" + M23 + " M24:" + M24 + "}" +
+ " {M31:" + M31 + " M32:" + M32 + " M33:" + M33 + " M34:" + M34 + "}" +
+ " {M41:" + M41 + " M42:" + M42 + " M43:" + M43 + " M44:" + M44 + "} }";
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Plane.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Plane.cs
new file mode 100644
index 0000000000..9970380f34
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Plane.cs
@@ -0,0 +1,212 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+namespace BizHawk.Bizware.BizwareGL
+{
+
+ [Serializable]
+ public struct Plane : IEquatable
+ {
+ #region Public Fields
+
+ public float D;
+ public Vector3 Normal;
+
+ #endregion Public Fields
+
+
+ #region Constructors
+
+ public Plane(Vector4 value)
+ : this(new Vector3(value.X, value.Y, value.Z), value.W)
+ {
+
+ }
+
+ public Plane(Vector3 normal, float d)
+ {
+ Normal = normal;
+ D = d;
+ }
+
+ public Plane(Vector3 a, Vector3 b, Vector3 c)
+ {
+ Vector3 ab = b - a;
+ Vector3 ac = c - a;
+
+ Vector3 cross = Vector3.Cross(ab, ac);
+ Normal = Vector3.Normalize(cross);
+ D = -(Vector3.Dot(cross, a));
+ }
+
+ public Plane(float a, float b, float c, float d)
+ : this(new Vector3(a, b, c), d)
+ {
+
+ }
+
+ #endregion Constructors
+
+
+ #region Public Methods
+
+ public float Dot(Vector4 value)
+ {
+ return ((((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + (this.D * value.W));
+ }
+
+ public void Dot(ref Vector4 value, out float result)
+ {
+ result = (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + (this.D * value.W);
+ }
+
+ public float DotCoordinate(Vector3 value)
+ {
+ return ((((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + this.D);
+ }
+
+ public void DotCoordinate(ref Vector3 value, out float result)
+ {
+ result = (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + this.D;
+ }
+
+ public float DotNormal(Vector3 value)
+ {
+ return (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z));
+ }
+
+ public void DotNormal(ref Vector3 value, out float result)
+ {
+ result = ((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z);
+ }
+
+ public static void Transform(ref Plane plane, ref Quaternion rotation, out Plane result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(ref Plane plane, ref Matrix matrix, out Plane result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Plane Transform(Plane plane, Quaternion rotation)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Plane Transform(Plane plane, Matrix matrix)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Normalize()
+ {
+ float factor;
+ Vector3 normal = Normal;
+ Normal = Vector3.Normalize(Normal);
+ factor = (float)Math.Sqrt(Normal.X * Normal.X + Normal.Y * Normal.Y + Normal.Z * Normal.Z) /
+ (float)Math.Sqrt(normal.X * normal.X + normal.Y * normal.Y + normal.Z * normal.Z);
+ D = D * factor;
+ }
+
+ public static Plane Normalize(Plane value)
+ {
+ Plane ret;
+ Normalize(ref value, out ret);
+ return ret;
+ }
+
+ public static void Normalize(ref Plane value, out Plane result)
+ {
+ float factor;
+ result.Normal = Vector3.Normalize(value.Normal);
+ factor = (float)Math.Sqrt(result.Normal.X * result.Normal.X + result.Normal.Y * result.Normal.Y + result.Normal.Z * result.Normal.Z) /
+ (float)Math.Sqrt(value.Normal.X * value.Normal.X + value.Normal.Y * value.Normal.Y + value.Normal.Z * value.Normal.Z);
+ result.D = value.D * factor;
+ }
+
+ public static bool operator !=(Plane plane1, Plane plane2)
+ {
+ return !plane1.Equals(plane2);
+ }
+
+ public static bool operator ==(Plane plane1, Plane plane2)
+ {
+ return plane1.Equals(plane2);
+ }
+
+ public override bool Equals(object other)
+ {
+ return (other is Plane) ? this.Equals((Plane)other) : false;
+ }
+
+ public bool Equals(Plane other)
+ {
+ return ((Normal == other.Normal) && (D == other.D));
+ }
+
+ public override int GetHashCode()
+ {
+ return Normal.GetHashCode() ^ D.GetHashCode();
+ }
+
+ public PlaneIntersectionType Intersects(BoundingBox box)
+ {
+ return box.Intersects(this);
+ }
+
+ public void Intersects(ref BoundingBox box, out PlaneIntersectionType result)
+ {
+ result = Intersects(box);
+ }
+
+ public PlaneIntersectionType Intersects(BoundingFrustum frustum)
+ {
+ return frustum.Intersects(this);
+ }
+
+ public PlaneIntersectionType Intersects(BoundingSphere sphere)
+ {
+ return sphere.Intersects(this);
+ }
+
+ public void Intersects(ref BoundingSphere sphere, out PlaneIntersectionType result)
+ {
+ result = Intersects(sphere);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{{Normal:{0} D:{1}}}", Normal, D);
+ }
+
+ #endregion
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/PlaneHelper.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/PlaneHelper.cs
new file mode 100644
index 0000000000..533ad89e72
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/PlaneHelper.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ internal class PlaneHelper
+ {
+ ///
+ /// Returns a value indicating what side (positive/negative) of a plane a point is
+ ///
+ /// The point to check with
+ /// The plane to check against
+ /// Greater than zero if on the positive side, less than zero if on the negative size, 0 otherwise
+ public static float ClassifyPoint(ref Vector3 point, ref Plane plane)
+ {
+ return point.X * plane.Normal.X + point.Y * plane.Normal.Y + point.Z * plane.Normal.Z + plane.D;
+ }
+
+ ///
+ /// Returns the perpendicular distance from a point to a plane
+ ///
+ /// The point to check
+ /// The place to check
+ /// The perpendicular distance from the point to the plane
+ public static float PerpendicularDistance(ref Vector3 point, ref Plane plane)
+ {
+ // dist = (ax + by + cz + d) / sqrt(a*a + b*b + c*c)
+ return (float)Math.Abs((plane.Normal.X * point.X + plane.Normal.Y * point.Y + plane.Normal.Z * point.Z)
+ / Math.Sqrt(plane.Normal.X * plane.Normal.X + plane.Normal.Y * plane.Normal.Y + plane.Normal.Z * plane.Normal.Z));
+ }
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Point.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Point.cs
new file mode 100644
index 0000000000..10fa723fa1
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Point.cs
@@ -0,0 +1,119 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+
+ public struct Point : IEquatable
+ {
+ #region Private Fields
+
+ private static Point zeroPoint = new Point();
+
+ #endregion Private Fields
+
+
+ #region Public Fields
+
+ public int X;
+ public int Y;
+
+ #endregion Public Fields
+
+
+ #region Properties
+
+ public static Point Zero
+ {
+ get { return zeroPoint; }
+ }
+
+ #endregion Properties
+
+
+ #region Constructors
+
+ ///
+ /// Makes new Point with integer accurate
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public Point(int x, int y)
+ {
+ this.X = x;
+ this.Y = y;
+ }
+
+ #endregion Constructors
+
+
+ #region Public methods
+
+ public static bool operator ==(Point a, Point b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(Point a, Point b)
+ {
+ return !a.Equals(b);
+ }
+
+ public bool Equals(Point other)
+ {
+ return ((X == other.X) && (Y == other.Y));
+ }
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Point) ? Equals((Point)obj) : false;
+ }
+
+ public override int GetHashCode()
+ {
+ return X ^ Y;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{{X:{0} Y:{1}}}", X, Y);
+ }
+
+ #endregion
+ }
+}
+
+
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Quaternion.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Quaternion.cs
new file mode 100644
index 0000000000..1edd9befbf
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Quaternion.cs
@@ -0,0 +1,687 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+using System.Text;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ public struct Quaternion : IEquatable
+ {
+ public float X;
+ public float Y;
+ public float Z;
+ public float W;
+ static Quaternion identity = new Quaternion(0, 0, 0, 1);
+
+
+ public Quaternion(float x, float y, float z, float w)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Z = z;
+ this.W = w;
+ }
+
+
+ public Quaternion(Vector3 vectorPart, float scalarPart)
+ {
+ this.X = vectorPart.X;
+ this.Y = vectorPart.Y;
+ this.Z = vectorPart.Z;
+ this.W = scalarPart;
+ }
+
+ public static Quaternion Identity
+ {
+ get{ return identity; }
+ }
+
+
+ public static Quaternion Add(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ quaternion1.X += quaternion2.X;
+ quaternion1.Y += quaternion2.Y;
+ quaternion1.Z += quaternion2.Z;
+ quaternion1.W += quaternion2.W;
+ return quaternion1;
+ }
+
+
+ public static void Add(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
+ {
+ result.W = quaternion1.W + quaternion2.W;
+ result.X = quaternion1.X + quaternion2.X;
+ result.Y = quaternion1.Y + quaternion2.Y;
+ result.Z = quaternion1.Z + quaternion2.Z;
+ }
+
+ public static Quaternion Concatenate(Quaternion value1, Quaternion value2)
+ {
+ Quaternion quaternion;
+ quaternion.X = ((value2.X * value1.W) + (value1.X * value2.W)) + (value2.Y * value1.Z) - (value2.Z * value1.Y);
+ quaternion.Y = ((value2.Y * value1.W) + (value1.Y * value2.W)) + (value2.Z * value1.X) - (value2.X * value1.Z);
+ quaternion.Z = ((value2.Z * value1.W) + (value1.Z * value2.W)) + (value2.X * value1.Y) - (value2.Y * value1.X);
+ quaternion.W = (value2.W * value1.W) - ((value2.X * value1.X) + (value2.Y * value1.Y)) + (value2.Z * value1.Z);
+ return quaternion;
+ }
+
+ public void Conjugate()
+ {
+ this.X = -this.X;
+ this.Y = -this.Y;
+ this.Z = -this.Z;
+ }
+
+ public static Quaternion Conjugate(Quaternion value)
+ {
+ Quaternion quaternion;
+ quaternion.X = -value.X;
+ quaternion.Y = -value.Y;
+ quaternion.Z = -value.Z;
+ quaternion.W = value.W;
+ return quaternion;
+ }
+
+ public static void Conjugate(ref Quaternion value, out Quaternion result)
+ {
+ result.X = -value.X;
+ result.Y = -value.Y;
+ result.Z = -value.Z;
+ result.W = value.W;
+ }
+
+ public static void Concatenate(ref Quaternion value1, ref Quaternion value2, out Quaternion result)
+ {
+ result.X = ((value2.X * value1.W) + (value1.X * value2.W)) + (value2.Y * value1.Z) - (value2.Z * value1.Y);
+ result.Y = ((value2.Y * value1.W) + (value1.Y * value2.W)) + (value2.Z * value1.X) - (value2.X * value1.Z);
+ result.Z = ((value2.Z * value1.W) + (value1.Z * value2.W)) + (value2.X * value1.Y) - (value2.Y * value1.X);
+ result.W = (value2.W * value1.W) - ((value2.X * value1.X) + (value2.Y * value1.Y)) + (value2.Z * value1.Z);
+ }
+
+ public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
+ {
+ Quaternion quaternion;
+ quaternion.X = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
+ quaternion.Y = (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) - (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
+ quaternion.Z = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f))) - (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f)));
+ quaternion.W = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
+ return quaternion;
+ }
+
+ public static void CreateFromYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result)
+ {
+ result.X = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
+ result.Y = (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) - (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
+ result.Z = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f))) - (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f)));
+ result.W = (((float)Math.Cos((double)(yaw * 0.5f)) * (float)Math.Cos((double)(pitch * 0.5f))) * (float)Math.Cos((double)(roll * 0.5f))) + (((float)Math.Sin((double)(yaw * 0.5f)) * (float)Math.Sin((double)(pitch * 0.5f))) * (float)Math.Sin((double)(roll * 0.5f)));
+ }
+
+ public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
+ {
+ float sin_a = (float)Math.Sin(angle / 2.0f);
+ return new Quaternion(axis.X * sin_a,axis.Y * sin_a,axis.Z * sin_a,(float)Math.Cos(angle / 2.0f));
+ }
+
+
+ public static void CreateFromAxisAngle(ref Vector3 axis, float angle, out Quaternion result)
+ {
+ float sin_a = (float)Math.Sin(angle / 2.0f);
+ result.X = axis.X * sin_a;
+ result.Y = axis.Y * sin_a;
+ result.Z = axis.Z * sin_a;
+ result.W = (float)Math.Cos(angle / 2.0f);
+ }
+
+
+ public static Quaternion CreateFromRotationMatrix(Matrix matrix)
+ {
+ Quaternion result;
+ if ((matrix.M11 + matrix.M22 + matrix.M33) > 0.0F)
+ {
+ float M1 = (float)System.Math.Sqrt((double)(matrix.M11 + matrix.M22 + matrix.M33 + 1.0F));
+ result.W = M1 * 0.5F;
+ M1 = 0.5F / M1;
+ result.X = (matrix.M23 - matrix.M32) * M1;
+ result.Y = (matrix.M31 - matrix.M13) * M1;
+ result.Z = (matrix.M12 - matrix.M21) * M1;
+ return result;
+ }
+ if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
+ {
+ float M2 = (float)System.Math.Sqrt((double)(1.0F + matrix.M11 - matrix.M22 - matrix.M33));
+ float M3 = 0.5F / M2;
+ result.X = 0.5F * M2;
+ result.Y = (matrix.M12 + matrix.M21) * M3;
+ result.Z = (matrix.M13 + matrix.M31) * M3;
+ result.W = (matrix.M23 - matrix.M32) * M3;
+ return result;
+ }
+ if (matrix.M22 > matrix.M33)
+ {
+ float M4 = (float)System.Math.Sqrt((double)(1.0F + matrix.M22 - matrix.M11 - matrix.M33));
+ float M5 = 0.5F / M4;
+ result.X = (matrix.M21 + matrix.M12) * M5;
+ result.Y = 0.5F * M4;
+ result.Z = (matrix.M32 + matrix.M23) * M5;
+ result.W = (matrix.M31 - matrix.M13) * M5;
+ return result;
+ }
+ float M6 = (float)System.Math.Sqrt((double)(1.0F + matrix.M33 - matrix.M11 - matrix.M22));
+ float M7 = 0.5F / M6;
+ result.X = (matrix.M31 + matrix.M13) * M7;
+ result.Y = (matrix.M32 + matrix.M23) * M7;
+ result.Z = 0.5F * M6;
+ result.W = (matrix.M12 - matrix.M21) * M7;
+ return result;
+ }
+
+
+ public static void CreateFromRotationMatrix(ref Matrix matrix, out Quaternion result)
+ {
+ if ((matrix.M11 + matrix.M22 + matrix.M33) > 0.0F)
+ {
+ float M1 = (float)System.Math.Sqrt((double)(matrix.M11 + matrix.M22 + matrix.M33 + 1.0F));
+ result.W = M1 * 0.5F;
+ M1 = 0.5F / M1;
+ result.X = (matrix.M23 - matrix.M32) * M1;
+ result.Y = (matrix.M31 - matrix.M13) * M1;
+ result.Z = (matrix.M12 - matrix.M21) * M1;
+ return;
+ }
+ if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
+ {
+ float M2 = (float)System.Math.Sqrt((double)(1.0F + matrix.M11 - matrix.M22 - matrix.M33));
+ float M3 = 0.5F / M2;
+ result.X = 0.5F * M2;
+ result.Y = (matrix.M12 + matrix.M21) * M3;
+ result.Z = (matrix.M13 + matrix.M31) * M3;
+ result.W = (matrix.M23 - matrix.M32) * M3;
+ return;
+ }
+ if (matrix.M22 > matrix.M33)
+ {
+ float M4 = (float)System.Math.Sqrt((double)(1.0F + matrix.M22 - matrix.M11 - matrix.M33));
+ float M5 = 0.5F / M4;
+ result.X = (matrix.M21 + matrix.M12) * M5;
+ result.Y = 0.5F * M4;
+ result.Z = (matrix.M32 + matrix.M23) * M5;
+ result.W = (matrix.M31 - matrix.M13) * M5;
+ return;
+ }
+ float M6 = (float)System.Math.Sqrt((double)(1.0F + matrix.M33 - matrix.M11 - matrix.M22));
+ float M7 = 0.5F / M6;
+ result.X = (matrix.M31 + matrix.M13) * M7;
+ result.Y = (matrix.M32 + matrix.M23) * M7;
+ result.Z = 0.5F * M6;
+ result.W = (matrix.M12 - matrix.M21) * M7;
+ }
+
+
+ public static Quaternion Divide(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ Quaternion result;
+
+ float w5 = 1.0F / ((quaternion2.X * quaternion2.X) + (quaternion2.Y * quaternion2.Y) + (quaternion2.Z * quaternion2.Z) + (quaternion2.W * quaternion2.W));
+ float w4 = -quaternion2.X * w5;
+ float w3 = -quaternion2.Y * w5;
+ float w2 = -quaternion2.Z * w5;
+ float w1 = quaternion2.W * w5;
+
+ result.X = (quaternion1.X * w1) + (w4 * quaternion1.W) + ((quaternion1.Y * w2) - (quaternion1.Z * w3));
+ result.Y = (quaternion1.Y * w1) + (w3 * quaternion1.W) + ((quaternion1.Z * w4) - (quaternion1.X * w2));
+ result.Z = (quaternion1.Z * w1) + (w2 * quaternion1.W) + ((quaternion1.X * w3) - (quaternion1.Y * w4));
+ result.W = (quaternion1.W * quaternion2.W * w5) - ((quaternion1.X * w4) + (quaternion1.Y * w3) + (quaternion1.Z * w2));
+ return result;
+ }
+
+
+ public static void Divide(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
+ {
+ float w5 = 1.0F / ((quaternion2.X * quaternion2.X) + (quaternion2.Y * quaternion2.Y) + (quaternion2.Z * quaternion2.Z) + (quaternion2.W * quaternion2.W));
+ float w4 = -quaternion2.X * w5;
+ float w3 = -quaternion2.Y * w5;
+ float w2 = -quaternion2.Z * w5;
+ float w1 = quaternion2.W * w5;
+
+ result.X = (quaternion1.X * w1) + (w4 * quaternion1.W) + ((quaternion1.Y * w2) - (quaternion1.Z * w3));
+ result.Y = (quaternion1.Y * w1) + (w3 * quaternion1.W) + ((quaternion1.Z * w4) - (quaternion1.X * w2));
+ result.Z = (quaternion1.Z * w1) + (w2 * quaternion1.W) + ((quaternion1.X * w3) - (quaternion1.Y * w4));
+ result.W = (quaternion1.W * quaternion2.W * w5) - ((quaternion1.X * w4) + (quaternion1.Y * w3) + (quaternion1.Z * w2));
+ }
+
+
+ public static float Dot(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ return (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
+ }
+
+
+ public static void Dot(ref Quaternion quaternion1, ref Quaternion quaternion2, out float result)
+ {
+ result = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
+ }
+
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Quaternion) ? this == (Quaternion)obj : false;
+ }
+
+
+ public bool Equals(Quaternion other)
+ {
+ if ((X == other.X) && (Y == other.Y) && (Z == other.Z))
+ return W == other.W;
+ return false;
+ }
+
+
+ public override int GetHashCode()
+ {
+ return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode();
+ }
+
+
+ public static Quaternion Inverse(Quaternion quaternion)
+ {
+ Quaternion result;
+ float m1 = 1.0F / ((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W));
+ result.X = -quaternion.X * m1;
+ result.Y = -quaternion.Y * m1;
+ result.Z = -quaternion.Z * m1;
+ result.W = quaternion.W * m1;
+ return result;
+ }
+
+
+ public static void Inverse(ref Quaternion quaternion, out Quaternion result)
+ {
+ float m1 = 1.0F / ((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W));
+ result.X = -quaternion.X * m1;
+ result.Y = -quaternion.Y * m1;
+ result.Z = -quaternion.Z * m1;
+ result.W = quaternion.W * m1;
+ }
+
+
+ public float Length()
+ {
+ return (float)System.Math.Sqrt((double)((X * X) + (Y * Y) + (Z * Z) + (W * W)));
+ }
+
+
+ public float LengthSquared()
+ {
+ return (X * X) + (Y * Y) + (Z * Z) + (W * W);
+ }
+
+
+ public static Quaternion Lerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
+ {
+ Quaternion result;
+ float f2 = 1.0F - amount;
+ if (((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W)) >= 0.0F)
+ {
+ result.X = (f2 * quaternion1.X) + (amount * quaternion2.X);
+ result.Y = (f2 * quaternion1.Y) + (amount * quaternion2.Y);
+ result.Z = (f2 * quaternion1.Z) + (amount * quaternion2.Z);
+ result.W = (f2 * quaternion1.W) + (amount * quaternion2.W);
+ }
+ else
+ {
+ result.X = (f2 * quaternion1.X) - (amount * quaternion2.X);
+ result.Y = (f2 * quaternion1.Y) - (amount * quaternion2.Y);
+ result.Z = (f2 * quaternion1.Z) - (amount * quaternion2.Z);
+ result.W = (f2 * quaternion1.W) - (amount * quaternion2.W);
+ }
+ float f4 = (result.X * result.X) + (result.Y * result.Y) + (result.Z * result.Z) + (result.W * result.W);
+ float f3 = 1.0F / (float)System.Math.Sqrt((double)f4);
+ result.X *= f3;
+ result.Y *= f3;
+ result.Z *= f3;
+ result.W *= f3;
+ return result;
+ }
+
+
+ public static void Lerp(ref Quaternion quaternion1, ref Quaternion quaternion2, float amount, out Quaternion result)
+ {
+ float m2 = 1.0F - amount;
+ if (((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W)) >= 0.0F)
+ {
+ result.X = (m2 * quaternion1.X) + (amount * quaternion2.X);
+ result.Y = (m2 * quaternion1.Y) + (amount * quaternion2.Y);
+ result.Z = (m2 * quaternion1.Z) + (amount * quaternion2.Z);
+ result.W = (m2 * quaternion1.W) + (amount * quaternion2.W);
+ }
+ else
+ {
+ result.X = (m2 * quaternion1.X) - (amount * quaternion2.X);
+ result.Y = (m2 * quaternion1.Y) - (amount * quaternion2.Y);
+ result.Z = (m2 * quaternion1.Z) - (amount * quaternion2.Z);
+ result.W = (m2 * quaternion1.W) - (amount * quaternion2.W);
+ }
+ float m4 = (result.X * result.X) + (result.Y * result.Y) + (result.Z * result.Z) + (result.W * result.W);
+ float m3 = 1.0F / (float)System.Math.Sqrt((double)m4);
+ result.X *= m3;
+ result.Y *= m3;
+ result.Z *= m3;
+ result.W *= m3;
+ }
+
+
+ public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
+ {
+ Quaternion result;
+ float q2, q3;
+
+ float q4 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
+ bool flag = false;
+ if (q4 < 0.0F)
+ {
+ flag = true;
+ q4 = -q4;
+ }
+ if (q4 > 0.999999F)
+ {
+ q3 = 1.0F - amount;
+ q2 = flag ? -amount : amount;
+ }
+ else
+ {
+ float q5 = (float)System.Math.Acos((double)q4);
+ float q6 = (float)(1.0 / System.Math.Sin((double)q5));
+ q3 = (float)System.Math.Sin((double)((1.0F - amount) * q5)) * q6;
+ q2 = flag ? (float)-System.Math.Sin((double)(amount * q5)) * q6 : (float)System.Math.Sin((double)(amount * q5)) * q6;
+ }
+ result.X = (q3 * quaternion1.X) + (q2 * quaternion2.X);
+ result.Y = (q3 * quaternion1.Y) + (q2 * quaternion2.Y);
+ result.Z = (q3 * quaternion1.Z) + (q2 * quaternion2.Z);
+ result.W = (q3 * quaternion1.W) + (q2 * quaternion2.W);
+ return result;
+ }
+
+
+ public static void Slerp(ref Quaternion quaternion1, ref Quaternion quaternion2, float amount, out Quaternion result)
+ {
+ float q2, q3;
+
+ float q4 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z) + (quaternion1.W * quaternion2.W);
+ bool flag = false;
+ if (q4 < 0.0F)
+ {
+ flag = true;
+ q4 = -q4;
+ }
+ if (q4 > 0.999999F)
+ {
+ q3 = 1.0F - amount;
+ q2 = flag ? -amount : amount;
+ }
+ else
+ {
+ float q5 = (float)System.Math.Acos((double)q4);
+ float q6 = (float)(1.0 / System.Math.Sin((double)q5));
+ q3 = (float)System.Math.Sin((double)((1.0F - amount) * q5)) * q6;
+ q2 = flag ? (float)-System.Math.Sin((double)(amount * q5)) * q6 : (float)System.Math.Sin((double)(amount * q5)) * q6;
+ }
+ result.X = (q3 * quaternion1.X) + (q2 * quaternion2.X);
+ result.Y = (q3 * quaternion1.Y) + (q2 * quaternion2.Y);
+ result.Z = (q3 * quaternion1.Z) + (q2 * quaternion2.Z);
+ result.W = (q3 * quaternion1.W) + (q2 * quaternion2.W);
+ }
+
+
+ public static Quaternion Subtract(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ quaternion1.X -= quaternion2.X;
+ quaternion1.Y -= quaternion2.Y;
+ quaternion1.Z -= quaternion2.Z;
+ quaternion1.W -= quaternion2.W;
+ return quaternion1;
+ }
+
+
+ public static void Subtract(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
+ {
+ result.X = quaternion1.X - quaternion2.X;
+ result.Y = quaternion1.Y - quaternion2.Y;
+ result.Z = quaternion1.Z - quaternion2.Z;
+ result.W = quaternion1.W - quaternion2.W;
+ }
+
+
+ public static Quaternion Multiply(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ Quaternion result;
+ float f12 = (quaternion1.Y * quaternion2.Z) - (quaternion1.Z * quaternion2.Y);
+ float f11 = (quaternion1.Z * quaternion2.X) - (quaternion1.X * quaternion2.Z);
+ float f10 = (quaternion1.X * quaternion2.Y) - (quaternion1.Y * quaternion2.X);
+ float f9 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z);
+ result.X = (quaternion1.X * quaternion2.W) + (quaternion2.X * quaternion1.W) + f12;
+ result.Y = (quaternion1.Y * quaternion2.W) + (quaternion2.Y * quaternion1.W) + f11;
+ result.Z = (quaternion1.Z * quaternion2.W) + (quaternion2.Z * quaternion1.W) + f10;
+ result.W = (quaternion1.W * quaternion2.W) - f9;
+ return result;
+ }
+
+
+ public static Quaternion Multiply(Quaternion quaternion1, float scaleFactor)
+ {
+ quaternion1.X *= scaleFactor;
+ quaternion1.Y *= scaleFactor;
+ quaternion1.Z *= scaleFactor;
+ quaternion1.W *= scaleFactor;
+ return quaternion1;
+ }
+
+
+ public static void Multiply(ref Quaternion quaternion1, float scaleFactor, out Quaternion result)
+ {
+ result.X = quaternion1.X * scaleFactor;
+ result.Y = quaternion1.Y * scaleFactor;
+ result.Z = quaternion1.Z * scaleFactor;
+ result.W = quaternion1.W * scaleFactor;
+ }
+
+
+ public static void Multiply(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
+ {
+ float f12 = (quaternion1.Y * quaternion2.Z) - (quaternion1.Z * quaternion2.Y);
+ float f11 = (quaternion1.Z * quaternion2.X) - (quaternion1.X * quaternion2.Z);
+ float f10 = (quaternion1.X * quaternion2.Y) - (quaternion1.Y * quaternion2.X);
+ float f9 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z);
+ result.X = (quaternion1.X * quaternion2.W) + (quaternion2.X * quaternion1.W) + f12;
+ result.Y = (quaternion1.Y * quaternion2.W) + (quaternion2.Y * quaternion1.W) + f11;
+ result.Z = (quaternion1.Z * quaternion2.W) + (quaternion2.Z * quaternion1.W) + f10;
+ result.W = (quaternion1.W * quaternion2.W) - f9;
+ }
+
+
+ public static Quaternion Negate(Quaternion quaternion)
+ {
+ Quaternion result;
+ result.X = -quaternion.X;
+ result.Y = -quaternion.Y;
+ result.Z = -quaternion.Z;
+ result.W = -quaternion.W;
+ return result;
+ }
+
+
+ public static void Negate(ref Quaternion quaternion, out Quaternion result)
+ {
+ result.X = -quaternion.X;
+ result.Y = -quaternion.Y;
+ result.Z = -quaternion.Z;
+ result.W = -quaternion.W;
+ }
+
+
+ public void Normalize()
+ {
+ float f1 = 1.0F / (float)System.Math.Sqrt((double)((this.X * this.X) + (this.Y * this.Y) + (this.Z * this.Z) + (this.W * this.W)));
+ this.X *= f1;
+ this.Y *= f1;
+ this.Z *= f1;
+ this.W *= f1;
+ }
+
+
+ public static Quaternion Normalize(Quaternion quaternion)
+ {
+ Quaternion result;
+ float f1 = 1.0F / (float)System.Math.Sqrt((double)((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W)));
+ result.X = quaternion.X * f1;
+ result.Y = quaternion.Y * f1;
+ result.Z = quaternion.Z * f1;
+ result.W = quaternion.W * f1;
+ return result;
+ }
+
+
+ public static void Normalize(ref Quaternion quaternion, out Quaternion result)
+ {
+ float f1 = 1.0F / (float)System.Math.Sqrt((double)((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y) + (quaternion.Z * quaternion.Z) + (quaternion.W * quaternion.W)));
+ result.X = quaternion.X * f1;
+ result.Y = quaternion.Y * f1;
+ result.Z = quaternion.Z * f1;
+ result.W = quaternion.W * f1;
+ }
+
+
+ public static Quaternion operator +(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ quaternion1.X += quaternion2.X;
+ quaternion1.Y += quaternion2.Y;
+ quaternion1.Z += quaternion2.Z;
+ quaternion1.W += quaternion2.W;
+ return quaternion1;
+ }
+
+
+ public static Quaternion operator /(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ Quaternion result;
+
+ float w5 = 1.0F / ((quaternion2.X * quaternion2.X) + (quaternion2.Y * quaternion2.Y) + (quaternion2.Z * quaternion2.Z) + (quaternion2.W * quaternion2.W));
+ float w4 = -quaternion2.X * w5;
+ float w3 = -quaternion2.Y * w5;
+ float w2 = -quaternion2.Z * w5;
+ float w1 = quaternion2.W * w5;
+
+ result.X = (quaternion1.X * w1) + (w4 * quaternion1.W) + ((quaternion1.Y * w2) - (quaternion1.Z * w3));
+ result.Y = (quaternion1.Y * w1) + (w3 * quaternion1.W) + ((quaternion1.Z * w4) - (quaternion1.X * w2));
+ result.Z = (quaternion1.Z * w1) + (w2 * quaternion1.W) + ((quaternion1.X * w3) - (quaternion1.Y * w4));
+ result.W = (quaternion1.W * quaternion2.W * w5) - ((quaternion1.X * w4) + (quaternion1.Y * w3) + (quaternion1.Z * w2));
+ return result;
+ }
+
+
+ public static bool operator ==(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ return quaternion1.X == quaternion2.X
+ && quaternion1.Y == quaternion2.Y
+ && quaternion1.Z == quaternion2.Z
+ && quaternion1.W == quaternion2.W;
+ }
+
+
+ public static bool operator !=(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ return quaternion1.X != quaternion2.X
+ || quaternion1.Y != quaternion2.Y
+ || quaternion1.Z != quaternion2.Z
+ || quaternion1.W != quaternion2.W;
+ }
+
+
+ public static Quaternion operator *(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ Quaternion result;
+ float f12 = (quaternion1.Y * quaternion2.Z) - (quaternion1.Z * quaternion2.Y);
+ float f11 = (quaternion1.Z * quaternion2.X) - (quaternion1.X * quaternion2.Z);
+ float f10 = (quaternion1.X * quaternion2.Y) - (quaternion1.Y * quaternion2.X);
+ float f9 = (quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y) + (quaternion1.Z * quaternion2.Z);
+ result.X = (quaternion1.X * quaternion2.W) + (quaternion2.X * quaternion1.W) + f12;
+ result.Y = (quaternion1.Y * quaternion2.W) + (quaternion2.Y * quaternion1.W) + f11;
+ result.Z = (quaternion1.Z * quaternion2.W) + (quaternion2.Z * quaternion1.W) + f10;
+ result.W = (quaternion1.W * quaternion2.W) - f9;
+ return result;
+ }
+
+
+ public static Quaternion operator *(Quaternion quaternion1, float scaleFactor)
+ {
+ quaternion1.X *= scaleFactor;
+ quaternion1.Y *= scaleFactor;
+ quaternion1.Z *= scaleFactor;
+ quaternion1.W *= scaleFactor;
+ return quaternion1;
+ }
+
+
+ public static Quaternion operator -(Quaternion quaternion1, Quaternion quaternion2)
+ {
+ quaternion1.X -= quaternion2.X;
+ quaternion1.Y -= quaternion2.Y;
+ quaternion1.Z -= quaternion2.Z;
+ quaternion1.W -= quaternion2.W;
+ return quaternion1;
+ }
+
+
+ public static Quaternion operator -(Quaternion quaternion)
+ {
+ quaternion.X = -quaternion.X;
+ quaternion.Y = -quaternion.Y;
+ quaternion.Z = -quaternion.Z;
+ quaternion.W = -quaternion.W;
+ return quaternion;
+ }
+
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(32);
+ sb.Append("{X:");
+ sb.Append(this.X);
+ sb.Append(" Y:");
+ sb.Append(this.Y);
+ sb.Append(" Z:");
+ sb.Append(this.Z);
+ sb.Append(" W:");
+ sb.Append(this.W);
+ sb.Append("}");
+ return sb.ToString();
+ }
+
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Ray.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Ray.cs
new file mode 100644
index 0000000000..ecfdb39c26
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Ray.cs
@@ -0,0 +1,233 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ public struct Ray : IEquatable
+ {
+ #region Public Fields
+
+ public Vector3 Direction;
+ public Vector3 Position;
+
+ #endregion
+
+
+ #region Public Constructors
+
+ public Ray(Vector3 position, Vector3 direction)
+ {
+ this.Position = position;
+ this.Direction = direction;
+ }
+
+ #endregion
+
+
+ #region Public Methods
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Ray) ? this.Equals((Ray)obj) : false;
+ }
+
+
+ public bool Equals(Ray other)
+ {
+ return this.Position.Equals(other.Position) && this.Direction.Equals(other.Direction);
+ }
+
+
+ public override int GetHashCode()
+ {
+ return Position.GetHashCode() ^ Direction.GetHashCode();
+ }
+
+
+ public float? Intersects(BoundingBox box)
+ {
+ //first test if start in box
+ if (Position.X >= box.Min.X
+ && Position.X <= box.Max.X
+ && Position.Y >= box.Min.Y
+ && Position.Y <= box.Max.Y
+ && Position.Z >= box.Min.Z
+ && Position.Z <= box.Max.Z)
+ return 0.0f;// here we concidere cube is full and origine is in cube so intersect at origine
+
+ //Second we check each face
+ Vector3 maxT = new Vector3(-1.0f);
+ //Vector3 minT = new Vector3(-1.0f);
+ //calcul intersection with each faces
+ if (Position.X < box.Min.X && Direction.X != 0.0f)
+ maxT.X = (box.Min.X - Position.X) / Direction.X;
+ else if (Position.X > box.Max.X && Direction.X != 0.0f)
+ maxT.X = (box.Max.X - Position.X) / Direction.X;
+ if (Position.Y < box.Min.Y && Direction.Y != 0.0f)
+ maxT.Y = (box.Min.Y - Position.Y) / Direction.Y;
+ else if (Position.Y > box.Max.Y && Direction.Y != 0.0f)
+ maxT.Y = (box.Max.Y - Position.Y) / Direction.Y;
+ if (Position.Z < box.Min.Z && Direction.Z != 0.0f)
+ maxT.Z = (box.Min.Z - Position.Z) / Direction.Z;
+ else if (Position.Z > box.Max.Z && Direction.Z != 0.0f)
+ maxT.Z = (box.Max.Z - Position.Z) / Direction.Z;
+
+ //get the maximum maxT
+ if (maxT.X > maxT.Y && maxT.X > maxT.Z)
+ {
+ if (maxT.X < 0.0f)
+ return null;// ray go on opposite of face
+ //coordonate of hit point of face of cube
+ float coord = Position.Z + maxT.X * Direction.Z;
+ // if hit point coord ( intersect face with ray) is out of other plane coord it miss
+ if (coord < box.Min.Z || coord > box.Max.Z)
+ return null;
+ coord = Position.Y + maxT.X * Direction.Y;
+ if (coord < box.Min.Y || coord > box.Max.Y)
+ return null;
+ return maxT.X;
+ }
+ if (maxT.Y > maxT.X && maxT.Y > maxT.Z)
+ {
+ if (maxT.Y < 0.0f)
+ return null;// ray go on opposite of face
+ //coordonate of hit point of face of cube
+ float coord = Position.Z + maxT.Y * Direction.Z;
+ // if hit point coord ( intersect face with ray) is out of other plane coord it miss
+ if (coord < box.Min.Z || coord > box.Max.Z)
+ return null;
+ coord = Position.X + maxT.Y * Direction.X;
+ if (coord < box.Min.X || coord > box.Max.X)
+ return null;
+ return maxT.Y;
+ }
+ else //Z
+ {
+ if (maxT.Z < 0.0f)
+ return null;// ray go on opposite of face
+ //coordonate of hit point of face of cube
+ float coord = Position.X + maxT.Z * Direction.X;
+ // if hit point coord ( intersect face with ray) is out of other plane coord it miss
+ if (coord < box.Min.X || coord > box.Max.X)
+ return null;
+ coord = Position.Y + maxT.Z * Direction.Y;
+ if (coord < box.Min.Y || coord > box.Max.Y)
+ return null;
+ return maxT.Z;
+ }
+ }
+
+
+ public void Intersects(ref BoundingBox box, out float? result)
+ {
+ result = Intersects(box);
+ }
+
+
+ public float? Intersects(BoundingFrustum frustum)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public float? Intersects(BoundingSphere sphere)
+ {
+ float? result;
+ Intersects(ref sphere, out result);
+ return result;
+ }
+
+ public float? Intersects(Plane plane)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref Plane plane, out float? result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref BoundingSphere sphere, out float? result)
+ {
+ // Find the vector between where the ray starts the the sphere's centre
+ Vector3 difference = sphere.Center - this.Position;
+
+ float differenceLengthSquared = difference.LengthSquared();
+ float sphereRadiusSquared = sphere.Radius * sphere.Radius;
+
+ float distanceAlongRay;
+
+ // If the distance between the ray start and the sphere's centre is less than
+ // the radius of the sphere, it means we've intersected. N.B. checking the LengthSquared is faster.
+ if (differenceLengthSquared < sphereRadiusSquared)
+ {
+ result = 0.0f;
+ return;
+ }
+
+ Vector3.Dot(ref this.Direction, ref difference, out distanceAlongRay);
+ // If the ray is pointing away from the sphere then we don't ever intersect
+ if (distanceAlongRay < 0)
+ {
+ result = null;
+ return;
+ }
+
+ // Next we kinda use Pythagoras to check if we are within the bounds of the sphere
+ // if x = radius of sphere
+ // if y = distance between ray position and sphere centre
+ // if z = the distance we've travelled along the ray
+ // if x^2 + z^2 - y^2 < 0, we do not intersect
+ float dist = sphereRadiusSquared + distanceAlongRay * distanceAlongRay - differenceLengthSquared;
+
+ result = (dist < 0) ? null : distanceAlongRay - (float?)Math.Sqrt(dist);
+ }
+
+
+ public static bool operator !=(Ray a, Ray b)
+ {
+ return !a.Equals(b);
+ }
+
+
+ public static bool operator ==(Ray a, Ray b)
+ {
+ return a.Equals(b);
+ }
+
+
+ public override string ToString()
+ {
+ return string.Format("{{Position:{0} Direction:{1}}}", Position.ToString(), Direction.ToString());
+ }
+ #endregion
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Rectangle.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Rectangle.cs
new file mode 100644
index 0000000000..69924053e0
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Rectangle.cs
@@ -0,0 +1,312 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.Globalization;
+using System.ComponentModel;
+
+
+namespace BizHawk.Bizware.BizwareGL
+{
+
+
+ public struct Rectangle : IEquatable
+ {
+ #region Private Fields
+
+ private static Rectangle emptyRectangle = new Rectangle();
+
+ #endregion Private Fields
+
+
+ #region Public Fields
+
+ public int X;
+ public int Y;
+ public int Width;
+ public int Height;
+
+ #endregion Public Fields
+
+
+ #region Public Properties
+
+ public Point Center
+ {
+ get
+ {
+ return new Point(this.X + (this.Width / 2), this.Y + (this.Height / 2));
+ }
+ }
+
+ public Point Location
+ {
+ get
+ {
+ return new Point(this.X, this.Y);
+ }
+ set
+ {
+ this.X = value.X;
+ this.Y = value.Y;
+ }
+ }
+
+ public bool IsEmpty
+ {
+ get
+ {
+ return ((((this.Width == 0) && (this.Height == 0)) && (this.X == 0)) && (this.Y == 0));
+ }
+ }
+
+ public static Rectangle Empty
+ {
+ get { return emptyRectangle; }
+ }
+
+ public int Left
+ {
+ get { return this.X; }
+ }
+
+ public int Right
+ {
+ get { return (this.X + this.Width); }
+ }
+
+ public int Top
+ {
+ get { return this.Y; }
+ }
+
+ public int Bottom
+ {
+ get { return (this.Y + this.Height); }
+ }
+
+ #endregion Public Properties
+
+
+ #region Constructors
+
+ public Rectangle(int x, int y, int width, int height)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Width = width;
+ this.Height = height;
+ }
+
+ #endregion Constructors
+
+
+ #region Public Methods
+
+ public static Rectangle Union(Rectangle value1, Rectangle value2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Rectangle Intersect(Rectangle value1, Rectangle value2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Intersects(ref Rectangle value, out bool result)
+ {
+ result = (((value.X < (this.X + this.Width)) && (this.X < (value.X + value.Width))) && (value.Y < (this.Y + this.Height))) && (this.Y < (value.Y + value.Height));
+ }
+
+ public bool Contains(Point value)
+ {
+ return ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
+ }
+
+ public bool Contains(Rectangle value)
+ {
+ return ((((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height)));
+ }
+
+ public void Contains(ref Rectangle value, out bool result)
+ {
+ result = (((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height));
+ }
+
+ public bool Contains(int x, int y)
+ {
+ return ((((this.X <= x) && (x < (this.X + this.Width))) && (this.Y <= y)) && (y < (this.Y + this.Height)));
+ }
+
+ public void Contains(ref Point value, out bool result)
+ {
+ result = (((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height));
+ }
+
+ public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static bool operator ==(Rectangle a, Rectangle b)
+ {
+ return ((a.X == b.X) && (a.Y == b.Y) && (a.Width == b.Width) && (a.Height == b.Height));
+ }
+
+ public static bool operator !=(Rectangle a, Rectangle b)
+ {
+ return !(a == b);
+ }
+
+ ///
+ /// Moves Rectangle for both Point values.
+ ///
+ ///
+ /// A
+ ///
+ public void Offset(Point offset)
+ {
+ X += offset.X;
+ Y += offset.Y;
+ }
+
+ ///
+ /// Moves rectangle for both values.
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public void Offset(int offsetX, int offsetY)
+ {
+ X += offsetX;
+ Y += offsetY;
+ }
+
+ ///
+ /// Grows the Rectangle. Down right point is in the same position.
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public void Inflate(int horizontalValue, int verticalValue)
+ {
+ X -= horizontalValue;
+ Y -= verticalValue;
+ Width += horizontalValue * 2;
+ Height += verticalValue * 2;
+ }
+
+ ///
+ /// It checks if two rectangle intersects.
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public bool Intersects(Rectangle rect)
+ {
+ if(this.X <= rect.X)
+ {
+ if((this.X + this.Width) > rect.X)
+ {
+ if(this.Y < rect.Y)
+ {
+ if((this.Y + this.Height) > rect.Y)
+ return true;
+ }
+ else
+ {
+ if((rect.Y + rect.Height) > this.Y)
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if((rect.X + rect.Width) > this.X)
+ {
+ if(this.Y < rect.Y)
+ {
+ if((this.Y + this.Height) > rect.Y)
+ return true;
+ }
+ else
+ {
+ if((rect.Y + rect.Height) > this.Y)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public bool Equals(Rectangle other)
+ {
+ return this == other;
+ }
+
+ ///
+ /// Returns true if recangles are same
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public override bool Equals(object obj)
+ {
+ return (obj is Rectangle) ? this == ((Rectangle)obj) : false;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{{X:{0} Y:{1} Width:{2} Height:{3}}}", X, Y, Width, Height);
+ }
+
+ public override int GetHashCode()
+ {
+ return (this.X ^ this.Y ^ this.Width ^ this.Height);
+ }
+
+ #endregion Public Methods
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Size.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Size.cs
new file mode 100644
index 0000000000..0524e0e10e
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Size.cs
@@ -0,0 +1,368 @@
+//
+// System.Drawing.Size.cs
+//
+// Author:
+// Mike Kestner (mkestner@speakeasy.net)
+//
+// Copyright (C) 2001 Mike Kestner
+// Copyright (C) 2004 Novell, Inc. http://www.novell.com
+//
+
+//The MIT license:
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ [ComVisible(true)]
+ public struct Size
+ {
+
+ // Private Height and width fields.
+ private int width, height;
+
+ // -----------------------
+ // Public Shared Members
+ // -----------------------
+
+ ///
+ /// Empty Shared Field
+ ///
+ ///
+ ///
+ /// An uninitialized Size Structure.
+ ///
+
+ public static readonly Size Empty;
+
+ ///
+ /// Ceiling Shared Method
+ ///
+ ///
+ ///
+ /// Produces a Size structure from a SizeF structure by
+ /// taking the ceiling of the Width and Height properties.
+ ///
+
+ public static Size Ceiling(SizeF value)
+ {
+ int w, h;
+ checked
+ {
+ w = (int)Math.Ceiling(value.Width);
+ h = (int)Math.Ceiling(value.Height);
+ }
+
+ return new Size(w, h);
+ }
+
+ ///
+ /// Round Shared Method
+ ///
+ ///
+ ///
+ /// Produces a Size structure from a SizeF structure by
+ /// rounding the Width and Height properties.
+ ///
+
+ public static Size Round(SizeF value)
+ {
+ int w, h;
+ checked
+ {
+ w = (int)Math.Round(value.Width);
+ h = (int)Math.Round(value.Height);
+ }
+
+ return new Size(w, h);
+ }
+
+ ///
+ /// Truncate Shared Method
+ ///
+ ///
+ ///
+ /// Produces a Size structure from a SizeF structure by
+ /// truncating the Width and Height properties.
+ ///
+
+ public static Size Truncate(SizeF value)
+ {
+ int w, h;
+ checked
+ {
+ w = (int)value.Width;
+ h = (int)value.Height;
+ }
+
+ return new Size(w, h);
+ }
+
+ ///
+ /// Addition Operator
+ ///
+ ///
+ ///
+ /// Addition of two Size structures.
+ ///
+
+ public static Size operator +(Size sz1, Size sz2)
+ {
+ return new Size(sz1.Width + sz2.Width,
+ sz1.Height + sz2.Height);
+ }
+
+ ///
+ /// Equality Operator
+ ///
+ ///
+ ///
+ /// Compares two Size objects. The return value is
+ /// based on the equivalence of the Width and Height
+ /// properties of the two Sizes.
+ ///
+
+ public static bool operator ==(Size sz1, Size sz2)
+ {
+ return ((sz1.Width == sz2.Width) &&
+ (sz1.Height == sz2.Height));
+ }
+
+ ///
+ /// Inequality Operator
+ ///
+ ///
+ ///
+ /// Compares two Size objects. The return value is
+ /// based on the equivalence of the Width and Height
+ /// properties of the two Sizes.
+ ///
+
+ public static bool operator !=(Size sz1, Size sz2)
+ {
+ return ((sz1.Width != sz2.Width) ||
+ (sz1.Height != sz2.Height));
+ }
+
+ ///
+ /// Subtraction Operator
+ ///
+ ///
+ ///
+ /// Subtracts two Size structures.
+ ///
+
+ public static Size operator -(Size sz1, Size sz2)
+ {
+ return new Size(sz1.Width - sz2.Width,
+ sz1.Height - sz2.Height);
+ }
+
+ ///
+ /// Size to Point Conversion
+ ///
+ ///
+ ///
+ /// Returns a Point based on the dimensions of a given
+ /// Size. Requires explicit cast.
+ ///
+
+ public static explicit operator Point(Size size)
+ {
+ return new Point(size.Width, size.Height);
+ }
+
+ ///
+ /// Size to SizeF Conversion
+ ///
+ ///
+ ///
+ /// Creates a SizeF based on the dimensions of a given
+ /// Size. No explicit cast is required.
+ ///
+
+ public static implicit operator SizeF(Size p)
+ {
+ return new SizeF(p.Width, p.Height);
+ }
+
+
+ // -----------------------
+ // Public Constructors
+ // -----------------------
+
+ ///
+ /// Size Constructor
+ ///
+ ///
+ ///
+ /// Creates a Size from a Point value.
+ ///
+
+ public Size(Point pt)
+ {
+ width = pt.X;
+ height = pt.Y;
+ }
+
+ ///
+ /// Size Constructor
+ ///
+ ///
+ ///
+ /// Creates a Size from specified dimensions.
+ ///
+
+ public Size(int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ // -----------------------
+ // Public Instance Members
+ // -----------------------
+
+ ///
+ /// IsEmpty Property
+ ///
+ ///
+ ///
+ /// Indicates if both Width and Height are zero.
+ ///
+
+ [Browsable(false)]
+ public bool IsEmpty
+ {
+ get
+ {
+ return ((width == 0) && (height == 0));
+ }
+ }
+
+ ///
+ /// Width Property
+ ///
+ ///
+ ///
+ /// The Width coordinate of the Size.
+ ///
+
+ public int Width
+ {
+ get
+ {
+ return width;
+ }
+ set
+ {
+ width = value;
+ }
+ }
+
+ ///
+ /// Height Property
+ ///
+ ///
+ ///
+ /// The Height coordinate of the Size.
+ ///
+
+ public int Height
+ {
+ get
+ {
+ return height;
+ }
+ set
+ {
+ height = value;
+ }
+ }
+
+ ///
+ /// Equals Method
+ ///
+ ///
+ ///
+ /// Checks equivalence of this Size and another object.
+ ///
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is Size))
+ return false;
+
+ return (this == (Size)obj);
+ }
+
+ ///
+ /// GetHashCode Method
+ ///
+ ///
+ ///
+ /// Calculates a hashing value.
+ ///
+
+ public override int GetHashCode()
+ {
+ return width ^ height;
+ }
+
+ ///
+ /// ToString Method
+ ///
+ ///
+ ///
+ /// Formats the Size as a string in coordinate notation.
+ ///
+
+ public override string ToString()
+ {
+ return String.Format("{{Width={0}, Height={1}}}", width, height);
+ }
+
+#if NET_2_0
+ public static Size Add (Size sz1, Size sz2)
+ {
+ return new Size (sz1.Width + sz2.Width,
+ sz1.Height + sz2.Height);
+
+ }
+
+ public static Size Subtract (Size sz1, Size sz2)
+ {
+ return new Size (sz1.Width - sz2.Width,
+ sz1.Height - sz2.Height);
+ }
+#endif
+
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector2.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector2.cs
new file mode 100644
index 0000000000..b03b511b1c
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector2.cs
@@ -0,0 +1,599 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Authors
+ * Alan McGovern
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct Vector2 : IEquatable
+ {
+ #region Private Fields
+
+ private static Vector2 zeroVector = new Vector2(0f, 0f);
+ private static Vector2 unitVector = new Vector2(1f, 1f);
+ private static Vector2 unitXVector = new Vector2(1f, 0f);
+ private static Vector2 unitYVector = new Vector2(0f, 1f);
+
+ #endregion Private Fields
+
+
+ #region Public Fields
+
+ public float X;
+ public float Y;
+
+ #endregion Public Fields
+
+
+ #region Properties
+
+ public static Vector2 Zero
+ {
+ get { return zeroVector; }
+ }
+
+ public static Vector2 One
+ {
+ get { return unitVector; }
+ }
+
+ public static Vector2 UnitX
+ {
+ get { return unitXVector; }
+ }
+
+ public static Vector2 UnitY
+ {
+ get { return unitYVector; }
+ }
+
+ #endregion Properties
+
+
+ #region Constructors
+
+ ///
+ /// Constructor foe standard 2D vector.
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public Vector2(float x, float y)
+ {
+ this.X = x;
+ this.Y = y;
+ }
+
+ ///
+ /// Constructor for "square" vector.
+ ///
+ ///
+ /// A
+ ///
+ public Vector2(float value)
+ {
+ this.X = value;
+ this.Y = value;
+ }
+
+ #endregion Constructors
+
+
+ #region Public Methods
+
+ public static void Reflect(ref Vector2 vector, ref Vector2 normal, out Vector2 result)
+ {
+ float dot = Dot(vector, normal);
+ result.X = vector.X - ((2f * dot) * normal.X);
+ result.Y = vector.Y - ((2f * dot) * normal.Y);
+ }
+
+ public static Vector2 Reflect(Vector2 vector, Vector2 normal)
+ {
+ Vector2 result;
+ Reflect(ref vector, ref normal, out result);
+ return result;
+ }
+
+ public static Vector2 Add(Vector2 value1, Vector2 value2)
+ {
+ value1.X += value2.X;
+ value1.Y += value2.Y;
+ return value1;
+ }
+
+ public static void Add(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
+ {
+ result.X = value1.X + value2.X;
+ result.Y = value1.Y + value2.Y;
+ }
+
+ public static Vector2 Barycentric(Vector2 value1, Vector2 value2, Vector2 value3, float amount1, float amount2)
+ {
+ return new Vector2(
+ MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
+ MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2));
+ }
+
+ public static void Barycentric(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, float amount1, float amount2, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
+ MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2));
+ }
+
+ public static Vector2 CatmullRom(Vector2 value1, Vector2 value2, Vector2 value3, Vector2 value4, float amount)
+ {
+ return new Vector2(
+ MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
+ MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount));
+ }
+
+ public static void CatmullRom(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, ref Vector2 value4, float amount, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
+ MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount));
+ }
+
+ public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
+ {
+ return new Vector2(
+ MathHelper.Clamp(value1.X, min.X, max.X),
+ MathHelper.Clamp(value1.Y, min.Y, max.Y));
+ }
+
+ public static void Clamp(ref Vector2 value1, ref Vector2 min, ref Vector2 max, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.Clamp(value1.X, min.X, max.X),
+ MathHelper.Clamp(value1.Y, min.Y, max.Y));
+ }
+
+ ///
+ /// Returns float precison distanve between two vectors
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public static float Distance(Vector2 value1, Vector2 value2)
+ {
+ return (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y));
+ }
+
+
+ public static void Distance(ref Vector2 value1, ref Vector2 value2, out float result)
+ {
+ result = (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y));
+ }
+
+ public static float DistanceSquared(Vector2 value1, Vector2 value2)
+ {
+ return (value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y);
+ }
+
+ public static void DistanceSquared(ref Vector2 value1, ref Vector2 value2, out float result)
+ {
+ result = (value1.X - value2.X) * (value1.X - value2.X) + (value1.Y - value2.Y) * (value1.Y - value2.Y);
+ }
+
+ ///
+ /// Devide first vector with the secund vector
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ public static Vector2 Divide(Vector2 value1, Vector2 value2)
+ {
+ value1.X /= value2.X;
+ value1.Y /= value2.Y;
+ return value1;
+ }
+
+ public static void Divide(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
+ {
+ result.X = value1.X / value2.X;
+ result.Y = value1.Y / value2.Y;
+ }
+
+ public static Vector2 Divide(Vector2 value1, float divider)
+ {
+ float factor = 1.0f / divider;
+ value1.X *= factor;
+ value1.Y *= factor;
+ return value1;
+ }
+
+ public static void Divide(ref Vector2 value1, float divider, out Vector2 result)
+ {
+ float factor = 1.0f / divider;
+ result.X = value1.X * factor;
+ result.Y = value1.Y * factor;
+ }
+
+ public static float Dot(Vector2 value1, Vector2 value2)
+ {
+ return value1.X * value2.X + value1.Y * value2.Y;
+ }
+
+ public static void Dot(ref Vector2 value1, ref Vector2 value2, out float result)
+ {
+ result = value1.X * value2.X + value1.Y * value2.Y;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Vector2) ? this == ((Vector2)obj) : false;
+ }
+
+ public bool Equals(Vector2 other)
+ {
+ return this == other;
+ }
+
+ public override int GetHashCode()
+ {
+ return (int)(this.X + this.Y);
+ }
+
+ public static Vector2 Hermite(Vector2 value1, Vector2 tangent1, Vector2 value2, Vector2 tangent2, float amount)
+ {
+ value1.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
+ value1.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
+ return value1;
+ }
+
+ public static void Hermite(ref Vector2 value1, ref Vector2 tangent1, ref Vector2 value2, ref Vector2 tangent2, float amount, out Vector2 result)
+ {
+ result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
+ result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
+ }
+
+ public float Length()
+ {
+ return (float)Math.Sqrt((double)(X * X + Y * Y));
+ }
+
+ public float LengthSquared()
+ {
+ return X * X + Y * Y;
+ }
+
+ public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
+ {
+ return new Vector2(
+ MathHelper.Lerp(value1.X, value2.X, amount),
+ MathHelper.Lerp(value1.Y, value2.Y, amount));
+ }
+
+ public static void Lerp(ref Vector2 value1, ref Vector2 value2, float amount, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.Lerp(value1.X, value2.X, amount),
+ MathHelper.Lerp(value1.Y, value2.Y, amount));
+ }
+
+ public static Vector2 Max(Vector2 value1, Vector2 value2)
+ {
+ return new Vector2(
+ MathHelper.Max(value1.X, value2.X),
+ MathHelper.Max(value1.Y, value2.Y));
+ }
+
+ public static void Max(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.Max(value1.X, value2.X),
+ MathHelper.Max(value1.Y, value2.Y));
+ }
+
+ public static Vector2 Min(Vector2 value1, Vector2 value2)
+ {
+ return new Vector2(
+ MathHelper.Min(value1.X, value2.X),
+ MathHelper.Min(value1.Y, value2.Y));
+ }
+
+ public static void Min(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.Min(value1.X, value2.X),
+ MathHelper.Min(value1.Y, value2.Y));
+ }
+
+ public static Vector2 Multiply(Vector2 value1, Vector2 value2)
+ {
+ value1.X *= value2.X;
+ value1.Y *= value2.Y;
+ return value1;
+ }
+
+ public static Vector2 Multiply(Vector2 value1, float scaleFactor)
+ {
+ value1.X *= scaleFactor;
+ value1.Y *= scaleFactor;
+ return value1;
+ }
+
+ public static void Multiply(ref Vector2 value1, float scaleFactor, out Vector2 result)
+ {
+ result.X = value1.X * scaleFactor;
+ result.Y = value1.Y * scaleFactor;
+ }
+
+ public static void Multiply(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
+ {
+ result.X = value1.X * value2.X;
+ result.Y = value1.Y * value2.Y;
+ }
+
+ public static Vector2 Negate(Vector2 value)
+ {
+ value.X = -value.X;
+ value.Y = -value.Y;
+ return value;
+ }
+
+ public static void Negate(ref Vector2 value, out Vector2 result)
+ {
+ result.X = -value.X;
+ result.Y = -value.Y;
+ }
+
+ public void Normalize()
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(X * X + Y * Y));
+ X *= factor;
+ Y *= factor;
+ }
+
+ public static Vector2 Normalize(Vector2 value)
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y));
+ value.X *= factor;
+ value.Y *= factor;
+ return value;
+ }
+
+ public static void Normalize(ref Vector2 value, out Vector2 result)
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y));
+ result.X = value.X * factor;
+ result.Y = value.Y * factor;
+ }
+
+ public static Vector2 SmoothStep(Vector2 value1, Vector2 value2, float amount)
+ {
+ return new Vector2(
+ MathHelper.SmoothStep(value1.X, value2.X, amount),
+ MathHelper.SmoothStep(value1.Y, value2.Y, amount));
+ }
+
+ public static void SmoothStep(ref Vector2 value1, ref Vector2 value2, float amount, out Vector2 result)
+ {
+ result = new Vector2(
+ MathHelper.SmoothStep(value1.X, value2.X, amount),
+ MathHelper.SmoothStep(value1.Y, value2.Y, amount));
+ }
+
+ public static Vector2 Subtract(Vector2 value1, Vector2 value2)
+ {
+ value1.X -= value2.X;
+ value1.Y -= value2.Y;
+ return value1;
+ }
+
+ public static void Subtract(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
+ {
+ result.X = value1.X - value2.X;
+ result.Y = value1.Y - value2.Y;
+ }
+
+ public static Vector2 Transform(Vector2 position, Matrix matrix)
+ {
+ Transform(ref position, ref matrix, out position);
+ return position;
+ }
+
+ public static void Transform(ref Vector2 position, ref Matrix matrix, out Vector2 result)
+ {
+ result = new Vector2((position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41,
+ (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42);
+ }
+
+ public static Vector2 Transform(Vector2 value, Quaternion rotation)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(ref Vector2 value, ref Quaternion rotation, out Vector2 result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector2[] sourceArray, ref Matrix matrix, Vector2[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector2[] sourceArray, ref Quaternion rotation, Vector2[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector2[] sourceArray, int sourceIndex, ref Matrix matrix, Vector2[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector2[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector2[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Vector2 TransformNormal(Vector2 normal, Matrix matrix)
+ {
+ Vector2.TransformNormal(ref normal, ref matrix, out normal);
+ return normal;
+ }
+
+ public static void TransformNormal(ref Vector2 normal, ref Matrix matrix, out Vector2 result)
+ {
+ result = new Vector2((normal.X * matrix.M11) + (normal.Y * matrix.M21),
+ (normal.X * matrix.M12) + (normal.Y * matrix.M22));
+ }
+
+ public static void TransformNormal(Vector2[] sourceArray, ref Matrix matrix, Vector2[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void TransformNormal(Vector2[] sourceArray, int sourceIndex, ref Matrix matrix, Vector2[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(24);
+ sb.Append("{X:");
+ sb.Append(this.X);
+ sb.Append(" Y:");
+ sb.Append(this.Y);
+ sb.Append("}");
+ return sb.ToString();
+ }
+
+ #endregion Public Methods
+
+
+ #region Operators
+
+ public static Vector2 operator -(Vector2 value)
+ {
+ value.X = -value.X;
+ value.Y = -value.Y;
+ return value;
+ }
+
+
+ public static bool operator ==(Vector2 value1, Vector2 value2)
+ {
+ return value1.X == value2.X && value1.Y == value2.Y;
+ }
+
+
+ public static bool operator !=(Vector2 value1, Vector2 value2)
+ {
+ return value1.X != value2.X || value1.Y != value2.Y;
+ }
+
+
+ public static Vector2 operator +(Vector2 value1, Vector2 value2)
+ {
+ value1.X += value2.X;
+ value1.Y += value2.Y;
+ return value1;
+ }
+
+
+ public static Vector2 operator -(Vector2 value1, Vector2 value2)
+ {
+ value1.X -= value2.X;
+ value1.Y -= value2.Y;
+ return value1;
+ }
+
+
+ public static Vector2 operator *(Vector2 value1, Vector2 value2)
+ {
+ value1.X *= value2.X;
+ value1.Y *= value2.Y;
+ return value1;
+ }
+
+
+ public static Vector2 operator *(Vector2 value, float scaleFactor)
+ {
+ value.X *= scaleFactor;
+ value.Y *= scaleFactor;
+ return value;
+ }
+
+
+ public static Vector2 operator *(float scaleFactor, Vector2 value)
+ {
+ value.X *= scaleFactor;
+ value.Y *= scaleFactor;
+ return value;
+ }
+
+
+ public static Vector2 operator /(Vector2 value1, Vector2 value2)
+ {
+ value1.X /= value2.X;
+ value1.Y /= value2.Y;
+ return value1;
+ }
+
+
+ public static Vector2 operator /(Vector2 value1, float divider)
+ {
+ float factor = 1 / divider;
+ value1.X *= factor;
+ value1.Y *= factor;
+ return value1;
+ }
+
+ #endregion Operators
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector3.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector3.cs
new file mode 100644
index 0000000000..7a93a379fc
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector3.cs
@@ -0,0 +1,679 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Authors:
+ * Alan McGovern
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct Vector3 : IEquatable
+ {
+ #region Private Fields
+
+ private static Vector3 zero = new Vector3(0f, 0f, 0f);
+ private static Vector3 one = new Vector3(1f, 1f, 1f);
+ private static Vector3 unitX = new Vector3(1f, 0f, 0f);
+ private static Vector3 unitY = new Vector3(0f, 1f, 0f);
+ private static Vector3 unitZ = new Vector3(0f, 0f, 1f);
+ private static Vector3 up = new Vector3(0f, 1f, 0f);
+ private static Vector3 down = new Vector3(0f, -1f, 0f);
+ private static Vector3 right = new Vector3(1f, 0f, 0f);
+ private static Vector3 left = new Vector3(-1f, 0f, 0f);
+ private static Vector3 forward = new Vector3(0f, 0f, -1f);
+ private static Vector3 backward = new Vector3(0f, 0f, 1f);
+
+ #endregion Private Fields
+
+
+ #region Public Fields
+
+ public float X;
+ public float Y;
+ public float Z;
+
+ #endregion Public Fields
+
+
+ #region Properties
+
+ public static Vector3 Zero
+ {
+ get { return zero; }
+ }
+
+ public static Vector3 One
+ {
+ get { return one; }
+ }
+
+ public static Vector3 UnitX
+ {
+ get { return unitX; }
+ }
+
+ public static Vector3 UnitY
+ {
+ get { return unitY; }
+ }
+
+ public static Vector3 UnitZ
+ {
+ get { return unitZ; }
+ }
+
+ public static Vector3 Up
+ {
+ get { return up; }
+ }
+
+ public static Vector3 Down
+ {
+ get { return down; }
+ }
+
+ public static Vector3 Right
+ {
+ get { return right; }
+ }
+
+ public static Vector3 Left
+ {
+ get { return left; }
+ }
+
+ public static Vector3 Forward
+ {
+ get { return forward; }
+ }
+
+ public static Vector3 Backward
+ {
+ get { return backward; }
+ }
+
+ #endregion Properties
+
+
+ #region Constructors
+
+ public Vector3(float x, float y, float z)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Z = z;
+ }
+
+
+ public Vector3(float value)
+ {
+ this.X = value;
+ this.Y = value;
+ this.Z = value;
+ }
+
+
+ public Vector3(Vector2 value, float z)
+ {
+ this.X = value.X;
+ this.Y = value.Y;
+ this.Z = z;
+ }
+
+
+ #endregion Constructors
+
+
+ #region Public Methods
+
+ public static Vector3 Add(Vector3 value1, Vector3 value2)
+ {
+ value1.X += value2.X;
+ value1.Y += value2.Y;
+ value1.Z += value2.Z;
+ return value1;
+ }
+
+ public static void Add(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
+ {
+ result.X = value1.X + value2.X;
+ result.Y = value1.Y + value2.Y;
+ result.Z = value1.Z + value2.Z;
+ }
+
+ public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2)
+ {
+ return new Vector3(
+ MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
+ MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
+ MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
+ }
+
+ public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
+ MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
+ MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2));
+ }
+
+ public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount)
+ {
+ return new Vector3(
+ MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
+ MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
+ MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
+ }
+
+ public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
+ MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
+ MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount));
+ }
+
+ public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max)
+ {
+ return new Vector3(
+ MathHelper.Clamp(value1.X, min.X, max.X),
+ MathHelper.Clamp(value1.Y, min.Y, max.Y),
+ MathHelper.Clamp(value1.Z, min.Z, max.Z));
+ }
+
+ public static void Clamp(ref Vector3 value1, ref Vector3 min, ref Vector3 max, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.Clamp(value1.X, min.X, max.X),
+ MathHelper.Clamp(value1.Y, min.Y, max.Y),
+ MathHelper.Clamp(value1.Z, min.Z, max.Z));
+ }
+
+ public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
+ {
+ Vector3 result;
+ result.X = vector1.Y * vector2.Z - vector2.Y * vector1.Z;
+ result.Y = vector2.X * vector1.Z - vector1.X * vector2.Z;
+ result.Z = vector1.X * vector2.Y - vector2.X * vector1.Y;
+ return result;
+ }
+
+ public static void Cross(ref Vector3 vector1, ref Vector3 vector2, out Vector3 result)
+ {
+ result.X = vector1.Y * vector2.Z - vector2.Y * vector1.Z;
+ result.Y = vector2.X * vector1.Z - vector1.X * vector2.Z;
+ result.Z = vector1.X * vector2.Y - vector2.X * vector1.Y;
+ }
+
+ public static float Distance(Vector3 value1, Vector3 value2)
+ {
+ return (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z));
+ }
+
+ public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result)
+ {
+ result = (float)Math.Sqrt((value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z));
+ }
+
+ public static float DistanceSquared(Vector3 value1, Vector3 value2)
+ {
+ return (value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z); ;
+ }
+
+ public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result)
+ {
+ result = (value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z);
+ }
+
+ public static Vector3 Divide(Vector3 value1, Vector3 value2)
+ {
+ value1.X /= value2.X;
+ value1.Y /= value2.Y;
+ value1.Z /= value2.Z;
+ return value1;
+ }
+
+ public static Vector3 Divide(Vector3 value1, float value2)
+ {
+ float factor = 1.0f / value2;
+ value1.X *= factor;
+ value1.Y *= factor;
+ value1.Z *= factor;
+ return value1;
+ }
+
+ public static void Divide(ref Vector3 value1, float divisor, out Vector3 result)
+ {
+ float factor = 1.0f / divisor;
+ result.X = value1.X * factor;
+ result.Y = value1.Y * factor;
+ result.Z = value1.Z * factor;
+ }
+
+ public static void Divide(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
+ {
+ result.X = value1.X / value2.X;
+ result.Y = value1.Y / value2.Y;
+ result.Z = value1.Z / value2.Z;
+ }
+
+ public static float Dot(Vector3 vector1, Vector3 vector2)
+ {
+ return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
+ }
+
+ public static void Dot(ref Vector3 vector1, ref Vector3 vector2, out float result)
+ {
+ result = vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Vector3) ? this == (Vector3)obj : false;
+ }
+
+ public bool Equals(Vector3 other)
+ {
+ return this == other;
+ }
+
+ public override int GetHashCode()
+ {
+ return (int)(this.X + this.Y + this.Z);
+ }
+
+ public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount)
+ {
+ value1.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
+ value1.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
+ value1.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
+ return value1;
+ }
+
+ public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result)
+ {
+ result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
+ result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
+ result.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
+ }
+
+ public float Length()
+ {
+ return (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z));
+ }
+
+ public float LengthSquared()
+ {
+ return X * X + Y * Y + Z * Z;
+ }
+
+ public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
+ {
+ return new Vector3(
+ MathHelper.Lerp(value1.X, value2.X, amount),
+ MathHelper.Lerp(value1.Y, value2.Y, amount),
+ MathHelper.Lerp(value1.Z, value2.Z, amount));
+ }
+
+ public static void Lerp(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.Lerp(value1.X, value2.X, amount),
+ MathHelper.Lerp(value1.Y, value2.Y, amount),
+ MathHelper.Lerp(value1.Z, value2.Z, amount));
+ }
+
+ public static Vector3 Max(Vector3 value1, Vector3 value2)
+ {
+ return new Vector3(
+ MathHelper.Max(value1.X, value2.X),
+ MathHelper.Max(value1.Y, value2.Y),
+ MathHelper.Max(value1.Z, value2.Z));
+ }
+
+ public static void Max(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.Max(value1.X, value2.X),
+ MathHelper.Max(value1.Y, value2.Y),
+ MathHelper.Max(value1.Z, value2.Z));
+ }
+
+ public static Vector3 Min(Vector3 value1, Vector3 value2)
+ {
+ return new Vector3(
+ MathHelper.Min(value1.X, value2.X),
+ MathHelper.Min(value1.Y, value2.Y),
+ MathHelper.Min(value1.Z, value2.Z));
+ }
+
+ public static void Min(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.Min(value1.X, value2.X),
+ MathHelper.Min(value1.Y, value2.Y),
+ MathHelper.Min(value1.Z, value2.Z));
+ }
+
+ public static Vector3 Multiply(Vector3 value1, Vector3 value2)
+ {
+ value1.X *= value2.X;
+ value1.Y *= value2.Y;
+ value1.Z *= value2.Z;
+ return value1;
+ }
+
+ public static Vector3 Multiply(Vector3 value1, float scaleFactor)
+ {
+ value1.X *= scaleFactor;
+ value1.Y *= scaleFactor;
+ value1.Z *= scaleFactor;
+ return value1;
+ }
+
+ public static void Multiply(ref Vector3 value1, float scaleFactor, out Vector3 result)
+ {
+ result.X = value1.X * scaleFactor;
+ result.Y = value1.Y * scaleFactor;
+ result.Z = value1.Z * scaleFactor;
+ }
+
+ public static void Multiply(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
+ {
+ result.X = value1.X * value2.X;
+ result.Y = value1.Y * value2.Y;
+ result.Z = value1.Z * value2.Z;
+ }
+
+ public static Vector3 Negate(Vector3 value)
+ {
+ value.X = -value.X;
+ value.Y = -value.Y;
+ value.Z = -value.Z;
+ return value;
+ }
+
+ public static void Negate(ref Vector3 value, out Vector3 result)
+ {
+ result.X = -value.X;
+ result.Y = -value.Y;
+ result.Z = -value.Z;
+ }
+
+ public void Normalize()
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z));
+ X *= factor;
+ Y *= factor;
+ Z *= factor;
+ }
+
+ public static Vector3 Normalize(Vector3 value)
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y + value.Z * value.Z));
+ value.X *= factor;
+ value.Y *= factor;
+ value.Z *= factor;
+ return value;
+ }
+
+ public static void Normalize(ref Vector3 value, out Vector3 result)
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(value.X * value.X + value.Y * value.Y + value.Z * value.Z));
+ result.X = value.X * factor;
+ result.Y = value.Y * factor;
+ result.Z = value.Z * factor;
+ }
+
+ public static Vector3 Reflect(Vector3 vector, Vector3 normal)
+ {
+ float dotTimesTwo = 2f * Dot(vector, normal);
+ vector.X = vector.X - dotTimesTwo * normal.X;
+ vector.Y = vector.Y - dotTimesTwo * normal.Y;
+ vector.Z = vector.Z - dotTimesTwo * normal.Z;
+ return vector;
+ }
+
+ public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result)
+ {
+ float dotTimesTwo = 2f * Dot(vector, normal);
+ result.X = vector.X - dotTimesTwo * normal.X;
+ result.Y = vector.Y - dotTimesTwo * normal.Y;
+ result.Z = vector.Z - dotTimesTwo * normal.Z;
+ }
+
+ public static Vector3 SmoothStep(Vector3 value1, Vector3 value2, float amount)
+ {
+ return new Vector3(
+ MathHelper.SmoothStep(value1.X, value2.X, amount),
+ MathHelper.SmoothStep(value1.Y, value2.Y, amount),
+ MathHelper.SmoothStep(value1.Z, value2.Z, amount));
+ }
+
+ public static void SmoothStep(ref Vector3 value1, ref Vector3 value2, float amount, out Vector3 result)
+ {
+ result = new Vector3(
+ MathHelper.SmoothStep(value1.X, value2.X, amount),
+ MathHelper.SmoothStep(value1.Y, value2.Y, amount),
+ MathHelper.SmoothStep(value1.Z, value2.Z, amount));
+ }
+
+ public static Vector3 Subtract(Vector3 value1, Vector3 value2)
+ {
+ value1.X -= value2.X;
+ value1.Y -= value2.Y;
+ value1.Z -= value2.Z;
+ return value1;
+ }
+
+ public static void Subtract(ref Vector3 value1, ref Vector3 value2, out Vector3 result)
+ {
+ result.X = value1.X - value2.X;
+ result.Y = value1.Y - value2.Y;
+ result.Z = value1.Z - value2.Z;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(32);
+ sb.Append("{X:");
+ sb.Append(this.X);
+ sb.Append(" Y:");
+ sb.Append(this.Y);
+ sb.Append(" Z:");
+ sb.Append(this.Z);
+ sb.Append("}");
+ return sb.ToString();
+ }
+
+ public static Vector3 Transform(Vector3 position, Matrix matrix)
+ {
+ Transform(ref position, ref matrix, out position);
+ return position;
+ }
+
+ public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result)
+ {
+ result = new Vector3((position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
+ (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
+ (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43);
+ }
+
+ public static Vector3 Transform(Vector3 value, Quaternion rotation)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector3[] sourceArray, ref Quaternion rotation, Vector3[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix, Vector3[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector3[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector3[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(ref Vector3 value, ref Quaternion rotation, out Vector3 result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void TransformNormal(Vector3[] sourceArray, ref Matrix matrix, Vector3[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void TransformNormal(Vector3[] sourceArray, int sourceIndex, ref Matrix matrix, Vector3[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Vector3 TransformNormal(Vector3 normal, Matrix matrix)
+ {
+ TransformNormal(ref normal, ref matrix, out normal);
+ return normal;
+ }
+
+ public static void TransformNormal(ref Vector3 normal, ref Matrix matrix, out Vector3 result)
+ {
+ result = new Vector3((normal.X * matrix.M11) + (normal.Y * matrix.M21) + (normal.Z * matrix.M31),
+ (normal.X * matrix.M12) + (normal.Y * matrix.M22) + (normal.Z * matrix.M32),
+ (normal.X * matrix.M13) + (normal.Y * matrix.M23) + (normal.Z * matrix.M33));
+ }
+
+ #endregion Public methods
+
+
+ #region Operators
+
+ public static bool operator ==(Vector3 value1, Vector3 value2)
+ {
+ return value1.X == value2.X
+ && value1.Y == value2.Y
+ && value1.Z == value2.Z;
+ }
+
+ public static bool operator !=(Vector3 value1, Vector3 value2)
+ {
+ return value1.X != value2.X
+ || value1.Y != value2.Y
+ || value1.Z != value2.Z;
+ }
+
+ public static Vector3 operator +(Vector3 value1, Vector3 value2)
+ {
+ value1.X += value2.X;
+ value1.Y += value2.Y;
+ value1.Z += value2.Z;
+ return value1;
+ }
+
+ public static Vector3 operator -(Vector3 value)
+ {
+ value = new Vector3(-value.X, -value.Y, -value.Z);
+ return value;
+ }
+
+ public static Vector3 operator -(Vector3 value1, Vector3 value2)
+ {
+ value1.X -= value2.X;
+ value1.Y -= value2.Y;
+ value1.Z -= value2.Z;
+ return value1;
+ }
+
+ public static Vector3 operator *(Vector3 value1, Vector3 value2)
+ {
+ value1.X *= value2.X;
+ value1.Y *= value2.Y;
+ value1.Z *= value2.Z;
+ return value1;
+ }
+
+ public static Vector3 operator *(Vector3 value, float scaleFactor)
+ {
+ value.X *= scaleFactor;
+ value.Y *= scaleFactor;
+ value.Z *= scaleFactor;
+ return value;
+ }
+
+ public static Vector3 operator *(float scaleFactor, Vector3 value)
+ {
+ value.X *= scaleFactor;
+ value.Y *= scaleFactor;
+ value.Z *= scaleFactor;
+ return value;
+ }
+
+ public static Vector3 operator /(Vector3 value1, Vector3 value2)
+ {
+ value1.X /= value2.X;
+ value1.Y /= value2.Y;
+ value1.Z /= value2.Z;
+ return value1;
+ }
+
+ public static Vector3 operator /(Vector3 value, float divider)
+ {
+ float factor = 1 / divider;
+ value.X *= factor;
+ value.Y *= factor;
+ value.Z *= factor;
+ return value;
+ }
+
+ #endregion
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector4.cs b/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector4.cs
new file mode 100644
index 0000000000..feef9703fb
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/Types/Vector4.cs
@@ -0,0 +1,709 @@
+#region License
+/*
+MIT License
+Copyright © 2006 The Mono.Xna Team
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+#endregion License
+
+using System;
+using System.ComponentModel;
+
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct Vector4 : IEquatable
+ {
+ #region Private Fields
+
+ private static Vector4 zeroVector = new Vector4();
+ private static Vector4 unitVector = new Vector4(1f, 1f, 1f, 1f);
+ private static Vector4 unitXVector = new Vector4(1f, 0f, 0f, 0f);
+ private static Vector4 unitYVector = new Vector4(0f, 1f, 0f, 0f);
+ private static Vector4 unitZVector = new Vector4(0f, 0f, 1f, 0f);
+ private static Vector4 unitWVector = new Vector4(0f, 0f, 0f, 1f);
+
+ #endregion Private Fields
+
+
+ #region Public Fields
+
+ public float X;
+ public float Y;
+ public float Z;
+ public float W;
+
+ #endregion Public Fields
+
+
+ #region Properties
+
+ public static Vector4 Zero
+ {
+ get { return zeroVector; }
+ }
+
+ public static Vector4 One
+ {
+ get { return unitVector; }
+ }
+
+ public static Vector4 UnitX
+ {
+ get { return unitXVector; }
+ }
+
+ public static Vector4 UnitY
+ {
+ get { return unitYVector; }
+ }
+
+ public static Vector4 UnitZ
+ {
+ get { return unitZVector; }
+ }
+
+ public static Vector4 UnitW
+ {
+ get { return unitWVector; }
+ }
+
+ #endregion Properties
+
+
+ #region Constructors
+
+ public Vector4(float x, float y, float z, float w)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Z = z;
+ this.W = w;
+ }
+
+ public Vector4(Vector2 value, float z, float w)
+ {
+ this.X = value.X;
+ this.Y = value.Y;
+ this.Z = z;
+ this.W = w;
+ }
+
+ public Vector4(Vector3 value, float w)
+ {
+ this.X = value.X;
+ this.Y = value.Y;
+ this.Z = value.Z;
+ this.W = w;
+ }
+
+ public Vector4(float value)
+ {
+ this.X = value;
+ this.Y = value;
+ this.Z = value;
+ this.W = value;
+ }
+
+ #endregion
+
+
+ #region Public Methods
+
+ public static Vector4 Add(Vector4 value1, Vector4 value2)
+ {
+ value1.W += value2.W;
+ value1.X += value2.X;
+ value1.Y += value2.Y;
+ value1.Z += value2.Z;
+ return value1;
+ }
+
+ public static void Add(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
+ {
+ result.W = value1.W + value2.W;
+ result.X = value1.X + value2.X;
+ result.Y = value1.Y + value2.Y;
+ result.Z = value1.Z + value2.Z;
+ }
+
+ public static Vector4 Barycentric(Vector4 value1, Vector4 value2, Vector4 value3, float amount1, float amount2)
+ {
+ return new Vector4(
+ MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
+ MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
+ MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2),
+ MathHelper.Barycentric(value1.W, value2.W, value3.W, amount1, amount2));
+ }
+
+ public static void Barycentric(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, float amount1, float amount2, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.Barycentric(value1.X, value2.X, value3.X, amount1, amount2),
+ MathHelper.Barycentric(value1.Y, value2.Y, value3.Y, amount1, amount2),
+ MathHelper.Barycentric(value1.Z, value2.Z, value3.Z, amount1, amount2),
+ MathHelper.Barycentric(value1.W, value2.W, value3.W, amount1, amount2));
+ }
+
+ public static Vector4 CatmullRom(Vector4 value1, Vector4 value2, Vector4 value3, Vector4 value4, float amount)
+ {
+ return new Vector4(
+ MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
+ MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
+ MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount),
+ MathHelper.CatmullRom(value1.W, value2.W, value3.W, value4.W, amount));
+ }
+
+ public static void CatmullRom(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, ref Vector4 value4, float amount, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.CatmullRom(value1.X, value2.X, value3.X, value4.X, amount),
+ MathHelper.CatmullRom(value1.Y, value2.Y, value3.Y, value4.Y, amount),
+ MathHelper.CatmullRom(value1.Z, value2.Z, value3.Z, value4.Z, amount),
+ MathHelper.CatmullRom(value1.W, value2.W, value3.W, value4.W, amount));
+ }
+
+ public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max)
+ {
+ return new Vector4(
+ MathHelper.Clamp(value1.X, min.X, max.X),
+ MathHelper.Clamp(value1.Y, min.Y, max.Y),
+ MathHelper.Clamp(value1.Z, min.Z, max.Z),
+ MathHelper.Clamp(value1.W, min.W, max.W));
+ }
+
+ public static void Clamp(ref Vector4 value1, ref Vector4 min, ref Vector4 max, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.Clamp(value1.X, min.X, max.X),
+ MathHelper.Clamp(value1.Y, min.Y, max.Y),
+ MathHelper.Clamp(value1.Z, min.Z, max.Z),
+ MathHelper.Clamp(value1.W, min.W, max.W));
+ }
+
+ public static float Distance(Vector4 value1, Vector4 value2)
+ {
+ return (float)Math.Sqrt((value1.W - value2.W) * (value1.W - value2.W) +
+ (value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z));
+ }
+
+ public static void Distance(ref Vector4 value1, ref Vector4 value2, out float result)
+ {
+ result = (float)Math.Sqrt((value1.W - value2.W) * (value1.W - value2.W) +
+ (value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z));
+ }
+
+ public static float DistanceSquared(Vector4 value1, Vector4 value2)
+ {
+ return (value1.W - value2.W) * (value1.W - value2.W) +
+ (value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z);
+ }
+
+ public static void DistanceSquared(ref Vector4 value1, ref Vector4 value2, out float result)
+ {
+ result = (value1.W - value2.W) * (value1.W - value2.W) +
+ (value1.X - value2.X) * (value1.X - value2.X) +
+ (value1.Y - value2.Y) * (value1.Y - value2.Y) +
+ (value1.Z - value2.Z) * (value1.Z - value2.Z);
+ }
+
+ public static Vector4 Divide(Vector4 value1, Vector4 value2)
+ {
+ value1.W /= value2.W;
+ value1.X /= value2.X;
+ value1.Y /= value2.Y;
+ value1.Z /= value2.Z;
+ return value1;
+ }
+
+ public static Vector4 Divide(Vector4 value1, float divider)
+ {
+ float factor = 1f / divider;
+ value1.W *= factor;
+ value1.X *= factor;
+ value1.Y *= factor;
+ value1.Z *= factor;
+ return value1;
+ }
+
+ public static void Divide(ref Vector4 value1, float divider, out Vector4 result)
+ {
+ float factor = 1f / divider;
+ result.W = value1.W * factor;
+ result.X = value1.X * factor;
+ result.Y = value1.Y * factor;
+ result.Z = value1.Z * factor;
+ }
+
+ public static void Divide(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
+ {
+ result.W = value1.W / value2.W;
+ result.X = value1.X / value2.X;
+ result.Y = value1.Y / value2.Y;
+ result.Z = value1.Z / value2.Z;
+ }
+
+ public static float Dot(Vector4 vector1, Vector4 vector2)
+ {
+ return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z + vector1.W * vector2.W;
+ }
+
+ public static void Dot(ref Vector4 vector1, ref Vector4 vector2, out float result)
+ {
+ result = vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z + vector1.W * vector2.W;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Vector4) ? this == (Vector4)obj : false;
+ }
+
+ public bool Equals(Vector4 other)
+ {
+ return this.W == other.W
+ && this.X == other.X
+ && this.Y == other.Y
+ && this.Z == other.Z;
+ }
+
+ public override int GetHashCode()
+ {
+ return (int)(this.W + this.X + this.Y + this.Y);
+ }
+
+ public static Vector4 Hermite(Vector4 value1, Vector4 tangent1, Vector4 value2, Vector4 tangent2, float amount)
+ {
+ value1.W = MathHelper.Hermite(value1.W, tangent1.W, value2.W, tangent2.W, amount);
+ value1.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
+ value1.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
+ value1.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
+
+ return value1;
+ }
+
+ public static void Hermite(ref Vector4 value1, ref Vector4 tangent1, ref Vector4 value2, ref Vector4 tangent2, float amount, out Vector4 result)
+ {
+ result.W = MathHelper.Hermite(value1.W, tangent1.W, value2.W, tangent2.W, amount);
+ result.X = MathHelper.Hermite(value1.X, tangent1.X, value2.X, tangent2.X, amount);
+ result.Y = MathHelper.Hermite(value1.Y, tangent1.Y, value2.Y, tangent2.Y, amount);
+ result.Z = MathHelper.Hermite(value1.Z, tangent1.Z, value2.Z, tangent2.Z, amount);
+ }
+
+ public float Length()
+ {
+ return (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z + W * W));
+ }
+
+ public float LengthSquared()
+ {
+ return X * X + Y * Y + Z * Z + W * W;
+ }
+
+ public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount)
+ {
+ return new Vector4(
+ MathHelper.Lerp(value1.X, value2.X, amount),
+ MathHelper.Lerp(value1.Y, value2.Y, amount),
+ MathHelper.Lerp(value1.Z, value2.Z, amount),
+ MathHelper.Lerp(value1.W, value2.W, amount));
+ }
+
+ public static void Lerp(ref Vector4 value1, ref Vector4 value2, float amount, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.Lerp(value1.X, value2.X, amount),
+ MathHelper.Lerp(value1.Y, value2.Y, amount),
+ MathHelper.Lerp(value1.Z, value2.Z, amount),
+ MathHelper.Lerp(value1.W, value2.W, amount));
+ }
+
+ public static Vector4 Max(Vector4 value1, Vector4 value2)
+ {
+ return new Vector4(
+ MathHelper.Max(value1.X, value2.X),
+ MathHelper.Max(value1.Y, value2.Y),
+ MathHelper.Max(value1.Z, value2.Z),
+ MathHelper.Max(value1.W, value2.W));
+ }
+
+ public static void Max(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.Max(value1.X, value2.X),
+ MathHelper.Max(value1.Y, value2.Y),
+ MathHelper.Max(value1.Z, value2.Z),
+ MathHelper.Max(value1.W, value2.W));
+ }
+
+ public static Vector4 Min(Vector4 value1, Vector4 value2)
+ {
+ return new Vector4(
+ MathHelper.Min(value1.X, value2.X),
+ MathHelper.Min(value1.Y, value2.Y),
+ MathHelper.Min(value1.Z, value2.Z),
+ MathHelper.Min(value1.W, value2.W));
+ }
+
+ public static void Min(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.Min(value1.X, value2.X),
+ MathHelper.Min(value1.Y, value2.Y),
+ MathHelper.Min(value1.Z, value2.Z),
+ MathHelper.Min(value1.W, value2.W));
+ }
+
+ public static Vector4 Multiply(Vector4 value1, Vector4 value2)
+ {
+ value1.W *= value2.W;
+ value1.X *= value2.X;
+ value1.Y *= value2.Y;
+ value1.Z *= value2.Z;
+ return value1;
+ }
+
+ public static Vector4 Multiply(Vector4 value1, float scaleFactor)
+ {
+ value1.W *= scaleFactor;
+ value1.X *= scaleFactor;
+ value1.Y *= scaleFactor;
+ value1.Z *= scaleFactor;
+ return value1;
+ }
+
+ public static void Multiply(ref Vector4 value1, float scaleFactor, out Vector4 result)
+ {
+ result.W = value1.W * scaleFactor;
+ result.X = value1.X * scaleFactor;
+ result.Y = value1.Y * scaleFactor;
+ result.Z = value1.Z * scaleFactor;
+ }
+
+ public static void Multiply(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
+ {
+ result.W = value1.W * value2.W;
+ result.X = value1.X * value2.X;
+ result.Y = value1.Y * value2.Y;
+ result.Z = value1.Z * value2.Z;
+ }
+
+ public static Vector4 Negate(Vector4 value)
+ {
+ value.X = -value.X;
+ value.Y = -value.Y;
+ value.Z = -value.Z;
+ value.W = -value.W;
+ return value;
+ }
+
+ public static void Negate(ref Vector4 value, out Vector4 result)
+ {
+ result.X = -value.X;
+ result.Y = -value.Y;
+ result.Z = -value.Z;
+ result.W = -value.W;
+ }
+
+ public void Normalize()
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(X * X + Y * Y + Z * Z + W * W));
+
+ W = W * factor;
+ X = X * factor;
+ Y = Y * factor;
+ Z = Z * factor;
+ }
+
+ public static Vector4 Normalize(Vector4 vector)
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z + vector.W * vector.W));
+
+ vector.W = vector.W * factor;
+ vector.X = vector.X * factor;
+ vector.Y = vector.Y * factor;
+ vector.Z = vector.Z * factor;
+
+ return vector;
+ }
+
+ public static void Normalize(ref Vector4 vector, out Vector4 result)
+ {
+ float factor = 1f / (float)Math.Sqrt((double)(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z + vector.W * vector.W));
+
+ result.W = vector.W * factor;
+ result.X = vector.X * factor;
+ result.Y = vector.Y * factor;
+ result.Z = vector.Z * factor;
+ }
+
+ public static Vector4 SmoothStep(Vector4 value1, Vector4 value2, float amount)
+ {
+ return new Vector4(
+ MathHelper.SmoothStep(value1.X, value2.X, amount),
+ MathHelper.SmoothStep(value1.Y, value2.Y, amount),
+ MathHelper.SmoothStep(value1.Z, value2.Z, amount),
+ MathHelper.SmoothStep(value1.W, value2.W, amount));
+ }
+
+ public static void SmoothStep(ref Vector4 value1, ref Vector4 value2, float amount, out Vector4 result)
+ {
+ result = new Vector4(
+ MathHelper.SmoothStep(value1.X, value2.X, amount),
+ MathHelper.SmoothStep(value1.Y, value2.Y, amount),
+ MathHelper.SmoothStep(value1.Z, value2.Z, amount),
+ MathHelper.SmoothStep(value1.W, value2.W, amount));
+ }
+
+ public static Vector4 Subtract(Vector4 value1, Vector4 value2)
+ {
+ value1.W -= value2.W;
+ value1.X -= value2.X;
+ value1.Y -= value2.Y;
+ value1.Z -= value2.Z;
+ return value1;
+ }
+
+ public static void Subtract(ref Vector4 value1, ref Vector4 value2, out Vector4 result)
+ {
+ result.W = value1.W - value2.W;
+ result.X = value1.X - value2.X;
+ result.Y = value1.Y - value2.Y;
+ result.Z = value1.Z - value2.Z;
+ }
+
+ public static Vector4 Transform(Vector2 position, Matrix matrix)
+ {
+ Vector4 result;
+ Transform(ref position, ref matrix, out result);
+ return result;
+ }
+
+ public static Vector4 Transform(Vector2 value, Quaternion rotation)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Vector4 Transform(Vector3 value, Quaternion rotation)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Vector4 Transform(Vector4 value, Quaternion rotation)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(ref Vector2 value, ref Quaternion rotation, out Vector4 result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(ref Vector3 value, ref Quaternion rotation, out Vector4 result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(ref Vector4 value, ref Quaternion rotation, out Vector4 result)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector4[] sourceArray, ref Quaternion rotation, Vector4[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector4[] sourceArray, ref Matrix matrix, Vector4[] destinationArray)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector4[] sourceArray, int sourceIndex, ref Matrix matrix, Vector4[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void Transform(Vector4[] sourceArray, int sourceIndex, ref Quaternion rotation, Vector4[] destinationArray, int destinationIndex, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static Vector4 Transform(Vector3 position, Matrix matrix)
+ {
+ Vector4 result;
+ Transform(ref position, ref matrix, out result);
+ return result;
+ }
+
+ public static Vector4 Transform(Vector4 vector, Matrix matrix)
+ {
+ Transform(ref vector, ref matrix, out vector);
+ return vector;
+ }
+
+ public static void Transform(ref Vector2 position, ref Matrix matrix, out Vector4 result)
+ {
+ result = new Vector4((position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41,
+ (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42,
+ (position.X * matrix.M13) + (position.Y * matrix.M23) + matrix.M43,
+ (position.X * matrix.M14) + (position.Y * matrix.M24) + matrix.M44);
+ }
+
+ public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector4 result)
+ {
+ result = new Vector4((position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41,
+ (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42,
+ (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43,
+ (position.X * matrix.M14) + (position.Y * matrix.M24) + (position.Z * matrix.M34) + matrix.M44);
+ }
+
+ public static void Transform(ref Vector4 vector, ref Matrix matrix, out Vector4 result)
+ {
+ result = new Vector4((vector.X * matrix.M11) + (vector.Y * matrix.M21) + (vector.Z * matrix.M31) + (vector.W * matrix.M41),
+ (vector.X * matrix.M12) + (vector.Y * matrix.M22) + (vector.Z * matrix.M32) + (vector.W * matrix.M42),
+ (vector.X * matrix.M13) + (vector.Y * matrix.M23) + (vector.Z * matrix.M33) + (vector.W * matrix.M43),
+ (vector.X * matrix.M14) + (vector.Y * matrix.M24) + (vector.Z * matrix.M34) + (vector.W * matrix.M44));
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(32);
+ sb.Append("{X:");
+ sb.Append(this.X);
+ sb.Append(" Y:");
+ sb.Append(this.Y);
+ sb.Append(" Z:");
+ sb.Append(this.Z);
+ sb.Append(" W:");
+ sb.Append(this.W);
+ sb.Append("}");
+ return sb.ToString();
+ }
+
+ #endregion Public Methods
+
+
+ #region Operators
+
+ public static Vector4 operator -(Vector4 value)
+ {
+ value.X = -value.X;
+ value.Y = -value.Y;
+ value.Z = -value.Z;
+ value.W = -value.W;
+ return value;
+ }
+
+ public static bool operator ==(Vector4 value1, Vector4 value2)
+ {
+ return value1.W == value2.W
+ && value1.X == value2.X
+ && value1.Y == value2.Y
+ && value1.Z == value2.Z;
+ }
+
+ public static bool operator !=(Vector4 value1, Vector4 value2)
+ {
+ return value1.W != value2.W
+ || value1.X != value2.X
+ || value1.Y != value2.Y
+ || value1.Z != value2.Z;
+ }
+
+ public static Vector4 operator +(Vector4 value1, Vector4 value2)
+ {
+ value1.W += value2.W;
+ value1.X += value2.X;
+ value1.Y += value2.Y;
+ value1.Z += value2.Z;
+ return value1;
+ }
+
+ public static Vector4 operator -(Vector4 value1, Vector4 value2)
+ {
+ value1.W -= value2.W;
+ value1.X -= value2.X;
+ value1.Y -= value2.Y;
+ value1.Z -= value2.Z;
+ return value1;
+ }
+
+ public static Vector4 operator *(Vector4 value1, Vector4 value2)
+ {
+ value1.W *= value2.W;
+ value1.X *= value2.X;
+ value1.Y *= value2.Y;
+ value1.Z *= value2.Z;
+ return value1;
+ }
+
+ public static Vector4 operator *(Vector4 value1, float scaleFactor)
+ {
+ value1.W *= scaleFactor;
+ value1.X *= scaleFactor;
+ value1.Y *= scaleFactor;
+ value1.Z *= scaleFactor;
+ return value1;
+ }
+
+ public static Vector4 operator *(float scaleFactor, Vector4 value1)
+ {
+ value1.W *= scaleFactor;
+ value1.X *= scaleFactor;
+ value1.Y *= scaleFactor;
+ value1.Z *= scaleFactor;
+ return value1;
+ }
+
+ public static Vector4 operator /(Vector4 value1, Vector4 value2)
+ {
+ value1.W /= value2.W;
+ value1.X /= value2.X;
+ value1.Y /= value2.Y;
+ value1.Z /= value2.Z;
+ return value1;
+ }
+
+ public static Vector4 operator /(Vector4 value1, float divider)
+ {
+ float factor = 1f / divider;
+ value1.W *= factor;
+ value1.X *= factor;
+ value1.Y *= factor;
+ value1.Z *= factor;
+ return value1;
+ }
+
+ #endregion Operators
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/UniformInfo.cs b/Bizware/BizHawk.Bizware.BizwareGL/UniformInfo.cs
new file mode 100644
index 0000000000..91cf9de274
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/UniformInfo.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ public class UniformInfo
+ {
+ public IntPtr Handle;
+ public string Name;
+ public int SamplerIndex;
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.BizwareGL/VertexLayout.cs b/Bizware/BizHawk.Bizware.BizwareGL/VertexLayout.cs
new file mode 100644
index 0000000000..f549d98298
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.BizwareGL/VertexLayout.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+
+namespace BizHawk.Bizware.BizwareGL
+{
+ //TEMP until its in bizhawk main
+ public class WorkingDictionary : Dictionary where V : new()
+ {
+ public new V this[K key]
+ {
+ get
+ {
+ V temp;
+ if (!TryGetValue(key, out temp))
+ {
+ temp = this[key] = new V();
+ }
+
+ return temp;
+ }
+
+ set
+ {
+ base[key] = value;
+ }
+ }
+
+ public WorkingDictionary() { }
+
+ }
+
+ public class VertexLayout : IDisposable
+ {
+ //TODO - could refactor to use vertex array objects? check opengl profile requirements (answer: 3.0. dont want to do this.)
+
+ public VertexLayout(IGL owner, IntPtr id)
+ {
+ Owner = owner;
+ Id = id;
+ Items = new MyDictionary();
+ }
+
+ public void Dispose()
+ {
+ //nothing to do yet..
+ }
+
+ public void Bind()
+ {
+ Owner.BindVertexLayout(this);
+ }
+
+ public void DefineVertexAttribute(int index, int components, VertexAttributeType attribType, bool normalized, int stride, int offset=0)
+ {
+ if (Closed)
+ throw new InvalidOperationException("Type is Closed and is now immutable.");
+ Items[index] = new LayoutItem { Components = components, AttribType = attribType, Normalized = normalized, Stride = stride, Offset = offset };
+ }
+
+ ///
+ /// finishes this VertexLayout and renders it immutable
+ ///
+ public void Close()
+ {
+ Closed = true;
+ }
+
+ public class LayoutItem
+ {
+ public int Components { get; internal set; }
+ public VertexAttributeType AttribType { get; internal set; }
+ public bool Normalized { get; internal set; }
+ public int Stride { get; internal set; }
+ public int Offset { get; internal set; }
+ }
+
+ public class MyDictionary : WorkingDictionary
+ {
+ public new LayoutItem this[int key]
+ {
+ get
+ {
+ return base[key];
+ }
+
+ internal set
+ {
+ base[key] = value;
+ }
+ }
+ }
+
+ public MyDictionary Items { get; private set; }
+ bool Closed = false;
+
+ public IGL Owner { get; private set; }
+ public IntPtr Id { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj b/Bizware/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj
new file mode 100644
index 0000000000..ab2262117e
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj
@@ -0,0 +1,99 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}
+ Exe
+ Properties
+ BizHawk.Bizware.Test
+ BizHawk.Bizware.Test
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ TestForm.cs
+
+
+
+
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}
+ BizHawk.Bizware.BizwareGL.OpenTK
+
+
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}
+ BizHawk.Bizware.BizwareGL
+
+
+
+
+
+
+
+ TestForm.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.Test/Program.cs b/Bizware/BizHawk.Bizware.Test/Program.cs
new file mode 100644
index 0000000000..2dcf882c52
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.Test/Program.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using BizHawk.Bizware.BizwareGL;
+
+namespace BizHawk.Bizware.Test
+{
+ class Program
+ {
+ static unsafe void Main(string[] args)
+ {
+ BizHawk.Bizware.BizwareGL.IGL igl = new BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
+
+
+
+ List testArts = new List();
+ ArtManager am = new ArtManager(igl);
+ foreach (var name in typeof(Program).Assembly.GetManifestResourceNames())
+ if (name.Contains("flame"))
+ testArts.Add(am.LoadArt(typeof(Program).Assembly.GetManifestResourceStream(name)));
+ var smile = am.LoadArt(typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Bizware.Test.TestImages.smile.png"));
+ am.Close(true);
+ StringRenderer sr;
+ using (var xml = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Bizware.Test.TestImages.courier16px.fnt"))
+ using (var tex = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Bizware.Test.TestImages.courier16px_0.png"))
+ sr = new StringRenderer(igl, xml, tex);
+
+ GuiRenderer gr = new GuiRenderer(igl);
+
+ TestForm tf = new TestForm();
+ GraphicsControl c = igl.CreateGraphicsControl();
+ tf.Controls.Add(c);
+ c.Control.Dock = System.Windows.Forms.DockStyle.Fill;
+ tf.FormClosing += (object sender, System.Windows.Forms.FormClosingEventArgs e) =>
+ {
+ tf.Controls.Remove(c);
+ c.Dispose();
+ c = null;
+ };
+ tf.Show();
+
+ c.SetVsync(false);
+
+ DateTime start = DateTime.Now;
+ int wobble = 0;
+ for (; ; )
+ {
+ if (c == null) break;
+
+ c.Begin();
+
+ igl.ClearColor(Color.Red);
+ igl.Clear(BizwareGL.ClearBufferMask.ColorBufferBit);
+
+ int frame = (int)((DateTime.Now - start).TotalSeconds) % testArts.Count;
+
+ gr.Begin(c.Control.ClientSize.Width, c.Control.ClientSize.Height);
+ sr.RenderString(gr, 0, 0, "60 fps");
+ gr.Modelview.Translate((float)Math.Sin(wobble / 360.0f) * 50, 0);
+ gr.Modelview.Translate(100, 100);
+ gr.Modelview.Push();
+ gr.Modelview.Translate(testArts[frame].Width, 0);
+ gr.Modelview.Scale(-1, 1);
+ wobble++;
+ gr.SetModulateColor(Color.Yellow);
+ gr.DrawFlipped(testArts[frame], true, false);
+ gr.SetModulateColorWhite();
+ gr.Modelview.Pop();
+ gr.SetBlendState(igl.BlendNormal);
+ gr.Draw(smile);
+ gr.End();
+
+ c.SwapBuffers();
+ c.End();
+
+ System.Windows.Forms.Application.DoEvents();
+ }
+ }
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.Test/TestForm.Designer.cs b/Bizware/BizHawk.Bizware.Test/TestForm.Designer.cs
new file mode 100644
index 0000000000..5cf840d839
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.Test/TestForm.Designer.cs
@@ -0,0 +1,48 @@
+namespace BizHawk.Bizware.Test
+{
+ partial class TestForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // TestForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(292, 273);
+ this.Name = "TestForm";
+ this.Text = "TestForm";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+
+ }
+}
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.Test/TestForm.cs b/Bizware/BizHawk.Bizware.Test/TestForm.cs
new file mode 100644
index 0000000000..b5054cd7dc
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.Test/TestForm.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BizHawk.Bizware.Test
+{
+ public partial class TestForm : Form
+ {
+ public TestForm()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Bizware/BizHawk.Bizware.Test/TestForm.resx b/Bizware/BizHawk.Bizware.Test/TestForm.resx
new file mode 100644
index 0000000000..29dcb1b3a3
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.Test/TestForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/courier16px.fnt b/Bizware/BizHawk.Bizware.Test/TestImages/courier16px.fnt
new file mode 100644
index 0000000000..0e8d5e8a1f
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.Test/TestImages/courier16px.fnt
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png b/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png
new file mode 100644
index 0000000000..e9e267cf8e
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/courier16px_0.png differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg
new file mode 100644
index 0000000000..0645716f53
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/flame1.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg
new file mode 100644
index 0000000000..8fa880ce44
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/flame2.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg
new file mode 100644
index 0000000000..d50f2f426e
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/flame3.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg
new file mode 100644
index 0000000000..a4f1722056
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/flame4.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg b/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg
new file mode 100644
index 0000000000..2a8d7e6d95
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/flame5.jpg differ
diff --git a/Bizware/BizHawk.Bizware.Test/TestImages/smile.png b/Bizware/BizHawk.Bizware.Test/TestImages/smile.png
new file mode 100644
index 0000000000..cc2befa7a5
Binary files /dev/null and b/Bizware/BizHawk.Bizware.Test/TestImages/smile.png differ
diff --git a/Bizware/BizHawk.Bizware.sln b/Bizware/BizHawk.Bizware.sln
new file mode 100644
index 0000000000..e455cd8008
--- /dev/null
+++ b/Bizware/BizHawk.Bizware.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL", "BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj", "{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.Test", "BizHawk.Bizware.Test\BizHawk.Bizware.Test.csproj", "{B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL.OpenTK", "BizHawk.Bizware.BizwareGL.OpenTK\BizHawk.Bizware.BizwareGL.OpenTK.csproj", "{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}.Release|x86.ActiveCfg = Release|Any CPU
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|x86.ActiveCfg = Debug|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Debug|x86.Build.0 = Debug|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|Any CPU.ActiveCfg = Release|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|Mixed Platforms.Build.0 = Release|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|x86.ActiveCfg = Release|x86
+ {B9925307-6A8F-4CD0-8EFB-0617FF0AE5AD}.Release|x86.Build.0 = Release|x86
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {5160CFB1-5389-47C1-B7F6-8A0DC97641EE}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/References/OpenTK.Compatibility.dll b/References/OpenTK.Compatibility.dll
new file mode 100644
index 0000000000..9efd281bd6
Binary files /dev/null and b/References/OpenTK.Compatibility.dll differ
diff --git a/References/OpenTK.GLControl.dll b/References/OpenTK.GLControl.dll
new file mode 100644
index 0000000000..9cfe53e67f
Binary files /dev/null and b/References/OpenTK.GLControl.dll differ
diff --git a/References/OpenTK.dll b/References/OpenTK.dll
new file mode 100644
index 0000000000..9e34c2f1e4
Binary files /dev/null and b/References/OpenTK.dll differ
diff --git a/References/OpenTK.dll.config b/References/OpenTK.dll.config
new file mode 100644
index 0000000000..975c2be900
--- /dev/null
+++ b/References/OpenTK.dll.config
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+