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 @@ + + + + + + + + + + + + + + + +