///// <summary>
        ///// Builds this quaternion from an axis-angle pair
        ///// </summary>
        ///// <param name="vec">Rotation vector</param>
        ///// <param name="angle">Rotation angle (in radians)</param>
        //public Quaternion( Vector3 vec, float angle )
        //{
        //    //	TODO: AP: ...
        //}
        /// <summary>
        /// Builds this quaternion from the rotation part of a transform matrix
        /// </summary>
        public Quaternion( Matrix44 matrix )
        {
            // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
            // article "Quaternion Calculus and Fast Animation".

            float trace = matrix[ 0, 0 ] + matrix[ 1, 1 ] + matrix[ 2, 2 ];
            float root;

            if ( trace > 0.0f )
            {
                // |w| > 1/2, may as well choose w > 1/2
                root = Functions.Sqrt( trace + 1.0f );  // 2w
                m_W = 0.5f * root;
                root = 0.5f / root;  // 1/(4w)
                m_X = ( matrix[ 2, 1 ] - matrix[ 1, 2 ] ) * root;
                m_Y = ( matrix[ 0, 2 ] - matrix[ 2, 0 ] ) * root;
                m_Z = ( matrix[ 1, 0 ] - matrix[ 0, 1 ] ) * root;
            }
            else
            {
                // |w| <= 1/2
                int i = 0;
                if ( matrix[ 1, 1 ] > matrix[ 0, 0 ] )
                {
                    i = 1;
                }
                if ( matrix[ 2, 2 ] > matrix[ i, i ] )
                {
                    i = 2;
                }
                int j = ( i + 1 ) % 3;
                int k = ( j + 1 ) % 3;

                root = Functions.Sqrt( matrix[ i, i ] - matrix[ j, j ] - matrix[ k, k ] + 1.0f );

                Point3 quat = new Point3( );
                quat[ i ] = 0.5f * root;
                root = 0.5f / root;
                m_W = ( matrix[ k, j ] - matrix[ j, k ] ) * root;
                quat[ j ] = ( matrix[ j, i ] + matrix[ i, j ] ) * root;
                quat[ k ] = ( matrix[ k, i ] + matrix[ i, k ] ) * root;

                m_X = quat.X;
                m_Y = quat.Y;
                m_Z = quat.Z;
            }
        }
 /// <summary>
 /// Sets up the renderer
 /// </summary>
 /// <param name="mainRenderingThread">Main rendering thread</param>
 /// <param name="mainRenderingThreadMarshaller">Marshaller for the main rendering thread</param>
 /// <remarks>
 /// OpenGL works within a single thread, and any resources (textures, display lists,...) must
 /// be created and destroyed on the same thread.
 ///  </remarks>
 public OpenGlRenderer( Thread mainRenderingThread, DelegateMarshaller mainRenderingThreadMarshaller )
     : base(mainRenderingThread, mainRenderingThreadMarshaller)
 {
     for ( int stackIndex = 0; stackIndex < m_LocalToWorldModifierStack.Length; ++stackIndex )
     {
         m_LocalToWorldModifierStack[ stackIndex ] = InvariantMatrix44.Identity;
     }
     for ( int stackIndex = 0; stackIndex < m_WorldToViewModifierStack.Length; ++stackIndex )
     {
         m_WorldToViewModifierStack[ stackIndex ] = InvariantMatrix44.Identity;
     }
     for ( int stackIndex = 0; stackIndex < m_LocalToWorldStack.Length; ++stackIndex )
     {
         m_LocalToWorldStack[ stackIndex ] = new Matrix44( );
     }
     for ( int stackIndex = 0; stackIndex < m_WorldToViewStack.Length; ++stackIndex )
     {
         m_WorldToViewStack[ stackIndex ] = new Matrix44( );
     }
 }
        /// <summary>
        /// Renders the entity
        /// </summary>
        /// <param name="context">Rendering context</param>
        public override void Render( IRenderContext context )
        {
            //	Get the interpolated position of the entity
            float t = ( float )( context.RenderTime - m_Position.LastStepTime ) / m_Position.LastStepInterval;
            Point3 curPos = m_Position.UpdateCurrent( t );

            //	TODO: Get the interpolated rotation of the entity

            //	Push the entity transform
            Matrix44 mat = new Matrix44( curPos, Left, Up, Ahead );

            Rb.Rendering.Graphics.Renderer.PushTransform( TransformType.LocalToWorld, mat );

            base.Render( context );

            //	Pop the entity transform
            Rb.Rendering.Graphics.Renderer.PopTransform( TransformType.LocalToWorld );
        }
 //    TODO: AP: Add rotation code
 /// <summary>
 /// Translation. Stores the result of this * T, where T is the translation matrix for (x,y,z)
 /// </summary>
 public void Translate( float x, float y, float z )
 {
     //	TODO: This is pretty lazy :)
     Matrix44 lhs = new Matrix44( this );
     Matrix44 rhs = new Matrix44( 1, 0, 0, 0,
                                  0, 1, 0, 0,
                                  0, 0, 1, 0,
                                  x, y, z, 1 );
     StoreMultiply( lhs, rhs );
 }
 /// <summary>
 /// Stores the result of multiplying this * rhs in this matrix
 /// </summary>
 public void StoreMultiply( Matrix44 rhs )
 {
     //	TODO: CHEATER!
     Matrix44 tmp = new Matrix44( this );
     StoreMultiply( tmp, rhs );
 }
 /// <summary>
 /// Stores the inverse of mat (mat.mat'=I) in this matrix
 /// </summary>
 /// <remarks>
 /// The generic inverse of a matrix A is found by dividing the adjoint of A by the determinant of A. The adjoint B of a matrix A is
 /// defined by B=bij, where bij is the determinant of A with row i and column j removed (the co-factors of A).
 /// I was too lazy to fully expand the calculations this implies for a 4x4 matrix, so I grabbed and adapted the following code from
 /// http://www.geometrictools.com
 /// </remarks>
 public void StoreInverse( Matrix44 mat )
 {
     MakeInverse( this, mat );
 }
 /// <summary>
 /// Returns true if the two matrices are equal, within a given tolerance per element
 /// </summary>
 public bool IsCloseTo( Matrix44 mat, float tol )
 {
     for ( int index = 0; index < 16; ++index )
     {
         if ( Math.Abs( this[ index ] - mat[ index ] ) > tol )
         {
             return false;
         }
     }
     return true;
 }
 /// <summary>
 /// Makes a matrix from a quaternion
 /// </summary>
 public static new Matrix44 MakeTranslationMatrix( Point3 pt )
 {
     Matrix44 result = new Matrix44( );
     MakeTranslationMatrix( result, pt.X, pt.Y, pt.Z );
     return result;
 }
 /// <summary>
 /// Stores the reflection of src in result
 /// </summary>
 public static new Matrix44 MakeReflectionMatrix( Point3 pointOnPlane, Vector3 planeNormal )
 {
     Matrix44 result = new Matrix44( );
     MakeReflectionMatrix( ( InvariantMatrix44 )result, pointOnPlane, planeNormal );
     return result;
 }
示例#10
0
        /// <summary>
        /// Reads frame information
        /// </summary>
        private static void ReadFrames( BinaryReader reader, long offset, int numFrames, ModelMesh mesh, Matrix44 transform )
        {
            reader.BaseStream.Seek( offset, SeekOrigin.Begin );

            ModelMesh.FrameInfo[] frames = new ModelMesh.FrameInfo[ numFrames ];

            float scaleLength = ( transform * new Vector3( 1, 1, 1 ) ).Length;

            for ( int frameCount = 0; frameCount < numFrames; ++frameCount )
            {
                frames[ frameCount]		= new ModelMesh.FrameInfo( );
                ModelMesh.FrameInfo curFrame	= frames[ frameCount ];
                curFrame.MinBounds		= transform * ReadPoint( reader );
                curFrame.MaxBounds		= transform * ReadPoint( reader );
                curFrame.Origin			= transform * ReadPoint( reader );
                curFrame.Radius			= reader.ReadSingle( ) * scaleLength;
                curFrame.Name			= ReadString( reader, FrameNameLength );
            }

            mesh.FrameInfoList = frames;
        }
示例#11
0
        private static void LoadObjectModel( Model model, ISource source, Matrix44 transform )
        {
            //	Load the skin file for the current part
            IDictionary< string, ITexture2d > textureTable = LoadSkin( source, DefaultSkinFile( source, ModelPart.Weapon ) );

            //	Load the MD3 associated with the current part
            ModelMesh partMesh = LoadMd3( source, model, ModelPart.Weapon, transform, source, textureTable );
            model.SetPartMesh( ModelPart.Weapon, partMesh );
            model.SetRootMesh( partMesh );
        }
示例#12
0
        private static void LoadNestedModel( Model model, ISource source, Matrix44 transform )
        {
            //	Run through all the parts
            for ( int partIndex = 0; partIndex < ( int )ModelPart.NumParts; ++partIndex )
            {
                ModelPart curPart = ( ModelPart )partIndex;

                if ( curPart == ModelPart.Weapon )
                {
                    //	The weapon does not have a related mesh, so just ignore...
                    continue;
                }
                //	Load the skin file for the current part
                IDictionary< string, ITexture2d > surfaceTextureTable = LoadSkin( source, DefaultSkinFile( source, curPart ) );

                //	Load the MD3 associated with the current part
                ModelMesh partMesh = LoadMd3( source, model, curPart, transform, MeshFile( source, curPart ), surfaceTextureTable );
                model.SetPartMesh( curPart, partMesh );
            }

            model.SetRootMesh( model.GetPartMesh( ModelPart.Lower ) );
            NestMesh( model, ModelPart.Lower, ModelPart.Upper, "tag_torso" );
            NestMesh( model, ModelPart.Upper, ModelPart.Head, "tag_head" );
            NestMesh( model, ModelPart.Upper, ModelPart.Weapon, "tag_weapon" );
        }
示例#13
0
        /// <summary>
        /// Loads an MD3 mesh resource from a stream
        /// </summary>
        private static ModelMesh LoadMd3( ISource source, Model model, ModelPart part, Matrix44 transform, ISource md3Source, IDictionary<string, ITexture2d> surfaceTextureTable )
        {
            using ( Stream inputStream = OpenStream( md3Source ) )
            {
                BinaryReader reader = new BinaryReader( inputStream );

                //	http://icculus.org/homepages/phaethon/q3a/formats/md3format.html

                //	Make sure of the MD3 identity
                byte[] ident		= reader.ReadBytes( 4 );
                if ( ( ident[ 0 ] != 'I' ) || ( ident[ 1 ] != 'D' ) || ( ident[ 2 ] != 'P' ) || ( ident[ 3 ] != '3' ) )
                {
                    throw new ApplicationException( "Failed to load MD3 resource - stream did not start with 'IDP3' MD3 identifier" );
                }

                //	Read in header
                //int version			=
                reader.ReadInt32( );
                //string name			=
                ReadString( reader, MaxPathLength );
                //int flags			=
                reader.ReadInt32( );
                int numFrames		= reader.ReadInt32( );
                int numTags			= reader.ReadInt32( );
                int numSurfaces		= reader.ReadInt32( );
                //int numSkins		=
                reader.ReadInt32( );
                int framesOffset	= reader.ReadInt32( );
                int tagsOffset		= reader.ReadInt32( );
                int surfacesOffset	= reader.ReadInt32( );
                //int eofOffset		=
                reader.ReadInt32( );

                //	TODO: Can load directly into mesh frame, tag and surface structures - don't do this intermediate step
                ModelMesh mesh = new ModelMesh( model, part );

                ReadFrames( reader, framesOffset, numFrames, mesh, transform );
                ReadTags( reader, tagsOffset, numTags, numFrames, mesh, transform );
                ReadSurfaces( source, reader, surfacesOffset, numSurfaces, numFrames, mesh, surfaceTextureTable, transform );

                //	TODO: REMOVE. test frames
                string md3Name = md3Source.ToString( );
                if ( md3Name.IndexOf( "Upper" ) != -1 )
                {
                    mesh.DefaultFrame = 151;
                }
                else if ( md3Name.IndexOf( "Head" ) != -1 )
                {
                    mesh.DefaultFrame = 0;
                }
                else
                {
                    mesh.DefaultFrame = 0;
                }

                return mesh;
            }
        }
 /// <summary>
 /// Creates a quaternion from a matrix
 /// </summary>
 public static Quaternion FromMatrix( Matrix44 matrix )
 {
     return new Quaternion( matrix );
 }
        /// <summary>
        /// Renders reflections on the first <see cref="ReflectionPlane"/> found in the scene
        /// </summary>
        private void RenderPlanarReflections( ReflectionsRenderContext reflectionsContext, ICamera3 camera )
        {
            ReflectionPlane plane = ReflectionPlane;
            if ( plane == null )
            {
                return;
            }

            //	Matrix44 reflectionMatrix = Matrix44.MakeReflectionMatrix( new Point3( 0, -10, 0 ), new Vector3( 0, 1, 0 ) );
            Matrix44 reflectionMatrix = plane.CreateReflectionMatrix( );
            Matrix44 reflectedCameraMatrix = new Matrix44( camera.InverseFrame * reflectionMatrix );
            //	reflectedCameraMatrix.YAxis = -reflectedCameraMatrix.YAxis; // Restore handedness
            Graphics.Renderer.PushTransform( TransformType.WorldToView );
            Graphics.Renderer.SetTransform( TransformType.WorldToView, reflectedCameraMatrix );
            Graphics.Renderer.PushTransform( TransformType.ViewToScreen );
            IProjectionCamera projCamera = ( IProjectionCamera )camera;
            Graphics.Renderer.SetPerspectiveProjectionTransform( projCamera.PerspectiveFovDegrees, 1, projCamera.PerspectiveZNear, projCamera.PerspectiveZFar );

            m_ReflectionMatrixDataSource.Value = Graphics.Renderer.GetTransform( TransformType.ViewToScreen ) * reflectedCameraMatrix;

            //	TODO: AP: Reflect camera position
            System.Drawing.Rectangle viewport = Graphics.Renderer.Viewport;
            Graphics.Renderer.SetViewport( 0, 0, m_Reflections.Width, m_Reflections.Height );
            reflectionsContext.RenderingReflections = true;
            m_Reflections.Begin( );
            Graphics.Renderer.ClearDepth( 1.0f );
            Graphics.Renderer.ClearColour( Color.SteelBlue );
            RenderSceneObjects( reflectionsContext );
            m_Reflections.End( );
            Graphics.Renderer.SetViewport( viewport.X, viewport.Y, viewport.Width, viewport.Height );
            Graphics.Renderer.PopTransform( TransformType.WorldToView );
            Graphics.Renderer.PopTransform( TransformType.ViewToScreen );
        }
 /// <summary>
 /// Makes a matrix from a quaternion
 /// </summary>
 public static new Matrix44 MakeQuaternionMatrix( Quaternion quaternion )
 {
     Matrix44 result = new Matrix44( );
     MakeQuaternionMatrix( ( InvariantMatrix44 )result, quaternion );
     return result;
 }
 /// <summary>
 /// Makes a matrix from a quaternion
 /// </summary>
 public static void MakeQuaternionMatrix( Matrix44 matrix, Quaternion quaternion )
 {
     MakeQuaternionMatrix( ( InvariantMatrix44 )matrix, quaternion );
 }
示例#18
0
        /// <summary>
        /// Reads surface information
        /// </summary>
        private static void ReadSurfaces( ISource source, BinaryReader reader, long offset, int numSurfaces, int numFrames, ModelMesh mesh, IDictionary<string, ITexture2d> surfaceTextureTable, Matrix44 transform)
        {
            //	Move to the start of the first surface
            reader.BaseStream.Seek( offset, SeekOrigin.Begin );

            //	Allocate mesh surface array
            mesh.Surfaces = new ModelMesh.Surface[ numSurfaces ];

            for ( int surfaceCount = 0; surfaceCount < numSurfaces; ++surfaceCount )
            {
                //	Create a new surface
                ModelMesh.Surface curSurface		= new ModelMesh.Surface( );

                //int		ident				=
                reader.ReadInt32( );
                string	name				= ReadString ( reader, MaxPathLength );
                //int		flags				=
                reader.ReadInt32( );
                //int		surfaceNumFrames	=
                reader.ReadInt32( );
                //int		numShaders			=
                reader.ReadInt32( );
                int		numVertices			= reader.ReadInt32( );
                int		numTriangles		= reader.ReadInt32( );
                int		trianglesOffset		= reader.ReadInt32( );
                //int		shadersOffset		=
                reader.ReadInt32( );
                int		texturesOffset		= reader.ReadInt32( );
                int		verticesOffset		= reader.ReadInt32( );
                int		endOffset			= reader.ReadInt32( );

                //	Assign surface texture
                curSurface.Texture			= GetTexture( source, surfaceTextureTable, name );

                //	Assign surface shaders
            //	ReadShaders( reader, offset + shadersOffset, numShaders );

                //	Read in surface index group and texture UVs
                curSurface.Group			= ReadTriangles( reader, offset + trianglesOffset, numTriangles );
                curSurface.TextureUVs		= ReadTextureUVs( reader, offset + texturesOffset, numVertices );

                //	Read in surface vertices
            //	curSurface.NumVertices		= numVertices;
                ReadVertices( reader, offset + verticesOffset, numVertices, numFrames, curSurface, transform );

                //	Assign the new surface to the mesh
                mesh.Surfaces[ surfaceCount ] = curSurface;

                //	Move the stream to the next surface
                reader.BaseStream.Seek( offset + endOffset, SeekOrigin.Begin );
                offset += endOffset;
            }
        }
 /// <summary>
 /// Stores the reflection of src in result
 /// </summary>
 public static void MakeReflectionMatrix( Matrix44 result, Point3 pointOnPlane, Vector3 planeNormal )
 {
     MakeReflectionMatrix( result, pointOnPlane, planeNormal );
 }
示例#20
0
        /// <summary>
        /// Reads tag information
        /// </summary>
        private static void ReadTags( BinaryReader reader, long offset, int numTags, int numFrames, ModelMesh mesh, Matrix44 transform )
        {
            reader.BaseStream.Seek( offset, SeekOrigin.Begin );

            mesh.TagNames = new string[ numTags ];

            for ( int frameIndex = 0; frameIndex < numFrames; ++frameIndex )
            {
                ModelMesh.Tag[] tags = new ModelMesh.Tag[ numTags ];
                for ( int tagCount = 0; tagCount < numTags; ++tagCount )
                {
                    string tagName = ReadString( reader, MaxPathLength );

                    if ( frameIndex == 0 )
                    {
                        mesh.TagNames[ tagCount ] = tagName;
                    }

                    Point3	origin	= transform * ReadPoint( reader );
                    Vector3 xAxis	= ReadVector( reader );
                    Vector3 yAxis	= ReadVector( reader );
                    Vector3 zAxis	= ReadVector( reader );

                    ModelMesh.Tag curTag = new ModelMesh.Tag( );
                    curTag.Transform = new Matrix44( origin, xAxis, yAxis, zAxis );
                    curTag.Name = tagName;

                    tags[ tagCount ] = curTag;
                }
                mesh.FrameInfoList[ frameIndex ].Tags = tags;
            }
        }
 /// <summary>
 /// Creates an inverted copy of this matrix
 /// </summary>
 public new Matrix44 Invert( )
 {
     Matrix44 result = new Matrix44( );
     MakeInverse( result, this );
     return result;
 }
示例#22
0
        /// <summary>
        /// Reads surface vertices (positions and normals)
        /// </summary>
        private static void ReadVertices( BinaryReader reader, long offset, int numVertices, int numFrames, ModelMesh.Surface surface, Matrix44 transform )
        {
            reader.BaseStream.Seek( offset, SeekOrigin.Begin );

            //	Allocate surface frames
            surface.SurfaceFrames = new ModelMesh.SurfaceFrame[ numFrames ];

            //	Allocate temporary arrays for storing position and normal data
            float[] positions	= new float[ numVertices * 3 ];
            float[] normals		= new float[ numVertices * 3 ];

            //	Run through all frames
            for ( int frameIndex = 0; frameIndex < numFrames; ++frameIndex )
            {
                int positionIndex	= 0;
                int normalIndex		= 0;

                //	Allocate a surface frame
                ModelMesh.SurfaceFrame frame = new ModelMesh.SurfaceFrame( );

                //	Run through all vertices
                for ( int vertexCount = 0; vertexCount < numVertices; ++vertexCount )
                {
                    //	NOTE: Re-order coordinates. I use +ve Y as up, +ve X as right, +ve Z as into, MD3 default is +ve X as into, +ve Y as right, +ve Z as up
                    Point3 pt = new Point3( );
                    pt.Z = reader.ReadInt16( ) * XyzScale;
                    pt.X = reader.ReadInt16( ) * XyzScale;
                    pt.Y = reader.ReadInt16( ) * XyzScale;

                    pt = transform * pt;

                    positions[ positionIndex + 0 ] = pt.X;
                    positions[ positionIndex + 1 ] = pt.Y;
                    positions[ positionIndex + 2 ] = pt.Z;
                    positionIndex += 3;

                    float s = reader.ReadByte( ) * ByteToAngle;
                    float t = reader.ReadByte( ) * ByteToAngle;

                    normals[ normalIndex + 2 ] = ( Functions.Cos( s ) * Functions.Sin( t ) );
                    normals[ normalIndex + 0 ] = ( Functions.Sin( s ) * Functions.Sin( t ) );
                    normals[ normalIndex + 1 ] = ( Functions.Cos( t ) );
                    normalIndex += 3;
                }

                //	Convert position and normal data into vertex buffer objects
                frame.VertexBuffers = new OpenGlVertexArray[ 2 ];

                frame.VertexBuffers[ 0 ] = new OpenGlVertexArray( numVertices, 0, Gl.GL_VERTEX_ARRAY, 0, 3, Gl.GL_STATIC_DRAW_ARB, positions );
                frame.VertexBuffers[ 1 ] = new OpenGlVertexArray( numVertices, 0, Gl.GL_NORMAL_ARRAY, 0, 3, Gl.GL_STATIC_DRAW_ARB, normals );

                //	Assign the frame to the surface
                surface.SurfaceFrames[ frameIndex ] = frame;
            }
        }
        /// <summary>
        /// Scales this matrix
        /// </summary>
        public void Scale( float x, float y, float z )
        {
            //	TODO: CHEAT! AGAIN!
            Matrix44 mat = new Matrix44( this );
            Matrix44 scaleMat = new Matrix44( x, 0, 0, 0,
                                              0, y, 0, 0,
                                              0, 0, z, 0,
                                              0, 0, 0, 1 );

            StoreMultiply( mat, scaleMat );
        }
示例#24
0
        /// <summary>
        /// Loads... stuff
        /// </summary>
        public override object Load( ISource source, LoadParameters parameters )
        {
            parameters.CanCache = true;

            Vector3 scale = new Vector3
                (
                    DynamicProperties.GetProperty( parameters.Properties, "scaleX", 1.0f ),
                    DynamicProperties.GetProperty( parameters.Properties, "scaleY", 1.0f ),
                    DynamicProperties.GetProperty( parameters.Properties, "scaleZ", 1.0f )
                );

            Matrix44 transform = new Matrix44( );
            transform.Scale( scale.X, scale.Y, scale.Z );

            //	create the model
            Model model = new Model( );

            //	oh dear another md3 hack - directories mean articulated models, with skins and animations. Files
            //	mean single objects
            if ( source is IFolder )
            {
                //	Load animations
                model.Animations = LoadAnimations( AnimationFile( source ) );
                LoadNestedModel( model, source, transform );
            }
            else
            {
                LoadObjectModel( model, source, transform );
            }
            return model;
        }
 /// <summary>
 /// Stores the inverse transpose of mat in this matrix. This is used to create a matrix that can be used to transform vertex normals
 /// </summary>
 public void StoreInverseTranspose( Matrix44 mat )
 {
 }
 /// <summary>
 /// Gets the current matrix from the specified transform stack
 /// </summary>
 public abstract void GetTransform( TransformType type, Matrix44 matrix );
 /// <summary>
 /// Stores the transpose of mat in this matrix
 /// </summary>
 /// <param name="mat"></param>
 public void StoreTranspose( Matrix44 mat )
 {
     for ( int row = 0; row < 4; ++row )
     {
         for ( int col = 0; col < 4; ++col )
         {
             this[ row, col ] = mat[ col, row ];
         }
     }
 }
 /// <summary>
 /// Multiplication operator
 /// </summary>
 public static Matrix44 operator *( Matrix44 lhs, Matrix44 rhs )
 {
     Matrix44 mat = new Matrix44( );
     mat.StoreMultiply( lhs, rhs );
     return mat;
 }
 /// <summary>
 /// Creates a transposed copy of this matrix
 /// </summary>
 public new Matrix44 Transpose( )
 {
     Matrix44 result = new Matrix44( );
     MakeTransposeMatrix( result, this );
     return result;
 }
 /// <summary>
 /// Makes the specified matrix an identity matrix
 /// </summary>
 public static void MakeIdentityMatrix( Matrix44 matrix )
 {
     matrix.Set( 1, 0, 0, 0,
                 0, 1, 0, 0,
                 0, 0, 1, 0,
                 0, 0, 0, 1 );
 }