Added OpenTK.Compatibility project to provide an upgrade path from 0.9.8.

This commit is contained in:
the_fiddler 2009-08-14 12:29:30 +00:00
parent 245f45c7eb
commit 81304f33b5
32 changed files with 184834 additions and 0 deletions

View file

@ -0,0 +1,134 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2009 the Open Toolkit library.
//
// 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
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace OpenTK.Graphics
{
// Used in debug-mode only, for automatic OpenGL error-checking.
//
// Works like this: an instance is created before each OpenGL function is called.
// The constructor resets the OpenGL error state. Once the native function returns,
// the error state is checked again, raising the relevant exceptions.
//
// A using-region is used to ensure Dispose() is called.
//
// Make sure that no error checking is added to the GetError function,
// as that would cause infinite recursion!
struct ErrorHelper : IDisposable
{
#region Fields
static readonly object SyncRoot = new object();
static readonly Dictionary<GraphicsContext, List<ErrorCode>> ContextErrors =
new Dictionary<GraphicsContext, List<ErrorCode>>();
readonly GraphicsContext Context;
#endregion
#region Constructors
public ErrorHelper(IGraphicsContext context)
{
if (context == null)
throw new GraphicsContextMissingException();
Context = (GraphicsContext)context;
lock (SyncRoot)
{
if (!ContextErrors.ContainsKey(Context))
ContextErrors.Add(Context, new List<ErrorCode>());
}
ResetErrors();
}
#endregion
#region Public Members
// Retrieve all OpenGL errors to clear the error list.
// See http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/geterror.html
[Conditional("DEBUG")]
internal void ResetErrors()
{
if (Context.ErrorChecking)
{
while (GL.GetError() != ErrorCode.NoError)
{ }
}
}
// Retrieve all OpenGL errors and throw an exception if anything other than NoError is returned.
[Conditional("DEBUG")]
internal void CheckErrors()
{
if (Context.ErrorChecking)
{
List<ErrorCode> error_list = ContextErrors[Context];
error_list.Clear();
ErrorCode error;
do
{
error = GL.GetError();
error_list.Add(error);
} while (error != ErrorCode.NoError);
if (error_list.Count != 1)
{
StringBuilder sb = new StringBuilder();
foreach (ErrorCode e in error_list)
{
if (e != ErrorCode.NoError)
{
sb.Append(e.ToString());
sb.Append(", ");
}
else
break;
}
sb.Remove(sb.Length - 2, 2); // Remove the last comma
throw new GraphicsErrorException(sb.ToString());
}
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
CheckErrors();
}
#endregion
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,190 @@
namespace OpenTK.Graphics
{
using System;
using System.Runtime.InteropServices;
#pragma warning disable 3019
#pragma warning disable 1591
partial class Glu
{
[Obsolete]
internal static partial class Imports
{
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBeginCurve", ExactSpelling = true)]
internal extern static void BeginCurve(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBeginPolygon", ExactSpelling = true)]
internal extern static void BeginPolygon(IntPtr tess);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBeginSurface", ExactSpelling = true)]
internal extern static void BeginSurface(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBeginTrim", ExactSpelling = true)]
internal extern static void BeginTrim(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBuild1DMipmapLevels", ExactSpelling = true)]
internal extern static Int32 Build1DMipmapLevels(TextureTarget target, Int32 internalFormat, Int32 width, PixelFormat format, PixelType type, Int32 level, Int32 @base, Int32 max, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBuild1DMipmaps", ExactSpelling = true)]
internal extern static Int32 Build1DMipmaps(TextureTarget target, Int32 internalFormat, Int32 width, PixelFormat format, PixelType type, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBuild2DMipmapLevels", ExactSpelling = true)]
internal extern static Int32 Build2DMipmapLevels(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, PixelFormat format, PixelType type, Int32 level, Int32 @base, Int32 max, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBuild2DMipmaps", ExactSpelling = true)]
internal extern static Int32 Build2DMipmaps(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, PixelFormat format, PixelType type, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBuild3DMipmapLevels", ExactSpelling = true)]
internal extern static Int32 Build3DMipmapLevels(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, Int32 depth, PixelFormat format, PixelType type, Int32 level, Int32 @base, Int32 max, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluBuild3DMipmaps", ExactSpelling = true)]
internal extern static Int32 Build3DMipmaps(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, Int32 depth, PixelFormat format, PixelType type, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluCheckExtension", ExactSpelling = true)]
internal extern static unsafe bool CheckExtension(Byte* extName, Byte* extString);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluCylinder", ExactSpelling = true)]
internal extern static void Cylinder(IntPtr quad, double @base, double top, double height, Int32 slices, Int32 stacks);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluDeleteNurbsRenderer", ExactSpelling = true)]
internal extern static void DeleteNurbsRenderer(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluDeleteQuadric", ExactSpelling = true)]
internal extern static void DeleteQuadric(IntPtr quad);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluDeleteTess", ExactSpelling = true)]
internal extern static void DeleteTess(IntPtr tess);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluDisk", ExactSpelling = true)]
internal extern static void Disk(IntPtr quad, double inner, double outer, Int32 slices, Int32 loops);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluEndCurve", ExactSpelling = true)]
internal extern static void EndCurve(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluEndPolygon", ExactSpelling = true)]
internal extern static void EndPolygon(IntPtr tess);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluEndSurface", ExactSpelling = true)]
internal extern static void EndSurface(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluEndTrim", ExactSpelling = true)]
internal extern static void EndTrim(IntPtr nurb);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluErrorString", ExactSpelling = true)]
internal extern static IntPtr ErrorString(OpenTK.Graphics.GluErrorCode error);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluGetString", ExactSpelling = true)]
internal extern static IntPtr GetString(OpenTK.Graphics.GluStringName name);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluGetNurbsProperty", ExactSpelling = true)]
internal extern static unsafe void GetNurbsProperty(IntPtr nurb, OpenTK.Graphics.NurbsProperty property, [Out] float* data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluGetTessProperty", ExactSpelling = true)]
internal extern static unsafe void GetTessProperty(IntPtr tess, OpenTK.Graphics.TessParameter which, [Out] double* data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluLoadSamplingMatrices", ExactSpelling = true)]
internal extern static unsafe void LoadSamplingMatrices(IntPtr nurb, float* model, float* perspective, Int32* view);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluLookAt", ExactSpelling = true)]
internal extern static void LookAt(double eyeX, double eyeY, double eyeZ, double centerX, double centerY, double centerZ, double upX, double upY, double upZ);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNewNurbsRenderer", ExactSpelling = true)]
internal extern static IntPtr NewNurbsRenderer();
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNewQuadric", ExactSpelling = true)]
internal extern static IntPtr NewQuadric();
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNewTess", ExactSpelling = true)]
internal extern static IntPtr NewTess();
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNextContour", ExactSpelling = true)]
internal extern static void NextContour(IntPtr tess, OpenTK.Graphics.TessContour type);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNurbsCallback", ExactSpelling = true)]
internal extern static void NurbsCallback(IntPtr nurb, OpenTK.Graphics.NurbsCallback which, Delegate CallBackFunc);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNurbsCallbackData", ExactSpelling = true)]
internal extern static void NurbsCallbackData(IntPtr nurb, IntPtr userData);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNurbsCurve", ExactSpelling = true)]
internal extern static unsafe void NurbsCurve(IntPtr nurb, Int32 knotCount, [Out] float* knots, Int32 stride, [Out] float* control, Int32 order, MapTarget type);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNurbsProperty", ExactSpelling = true)]
internal extern static void NurbsProperty(IntPtr nurb, OpenTK.Graphics.NurbsProperty property, float value);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluNurbsSurface", ExactSpelling = true)]
internal extern static unsafe void NurbsSurface(IntPtr nurb, Int32 sKnotCount, float* sKnots, Int32 tKnotCount, float* tKnots, Int32 sStride, Int32 tStride, float* control, Int32 sOrder, Int32 tOrder, MapTarget type);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluOrtho2D", ExactSpelling = true)]
internal extern static void Ortho2D(double left, double right, double bottom, double top);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluPartialDisk", ExactSpelling = true)]
internal extern static void PartialDisk(IntPtr quad, double inner, double outer, Int32 slices, Int32 loops, double start, double sweep);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluPerspective", ExactSpelling = true)]
internal extern static void Perspective(double fovy, double aspect, double zNear, double zFar);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluPickMatrix", ExactSpelling = true)]
internal extern static unsafe void PickMatrix(double x, double y, double delX, double delY, [Out] Int32* viewport);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluProject", ExactSpelling = true)]
internal extern static unsafe Int32 Project(double objX, double objY, double objZ, double* model, double* proj, Int32* view, double* winX, double* winY, double* winZ);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluPwlCurve", ExactSpelling = true)]
internal extern static unsafe void PwlCurve(IntPtr nurb, Int32 count, float* data, Int32 stride, OpenTK.Graphics.NurbsTrim type);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluQuadricCallback", ExactSpelling = true)]
internal extern static void QuadricCallback(IntPtr quad, OpenTK.Graphics.QuadricCallback which, Delegate CallBackFunc);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluQuadricDrawStyle", ExactSpelling = true)]
internal extern static void QuadricDrawStyle(IntPtr quad, OpenTK.Graphics.QuadricDrawStyle draw);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluQuadricNormals", ExactSpelling = true)]
internal extern static void QuadricNormals(IntPtr quad, OpenTK.Graphics.QuadricNormal normal);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluQuadricOrientation", ExactSpelling = true)]
internal extern static void QuadricOrientation(IntPtr quad, OpenTK.Graphics.QuadricOrientation orientation);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluQuadricTexture", ExactSpelling = true)]
internal extern static void QuadricTexture(IntPtr quad, bool texture);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluScaleImage", ExactSpelling = true)]
internal extern static Int32 ScaleImage(PixelFormat format, Int32 wIn, Int32 hIn, PixelType typeIn, IntPtr dataIn, Int32 wOut, Int32 hOut, PixelType typeOut, [Out] IntPtr dataOut);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluSphere", ExactSpelling = true)]
internal extern static void Sphere(IntPtr quad, double radius, Int32 slices, Int32 stacks);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessBeginContour", ExactSpelling = true)]
internal extern static void TessBeginContour(IntPtr tess);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessBeginPolygon", ExactSpelling = true)]
internal extern static void TessBeginPolygon(IntPtr tess, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessCallback", ExactSpelling = true)]
internal extern static void TessCallback(IntPtr tess, OpenTK.Graphics.TessCallback which, Delegate CallBackFunc);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessEndContour", ExactSpelling = true)]
internal extern static void TessEndContour(IntPtr tess);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessEndPolygon", ExactSpelling = true)]
internal extern static void TessEndPolygon(IntPtr tess);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessNormal", ExactSpelling = true)]
internal extern static void TessNormal(IntPtr tess, double valueX, double valueY, double valueZ);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessProperty", ExactSpelling = true)]
internal extern static void TessProperty(IntPtr tess, OpenTK.Graphics.TessParameter which, double data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluTessVertex", ExactSpelling = true)]
internal extern static unsafe void TessVertex(IntPtr tess, double* location, IntPtr data);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluUnProject", ExactSpelling = true)]
internal extern static unsafe Int32 UnProject(double winX, double winY, double winZ, double* model, double* proj, Int32* view, double* objX, double* objY, double* objZ);
[System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(Glu.Library, EntryPoint = "gluUnProject4", ExactSpelling = true)]
internal extern static unsafe Int32 UnProject4(double winX, double winY, double winZ, double clipW, double* model, double* proj, Int32* view, double near, double far, double* objX, double* objY, double* objZ, double* objW);
}
}
}

View file

@ -0,0 +1,195 @@
namespace OpenTK.Graphics
{
using System;
using System.Runtime.InteropServices;
#pragma warning disable 0649
#pragma warning disable 3019
#pragma warning disable 1591
partial class Glu
{
internal static partial class Delegates
{
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void BeginCurve(IntPtr nurb);
internal static BeginCurve gluBeginCurve;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void BeginPolygon(IntPtr tess);
internal static BeginPolygon gluBeginPolygon;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void BeginSurface(IntPtr nurb);
internal static BeginSurface gluBeginSurface;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void BeginTrim(IntPtr nurb);
internal static BeginTrim gluBeginTrim;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 Build1DMipmapLevels(TextureTarget target, Int32 internalFormat, Int32 width, PixelFormat format, PixelType type, Int32 level, Int32 @base, Int32 max, IntPtr data);
internal static Build1DMipmapLevels gluBuild1DMipmapLevels;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 Build1DMipmaps(TextureTarget target, Int32 internalFormat, Int32 width, PixelFormat format, PixelType type, IntPtr data);
internal static Build1DMipmaps gluBuild1DMipmaps;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 Build2DMipmapLevels(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, PixelFormat format, PixelType type, Int32 level, Int32 @base, Int32 max, IntPtr data);
internal static Build2DMipmapLevels gluBuild2DMipmapLevels;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 Build2DMipmaps(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, PixelFormat format, PixelType type, IntPtr data);
internal static Build2DMipmaps gluBuild2DMipmaps;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 Build3DMipmapLevels(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, Int32 depth, PixelFormat format, PixelType type, Int32 level, Int32 @base, Int32 max, IntPtr data);
internal static Build3DMipmapLevels gluBuild3DMipmapLevels;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 Build3DMipmaps(TextureTarget target, Int32 internalFormat, Int32 width, Int32 height, Int32 depth, PixelFormat format, PixelType type, IntPtr data);
internal static Build3DMipmaps gluBuild3DMipmaps;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate bool CheckExtension(Byte* extName, Byte* extString);
internal unsafe static CheckExtension gluCheckExtension;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void Cylinder(IntPtr quad, double @base, double top, double height, Int32 slices, Int32 stacks);
internal static Cylinder gluCylinder;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void DeleteNurbsRenderer(IntPtr nurb);
internal static DeleteNurbsRenderer gluDeleteNurbsRenderer;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void DeleteQuadric(IntPtr quad);
internal static DeleteQuadric gluDeleteQuadric;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void DeleteTess(IntPtr tess);
internal static DeleteTess gluDeleteTess;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void Disk(IntPtr quad, double inner, double outer, Int32 slices, Int32 loops);
internal static Disk gluDisk;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void EndCurve(IntPtr nurb);
internal static EndCurve gluEndCurve;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void EndPolygon(IntPtr tess);
internal static EndPolygon gluEndPolygon;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void EndSurface(IntPtr nurb);
internal static EndSurface gluEndSurface;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void EndTrim(IntPtr nurb);
internal static EndTrim gluEndTrim;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate IntPtr ErrorString(OpenTK.Graphics.GluErrorCode error);
internal static ErrorString gluErrorString;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate IntPtr GetString(OpenTK.Graphics.GluStringName name);
internal static GetString gluGetString;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void GetNurbsProperty(IntPtr nurb, OpenTK.Graphics.NurbsProperty property, [Out] float* data);
internal unsafe static GetNurbsProperty gluGetNurbsProperty;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void GetTessProperty(IntPtr tess, OpenTK.Graphics.TessParameter which, [Out] double* data);
internal unsafe static GetTessProperty gluGetTessProperty;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void LoadSamplingMatrices(IntPtr nurb, float* model, float* perspective, Int32* view);
internal unsafe static LoadSamplingMatrices gluLoadSamplingMatrices;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void LookAt(double eyeX, double eyeY, double eyeZ, double centerX, double centerY, double centerZ, double upX, double upY, double upZ);
internal static LookAt gluLookAt;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate IntPtr NewNurbsRenderer();
internal static NewNurbsRenderer gluNewNurbsRenderer;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate IntPtr NewQuadric();
internal static NewQuadric gluNewQuadric;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate IntPtr NewTess();
internal static NewTess gluNewTess;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void NextContour(IntPtr tess, OpenTK.Graphics.TessContour type);
internal static NextContour gluNextContour;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void NurbsCallback(IntPtr nurb, OpenTK.Graphics.NurbsCallback which, Delegate CallBackFunc);
internal static NurbsCallback gluNurbsCallback;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void NurbsCallbackData(IntPtr nurb, IntPtr userData);
internal static NurbsCallbackData gluNurbsCallbackData;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void NurbsCallbackDataEXT(IntPtr nurb, IntPtr userData);
internal static NurbsCallbackDataEXT gluNurbsCallbackDataEXT;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void NurbsCurve(IntPtr nurb, Int32 knotCount, [Out] float* knots, Int32 stride, [Out] float* control, Int32 order, MapTarget type);
internal unsafe static NurbsCurve gluNurbsCurve;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void NurbsProperty(IntPtr nurb, OpenTK.Graphics.NurbsProperty property, float value);
internal static NurbsProperty gluNurbsProperty;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void NurbsSurface(IntPtr nurb, Int32 sKnotCount, float* sKnots, Int32 tKnotCount, float* tKnots, Int32 sStride, Int32 tStride, float* control, Int32 sOrder, Int32 tOrder, MapTarget type);
internal unsafe static NurbsSurface gluNurbsSurface;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void Ortho2D(double left, double right, double bottom, double top);
internal static Ortho2D gluOrtho2D;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void PartialDisk(IntPtr quad, double inner, double outer, Int32 slices, Int32 loops, double start, double sweep);
internal static PartialDisk gluPartialDisk;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void Perspective(double fovy, double aspect, double zNear, double zFar);
internal static Perspective gluPerspective;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void PickMatrix(double x, double y, double delX, double delY, [Out] Int32* viewport);
internal unsafe static PickMatrix gluPickMatrix;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate Int32 Project(double objX, double objY, double objZ, double* model, double* proj, Int32* view, double* winX, double* winY, double* winZ);
internal unsafe static Project gluProject;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void PwlCurve(IntPtr nurb, Int32 count, float* data, Int32 stride, OpenTK.Graphics.NurbsTrim type);
internal unsafe static PwlCurve gluPwlCurve;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void QuadricCallback(IntPtr quad, OpenTK.Graphics.QuadricCallback which, Delegate CallBackFunc);
internal static QuadricCallback gluQuadricCallback;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void QuadricDrawStyle(IntPtr quad, OpenTK.Graphics.QuadricDrawStyle draw);
internal static QuadricDrawStyle gluQuadricDrawStyle;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void QuadricNormals(IntPtr quad, OpenTK.Graphics.QuadricNormal normal);
internal static QuadricNormals gluQuadricNormals;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void QuadricOrientation(IntPtr quad, OpenTK.Graphics.QuadricOrientation orientation);
internal static QuadricOrientation gluQuadricOrientation;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void QuadricTexture(IntPtr quad, bool texture);
internal static QuadricTexture gluQuadricTexture;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate Int32 ScaleImage(PixelFormat format, Int32 wIn, Int32 hIn, PixelType typeIn, IntPtr dataIn, Int32 wOut, Int32 hOut, PixelType typeOut, [Out] IntPtr dataOut);
internal static ScaleImage gluScaleImage;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void Sphere(IntPtr quad, double radius, Int32 slices, Int32 stacks);
internal static Sphere gluSphere;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessBeginContour(IntPtr tess);
internal static TessBeginContour gluTessBeginContour;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessBeginPolygon(IntPtr tess, IntPtr data);
internal static TessBeginPolygon gluTessBeginPolygon;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessCallback(IntPtr tess, OpenTK.Graphics.TessCallback which, Delegate CallBackFunc);
internal static TessCallback gluTessCallback;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessEndContour(IntPtr tess);
internal static TessEndContour gluTessEndContour;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessEndPolygon(IntPtr tess);
internal static TessEndPolygon gluTessEndPolygon;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessNormal(IntPtr tess, double valueX, double valueY, double valueZ);
internal static TessNormal gluTessNormal;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void TessProperty(IntPtr tess, OpenTK.Graphics.TessParameter which, double data);
internal static TessProperty gluTessProperty;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void TessVertex(IntPtr tess, double* location, IntPtr data);
internal unsafe static TessVertex gluTessVertex;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate Int32 TexFilterFuncSGI(TextureTarget target, SgisTextureFilter4 filtertype, float* parms, Int32 n, [Out] float* weights);
internal unsafe static TexFilterFuncSGI gluTexFilterFuncSGI;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate Int32 UnProject(double winX, double winY, double winZ, double* model, double* proj, Int32* view, double* objX, double* objY, double* objZ);
internal unsafe static UnProject gluUnProject;
[System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate Int32 UnProject4(double winX, double winY, double winZ, double clipW, double* model, double* proj, Int32* view, double near, double far, double* objX, double* objY, double* objZ, double* objW);
internal unsafe static UnProject4 gluUnProject4;
}
}
}

View file

@ -0,0 +1,390 @@
namespace OpenTK.Graphics
{
#pragma warning disable 1591
public enum GluVersion
{
Version11 = ((int)1),
Version13 = ((int)1),
Version12 = ((int)1),
}
public enum GluStringName
{
Version = ((int)100800),
Extensions = ((int)100801),
}
public enum GluErrorCode
{
OutOfMemory = ((int)100902),
InvalidEnum = ((int)100900),
InvalidValue = ((int)100901),
InvalidOperation = ((int)100904),
}
public enum Filter4TypeSGIS
{
MitchellNetravaliSgi = ((int)100301),
LagrangianSgi = ((int)100300),
}
public enum NurbsDisplay
{
OutlinePolygon = ((int)100240),
OutlinePatch = ((int)100241),
Fill = ((int)QuadricDrawStyle.Fill),
}
public enum NurbsCallback
{
NurbsColorData = ((int)100173),
NurbsVertexData = ((int)100171),
NurbsNormal = ((int)100166),
NurbsError = ((int)100103),
NurbsTextureCoordExt = ((int)100168),
Error = ((int)100103),
NurbsEndDataExt = ((int)100175),
NurbsEnd = ((int)100169),
NurbsTextureCoord = ((int)100168),
NurbsEndExt = ((int)100169),
NurbsNormalDataExt = ((int)100172),
NurbsColor = ((int)100167),
NurbsColorExt = ((int)100167),
NurbsVertexExt = ((int)100165),
NurbsBeginExt = ((int)100164),
NurbsTextureCoordData = ((int)100174),
NurbsBeginData = ((int)100170),
NurbsColorDataExt = ((int)100173),
NurbsBeginDataExt = ((int)100170),
NurbsVertex = ((int)100165),
NurbsTextureCoordDataExt = ((int)100174),
NurbsNormalExt = ((int)100166),
NurbsVertexDataExt = ((int)100171),
NurbsBegin = ((int)100164),
NurbsEndData = ((int)100175),
NurbsNormalData = ((int)100172),
}
public enum NurbsError
{
NurbsError37 = ((int)100287),
NurbsError16 = ((int)100266),
NurbsError26 = ((int)100276),
NurbsError36 = ((int)100286),
NurbsError19 = ((int)100269),
NurbsError29 = ((int)100279),
NurbsError8 = ((int)100258),
NurbsError12 = ((int)100262),
NurbsError9 = ((int)100259),
NurbsError1 = ((int)100251),
NurbsError18 = ((int)100268),
NurbsError28 = ((int)100278),
NurbsError4 = ((int)100254),
NurbsError5 = ((int)100255),
NurbsError6 = ((int)100256),
NurbsError7 = ((int)100257),
NurbsError3 = ((int)100253),
NurbsError22 = ((int)100272),
NurbsError32 = ((int)100282),
NurbsError2 = ((int)100252),
NurbsError11 = ((int)100261),
NurbsError21 = ((int)100271),
NurbsError31 = ((int)100281),
NurbsError10 = ((int)100260),
NurbsError20 = ((int)100270),
NurbsError30 = ((int)100280),
NurbsError15 = ((int)100265),
NurbsError25 = ((int)100275),
NurbsError35 = ((int)100285),
NurbsError14 = ((int)100264),
NurbsError24 = ((int)100274),
NurbsError34 = ((int)100284),
NurbsError13 = ((int)100263),
NurbsError23 = ((int)100273),
NurbsError33 = ((int)100283),
NurbsError17 = ((int)100267),
NurbsError27 = ((int)100277),
}
public enum NurbsProperty
{
DisplayMode = ((int)100204),
ParametricTolerance = ((int)100202),
NurbsRenderer = ((int)100162),
NurbsTessellator = ((int)100161),
NurbsTessellatorExt = ((int)100161),
NurbsModeExt = ((int)100160),
UStep = ((int)100206),
SamplingMethod = ((int)100205),
AutoLoadMatrix = ((int)100200),
VStep = ((int)100207),
Culling = ((int)100201),
NurbsRendererExt = ((int)100162),
NurbsMode = ((int)100160),
SamplingTolerance = ((int)100203),
}
public enum NurbsSampling
{
ObjectParametricError = ((int)100208),
ObjectPathLength = ((int)100209),
PathLength = ((int)100215),
DomainDistance = ((int)100217),
ObjectPathLengthExt = ((int)100209),
ObjectParametricErrorExt = ((int)100208),
ParametricError = ((int)100216),
}
public enum NurbsTrim
{
Map1Trim3 = ((int)100211),
Map1Trim2 = ((int)100210),
}
public enum QuadricDrawStyle
{
Line = ((int)100011),
Silhouette = ((int)100013),
Point = ((int)100010),
Fill = ((int)100012),
}
public enum QuadricCallback
{
Error = ((int)NurbsCallback.Error),
}
public enum QuadricNormal
{
None = ((int)100002),
Flat = ((int)100001),
Smooth = ((int)100000),
}
public enum QuadricOrientation
{
Outside = ((int)100020),
Inside = ((int)100021),
}
public enum TessCallback
{
TessEdgeFlagData = ((int)100110),
Begin = ((int)100100),
TessError = ((int)100103),
EdgeFlag = ((int)100104),
End = ((int)100102),
TessCombine = ((int)100105),
Error = ((int)100103),
TessEndData = ((int)100108),
TessBeginData = ((int)100106),
TessErrorData = ((int)100109),
Vertex = ((int)100101),
TessVertexData = ((int)100107),
TessVertex = ((int)100101),
TessEdgeFlag = ((int)100104),
TessEnd = ((int)100102),
TessBegin = ((int)100100),
TessCombineData = ((int)100111),
}
public enum TessContour
{
Exterior = ((int)100123),
Ccw = ((int)100121),
Interior = ((int)100122),
Unknown = ((int)100124),
Cw = ((int)100120),
}
public enum TessParameter
{
TessWindingRule = ((int)100140),
TessBoundaryOnly = ((int)100141),
TessTolerance = ((int)100142),
}
public enum TessError
{
TessMissingBeginPolygon = ((int)100151),
TessMissingEndPolygon = ((int)100153),
TessError1 = ((int)100151),
TessMissingBeginContour = ((int)100152),
TessCoordTooLarge = ((int)100155),
TessError7 = ((int)100157),
TessError2 = ((int)100152),
TessError4 = ((int)100154),
TessNeedCombineCallback = ((int)100156),
TessError3 = ((int)100153),
TessError6 = ((int)100156),
TessError5 = ((int)100155),
TessError8 = ((int)100158),
TessMissingEndContour = ((int)100154),
}
public enum TessWinding
{
TessWindingNonzero = ((int)100131),
TessWindingOdd = ((int)100130),
TessWindingPositive = ((int)100132),
TessWindingAbsGeqTwo = ((int)100134),
TessWindingNegative = ((int)100133),
}
public enum AllGlu
{
None = ((int)100002),
TessWindingRule = ((int)100140),
TessWindingPositive = ((int)100132),
ObjectPathLength = ((int)100209),
NurbsTextureCoordExt = ((int)100168),
Vertex = ((int)100101),
TessCombine = ((int)100105),
AutoLoadMatrix = ((int)100200),
TessBoundaryOnly = ((int)100141),
NurbsEndExt = ((int)100169),
NurbsError17 = ((int)100267),
NurbsError27 = ((int)100277),
NurbsError37 = ((int)100287),
Interior = ((int)100122),
TessWindingOdd = ((int)100130),
InvalidValue = ((int)100901),
ParametricError = ((int)100216),
TessError8 = ((int)100158),
NurbsError14 = ((int)100264),
NurbsError24 = ((int)100274),
NurbsError34 = ((int)100284),
NurbsTextureCoordDataExt = ((int)100174),
TessMissingBeginContour = ((int)100152),
Silhouette = ((int)100013),
TessError7 = ((int)100157),
NurbsNormalDataExt = ((int)100172),
NurbsError21 = ((int)100271),
NurbsError31 = ((int)100281),
PathLength = ((int)100215),
OutlinePolygon = ((int)100240),
TessVertex = ((int)100101),
TessWindingAbsGeqTwo = ((int)100134),
Extensions = ((int)100801),
TessEdgeFlagData = ((int)100110),
EdgeFlag = ((int)100104),
TessError1 = ((int)100151),
Line = ((int)100011),
NurbsBeginExt = ((int)100164),
Point = ((int)100010),
Begin = ((int)100100),
Inside = ((int)100021),
Flat = ((int)100001),
TessBegin = ((int)100100),
NurbsNormal = ((int)100166),
NurbsColorData = ((int)100173),
NurbsBeginDataExt = ((int)100170),
NurbsRenderer = ((int)100162),
NurbsBeginData = ((int)100170),
Outside = ((int)100020),
DisplayMode = ((int)100204),
NurbsError15 = ((int)100265),
NurbsError25 = ((int)100275),
NurbsError35 = ((int)100285),
NurbsVertexExt = ((int)100165),
TessError5 = ((int)100155),
Unknown = ((int)100124),
NurbsEndDataExt = ((int)100175),
NurbsError12 = ((int)100262),
NurbsError22 = ((int)100272),
NurbsError32 = ((int)100282),
ObjectParametricErrorExt = ((int)100208),
NurbsRendererExt = ((int)100162),
TessError3 = ((int)100153),
Fill = ((int)100012),
TessError = ((int)100103),
ObjectPathLengthExt = ((int)100209),
TessWindingNegative = ((int)100133),
NurbsTessellator = ((int)100161),
NurbsColor = ((int)100167),
NurbsModeExt = ((int)100160),
SamplingTolerance = ((int)100203),
NurbsColorDataExt = ((int)100173),
Exterior = ((int)100123),
Ccw = ((int)100121),
Cw = ((int)100120),
NurbsNormalExt = ((int)100166),
NurbsError18 = ((int)100268),
NurbsError28 = ((int)100278),
LagrangianSgi = ((int)100300),
TessEnd = ((int)100102),
NurbsTessellatorExt = ((int)100161),
NurbsEnd = ((int)100169),
TessWindingNonzero = ((int)100131),
OutOfMemory = ((int)100902),
TessBeginData = ((int)100106),
Error = ((int)100103),
ObjectParametricError = ((int)100208),
NurbsBegin = ((int)100164),
TessCombineData = ((int)100111),
TessMissingEndPolygon = ((int)100153),
NurbsTextureCoord = ((int)100168),
Smooth = ((int)100000),
TessMissingBeginPolygon = ((int)100151),
NurbsEndData = ((int)100175),
NurbsVertexData = ((int)100171),
TessEndData = ((int)100108),
NurbsError11 = ((int)100261),
NurbsVertex = ((int)100165),
NurbsError30 = ((int)100280),
Version11 = ((int)1),
TessError6 = ((int)100156),
Version13 = ((int)1),
Version12 = ((int)1),
TessErrorData = ((int)100109),
NurbsError36 = ((int)100286),
End = ((int)100102),
SamplingMethod = ((int)100205),
TessNeedCombineCallback = ((int)100156),
UStep = ((int)100206),
DomainDistance = ((int)100217),
TessEdgeFlag = ((int)100104),
NurbsColorExt = ((int)100167),
NurbsError19 = ((int)100269),
NurbsError29 = ((int)100279),
InvalidOperation = ((int)100904),
TessCoordTooLarge = ((int)100155),
TessVertexData = ((int)100107),
NurbsMode = ((int)100160),
ParametricTolerance = ((int)100202),
NurbsError2 = ((int)100252),
VStep = ((int)100207),
TessMissingEndContour = ((int)100154),
Map1Trim2 = ((int)100210),
Map1Trim3 = ((int)100211),
Culling = ((int)100201),
NurbsError16 = ((int)100266),
NurbsError26 = ((int)100276),
NurbsVertexDataExt = ((int)100171),
NurbsNormalData = ((int)100172),
TessError2 = ((int)100152),
NurbsError13 = ((int)100263),
NurbsError23 = ((int)100273),
NurbsError33 = ((int)100283),
NurbsError8 = ((int)100258),
NurbsError9 = ((int)100259),
TessError4 = ((int)100154),
NurbsError10 = ((int)100260),
NurbsError20 = ((int)100270),
OutlinePatch = ((int)100241),
NurbsError = ((int)100103),
NurbsTextureCoordData = ((int)100174),
NurbsError1 = ((int)100251),
InvalidEnum = ((int)100900),
NurbsError3 = ((int)100253),
NurbsError4 = ((int)100254),
NurbsError5 = ((int)100255),
NurbsError6 = ((int)100256),
NurbsError7 = ((int)100257),
MitchellNetravaliSgi = ((int)100301),
Version = ((int)100800),
TessTolerance = ((int)100142),
}
}

View file

@ -0,0 +1,446 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* Contributions by Andy Gill.
* See license.txt for license info
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Reflection.Emit;
using OpenTK.Platform;
namespace OpenTK.Graphics
{
/// <summary>
/// Provides access to the OpenGL Utilities library.
/// Methods i this library are considered deprecated and should be avoided.
/// </summary>
[Obsolete("Use OpenTK math functions instead.")]
public static partial class Glu
{
private const string Library = "glu32.dll";
private static Dictionary<string, bool> AvailableExtensions = new Dictionary<string, bool>();
private static bool rebuildExtensionList = true;
private static Type importsClass = typeof(Imports);
static Glu()
{
// Glu doesn't have any extensions, so this is safe to call once and be done with it.
LoadAll();
}
#region private static Delegate LoadDelegate(string name, Type signature)
/// <summary>
/// Creates a System.Delegate that can be used to call a GLU function, core or extension.
/// </summary>
/// <param name="name">The name of the GLU function (eg. "gluBuild2DMipmaps")</param>
/// <param name="signature">The signature of the GLU function.</param>
/// <returns>
/// A System.Delegate that can be used to call this GLU function, or null if the specified
/// function name did not correspond to an GLU function.
/// </returns>
private static Delegate LoadDelegate(string name, Type signature)
{
MethodInfo m = importsClass.GetMethod(name.Substring(3), BindingFlags.Static | BindingFlags.NonPublic);
return
GL.GetExtensionDelegate(name, signature) ??
(m != null ? Delegate.CreateDelegate(signature, m) : null);
}
#endregion
#region public static void LoadAll()
/// <summary>
/// Loads all GLU functions (core and extensions).
/// </summary>
/// <remarks>
/// <para>
/// Call this function manually whenever you need to update GLU entry points.
/// This need will never arise under normal usage patterns.
/// </para>
/// </remarks>
public static void LoadAll()
{
int supported = 0;
Type extensions_class = typeof(Glu).GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (extensions_class == null)
throw new InvalidOperationException("The specified type does not have any loadable extensions.");
FieldInfo[] delegates = extensions_class.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (delegates == null)
throw new InvalidOperationException("The specified type does not have any loadable extensions.");
foreach (FieldInfo f in delegates)
{
Delegate d = LoadDelegate(f.Name, f.FieldType);
if (d != null)
++supported;
f.SetValue(null, d);
}
rebuildExtensionList = true;
}
#endregion
#region public static bool Load(string function)
/// <summary>
/// Tries to reload the given GLU function (core or extension).
/// </summary>
/// <param name="function">The name of the GLU function.</param>
/// <returns>True if the function was found and reloaded, false otherwise.</returns>
/// <remarks>
/// <para>
/// While the automatic initialisation will load all GLU entry points, in some cases
/// the initialization can take place before a render context has been established.
/// In this case, use this function to load the entry points for the GLU functions
/// you will need, or use LoadAll() to load all available entry points.
/// </para>
/// <para>
/// This function returns true if the given GLU function is supported, false otherwise.
/// </para>
/// <para>
/// To query for supported extensions use the IsExtensionSupported() function instead.
/// </para>
/// </remarks>
public static bool Load(string function)
{
// Glu does not contain any extensions - this method does nothing.
return true;
}
#endregion
#region public static bool SupportsExtension(string name)
/// <summary>
/// Determines whether the specified GLU extension is available in
/// the current GLU context.
/// </summary>
/// <param name="name">The string for the GLU extension.</param>
/// <returns>True if the specified extension is available, false otherwise.</returns>
public static bool SupportsExtension(string name)
{
if (rebuildExtensionList)
{
BuildExtensionList();
}
// Search the cache for the string. Note that the cache substitutes
// strings "1.0" to "2.1" with "GL_VERSION_1_0" to "GL_VERSION_2_1"
if (AvailableExtensions.ContainsKey(name))
{
return AvailableExtensions[name];
}
return false;
}
#endregion
#region private static void BuildExtensionList()
/// <summary>
/// Builds a cache of the supported extensions to speed up searches.
/// </summary>
private static void BuildExtensionList()
{
// Assumes there is an opengl context current.
AvailableExtensions.Clear();
string version_string = Glu.GetString(GluStringName.Version);
if (String.IsNullOrEmpty(version_string))
{
throw new ApplicationException("Failed to build extension list. Is there an opengl context current?");
}
string version = version_string.Trim(' ');
if (version.StartsWith("1.0"))
{
AvailableExtensions.Add("VERSION_1_0", true);
}
else if (version.StartsWith("1.1"))
{
AvailableExtensions.Add("VERSION_1_0", true);
AvailableExtensions.Add("VERSION_1_1", true);
}
else if (version.StartsWith("1.2"))
{
AvailableExtensions.Add("VERSION_1_0", true);
AvailableExtensions.Add("VERSION_1_1", true);
AvailableExtensions.Add("VERSION_1_2", true);
}
else if (version.StartsWith("1.3"))
{
AvailableExtensions.Add("VERSION_1_0", true);
AvailableExtensions.Add("VERSION_1_1", true);
AvailableExtensions.Add("VERSION_1_2", true);
AvailableExtensions.Add("VERSION_1_3", true);
}
string extension_string = Glu.GetString(GluStringName.Extensions);
if (String.IsNullOrEmpty(extension_string))
{ // no extensions are available
return;
}
string[] extensions = extension_string.Split(' ');
foreach (string ext in extensions)
{
AvailableExtensions.Add(ext, true);
}
rebuildExtensionList = false;
}
#endregion
#region Overloads
public static void LookAt(Vector3 eye, Vector3 center, Vector3 up)
{
Delegates.gluLookAt((double)eye.X, (double)eye.Y, (double)eye.Z, (double)center.X, (double)center.Y, (double)center.Z, (double)up.X, (double)up.Y, (double)up.Z);
}
// One token Project overload, I picked this one because it's CLS compliant, and it
// makes reasonably clear which args are inputs and which are outputs.
public static Int32 Project(Vector3 obj, double[] model, double[] proj, Int32[] view, out Vector3 win)
{
unsafe
{
double winX, winY, winZ;
double* winX_ptr = &winX;
double* winY_ptr = &winY;
double* winZ_ptr = &winZ;
fixed (double* model_ptr = model)
fixed (double* proj_ptr = proj)
fixed (Int32* view_ptr = view)
{
Int32 retval = Delegates.gluProject((double)obj.X, (double)obj.Y, (double)obj.Z, (double*)model_ptr, (double*)proj_ptr, (Int32*)view_ptr, (double*)winX_ptr, (double*)winY_ptr, (double*)winZ_ptr);
win = new Vector3((float)*winX_ptr, (float)*winY_ptr, (float)*winZ_ptr);
return retval;
}
}
}
public static void TessNormal(IntPtr tess, Vector3 normal)
{
Delegates.gluTessNormal(tess, (double)normal.X, (double)normal.Y, (double)normal.Z);
}
public static Int32 UnProject(Vector3 win, double[] model, double[] proj, Int32[] view, out Vector3 obj)
{
unsafe
{
double objX, objY, objZ;
double* objX_ptr = &objX;
double* objY_ptr = &objY;
double* objZ_ptr = &objZ;
fixed (double* model_ptr = model)
fixed (double* proj_ptr = proj)
fixed (Int32* view_ptr = view)
{
Int32 retval = Delegates.gluUnProject((double)win.X, (double)win.Y, (double)win.Z, (double*)model_ptr, (double*)proj_ptr, (Int32*)view_ptr, (double*)objX_ptr, (double*)objY_ptr, (double*)objZ_ptr);
obj = new Vector3((float)*objX_ptr, (float)*objY_ptr, (float)*objZ_ptr);
return retval;
}
}
}
public static Int32 UnProject4(Vector4 win, double[] model, double[] proj, Int32[] view, double near, double far, out Vector4 obj)
{
unsafe
{
double objX, objY, objZ, objW;
double* objX_ptr = &objX;
double* objY_ptr = &objY;
double* objZ_ptr = &objZ;
double* objW_ptr = &objW;
fixed (double* model_ptr = model)
fixed (double* proj_ptr = proj)
fixed (Int32* view_ptr = view)
{
Int32 retval = Delegates.gluUnProject4((double)win.X, (double)win.Y, (double)win.Z, (double)win.W, (double*)model_ptr, (double*)proj_ptr, (Int32*)view_ptr, (double)near, (double)far, (double*)objX_ptr, (double*)objY_ptr, (double*)objZ_ptr, (double*)objW_ptr);
obj = new Vector4((float)*objX_ptr, (float)*objY_ptr, (float)*objZ_ptr, (float)*objW_ptr);
return retval;
}
}
}
public static string ErrorString(ErrorCode error)
{
return ErrorString((GluErrorCode)error);
}
public static void TessWindingRuleProperty(IntPtr tess, TessWinding property)
{
Glu.TessProperty(tess, TessParameter.TessWindingRule, (double)property);
}
#endregion
}
#if false
//public delegate object
public delegate void FastVoidInvokeHandler(object target, object[] paramters);
public delegate object FastInvokeHandler(object target, object[] paramters);
public static class FastInvoker
{
/// <summary>
/// Use this one instead of MethodInfo.Invoke, this way it is 50 times quicker.
///
/// <example>
/// string Filter = "FirstName = 'Ton'"
/// MethodInfo mi = typeof(Person).GetMethod("GetAll");
/// snoei.net.Reflection.FastInvoker.FastInvokeHandler fi = snoei.net.Reflection.FastInvoker.GetMethodInvoker( mi );
// return fi.Invoke( Person, new object[]{Filter} );
/// //Calls Person.GetAll(string Filter);
/// </example>
/// </summary>
/// <param name="methodInfo"></param>
/// <returns></returns>
public static Delegate GetMethodInvoker(MethodInfo methodInfo)
{
DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, methodInfo.ReturnType, new Type[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType.Module);
ILGenerator il = dynamicMethod.GetILGenerator();
ParameterInfo[] ps = methodInfo.GetParameters();
Type[] paramTypes = new Type[ps.Length];
for (int i = 0; i < paramTypes.Length; i++)
{
if (ps[i].ParameterType.IsByRef)
paramTypes[i] = ps[i].ParameterType.GetElementType();
else
paramTypes[i] = ps[i].ParameterType;
}
LocalBuilder[] locals = new LocalBuilder[paramTypes.Length];
for (int i = 0; i < paramTypes.Length; i++)
locals[i] = il.DeclareLocal(paramTypes[i], true);
for (int i = 0; i < paramTypes.Length; i++)
{
il.Emit(OpCodes.Ldarg_1);
EmitFastInt(il, i);
il.Emit(OpCodes.Ldelem_Ref);
EmitCastToReference(il, paramTypes[i]);
il.Emit(OpCodes.Stloc, locals[i]);
}
if (!methodInfo.IsStatic)
il.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < paramTypes.Length; i++)
{
if (ps[i].ParameterType.IsByRef)
il.Emit(OpCodes.Ldloca_S, locals[i]);
else
il.Emit(OpCodes.Ldloc, locals[i]);
}
if (methodInfo.IsStatic)
il.EmitCall(OpCodes.Call, methodInfo, null);
else
il.EmitCall(OpCodes.Callvirt, methodInfo, null);
if (methodInfo.ReturnType == typeof(void))
il.Emit(OpCodes.Ldnull);
else
EmitBoxIfNeeded(il, methodInfo.ReturnType);
for (int i = 0; i < paramTypes.Length; i++)
{
if (ps[i].ParameterType.IsByRef)
{
il.Emit(OpCodes.Ldarg_1);
EmitFastInt(il, i);
il.Emit(OpCodes.Ldloc, locals[i]);
if (locals[i].LocalType.IsValueType)
il.Emit(OpCodes.Box, locals[i].LocalType);
il.Emit(OpCodes.Stelem_Ref);
}
}
il.Emit(OpCodes.Ret);
if (methodInfo.ReturnType == typeof(void))
return dynamicMethod.CreateDelegate(typeof(FastVoidInvokeHandler));
else
return dynamicMethod.CreateDelegate(typeof(FastInvokeHandler));
}
private static void EmitCastToReference(ILGenerator il, System.Type type)
{
if (type.IsValueType)
il.Emit(OpCodes.Unbox_Any, type);
else
il.Emit(OpCodes.Castclass, type);
}
private static void EmitBoxIfNeeded(ILGenerator il, System.Type type)
{
if (type.IsValueType)
il.Emit(OpCodes.Box, type);
}
private static void EmitFastInt(ILGenerator il, int value)
{
switch (value)
{
case -1:
il.Emit(OpCodes.Ldc_I4_M1);
return;
case 0:
il.Emit(OpCodes.Ldc_I4_0);
return;
case 1:
il.Emit(OpCodes.Ldc_I4_1);
return;
case 2:
il.Emit(OpCodes.Ldc_I4_2);
return;
case 3:
il.Emit(OpCodes.Ldc_I4_3);
return;
case 4:
il.Emit(OpCodes.Ldc_I4_4);
return;
case 5:
il.Emit(OpCodes.Ldc_I4_5);
return;
case 6:
il.Emit(OpCodes.Ldc_I4_6);
return;
case 7:
il.Emit(OpCodes.Ldc_I4_7);
return;
case 8:
il.Emit(OpCodes.Ldc_I4_8);
return;
}
if (value > -129 && value < 128)
il.Emit(OpCodes.Ldc_I4_S, (SByte)value);
else
il.Emit(OpCodes.Ldc_I4, value);
}
}
#endif
}

View file

@ -0,0 +1,261 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
* Contributions by Georg W<EFBFBD>chter.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Math
{
/// <summary>
/// Represents a bezier curve with as many points as you want.
/// </summary>
[Serializable]
public struct BezierCurve
{
#region Fields
private List<Vector2> points;
/// <summary>
/// The parallel value.
/// </summary>
/// <remarks>This value defines whether the curve should be calculated as a
/// parallel curve to the original bezier curve. A value of 0.0f represents
/// the original curve, 5.0f i.e. stands for a curve that has always a distance
/// of 5.0f to the orignal curve at any point.</remarks>
public float Parallel;
#endregion
#region Properties
/// <summary>
/// Gets the points of this curve.
/// </summary>
/// <remarks>The first point and the last points represent the anchor points.</remarks>
public IList<Vector2> Points
{
get
{
return points;
}
}
#endregion
#region Constructors
/// <summary>
/// Constructs a new <see cref="BezierCurve"/>.
/// </summary>
/// <param name="points">The points.</param>
public BezierCurve(IEnumerable<Vector2> points)
{
if (points == null)
throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
this.points = new List<Vector2>(points);
this.Parallel = 0.0f;
}
/// <summary>
/// Constructs a new <see cref="BezierCurve"/>.
/// </summary>
/// <param name="points">The points.</param>
public BezierCurve(params Vector2[] points)
{
if (points == null)
throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
this.points = new List<Vector2>(points);
this.Parallel = 0.0f;
}
/// <summary>
/// Constructs a new <see cref="BezierCurve"/>.
/// </summary>
/// <param name="parallel">The parallel value.</param>
/// <param name="points">The points.</param>
public BezierCurve(float parallel, params Vector2[] points)
{
if (points == null)
throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
this.Parallel = parallel;
this.points = new List<Vector2>(points);
}
/// <summary>
/// Constructs a new <see cref="BezierCurve"/>.
/// </summary>
/// <param name="parallel">The parallel value.</param>
/// <param name="points">The points.</param>
public BezierCurve(float parallel, IEnumerable<Vector2> points)
{
if (points == null)
throw new ArgumentNullException("points", "Must point to a valid list of Vector2 structures.");
this.Parallel = parallel;
this.points = new List<Vector2>(points);
}
#endregion
#region Functions
/// <summary>
/// Calculates the point with the specified t.
/// </summary>
/// <param name="t">The t value, between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
public Vector2 CalculatePoint(float t)
{
return BezierCurve.CalculatePoint(points, t, Parallel);
}
/// <summary>
/// Calculates the length of this bezier curve.
/// </summary>
/// <param name="precision">The precision.</param>
/// <returns>Length of curve.</returns>
/// <remarks>The precision gets better as the <paramref name="precision"/>
/// value gets smaller.</remarks>
public float CalculateLength(float precision)
{
return BezierCurve.CalculateLength(points, precision, Parallel);
}
#region Static methods
/// <summary>
/// Calculates the length of the specified bezier curve.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="precision">The precision value.</param>
/// <returns>The precision gets better as the <paramref name="precision"/>
/// value gets smaller.</returns>
public static float CalculateLength(IList<Vector2> points, float precision)
{
return BezierCurve.CalculateLength(points, precision, 0.0f);
}
/// <summary>
/// Calculates the length of the specified bezier curve.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="precision">The precision value.</param>
/// <param name="parallel">The parallel value.</param>
/// <returns>Length of curve.</returns>
/// <remarks><para>The precision gets better as the <paramref name="precision"/>
/// value gets smaller.</para>
/// <para>The <paramref name="parallel"/> parameter defines whether the curve should be calculated as a
/// parallel curve to the original bezier curve. A value of 0.0f represents
/// the original curve, 5.0f represents a curve that has always a distance
/// of 5.0f to the orignal curve.</para></remarks>
public static float CalculateLength(IList<Vector2> points, float precision, float parallel)
{
float length = 0.0f;
Vector2 old = BezierCurve.CalculatePoint(points, 0.0f, parallel);
for (float i = precision; i < (1.0f + precision); i += precision)
{
Vector2 n = CalculatePoint(points, i, parallel);
length += (n - old).Length;
old = n;
}
return length;
}
/// <summary>
/// Calculates the point on the given bezier curve with the specified t parameter.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="t">The t parameter, a value between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
public static Vector2 CalculatePoint(IList<Vector2> points, float t)
{
return BezierCurve.CalculatePoint(points, t, 0.0f);
}
/// <summary>
/// Calculates the point on the given bezier curve with the specified t parameter.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="t">The t parameter, a value between 0.0f and 1.0f.</param>
/// <param name="parallel">The parallel value.</param>
/// <returns>Resulting point.</returns>
/// <remarks>The <paramref name="parallel"/> parameter defines whether the curve should be calculated as a
/// parallel curve to the original bezier curve. A value of 0.0f represents
/// the original curve, 5.0f represents a curve that has always a distance
/// of 5.0f to the orignal curve.</remarks>
public static Vector2 CalculatePoint(IList<Vector2> points, float t, float parallel)
{
Vector2 r = new Vector2();
double c = 1.0d - (double)t;
float temp;
int i = 0;
foreach (Vector2 pt in points)
{
temp = (float)Functions.BinomialCoefficient(points.Count - 1, i) * (float)(System.Math.Pow(t, i) *
System.Math.Pow(c, (points.Count - 1) - i));
r.X += temp * pt.X;
r.Y += temp * pt.Y;
i++;
}
if (parallel == 0.0f)
return r;
Vector2 perpendicular = new Vector2();
if (t != 0.0f)
perpendicular = r - BezierCurve.CalculatePointOfDerivative(points, t);
else
perpendicular = points[1] - points[0];
return r + Vector2.Normalize(perpendicular).PerpendicularRight * parallel;
}
/// <summary>
/// Calculates the point with the specified t of the derivative of the given bezier function.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="t">The t parameter, value between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
private static Vector2 CalculatePointOfDerivative(IList<Vector2> points, float t)
{
Vector2 r = new Vector2();
double c = 1.0d - (double)t;
float temp;
int i = 0;
foreach (Vector2 pt in points)
{
temp = (float)Functions.BinomialCoefficient(points.Count - 2, i) * (float)(System.Math.Pow(t, i) *
System.Math.Pow(c, (points.Count - 2) - i));
r.X += temp * pt.X;
r.Y += temp * pt.Y;
i++;
}
return r;
}
#endregion
#endregion
}
}

View file

@ -0,0 +1,163 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
* Contributions by Georg W<EFBFBD>chter.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Math
{
/// <summary>
/// Represents a cubic bezier curve with two anchor and two control points.
/// </summary>
[Serializable]
public struct BezierCurveCubic
{
#region Fields
/// <summary>
/// Start anchor point.
/// </summary>
public Vector2 StartAnchor;
/// <summary>
/// End anchor point.
/// </summary>
public Vector2 EndAnchor;
/// <summary>
/// First control point, controls the direction of the curve start.
/// </summary>
public Vector2 FirstControlPoint;
/// <summary>
/// Second control point, controls the direction of the curve end.
/// </summary>
public Vector2 SecondControlPoint;
/// <summary>
/// Gets or sets the parallel value.
/// </summary>
/// <remarks>This value defines whether the curve should be calculated as a
/// parallel curve to the original bezier curve. A value of 0.0f represents
/// the original curve, 5.0f i.e. stands for a curve that has always a distance
/// of 5.f to the orignal curve at any point.</remarks>
public float Parallel;
#endregion
#region Constructors
/// <summary>
/// Constructs a new <see cref="BezierCurveCubic"/>.
/// </summary>
/// <param name="startAnchor">The start anchor point.</param>
/// <param name="endAnchor">The end anchor point.</param>
/// <param name="firstControlPoint">The first control point.</param>
/// <param name="secondControlPoint">The second control point.</param>
public BezierCurveCubic(Vector2 startAnchor, Vector2 endAnchor, Vector2 firstControlPoint, Vector2 secondControlPoint)
{
this.StartAnchor = startAnchor;
this.EndAnchor = endAnchor;
this.FirstControlPoint = firstControlPoint;
this.SecondControlPoint = secondControlPoint;
this.Parallel = 0.0f;
}
/// <summary>
/// Constructs a new <see cref="BezierCurveCubic"/>.
/// </summary>
/// <param name="parallel">The parallel value.</param>
/// <param name="startAnchor">The start anchor point.</param>
/// <param name="endAnchor">The end anchor point.</param>
/// <param name="firstControlPoint">The first control point.</param>
/// <param name="secondControlPoint">The second control point.</param>
public BezierCurveCubic(float parallel, Vector2 startAnchor, Vector2 endAnchor, Vector2 firstControlPoint, Vector2 secondControlPoint)
{
this.Parallel = parallel;
this.StartAnchor = startAnchor;
this.EndAnchor = endAnchor;
this.FirstControlPoint = firstControlPoint;
this.SecondControlPoint = secondControlPoint;
}
#endregion
#region Functions
/// <summary>
/// Calculates the point with the specified t.
/// </summary>
/// <param name="t">The t value, between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
public Vector2 CalculatePoint(float t)
{
Vector2 r = new Vector2();
float c = 1.0f - t;
r.X = (StartAnchor.X * c * c * c) + (FirstControlPoint.X * 3 * t * c * c) + (SecondControlPoint.X * 3 * t * t * c)
+ EndAnchor.X * t * t * t;
r.Y = (StartAnchor.Y * c * c * c) + (FirstControlPoint.Y * 3 * t * c * c) + (SecondControlPoint.Y * 3 * t * t * c)
+ EndAnchor.Y * t * t * t;
if (Parallel == 0.0f)
return r;
Vector2 perpendicular = new Vector2();
if (t == 0.0f)
perpendicular = FirstControlPoint - StartAnchor;
else
perpendicular = r - CalculatePointOfDerivative(t);
return r + Vector2.Normalize(perpendicular).PerpendicularRight * Parallel;
}
/// <summary>
/// Calculates the point with the specified t of the derivative of this function.
/// </summary>
/// <param name="t">The t, value between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
private Vector2 CalculatePointOfDerivative(float t)
{
Vector2 r = new Vector2();
float c = 1.0f - t;
r.X = (c * c * StartAnchor.X) + (2 * t * c * FirstControlPoint.X) + (t * t * SecondControlPoint.X);
r.Y = (c * c * StartAnchor.Y) + (2 * t * c * FirstControlPoint.Y) + (t * t * SecondControlPoint.Y);
return r;
}
/// <summary>
/// Calculates the length of this bezier curve.
/// </summary>
/// <param name="precision">The precision.</param>
/// <returns>Length of the curve.</returns>
/// <remarks>The precision gets better when the <paramref name="precision"/>
/// value gets smaller.</remarks>
public float CalculateLength(float precision)
{
float length = 0.0f;
Vector2 old = CalculatePoint(0.0f);
for (float i = precision; i < (1.0f + precision); i += precision)
{
Vector2 n = CalculatePoint(i);
length += (n - old).Length;
old = n;
}
return length;
}
#endregion
}
}

View file

@ -0,0 +1,151 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
* Contributions by Georg W<EFBFBD>chter.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Math
{
/// <summary>
/// Represents a quadric bezier curve with two anchor and one control point.
/// </summary>
[Serializable]
public struct BezierCurveQuadric
{
#region Fields
/// <summary>
/// Start anchor point.
/// </summary>
public Vector2 StartAnchor;
/// <summary>
/// End anchor point.
/// </summary>
public Vector2 EndAnchor;
/// <summary>
/// Control point, controls the direction of both endings of the curve.
/// </summary>
public Vector2 ControlPoint;
/// <summary>
/// The parallel value.
/// </summary>
/// <remarks>This value defines whether the curve should be calculated as a
/// parallel curve to the original bezier curve. A value of 0.0f represents
/// the original curve, 5.0f i.e. stands for a curve that has always a distance
/// of 5.f to the orignal curve at any point.</remarks>
public float Parallel;
#endregion
#region Constructors
/// <summary>
/// Constructs a new <see cref="BezierCurveQuadric"/>.
/// </summary>
/// <param name="startAnchor">The start anchor.</param>
/// <param name="endAnchor">The end anchor.</param>
/// <param name="controlPoint">The control point.</param>
public BezierCurveQuadric(Vector2 startAnchor, Vector2 endAnchor, Vector2 controlPoint)
{
this.StartAnchor = startAnchor;
this.EndAnchor = endAnchor;
this.ControlPoint = controlPoint;
this.Parallel = 0.0f;
}
/// <summary>
/// Constructs a new <see cref="BezierCurveQuadric"/>.
/// </summary>
/// <param name="parallel">The parallel value.</param>
/// <param name="startAnchor">The start anchor.</param>
/// <param name="endAnchor">The end anchor.</param>
/// <param name="controlPoint">The control point.</param>
public BezierCurveQuadric(float parallel, Vector2 startAnchor, Vector2 endAnchor, Vector2 controlPoint)
{
this.Parallel = parallel;
this.StartAnchor = startAnchor;
this.EndAnchor = endAnchor;
this.ControlPoint = controlPoint;
}
#endregion
#region Functions
/// <summary>
/// Calculates the point with the specified t.
/// </summary>
/// <param name="t">The t value, between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
public Vector2 CalculatePoint(float t)
{
Vector2 r = new Vector2();
float c = 1.0f - t;
r.X = (c * c * StartAnchor.X) + (2 * t * c * ControlPoint.X) + (t * t * EndAnchor.X);
r.Y = (c * c * StartAnchor.Y) + (2 * t * c * ControlPoint.Y) + (t * t * EndAnchor.Y);
if (Parallel == 0.0f)
return r;
Vector2 perpendicular = new Vector2();
if (t == 0.0f)
perpendicular = ControlPoint - StartAnchor;
else
perpendicular = r - CalculatePointOfDerivative(t);
return r + Vector2.Normalize(perpendicular).PerpendicularRight * Parallel;
}
/// <summary>
/// Calculates the point with the specified t of the derivative of this function.
/// </summary>
/// <param name="t">The t, value between 0.0f and 1.0f.</param>
/// <returns>Resulting point.</returns>
private Vector2 CalculatePointOfDerivative(float t)
{
Vector2 r = new Vector2();
r.X = (1.0f - t) * StartAnchor.X + t * ControlPoint.X;
r.Y = (1.0f - t) * StartAnchor.Y + t * ControlPoint.Y;
return r;
}
/// <summary>
/// Calculates the length of this bezier curve.
/// </summary>
/// <param name="precision">The precision.</param>
/// <returns>Length of curve.</returns>
/// <remarks>The precision gets better when the <paramref name="precision"/>
/// value gets smaller.</remarks>
public float CalculateLength(float precision)
{
float length = 0.0f;
Vector2 old = CalculatePoint(0.0f);
for (float i = precision; i < (1.0f + precision); i += precision)
{
Vector2 n = CalculatePoint(i);
length += (n - old).Length;
old = n;
}
return length;
}
#endregion
}
}

View file

@ -0,0 +1,96 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace OpenTK.Math
{
/// <summary>
/// Defines a 2d box (rectangle).
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Box2
{
/// <summary>
/// The left boundary of the structure.
/// </summary>
public float Left;
/// <summary>
/// The right boundary of the structure.
/// </summary>
public float Right;
/// <summary>
/// The top boundary of the structure.
/// </summary>
public float Top;
/// <summary>
/// The bottom boundary of the structure.
/// </summary>
public float Bottom;
/// <summary>
/// Constructs a new Box2 with the specified dimensions.
/// </summary>
/// <param name="topLeft">AnOpenTK.Vector2 describing the top-left corner of the Box2.</param>
/// <param name="bottomRight">An OpenTK.Vector2 describing the bottom-right corner of the Box2.</param>
public Box2(Vector2 topLeft, Vector2 bottomRight)
{
Left = topLeft.X;
Top = topLeft.Y;
Right = topLeft.X;
Bottom = topLeft.Y;
}
/// <summary>
/// Constructs a new Box2 with the specified dimensions.
/// </summary>
/// <param name="left">The position of the left boundary.</param>
/// <param name="top">The position of the top boundary.</param>
/// <param name="right">The position of the right boundary.</param>
/// <param name="bottom">The position of the bottom boundary.</param>
public Box2(float left, float top, float right, float bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
/// <summary>
/// Creates a new Box2 with the specified dimensions.
/// </summary>
/// <param name="top">The position of the top boundary.</param>
/// <param name="left">The position of the left boundary.</param>
/// <param name="right">The position of the right boundary.</param>
/// <param name="bottom">The position of the bottom boundary.</param>
/// <returns>A new OpenTK.Box2 with the specfied dimensions.</returns>
public static Box2 FromTLRB(float top, float left, float right, float bottom)
{
return new Box2(left, top, right, bottom);
}
/// <summary>
/// Gets a float describing the width of the Box2 structure.
/// </summary>
public float Width { get { return (float)System.Math.Abs(Right - Left); } }
/// <summary>
/// Gets a float describing the height of the Box2 structure.
/// </summary>
public float Height { get { return (float)System.Math.Abs(Bottom - Top); } }
public override string ToString()
{
return String.Format("({0},{1})-({2},{3})", Left, Top, Right, Bottom);
}
}
}

View file

@ -0,0 +1,326 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
* Contributions by Andy Gill, James Talton and Georg Wächter.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Math
{
/// <summary>
/// Contains mathematical functions for the OpenTK.Math toolkit.
/// </summary>
public static class Functions
{
#region public static long NextPowerOfTwo(long n)
/// <summary>
/// Returns the next power of two that is larger than the specified number.
/// </summary>
/// <param name="n">The specified number.</param>
/// <returns>The next power of two.</returns>
public static long NextPowerOfTwo(long n)
{
if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (long)System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2)));
}
#endregion
#region public static int NextPowerOfTwo(int n)
/// <summary>
/// Returns the next power of two that is larger than the specified number.
/// </summary>
/// <param name="n">The specified number.</param>
/// <returns>The next power of two.</returns>
public static int NextPowerOfTwo(int n)
{
if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (int)System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2)));
}
#endregion
#region public static int NextPowerOfTwo(int n)
/// <summary>
/// Returns the next power of two that is larger than the specified number.
/// </summary>
/// <param name="n">The specified number.</param>
/// <returns>The next power of two.</returns>
public static float NextPowerOfTwo(float n)
{
if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (float)System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2)));
}
#endregion
#region public static int NextPowerOfTwo(int n)
/// <summary>
/// Returns the next power of two that is larger than the specified number.
/// </summary>
/// <param name="n">The specified number.</param>
/// <returns>The next power of two.</returns>
public static double NextPowerOfTwo(double n)
{
if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
return System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2)));
}
#endregion
/// <summary>Calculates the factorial of a given natural number.
/// </summary>
/// <param name="n">The number.</param>
/// <returns>n!</returns>
public static long Factorial(int n)
{
long result = 1;
for (; n > 1; n--)
result *= n;
return result;
}
/// <summary>
/// Calculates the binomial coefficient <paramref name="n"/> above <paramref name="k"/>.
/// </summary>
/// <param name="n">The n.</param>
/// <param name="k">The k.</param>
/// <returns>n! / (k! * (n - k)!)</returns>
public static long BinomialCoefficient(int n, int k)
{
return Factorial(n) / (Factorial(k) * Factorial(n - k));
}
/// <summary>
/// Returns an approximation of the inverse square root of left number.
/// </summary>
/// <param name="x">A number.</param>
/// <returns>An approximation of the inverse square root of the specified number, with an upper error bound of 0.001</returns>
/// <remarks>
/// This is an improved implementation of the the method known as Carmack's inverse square root
/// which is found in the Quake III source code. This implementation comes from
/// http://www.codemaestro.com/reviews/review00000105.html. For the history of this method, see
/// http://www.beyond3d.com/content/articles/8/
/// </remarks>
public static float InverseSqrtFast(float x)
{
unsafe
{
float xhalf = 0.5f * x;
int i = *(int*)&x; // Read bits as integer.
i = 0x5f375a86 - (i >> 1); // Make an initial guess for Newton-Raphson approximation
x = *(float*)&i; // Convert bits back to float
x = x * (1.5f - xhalf * x * x); // Perform left single Newton-Raphson step.
return x;
}
}
/// <summary>
/// Returns an approximation of the inverse square root of left number.
/// </summary>
/// <param name="x">A number.</param>
/// <returns>An approximation of the inverse square root of the specified number, with an upper error bound of 0.001</returns>
/// <remarks>
/// This is an improved implementation of the the method known as Carmack's inverse square root
/// which is found in the Quake III source code. This implementation comes from
/// http://www.codemaestro.com/reviews/review00000105.html. For the history of this method, see
/// http://www.beyond3d.com/content/articles/8/
/// </remarks>
public static double InverseSqrtFast(double x)
{
return InverseSqrtFast((float)x);
// TODO: The following code is wrong. Fix it, to improve precision.
#if false
unsafe
{
double xhalf = 0.5f * x;
int i = *(int*)&x; // Read bits as integer.
i = 0x5f375a86 - (i >> 1); // Make an initial guess for Newton-Raphson approximation
x = *(float*)&i; // Convert bits back to float
x = x * (1.5f - xhalf * x * x); // Perform left single Newton-Raphson step.
return x;
}
#endif
}
/// <summary>
/// Convert degrees to radians
/// </summary>
/// <param name="degrees">An angle in degrees</param>
/// <returns>The angle expressed in radians</returns>
public static float DegreesToRadians(float degrees)
{
const float degToRad = (float)System.Math.PI / 180.0f;
return degrees * degToRad;
}
/// <summary>
/// Convert radians to degrees
/// </summary>
/// <param name="radians">An angle in radians</param>
/// <returns>The angle expressed in degrees</returns>
public static float RadiansToDegrees(float radians)
{
const float radToDeg = 180.0f / (float)System.Math.PI;
return radians * radToDeg;
}
public static readonly float PIF = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930382f;
public static readonly float RTODF = 180.0f / PIF;
public static readonly float DTORF = PIF / 180.0f;
public static readonly double PI = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930382d;
public static readonly double RTOD = 180.0d / PIF;
public static readonly double DTOR = PIF / 180.0d;
public static void Swap(ref double a, ref double b)
{
double temp = a;
a = b;
b = temp;
}
public static void Swap(ref float a, ref float b)
{
float temp = a;
a = b;
b = temp;
}
}
#if false
public static partial class Math
{
#region --- Vectors ---
#region --- Addition ---
/// <summary>
/// Adds the given Vector2 to the current Vector3.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector3 containing the result of the addition.</returns>
public static Vector2 Add(Vector2 left, Vector2 right)
{
return new Vector2(left).Add(right);
}
/// <summary>
/// Adds the given Vector3 to the current Vector3.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector3 containing the result of the addition.</returns>
public static Vector3 Add(Vector2 left, Vector3 right)
{
return new Vector3(left).Add(right);
}
/// <summary>
/// Adds the given Vector4 to the current Vector3. W-coordinate remains unaffected.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector4 containing the result of the addition.</returns>
public static Vector4 Add(Vector2 left, Vector4 right)
{
return new Vector4(left).Add(right);
}
/// <summary>
/// Adds the given Vector2 to the current Vector3.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector3 containing the result of the addition.</returns>
public static Vector3 Add(Vector3 left, Vector2 right)
{
return new Vector3(left).Add(right);
}
/// <summary>
/// Adds the given Vector3 to the current Vector3.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector3 containing the result of the addition.</returns>
public static Vector3 Add(Vector3 left, Vector3 right)
{
return new Vector3(left).Add(right);
}
/// <summary>
/// Adds the given Vector4 to the current Vector3. W-coordinate remains unaffected.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector4 containing the result of the addition.</returns>
public static Vector4 Add(Vector3 left, Vector4 right)
{
return new Vector4(left).Add(right);
}
/// <summary>
/// Adds the given Vector2 to the current Vector3.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector3 containing the result of the addition.</returns>
public static Vector4 Add(Vector4 left, Vector2 right)
{
return new Vector4(left).Add(right);
}
/// <summary>
/// Adds the given Vector3 to the current Vector3.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector3 containing the result of the addition.</returns>
public static Vector4 Add(Vector4 left, Vector3 right)
{
return new Vector4(left).Add(right);
}
/// <summary>
/// Adds the given Vector4 to the current Vector3. W-coordinate remains unaffected.
/// </summary>
/// <param name="right">The right operand of the addition.</param>
/// <returns>A new Vector4 containing the result of the addition.</returns>
public static Vector4 Add(Vector4 left, Vector4 right)
{
return new Vector4(left).Add(right);
}
#endregion
#region --- Subtraction ---
#endregion
#region --- Cross ---
/// <summary>
/// Computes the cross product between the current and the given Vector3. The current Vector3 is set to the result of the computation.
/// </summary>
/// <param name="right">The right operand of the cross product</param>
/// <returns>The current </returns>
public static Vector3 Cross(Vector3 left, Vector3 right)
{
return new Vector3(left).Cross(right);
}
#endregion
#endregion
}
#endif
}

View file

@ -0,0 +1,588 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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.
*/
/*
The conversion functions are derived from OpenEXR's implementation and are
governed by the following license:
Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
Digital Ltd. LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Industrial Light & Magic nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion --- License ---
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace OpenTK.Math
{
/// <summary>
/// The name Half is derived from half-precision floating-point number.
/// It occupies only 16 Bits, which are split into 1 Sign bit, 5 Exponent bits and 10 Mantissa bits.
/// </summary>
/// <remarks>
/// Quote from ARB_half_float_pixel specification:
/// Any representable 16-bit floating-point value is legal as input to a GL command that accepts 16-bit floating-point data. The
/// result of providing a value that is not a floating-point number (such as infinity or NaN) to such a command is unspecified,
/// but must not lead to GL interruption or termination. Providing a denormalized number or negative zero to GL must yield
/// predictable results.
/// </remarks>
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Half : ISerializable, IComparable<Half>, IFormattable, IEquatable<Half>
{
#region Internal Field
UInt16 bits;
#endregion Internal Field
#region Properties
/// <summary>Returns true if the Half is zero.</summary>
public bool IsZero { get { return (bits == 0) || (bits == 0x8000); } }
/// <summary>Returns true if the Half represents Not A Number (NaN)</summary>
public bool IsNaN { get { return (((bits & 0x7C00) == 0x7C00) && (bits & 0x03FF) != 0x0000); } }
/// <summary>Returns true if the Half represents positive infinity.</summary>
public bool IsPositiveInfinity { get { return (bits == 31744); } }
/// <summary>Returns true if the Half represents negative infinity.</summary>
public bool IsNegativeInfinity { get { return (bits == 64512); } }
#endregion Properties
#region Constructors
/// <summary>
/// The new Half instance will convert the parameter into 16-Bit Half precision floating point.
/// </summary>
/// <param name="f">32-Bit Single precision floating point number.</param>
public Half(Single f)
: this()
{
unsafe
{
bits = SingleToHalf(*(int*)&f);
}
}
/// <summary>
/// The new Half instance will convert the parameter into 16-Bit Half precision floating point.
/// </summary>
/// <param name="f">32-Bit Single precision floating point number.</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Half(Single f, bool throwOnError)
: this(f)
{
if (throwOnError)
{
// handle cases that cause overflow rather than silently ignoring it
if (f > Half.MaxValue) throw new ArithmeticException("Half: Positive maximum value exceeded.");
if (f < -Half.MaxValue) throw new ArithmeticException("Half: Negative minimum value exceeded.");
// handle cases that make no sense
if (Single.IsNaN(f)) throw new ArithmeticException("Half: input is Not a Number (NaN).");
if (Single.IsPositiveInfinity(f)) throw new ArithmeticException("Half: input is +infinity.");
if (Single.IsNegativeInfinity(f)) throw new ArithmeticException("Half: input is -infinity.");
}
}
/// <summary>
/// The new Half instance will convert the parameter into 16-Bit Half precision floating point.
/// </summary>
/// <param name="d">64-Bit Double precision floating point number.</param>
public Half(Double d) : this((Single)d) { }
/// <summary>
/// The new Half instance will convert the parameter into 16-Bit Half precision floating point.
/// </summary>
/// <param name="d">64-Bit Double precision floating point number.</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Half(Double d, bool throwOnError) : this((Single)d, throwOnError) { }
#endregion Constructors
#region Single -> Half
/// <summary>Ported from OpenEXR's IlmBase 1.0.1</summary>
private UInt16 SingleToHalf(Int32 si32)
{
// Our floating point number, F, is represented by the bit pattern in integer i.
// Disassemble that bit pattern into the sign, S, the exponent, E, and the significand, M.
// Shift S into the position where it will go in in the resulting half number.
// Adjust E, accounting for the different exponent bias of float and half (127 versus 15).
Int32 sign = (si32 >> 16) & 0x00008000;
Int32 exponent = ((si32 >> 23) & 0x000000ff) - (127 - 15);
Int32 mantissa = si32 & 0x007fffff;
// Now reassemble S, E and M into a half:
if (exponent <= 0)
{
if (exponent < -10)
{
// E is less than -10. The absolute value of F is less than Half.MinValue
// (F may be a small normalized float, a denormalized float or a zero).
//
// We convert F to a half zero with the same sign as F.
return (UInt16)sign;
}
// E is between -10 and 0. F is a normalized float whose magnitude is less than Half.MinNormalizedValue.
//
// We convert F to a denormalized half.
// Add an explicit leading 1 to the significand.
mantissa = mantissa | 0x00800000;
// Round to M to the nearest (10+E)-bit value (with E between -10 and 0); in case of a tie, round to the nearest even value.
//
// Rounding may cause the significand to overflow and make our number normalized. Because of the way a half's bits
// are laid out, we don't have to treat this case separately; the code below will handle it correctly.
Int32 t = 14 - exponent;
Int32 a = (1 << (t - 1)) - 1;
Int32 b = (mantissa >> t) & 1;
mantissa = (mantissa + a + b) >> t;
// Assemble the half from S, E (==zero) and M.
return (UInt16)(sign | mantissa);
}
else if (exponent == 0xff - (127 - 15))
{
if (mantissa == 0)
{
// F is an infinity; convert F to a half infinity with the same sign as F.
return (UInt16)(sign | 0x7c00);
}
else
{
// F is a NAN; we produce a half NAN that preserves the sign bit and the 10 leftmost bits of the
// significand of F, with one exception: If the 10 leftmost bits are all zero, the NAN would turn
// into an infinity, so we have to set at least one bit in the significand.
mantissa >>= 13;
return (UInt16)(sign | 0x7c00 | mantissa | ((mantissa == 0) ? 1 : 0));
}
}
else
{
// E is greater than zero. F is a normalized float. We try to convert F to a normalized half.
// Round to M to the nearest 10-bit value. In case of a tie, round to the nearest even value.
mantissa = mantissa + 0x00000fff + ((mantissa >> 13) & 1);
if ((mantissa & 0x00800000) == 1)
{
mantissa = 0; // overflow in significand,
exponent += 1; // adjust exponent
}
// exponent overflow
if (exponent > 30) throw new ArithmeticException("Half: hardware floating point overflow.");
// Assemble the half from S, E and M.
return (UInt16)(sign | (exponent << 10) | (mantissa >> 13));
}
}
#endregion Single -> Half
#region Half -> Single
/// <summary>Converts the 16-Bit half to 32-Bit floating point.</summary>
/// <returns>A Single precision floating point Number.</returns>
public Single ToSingle()
{
int i = HalfToFloat(bits);
unsafe
{
return *(float*)&i;
}
}
/// <summary>Ported from OpenEXR's IlmBase 1.0.1</summary>
private Int32 HalfToFloat(UInt16 ui16)
{
Int32 sign = (ui16 >> 15) & 0x00000001;
Int32 exponent = (ui16 >> 10) & 0x0000001f;
Int32 mantissa = ui16 & 0x000003ff;
if (exponent == 0)
{
if (mantissa == 0)
{
// Plus or minus zero
return sign << 31;
}
else
{
// Denormalized number -- renormalize it
while ((mantissa & 0x00000400) == 0)
{
mantissa <<= 1;
exponent -= 1;
}
exponent += 1;
mantissa &= ~0x00000400;
}
}
else if (exponent == 31)
{
if (mantissa == 0)
{
// Positive or negative infinity
return (sign << 31) | 0x7f800000;
}
else
{
// Nan -- preserve sign and significand bits
return (sign << 31) | 0x7f800000 | (mantissa << 13);
}
}
// Normalized number
exponent = exponent + (127 - 15);
mantissa = mantissa << 13;
// Assemble S, E and M.
return (sign << 31) | (exponent << 23) | mantissa;
}
#endregion Half -> Single
#region Conversions
/// <summary>
/// Converts a System.Single to a OpenTK.Half.
/// </summary>
/// <param name="f">The value to convert.
/// A <see cref="System.Single"/>
/// </param>
/// <returns>The result of the conversion.
/// A <see cref="Half"/>
/// </returns>
public static explicit operator Half(float f)
{
return new Half(f);
}
/// <summary>
/// Converts a System.Double to a OpenTK.Half.
/// </summary>
/// <param name="d">The value to convert.
/// A <see cref="System.Double"/>
/// </param>
/// <returns>The result of the conversion.
/// A <see cref="Half"/>
/// </returns>
public static explicit operator Half(double d)
{
return new Half(d);
}
/// <summary>
/// Converts a OpenTK.Half to a System.Single.
/// </summary>
/// <param name="h">The value to convert.
/// A <see cref="Half"/>
/// </param>
/// <returns>The result of the conversion.
/// A <see cref="System.Single"/>
/// </returns>
public static implicit operator float(Half h)
{
return h.ToSingle();
}
/// <summary>
/// Converts a OpenTK.Half to a System.Double.
/// </summary>
/// <param name="h">The value to convert.
/// A <see cref="Half"/>
/// </param>
/// <returns>The result of the conversion.
/// A <see cref="System.Double"/>
/// </returns>
public static implicit operator double(Half h)
{
return (double)h.ToSingle();
}
#endregion Conversions
#region Constants
/// <summary>The size in bytes for an instance of the Half struct.</summary>
public static readonly Int32 SizeInBytes = 2;
/// <summary>Smallest positive half</summary>
public static readonly Single MinValue = 5.96046448e-08f;
/// <summary>Smallest positive normalized half</summary>
public static readonly Single MinNormalizedValue = 6.10351562e-05f;
/// <summary>Largest positive half</summary>
public static readonly Single MaxValue = 65504.0f;
/// <summary>Smallest positive e for which half (1.0 + e) != half (1.0)</summary>
public static readonly Single Epsilon = 0.00097656f;
#endregion Constants
#region ISerializable
/// <summary>Constructor used by ISerializable to deserialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public Half(SerializationInfo info, StreamingContext context)
{
this.bits = (ushort)info.GetValue("bits", typeof(ushort));
}
/// <summary>Used by ISerialize to serialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("bits", this.bits);
}
#endregion ISerializable
#region Binary dump
/// <summary>Updates the Half by reading from a Stream.</summary>
/// <param name="bin">A BinaryReader instance associated with an open Stream.</param>
public void FromBinaryStream(BinaryReader bin)
{
this.bits = bin.ReadUInt16();
}
/// <summary>Writes the Half into a Stream.</summary>
/// <param name="bin">A BinaryWriter instance associated with an open Stream.</param>
public void ToBinaryStream(BinaryWriter bin)
{
bin.Write(this.bits);
}
#endregion Binary dump
#region IEquatable<Half> Members
const int maxUlps = 1;
/// <summary>
/// Returns a value indicating whether this instance is equal to a specified OpenTK.Half value.
/// </summary>
/// <param name="other">OpenTK.Half object to compare to this instance..</param>
/// <returns>True, if other is equal to this instance; false otherwise.</returns>
public bool Equals(Half other)
{
short aInt, bInt;
unchecked { aInt = (short)other.bits; }
unchecked { bInt = (short)this.bits; }
// Make aInt lexicographically ordered as a twos-complement int
if (aInt < 0)
aInt = (short)(0x8000 - aInt);
// Make bInt lexicographically ordered as a twos-complement int
if (bInt < 0)
bInt = (short)(0x8000 - bInt);
short intDiff = System.Math.Abs((short)(aInt - bInt));
if (intDiff <= maxUlps)
return true;
return false;
}
#endregion
#region IComparable<Half> Members
/// <summary>
/// Compares this instance to a specified half-precision floating-point number
/// and returns an integer that indicates whether the value of this instance
/// is less than, equal to, or greater than the value of the specified half-precision
/// floating-point number.
/// </summary>
/// <param name="other">A half-precision floating-point number to compare.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and value. If the number is:
/// <para>Less than zero, then this instance is less than other, or this instance is not a number
/// (OpenTK.Half.NaN) and other is a number.</para>
/// <para>Zero: this instance is equal to value, or both this instance and other
/// are not a number (OpenTK.Half.NaN), OpenTK.Half.PositiveInfinity, or
/// OpenTK.Half.NegativeInfinity.</para>
/// <para>Greater than zero: this instance is greater than othrs, or this instance is a number
/// and other is not a number (OpenTK.Half.NaN).</para>
/// </returns>
public int CompareTo(Half other)
{
return ((float)this).CompareTo((float)other);
}
#endregion IComparable<Half> Members
#region IFormattable Members
/// <summary>Converts this Half into a human-legible string representation.</summary>
/// <returns>The string representation of this instance.</returns>
public override string ToString()
{
return this.ToSingle().ToString();
}
/// <summary>Converts this Half into a human-legible string representation.</summary>
/// <param name="format">formatting for the output string.</param>
/// <param name="formatProvider">Culture-specific formatting information.</param>
/// <returns>The string representation of this instance.</returns>
public string ToString(string format, IFormatProvider formatProvider)
{
return this.ToSingle().ToString(format, formatProvider);
}
#endregion IFormattable Members
#region String -> Half
/// <summary>Converts the string representation of a number to a Half precision floating point equivalent.</summary>
/// <param name="s">string representation of the number to convert.</param>
/// <returns>A new Half instance.</returns>
public static Half Parse(string s)
{
return (Half)Single.Parse(s);
}
/// <summary>Converts the string representation of a number to a Half precision floating point equivalent.</summary>
/// <param name="s">string representation of the number to convert.</param>
/// <param name="style">specifies the format of s.</param>
/// <param name="provider">Culture-specific formatting information.</param>
/// <returns>A new Half instance.</returns>
public static Half Parse(string s, System.Globalization.NumberStyles style, IFormatProvider provider)
{
return (Half)Single.Parse(s, style, provider);
}
/// <summary>Converts the string representation of a number to a Half precision floating point equivalent. Returns success.</summary>
/// <param name="s">string representation of the number to convert.</param>
/// <param name="result">The Half instance to write to.</param>
/// <returns>Success.</returns>
public static bool TryParse(string s, out Half result)
{
float f;
bool b = Single.TryParse(s, out f);
result = (Half)f;
return b;
}
/// <summary>Converts the string representation of a number to a Half precision floating point equivalent. Returns success.</summary>
/// <param name="s">string representation of the number to convert.</param>
/// <param name="style">specifies the format of s.</param>
/// <param name="provider">Culture-specific formatting information.</param>
/// <param name="result">The Half instance to write to.</param>
/// <returns>Success.</returns>
public static bool TryParse(string s, System.Globalization.NumberStyles style, IFormatProvider provider, out Half result)
{
float f;
bool b = Single.TryParse(s, style, provider, out f);
result = (Half)f;
return b;
}
#endregion String -> Half
#region BitConverter
/// <summary>Returns the Half as an array of bytes.</summary>
/// <param name="h">The Half to convert.</param>
/// <returns>The input as byte array.</returns>
public static byte[] GetBytes(Half h)
{
return BitConverter.GetBytes(h.bits);
}
/// <summary>Converts an array of bytes into Half.</summary>
/// <param name="value">A Half in it's byte[] representation.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A new Half instance.</returns>
public static Half FromBytes(byte[] value, int startIndex)
{
Half h;
h.bits = BitConverter.ToUInt16(value, startIndex);
return h;
}
#endregion BitConverter
}
}

View file

@ -0,0 +1,828 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.Runtime.InteropServices;
namespace OpenTK.Math
{
// Todo: Remove this warning when the code goes public.
#pragma warning disable 3019
#if false
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Matrix3d : IEquatable<Matrix3d>
{
#region Fields & Access
/// <summary>Row 0, Column 0</summary>
public double R0C0;
/// <summary>Row 0, Column 1</summary>
public double R0C1;
/// <summary>Row 0, Column 2</summary>
public double R0C2;
/// <summary>Row 1, Column 0</summary>
public double R1C0;
/// <summary>Row 1, Column 1</summary>
public double R1C1;
/// <summary>Row 1, Column 2</summary>
public double R1C2;
/// <summary>Row 2, Column 0</summary>
public double R2C0;
/// <summary>Row 2, Column 1</summary>
public double R2C1;
/// <summary>Row 2, Column 2</summary>
public double R2C2;
/// <summary>Gets the component at the given row and column in the matrix.</summary>
/// <param name="row">The row of the matrix.</param>
/// <param name="column">The column of the matrix.</param>
/// <returns>The component at the given row and column in the matrix.</returns>
public double this[int row, int column]
{
get
{
switch( row )
{
case 0:
switch (column)
{
case 0: return R0C0;
case 1: return R0C1;
case 2: return R0C2;
}
break;
case 1:
switch (column)
{
case 0: return R1C0;
case 1: return R1C1;
case 2: return R1C2;
}
break;
case 2:
switch (column)
{
case 0: return R2C0;
case 1: return R2C1;
case 2: return R2C2;
}
break;
}
throw new IndexOutOfRangeException();
}
set
{
switch( row )
{
case 0:
switch (column)
{
case 0: R0C0 = value; return;
case 1: R0C1 = value; return;
case 2: R0C2 = value; return;
}
break;
case 1:
switch (column)
{
case 0: R1C0 = value; return;
case 1: R1C1 = value; return;
case 2: R1C2 = value; return;
}
break;
case 2:
switch (column)
{
case 0: R2C0 = value; return;
case 1: R2C1 = value; return;
case 2: R2C2 = value; return;
}
break;
}
throw new IndexOutOfRangeException();
}
}
/// <summary>Gets the component at the index into the matrix.</summary>
/// <param name="index">The index into the components of the matrix.</param>
/// <returns>The component at the given index into the matrix.</returns>
public double this[int index]
{
get
{
switch (index)
{
case 0: return R0C0;
case 1: return R0C1;
case 2: return R0C2;
case 3: return R1C0;
case 4: return R1C1;
case 5: return R1C2;
case 6: return R2C0;
case 7: return R2C1;
case 8: return R2C2;
default: throw new IndexOutOfRangeException();
}
}
set
{
switch (index)
{
case 0: R0C0 = value; return;
case 1: R0C1 = value; return;
case 2: R0C2 = value; return;
case 3: R1C0 = value; return;
case 4: R1C1 = value; return;
case 5: R1C2 = value; return;
case 6: R2C0 = value; return;
case 7: R2C1 = value; return;
case 8: R2C2 = value; return;
default: throw new IndexOutOfRangeException();
}
}
}
/// <summary>Converts the matrix into an IntPtr.</summary>
/// <param name="matrix">The matrix to convert.</param>
/// <returns>An IntPtr for the matrix.</returns>
public static explicit operator IntPtr(Matrix3d matrix)
{
unsafe
{
return (IntPtr)(&matrix.R0C0);
}
}
/// <summary>Converts the matrix into left double*.</summary>
/// <param name="matrix">The matrix to convert.</param>
/// <returns>A double* for the matrix.</returns>
[CLSCompliant(false)]
unsafe public static explicit operator double*(Matrix3d matrix)
{
return &matrix.R0C0;
}
/// <summary>Converts the matrix into an array of doubles.</summary>
/// <param name="matrix">The matrix to convert.</param>
/// <returns>An array of doubles for the matrix.</returns>
public static explicit operator double[](Matrix3d matrix)
{
return new double[9]
{
matrix.R0C0,
matrix.R0C1,
matrix.R0C2,
matrix.R1C0,
matrix.R1C1,
matrix.R1C2,
matrix.R2C0,
matrix.R2C1,
matrix.R2C2
};
}
#endregion
#region Constructors
/// <summary>Constructs left matrix with the same components as the given matrix.</summary>
/// <param name="vector">The matrix whose components to copy.</param>
public Matrix3d(ref Matrix3d matrix)
{
this.R0C0 = matrix.R0C0;
this.R0C1 = matrix.R0C1;
this.R0C2 = matrix.R0C2;
this.R1C0 = matrix.R1C0;
this.R1C1 = matrix.R1C1;
this.R1C2 = matrix.R1C2;
this.R2C0 = matrix.R2C0;
this.R2C1 = matrix.R2C1;
this.R2C2 = matrix.R2C2;
}
/// <summary>Constructs left matrix with the given values.</summary>
/// <param name="r0c0">The value for row 0 column 0.</param>
/// <param name="r0c1">The value for row 0 column 1.</param>
/// <param name="r0c2">The value for row 0 column 2.</param>
/// <param name="r1c0">The value for row 1 column 0.</param>
/// <param name="r1c1">The value for row 1 column 1.</param>
/// <param name="r1c2">The value for row 1 column 2.</param>
/// <param name="r2c0">The value for row 2 column 0.</param>
/// <param name="r2c1">The value for row 2 column 1.</param>
/// <param name="r2c2">The value for row 2 column 2.</param>
public Matrix3d
(
double r0c0,
double r0c1,
double r0c2,
double r1c0,
double r1c1,
double r1c2,
double r2c0,
double r2c1,
double r2c2
)
{
this.R0C0 = r0c0;
this.R0C1 = r0c1;
this.R0C2 = r0c2;
this.R1C0 = r1c0;
this.R1C1 = r1c1;
this.R1C2 = r1c2;
this.R2C0 = r2c0;
this.R2C1 = r2c1;
this.R2C2 = r2c2;
}
/// <summary>Constructs left matrix from the given array of double-precision floating point numbers.</summary>
/// <param name="doubleArray">The array of doubles for the components of the matrix.</param>
public Matrix3d(double[] doubleArray)
{
if (doubleArray == null || doubleArray.GetLength(0) < 9) throw new MissingFieldException();
this.R0C0 = doubleArray[0];
this.R0C1 = doubleArray[1];
this.R0C2 = doubleArray[2];
this.R1C0 = doubleArray[3];
this.R1C1 = doubleArray[4];
this.R1C2 = doubleArray[5];
this.R2C0 = doubleArray[6];
this.R2C1 = doubleArray[7];
this.R2C2 = doubleArray[8];
}
/// <summary>Constructs left matrix from the given quaternion.</summary>
/// <param name="quaternion">The quaternion to use to construct the martix.</param>
public Matrix3d(Quaterniond quaternion)
{
quaternion.Normalize();
double xx = quaternion.X * quaternion.X;
double yy = quaternion.Y * quaternion.Y;
double zz = quaternion.Z * quaternion.Z;
double xy = quaternion.X * quaternion.Y;
double xz = quaternion.X * quaternion.Z;
double yz = quaternion.Y * quaternion.Z;
double wx = quaternion.W * quaternion.X;
double wy = quaternion.W * quaternion.Y;
double wz = quaternion.W * quaternion.Z;
R0C0 = 1 - 2 * (yy + zz);
R0C1 = 2 * (xy - wz);
R0C2 = 2 * (xz + wy);
R1C0 = 2 * (xy + wz);
R1C1 = 1 - 2 * (xx + zz);
R1C2 = 2 * (yz - wx);
R2C0 = 2 * (xz - wy);
R2C1 = 2 * (yz + wx);
R2C2 = 1 - 2 * (xx + yy);
}
#endregion
#region Equality
/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
/// <param name="matrix">The OpenTK.Matrix3d structure to compare with.</param>
/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
[CLSCompliant(false)]
public bool Equals(Matrix3d matrix)
{
return
R0C0 == matrix.R0C0 &&
R0C1 == matrix.R0C1 &&
R0C2 == matrix.R0C2 &&
R1C0 == matrix.R1C0 &&
R1C1 == matrix.R1C1 &&
R1C2 == matrix.R1C2 &&
R2C0 == matrix.R2C0 &&
R2C1 == matrix.R2C1 &&
R2C2 == matrix.R2C2;
}
/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
/// <param name="matrix">The OpenTK.Matrix3d structure to compare to.</param>
/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
public bool Equals(ref Matrix3d matrix)
{
return
R0C0 == matrix.R0C0 &&
R0C1 == matrix.R0C1 &&
R0C2 == matrix.R0C2 &&
R1C0 == matrix.R1C0 &&
R1C1 == matrix.R1C1 &&
R1C2 == matrix.R1C2 &&
R2C0 == matrix.R2C0 &&
R2C1 == matrix.R2C1 &&
R2C2 == matrix.R2C2;
}
/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
/// <param name="left">The left-hand operand.</param>
/// <param name="right">The right-hand operand.</param>
/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
public static bool Equals(ref Matrix3d left, ref Matrix3d right)
{
return
left.R0C0 == right.R0C0 &&
left.R0C1 == right.R0C1 &&
left.R0C2 == right.R0C2 &&
left.R1C0 == right.R1C0 &&
left.R1C1 == right.R1C1 &&
left.R1C2 == right.R1C2 &&
left.R2C0 == right.R2C0 &&
left.R2C1 == right.R2C1 &&
left.R2C2 == right.R2C2;
}
/// <summary>Indicates whether the current matrix is approximately equal to another matrix.</summary>
/// <param name="matrix">The OpenTK.Matrix3d structure to compare with.</param>
/// <param name="tolerance">The limit below which the matrices are considered equal.</param>
/// <returns>true if the current matrix is approximately equal to the matrix parameter; otherwise, false.</returns>
public bool EqualsApprox(ref Matrix3d matrix, double tolerance)
{
return
System.Math.Abs(R0C0 - matrix.R0C0) <= tolerance &&
System.Math.Abs(R0C1 - matrix.R0C1) <= tolerance &&
System.Math.Abs(R0C2 - matrix.R0C2) <= tolerance &&
System.Math.Abs(R1C0 - matrix.R1C0) <= tolerance &&
System.Math.Abs(R1C1 - matrix.R1C1) <= tolerance &&
System.Math.Abs(R1C2 - matrix.R1C2) <= tolerance &&
System.Math.Abs(R2C0 - matrix.R2C0) <= tolerance &&
System.Math.Abs(R2C1 - matrix.R2C1) <= tolerance &&
System.Math.Abs(R2C2 - matrix.R2C2) <= tolerance;
}
/// <summary>Indicates whether the current matrix is approximately equal to another matrix.</summary>
/// <param name="left">The left-hand operand.</param>
/// <param name="right">The right-hand operand.</param>
/// <param name="tolerance">The limit below which the matrices are considered equal.</param>
/// <returns>true if the current matrix is approximately equal to the matrix parameter; otherwise, false.</returns>
public static bool EqualsApprox(ref Matrix3d left, ref Matrix3d right, double tolerance)
{
return
System.Math.Abs(left.R0C0 - right.R0C0) <= tolerance &&
System.Math.Abs(left.R0C1 - right.R0C1) <= tolerance &&
System.Math.Abs(left.R0C2 - right.R0C2) <= tolerance &&
System.Math.Abs(left.R1C0 - right.R1C0) <= tolerance &&
System.Math.Abs(left.R1C1 - right.R1C1) <= tolerance &&
System.Math.Abs(left.R1C2 - right.R1C2) <= tolerance &&
System.Math.Abs(left.R2C0 - right.R2C0) <= tolerance &&
System.Math.Abs(left.R2C1 - right.R2C1) <= tolerance &&
System.Math.Abs(left.R2C2 - right.R2C2) <= tolerance;
}
#endregion
#region Arithmetic Operators
/// <summary>Add left matrix to this matrix.</summary>
/// <param name="matrix">The matrix to add.</param>
public void Add(ref Matrix3d matrix)
{
R0C0 = R0C0 + matrix.R0C0;
R0C1 = R0C1 + matrix.R0C1;
R0C2 = R0C2 + matrix.R0C2;
R1C0 = R1C0 + matrix.R1C0;
R1C1 = R1C1 + matrix.R1C1;
R1C2 = R1C2 + matrix.R1C2;
R2C0 = R2C0 + matrix.R2C0;
R2C1 = R2C1 + matrix.R2C1;
R2C2 = R2C2 + matrix.R2C2;
}
/// <summary>Add left matrix to this matrix.</summary>
/// <param name="matrix">The matrix to add.</param>
/// <param name="result">The resulting matrix of the addition.</param>
public void Add(ref Matrix3d matrix, out Matrix3d result)
{
result.R0C0 = R0C0 + matrix.R0C0;
result.R0C1 = R0C1 + matrix.R0C1;
result.R0C2 = R0C2 + matrix.R0C2;
result.R1C0 = R1C0 + matrix.R1C0;
result.R1C1 = R1C1 + matrix.R1C1;
result.R1C2 = R1C2 + matrix.R1C2;
result.R2C0 = R2C0 + matrix.R2C0;
result.R2C1 = R2C1 + matrix.R2C1;
result.R2C2 = R2C2 + matrix.R2C2;
}
/// <summary>Add left matrix to left matrix.</summary>
/// <param name="matrix">The matrix on the matrix side of the equation.</param>
/// <param name="right">The matrix on the right side of the equation</param>
/// <param name="result">The resulting matrix of the addition.</param>
public static void Add(ref Matrix3d left, ref Matrix3d right, out Matrix3d result)
{
result.R0C0 = left.R0C0 + right.R0C0;
result.R0C1 = left.R0C1 + right.R0C1;
result.R0C2 = left.R0C2 + right.R0C2;
result.R1C0 = left.R1C0 + right.R1C0;
result.R1C1 = left.R1C1 + right.R1C1;
result.R1C2 = left.R1C2 + right.R1C2;
result.R2C0 = left.R2C0 + right.R2C0;
result.R2C1 = left.R2C1 + right.R2C1;
result.R2C2 = left.R2C2 + right.R2C2;
}
/// <summary>Subtract left matrix from this matrix.</summary>
/// <param name="matrix">The matrix to subtract.</param>
public void Subtract(ref Matrix3d matrix)
{
R0C0 = R0C0 + matrix.R0C0;
R0C1 = R0C1 + matrix.R0C1;
R0C2 = R0C2 + matrix.R0C2;
R1C0 = R1C0 + matrix.R1C0;
R1C1 = R1C1 + matrix.R1C1;
R1C2 = R1C2 + matrix.R1C2;
R2C0 = R2C0 + matrix.R2C0;
R2C1 = R2C1 + matrix.R2C1;
R2C2 = R2C2 + matrix.R2C2;
}
/// <summary>Subtract left matrix from this matrix.</summary>
/// <param name="matrix">The matrix to subtract.</param>
/// <param name="result">The resulting matrix of the subtraction.</param>
public void Subtract(ref Matrix3d matrix, out Matrix3d result)
{
result.R0C0 = R0C0 + matrix.R0C0;
result.R0C1 = R0C1 + matrix.R0C1;
result.R0C2 = R0C2 + matrix.R0C2;
result.R1C0 = R1C0 + matrix.R1C0;
result.R1C1 = R1C1 + matrix.R1C1;
result.R1C2 = R1C2 + matrix.R1C2;
result.R2C0 = R2C0 + matrix.R2C0;
result.R2C1 = R2C1 + matrix.R2C1;
result.R2C2 = R2C2 + matrix.R2C2;
}
/// <summary>Subtract left matrix from left matrix.</summary>
/// <param name="matrix">The matrix on the matrix side of the equation.</param>
/// <param name="right">The matrix on the right side of the equation</param>
/// <param name="result">The resulting matrix of the subtraction.</param>
public static void Subtract(ref Matrix3d left, ref Matrix3d right, out Matrix3d result)
{
result.R0C0 = left.R0C0 + right.R0C0;
result.R0C1 = left.R0C1 + right.R0C1;
result.R0C2 = left.R0C2 + right.R0C2;
result.R1C0 = left.R1C0 + right.R1C0;
result.R1C1 = left.R1C1 + right.R1C1;
result.R1C2 = left.R1C2 + right.R1C2;
result.R2C0 = left.R2C0 + right.R2C0;
result.R2C1 = left.R2C1 + right.R2C1;
result.R2C2 = left.R2C2 + right.R2C2;
}
/// <summary>Multiply left martix times this matrix.</summary>
/// <param name="matrix">The matrix to multiply.</param>
public void Multiply(ref Matrix3d matrix)
{
double r0c0 = matrix.R0C0 * R0C0 + matrix.R0C1 * R1C0 + matrix.R0C2 * R2C0;
double r0c1 = matrix.R0C0 * R0C1 + matrix.R0C1 * R1C1 + matrix.R0C2 * R2C1;
double r0c2 = matrix.R0C0 * R0C2 + matrix.R0C1 * R1C2 + matrix.R0C2 * R2C2;
double r1c0 = matrix.R1C0 * R0C0 + matrix.R1C1 * R1C0 + matrix.R1C2 * R2C0;
double r1c1 = matrix.R1C0 * R0C1 + matrix.R1C1 * R1C1 + matrix.R1C2 * R2C1;
double r1c2 = matrix.R1C0 * R0C2 + matrix.R1C1 * R1C2 + matrix.R1C2 * R2C2;
R2C0 = matrix.R2C0 * R0C0 + matrix.R2C1 * R1C0 + matrix.R2C2 * R2C0;
R2C1 = matrix.R2C0 * R0C1 + matrix.R2C1 * R1C1 + matrix.R2C2 * R2C1;
R2C2 = matrix.R2C0 * R0C2 + matrix.R2C1 * R1C2 + matrix.R2C2 * R2C2;
R0C0 = r0c0;
R0C1 = r0c1;
R0C2 = r0c2;
R1C0 = r1c0;
R1C1 = r1c1;
R1C2 = r1c2;
}
/// <summary>Multiply matrix times this matrix.</summary>
/// <param name="matrix">The matrix to multiply.</param>
/// <param name="result">The resulting matrix of the multiplication.</param>
public void Multiply(ref Matrix3d matrix, out Matrix3d result)
{
result.R0C0 = matrix.R0C0 * R0C0 + matrix.R0C1 * R1C0 + matrix.R0C2 * R2C0;
result.R0C1 = matrix.R0C0 * R0C1 + matrix.R0C1 * R1C1 + matrix.R0C2 * R2C1;
result.R0C2 = matrix.R0C0 * R0C2 + matrix.R0C1 * R1C2 + matrix.R0C2 * R2C2;
result.R1C0 = matrix.R1C0 * R0C0 + matrix.R1C1 * R1C0 + matrix.R1C2 * R2C0;
result.R1C1 = matrix.R1C0 * R0C1 + matrix.R1C1 * R1C1 + matrix.R1C2 * R2C1;
result.R1C2 = matrix.R1C0 * R0C2 + matrix.R1C1 * R1C2 + matrix.R1C2 * R2C2;
result.R2C0 = matrix.R2C0 * R0C0 + matrix.R2C1 * R1C0 + matrix.R2C2 * R2C0;
result.R2C1 = matrix.R2C0 * R0C1 + matrix.R2C1 * R1C1 + matrix.R2C2 * R2C1;
result.R2C2 = matrix.R2C0 * R0C2 + matrix.R2C1 * R1C2 + matrix.R2C2 * R2C2;
}
/// <summary>Multiply left matrix times left matrix.</summary>
/// <param name="matrix">The matrix on the matrix side of the equation.</param>
/// <param name="right">The matrix on the right side of the equation</param>
/// <param name="result">The resulting matrix of the multiplication.</param>
public static void Multiply(ref Matrix3d left, ref Matrix3d right, out Matrix3d result)
{
result.R0C0 = right.R0C0 * left.R0C0 + right.R0C1 * left.R1C0 + right.R0C2 * left.R2C0;
result.R0C1 = right.R0C0 * left.R0C1 + right.R0C1 * left.R1C1 + right.R0C2 * left.R2C1;
result.R0C2 = right.R0C0 * left.R0C2 + right.R0C1 * left.R1C2 + right.R0C2 * left.R2C2;
result.R1C0 = right.R1C0 * left.R0C0 + right.R1C1 * left.R1C0 + right.R1C2 * left.R2C0;
result.R1C1 = right.R1C0 * left.R0C1 + right.R1C1 * left.R1C1 + right.R1C2 * left.R2C1;
result.R1C2 = right.R1C0 * left.R0C2 + right.R1C1 * left.R1C2 + right.R1C2 * left.R2C2;
result.R2C0 = right.R2C0 * left.R0C0 + right.R2C1 * left.R1C0 + right.R2C2 * left.R2C0;
result.R2C1 = right.R2C0 * left.R0C1 + right.R2C1 * left.R1C1 + right.R2C2 * left.R2C1;
result.R2C2 = right.R2C0 * left.R0C2 + right.R2C1 * left.R1C2 + right.R2C2 * left.R2C2;
}
/// <summary>Multiply matrix times this matrix.</summary>
/// <param name="matrix">The matrix to multiply.</param>
public void Multiply(double scalar)
{
R0C0 = scalar * R0C0;
R0C1 = scalar * R0C1;
R0C2 = scalar * R0C2;
R1C0 = scalar * R1C0;
R1C1 = scalar * R1C1;
R1C2 = scalar * R1C2;
R2C0 = scalar * R2C0;
R2C1 = scalar * R2C1;
R2C2 = scalar * R2C2;
}
/// <summary>Multiply matrix times this matrix.</summary>
/// <param name="matrix">The matrix to multiply.</param>
/// <param name="result">The resulting matrix of the multiplication.</param>
public void Multiply(double scalar, out Matrix3d result)
{
result.R0C0 = scalar * R0C0;
result.R0C1 = scalar * R0C1;
result.R0C2 = scalar * R0C2;
result.R1C0 = scalar * R1C0;
result.R1C1 = scalar * R1C1;
result.R1C2 = scalar * R1C2;
result.R2C0 = scalar * R2C0;
result.R2C1 = scalar * R2C1;
result.R2C2 = scalar * R2C2;
}
/// <summary>Multiply left matrix times left matrix.</summary>
/// <param name="matrix">The matrix on the matrix side of the equation.</param>
/// <param name="right">The matrix on the right side of the equation</param>
/// <param name="result">The resulting matrix of the multiplication.</param>
public static void Multiply(ref Matrix3d matrix, double scalar, out Matrix3d result)
{
result.R0C0 = scalar * matrix.R0C0;
result.R0C1 = scalar * matrix.R0C1;
result.R0C2 = scalar * matrix.R0C2;
result.R1C0 = scalar * matrix.R1C0;
result.R1C1 = scalar * matrix.R1C1;
result.R1C2 = scalar * matrix.R1C2;
result.R2C0 = scalar * matrix.R2C0;
result.R2C1 = scalar * matrix.R2C1;
result.R2C2 = scalar * matrix.R2C2;
}
#endregion
#region Functions
public double Determinant
{
get
{
return R0C0 * R1C1 * R2C2 - R0C0 * R1C2 * R2C1 - R0C1 * R1C0 * R2C2 + R0C2 * R1C0 * R2C1 + R0C1 * R1C2 * R2C0 - R0C2 * R1C1 * R2C0;
}
}
public void Transpose()
{
Functions.Swap(ref R0C1, ref R1C0);
Functions.Swap(ref R0C2, ref R2C0);
Functions.Swap(ref R1C2, ref R2C1);
}
public void Transpose(out Matrix3d result)
{
result.R0C0 = R0C0;
result.R0C1 = R1C0;
result.R0C2 = R2C0;
result.R1C0 = R0C1;
result.R1C1 = R1C1;
result.R1C2 = R2C1;
result.R2C0 = R0C2;
result.R2C1 = R1C2;
result.R2C2 = R2C2;
}
public static void Transpose(ref Matrix3d matrix, out Matrix3d result)
{
result.R0C0 = matrix.R0C0;
result.R0C1 = matrix.R1C0;
result.R0C2 = matrix.R2C0;
result.R1C0 = matrix.R0C1;
result.R1C1 = matrix.R1C1;
result.R1C2 = matrix.R2C1;
result.R2C0 = matrix.R0C2;
result.R2C1 = matrix.R1C2;
result.R2C2 = matrix.R2C2;
}
#endregion
#region Transformation Functions
public void Transform(ref Vector3d vector)
{
double x = R0C0 * vector.X + R0C1 * vector.Y + R0C2 * vector.Z;
double y = R1C0 * vector.X + R1C1 * vector.Y + R1C2 * vector.Z;
vector.Z = R2C0 * vector.X + R2C1 * vector.Y + R2C2 * vector.Z;
vector.X = x;
vector.Y = y;
}
public static void Transform(ref Matrix3d matrix, ref Vector3d vector)
{
double x = matrix.R0C0 * vector.X + matrix.R0C1 * vector.Y + matrix.R0C2 * vector.Z;
double y = matrix.R1C0 * vector.X + matrix.R1C1 * vector.Y + matrix.R1C2 * vector.Z;
vector.Z = matrix.R2C0 * vector.X + matrix.R2C1 * vector.Y + matrix.R2C2 * vector.Z;
vector.X = x;
vector.Y = y;
}
public void Transform(ref Vector3d vector, out Vector3d result)
{
result.X = R0C0 * vector.X + R0C1 * vector.Y + R0C2 * vector.Z;
result.Y = R1C0 * vector.X + R1C1 * vector.Y + R1C2 * vector.Z;
result.Z = R2C0 * vector.X + R2C1 * vector.Y + R2C2 * vector.Z;
}
public static void Transform(ref Matrix3d matrix, ref Vector3d vector, out Vector3d result)
{
result.X = matrix.R0C0 * vector.X + matrix.R0C1 * vector.Y + matrix.R0C2 * vector.Z;
result.Y = matrix.R1C0 * vector.X + matrix.R1C1 * vector.Y + matrix.R1C2 * vector.Z;
result.Z = matrix.R2C0 * vector.X + matrix.R2C1 * vector.Y + matrix.R2C2 * vector.Z;
}
public void Rotate(double angle)
{
double angleRadians = Functions.DTOR * angle;
double sin = (double)System.Math.Sin(angleRadians);
double cos = (double)System.Math.Cos(angleRadians);
double r0c0 = cos * R0C0 + sin * R1C0;
double r0c1 = cos * R0C1 + sin * R1C1;
double r0c2 = cos * R0C2 + sin * R1C2;
R1C0 = cos * R1C0 - sin * R0C0;
R1C1 = cos * R1C1 - sin * R0C1;
R1C2 = cos * R1C2 - sin * R0C2;
R0C0 = r0c0;
R0C1 = r0c1;
R0C2 = r0c2;
}
public void Rotate(double angle, out Matrix3d result)
{
double angleRadians = Functions.DTOR * angle;
double sin = (double)System.Math.Sin(angleRadians);
double cos = (double)System.Math.Cos(angleRadians);
result.R0C0 = cos * R0C0 + sin * R1C0;
result.R0C1 = cos * R0C1 + sin * R1C1;
result.R0C2 = cos * R0C2 + sin * R1C2;
result.R1C0 = cos * R1C0 - sin * R0C0;
result.R1C1 = cos * R1C1 - sin * R0C1;
result.R1C2 = cos * R1C2 - sin * R0C2;
result.R2C0 = R2C0;
result.R2C1 = R2C1;
result.R2C2 = R2C2;
}
public static void Rotate(ref Matrix3d matrix, double angle, out Matrix3d result)
{
double angleRadians = Functions.DTOR * angle;
double sin = (double)System.Math.Sin(angleRadians);
double cos = (double)System.Math.Cos(angleRadians);
result.R0C0 = cos * matrix.R0C0 + sin * matrix.R1C0;
result.R0C1 = cos * matrix.R0C1 + sin * matrix.R1C1;
result.R0C2 = cos * matrix.R0C2 + sin * matrix.R1C2;
result.R1C0 = cos * matrix.R1C0 - sin * matrix.R0C0;
result.R1C1 = cos * matrix.R1C1 - sin * matrix.R0C1;
result.R1C2 = cos * matrix.R1C2 - sin * matrix.R0C2;
result.R2C0 = matrix.R2C0;
result.R2C1 = matrix.R2C1;
result.R2C2 = matrix.R2C2;
}
public static void RotateMatrix(double angle, out Matrix3d result)
{
double angleRadians = Functions.DTOR * angle;
double sin = (double)System.Math.Sin(angleRadians);
double cos = (double)System.Math.Cos(angleRadians);
result.R0C0 = cos;
result.R0C1 = sin;
result.R0C2 = 0;
result.R1C0 = -sin;
result.R1C1 = cos;
result.R1C2 = 0;
result.R2C0 = 0;
result.R2C1 = 0;
result.R2C2 = 1;
}
public Quaterniond ToQuaternion()
{
//return new Quaterniond(ref this);
}
#endregion
#region Constants
/// <summary>The identity matrix.</summary>
public static readonly Matrix3d Identity = new Matrix3d
(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
/// <summary>A matrix of all zeros.</summary>
public static readonly Matrix3d Zero = new Matrix3d
(
0, 0, 0,
0, 0, 0,
0, 0, 0
);
#endregion
#region HashCode
/// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode()
{
return
R0C0.GetHashCode() ^ R0C1.GetHashCode() ^ R0C2.GetHashCode() ^
R1C0.GetHashCode() ^ R1C1.GetHashCode() ^ R1C2.GetHashCode() ^
R2C0.GetHashCode() ^ R2C1.GetHashCode() ^ R2C2.GetHashCode();
}
#endregion
#region String
/// <summary>Returns the fully qualified type name of this instance.</summary>
/// <returns>A System.String containing left fully qualified type name.</returns>
public override string ToString()
{
return String.Format(
"|{00}, {01}, {02}|\n" +
"|{03}, {04}, {05}|\n" +
"|{06}, {07}, {18}|\n" +
R0C0, R0C1, R0C2,
R1C0, R1C1, R1C2,
R2C0, R2C1, R2C2);
}
#endregion
}
#endif
#pragma warning restore 3019
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,968 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.Runtime.InteropServices;
namespace OpenTK.Math
{
/// <summary>
/// Represents a 4x4 Matrix with double-precision components.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Matrix4d : IEquatable<Matrix4d>
{
#region Fields
/// <summary>
/// Top row of the matrix
/// </summary>
public Vector4d Row0;
/// <summary>
/// 2nd row of the matrix
/// </summary>
public Vector4d Row1;
/// <summary>
/// 3rd row of the matrix
/// </summary>
public Vector4d Row2;
/// <summary>
/// Bottom row of the matrix
/// </summary>
public Vector4d Row3;
/// <summary>
/// The identity matrix
/// </summary>
public static Matrix4d Identity = new Matrix4d(Vector4d .UnitX, Vector4d .UnitY, Vector4d .UnitZ, Vector4d .UnitW);
#endregion
#region Constructors
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="row0">Top row of the matrix</param>
/// <param name="row1">Second row of the matrix</param>
/// <param name="row2">Third row of the matrix</param>
/// <param name="row3">Bottom row of the matrix</param>
public Matrix4d(Vector4d row0, Vector4d row1, Vector4d row2, Vector4d row3)
{
Row0 = row0;
Row1 = row1;
Row2 = row2;
Row3 = row3;
}
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="m00">First item of the first row.</param>
/// <param name="m01">Second item of the first row.</param>
/// <param name="m02">Third item of the first row.</param>
/// <param name="m03">Fourth item of the first row.</param>
/// <param name="m10">First item of the second row.</param>
/// <param name="m11">Second item of the second row.</param>
/// <param name="m12">Third item of the second row.</param>
/// <param name="m13">Fourth item of the second row.</param>
/// <param name="m20">First item of the third row.</param>
/// <param name="m21">Second item of the third row.</param>
/// <param name="m22">Third item of the third row.</param>
/// <param name="m23">First item of the third row.</param>
/// <param name="m30">Fourth item of the fourth row.</param>
/// <param name="m31">Second item of the fourth row.</param>
/// <param name="m32">Third item of the fourth row.</param>
/// <param name="m33">Fourth item of the fourth row.</param>
public Matrix4d(
float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
Row0 = new Vector4d(m00, m01, m02, m03);
Row1 = new Vector4d(m10, m11, m12, m13);
Row2 = new Vector4d(m20, m21, m22, m23);
Row3 = new Vector4d(m30, m31, m32, m33);
}
#endregion
#region Public Members
#region Properties
/// <summary>
/// The determinant of this matrix
/// </summary>
public double Determinant
{
get
{
return
Row0.X * Row1.Y * Row2.Z * Row3.W - Row0.X * Row1.Y * Row2.W * Row3.Z + Row0.X * Row1.Z * Row2.W * Row3.Y - Row0.X * Row1.Z * Row2.Y * Row3.W
+ Row0.X * Row1.W * Row2.Y * Row3.Z - Row0.X * Row1.W * Row2.Z * Row3.Y - Row0.Y * Row1.Z * Row2.W * Row3.X + Row0.Y * Row1.Z * Row2.X * Row3.W
- Row0.Y * Row1.W * Row2.X * Row3.Z + Row0.Y * Row1.W * Row2.Z * Row3.X - Row0.Y * Row1.X * Row2.Z * Row3.W + Row0.Y * Row1.X * Row2.W * Row3.Z
+ Row0.Z * Row1.W * Row2.X * Row3.Y - Row0.Z * Row1.W * Row2.Y * Row3.X + Row0.Z * Row1.X * Row2.Y * Row3.W - Row0.Z * Row1.X * Row2.W * Row3.Y
+ Row0.Z * Row1.Y * Row2.W * Row3.X - Row0.Z * Row1.Y * Row2.X * Row3.W - Row0.W * Row1.X * Row2.Y * Row3.Z + Row0.W * Row1.X * Row2.Z * Row3.Y
- Row0.W * Row1.Y * Row2.Z * Row3.X + Row0.W * Row1.Y * Row2.X * Row3.Z - Row0.W * Row1.Z * Row2.X * Row3.Y + Row0.W * Row1.Z * Row2.Y * Row3.X;
}
}
/// <summary>
/// The first column of this matrix
/// </summary>
public Vector4d Column0
{
get { return new Vector4d (Row0.X, Row1.X, Row2.X, Row3.X); }
}
/// <summary>
/// The second column of this matrix
/// </summary>
public Vector4d Column1
{
get { return new Vector4d (Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
}
/// <summary>
/// The third column of this matrix
/// </summary>
public Vector4d Column2
{
get { return new Vector4d (Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
}
/// <summary>
/// The fourth column of this matrix
/// </summary>
public Vector4d Column3
{
get { return new Vector4d (Row0.W, Row1.W, Row2.W, Row3.W); }
}
public double this[int i, int j]
{
get
{
if (i < 0 || i > 3)
throw new ArgumentOutOfRangeException("i");
if (j < 0 || j > 3)
throw new ArgumentOutOfRangeException("j");
unsafe
{
fixed (Matrix4d* ptr = &this)
return *((double*)ptr + i + j * 4);
}
}
set
{
if (i < 0 || i > 3)
throw new ArgumentOutOfRangeException("i");
if (j < 0 || j > 3)
throw new ArgumentOutOfRangeException("j");
unsafe
{
fixed (Matrix4d* ptr = &this)
*((double*)ptr + i + j * 4) = value;
}
}
}
/// <summary>
/// Gets or sets the value at row 1, column 1 of this instance.
/// </summary>
public double M11 { get { return Row0.X; } set { Row0.X = value; } }
/// <summary>
/// Gets or sets the value at row 1, column 2 of this instance.
/// </summary>
public double M12 { get { return Row0.Y; } set { Row0.Y = value; } }
/// <summary>
/// Gets or sets the value at row 1, column 3 of this instance.
/// </summary>
public double M13 { get { return Row0.Z; } set { Row0.Z = value; } }
/// <summary>
/// Gets or sets the value at row 1, column 4 of this instance.
/// </summary>
public double M14 { get { return Row0.W; } set { Row0.W = value; } }
/// <summary>
/// Gets or sets the value at row 2, column 1 of this instance.
/// </summary>
public double M21 { get { return Row1.X; } set { Row1.X = value; } }
/// <summary>
/// Gets or sets the value at row 2, column 2 of this instance.
/// </summary>
public double M22 { get { return Row1.Y; } set { Row1.Y = value; } }
/// <summary>
/// Gets or sets the value at row 2, column 3 of this instance.
/// </summary>
public double M23 { get { return Row1.Z; } set { Row1.Z = value; } }
/// <summary>
/// Gets or sets the value at row 2, column 4 of this instance.
/// </summary>
public double M24 { get { return Row1.W; } set { Row1.W = value; } }
/// <summary>
/// Gets or sets the value at row 3, column 1 of this instance.
/// </summary>
public double M31 { get { return Row2.X; } set { Row2.X = value; } }
/// <summary>
/// Gets or sets the value at row 3, column 2 of this instance.
/// </summary>
public double M32 { get { return Row2.Y; } set { Row2.Y = value; } }
/// <summary>
/// Gets or sets the value at row 3, column 3 of this instance.
/// </summary>
public double M33 { get { return Row2.Z; } set { Row2.Z = value; } }
/// <summary>
/// Gets or sets the value at row 3, column 4 of this instance.
/// </summary>
public double M34 { get { return Row2.W; } set { Row2.W = value; } }
/// <summary>
/// Gets or sets the value at row 4, column 1 of this instance.
/// </summary>
public double M41 { get { return Row3.X; } set { Row3.X = value; } }
/// <summary>
/// Gets or sets the value at row 4, column 3 of this instance.
/// </summary>
public double M42 { get { return Row3.Y; } set { Row3.Y = value; } }
/// <summary>
/// Gets or sets the value at row 4, column 3 of this instance.
/// </summary>
public double M43 { get { return Row3.Z; } set { Row3.Z = value; } }
/// <summary>
/// Gets or sets the value at row 4, column 4 of this instance.
/// </summary>
public double M44 { get { return Row3.W; } set { Row3.W = value; } }
#endregion
#region Instance
#region public void Invert()
public void Invert()
{
this = Matrix4d.Invert(this);
}
#endregion
#region public void Transpose()
public void Transpose()
{
this = Matrix4d.Transpose(this);
}
#endregion
#endregion
#region Static
#region CreateTranslation
/// <summary>
/// Creates a translation matrix.
/// </summary>
/// <param name="x">X translation.</param>
/// <param name="y">Y translation.</param>
/// <param name="z">Z translation.</param>
/// <param name="result">The resulting Matrix4d instance.</param>
public static void CreateTranslation(double x, double y, double z, out Matrix4d result)
{
result = Identity;
result.Row3 = new Vector4d(x, y, z, 1);
}
/// <summary>
/// Creates a translation matrix.
/// </summary>
/// <param name="vector">The translation vector.</param>
/// <param name="result">The resulting Matrix4d instance.</param>
public static void CreateTranslation(ref Vector3d vector, out Matrix4d result)
{
result = Identity;
result.Row3 = new Vector4d(vector.X, vector.Y, vector.Z, 1);
}
/// <summary>
/// Creates a translation matrix.
/// </summary>
/// <param name="x">X translation.</param>
/// <param name="y">Y translation.</param>
/// <param name="z">Z translation.</param>
/// <returns>The resulting Matrix4d instance.</returns>
public static Matrix4d CreateTranslation(double x, double y, double z)
{
Matrix4d result;
CreateTranslation(x, y, z, out result);
return result;
}
/// <summary>
/// Creates a translation matrix.
/// </summary>
/// <param name="vector">The translation vector.</param>
/// <returns>The resulting Matrix4d instance.</returns>
public static Matrix4d CreateTranslation(Vector3d vector)
{
Matrix4d result;
CreateTranslation(vector.X, vector.Y, vector.Z, out result);
return result;
}
#endregion
#region CreateOrthographic
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="width">The width of the projection volume.</param>
/// <param name="height">The height of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <param name="result">The resulting Matrix4d instance.</param>
public static void CreateOrthographic(double width, double height, double zNear, double zFar, out Matrix4d result)
{
CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
}
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="width">The width of the projection volume.</param>
/// <param name="height">The height of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <rereturns>The resulting Matrix4d instance.</rereturns>
public static Matrix4d CreateOrthographic(double width, double height, double zNear, double zFar)
{
Matrix4d result;
CreateOrthographicOffCenter(-width / 2, width / 2, -height / 2, height / 2, zNear, zFar, out result);
return result;
}
#endregion
#region CreateOrthographicOffCenter
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="left">The left edge of the projection volume.</param>
/// <param name="right">The right edge of the projection volume.</param>
/// <param name="bottom">The bottom edge of the projection volume.</param>
/// <param name="top">The top edge of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <param name="result">The resulting Matrix4d instance.</param>
public static void CreateOrthographicOffCenter(double left, double right, double bottom, double top, double zNear, double zFar, out Matrix4d result)
{
result = new Matrix4d();
double invRL = 1 / (right - left);
double invTB = 1 / (top - bottom);
double invFN = 1 / (zFar - zNear);
result.M11 = 2 * invRL;
result.M22 = 2 * invTB;
result.M33 = -2 * invFN;
result.M41 = -(right + left) * invRL;
result.M42 = -(top + bottom) * invTB;
result.M43 = -(zFar + zNear) * invFN;
}
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="left">The left edge of the projection volume.</param>
/// <param name="right">The right edge of the projection volume.</param>
/// <param name="bottom">The bottom edge of the projection volume.</param>
/// <param name="top">The top edge of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <returns>The resulting Matrix4d instance.</returns>
public static Matrix4d CreateOrthographicOffCenter(double left, double right, double bottom, double top, double zNear, double zFar)
{
Matrix4d result;
CreateOrthographicOffCenter(left, right, bottom, top, zNear, zFar, out result);
return result;
}
#endregion
#region Obsolete Functions
#region Translation Functions
/// <summary>
/// Build a translation matrix with the given translation
/// </summary>
/// <param name="trans">The vector to translate along</param>
/// <returns>A Translation matrix</returns>
[Obsolete("Use CreateTranslation instead.")]
public static Matrix4d Translation(Vector3d trans)
{
return Translation(trans.X, trans.Y, trans.Z);
}
/// <summary>
/// Build a translation matrix with the given translation
/// </summary>
/// <param name="x">X translation</param>
/// <param name="y">Y translation</param>
/// <param name="z">Z translation</param>
/// <returns>A Translation matrix</returns>
[Obsolete("Use CreateTranslation instead.")]
public static Matrix4d Translation(double x, double y, double z)
{
Matrix4d result = Identity;
result.Row3 = new Vector4d(x, y, z, 1.0f);
return result;
}
#endregion
#endregion
#region Scale Functions
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <param name="scale">Single scale factor for x,y and z axes</param>
/// <returns>A scaling matrix</returns>
public static Matrix4d Scale(double scale)
{
return Scale(scale, scale, scale);
}
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <param name="scale">Scale factors for x,y and z axes</param>
/// <returns>A scaling matrix</returns>
public static Matrix4d Scale(Vector3d scale)
{
return Scale(scale.X, scale.Y, scale.Z);
}
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <param name="x">Scale factor for x-axis</param>
/// <param name="y">Scale factor for y-axis</param>
/// <param name="z">Scale factor for z-axis</param>
/// <returns>A scaling matrix</returns>
public static Matrix4d Scale(double x, double y, double z)
{
Matrix4d result;
result.Row0 = Vector4d .UnitX * x;
result.Row1 = Vector4d .UnitY * y;
result.Row2 = Vector4d .UnitZ * z;
result.Row3 = Vector4d .UnitW;
return result;
}
#endregion
#region Rotation Functions
/// <summary>
/// Build a rotation matrix that rotates about the x-axis
/// </summary>
/// <param name="angle">angle in radians to rotate counter-clockwise around the x-axis</param>
/// <returns>A rotation matrix</returns>
public static Matrix4d RotateX(double angle)
{
double cos = (double)System.Math.Cos(angle);
double sin = (double)System.Math.Sin(angle);
Matrix4d result;
result.Row0 = Vector4d .UnitX;
result.Row1 = new Vector4d (0.0f, cos, sin, 0.0f);
result.Row2 = new Vector4d (0.0f, -sin, cos, 0.0f);
result.Row3 = Vector4d .UnitW;
return result;
}
/// <summary>
/// Build a rotation matrix that rotates about the y-axis
/// </summary>
/// <param name="angle">angle in radians to rotate counter-clockwise around the y-axis</param>
/// <returns>A rotation matrix</returns>
public static Matrix4d RotateY(double angle)
{
double cos = (double)System.Math.Cos(angle);
double sin = (double)System.Math.Sin(angle);
Matrix4d result;
result.Row0 = new Vector4d (cos, 0.0f, -sin, 0.0f);
result.Row1 = Vector4d .UnitY;
result.Row2 = new Vector4d (sin, 0.0f, cos, 0.0f);
result.Row3 = Vector4d .UnitW;
return result;
}
/// <summary>
/// Build a rotation matrix that rotates about the z-axis
/// </summary>
/// <param name="angle">angle in radians to rotate counter-clockwise around the z-axis</param>
/// <returns>A rotation matrix</returns>
public static Matrix4d RotateZ(double angle)
{
double cos = (double)System.Math.Cos(angle);
double sin = (double)System.Math.Sin(angle);
Matrix4d result;
result.Row0 = new Vector4d (cos, sin, 0.0f, 0.0f);
result.Row1 = new Vector4d (-sin, cos, 0.0f, 0.0f);
result.Row2 = Vector4d .UnitZ;
result.Row3 = Vector4d .UnitW;
return result;
}
/// <summary>
/// Build a rotation matrix to rotate about the given axis
/// </summary>
/// <param name="axis">the axis to rotate about</param>
/// <param name="angle">angle in radians to rotate counter-clockwise (looking in the direction of the given axis)</param>
/// <returns>A rotation matrix</returns>
public static Matrix4d Rotate(Vector3d axis, double angle)
{
double cos = (double)System.Math.Cos(-angle);
double sin = (double)System.Math.Sin(-angle);
double t = 1.0f - cos;
axis.Normalize();
Matrix4d result;
result.Row0 = new Vector4d (t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f);
result.Row1 = new Vector4d (t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f);
result.Row2 = new Vector4d (t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f);
result.Row3 = Vector4d .UnitW;
return result;
}
/// <summary>
/// Build a rotation matrix from a quaternion
/// </summary>
/// <param name="q">the quaternion</param>
/// <returns>A rotation matrix</returns>
public static Matrix4d Rotate(Quaterniond q)
{
Vector3d axis;
double angle;
q.ToAxisAngle(out axis, out angle);
return Rotate(axis, angle);
}
#endregion
#region Camera Helper Functions
/// <summary>
/// Build a world space to camera space matrix
/// </summary>
/// <param name="eye">Eye (camera) position in world space</param>
/// <param name="target">Target position in world space</param>
/// <param name="up">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <returns>A Matrix that transforms world space to camera space</returns>
public static Matrix4d LookAt(Vector3d eye, Vector3d target, Vector3d up)
{
Vector3d z = Vector3d.Normalize(eye - target);
Vector3d x = Vector3d.Normalize(Vector3d.Cross(up, z));
Vector3d y = Vector3d.Normalize(Vector3d.Cross(z, x));
Matrix4d rot = new Matrix4d(new Vector4d (x.X, y.X, z.X, 0.0f),
new Vector4d (x.Y, y.Y, z.Y, 0.0f),
new Vector4d (x.Z, y.Z, z.Z, 0.0f),
Vector4d .UnitW);
Matrix4d trans = Matrix4d.CreateTranslation(-eye);
return trans * rot;
}
/// <summary>
/// Build a world space to camera space matrix
/// </summary>
/// <param name="eyeX">Eye (camera) position in world space</param>
/// <param name="eyeY">Eye (camera) position in world space</param>
/// <param name="eyeZ">Eye (camera) position in world space</param>
/// <param name="targetX">Target position in world space</param>
/// <param name="targetY">Target position in world space</param>
/// <param name="targetZ">Target position in world space</param>
/// <param name="upX">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <param name="upY">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <param name="upZ">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <returns>A Matrix4 that transforms world space to camera space</returns>
public static Matrix4d LookAt(double eyeX, double eyeY, double eyeZ, double targetX, double targetY, double targetZ, double upX, double upY, double upZ)
{
return LookAt(new Vector3d(eyeX, eyeY, eyeZ), new Vector3d(targetX, targetY, targetZ), new Vector3d(upX, upY, upZ));
}
/// <summary>
/// Build a projection matrix
/// </summary>
/// <param name="left">Left edge of the view frustum</param>
/// <param name="right">Right edge of the view frustum</param>
/// <param name="bottom">Bottom edge of the view frustum</param>
/// <param name="top">Top edge of the view frustum</param>
/// <param name="near">Distance to the near clip plane</param>
/// <param name="far">Distance to the far clip plane</param>
/// <returns>A projection matrix that transforms camera space to raster space</returns>
public static Matrix4d Frustum(double left, double right, double bottom, double top, double near, double far)
{
double invRL = 1.0f / (right - left);
double invTB = 1.0f / (top - bottom);
double invFN = 1.0f / (far - near);
return new Matrix4d(new Vector4d (2.0f * near * invRL, 0.0f, 0.0f, 0.0f),
new Vector4d (0.0f, 2.0f * near * invTB, 0.0f, 0.0f),
new Vector4d ((right + left) * invRL, (top + bottom) * invTB, -(far + near) * invFN, -1.0f),
new Vector4d (0.0f, 0.0f, -2.0f * far * near * invFN, 0.0f));
}
/// <summary>
/// Build a projection matrix
/// </summary>
/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
/// <param name="aspect">Aspect ratio of the view (width / height)</param>
/// <param name="near">Distance to the near clip plane</param>
/// <param name="far">Distance to the far clip plane</param>
/// <returns>A projection matrix that transforms camera space to raster space</returns>
public static Matrix4d Perspective(double fovy, double aspect, double near, double far)
{
double yMax = near * (double)System.Math.Tan(0.5f * fovy);
double yMin = -yMax;
double xMin = yMin * aspect;
double xMax = yMax * aspect;
return Frustum(xMin, xMax, yMin, yMax, near, far);
}
#endregion
#region Multiply Functions
/// <summary>
/// Multiplies two instances.
/// </summary>
/// <param name="left">The left operand of the multiplication.</param>
/// <param name="right">The right operand of the multiplication.</param>
/// <returns>A new instance that is the result of the multiplication</returns>
public static Matrix4d Mult(Matrix4d left, Matrix4d right)
{
Matrix4d result;
Mult(ref left, ref right, out result);
return result;
}
/// <summary>
/// Multiplies two instances.
/// </summary>
/// <param name="left">The left operand of the multiplication.</param>
/// <param name="right">The right operand of the multiplication.</param>
/// <param name="result">A new instance that is the result of the multiplication</param>
public static void Mult(ref Matrix4d left, ref Matrix4d right, out Matrix4d result)
{
result = new Matrix4d();
result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41;
result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42;
result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43;
result.M14 = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44;
result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41;
result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42;
result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43;
result.M24 = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44;
result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41;
result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42;
result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43;
result.M34 = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44;
result.M41 = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41;
result.M42 = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42;
result.M43 = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43;
result.M44 = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44;
}
#endregion
#region Invert Functions
/// <summary>
/// Calculate the inverse of the given matrix
/// </summary>
/// <param name="mat">The matrix to invert</param>
/// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
/// <exception cref="InvalidOperationException">Thrown if the Matrix4d is singular.</exception>
public static Matrix4d Invert(Matrix4d mat)
{
int[] colIdx = { 0, 0, 0, 0 };
int[] rowIdx = { 0, 0, 0, 0 };
int[] pivotIdx = { -1, -1, -1, -1 };
// convert the matrix to an array for easy looping
double[,] inverse = {{mat.Row0.X, mat.Row0.Y, mat.Row0.Z, mat.Row0.W},
{mat.Row1.X, mat.Row1.Y, mat.Row1.Z, mat.Row1.W},
{mat.Row2.X, mat.Row2.Y, mat.Row2.Z, mat.Row2.W},
{mat.Row3.X, mat.Row3.Y, mat.Row3.Z, mat.Row3.W} };
int icol = 0;
int irow = 0;
for (int i = 0; i < 4; i++)
{
// Find the largest pivot value
double maxPivot = 0.0f;
for (int j = 0; j < 4; j++)
{
if (pivotIdx[j] != 0)
{
for (int k = 0; k < 4; ++k)
{
if (pivotIdx[k] == -1)
{
double absVal = System.Math.Abs(inverse[j, k]);
if (absVal > maxPivot)
{
maxPivot = absVal;
irow = j;
icol = k;
}
}
else if (pivotIdx[k] > 0)
{
return mat;
}
}
}
}
++(pivotIdx[icol]);
// Swap rows over so pivot is on diagonal
if (irow != icol)
{
for (int k = 0; k < 4; ++k)
{
double f = inverse[irow, k];
inverse[irow, k] = inverse[icol, k];
inverse[icol, k] = f;
}
}
rowIdx[i] = irow;
colIdx[i] = icol;
double pivot = inverse[icol, icol];
// check for singular matrix
if (pivot == 0.0f)
{
throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
//return mat;
}
// Scale row so it has a unit diagonal
double oneOverPivot = 1.0f / pivot;
inverse[icol, icol] = 1.0f;
for (int k = 0; k < 4; ++k)
inverse[icol, k] *= oneOverPivot;
// Do elimination of non-diagonal elements
for (int j = 0; j < 4; ++j)
{
// check this isn't on the diagonal
if (icol != j)
{
double f = inverse[j, icol];
inverse[j, icol] = 0.0f;
for (int k = 0; k < 4; ++k)
inverse[j, k] -= inverse[icol, k] * f;
}
}
}
for (int j = 3; j >= 0; --j)
{
int ir = rowIdx[j];
int ic = colIdx[j];
for (int k = 0; k < 4; ++k)
{
double f = inverse[k, ir];
inverse[k, ir] = inverse[k, ic];
inverse[k, ic] = f;
}
}
mat.Row0 = new Vector4d (inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
mat.Row1 = new Vector4d (inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
mat.Row2 = new Vector4d (inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
mat.Row3 = new Vector4d (inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
return mat;
}
#endregion
#region Transpose
/// <summary>
/// Calculate the transpose of the given matrix
/// </summary>
/// <param name="mat">The matrix to transpose</param>
/// <returns>The transpose of the given matrix</returns>
public static Matrix4d Transpose(Matrix4d mat)
{
return new Matrix4d(mat.Column0, mat.Column1, mat.Column2, mat.Column3);
}
/// <summary>
/// Calculate the transpose of the given matrix
/// </summary>
/// <param name="mat">The matrix to transpose</param>
/// <param name="result">The result of the calculation</param>
public static void Transpose(ref Matrix4d mat, out Matrix4d result)
{
result.Row0 = mat.Column0;
result.Row1 = mat.Column1;
result.Row2 = mat.Column2;
result.Row3 = mat.Column3;
}
#endregion
#endregion
#region Operators
/// <summary>
/// Matrix multiplication
/// </summary>
/// <param name="left">left-hand operand</param>
/// <param name="right">right-hand operand</param>
/// <returns>A new Matrix44 which holds the result of the multiplication</returns>
public static Matrix4d operator *(Matrix4d left, Matrix4d right)
{
return Matrix4d.Mult(left, right);
}
public static bool operator ==(Matrix4d left, Matrix4d right)
{
return left.Equals(right);
}
public static bool operator !=(Matrix4d left, Matrix4d right)
{
return !left.Equals(right);
}
#endregion
#region Overrides
#region public override string ToString()
/// <summary>
/// Returns a System.String that represents the current Matrix44.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
}
#endregion
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Matrix4d))
return false;
return this.Equals((Matrix4d)obj);
}
#endregion
#endregion
#endregion
#region IEquatable<Matrix4d> Members
/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
/// <param name="other">An matrix to compare with this matrix.</param>
/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
public bool Equals(Matrix4d other)
{
return
Row0 == other.Row0 &&
Row1 == other.Row1 &&
Row2 == other.Row2 &&
Row3 == other.Row3;
}
#endregion
}
}

View file

@ -0,0 +1,586 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Xml.Serialization;
namespace OpenTK.Math
{
/// <summary>
/// Represents a Quaternion.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Quaternion : IEquatable<Quaternion>
{
#region Fields
Vector3 xyz;
float w;
#endregion
#region Constructors
/// <summary>
/// Construct a new Quaternion from vector and w components
/// </summary>
/// <param name="v">The vector part</param>
/// <param name="w">The w part</param>
public Quaternion(Vector3 v, float w)
{
this.xyz = v;
this.w = w;
}
/// <summary>
/// Construct a new Quaternion
/// </summary>
/// <param name="x">The x component</param>
/// <param name="y">The y component</param>
/// <param name="z">The z component</param>
/// <param name="w">The w component</param>
public Quaternion(float x, float y, float z, float w)
: this(new Vector3(x, y, z), w)
{ }
#endregion
#region Public Members
#region Properties
/// <summary>
/// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance.
/// </summary>
[Obsolete("Use Xyz property instead.")]
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[XmlIgnore]
public Vector3 XYZ { get { return Xyz; } set { Xyz = value; } }
/// <summary>
/// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance.
/// </summary>
public Vector3 Xyz { get { return xyz; } set { xyz = value; } }
/// <summary>
/// Gets or sets the X component of this instance.
/// </summary>
[XmlIgnore]
public float X { get { return xyz.X; } set { xyz.X = value; } }
/// <summary>
/// Gets or sets the Y component of this instance.
/// </summary>
[XmlIgnore]
public float Y { get { return xyz.Y; } set { xyz.Y = value; } }
/// <summary>
/// Gets or sets the Z component of this instance.
/// </summary>
[XmlIgnore]
public float Z { get { return xyz.Z; } set { xyz.Z = value; } }
/// <summary>
/// Gets or sets the W component of this instance.
/// </summary>
public float W { get { return w; } set { w = value; } }
#endregion
#region Instance
#region ToAxisAngle
/// <summary>
/// Convert the current quaternion to axis angle representation
/// </summary>
/// <param name="axis">The resultant axis</param>
/// <param name="angle">The resultant angle</param>
public void ToAxisAngle(out Vector3 axis, out float angle)
{
Vector4 result = ToAxisAngle();
axis = result.Xyz;
angle = result.W;
}
/// <summary>
/// Convert this instance to an axis-angle representation.
/// </summary>
/// <returns>A Vector4 that is the axis-angle representation of this quaternion.</returns>
public Vector4 ToAxisAngle()
{
Quaternion q = this;
if (q.W > 1.0f)
q.Normalize();
Vector4 result = new Vector4();
result.W = 2.0f * (float)System.Math.Acos(q.W); // angle
float den = (float)System.Math.Sqrt(1.0 - q.W * q.W);
if (den > 0.0001f)
{
result.Xyz = q.Xyz / den;
}
else
{
// This occurs when the angle is zero.
// Not a problem: just set an arbitrary normalized axis.
result.Xyz = Vector3.UnitX;
}
return result;
}
#endregion
#region public float Length
/// <summary>
/// Gets the length (magnitude) of the quaternion.
/// </summary>
/// <seealso cref="LengthSquared"/>
public float Length
{
get
{
return (float)System.Math.Sqrt(W * W + Xyz.LengthSquared);
}
}
#endregion
#region public float LengthSquared
/// <summary>
/// Gets the square of the quaternion length (magnitude).
/// </summary>
public float LengthSquared
{
get
{
return W * W + Xyz.LengthSquared;
}
}
#endregion
#region public void Normalize()
/// <summary>
/// Scales the Quaternion to unit length.
/// </summary>
public void Normalize()
{
float scale = 1.0f / this.Length;
Xyz *= scale;
W *= scale;
}
#endregion
#region public void Conjugate()
/// <summary>
/// Convert this quaternion to its conjugate
/// </summary>
public void Conjugate()
{
Xyz = -Xyz;
}
#endregion
#endregion
#region Static
#region Fields
/// <summary>
/// Defines the identity quaternion.
/// </summary>
public static Quaternion Identity = new Quaternion(0, 0, 0, 1);
#endregion
#region Add
/// <summary>
/// Add two quaternions
/// </summary>
/// <param name="left">The first operand</param>
/// <param name="right">The second operand</param>
/// <returns>The result of the addition</returns>
public static Quaternion Add(Quaternion left, Quaternion right)
{
return new Quaternion(
left.Xyz + right.Xyz,
left.W + right.W);
}
/// <summary>
/// Add two quaternions
/// </summary>
/// <param name="left">The first operand</param>
/// <param name="right">The second operand</param>
/// <param name="result">The result of the addition</param>
public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result)
{
result = new Quaternion(
left.Xyz + right.Xyz,
left.W + right.W);
}
#endregion
#region Sub
/// <summary>
/// Subtracts two instances.
/// </summary>
/// <param name="left">The left instance.</param>
/// <param name="right">The right instance.</param>
/// <returns>The result of the operation.</returns>
public static Quaternion Sub(Quaternion left, Quaternion right)
{
return new Quaternion(
left.Xyz - right.Xyz,
left.W - right.W);
}
/// <summary>
/// Subtracts two instances.
/// </summary>
/// <param name="left">The left instance.</param>
/// <param name="right">The right instance.</param>
/// <returns>The result of the operation.</returns>
public static void Sub(ref Quaternion left, ref Quaternion right, out Quaternion result)
{
result = new Quaternion(
left.Xyz - right.Xyz,
left.W - right.W);
}
#endregion
#region Mult
public static Quaternion Mult(Quaternion left, Quaternion right)
{
return new Quaternion(
right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz),
left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz));
}
public static void Mult(ref Quaternion left, ref Quaternion right, out Quaternion result)
{
result = new Quaternion(
right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz),
left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz));
}
#endregion
#region Conjugate
/// <summary>
/// Get the conjugate of the given quaternion
/// </summary>
/// <param name="q">The quaternion</param>
/// <returns>The conjugate of the given quaternion</returns>
public static Quaternion Conjugate(Quaternion q)
{
return new Quaternion(-q.Xyz, q.W);
}
/// <summary>
/// Get the conjugate of the given quaternion
/// </summary>
/// <param name="q">The quaternion</param>
/// <param name="result">The conjugate of the given quaternion</param>
public static void Conjugate(ref Quaternion q, out Quaternion result)
{
result = new Quaternion(-q.Xyz, q.W);
}
#endregion
#region Invert
/// <summary>
/// Get the inverse of the given quaternion
/// </summary>
/// <param name="q">The quaternion to invert</param>
/// <returns>The inverse of the given quaternion</returns>
public static Quaternion Invert(Quaternion q)
{
Quaternion result;
Invert(ref q, out result);
return result;
}
/// <summary>
/// Get the inverse of the given quaternion
/// </summary>
/// <param name="q">The quaternion to invert</param>
/// <param name="result">The inverse of the given quaternion</param>
public static void Invert(ref Quaternion q, out Quaternion result)
{
float lengthSq = q.LengthSquared;
if (lengthSq != 0.0)
{
float i = 1.0f / lengthSq;
result = new Quaternion(q.Xyz * -i, q.W * i);
}
else
{
result = q;
}
}
#endregion
#region Normalize
/// <summary>
/// Scale the given quaternion to unit length
/// </summary>
/// <param name="q">The quaternion to normalize</param>
/// <returns>The normalized quaternion</returns>
public static Quaternion Normalize(Quaternion q)
{
Quaternion result;
Normalize(ref q, out result);
return result;
}
/// <summary>
/// Scale the given quaternion to unit length
/// </summary>
/// <param name="q">The quaternion to normalize</param>
/// <param name="result">The normalized quaternion</param>
public static void Normalize(ref Quaternion q, out Quaternion result)
{
float scale = 1.0f / q.Length;
result = new Quaternion(q.Xyz * scale, q.W * scale);
}
#endregion
#region FromAxisAngle
/// <summary>
/// Build a quaternion from the given axis and angle
/// </summary>
/// <param name="axis">The axis to rotate about</param>
/// <param name="angle">The rotation angle in radians</param>
/// <returns></returns>
public static Quaternion FromAxisAngle(Vector3 axis, float angle)
{
if (axis.LengthSquared == 0.0f)
return Identity;
Quaternion result = Identity;
angle *= 0.5f;
axis.Normalize();
result.Xyz = axis * (float)System.Math.Sin(angle);
result.W = (float)System.Math.Cos(angle);
return Normalize(result);
}
#endregion
#region Slerp
/// <summary>
/// Do Spherical linear interpolation between two quaternions
/// </summary>
/// <param name="q1">The first quaternion</param>
/// <param name="q2">The second quaternion</param>
/// <param name="blend">The blend factor</param>
/// <returns>A smooth blend between the given quaternions</returns>
public static Quaternion Slerp(Quaternion q1, Quaternion q2, float blend)
{
// if either input is zero, return the other.
if (q1.LengthSquared == 0.0f)
{
if (q2.LengthSquared == 0.0f)
{
return Identity;
}
return q2;
}
else if (q2.LengthSquared == 0.0f)
{
return q1;
}
float cosHalfAngle = q1.W * q2.W + Vector3.Dot(q1.Xyz, q2.Xyz);
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
{
// angle = 0.0f, so just return one input.
return q1;
}
else if (cosHalfAngle < 0.0f)
{
q2.Xyz = -q2.Xyz;
q2.W = -q2.W;
cosHalfAngle = -cosHalfAngle;
}
float blendA;
float blendB;
if (cosHalfAngle < 0.99f)
{
// do proper slerp for big angles
float halfAngle = (float)System.Math.Acos(cosHalfAngle);
float sinHalfAngle = (float)System.Math.Sin(halfAngle);
float oneOverSinHalfAngle = 1.0f / sinHalfAngle;
blendA = (float)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
blendB = (float)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
}
else
{
// do lerp if angle is really small.
blendA = 1.0f - blend;
blendB = blend;
}
Quaternion result = new Quaternion(blendA * q1.Xyz + blendB * q2.Xyz, blendA * q1.W + blendB * q2.W);
if (result.LengthSquared > 0.0f)
return Normalize(result);
else
return Identity;
}
#endregion
#endregion
#region Operators
public static Quaternion operator +(Quaternion left, Quaternion right)
{
left.Xyz += right.Xyz;
left.W += right.W;
return left;
}
public static Quaternion operator -(Quaternion left, Quaternion right)
{
left.Xyz -= right.Xyz;
left.W -= right.W;
return left;
}
public static Quaternion operator *(Quaternion left, Quaternion right)
{
float w = left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz);
left.Xyz = right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz);
left.W = w;
return left;
}
public static bool operator ==(Quaternion left, Quaternion right)
{
return left.Equals(right);
}
public static bool operator !=(Quaternion left, Quaternion right)
{
return !left.Equals(right);
}
#endregion
#region Overrides
#region public override string ToString()
/// <summary>
/// Returns a System.String that represents the current Quaternion.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("V: {0}, W: {1}", Xyz, W);
}
#endregion
#region public override bool Equals (object o)
/// <summary>
/// Compares this object instance to another object for equality.
/// </summary>
/// <param name="other">The other object to be used in the comparison.</param>
/// <returns>True if both objects are Quaternions of equal value. Otherwise it returns false.</returns>
public override bool Equals(object other)
{
if (other is Quaternion == false) return false;
return this == (Quaternion)other;
}
#endregion
#region public override int GetHashCode ()
/// <summary>
/// Provides the hash code for this object.
/// </summary>
/// <returns>A hash code formed from the bitwise XOR of this objects members.</returns>
public override int GetHashCode()
{
return Xyz.GetHashCode() ^ W.GetHashCode();
}
#endregion
#endregion
#endregion
#region IEquatable<Quaternion> Members
/// <summary>
/// Compares this Quaternion instance to another Quaternion for equality.
/// </summary>
/// <param name="other">The other Quaternion to be used in the comparison.</param>
/// <returns>True if both instances are equal; false otherwise.</returns>
public bool Equals(Quaternion other)
{
return Xyz == other.Xyz && W == other.W;
}
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,914 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.Runtime.InteropServices;
namespace OpenTK.Math
{
/// <summary>Represents a 2D vector using two single-precision floating-point numbers.</summary>
/// <remarks>
/// The Vector2 structure is suitable for interoperation with unmanaged code requiring two consecutive floats.
/// </remarks>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector2 : IEquatable<Vector2>
{
#region Fields
/// <summary>
/// The X component of the Vector2.
/// </summary>
public float X;
/// <summary>
/// The Y component of the Vector2.
/// </summary>
public float Y;
#endregion
#region Constructors
/// <summary>
/// Constructs a new Vector2.
/// </summary>
/// <param name="x">The x coordinate of the net Vector2.</param>
/// <param name="y">The y coordinate of the net Vector2.</param>
public Vector2(float x, float y)
{
X = x;
Y = y;
}
/// <summary>
/// Constructs a new Vector2 from the given Vector2.
/// </summary>
/// <param name="v">The Vector2 to copy components from.</param>
[Obsolete]
public Vector2(Vector2 v)
{
X = v.X;
Y = v.Y;
}
/// <summary>
/// Constructs a new Vector2 from the given Vector3.
/// </summary>
/// <param name="v">The Vector3 to copy components from. Z is discarded.</param>
[Obsolete]
public Vector2(Vector3 v)
{
X = v.X;
Y = v.Y;
}
/// <summary>
/// Constructs a new Vector2 from the given Vector4.
/// </summary>
/// <param name="v">The Vector4 to copy components from. Z and W are discarded.</param>
[Obsolete]
public Vector2(Vector4 v)
{
X = v.X;
Y = v.Y;
}
#endregion
#region Public Members
#region Instance
#region public void Add()
/// <summary>Add the Vector passed as parameter to this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
public void Add( Vector2 right )
{
this.X += right.X;
this.Y += right.Y;
}
/// <summary>Add the Vector passed as parameter to this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
[CLSCompliant(false)]
public void Add( ref Vector2 right )
{
this.X += right.X;
this.Y += right.Y;
}
#endregion public void Add()
#region public void Sub()
/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
public void Sub( Vector2 right )
{
this.X -= right.X;
this.Y -= right.Y;
}
/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
[CLSCompliant(false)]
public void Sub( ref Vector2 right )
{
this.X -= right.X;
this.Y -= right.Y;
}
#endregion public void Sub()
#region public void Mult()
/// <summary>Multiply this instance by a scalar.</summary>
/// <param name="f">Scalar operand.</param>
public void Mult( float f )
{
this.X *= f;
this.Y *= f;
}
#endregion public void Mult()
#region public void Div()
/// <summary>Divide this instance by a scalar.</summary>
/// <param name="f">Scalar operand.</param>
public void Div( float f )
{
float mult = 1.0f / f;
this.X *= mult;
this.Y *= mult;
}
#endregion public void Div()
#region public float Length
/// <summary>
/// Gets the length (magnitude) of the vector.
/// </summary>
/// <see cref="LengthFast"/>
/// <seealso cref="LengthSquared"/>
public float Length
{
get
{
return (float)System.Math.Sqrt(X * X + Y * Y);
}
}
#endregion
#region public float LengthFast
/// <summary>
/// Gets an approximation of the vector length (magnitude).
/// </summary>
/// <remarks>
/// This property uses an approximation of the square root function to calculate vector magnitude, with
/// an upper error bound of 0.001.
/// </remarks>
/// <see cref="Length"/>
/// <seealso cref="LengthSquared"/>
public float LengthFast
{
get
{
return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y);
}
}
#endregion
#region public float LengthSquared
/// <summary>
/// Gets the square of the vector length (magnitude).
/// </summary>
/// <remarks>
/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
/// for comparisons.
/// </remarks>
/// <see cref="Length"/>
/// <seealso cref="LengthFast"/>
public float LengthSquared
{
get
{
return X * X + Y * Y;
}
}
#endregion
#region public Vector2 PerpendicularRight
/// <summary>
/// Gets the perpendicular vector on the right side of this vector.
/// </summary>
public Vector2 PerpendicularRight
{
get
{
return new Vector2(Y, -X);
}
}
#endregion
#region public Vector2 PerpendicularLeft
/// <summary>
/// Gets the perpendicular vector on the left side of this vector.
/// </summary>
public Vector2 PerpendicularLeft
{
get
{
return new Vector2(-Y, X);
}
}
#endregion
#region public void Normalize()
/// <summary>
/// Scales the Vector2 to unit length.
/// </summary>
public void Normalize()
{
float scale = 1.0f / this.Length;
X *= scale;
Y *= scale;
}
#endregion
#region public void NormalizeFast()
/// <summary>
/// Scales the Vector2 to approximately unit length.
/// </summary>
public void NormalizeFast()
{
float scale = Functions.InverseSqrtFast(X * X + Y * Y);
X *= scale;
Y *= scale;
}
#endregion
#region public void Scale()
/// <summary>
/// Scales the current Vector2 by the given amounts.
/// </summary>
/// <param name="sx">The scale of the X component.</param>
/// <param name="sy">The scale of the Y component.</param>
public void Scale(float sx, float sy)
{
this.X = X * sx;
this.Y = Y * sy;
}
/// <summary>Scales this instance by the given parameter.</summary>
/// <param name="scale">The scaling of the individual components.</param>
public void Scale( Vector2 scale )
{
this.X *= scale.X;
this.Y *= scale.Y;
}
/// <summary>Scales this instance by the given parameter.</summary>
/// <param name="scale">The scaling of the individual components.</param>
[CLSCompliant(false)]
public void Scale( ref Vector2 scale )
{
this.X *= scale.X;
this.Y *= scale.Y;
}
#endregion public void Scale()
#endregion
#region Static
#region Fields
/// <summary>
/// Defines a unit-length Vector2 that points towards the X-axis.
/// </summary>
public static readonly Vector2 UnitX = new Vector2(1, 0);
/// <summary>
/// Defines a unit-length Vector2 that points towards the Y-axis.
/// </summary>
public static readonly Vector2 UnitY = new Vector2(0, 1);
/// <summary>
/// Defines a zero-length Vector2.
/// </summary>
public static readonly Vector2 Zero = new Vector2(0, 0);
/// <summary>
/// Defines an instance with all components set to 1.
/// </summary>
public static readonly Vector2 One = new Vector2(1, 1);
/// <summary>
/// Defines the size of the Vector2 struct in bytes.
/// </summary>
public static readonly int SizeInBytes = Marshal.SizeOf(new Vector2());
#endregion
#region Add
/// <summary>
/// Add the specified instances
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>Result of addition</returns>
public static Vector2 Add(Vector2 a, Vector2 b)
{
a.X += b.X;
a.Y += b.Y;
return a;
}
/// <summary>
/// Add two Vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">Result of addition</param>
public static void Add(ref Vector2 a, ref Vector2 b, out Vector2 result)
{
result.X = a.X + b.X;
result.Y = a.Y + b.Y;
}
#endregion
#region Sub
/// <summary>
/// Subtract one Vector from another
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>Result of subtraction</returns>
public static Vector2 Sub(Vector2 a, Vector2 b)
{
a.X -= b.X;
a.Y -= b.Y;
return a;
}
/// <summary>
/// Subtract one Vector from another
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">Result of subtraction</param>
public static void Sub(ref Vector2 a, ref Vector2 b, out Vector2 result)
{
result.X = a.X - b.X;
result.Y = a.Y - b.Y;
}
#endregion
#region Mult
/// <summary>
/// Multiply a vector and a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <returns>Result of the multiplication</returns>
public static Vector2 Mult(Vector2 a, float f)
{
a.X *= f;
a.Y *= f;
return a;
}
/// <summary>
/// Multiply a vector and a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <param name="result">Result of the multiplication</param>
public static void Mult(ref Vector2 a, float f, out Vector2 result)
{
result.X = a.X * f;
result.Y = a.Y * f;
}
#endregion
#region Div
/// <summary>
/// Divide a vector by a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <returns>Result of the division</returns>
public static Vector2 Div(Vector2 a, float f)
{
float mult = 1.0f / f;
a.X *= mult;
a.Y *= mult;
return a;
}
/// <summary>
/// Divide a vector by a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <param name="result">Result of the division</param>
public static void Div(ref Vector2 a, float f, out Vector2 result)
{
float mult = 1.0f / f;
result.X = a.X * mult;
result.Y = a.Y * mult;
}
#endregion
#region ComponentMin
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
public static Vector2 ComponentMin(Vector2 a, Vector2 b)
{
a.X = a.X < b.X ? a.X : b.X;
a.Y = a.Y < b.Y ? a.Y : b.Y;
return a;
}
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
public static void ComponentMin(ref Vector2 a, ref Vector2 b, out Vector2 result)
{
result.X = a.X < b.X ? a.X : b.X;
result.Y = a.Y < b.Y ? a.Y : b.Y;
}
#endregion
#region ComponentMax
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
public static Vector2 ComponentMax(Vector2 a, Vector2 b)
{
a.X = a.X > b.X ? a.X : b.X;
a.Y = a.Y > b.Y ? a.Y : b.Y;
return a;
}
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
public static void ComponentMax(ref Vector2 a, ref Vector2 b, out Vector2 result)
{
result.X = a.X > b.X ? a.X : b.X;
result.Y = a.Y > b.Y ? a.Y : b.Y;
}
#endregion
#region Min
/// <summary>
/// Returns the Vector3 with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
public static Vector2 Min(Vector2 left, Vector2 right)
{
return left.LengthSquared < right.LengthSquared ? left : right;
}
#endregion
#region Max
/// <summary>
/// Returns the Vector3 with the minimum magnitude
/// </summary>
/// <param name="left">Left operand</param>
/// <param name="right">Right operand</param>
/// <returns>The minimum Vector3</returns>
public static Vector2 Max(Vector2 left, Vector2 right)
{
return left.LengthSquared >= right.LengthSquared ? left : right;
}
#endregion
#region Clamp
/// <summary>
/// Clamp a vector to the given minimum and maximum vectors
/// </summary>
/// <param name="vec">Input vector</param>
/// <param name="min">Minimum vector</param>
/// <param name="max">Maximum vector</param>
/// <returns>The clamped vector</returns>
public static Vector2 Clamp(Vector2 vec, Vector2 min, Vector2 max)
{
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
return vec;
}
/// <summary>
/// Clamp a vector to the given minimum and maximum vectors
/// </summary>
/// <param name="vec">Input vector</param>
/// <param name="min">Minimum vector</param>
/// <param name="max">Maximum vector</param>
/// <param name="result">The clamped vector</param>
public static void Clamp(ref Vector2 vec, ref Vector2 min, ref Vector2 max, out Vector2 result)
{
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
}
#endregion
#region Normalize
/// <summary>
/// Scale a vector to unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <returns>The normalized vector</returns>
public static Vector2 Normalize(Vector2 vec)
{
float scale = 1.0f / vec.Length;
vec.X *= scale;
vec.Y *= scale;
return vec;
}
/// <summary>
/// Scale a vector to unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <param name="result">The normalized vector</param>
public static void Normalize(ref Vector2 vec, out Vector2 result)
{
float scale = 1.0f / vec.Length;
result.X = vec.X * scale;
result.Y = vec.Y * scale;
}
#endregion
#region NormalizeFast
/// <summary>
/// Scale a vector to approximately unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <returns>The normalized vector</returns>
public static Vector2 NormalizeFast(Vector2 vec)
{
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
vec.X *= scale;
vec.Y *= scale;
return vec;
}
/// <summary>
/// Scale a vector to approximately unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <param name="result">The normalized vector</param>
public static void NormalizeFast(ref Vector2 vec, out Vector2 result)
{
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
result.X = vec.X * scale;
result.Y = vec.Y * scale;
}
#endregion
#region Dot
/// <summary>
/// Calculate the dot (scalar) product of two vectors
/// </summary>
/// <param name="left">First operand</param>
/// <param name="right">Second operand</param>
/// <returns>The dot product of the two inputs</returns>
public static float Dot(Vector2 left, Vector2 right)
{
return left.X * right.X + left.Y * right.Y;
}
/// <summary>
/// Calculate the dot (scalar) product of two vectors
/// </summary>
/// <param name="left">First operand</param>
/// <param name="right">Second operand</param>
/// <param name="result">The dot product of the two inputs</param>
public static void Dot( ref Vector2 left, ref Vector2 right, out float result )
{
result = left.X * right.X + left.Y * right.Y;
}
#endregion
#region Lerp
/// <summary>
/// Returns a new Vector that is the linear blend of the 2 given Vectors
/// </summary>
/// <param name="a">First input vector</param>
/// <param name="b">Second input vector</param>
/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
public static Vector2 Lerp(Vector2 a, Vector2 b, float blend)
{
a.X = blend * (b.X - a.X) + a.X;
a.Y = blend * (b.Y - a.Y) + a.Y;
return a;
}
/// <summary>
/// Returns a new Vector that is the linear blend of the 2 given Vectors
/// </summary>
/// <param name="a">First input vector</param>
/// <param name="b">Second input vector</param>
/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
/// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
public static void Lerp( ref Vector2 a, ref Vector2 b, float blend, out Vector2 result )
{
result.X = blend * ( b.X - a.X ) + a.X;
result.Y = blend * ( b.Y - a.Y ) + a.Y;
}
#endregion
#region Barycentric
/// <summary>
/// Interpolate 3 Vectors using Barycentric coordinates
/// </summary>
/// <param name="a">First input Vector</param>
/// <param name="b">Second input Vector</param>
/// <param name="c">Third input Vector</param>
/// <param name="u">First Barycentric Coordinate</param>
/// <param name="v">Second Barycentric Coordinate</param>
/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
public static Vector2 BaryCentric(Vector2 a, Vector2 b, Vector2 c, float u, float v)
{
return a + u * (b - a) + v * (c - a);
}
/// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
/// <param name="a">First input Vector.</param>
/// <param name="b">Second input Vector.</param>
/// <param name="c">Third input Vector.</param>
/// <param name="u">First Barycentric Coordinate.</param>
/// <param name="v">Second Barycentric Coordinate.</param>
/// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
public static void BaryCentric( ref Vector2 a, ref Vector2 b, ref Vector2 c, float u, float v, out Vector2 result )
{
result = a; // copy
Vector2 temp = b; // copy
temp.Sub( ref a );
temp.Mult( u );
result.Add( ref temp );
temp = c; // copy
temp.Sub( ref a );
temp.Mult( v );
result.Add( ref temp );
}
#endregion
#endregion
#region Operators
/// <summary>
/// Adds the specified instances.
/// </summary>
/// <param name="left">Left operand.</param>
/// <param name="right">Right operand.</param>
/// <returns>Result of addition.</returns>
public static Vector2 operator +(Vector2 left, Vector2 right)
{
left.X += right.X;
left.Y += right.Y;
return left;
}
/// <summary>
/// Subtracts the specified instances.
/// </summary>
/// <param name="left">Left operand.</param>
/// <param name="right">Right operand.</param>
/// <returns>Result of subtraction.</returns>
public static Vector2 operator -(Vector2 left, Vector2 right)
{
left.X -= right.X;
left.Y -= right.Y;
return left;
}
/// <summary>
/// Negates the specified instance.
/// </summary>
/// <param name="vec">Operand.</param>
/// <returns>Result of negation.</returns>
public static Vector2 operator -(Vector2 vec)
{
vec.X = -vec.X;
vec.Y = -vec.Y;
return vec;
}
/// <summary>
/// Multiplies the specified instance by a scalar.
/// </summary>
/// <param name="vec">Left operand.</param>
/// <param name="scale">Right operand.</param>
/// <returns>Result of multiplication.</returns>
public static Vector2 operator *(Vector2 vec, float scale)
{
vec.X *= scale;
vec.Y *= scale;
return vec;
}
/// <summary>
/// Multiplies the specified instance by a scalar.
/// </summary>
/// <param name="scale">Left operand.</param>
/// <param name="vec">Right operand.</param>
/// <returns>Result of multiplication.</returns>
public static Vector2 operator *(float scale, Vector2 vec)
{
vec.X *= scale;
vec.Y *= scale;
return vec;
}
/// <summary>
/// Divides the specified instance by a scalar.
/// </summary>
/// <param name="vec">Left operand</param>
/// <param name="scale">Right operand</param>
/// <returns>Result of the division.</returns>
public static Vector2 operator /(Vector2 vec, float scale)
{
float mult = 1.0f / scale;
vec.X *= mult;
vec.Y *= mult;
return vec;
}
/// <summary>
/// Compares the specified instances for equality.
/// </summary>
/// <param name="left">Left operand.</param>
/// <param name="right">Right operand.</param>
/// <returns>True if both instances are equal; false otherwise.</returns>
public static bool operator ==(Vector2 left, Vector2 right)
{
return left.Equals(right);
}
/// <summary>
/// Compares the specified instances for inequality.
/// </summary>
/// <param name="left">Left operand.</param>
/// <param name="right">Right operand.</param>
/// <returns>True if both instances are not equal; false otherwise.</returns>
public static bool operator !=(Vector2 left, Vector2 right)
{
return !left.Equals(right);
}
#endregion
#region Overrides
#region public override string ToString()
/// <summary>
/// Returns a System.String that represents the current Vector2.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("({0}, {1})", X, Y);
}
#endregion
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector2))
return false;
return this.Equals((Vector2)obj);
}
#endregion
#endregion
#endregion
#region IEquatable<Vector2> Members
/// <summary>Indicates whether the current vector is equal to another vector.</summary>
/// <param name="other">A vector to compare with this vector.</param>
/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
public bool Equals(Vector2 other)
{
return
X == other.X &&
Y == other.Y;
}
#endregion
}
}

View file

@ -0,0 +1,817 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.Runtime.InteropServices;
namespace OpenTK.Math
{
/// <summary>Represents a 2D vector using two double-precision floating-point numbers.</summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector2d : IEquatable<Vector2d>
{
#region Fields
/// <summary>The X coordinate of this instance.</summary>
public double X;
/// <summary>The Y coordinate of this instance.</summary>
public double Y;
/// <summary>
/// Defines a unit-length Vector2d that points towards the X-axis.
/// </summary>
public static Vector2d UnitX = new Vector2d(1, 0);
/// <summary>
/// Defines a unit-length Vector2d that points towards the Y-axis.
/// </summary>
public static Vector2d UnitY = new Vector2d(0, 1);
/// <summary>
/// Defines a zero-length Vector2d.
/// </summary>
public static Vector2d Zero = new Vector2d(0, 0);
/// <summary>
/// Defines an instance with all components set to 1.
/// </summary>
public static readonly Vector2d One = new Vector2d(1, 1);
/// <summary>
/// Defines the size of the Vector2d struct in bytes.
/// </summary>
public static readonly int SizeInBytes = Marshal.SizeOf(new Vector2d());
#endregion
#region Constructors
/// <summary>Constructs left vector with the given coordinates.</summary>
/// <param name="x">The X coordinate.</param>
/// <param name="y">The Y coordinate.</param>
public Vector2d(double x, double y)
{
this.X = x;
this.Y = y;
}
#endregion
#region Public Members
#region Instance
#region public void Add()
/// <summary>Add the Vector passed as parameter to this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
public void Add(Vector2d right)
{
this.X += right.X;
this.Y += right.Y;
}
/// <summary>Add the Vector passed as parameter to this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
[CLSCompliant(false)]
public void Add(ref Vector2d right)
{
this.X += right.X;
this.Y += right.Y;
}
#endregion public void Add()
#region public void Sub()
/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
public void Sub(Vector2d right)
{
this.X -= right.X;
this.Y -= right.Y;
}
/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
[CLSCompliant(false)]
public void Sub(ref Vector2d right)
{
this.X -= right.X;
this.Y -= right.Y;
}
#endregion public void Sub()
#region public void Mult()
/// <summary>Multiply this instance by a scalar.</summary>
/// <param name="f">Scalar operand.</param>
public void Mult(double f)
{
this.X *= f;
this.Y *= f;
}
#endregion public void Mult()
#region public void Div()
/// <summary>Divide this instance by a scalar.</summary>
/// <param name="f">Scalar operand.</param>
public void Div(double f)
{
double mult = 1.0 / f;
this.X *= mult;
this.Y *= mult;
}
#endregion public void Div()
#region public double Length
/// <summary>
/// Gets the length (magnitude) of the vector.
/// </summary>
/// <seealso cref="LengthSquared"/>
public double Length
{
get
{
return (float)System.Math.Sqrt(X * X + Y * Y);
}
}
#endregion
#region public double LengthSquared
/// <summary>
/// Gets the square of the vector length (magnitude).
/// </summary>
/// <remarks>
/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
/// for comparisons.
/// </remarks>
/// <see cref="Length"/>
public double LengthSquared
{
get
{
return X * X + Y * Y;
}
}
#endregion
#region public Vector2d PerpendicularRight
/// <summary>
/// Gets the perpendicular vector on the right side of this vector.
/// </summary>
public Vector2d PerpendicularRight
{
get
{
return new Vector2d(Y, -X);
}
}
#endregion
#region public Vector2d PerpendicularLeft
/// <summary>
/// Gets the perpendicular vector on the left side of this vector.
/// </summary>
public Vector2d PerpendicularLeft
{
get
{
return new Vector2d(-Y, X);
}
}
#endregion
#region public void Normalize()
/// <summary>
/// Scales the Vector2 to unit length.
/// </summary>
public void Normalize()
{
double scale = 1.0f / Length;
X *= scale;
Y *= scale;
}
#endregion
#region public void Scale()
/// <summary>
/// Scales the current Vector2 by the given amounts.
/// </summary>
/// <param name="sx">The scale of the X component.</param>
/// <param name="sy">The scale of the Y component.</param>
public void Scale(double sx, double sy)
{
X *= sx;
Y *= sy;
}
/// <summary>Scales this instance by the given parameter.</summary>
/// <param name="scale">The scaling of the individual components.</param>
public void Scale(Vector2d scale)
{
this.X *= scale.X;
this.Y *= scale.Y;
}
/// <summary>Scales this instance by the given parameter.</summary>
/// <param name="scale">The scaling of the individual components.</param>
[CLSCompliant(false)]
public void Scale(ref Vector2d scale)
{
this.X *= scale.X;
this.Y *= scale.Y;
}
#endregion public void Scale()
#endregion
#region Static
#region Add
/// <summary>
/// Add two Vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>Result of addition</returns>
public static Vector2d Add(Vector2d a, Vector2d b)
{
a.X += b.X;
a.Y += b.Y;
return a;
}
/// <summary>
/// Add two Vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">Result of addition</param>
public static void Add(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X + b.X;
result.Y = a.Y + b.Y;
}
#endregion
#region Sub
/// <summary>
/// Subtract one Vector from another
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>Result of subtraction</returns>
public static Vector2d Sub(Vector2d a, Vector2d b)
{
a.X -= b.X;
a.Y -= b.Y;
return a;
}
/// <summary>
/// Subtract one Vector from another
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">Result of subtraction</param>
public static void Sub(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X - b.X;
result.Y = a.Y - b.Y;
}
#endregion
#region Mult
/// <summary>
/// Multiply a vector and a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="d">Scalar operand</param>
/// <returns>Result of the multiplication</returns>
public static Vector2d Mult(Vector2d a, double d)
{
a.X *= d;
a.Y *= d;
return a;
}
/// <summary>
/// Multiply a vector and a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="d">Scalar operand</param>
/// <param name="result">Result of the multiplication</param>
public static void Mult(ref Vector2d a, double d, out Vector2d result)
{
result.X = a.X * d;
result.Y = a.Y * d;
}
#endregion
#region Div
/// <summary>
/// Divide a vector by a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="d">Scalar operand</param>
/// <returns>Result of the division</returns>
public static Vector2d Div(Vector2d a, double d)
{
double mult = 1.0 / d;
a.X *= mult;
a.Y *= mult;
return a;
}
/// <summary>
/// Divide a vector by a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="d">Scalar operand</param>
/// <param name="result">Result of the division</param>
public static void Div(ref Vector2d a, double d, out Vector2d result)
{
double mult = 1.0 / d;
result.X = a.X * mult;
result.Y = a.Y * mult;
}
#endregion
#region Min
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
public static Vector2d Min(Vector2d a, Vector2d b)
{
a.X = a.X < b.X ? a.X : b.X;
a.Y = a.Y < b.Y ? a.Y : b.Y;
return a;
}
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
public static void Min(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X < b.X ? a.X : b.X;
result.Y = a.Y < b.Y ? a.Y : b.Y;
}
#endregion
#region Max
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
public static Vector2d Max(Vector2d a, Vector2d b)
{
a.X = a.X > b.X ? a.X : b.X;
a.Y = a.Y > b.Y ? a.Y : b.Y;
return a;
}
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
public static void Max(ref Vector2d a, ref Vector2d b, out Vector2d result)
{
result.X = a.X > b.X ? a.X : b.X;
result.Y = a.Y > b.Y ? a.Y : b.Y;
}
#endregion
#region Clamp
/// <summary>
/// Clamp a vector to the given minimum and maximum vectors
/// </summary>
/// <param name="vec">Input vector</param>
/// <param name="min">Minimum vector</param>
/// <param name="max">Maximum vector</param>
/// <returns>The clamped vector</returns>
public static Vector2d Clamp(Vector2d vec, Vector2d min, Vector2d max)
{
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
return vec;
}
/// <summary>
/// Clamp a vector to the given minimum and maximum vectors
/// </summary>
/// <param name="vec">Input vector</param>
/// <param name="min">Minimum vector</param>
/// <param name="max">Maximum vector</param>
/// <param name="result">The clamped vector</param>
public static void Clamp(ref Vector2d vec, ref Vector2d min, ref Vector2d max, out Vector2d result)
{
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
}
#endregion
#region Normalize
/// <summary>
/// Scale a vector to unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <returns>The normalized vector</returns>
public static Vector2d Normalize(Vector2d vec)
{
double scale = 1.0f / vec.Length;
vec.X *= scale;
vec.Y *= scale;
return vec;
}
/// <summary>
/// Scale a vector to unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <param name="result">The normalized vector</param>
public static void Normalize(ref Vector2d vec, out Vector2d result)
{
double scale = 1.0f / vec.Length;
result.X = vec.X * scale;
result.Y = vec.Y * scale;
}
#endregion
#region NormalizeFast
/// <summary>
/// Scale a vector to approximately unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <returns>The normalized vector</returns>
public static Vector2d NormalizeFast(Vector2d vec)
{
double scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
vec.X *= scale;
vec.Y *= scale;
return vec;
}
/// <summary>
/// Scale a vector to approximately unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <param name="result">The normalized vector</param>
public static void NormalizeFast(ref Vector2d vec, out Vector2d result)
{
double scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
result.X = vec.X * scale;
result.Y = vec.Y * scale;
}
#endregion
#region Dot
/// <summary>
/// Calculate the dot (scalar) product of two vectors
/// </summary>
/// <param name="left">First operand</param>
/// <param name="right">Second operand</param>
/// <returns>The dot product of the two inputs</returns>
public static double Dot(Vector2d left, Vector2d right)
{
return left.X * right.X + left.Y * right.Y;
}
/// <summary>
/// Calculate the dot (scalar) product of two vectors
/// </summary>
/// <param name="left">First operand</param>
/// <param name="right">Second operand</param>
/// <param name="result">The dot product of the two inputs</param>
public static void Dot(ref Vector2d left, ref Vector2d right, out double result)
{
result = left.X * right.X + left.Y * right.Y;
}
#endregion
#region Lerp
/// <summary>
/// Returns a new Vector that is the linear blend of the 2 given Vectors
/// </summary>
/// <param name="a">First input vector</param>
/// <param name="b">Second input vector</param>
/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
public static Vector2d Lerp(Vector2d a, Vector2d b, double blend)
{
a.X = blend * (b.X - a.X) + a.X;
a.Y = blend * (b.Y - a.Y) + a.Y;
return a;
}
/// <summary>
/// Returns a new Vector that is the linear blend of the 2 given Vectors
/// </summary>
/// <param name="a">First input vector</param>
/// <param name="b">Second input vector</param>
/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
/// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
public static void Lerp(ref Vector2d a, ref Vector2d b, double blend, out Vector2d result)
{
result.X = blend * (b.X - a.X) + a.X;
result.Y = blend * (b.Y - a.Y) + a.Y;
}
#endregion
#region Barycentric
/// <summary>
/// Interpolate 3 Vectors using Barycentric coordinates
/// </summary>
/// <param name="a">First input Vector</param>
/// <param name="b">Second input Vector</param>
/// <param name="c">Third input Vector</param>
/// <param name="u">First Barycentric Coordinate</param>
/// <param name="v">Second Barycentric Coordinate</param>
/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
public static Vector2d BaryCentric(Vector2d a, Vector2d b, Vector2d c, double u, double v)
{
return a + u * (b - a) + v * (c - a);
}
/// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
/// <param name="a">First input Vector.</param>
/// <param name="b">Second input Vector.</param>
/// <param name="c">Third input Vector.</param>
/// <param name="u">First Barycentric Coordinate.</param>
/// <param name="v">Second Barycentric Coordinate.</param>
/// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
public static void BaryCentric(ref Vector2d a, ref Vector2d b, ref Vector2d c, float u, float v, out Vector2d result)
{
result = a; // copy
Vector2d temp = b; // copy
temp.Sub(ref a);
temp.Mult(u);
result.Add(ref temp);
temp = c; // copy
temp.Sub(ref a);
temp.Mult(v);
result.Add(ref temp);
}
#endregion
#endregion
#region Operators
/// <summary>
/// Adds two instances.
/// </summary>
/// <param name="left">The left instance.</param>
/// <param name="right">The right instance.</param>
/// <returns>The result of the operation.</returns>
public static Vector2d operator +(Vector2d left, Vector2d right)
{
left.X += right.X;
left.Y += right.Y;
return left;
}
/// <summary>
/// Subtracts two instances.
/// </summary>
/// <param name="left">The left instance.</param>
/// <param name="right">The right instance.</param>
/// <returns>The result of the operation.</returns>
public static Vector2d operator -(Vector2d left, Vector2d right)
{
left.X -= right.X;
left.Y -= right.Y;
return left;
}
/// <summary>
/// Negates an instance.
/// </summary>
/// <param name="vec">The instance.</param>
/// <returns>The result of the operation.</returns>
public static Vector2d operator -(Vector2d vec)
{
vec.X = -vec.X;
vec.Y = -vec.Y;
return vec;
}
/// <summary>
/// Multiplies an instance by a scalar.
/// </summary>
/// <param name="vec">The instance.</param>
/// <param name="f">The scalar.</param>
/// <returns>The result of the operation.</returns>
public static Vector2d operator *(Vector2d vec, double f)
{
vec.X *= f;
vec.Y *= f;
return vec;
}
/// <summary>
/// Multiply an instance by a scalar.
/// </summary>
/// <param name="f">The scalar.</param>
/// <param name="vec">The instance.</param>
/// <returns>The result of the operation.</returns>
public static Vector2d operator *(double f, Vector2d vec)
{
vec.X *= f;
vec.Y *= f;
return vec;
}
/// <summary>
/// Divides an instance by a scalar.
/// </summary>
/// <param name="vec">The instance.</param>
/// <param name="f">The scalar.</param>
/// <returns>The result of the operation.</returns>
public static Vector2d operator /(Vector2d vec, double f)
{
double mult = 1.0f / f;
vec.X *= mult;
vec.Y *= mult;
return vec;
}
/// <summary>
/// Compares two instances for equality.
/// </summary>
/// <param name="left">The left instance.</param>
/// <param name="right">The right instance.</param>
/// <returns>True, if both instances are equal; false otherwise.</returns>
public static bool operator ==(Vector2d left, Vector2d right)
{
return left.Equals(right);
}
/// <summary>
/// Compares two instances for ienquality.
/// </summary>
/// <param name="left">The left instance.</param>
/// <param name="right">The right instance.</param>
/// <returns>True, if the instances are not equal; false otherwise.</returns>
public static bool operator !=(Vector2d left, Vector2d right)
{
return !left.Equals(right);
}
/// <summary>Converts OpenTK.Vector2 to OpenTK.Vector2d.</summary>
/// <param name="v2">The Vector2 to convert.</param>
/// <returns>The resulting Vector2d.</returns>
public static explicit operator Vector2d(Vector2 v2)
{
return new Vector2d(v2.X, v2.Y);
}
/// <summary>Converts OpenTK.Vector2d to OpenTK.Vector2.</summary>
/// <param name="v2d">The Vector2d to convert.</param>
/// <returns>The resulting Vector2.</returns>
public static explicit operator Vector2(Vector2d v2d)
{
return new Vector2((float)v2d.X, (float)v2d.Y);
}
#endregion
#region Overrides
#region public override string ToString()
/// <summary>
/// Returns a System.String that represents the current instance.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("({0}, {1})", X, Y);
}
#endregion
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector2d))
return false;
return this.Equals((Vector2d)obj);
}
#endregion
#endregion
#endregion
#region IEquatable<Vector2d> Members
/// <summary>Indicates whether the current vector is equal to another vector.</summary>
/// <param name="other">A vector to compare with this vector.</param>
/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
public bool Equals(Vector2d other)
{
return
X == other.X &&
Y == other.Y;
}
#endregion
}
}

View file

@ -0,0 +1,336 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace OpenTK.Math
{
/// <summary>2-component Vector of the Half type. Occupies 4 Byte total.</summary>
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Vector2h : ISerializable, IEquatable<Vector2h>
{
#region Fields
/// <summary>The X component of the Half2.</summary>
public Half X;
/// <summary>The Y component of the Half2.</summary>
public Half Y;
#endregion
#region Constructors
/// <summary>
/// The new Half2 instance will avoid conversion and copy directly from the Half parameters.
/// </summary>
/// <param name="x">An Half instance of a 16-Bit half precision floating point number.</param>
/// <param name="y">An Half instance of a 16-Bit half precision floating point number.</param>
public Vector2h(Half x, Half y)
{
X = x;
Y = y;
}
/// <summary>
/// The new Half2 instance will convert the 2 parameters into 16-Bit Half precision floating point.
/// </summary>
/// <param name="x">32-Bit Single precision floating point number.</param>
/// <param name="y">32-Bit Single precision floating point number.</param>
public Vector2h(Single x, Single y)
{
X = new Half(x);
Y = new Half(y);
}
/// <summary>
/// The new Half2 instance will convert the 2 parameters into 16-Bit Half precision floating point.
/// </summary>
/// <param name="x">32-Bit Single precision floating point number.</param>
/// <param name="y">32-Bit Single precision floating point number.</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector2h(Single x, Single y, bool throwOnError)
{
X = new Half(x, throwOnError);
Y = new Half(y, throwOnError);
}
/// <summary>
/// The new Half2 instance will convert the Vector2 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector2</param>
[CLSCompliant(false)]
public Vector2h(Vector2 v)
{
X = new Half(v.X);
Y = new Half(v.Y);
}
/// <summary>
/// The new Half2 instance will convert the Vector2 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector2</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
[CLSCompliant(false)]
public Vector2h(Vector2 v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
}
/// <summary>
/// The new Half2 instance will convert the Vector2 into 16-Bit Half precision floating point.
/// This is the fastest constructor.
/// </summary>
/// <param name="v">OpenTK.Vector2</param>
public Vector2h(ref Vector2 v)
{
X = new Half(v.X);
Y = new Half(v.Y);
}
/// <summary>
/// The new Half2 instance will convert the Vector2 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector2</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector2h(ref Vector2 v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
}
/// <summary>
/// The new Half2 instance will convert the Vector2d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector2d</param>
public Vector2h(Vector2d v)
{
X = new Half(v.X);
Y = new Half(v.Y);
}
/// <summary>
/// The new Half2 instance will convert the Vector2d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector2d</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector2h(Vector2d v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
}
/// <summary>
/// The new Half2 instance will convert the Vector2d into 16-Bit Half precision floating point.
/// This is the faster constructor.
/// </summary>
/// <param name="v">OpenTK.Vector2d</param>
[CLSCompliant(false)]
public Vector2h(ref Vector2d v)
{
X = new Half(v.X);
Y = new Half(v.Y);
}
/// <summary>
/// The new Half2 instance will convert the Vector2d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector2d</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
[CLSCompliant(false)]
public Vector2h(ref Vector2d v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
}
#endregion Constructors
#region Half -> Single
/// <summary>
/// Returns this Half2 instance's contents as Vector2.
/// </summary>
/// <returns>OpenTK.Vector2</returns>
public Vector2 ToVector2()
{
return new Vector2(X, Y);
}
/// <summary>
/// Returns this Half2 instance's contents as Vector2d.
/// </summary>
public Vector2d ToVector2d()
{
return new Vector2d(X, Y);
}
#endregion Half -> Single
#region Conversions
/// <summary>Converts OpenTK.Vector2 to OpenTK.Half2.</summary>
/// <param name="v">The Vector2 to convert.</param>
/// <returns>The resulting Half vector.</returns>
public static explicit operator Vector2h(Vector2 v)
{
return new Vector2h(v);
}
/// <summary>Converts OpenTK.Vector2d to OpenTK.Half2.</summary>
/// <param name="v">The Vector2d to convert.</param>
/// <returns>The resulting Half vector.</returns>
public static explicit operator Vector2h(Vector2d v)
{
return new Vector2h(v);
}
/// <summary>Converts OpenTK.Half2 to OpenTK.Vector2.</summary>
/// <param name="h">The Half2 to convert.</param>
/// <returns>The resulting Vector2.</returns>
public static explicit operator Vector2(Vector2h h)
{
return new Vector2(h.X, h.Y);
}
/// <summary>Converts OpenTK.Half2 to OpenTK.Vector2d.</summary>
/// <param name="h">The Half2 to convert.</param>
/// <returns>The resulting Vector2d.</returns>
public static explicit operator Vector2d(Vector2h h)
{
return new Vector2d(h.X, h.Y);
}
#endregion Conversions
#region Constants
/// <summary>The size in bytes for an instance of the Half2 struct is 4.</summary>
public static readonly int SizeInBytes = 4;
#endregion Constants
#region ISerializable
/// <summary>Constructor used by ISerializable to deserialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public Vector2h(SerializationInfo info, StreamingContext context)
{
this.X = (Half)info.GetValue("X", typeof(Half));
this.Y = (Half)info.GetValue("Y", typeof(Half));
}
/// <summary>Used by ISerialize to serialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("X", this.X);
info.AddValue("Y", this.Y);
}
#endregion ISerializable
#region Binary dump
/// <summary>Updates the X and Y components of this instance by reading from a Stream.</summary>
/// <param name="bin">A BinaryReader instance associated with an open Stream.</param>
public void FromBinaryStream(BinaryReader bin)
{
X.FromBinaryStream(bin);
Y.FromBinaryStream(bin);
}
/// <summary>Writes the X and Y components of this instance into a Stream.</summary>
/// <param name="bin">A BinaryWriter instance associated with an open Stream.</param>
public void ToBinaryStream(BinaryWriter bin)
{
X.ToBinaryStream(bin);
Y.ToBinaryStream(bin);
}
#endregion Binary dump
#region IEquatable<Half2> Members
/// <summary>Returns a value indicating whether this instance is equal to a specified OpenTK.Half2 vector.</summary>
/// <param name="other">OpenTK.Half2 to compare to this instance..</param>
/// <returns>True, if other is equal to this instance; false otherwise.</returns>
public bool Equals(Vector2h other)
{
return (this.X.Equals(other.X) && this.Y.Equals(other.Y));
}
#endregion
#region ToString()
/// <summary>Returns a string that contains this Half2's numbers in human-legible form.</summary>
public override string ToString()
{
return String.Format("({0}, {1})", X.ToString(), Y.ToString());
}
#endregion ToString()
#region BitConverter
/// <summary>Returns the Half2 as an array of bytes.</summary>
/// <param name="h">The Half2 to convert.</param>
/// <returns>The input as byte array.</returns>
public static byte[] GetBytes(Vector2h h)
{
byte[] result = new byte[SizeInBytes];
byte[] temp = Half.GetBytes(h.X);
result[0] = temp[0];
result[1] = temp[1];
temp = Half.GetBytes(h.Y);
result[2] = temp[0];
result[3] = temp[1];
return result;
}
/// <summary>Converts an array of bytes into Half2.</summary>
/// <param name="value">A Half2 in it's byte[] representation.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A new Half2 instance.</returns>
public static Vector2h FromBytes(byte[] value, int startIndex)
{
Vector2h h2 = new Vector2h();
h2.X = Half.FromBytes(value, startIndex);
h2.Y = Half.FromBytes(value, startIndex + 2);
return h2;
}
#endregion BitConverter
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,381 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Xml.Serialization;
namespace OpenTK.Math
{
/// <summary>
/// 3-component Vector of the Half type. Occupies 6 Byte total.
/// </summary>
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Vector3h : ISerializable, IEquatable<Vector3h>
{
#region Public Fields
/// <summary>The X component of the Half3.</summary>
public Half X;
/// <summary>The Y component of the Half3.</summary>
public Half Y;
/// <summary>The Z component of the Half3.</summary>
public Half Z;
#endregion Public Fields
#region Constructors
/// <summary>
/// The new Half3 instance will avoid conversion and copy directly from the Half parameters.
/// </summary>
/// <param name="x">An Half instance of a 16-Bit half precision floating point number.</param>
/// <param name="y">An Half instance of a 16-Bit half precision floating point number.</param>
/// <param name="z">An Half instance of a 16-Bit half precision floating point number.</param>
public Vector3h(Half x, Half y, Half z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
/// <summary>
/// The new Half3 instance will convert the 3 parameters into 16-Bit Half precision floating point.
/// </summary>
/// <param name="x">32-Bit Single precision floating point number.</param>
/// <param name="y">32-Bit Single precision floating point number.</param>
/// <param name="z">32-Bit Single precision floating point number.</param>
public Vector3h(Single x, Single y, Single z)
{
X = new Half(x);
Y = new Half(y);
Z = new Half(z);
}
/// <summary>
/// The new Half3 instance will convert the 3 parameters into 16-Bit Half precision floating point.
/// </summary>
/// <param name="x">32-Bit Single precision floating point number.</param>
/// <param name="y">32-Bit Single precision floating point number.</param>
/// <param name="z">32-Bit Single precision floating point number.</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector3h(Single x, Single y, Single z, bool throwOnError)
{
X = new Half(x, throwOnError);
Y = new Half(y, throwOnError);
Z = new Half(z, throwOnError);
}
/// <summary>
/// The new Half3 instance will convert the Vector3 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector3</param>
[CLSCompliant(false)]
public Vector3h(Vector3 v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
}
/// <summary>
/// The new Half3 instance will convert the Vector3 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector3</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
[CLSCompliant(false)]
public Vector3h(Vector3 v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
}
/// <summary>
/// The new Half3 instance will convert the Vector3 into 16-Bit Half precision floating point.
/// This is the fastest constructor.
/// </summary>
/// <param name="v">OpenTK.Vector3</param>
public Vector3h(ref Vector3 v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
}
/// <summary>
/// The new Half3 instance will convert the Vector3 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector3</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector3h(ref Vector3 v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
}
/// <summary>
/// The new Half3 instance will convert the Vector3d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector3d</param>
public Vector3h(Vector3d v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
}
/// <summary>
/// The new Half3 instance will convert the Vector3d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector3d</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector3h(Vector3d v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
}
/// <summary>
/// The new Half3 instance will convert the Vector3d into 16-Bit Half precision floating point.
/// This is the faster constructor.
/// </summary>
/// <param name="v">OpenTK.Vector3d</param>
[CLSCompliant(false)]
public Vector3h(ref Vector3d v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
}
/// <summary>
/// The new Half3 instance will convert the Vector3d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector3d</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
[CLSCompliant(false)]
public Vector3h(ref Vector3d v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
}
#endregion Constructors
#region Swizzle
/// <summary>
/// Gets or sets an OpenTK.Vector2h with the X and Y components of this instance.
/// </summary>
[XmlIgnore]
public Vector2h Xy { get { return new Vector2h(X, Y); } set { X = value.X; Y = value.Y; } }
#endregion
#region Half -> Single
/// <summary>
/// Returns this Half3 instance's contents as Vector3.
/// </summary>
/// <returns>OpenTK.Vector3</returns>
public Vector3 ToVector3()
{
return new Vector3(X, Y, Z);
}
/// <summary>
/// Returns this Half3 instance's contents as Vector3d.
/// </summary>
public Vector3d ToVector3d()
{
return new Vector3d(X, Y, Z);
}
#endregion Half -> Single
#region Conversions
/// <summary>Converts OpenTK.Vector3 to OpenTK.Half3.</summary>
/// <param name="v3f">The Vector3 to convert.</param>
/// <returns>The resulting Half vector.</returns>
public static explicit operator Vector3h(Vector3 v3f)
{
return new Vector3h(v3f);
}
/// <summary>Converts OpenTK.Vector3d to OpenTK.Half3.</summary>
/// <param name="v3d">The Vector3d to convert.</param>
/// <returns>The resulting Half vector.</returns>
public static explicit operator Vector3h(Vector3d v3d)
{
return new Vector3h(v3d);
}
/// <summary>Converts OpenTK.Half3 to OpenTK.Vector3.</summary>
/// <param name="h3">The Half3 to convert.</param>
/// <returns>The resulting Vector3.</returns>
public static explicit operator Vector3(Vector3h h3)
{
Vector3 result = new Vector3();
result.X = h3.X.ToSingle();
result.Y = h3.Y.ToSingle();
result.Z = h3.Z.ToSingle();
return result;
}
/// <summary>Converts OpenTK.Half3 to OpenTK.Vector3d.</summary>
/// <param name="h3">The Half3 to convert.</param>
/// <returns>The resulting Vector3d.</returns>
public static explicit operator Vector3d(Vector3h h3)
{
Vector3d result = new Vector3d();
result.X = h3.X.ToSingle();
result.Y = h3.Y.ToSingle();
result.Z = h3.Z.ToSingle();
return result;
}
#endregion Conversions
#region Constants
/// <summary>The size in bytes for an instance of the Half3 struct is 6.</summary>
public static readonly int SizeInBytes = 6;
#endregion Constants
#region ISerializable
/// <summary>Constructor used by ISerializable to deserialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public Vector3h(SerializationInfo info, StreamingContext context)
{
this.X = (Half)info.GetValue("X", typeof(Half));
this.Y = (Half)info.GetValue("Y", typeof(Half));
this.Z = (Half)info.GetValue("Z", typeof(Half));
}
/// <summary>Used by ISerialize to serialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("X", this.X);
info.AddValue("Y", this.Y);
info.AddValue("Z", this.Z);
}
#endregion ISerializable
#region Binary dump
/// <summary>Updates the X,Y and Z components of this instance by reading from a Stream.</summary>
/// <param name="bin">A BinaryReader instance associated with an open Stream.</param>
public void FromBinaryStream(BinaryReader bin)
{
X.FromBinaryStream(bin);
Y.FromBinaryStream(bin);
Z.FromBinaryStream(bin);
}
/// <summary>Writes the X,Y and Z components of this instance into a Stream.</summary>
/// <param name="bin">A BinaryWriter instance associated with an open Stream.</param>
public void ToBinaryStream(BinaryWriter bin)
{
X.ToBinaryStream(bin);
Y.ToBinaryStream(bin);
Z.ToBinaryStream(bin);
}
#endregion Binary dump
#region IEquatable<Half3> Members
/// <summary>Returns a value indicating whether this instance is equal to a specified OpenTK.Half3 vector.</summary>
/// <param name="other">OpenTK.Half3 to compare to this instance..</param>
/// <returns>True, if other is equal to this instance; false otherwise.</returns>
public bool Equals(Vector3h other)
{
return (this.X.Equals(other.X) && this.Y.Equals(other.Y) && this.Z.Equals(other.Z));
}
#endregion
#region ToString()
/// <summary>Returns a string that contains this Half3's numbers in human-legible form.</summary>
public override string ToString()
{
return String.Format("({0}, {1}, {2})", X.ToString(), Y.ToString(), Z.ToString());
}
#endregion ToString()
#region BitConverter
/// <summary>Returns the Half3 as an array of bytes.</summary>
/// <param name="h">The Half3 to convert.</param>
/// <returns>The input as byte array.</returns>
public static byte[] GetBytes(Vector3h h)
{
byte[] result = new byte[SizeInBytes];
byte[] temp = Half.GetBytes(h.X);
result[0] = temp[0];
result[1] = temp[1];
temp = Half.GetBytes(h.Y);
result[2] = temp[0];
result[3] = temp[1];
temp = Half.GetBytes(h.Z);
result[4] = temp[0];
result[5] = temp[1];
return result;
}
/// <summary>Converts an array of bytes into Half3.</summary>
/// <param name="value">A Half3 in it's byte[] representation.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A new Half3 instance.</returns>
public static Vector3h FromBytes(byte[] value, int startIndex)
{
Vector3h h3 = new Vector3h();
h3.X = Half.FromBytes(value, startIndex);
h3.Y = Half.FromBytes(value, startIndex + 2);
h3.Z = Half.FromBytes(value, startIndex + 4);
return h3;
}
#endregion BitConverter
}
}

View file

@ -0,0 +1,997 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
namespace OpenTK.Math
{
/// <summary>Represents a 4D vector using four single-precision floating-point numbers.</summary>
/// <remarks>
/// The Vector4 structure is suitable for interoperation with unmanaged code requiring four consecutive floats.
/// </remarks>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector4 : IEquatable<Vector4>
{
#region Fields
/// <summary>
/// The X component of the Vector4.
/// </summary>
public float X;
/// <summary>
/// The Y component of the Vector4.
/// </summary>
public float Y;
/// <summary>
/// The Z component of the Vector4.
/// </summary>
public float Z;
/// <summary>
/// The W component of the Vector4.
/// </summary>
public float W;
/// <summary>
/// Defines a unit-length Vector4 that points towards the X-axis.
/// </summary>
public static Vector4 UnitX = new Vector4(1, 0, 0, 0);
/// <summary>
/// Defines a unit-length Vector4 that points towards the Y-axis.
/// </summary>
public static Vector4 UnitY = new Vector4(0, 1, 0, 0);
/// <summary>
/// Defines a unit-length Vector4 that points towards the Z-axis.
/// </summary>
public static Vector4 UnitZ = new Vector4(0, 0, 1, 0);
/// <summary>
/// Defines a unit-length Vector4 that points towards the W-axis.
/// </summary>
public static Vector4 UnitW = new Vector4(0, 0, 0, 1);
/// <summary>
/// Defines a zero-length Vector4.
/// </summary>
public static Vector4 Zero = new Vector4(0, 0, 0, 0);
/// <summary>
/// Defines an instance with all components set to 1.
/// </summary>
public static readonly Vector4 One = new Vector4(1, 1, 1, 1);
/// <summary>
/// Defines the size of the Vector4 struct in bytes.
/// </summary>
public static readonly int SizeInBytes = Marshal.SizeOf(new Vector4());
#endregion
#region Constructors
/// <summary>
/// Constructs a new Vector4.
/// </summary>
/// <param name="x">The x component of the Vector4.</param>
/// <param name="y">The y component of the Vector4.</param>
/// <param name="z">The z component of the Vector4.</param>
/// <param name="w">The z component of the Vector4.</param>
public Vector4(float x, float y, float z, float w)
{
X = x;
Y = y;
Z = z;
W = w;
}
/// <summary>
/// Constructs a new Vector4 from the given Vector2.
/// </summary>
/// <param name="v">The Vector2 to copy components from.</param>
public Vector4(Vector2 v)
{
X = v.X;
Y = v.Y;
Z = 0.0f;
W = 0.0f;
}
/// <summary>
/// Constructs a new Vector4 from the given Vector3.
/// </summary>
/// <param name="v">The Vector3 to copy components from.</param>
public Vector4(Vector3 v)
{
X = v.X;
Y = v.Y;
Z = v.Z;
W = 0.0f;
}
/// <summary>
/// Constructs a new Vector4 from the specified Vector3 and W component.
/// </summary>
/// <param name="v">The Vector3 to copy components from.</param>
/// <param name="w">The W component of the new Vector4.</param>
public Vector4(Vector3 v, float w)
{
X = v.X;
Y = v.Y;
Z = v.Z;
W = w;
}
/// <summary>
/// Constructs a new Vector4 from the given Vector4.
/// </summary>
/// <param name="v">The Vector4 to copy components from.</param>
public Vector4(Vector4 v)
{
X = v.X;
Y = v.Y;
Z = v.Z;
W = v.W;
}
#endregion
#region Public Members
#region Instance
#region public void Add()
/// <summary>Add the Vector passed as parameter to this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
public void Add( Vector4 right )
{
this.X += right.X;
this.Y += right.Y;
this.Z += right.Z;
this.W += right.W;
}
/// <summary>Add the Vector passed as parameter to this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
[CLSCompliant(false)]
public void Add( ref Vector4 right )
{
this.X += right.X;
this.Y += right.Y;
this.Z += right.Z;
this.W += right.W;
}
#endregion public void Add()
#region public void Sub()
/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
public void Sub( Vector4 right )
{
this.X -= right.X;
this.Y -= right.Y;
this.Z -= right.Z;
this.W -= right.W;
}
/// <summary>Subtract the Vector passed as parameter from this instance.</summary>
/// <param name="right">Right operand. This parameter is only read from.</param>
[CLSCompliant(false)]
public void Sub( ref Vector4 right )
{
this.X -= right.X;
this.Y -= right.Y;
this.Z -= right.Z;
this.W -= right.W;
}
#endregion public void Sub()
#region public void Mult()
/// <summary>Multiply this instance by a scalar.</summary>
/// <param name="f">Scalar operand.</param>
public void Mult( float f )
{
this.X *= f;
this.Y *= f;
this.Z *= f;
this.W *= f;
}
#endregion public void Mult()
#region public void Div()
/// <summary>Divide this instance by a scalar.</summary>
/// <param name="f">Scalar operand.</param>
public void Div( float f )
{
float mult = 1.0f / f;
this.X *= mult;
this.Y *= mult;
this.Z *= mult;
this.W *= mult;
}
#endregion public void Div()
#region public float Length
/// <summary>
/// Gets the length (magnitude) of the vector.
/// </summary>
/// <see cref="LengthFast"/>
/// <seealso cref="LengthSquared"/>
public float Length
{
get
{
return (float)System.Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
}
}
#endregion
#region public float LengthFast
/// <summary>
/// Gets an approximation of the vector length (magnitude).
/// </summary>
/// <remarks>
/// This property uses an approximation of the square root function to calculate vector magnitude, with
/// an upper error bound of 0.001.
/// </remarks>
/// <see cref="Length"/>
/// <seealso cref="LengthSquared"/>
public float LengthFast
{
get
{
return 1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
}
}
#endregion
#region public float LengthSquared
/// <summary>
/// Gets the square of the vector length (magnitude).
/// </summary>
/// <remarks>
/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
/// for comparisons.
/// </remarks>
/// <see cref="Length"/>
/// <seealso cref="LengthFast"/>
public float LengthSquared
{
get
{
return X * X + Y * Y + Z * Z + W * W;
}
}
#endregion
#region public void Normalize()
/// <summary>
/// Scales the Vector4 to unit length.
/// </summary>
public void Normalize()
{
float scale = 1.0f / this.Length;
X *= scale;
Y *= scale;
Z *= scale;
W *= scale;
}
#endregion
#region public void NormalizeFast()
/// <summary>
/// Scales the Vector4 to approximately unit length.
/// </summary>
public void NormalizeFast()
{
float scale = Functions.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
X *= scale;
Y *= scale;
Z *= scale;
W *= scale;
}
#endregion
#region public void Scale()
/// <summary>
/// Scales the current Vector4 by the given amounts.
/// </summary>
/// <param name="sx">The scale of the X component.</param>
/// <param name="sy">The scale of the Y component.</param>
/// <param name="sz">The scale of the Z component.</param>
/// <param name="sw">The scale of the Z component.</param>
public void Scale( float sx, float sy, float sz, float sw )
{
this.X = X * sx;
this.Y = Y * sy;
this.Z = Z * sz;
this.W = W * sw;
}
/// <summary>Scales this instance by the given parameter.</summary>
/// <param name="scale">The scaling of the individual components.</param>
public void Scale( Vector4 scale )
{
this.X *= scale.X;
this.Y *= scale.Y;
this.Z *= scale.Z;
this.W *= scale.W;
}
/// <summary>Scales this instance by the given parameter.</summary>
/// <param name="scale">The scaling of the individual components.</param>
[CLSCompliant(false)]
public void Scale( ref Vector4 scale )
{
this.X *= scale.X;
this.Y *= scale.Y;
this.Z *= scale.Z;
this.W *= scale.W;
}
#endregion public void Scale()
#endregion
#region Static
#region Add
/// <summary>
/// Add two Vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>Result of addition</returns>
public static Vector4 Add(Vector4 a, Vector4 b)
{
a.X += b.X;
a.Y += b.Y;
a.Z += b.Z;
a.W += b.W;
return a;
}
/// <summary>
/// Add two Vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">Result of addition</param>
public static void Add(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X + b.X;
result.Y = a.Y + b.Y;
result.Z = a.Z + b.Z;
result.W = a.W + b.W;
}
#endregion
#region Sub
/// <summary>
/// Subtract one Vector from another
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>Result of subtraction</returns>
public static Vector4 Sub(Vector4 a, Vector4 b)
{
a.X -= b.X;
a.Y -= b.Y;
a.Z -= b.Z;
a.W -= b.W;
return a;
}
/// <summary>
/// Subtract one Vector from another
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">Result of subtraction</param>
public static void Sub(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X - b.X;
result.Y = a.Y - b.Y;
result.Z = a.Z - b.Z;
result.W = a.W - b.W;
}
#endregion
#region Mult
/// <summary>
/// Multiply a vector and a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <returns>Result of the multiplication</returns>
public static Vector4 Mult(Vector4 a, float f)
{
a.X *= f;
a.Y *= f;
a.Z *= f;
a.W *= f;
return a;
}
/// <summary>
/// Multiply a vector and a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <param name="result">Result of the multiplication</param>
public static void Mult(ref Vector4 a, float f, out Vector4 result)
{
result.X = a.X * f;
result.Y = a.Y * f;
result.Z = a.Z * f;
result.W = a.W * f;
}
#endregion
#region Div
/// <summary>
/// Divide a vector by a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <returns>Result of the division</returns>
public static Vector4 Div(Vector4 a, float f)
{
float mult = 1.0f / f;
a.X *= mult;
a.Y *= mult;
a.Z *= mult;
a.W *= mult;
return a;
}
/// <summary>
/// Divide a vector by a scalar
/// </summary>
/// <param name="a">Vector operand</param>
/// <param name="f">Scalar operand</param>
/// <param name="result">Result of the division</param>
public static void Div(ref Vector4 a, float f, out Vector4 result)
{
float mult = 1.0f / f;
result.X = a.X * mult;
result.Y = a.Y * mult;
result.Z = a.Z * mult;
result.W = a.W * mult;
}
#endregion
#region Min
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise minimum</returns>
public static Vector4 Min(Vector4 a, Vector4 b)
{
a.X = a.X < b.X ? a.X : b.X;
a.Y = a.Y < b.Y ? a.Y : b.Y;
a.Z = a.Z < b.Z ? a.Z : b.Z;
a.W = a.W < b.W ? a.W : b.W;
return a;
}
/// <summary>
/// Calculate the component-wise minimum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise minimum</param>
public static void Min(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X < b.X ? a.X : b.X;
result.Y = a.Y < b.Y ? a.Y : b.Y;
result.Z = a.Z < b.Z ? a.Z : b.Z;
result.W = a.W < b.W ? a.W : b.W;
}
#endregion
#region Max
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <returns>The component-wise maximum</returns>
public static Vector4 Max(Vector4 a, Vector4 b)
{
a.X = a.X > b.X ? a.X : b.X;
a.Y = a.Y > b.Y ? a.Y : b.Y;
a.Z = a.Z > b.Z ? a.Z : b.Z;
a.W = a.W > b.W ? a.W : b.W;
return a;
}
/// <summary>
/// Calculate the component-wise maximum of two vectors
/// </summary>
/// <param name="a">First operand</param>
/// <param name="b">Second operand</param>
/// <param name="result">The component-wise maximum</param>
public static void Max(ref Vector4 a, ref Vector4 b, out Vector4 result)
{
result.X = a.X > b.X ? a.X : b.X;
result.Y = a.Y > b.Y ? a.Y : b.Y;
result.Z = a.Z > b.Z ? a.Z : b.Z;
result.W = a.W > b.W ? a.W : b.W;
}
#endregion
#region Clamp
/// <summary>
/// Clamp a vector to the given minimum and maximum vectors
/// </summary>
/// <param name="vec">Input vector</param>
/// <param name="min">Minimum vector</param>
/// <param name="max">Maximum vector</param>
/// <returns>The clamped vector</returns>
public static Vector4 Clamp(Vector4 vec, Vector4 min, Vector4 max)
{
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
vec.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
vec.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
return vec;
}
/// <summary>
/// Clamp a vector to the given minimum and maximum vectors
/// </summary>
/// <param name="vec">Input vector</param>
/// <param name="min">Minimum vector</param>
/// <param name="max">Maximum vector</param>
/// <param name="result">The clamped vector</param>
public static void Clamp(ref Vector4 vec, ref Vector4 min, ref Vector4 max, out Vector4 result)
{
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
result.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
result.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
}
#endregion
#region Normalize
/// <summary>
/// Scale a vector to unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <returns>The normalized vector</returns>
public static Vector4 Normalize(Vector4 vec)
{
float scale = 1.0f / vec.Length;
vec.X *= scale;
vec.Y *= scale;
vec.Z *= scale;
vec.W *= scale;
return vec;
}
/// <summary>
/// Scale a vector to unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <param name="result">The normalized vector</param>
public static void Normalize(ref Vector4 vec, out Vector4 result)
{
float scale = 1.0f / vec.Length;
result.X = vec.X * scale;
result.Y = vec.Y * scale;
result.Z = vec.Z * scale;
result.W = vec.W * scale;
}
#endregion
#region NormalizeFast
/// <summary>
/// Scale a vector to approximately unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <returns>The normalized vector</returns>
public static Vector4 NormalizeFast(Vector4 vec)
{
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
vec.X *= scale;
vec.Y *= scale;
vec.Z *= scale;
vec.W *= scale;
return vec;
}
/// <summary>
/// Scale a vector to approximately unit length
/// </summary>
/// <param name="vec">The input vector</param>
/// <param name="result">The normalized vector</param>
public static void NormalizeFast(ref Vector4 vec, out Vector4 result)
{
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
result.X = vec.X * scale;
result.Y = vec.Y * scale;
result.Z = vec.Z * scale;
result.W = vec.W * scale;
}
#endregion
#region Dot
/// <summary>
/// Calculate the dot product of two vectors
/// </summary>
/// <param name="left">First operand</param>
/// <param name="right">Second operand</param>
/// <returns>The dot product of the two inputs</returns>
public static float Dot(Vector4 left, Vector4 right)
{
return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
}
/// <summary>
/// Calculate the dot product of two vectors
/// </summary>
/// <param name="left">First operand</param>
/// <param name="right">Second operand</param>
/// <param name="result">The dot product of the two inputs</param>
public static void Dot( ref Vector4 left, ref Vector4 right, out float result )
{
result = left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
}
#endregion
#region Lerp
/// <summary>
/// Returns a new Vector that is the linear blend of the 2 given Vectors
/// </summary>
/// <param name="a">First input vector</param>
/// <param name="b">Second input vector</param>
/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
public static Vector4 Lerp(Vector4 a, Vector4 b, float blend)
{
a.X = blend * (b.X - a.X) + a.X;
a.Y = blend * (b.Y - a.Y) + a.Y;
a.Z = blend * (b.Z - a.Z) + a.Z;
a.W = blend * (b.W - a.W) + a.W;
return a;
}
/// <summary>
/// Returns a new Vector that is the linear blend of the 2 given Vectors
/// </summary>
/// <param name="a">First input vector</param>
/// <param name="b">Second input vector</param>
/// <param name="blend">The blend factor. a when blend=0, b when blend=1.</param>
/// <param name="result">a when blend=0, b when blend=1, and a linear combination otherwise</param>
public static void Lerp( ref Vector4 a, ref Vector4 b, float blend, out Vector4 result )
{
result.X = blend * ( b.X - a.X ) + a.X;
result.Y = blend * ( b.Y - a.Y ) + a.Y;
result.Z = blend * ( b.Z - a.Z ) + a.Z;
result.W = blend * ( b.W - a.W ) + a.W;
}
#endregion
#region Barycentric
/// <summary>
/// Interpolate 3 Vectors using Barycentric coordinates
/// </summary>
/// <param name="a">First input Vector</param>
/// <param name="b">Second input Vector</param>
/// <param name="c">Third input Vector</param>
/// <param name="u">First Barycentric Coordinate</param>
/// <param name="v">Second Barycentric Coordinate</param>
/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
public static Vector4 BaryCentric(Vector4 a, Vector4 b, Vector4 c, float u, float v)
{
return a + u * (b - a) + v * (c - a);
}
/// <summary>Interpolate 3 Vectors using Barycentric coordinates</summary>
/// <param name="a">First input Vector.</param>
/// <param name="b">Second input Vector.</param>
/// <param name="c">Third input Vector.</param>
/// <param name="u">First Barycentric Coordinate.</param>
/// <param name="v">Second Barycentric Coordinate.</param>
/// <param name="result">Output Vector. a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</param>
public static void BaryCentric( ref Vector4 a, ref Vector4 b, ref Vector4 c, float u, float v, out Vector4 result )
{
result = a; // copy
Vector4 temp = b; // copy
temp.Sub( ref a );
temp.Mult( u );
result.Add( ref temp );
temp = c; // copy
temp.Sub( ref a );
temp.Mult( v );
result.Add( ref temp );
}
#endregion
#region Transform
/// <summary>Transform a Vector by the given Matrix</summary>
/// <param name="vec">The vector to transform</param>
/// <param name="mat">The desired transformation</param>
/// <returns>The transformed vector</returns>
public static Vector4 Transform(Vector4 vec, Matrix4 mat)
{
Vector4 result;
result.X = Vector4.Dot(vec, mat.Column0);
result.Y = Vector4.Dot(vec, mat.Column1);
result.Z = Vector4.Dot(vec, mat.Column2);
result.W = Vector4.Dot(vec, mat.Column3);
return result;
}
/// <summary>Transform a Vector by the given Matrix</summary>
/// <param name="vec">The vector to transform</param>
/// <param name="mat">The desired transformation</param>
/// <param name="result">The transformed vector</param>
public static void Transform( ref Vector4 vec, ref Matrix4 mat, out Vector4 result )
{
result.X = vec.X * mat.Row0.X +
vec.Y * mat.Row1.X +
vec.Z * mat.Row2.X +
vec.W * mat.Row3.X;
result.Y = vec.X * mat.Row0.Y +
vec.Y * mat.Row1.Y +
vec.Z * mat.Row2.Y +
vec.W * mat.Row3.Y;
result.Z = vec.X * mat.Row0.Z +
vec.Y * mat.Row1.Z +
vec.Z * mat.Row2.Z +
vec.W * mat.Row3.Z;
result.W = vec.X * mat.Row0.W +
vec.Y * mat.Row1.W +
vec.Z * mat.Row2.W +
vec.W * mat.Row3.W;
}
#endregion
#endregion
#region Swizzle
/// <summary>
/// Gets or sets an OpenTK.Vector2 with the X and Y components of this instance.
/// </summary>
[XmlIgnore]
public Vector2 Xy { get { return new Vector2(X, Y); } set { X = value.X; Y = value.Y; } }
/// <summary>
/// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance.
/// </summary>
[XmlIgnore]
public Vector3 Xyz { get { return new Vector3(X, Y, Z); } set { X = value.X; Y = value.Y; Z = value.Z; } }
#endregion
#region Operators
public static Vector4 operator +(Vector4 left, Vector4 right)
{
left.X += right.X;
left.Y += right.Y;
left.Z += right.Z;
left.W += right.W;
return left;
}
public static Vector4 operator -(Vector4 left, Vector4 right)
{
left.X -= right.X;
left.Y -= right.Y;
left.Z -= right.Z;
left.W -= right.W;
return left;
}
public static Vector4 operator -(Vector4 vec)
{
vec.X = -vec.X;
vec.Y = -vec.Y;
vec.Z = -vec.Z;
vec.W = -vec.W;
return vec;
}
public static Vector4 operator *(Vector4 vec, float f)
{
vec.X *= f;
vec.Y *= f;
vec.Z *= f;
vec.W *= f;
return vec;
}
public static Vector4 operator *(float f, Vector4 vec)
{
vec.X *= f;
vec.Y *= f;
vec.Z *= f;
vec.W *= f;
return vec;
}
public static Vector4 operator /(Vector4 vec, float f)
{
float mult = 1.0f / f;
vec.X *= mult;
vec.Y *= mult;
vec.Z *= mult;
vec.W *= mult;
return vec;
}
public static bool operator ==(Vector4 left, Vector4 right)
{
return left.Equals(right);
}
public static bool operator !=(Vector4 left, Vector4 right)
{
return !left.Equals(right);
}
[CLSCompliant(false)]
unsafe public static explicit operator float*(Vector4 v)
{
return &v.X;
}
public static explicit operator IntPtr(Vector4 v)
{
unsafe
{
return (IntPtr)(&v.X);
}
}
#endregion
#region Overrides
#region public override string ToString()
/// <summary>
/// Returns a System.String that represents the current Vector4.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("({0}, {1}, {2}, {3})", X, Y, Z, W);
}
#endregion
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector4))
return false;
return this.Equals((Vector4)obj);
}
#endregion
#endregion
#endregion
#region IEquatable<Vector4> Members
/// <summary>Indicates whether the current vector is equal to another vector.</summary>
/// <param name="other">A vector to compare with this vector.</param>
/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
public bool Equals(Vector4 other)
{
return
X == other.X &&
Y == other.Y &&
Z == other.Z &&
W == other.W;
}
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,414 @@
#region --- License ---
/*
Copyright (c) 2006 - 2008 The Open Toolkit library.
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
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Xml.Serialization;
namespace OpenTK.Math
{
/// <summary>
/// 4-component Vector of the Half type. Occupies 8 Byte total.
/// </summary>
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Vector4h : ISerializable, IEquatable<Vector4h>
{
#region Public Fields
/// <summary>The X component of the Half4.</summary>
public Half X;
/// <summary>The Y component of the Half4.</summary>
public Half Y;
/// <summary>The Z component of the Half4.</summary>
public Half Z;
/// <summary>The W component of the Half4.</summary>
public Half W;
#endregion Public Fields
#region Constructors
/// <summary>
/// The new Half4 instance will avoid conversion and copy directly from the Half parameters.
/// </summary>
/// <param name="x">An Half instance of a 16-Bit half precision floating point number.</param>
/// <param name="y">An Half instance of a 16-Bit half precision floating point number.</param>
/// <param name="z">An Half instance of a 16-Bit half precision floating point number.</param>
/// <param name="w">An Half instance of a 16-Bit half precision floating point number.</param>
public Vector4h(Half x, Half y, Half z, Half w)
{
this.X = x;
this.Y = y;
this.Z = z;
this.W = w;
}
/// <summary>
/// The new Half4 instance will convert the 4 parameters into 16-Bit Half precision floating point.
/// </summary>
/// <param name="x">32-Bit Single precision floating point number.</param>
/// <param name="y">32-Bit Single precision floating point number.</param>
/// <param name="z">32-Bit Single precision floating point number.</param>
/// <param name="w">32-Bit Single precision floating point number.</param>
public Vector4h(Single x, Single y, Single z, Single w)
{
X = new Half(x);
Y = new Half(y);
Z = new Half(z);
W = new Half(w);
}
/// <summary>
/// The new Half4 instance will convert the 4 parameters into 16-Bit Half precision floating point.
/// </summary>
/// <param name="x">32-Bit Single precision floating point number.</param>
/// <param name="y">32-Bit Single precision floating point number.</param>
/// <param name="z">32-Bit Single precision floating point number.</param>
/// <param name="w">32-Bit Single precision floating point number.</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector4h(Single x, Single y, Single z, Single w, bool throwOnError)
{
X = new Half(x, throwOnError);
Y = new Half(y, throwOnError);
Z = new Half(z, throwOnError);
W = new Half(w, throwOnError);
}
/// <summary>
/// The new Half4 instance will convert the Vector4 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector4</param>
[CLSCompliant(false)]
public Vector4h(Vector4 v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
W = new Half(v.W);
}
/// <summary>
/// The new Half4 instance will convert the Vector4 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector4</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
[CLSCompliant(false)]
public Vector4h(Vector4 v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
W = new Half(v.W, throwOnError);
}
/// <summary>
/// The new Half4 instance will convert the Vector4 into 16-Bit Half precision floating point.
/// This is the fastest constructor.
/// </summary>
/// <param name="v">OpenTK.Vector4</param>
public Vector4h(ref Vector4 v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
W = new Half(v.W);
}
/// <summary>
/// The new Half4 instance will convert the Vector4 into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector4</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector4h(ref Vector4 v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
W = new Half(v.W, throwOnError);
}
/// <summary>
/// The new Half4 instance will convert the Vector4d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector4d</param>
public Vector4h(Vector4d v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
W = new Half(v.W);
}
/// <summary>
/// The new Half4 instance will convert the Vector4d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector4d</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
public Vector4h(Vector4d v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
W = new Half(v.W, throwOnError);
}
/// <summary>
/// The new Half4 instance will convert the Vector4d into 16-Bit Half precision floating point.
/// This is the faster constructor.
/// </summary>
/// <param name="v">OpenTK.Vector4d</param>
[CLSCompliant(false)]
public Vector4h(ref Vector4d v)
{
X = new Half(v.X);
Y = new Half(v.Y);
Z = new Half(v.Z);
W = new Half(v.W);
}
/// <summary>
/// The new Half4 instance will convert the Vector4d into 16-Bit Half precision floating point.
/// </summary>
/// <param name="v">OpenTK.Vector4d</param>
/// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param>
[CLSCompliant(false)]
public Vector4h(ref Vector4d v, bool throwOnError)
{
X = new Half(v.X, throwOnError);
Y = new Half(v.Y, throwOnError);
Z = new Half(v.Z, throwOnError);
W = new Half(v.W, throwOnError);
}
#endregion Constructors
#region Swizzle
/// <summary>
/// Gets or sets an OpenTK.Vector2h with the X and Y components of this instance.
/// </summary>
[XmlIgnore]
public Vector2h Xy { get { return new Vector2h(X, Y); } set { X = value.X; Y = value.Y; } }
/// <summary>
/// Gets or sets an OpenTK.Vector3h with the X, Y and Z components of this instance.
/// </summary>
[XmlIgnore]
public Vector3h Xyz { get { return new Vector3h(X, Y, Z); } set { X = value.X; Y = value.Y; Z = value.Z; } }
#endregion
#region Half -> Single
/// <summary>
/// Returns this Half4 instance's contents as Vector4.
/// </summary>
/// <returns>OpenTK.Vector4</returns>
public Vector4 ToVector4()
{
return new Vector4(X, Y, Z, W);
}
/// <summary>
/// Returns this Half4 instance's contents as Vector4d.
/// </summary>
public Vector4d ToVector4d()
{
return new Vector4d(X, Y, Z, W);
}
#endregion Half -> Single
#region Conversions
/// <summary>Converts OpenTK.Vector4 to OpenTK.Half4.</summary>
/// <param name="v4f">The Vector4 to convert.</param>
/// <returns>The resulting Half vector.</returns>
public static explicit operator Vector4h(Vector4 v4f)
{
return new Vector4h(v4f);
}
/// <summary>Converts OpenTK.Vector4d to OpenTK.Half4.</summary>
/// <param name="v4d">The Vector4d to convert.</param>
/// <returns>The resulting Half vector.</returns>
public static explicit operator Vector4h(Vector4d v4d)
{
return new Vector4h(v4d);
}
/// <summary>Converts OpenTK.Half4 to OpenTK.Vector4.</summary>
/// <param name="h4">The Half4 to convert.</param>
/// <returns>The resulting Vector4.</returns>
public static explicit operator Vector4(Vector4h h4)
{
Vector4 result = new Vector4();
result.X = h4.X.ToSingle();
result.Y = h4.Y.ToSingle();
result.Z = h4.Z.ToSingle();
result.W = h4.W.ToSingle();
return result;
}
/// <summary>Converts OpenTK.Half4 to OpenTK.Vector4d.</summary>
/// <param name="h4">The Half4 to convert.</param>
/// <returns>The resulting Vector4d.</returns>
public static explicit operator Vector4d(Vector4h h4)
{
Vector4d result = new Vector4d();
result.X = h4.X.ToSingle();
result.Y = h4.Y.ToSingle();
result.Z = h4.Z.ToSingle();
result.W = h4.W.ToSingle();
return result;
}
#endregion Conversions
#region Constants
/// <summary>The size in bytes for an instance of the Half4 struct is 8.</summary>
public static readonly int SizeInBytes = 8;
#endregion Constants
#region ISerializable
/// <summary>Constructor used by ISerializable to deserialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public Vector4h(SerializationInfo info, StreamingContext context)
{
this.X = (Half)info.GetValue("X", typeof(Half));
this.Y = (Half)info.GetValue("Y", typeof(Half));
this.Z = (Half)info.GetValue("Z", typeof(Half));
this.W = (Half)info.GetValue("W", typeof(Half));
}
/// <summary>Used by ISerialize to serialize the object.</summary>
/// <param name="info"></param>
/// <param name="context"></param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("X", this.X);
info.AddValue("Y", this.Y);
info.AddValue("Z", this.Z);
info.AddValue("W", this.W);
}
#endregion ISerializable
#region Binary dump
/// <summary>Updates the X,Y,Z and W components of this instance by reading from a Stream.</summary>
/// <param name="bin">A BinaryReader instance associated with an open Stream.</param>
public void FromBinaryStream(BinaryReader bin)
{
X.FromBinaryStream(bin);
Y.FromBinaryStream(bin);
Z.FromBinaryStream(bin);
W.FromBinaryStream(bin);
}
/// <summary>Writes the X,Y,Z and W components of this instance into a Stream.</summary>
/// <param name="bin">A BinaryWriter instance associated with an open Stream.</param>
public void ToBinaryStream(BinaryWriter bin)
{
X.ToBinaryStream(bin);
Y.ToBinaryStream(bin);
Z.ToBinaryStream(bin);
W.ToBinaryStream(bin);
}
#endregion Binary dump
#region IEquatable<Half4> Members
/// <summary>Returns a value indicating whether this instance is equal to a specified OpenTK.Half4 vector.</summary>
/// <param name="other">OpenTK.Half4 to compare to this instance..</param>
/// <returns>True, if other is equal to this instance; false otherwise.</returns>
public bool Equals(Vector4h other)
{
return (this.X.Equals(other.X) && this.Y.Equals(other.Y) && this.Z.Equals(other.Z) && this.W.Equals(other.W));
}
#endregion
#region ToString()
/// <summary>Returns a string that contains this Half4's numbers in human-legible form.</summary>
public override string ToString()
{
return String.Format("({0}, {1}, {2}, {3})", X.ToString(), Y.ToString(), Z.ToString(), W.ToString());
}
#endregion ToString()
#region BitConverter
/// <summary>Returns the Half4 as an array of bytes.</summary>
/// <param name="h">The Half4 to convert.</param>
/// <returns>The input as byte array.</returns>
public static byte[] GetBytes(Vector4h h)
{
byte[] result = new byte[SizeInBytes];
byte[] temp = Half.GetBytes(h.X);
result[0] = temp[0];
result[1] = temp[1];
temp = Half.GetBytes(h.Y);
result[2] = temp[0];
result[3] = temp[1];
temp = Half.GetBytes(h.Z);
result[4] = temp[0];
result[5] = temp[1];
temp = Half.GetBytes(h.W);
result[6] = temp[0];
result[7] = temp[1];
return result;
}
/// <summary>Converts an array of bytes into Half4.</summary>
/// <param name="value">A Half4 in it's byte[] representation.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A new Half4 instance.</returns>
public static Vector4h FromBytes(byte[] value, int startIndex)
{
Vector4h h4 = new Vector4h();
h4.X = Half.FromBytes(value, startIndex);
h4.Y = Half.FromBytes(value, startIndex + 2);
h4.Z = Half.FromBytes(value, startIndex + 4);
h4.W = Half.FromBytes(value, startIndex + 6);
return h4;
}
#endregion BitConverter
}
}

View file

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("The Open Toolkit Compatilibity library")]
[assembly: AssemblyDescription("Provides compatibility with previous versions of OpenTK")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("The Open Toolkit Library")]
[assembly: AssemblyProduct("The Open Toolkit Library")]
[assembly: AssemblyCopyright("Copyright © 2006-2009 the Open Toolkit team")]
[assembly: AssemblyTrademark("OpenTK")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7c495044-4b1a-4bff-aee9-ff9dbf85433f")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("0.9.9.2")]
[assembly: AssemblyFileVersion("0.9.9.2")]
[assembly: System.CLSCompliant(true)]