public void ExpandLibraryNode( LibraryNode lnode, string referrerId, Matrix4 localTransform, Matrix4 transform, ColladaMeshInfo meshInfo )
 {
     // recurse through any child nodes
     int childNo = 0;
     foreach( LibraryNode child in lnode.children )
         ExpandLibraryNode( child, referrerId + "." + (childNo++).ToString(), localTransform, transform, meshInfo );
     // expand geometry_instance references
     int instNo = 0;
     foreach( string geoInstanceId in lnode.geoInstanceIds )
     {
         GeometryInstance geoInstance = new GeometryInstance( referrerId + "." + (instNo++).ToString(), null, localTransform, transform );
         if( meshInfo.Geometries.ContainsKey( geoInstanceId ) )
         {
             // this was an instance_geometry instead of an instance_controller in 1.4 terms
             geoInstance.controller = null;
             geoInstance.geoSet = meshInfo.Geometries[ geoInstanceId ].Clone( geoInstance.name );
             meshInfo.GeoInstances.Add( geoInstance );
         }
     }
 }
        private static void ConvertFile( string srcDir, string dstDir, string name,
                                        Matrix4 transform, bool build_tangents,
                                        bool extract_collision_volumes, bool optimize_mesh,
                                        string skeleton_file )
        {
            if( String.IsNullOrEmpty( name ) )
            {
                // TODO: It would be better to catch this while parsing command args, but
                // that's a bit too hairy for now. This will at least inform the user.
                throw new ArgumentException( "No file named for conversion" );
            }

            string dir = string.Empty;
            string path = string.Empty;
            SplitPath( ref dir, ref path, name );
            if( srcDir == string.Empty )
                srcDir = dir;
            if( dstDir == string.Empty )
                dstDir = dir;
            name = path;
            // get the resource data from MeshManager
            string extension = Path.GetExtension( name ).ToLower();

            string baseFile = Path.GetFileNameWithoutExtension( name );
            if( baseFile.EndsWith( ".mesh" ) )
                baseFile = baseFile.Substring( 0, baseFile.Length - 5 );

            string baseSkeletonName = null;
            if( skeleton_file != null )
                baseSkeletonName = Path.GetFileName( skeleton_file );

            // mesh loading stats
            int before, after;

            // get the tick count before loading the mesh
            before = Environment.TickCount;

            string materialScript = null;
            Mesh mesh = ReadMesh( ref materialScript, transform, srcDir, dstDir, name );
            if( optimize_mesh )
                mesh = MeshUtility.CopyMesh( mesh );

            // get the tick count after loading the mesh
            after = Environment.TickCount;

            // record the time elapsed while loading the mesh
            log.InfoFormat( "Mesh: Loaded '{0}', took {1}ms", mesh.Name, (after - before) );

            // Build tangent vectors
            if( build_tangents )
            {
                log.Info( "Building tangent vectors from uv map" );
                MeshHelper.BuildTangentVectors( mesh );
            }

            if( extract_collision_volumes )
            {
                log.InfoFormat( "Extracting collision volumes from '{0}'", mesh.Name );
                CVExtractor.ExtractCollisionShapes( mesh, dstDir + baseFile );
            }

            //// prepare the mesh for a shadow volume?
            //if (MeshManager.Instance.PrepareAllMeshesForShadowVolumes) {
            //    if (edgeListsBuilt || autoBuildEdgeLists) {
            //        PrepareForShadowVolume();
            //    }
            //    if (!edgeListsBuilt && autoBuildEdgeLists) {
            //        BuildEdgeList();
            //    }
            //}

            // Allow them to override the skeleton reference of the mesh
            if( baseSkeletonName != null )
                mesh.SkeletonName = baseSkeletonName;

            string meshFile = baseFile + ".mesh";
            MeshSerializer meshWriter = new MeshSerializer();
            meshWriter.ExportMesh( mesh, dstDir + meshFile );

            // If it was a .dae file, we will need to export the material and skeleton as well
            if( extension != ".dae" && extension != ".kmz" )
                return;

            if( materialScript != null )
            {
                string materialFile = baseFile + ".material";
                Stream materialData = new FileStream( dstDir + materialFile, FileMode.Create );
                StreamWriter materialWriter = new StreamWriter( materialData );
                materialWriter.Write( materialScript );
                materialWriter.Close();
            }

            if( mesh.Skeleton == null )
                return;
            #if USE_XML
            string skelFile = baseFile + ".skeleton.xml";
            Stream skelData = new FileStream(dstDir + skelFile, FileMode.Create);
            OgreXmlSkeletonWriter skelWriter = new OgreXmlSkeletonWriter(skelData);
            skelWriter.Export(mesh.Skeleton);
            skelData.Close();
            #else
            // DEBUG
            foreach( AttachmentPoint socket in mesh.Skeleton.AttachmentPoints )
            {
                log.InfoFormat( "Created attachment point with parent {0}", socket.ParentBone );
                log.InfoFormat( "  Relative Position: {0}", socket.Position );
                log.InfoFormat( "  Relative Up: {0}", socket.Orientation * Vector3.UnitZ );
                Bone bone = mesh.Skeleton.GetBone( socket.ParentBone );
                Vector3 derivedPos = bone.DerivedPosition + socket.Position;
                Vector3 derivedUp = socket.Orientation * bone.DerivedOrientation * Vector3.UnitZ;
                log.InfoFormat( "  Absolute Position: {0}", derivedPos );
                log.InfoFormat( "  Absolute Up: {0}", derivedUp );
            }

            string skelFile = baseFile + ".skeleton";
            OgreSkeletonSerializer skelWriter = new OgreSkeletonSerializer();
            skelWriter.ExportSkeleton( mesh.Skeleton, dstDir + skelFile );
            #endif
        }
 private static Mesh ReadMesh(Matrix4 transform, string srcDir, string meshFile)
 {
     Stream meshData = new FileStream(srcDir + meshFile, FileMode.Open);
     Mesh mesh = new Mesh(meshFile);
     if (meshFile.EndsWith(".mesh", StringComparison.CurrentCultureIgnoreCase)) {
         MeshSerializer meshReader = new MeshSerializer();
         meshReader.ImportMesh(meshData, mesh);
     } else if (meshFile.EndsWith(".mesh.xml", StringComparison.CurrentCultureIgnoreCase)) {
         OgreXmlMeshReader meshReader = new OgreXmlMeshReader(meshData);
         meshReader.Import(mesh);
     } else if (meshFile.EndsWith(".dae", StringComparison.CurrentCultureIgnoreCase)) {
         string extension = Path.GetExtension(meshFile);
         string baseFile = Path.GetFileNameWithoutExtension(meshFile);
         string basename = meshFile.Substring(0, meshFile.Length - extension.Length);
         ColladaMeshReader meshReader = new ColladaMeshReader(meshData, baseFile);
         // import the .dae file
         meshReader.Import(transform, mesh, null, "idle", basename);
         // materialScript = meshReader.MaterialScript;
     } else {
         meshData.Close();
         string extension = Path.GetExtension(meshFile);
         throw new AxiomException("Unsupported mesh format '{0}'", extension);
     }
     meshData.Close();
     return mesh;
 }
        /// <summary>
        ///   Import into the mesh, using the skeleton provided, and 
        ///   assigning the animation data to a new animation.
        /// </summary>
        /// <param name="transform">the world transform to apply to this object</param>
        /// <param name="mesh">the mesh we will populate</param>
        /// <param name="skeleton">the skeleton to which we will add animations (or null if we are creating one)</param>
        /// <param name="animationName">the name that will be used for the animation</param>
        /// <param name="materialNamespace">namespace used for generation of material names</param>
        public void Import( Matrix4 transform, Mesh mesh, Skeleton skeleton, string animationName, string materialNamespace )
        {
            ColladaMeshReader reader = null;

            XmlDocument document = new XmlDocument();

            document.Load( m_Stream );

            XmlElement rootElement = document.DocumentElement;

            // This is slightly weird. The client calls this method on this object,
            // but then we determine which version of collada we're actually looking
            // at, and create a new instances of a derived collada reader.  As an
            // outcome, we have to copy fields from the factory-created instance
            // back to this instance.
            // TODO: Need a static factory method on the base class to create the
            // collada reader instance, then call that instance from the client;
            // that way we'll only have one instance in the first place.
            reader = GetColladaParser( rootElement );

            reader.m_ColladaRootNode = rootElement;
            reader.m_Document = document;

            reader.m_MaterialBuilder = new MaterialScriptBuilder( materialNamespace );

            ColladaMeshInfo meshInfo = new ColladaMeshInfo( mesh );

            reader.ReadCollada( rootElement, meshInfo );

            meshInfo.NoRiggingCulling = NoRiggingCulling;

            meshInfo.Process( transform, skeleton, m_BaseFile, animationName );

            this.m_MaterialBuilder = reader.MaterialBuilder;
        }
 public static Quaternion GetRotation(Matrix4 transform)
 {
     Matrix3 tmp =
         new Matrix3(transform.m00, transform.m01, transform.m02,
                     transform.m10, transform.m11, transform.m12,
                     transform.m20, transform.m21, transform.m22);
     float scale = (float)Math.Pow(tmp.Determinant, 1 / 3.0f);
     tmp = tmp * scale;
     Quaternion rv = Quaternion.Identity;
     rv.FromRotationMatrix(tmp);
     return rv;
 }
 protected void TransformSkeleton(Matrix4 unscaledTransform, float scale)
 {
     Matrix4 invExportTransform = unscaledTransform.Inverse();
     Dictionary<string, Matrix4> fullInverseBoneTransforms = new Dictionary<string, Matrix4>();
     Skeleton newSkeleton = new Skeleton(skeleton.Name);
     // Construct new versions of the bones, and build
     // the inverse bind matrix that will be needed.
     for (ushort i = 0; i < skeleton.BoneCount; ++i) {
         Bone bone = skeleton.GetBone(i);
         Bone newBone = newSkeleton.CreateBone(bone.Name, bone.Handle);
         fullInverseBoneTransforms[bone.Name] =
             bone.BindDerivedInverseTransform * invExportTransform;
     }
     //  Build the parenting relationship for the new skeleton
     for (ushort i = 0; i < skeleton.BoneCount; ++i) {
         Bone bone = skeleton.GetBone(i);
         Bone newBone = newSkeleton.GetBone(i);
         Bone parentBone = (Bone)bone.Parent;
         if (parentBone != null) {
             Bone newParentBone = newSkeleton.GetBone(parentBone.Handle);
             newParentBone.AddChild(newBone);
         }
     }
     // Set the orientation and position for the various bones
     for (ushort i = 0; i < newSkeleton.BoneCount; ++i) {
         Bone bone = skeleton.GetBone(i);
         string boneName = bone.Name;
         string parentName = (bone.Parent == null) ? null : bone.Parent.Name;
         Matrix4 transform = GetLocalBindMatrix(fullInverseBoneTransforms, boneName, parentName, true);
         Quaternion orientation = GetRotation(transform);
         Bone newBone = newSkeleton.GetBone(i);
         newBone.Orientation = orientation;
         // newBone.Scale = transform.Scale;
         newBone.Position = scale * transform.Translation;
     }
     newSkeleton.SetBindingPose();
     for (int i = 0; i < skeleton.AnimationCount; ++i) {
         Animation anim = skeleton.GetAnimation(i);
         Animation newAnim = newSkeleton.CreateAnimation(anim.Name, anim.Length);
         TransformAnimation(unscaledTransform, scale, newAnim, anim, newSkeleton);
     }
     skeleton = newSkeleton;
 }
        protected void TransformTrack(Matrix4 exportTransform,
									  NodeAnimationTrack newTrack, 
									  NodeAnimationTrack track,
									  Bone bone)
        {
            Matrix4 invExportTransform = exportTransform.Inverse();
            Bone oldNode = (Bone)track.TargetNode;
            Bone newNode = (Bone)newTrack.TargetNode;
            for (int i = 0; i < track.KeyFrames.Count; ++i) {
                TransformKeyFrame keyFrame = track.GetTransformKeyFrame(i);
                TransformKeyFrame newKeyFrame = newTrack.CreateNodeKeyFrame(keyFrame.Time);
                Quaternion oldOrientation = oldNode.Orientation * keyFrame.Rotation;
                Vector3 oldTranslation = oldNode.Position + keyFrame.Translate;
                Matrix4 oldTransform = Multiverse.MathLib.MathUtil.GetTransform(oldOrientation, oldTranslation);
                Matrix4 newTransform = exportTransform * oldTransform * invExportTransform;
                Quaternion newOrientation = GetRotation(newTransform);
                Vector3 newTranslation = newTransform.Translation;
                newKeyFrame.Rotation = newNode.Orientation.Inverse() * newOrientation;
                newKeyFrame.Translate = newTranslation - newNode.Position;
                //if (oldNode.Name == "Lower_Torso_BIND_jjj") {
                //    log.DebugFormat("New translation: {0}; New Position: {1}", newTranslation, newNode.Position);
                //}
            }
        }
 public void Export(Skeleton skeleton, Matrix4 exportTransform)
 {
     this.exportTransform = exportTransform;
     float det = exportTransform.Determinant;
     this.exportScale = (float)Math.Pow(det, 1 / 3.0f);
     Export(skeleton);
 }
 public void AddModelPathObject(bool logPathGeneration, PathObjectType type, string modelName,
                                Vector3 modelPosition, Matrix4 modelTransform, 
                                List<CollisionShape> shapes, float terrainHeight)
 {
     PathGenerator pathGenerator = new PathGenerator(logPathGeneration, modelName, type, terrainHeight,
                                                     modelTransform, shapes);
     // Perform traversal and creation of polygons, arcs
     // between polygons, and portals to the terrain
     pathGenerator.GeneratePolygonsArcsAndPortals();
     List<PathPolygon> polygons = new List<PathPolygon>();
     List<PathArc> portals = new List<PathArc>();
     List<PathArc> arcs = new List<PathArc>();
     foreach(GridPolygon r in pathGenerator.CVPolygons)
         polygons.Add(new PathPolygon(r.Index, PolygonKind.CV, r.CornerLocs));
     foreach(GridPolygon r in pathGenerator.TerrainPolygons)
         polygons.Add(new PathPolygon(r.Index, PolygonKind.Terrain, r.CornerLocs));
     foreach(PolygonArc portal in pathGenerator.TerrainPortals)
         portals.Add(new PathArc(portal.Kind, portal.Poly1Index, portal.Poly2Index, MakePathEdge(portal.Edge)));
     foreach(PolygonArc arc in pathGenerator.PolygonArcs)
         arcs.Add(new PathArc(arc.Kind, arc.Poly1Index, arc.Poly2Index, MakePathEdge(arc.Edge)));
     pathObjects.Add(new PathObject(pathGenerator.ModelName, type.name, pathGenerator.FirstTerrainIndex,
                                    new PathPolygon(0, PolygonKind.Bounding, pathGenerator.ModelCorners),
             polygons, portals, arcs));
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="matrix"></param>
        public void Transform(Matrix4 matrix)
        {
            // do nothing for a null box
            if(isNull)
                return;

            Vector3 min = new Vector3();
            Vector3 max = new Vector3();
            Vector3 temp = new Vector3();

            bool isFirst = true;
            int i;

            for( i = 0; i < corners.Length; i++ ) {
                // Transform and check extents
                temp = matrix * corners[i];
                if( isFirst || temp.x > max.x )
                    max.x = temp.x;
                if( isFirst || temp.y > max.y )
                    max.y = temp.y;
                if( isFirst || temp.z > max.z )
                    max.z = temp.z;
                if( isFirst || temp.x < min.x )
                    min.x = temp.x;
                if( isFirst || temp.y < min.y )
                    min.y = temp.y;
                if( isFirst || temp.z < min.z )
                    min.z = temp.z;

                isFirst = false;
            }

            SetExtents(min, max);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="matrices"></param>
        public void GetWorldTransforms(Matrix4[] matrices)
        {
            if(parent.numBoneMatrices == 0 || !parent.IsHardwareAnimationEnabled) {
                matrices[0] = parent.ParentFullTransform;
            }
            else {
                // Hardware skinning, pass all actually used matrices
                List<ushort> indexMap = subMesh.useSharedVertices ?
                    subMesh.Parent.SharedBlendIndexToBoneIndexMap : subMesh.BlendIndexToBoneIndexMap;
                Debug.Assert(indexMap.Count <= this.Parent.numBoneMatrices);

                if (parent.IsSkeletonAnimated)
                {
                    // Bones, use cached matrices built when Entity::UpdateRenderQueue was called
                    Debug.Assert(parent.boneMatrices != null);

                    for (int i = 0; i < indexMap.Count; i++) {
                        matrices[i] = parent.boneMatrices[indexMap[i]];
                    }
                }
                else
                {
                    // All animations disabled, use parent entity world transform only
                    for (int i = 0; i < indexMap.Count; i++) {
                        matrices[i] = parent.ParentFullTransform;
                    }
                }
            }
        }
 public void ProcessArgs( string[] args )
 {
     for( int i = 0; i < args.Length; ++i )
     {
         switch( args[ i ] )
         {
             case "--transform":
                 for( int j = 0; j < 16; ++j )
                     if( i + 1 < args.Length )
                         transform[ j ] = float.Parse( args[ ++i ] );
                     else
                         Console.WriteLine( "Invalid transform" );
                 break;
             case "--build_skeleton":
                 build_skeleton = true;
                 break;
             case "--base_skeleton":
                 // This is overloaded.  It is used for adding multiple animations
                 // into a single skeleton, but it is also used to specify the name
                 // of the skeleton that will be referenced by the mesh file.
                 skeleton_file = args[ ++i ];
                 break;
             case "--build_tangents":
                 build_tangents = true;
                 break;
             case "--out_skeleton":
                 out_skeleton_file = args[ ++i ];
                 break;
             case "--optimize_mesh":
             case "--optimise_mesh":
                 optimize_mesh = true;
                 break;
             case "--animation":
                 {
                     AnimationEntry entry = new AnimationEntry();
                     entry.animation_name = args[ ++i ];
                     entry.animation_file = args[ ++i ];
                     animations.Add( entry );
                     break;
                 }
             case "--manual_lod":
                 {
                     LodEntry entry = new LodEntry();
                     entry.distance = float.Parse( args[ ++i ] );
                     entry.meshFile = args[ ++i ];
                     manualLodEntries.Add( entry );
                     break;
                 }
             case "--socket":
                 {
                     Matrix4 attachTransform = Matrix4.Identity;
                     string name = args[ ++i ];
                     string parentBone = args[ ++i ];
                     for( int j = 0; j < 16; ++j )
                         if( i + 1 < args.Length )
                             attachTransform[ j ] = float.Parse( args[ ++i ] );
                         else
                             Console.WriteLine( "Invalid transform" );
                     AttachmentPointNode ap = new AttachmentPointNode( name, parentBone, attachTransform );
                     attachPoints.Add( ap );
                     break;
                 }
             case "--test_physics":
                 {
                     test_physics = true;
                     return;
                 }
             // LOD options
             case "--lod_levels":
                 {
                     lodlevels = int.Parse( args[ ++i ] );
                     break;
                 }
             case "--lod_distance":
                 {
                     loddist = float.Parse( args[ ++i ] );
                     break;
                 }
             case "--lod_percent":
                 {
                     lodpercent = float.Parse( args[ ++i ] );
                     break;
                 }
             case "--lod_num_triangles":
                 {
                     // lodnumtris
                     break;
                 }
     #if NOT_USED
             case "--merge_animations": {
                     // Deprecated
                     string destFile = args[++i];
                     string rigFile = args[++i];
                     List<string> animFiles = new List<string>();
                     while (i + 1 < args.Length)
                         animFiles.Add(args[++i]);
                     MergeAnimations(srcDir, dstDir, destFile, rigFile, animFiles);
                     return;
                 }
             case "--merge_collada": {
                     // Deprecated
                     string destFile = args[++i];
                     string rigFile = args[++i];
                     string animFile = args[++i];
                     MergeColladaFiles(srcDir, dstDir, destFile, rigFile, animFile);
                     return;
                 }
     #endif
             case "--3ds":
                 {
                     // Convert from a right handed system where z is up to a right handed system where y is up.
                     Matrix4 yupTrans = new Matrix4( 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 );
                     transform = transform * yupTrans;
                     break;
                 }
             case "--src_dir":
                 srcDir = MaybeAddTrailingBackslash( args[ ++i ] );
                 break;
             case "--dst_dir":
                 dstDir = MaybeAddTrailingBackslash( args[ ++i ] );
                 break;
     #if NOT_USED
             case "--test_sockets":
                 TestSockets();
                 break;
     #endif
             case "--dont_extract_collision_volumes":
                 extract_collision_volumes = false;
                 break;
             case "--log_collision_volumes":
                 CVExtractor.InitLog( true );
                 break;
             case "--args_file":
                 ProcessArgumentFile( args[ ++i ] );
                 break;
             case "--log_file":
                 log_file = args[ ++i ];
                 break;
             case "--throw":
                 rethrow = true;
                 break;
             case "--version":
                 Console.WriteLine( string.Format( "ConversionTool version: {0}",
                                                 System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() ) );
                 break;
             case "--no_rigging_culling":
                 ColladaMeshReader.NoRiggingCulling = true;
                 break;
             case "--":
             case "--usage":
             case "--help":
                 Convert.Usage();
                 abort = true;
                 break;
             default:
                 last_arg = args[ i ];
                 break;
         }
         if( abort )
             break;
     }
 }
        /// <summary>
        ///   Utility method to merge animations from other files into a single skeleton
        /// </summary>
        /// <param name="srcDir">the directory from which the new animations will be loaded</param>
        /// <param name="dstDir">the directory to which the modified skeleton will be saved</param>
        /// <param name="skelFile">the name of the file to which the modified skeleton will be written</param>
        /// <param name="transform">the transform to apply to the skeleton and animations</param>
        /// <param name="skeleton">the original skeleton</param>
        /// <param name="animations">the list of animations</param>
        private static void AddAnimations( string srcDir, string dstDir,
                                        string skelFile,
                                        Matrix4 transform, Skeleton skeleton,
                                        List<AnimationEntry> animations )
        {
            // mesh loading stats
            int before, after;

            // get the tick count before loading the mesh
            before = Environment.TickCount;

            foreach( AnimationEntry entry in animations )
            {
                Mesh mesh = new Mesh( "Mesh" );
                Stream data = new FileStream( srcDir + entry.animation_file, FileMode.Open );
                ColladaMeshReader meshReader = new ColladaMeshReader( data, null );
                // import the .dae file
                meshReader.Import( transform, mesh, skeleton, entry.animation_name, null );
                // close the stream (we don't need to leave it open here)
                data.Close();
            }

            // get the tick count after loading the mesh
            after = Environment.TickCount;

            // record the time elapsed while loading the mesh
            log.InfoFormat( "Mesh: took {0}ms", (after - before) );

            //// prepare the mesh for a shadow volume?
            //if (MeshManager.Instance.PrepareAllMeshesForShadowVolumes) {
            //    if (edgeListsBuilt || autoBuildEdgeLists) {
            //        PrepareForShadowVolume();
            //    }
            //    if (!edgeListsBuilt && autoBuildEdgeLists) {
            //        BuildEdgeList();
            //    }
            //}

            OgreSkeletonSerializer skelWriter = new OgreSkeletonSerializer();
            skelWriter.ExportSkeleton( skeleton, dstDir + skelFile );
        }
 private static Skeleton ReadSkeleton( Matrix4 transform, string srcDir, string skelFile )
 {
     Stream skelData = new FileStream( srcDir + skelFile, FileMode.Open );
     Skeleton skeleton = new Skeleton( skelFile );
     if( skelFile.EndsWith( ".skeleton" ) )
     {
         OgreSkeletonSerializer skelReader = new OgreSkeletonSerializer();
         skelReader.ImportSkeleton( skelData, skeleton );
     }
     else if( skelFile.EndsWith( ".skeleton.xml" ) )
     {
         OgreXmlSkeletonReader skelReader = new OgreXmlSkeletonReader( skelData );
         skelReader.Import( skeleton );
     }
     else
     {
         skelData.Close();
         string extension = Path.GetExtension( skelFile );
         throw new AxiomException( "Unsupported skeleton format '{0}'", extension );
     }
     skelData.Close();
     return skeleton;
 }
        // mesh will be null if this fails
        static void ImportKMZFile( 
            ref string materialScript, Matrix4 transform,
            string dstDir, string meshFile, 
            FileStream kmzStream, Mesh mesh )
        {
            string daeFile = ExtractKMZComponentFiles( dstDir, kmzStream );

            if( ! String.IsNullOrEmpty( daeFile ) )
            {
                string materialNamespace  = Path.GetFileNameWithoutExtension( daeFile );
                string animationNamespace = materialNamespace;

                FileStream daeStream = new FileStream( daeFile, FileMode.Open );

                ColladaMeshReader meshReader = new ColladaMeshReader( daeStream, animationNamespace );

                // Convert from a left handed system where z is up to a right handed system where y is up.
                Matrix4 yupTrans = new Matrix4( 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 );
                Matrix4 yupTransform = transform * yupTrans;

                // import the .dae file
                meshReader.Import( yupTransform, mesh, null, "base", materialNamespace );

                materialScript = meshReader.MaterialScript;
            }
        }
 public static float GetScale(Matrix4 transform)
 {
     Matrix3 tmp =
         new Matrix3(transform.m00, transform.m01, transform.m02,
                     transform.m10, transform.m11, transform.m12,
                     transform.m20, transform.m21, transform.m22);
     return (float)Math.Pow(tmp.Determinant, 1 / 3.0f);
 }
 public static Matrix4 ScaleMatrix(Matrix4 transform, float scale)
 {
     Matrix4 rv = transform;
     for (int row = 0; row < 3; ++row) {
         for (int col = 0; col < 3; ++col) {
             rv[row, col] *= scale;
         }
     }
     return rv;
 }
        /// <summary>
        ///		Interpolates a single segment of the spline given a parametric value.
        /// </summary>
        /// <param name="index">The point index to treat as t=0. index + 1 is deemed to be t=1</param>
        /// <param name="t">Parametric value</param>
        /// <returns>An interpolated point along the spline.</returns>
        public Vector3 Interpolate(int index, float t)
        {
            Debug.Assert(index >= 0 && index < pointList.Count, "Spline point index overrun.");

            if((index + 1) == pointList.Count) {
                // cant interpolate past the end of the list, just return the last point
                return pointList[index];
            }

            // quick special cases
            if(t == 0.0f)
                return pointList[index];
            else if(t == 1.0f)
                return pointList[index + 1];

            // Time for real interpolation
            // Construct a Vector4 of powers of 2
            float t2, t3;
            // t^2
            t2 = t * t;
            // t^3
            t3 = t2 * t;

            Vector4 powers = new Vector4(t3, t2, t, 1);

            // Algorithm is result = powers * hermitePoly * Matrix4(point1, point2, tangent1, tangent2)
            Vector3 point1 = pointList[index];
            Vector3 point2 = pointList[index + 1];
            Vector3 tangent1 = tangentList[index];
            Vector3 tangent2 = tangentList[index + 1];
            Matrix4 point = new Matrix4();

            // create the matrix 4 with the 2 point and tangent values
            point.m00 = point1.x;
            point.m01 = point1.y;
            point.m02 = point1.z;
            point.m03 = 1.0f;
            point.m10 = point2.x;
            point.m11 = point2.y;
            point.m12 = point2.z;
            point.m13 = 1.0f;
            point.m20 = tangent1.x;
            point.m21 = tangent1.y;
            point.m22 = tangent1.z;
            point.m23 = 1.0f;
            point.m30 = tangent2.x;
            point.m31 = tangent2.y;
            point.m32 = tangent2.z;
            point.m33 = 1.0f;

            // get the final result in a Vector4
            Vector4 result = powers * hermitePoly * point;

            // return the final result
            return new Vector3(result.x, result.y, result.z);
        }
        protected void TransformAnimation(Matrix4 exportTransform, 
										  Animation newAnim, Animation anim,
										  Skeleton newSkeleton)
        {
            foreach (NodeAnimationTrack track in anim.NodeTracks.Values) {
                NodeAnimationTrack newTrack = newAnim.CreateNodeTrack(track.Handle);
                Bone targetBone = (Bone)track.TargetNode;
                newTrack.TargetNode = newSkeleton.GetBone(targetBone.Handle);
                TransformTrack(exportTransform, newTrack, track, targetBone);
            }
        }
        /// <summary>
        ///    Used to transform the overlay when scrolling, scaling etc.
        /// </summary>
        /// <param name="xform">Array of Matrix4s to populate with the world 
        ///    transforms of this overlay.
        /// </param>
        public void GetWorldTransforms(Matrix4[] xform)
        {
            if(isTransformOutOfDate) {
                UpdateTransforms();
            }

            xform[0] = transform;
        }
        protected void TransformAnimation(Matrix4 unscaledTransform, float scale,
										  Animation newAnim, Animation anim,
										  Skeleton newSkeleton)
        {
            // With the new idea I had for transforming these, I need the tracks
            // set up for the parent bones before I can handle the child bones.
            for (int i = 0; i < anim.Tracks.Count; ++i) {
                AnimationTrack track = anim.Tracks[i];
                AnimationTrack newTrack = newAnim.CreateTrack(track.Handle);
                Bone targetBone = (Bone)track.TargetNode;
                newTrack.TargetNode = newSkeleton.GetBone(targetBone.Handle);
            }
            // This gets the ordered bone list, and transforms the tracks in
            // that order instead.
            List<Bone> orderedBoneList = GetOrderedBoneList(null, newSkeleton);
            foreach (Bone bone in orderedBoneList)
                TransformTrack(unscaledTransform, scale, newAnim, anim, bone);
        }
        /// <summary>
        ///    Internal lazy update method.
        /// </summary>
        protected void UpdateTransforms()
        {
            // Ordering:
            //    1. Scale
            //    2. Rotate
            //    3. Translate
            Matrix3 rot3x3 = Matrix3.Identity;
            Matrix3 scale3x3 = Matrix3.Zero;

            rot3x3.FromEulerAnglesXYZ(0, 0, MathUtil.DegreesToRadians(rotate));
            scale3x3.m00 = scaleX;
            scale3x3.m11 = scaleY;
            scale3x3.m22 = 1.0f;

            transform = Matrix4.Identity;
            transform = rot3x3 * scale3x3;
            transform.Translation = new Vector3(scrollX, scrollY, 0);

            isTransformOutOfDate = false;
        }
        protected void TransformTrack(Matrix4 unscaledTransform, float scale,
									  Animation newAnim, Animation anim, Bone bone)
        {
            AnimationTrack track = GetBoneTrack(anim, bone.Handle);
            AnimationTrack newTrack = GetBoneTrack(newAnim, bone.Handle);
            Bone oldNode = (Bone)track.TargetNode;
            Bone newNode = (Bone)newTrack.TargetNode;
            Quaternion exportRotation = GetRotation(unscaledTransform);
            Vector3 exportTranslation = unscaledTransform.Translation;
            for (int i = 0; i < track.KeyFrames.Count; ++i) {
                KeyFrame keyFrame = track.KeyFrames[i];
                Quaternion oldOrientation = Quaternion.Identity;
                Vector3 oldTranslation = Vector3.Zero;
                // Now build the composite transform for the old node
                GetCompositeTransform(ref oldOrientation, ref oldTranslation, oldNode, anim, i);
                Quaternion targetOrientation = exportRotation * oldOrientation;
                Vector3 targetTranslation = exportTranslation + scale * (exportRotation * oldTranslation);
                KeyFrame newKeyFrame = newTrack.CreateKeyFrame(keyFrame.Time);
                // we have a parent - where is it?
                Quaternion parentOrientation = Quaternion.Identity;
                Vector3 parentTranslation = Vector3.Zero;
                GetCompositeTransform(ref parentOrientation, ref parentTranslation, (Bone)newNode.Parent, newAnim, i);
                newKeyFrame.Rotation = newNode.Orientation.Inverse() * parentOrientation.Inverse() * targetOrientation;
                newKeyFrame.Translate = (-1 * newNode.Position) + (-1 * parentTranslation) + targetTranslation;
            }
        }
 /// <summary>
 ///		
 /// </summary>
 /// <param name="vector"></param>
 /// <param name="matrix"></param>
 /// <returns></returns>
 public static Vector4 Multiply(Vector4 vector, Matrix4 matrix)
 {
     return vector * matrix;
 }
 public void GetWorldTransforms( Matrix4[] xform )
 {
     parentNode.GetWorldTransforms(xform);
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="matrices"></param>
 public void GetWorldTransforms(Matrix4[] matrices)
 {
     matrices[0] = parent.ParentFullTransform;
 }
 /// <summary>
 ///    Gets the world transform matrix / matrices for this renderable object.
 /// </summary>
 /// <remarks>
 ///    If the object has any derived transforms, these are expected to be up to date as long as
 ///    all the SceneNode structures have been updated before this is called.
 ///  <p/>
 ///    This method will populate xform with 1 matrix if it does not use vertex blending. If it
 ///    does use vertex blending it will fill the passed in pointer with an array of matrices,
 ///    the length being the value returned from getNumWorldTransforms.
 /// </remarks>
 public void GetWorldTransforms(Matrix4[] matrices)
 {
 }
        private static void GenerateCurvedIllusionPlaneVertexData(HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float cameraPosition, float sphereRadius, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;
            Vector3 norm;
            float sphereDistance;
            unsafe {
                // lock the vertex buffer
                IntPtr data = vertexBuffer.Lock(BufferLocking.Discard);

                float* pData = (float*)data.ToPointer();

                for (int y = 0; y < ySegments + 1; ++y) {
                    for (int x = 0; x < xSegments + 1; ++x) {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        // transform by orientation and distance
                        vec = xform * vec;

                        // assign to geometry
                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // build bounds as we go
                        if (firstTime) {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime = false;
                        } else {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals) {
                            norm = Vector3.UnitZ;
                            norm = orientation * norm;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        // generate texture coordinates, normalize position, modify by orientation to return +y up
                        vec = orientation.Inverse() * vec;
                        vec.Normalize();

                        // find distance to sphere
                        sphereDistance = MathUtil.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y;

                        vec.x *= sphereDistance;
                        vec.z *= sphereDistance;

                        // use x and y on sphere as texture coordinates, tiled
                        float s = vec.x * (0.01f * uTiles);
                        float t = vec.z * (0.01f * vTiles);
                        for (int i = 0; i < numberOfTexCoordSets; i++) {
                            *pData++ = s;
                            *pData++ = (1 - t);
                        }
                    } // x
                } // y

                // unlock the buffer
                vertexBuffer.Unlock();
            } // unsafe
        }
 public static Quaternion GetRotation(Matrix4 transform)
 {
     Matrix3 tmp =
         new Matrix3(transform.m00, transform.m01, transform.m02,
                     transform.m10, transform.m11, transform.m12,
                     transform.m20, transform.m21, transform.m22);
     float det = tmp.Determinant;
     float scale = (float)(1 / Math.Pow(det, 1.0 / 3.0));
     tmp = tmp * scale;
     Quaternion rv = Quaternion.Identity;
     rv.FromRotationMatrix(tmp);
     Debug.Assert(Math.Abs(1.0 - rv.Norm) < .001f, "Possible non-uniform scale factor on rotation matrix");
     // rv.Normalize();
     return rv;
 }
        private static void GeneratePlaneVertexData(HardwareVertexBuffer vbuf, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 transform, bool firstTime, bool normals, Matrix4 rotation, int numTexCoordSets, float xTexCoord, float yTexCoord, SubMesh subMesh, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;
            unsafe {
                // lock the vertex buffer
                IntPtr data = vbuf.Lock(BufferLocking.Discard);

                float* pData = (float*)data.ToPointer();

                for (int y = 0; y <= ySegments; y++) {
                    for (int x = 0; x <= xSegments; x++) {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        vec = transform * vec;

                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // Build bounds as we go
                        if (firstTime) {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime = false;
                        } else {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals) {
                            vec = Vector3.UnitZ;
                            vec = rotation * vec;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        for (int i = 0; i < numTexCoordSets; i++) {
                            *pData++ = x * xTexCoord;
                            *pData++ = 1 - (y * yTexCoord);
                        } // for texCoords
                    } // for x
                } // for y

                // unlock the buffer
                vbuf.Unlock();

                subMesh.useSharedVertices = true;

            } // unsafe
        }