Пример #1
0
        protected override void OnLoad(System.EventArgs e)
        {
            VSync = VSyncMode.On;

            GL.Enable(EnableCap.Texture2D);
            GL.Enable(EnableCap.DepthTest);
            GL.Enable(EnableCap.CullFace);
            GL.CullFace(CullFaceMode.Back);
            GL.FrontFace(FrontFaceDirection.Cw);
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
            GL.ClearColor(Color.FromArgb(255, 24, 24, 24));

            multisampling = new Multisampling(Width, Height, 8);
            defaultShader = new DefaultShader();

            model = ColladaLoader.Load(modelName);
            model.CreateVBOs();
            model.LoadTextures();
            model.Bind(defaultShader.ShaderProgram,
                       defaultShader.Texture,
                       defaultShader.HaveTexture,
                       defaultShader.Ambient,
                       defaultShader.Diffuse,
                       defaultShader.Specular,
                       defaultShader.Shininess);
        }
Пример #2
0
        public static void TestRenderBones()
        {
            TestXNAGame main = null;


            SkinnedModel model = null;
            ColladaModel col   = null;

            TestXNAGame.Start("TestShowBones",
                              delegate
            {
                main = TestXNAGame.Instance;


                //col = ColladaModel.FromFile( new GameFile( main.RootDirectory + "/Content/Goblin.DAE" ) );
                //col = ColladaModel.LoadSimpleCharacterAnim001();
                col = ColladaModel.LoadSimpleBones001();

                model = SkinnedModelBuilder.LoadSkinnedModel(main, col);
                //model.WorldMatrix = Matrix.CreateFromYawPitchRoll( -MathHelper.PiOver2, -MathHelper.PiOver2, 0 );
            },
                              delegate
            {
                model.UpdateAnimation(main.Elapsed);
                model.RenderBonesLines();
            });
        }
Пример #3
0
        public void ColladaModelConstructorTest()
        {
            string filename = TestDataLoader.GetTestFilePath("APC_animation.DAE");
            Assert.IsTrue(File.Exists(filename), (new FileInfo(filename).FullName) + " does not exist");

            ColladaModel target = new ColladaModel(filename);
        }
Пример #4
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            _model = model;
            XmlNode xmlScene = xmlRoot.SelectSingleNode("scene");

            model.MeshInstances = ImportMeshInstances(xmlScene, model);
        }
Пример #5
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            _model = model;
            XmlNode xmlScene = xmlRoot.SelectSingleNode("scene");

            model.MeshInstances = ImportMeshInstances(xmlScene, model);
        }
Пример #6
0
        public static ColladaModel Load(string name)
        {
            using (var xml = SourceLoader.AsStream($"models.{name}.dae"))
            {
                var xRoot = XDocument.Load(xml);
                var model = new ColladaModel();

                // Parse Geometries
                var xMeshes = xRoot.Descendants($"{ns}mesh");
                if (!xMeshes.Any())
                {
                    throw new ApplicationException("Failed to find geometries!");
                }

                foreach (var xMesh in xMeshes)
                {
                    var geoLoader = new GeometryLoader(xMesh);
                    var geometry  = geoLoader.Load();

                    model.Geometries.Add(geometry);
                }

                // Parse Materials
                var xMaterials = xRoot.Descendants($"{ns}material");
                foreach (var xMaterial in xMaterials)
                {
                    var materialLoader = new MaterialLoader(xRoot, xMaterial);
                    var material       = materialLoader.Load();

                    model.Materials.Add(material);
                }

                return(model);
            }
        }
Пример #7
0
        public static SkinnedModel LoadSkinnedModel(IXNAGame game, Stream colladaStream)
        {
            ColladaModel colladaModel = ColladaModel.FromStream(colladaStream);

            SkinnedModelBuilder builder = new SkinnedModelBuilder();

            return(builder.CreateSkinnedModel(game, colladaModel));
        }
Пример #8
0
        public void ColladaModelConstructorTest()
        {
            string filename = TestDataLoader.GetTestFilePath("APC_animation.DAE");

            Assert.IsTrue(File.Exists(filename), (new FileInfo(filename).FullName) + " does not exist");

            ColladaModel target = new ColladaModel(filename);
        }
Пример #9
0
 public ColladaScene(ColladaModel nModel)
 {
     model             = nModel;
     Type              = NodeType.Scene;
     Matrix            = Matrix.Identity;
     scene             = this;
     parent            = null;
     Instance_Geometry = null;
 }
Пример #10
0
        public void ImportTest()
        {
            AnimationImporter target  = new AnimationImporter(); // TODO: Initialize to an appropriate value
            XmlNode           xmlRoot = null;                    // TODO: Initialize to an appropriate value
            ColladaModel      model   = null;                    // TODO: Initialize to an appropriate value

            target.Import(xmlRoot, model);
            Assert.Inconclusive("A method that does not return a value cannot be verified.");
        }
Пример #11
0
        /// <summary>
        /// Retrieves all the joints referenced by the given skin. The bones are only
        /// references to the bones contained by the given model! While fetching
        /// the bones (by following references in XML) this method updates the
        /// inverse bind-pose matrix of each bone according to the XML INV_BIND_MATRIX
        /// input as found in the XML skin definition.
        /// </summary>
        /// <param name="xmlSkin">XML skin node</param>
        /// <param name="model">Model instance</param>
        /// <returns>Used bones with updated inverse bind-pose matrices</returns>
        static List <Joint> GetUpdatedJointsFromSkin(XmlNode xmlSkin, ColladaModel model)
        {
            if (model.Joints.Count <= 1)
            {
                throw new ArgumentException("Model does not contain any joints");
            }

            // Inverse Bind-Pose Matrices
            XmlNode       xmlMatInput     = xmlSkin.SelectSingleNode("joints/input[@semantic='INV_BIND_MATRIX']");
            Source        matrixSource    = Source.FromInput(xmlMatInput, xmlSkin);
            List <Matrix> invBindMatrices = matrixSource.GetData <Matrix>();

            // Joints (as referenced by this skin)
            XmlNode       xmlJointInput = xmlSkin.SelectSingleNode("joints/input[@semantic='JOINT']");
            Source        jointSource   = Source.FromInput(xmlJointInput, xmlSkin);
            List <string> names         = jointSource.GetData <string>();
            List <Joint>  joints        = new List <Joint>(names.Count);
            int           i             = 0;

            // Dictionary of joints in model by their name
            Dictionary <string, Joint> modelJoints = model.Joints.ToDictionary(j =>
                                                                               j.GetAddressPart(jointSource.ColladaType));

            // Check if the names actually refer to the joints in the dictionary
            if (modelJoints.ContainsKey(names[0]) == false)
            {
                // As of COLLADA 1.4 "name" can refer to name OR sid attribute!
                // If the former didn't work try the latter
                if (jointSource.ColladaType == "name")
                {
                    // Only elements that actually have a sid can be part of the dictionary.
                    // Elements which don't have a SID usually aren't referenced, so they are
                    // not needed in the dictionary anyway
                    modelJoints = model.Joints.Where(j => j.GetAddressPart("sid") != null).
                                  ToDictionary(j => j.GetAddressPart("sid"));
                }

                // If that still didn't help it's hopeless
                if (modelJoints.ContainsKey(names[0]) == false)
                {
                    throw new ApplicationException("Invalid joint references in skin definition");
                }
            }

            // Look up bones within the model by name from JOINT input)
            foreach (Joint joint in names.Select(name => modelJoints[name]))
            {
                Debug.Assert(joint != null);

                // while we're at it update inverse bind-pose matrix
                joint.InvBindPose = invBindMatrices[i++];

                joints.Add(joint);
            }

            return(joints);
        }
Пример #12
0
        public static void Main(string[] args)
        {
            ColladaModel model = new ColladaModel();

            model.Libraries.Add(new ColladaLibraryGeometries());

            Console.Write(ColladaExporter.Export(model));
            Console.ReadLine();
        }
Пример #13
0
        private void ImportAnimationClips(XmlNode xmlNode, ColladaModel model)
        {
            if (xmlNode == null || model.JointAnimations == null || !model.JointAnimations.Any())
            {
                return;
            }

            XmlNodeList xmlClips = xmlNode.SelectNodes("animation_clip");

            if (xmlClips == null)
            {
                return;
            }

            foreach (XmlNode xmlClip in xmlClips)
            {
                // Reference name of the animation clip: name > id > sid
                String name = xmlClip.GetAttributeString("name") ??
                              (xmlClip.GetAttributeString("id") ??
                               xmlClip.GetAttributeString("sid"));

                // Start and end times
                float start = float.Parse(xmlClip.Attributes["start"].Value,
                                          CultureInfo.InvariantCulture);

                float end = float.Parse(xmlClip.Attributes["end"].Value,
                                        CultureInfo.InvariantCulture);

                // Animations to be played
                XmlNodeList xmlInstances = xmlClip.SelectNodes("instance_animation");
                if (xmlInstances == null)
                {
                    return;
                }

                List <JointAnimation> animations = new List <JointAnimation>();

                foreach (XmlNode xmlInstance in xmlInstances)
                {
                    // Assume url="#id"
                    String id = xmlInstance.GetAttributeString("url").Substring(1);

                    // Find animation with given id
                    var temp = from a in model.JointAnimations
                               where a.GlobalID.Equals("id")
                               select a;

                    animations.AddRange(temp);
                }

                JointAnimationClip clip = new JointAnimationClip(animations.ToArray(),
                                                                 TimeSpan.FromSeconds(start), TimeSpan.FromSeconds(end));

                model.JointAnimationClips.Add(clip);
            }
        }
Пример #14
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            XmlNodeList xmlLightInstances = xmlRoot.SelectNodes(".//instance_light");
            if (xmlLightInstances == null || xmlLightInstances.Count == 0)
            {
                // silently quit (lights are not vital)
                return;
            }

            model.Lights = (from XmlNode xmlInstance in xmlLightInstances
                            where CanImport(xmlInstance)
                            select ImportLight(xmlInstance)).ToList();
        }
Пример #15
0
        /// <summary>
        /// Imports skin information
        /// </summary>
        /// <remarks>Joint weights and indices defined by skins are imported
        /// by GeometryImporter since these values have to be added to the
        /// vertex container of the meshes.</remarks>
        /// <param name="xmlSkin"></param>
        /// <param name="model"></param>
        static void ImportSkin(XmlNode xmlSkin, ColladaModel model)
        {
            Mesh mesh = GetMeshFromSkin(xmlSkin, model);

            if (mesh == null)
            {
                throw new Exception("Mesh referenced by skin not found");
            }

            // TODO: Take bind_shape_matrix into consideration for animation

            // Read inverse bind-pose matrices and save them in the corresponding joints
            GetUpdatedJointsFromSkin(xmlSkin, model);
        }
Пример #16
0
        /// <summary>
        /// Returns the mesh referenced by given skin XML node if that mesh exists
        /// in the given model. Otherwise null is returned.
        /// </summary>
        /// <param name="xmlSkin">XML skin node</param>
        /// <param name="model">Model instance</param>
        /// <returns>instance of Mesh or null</returns>
        static Mesh GetMeshFromSkin(XmlNode xmlSkin, ColladaModel model)
        {
            string  meshId  = xmlSkin.Attributes["source"].Value.Substring(1);
            XmlNode xmlGeom = xmlSkin.OwnerDocument.DocumentElement.
                              SelectSingleNode(".//geometry[@id='" + meshId + "']");

            string name = xmlGeom.Attributes["name"] != null
                              ? xmlGeom.Attributes["name"].Value
                              : meshId;

            return((from mesh in model.Meshes
                    where mesh.Name.Equals(name)
                    select mesh).SingleOrDefault());
        }
Пример #17
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            XmlNodeList xmlLightInstances = xmlRoot.SelectNodes(".//instance_light");

            if (xmlLightInstances == null || xmlLightInstances.Count == 0)
            {
                // silently quit (lights are not vital)
                return;
            }

            model.Lights = (from XmlNode xmlInstance in xmlLightInstances
                            where CanImport(xmlInstance)
                            select ImportLight(xmlInstance)).ToList();
        }
        public void TestCreateObjectAndSaveWorkingCopy()
        {
            WizardsEditor wizardsEditor = new WizardsEditor();

            EntityWizardsEditorExtension extension = new EntityWizardsEditorExtension(wizardsEditor);
            EditorObject obj = new EditorObject();

            obj.FullData = new ObjectFullData();
            extension.EditorObjects.Add(obj);

            ObjectEditor objectEditor = new ObjectEditor(obj, wizardsEditor);

            objectEditor.AddColladaModel(ColladaModel.LoadWall001());

            wizardsEditor.SaveToWorkingCopy();
        }
Пример #19
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            this.model = model;

            // Find material nodes in library
            XmlNodeList xmlMaterials = xmlRoot.SelectNodes("library_materials/material");

            if (xmlMaterials == null || xmlMaterials.Count == 0)
            {
                // No Materials found
                return;
            }

            model.Materials = (from XmlNode xmlMaterial in xmlMaterials
                               select ImportMaterial(xmlMaterial)).ToList();
        }
Пример #20
0
        Joint GetParentJoint(XmlNode xmlNode, ColladaModel model)
        {
            XmlNode xmlParent = xmlNode.ParentNode;

            if (xmlParent == null)
            {
                return(null);
            }
            if (xmlParent.Attributes == null || xmlParent.Attributes.Count == 0)
            {
                return(null);
            }

            string name = xmlParent.Attributes["name"] != null
                              ? xmlParent.Attributes["name"].Value
                              : xmlParent.Attributes["id"].Value;

            return(model.Joints.Where(j => j.Name.Equals(name)).FirstOrDefault());
        }
Пример #21
0
        static void ImportAnimations(XmlNodeList xmlAnimations, ColladaModel model)
        {
            // Joint dictionary
            Dictionary <string, Joint> joints = model.Joints.ToDictionary(joint => joint.GlobalID);

            // Import single animations
            List <JointAnimation> animations = (from XmlNode xmlAnim in xmlAnimations
                                                where DoesAnimationAffectJoints(joints, xmlAnim)
                                                select ImportAnimation(xmlAnim, joints)).ToList();

            // Combine those affecting the same joint to one animation
            var combined = from c in
                           (from anim in animations
                            where anim.Channels.Length == 1
                            group anim by anim.Channels[0].Target)
                           select CombineAnimations(c);

            // List of those who cannot be joined (because they have multiple channels)
            var rest = from anim in animations where anim.Channels.Length > 1 select anim;

            animations = combined.Union(rest).ToList();

            // TODO: Implement Animation Clips (missing example so far)

            // Try to merge all animations (must be extended to consider animation clips)
            // NOTE: Didn't work for Maya animations, something's still of with them
            if (animations.Count > 1 && false)
            {
                try
                {
                    var animation = MergeAnimations(animations);
                    animations.Clear();
                    animations.Add(animation);
                }
                catch (Exception)
                {
                    // didn't work, ignore
                }
            }

            model.JointAnimations = new JointAnimationList(animations);
        }
Пример #22
0
        /// <summary>
        /// Imports all joint nodes referenced by &lt;skeleton&gt; nodes and their
        /// children. Stores the found joints in the given model's joint collection.
        /// </summary>
        /// <param name="xmlRoot">XML root node</param>
        /// <param name="model">model to store joints in</param>
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            knownJoints.Clear();

            // Add root joint that can be used to transform the model alltogether
            Joint root = new Joint("__root")
                             {
                                 Parent = null,
                                 Transform = Matrix.Identity,
                                 Index = 0,
                                 ScopedID = "__root",
                                 GlobalID = "__root"
                             };

            ReadJoints(root, FindJointNodes(xmlRoot), model);

            // Last joint is the root
            model.Joints.Add(root);
            root.Index = model.Joints.Count - 1;
        }
Пример #23
0
        /// <summary>
        /// Imports all joint nodes referenced by &lt;skeleton&gt; nodes and their
        /// children. Stores the found joints in the given model's joint collection.
        /// </summary>
        /// <param name="xmlRoot">XML root node</param>
        /// <param name="model">model to store joints in</param>
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            knownJoints.Clear();

            // Add root joint that can be used to transform the model alltogether
            Joint root = new Joint("__root")
            {
                Parent    = null,
                Transform = Matrix.Identity,
                Index     = 0,
                ScopedID  = "__root",
                GlobalID  = "__root"
            };

            ReadJoints(root, FindJointNodes(xmlRoot), model);

            // Last joint is the root
            model.Joints.Add(root);
            root.Index = model.Joints.Count - 1;
        }
Пример #24
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            _model = model;

            // Find skin definitions. Multiple skin definitions are supported
            // but they have to work on disjoint sets (relate to different joints)
            XmlNodeList xmlSkins = xmlRoot.SelectNodes(".//skin");

            foreach (XmlNode xmlSkin in xmlSkins)
            {
                ImportSkin(xmlSkin, model);
            }

            // Next import animations from library_animations
            XmlNodeList xmlAnimations = xmlRoot.SelectNodes("/COLLADA/library_animations/animation");

            ImportAnimations(xmlAnimations, model);

            // Import the animation clips library
            XmlNode xmlNode = xmlRoot.SelectSingleNode("/COLLADA/library_animation_clips");
            ImportAnimationClips(xmlNode, model);
        }
Пример #25
0
        public SkinnedModel CreateSkinnedModel(IXNAGame game, ColladaModel _colladaModel)
        {
            SkinnedModel ret;

            colladaModel = _colladaModel;
            skinnedModel = new SkinnedModel(game);
            ret          = skinnedModel;


            skinnedModel.FrameRate       = colladaModel.frameRate;
            skinnedModel.numOfAnimations = colladaModel.numOfAnimations;

            LoadMeshes();
            LoadBones();


            // Clean up for possible next creation
            colladaModel = null;
            skinnedModel = null;

            return(ret);
        }
Пример #26
0
        public void LoadNode(XmlNode nodeNode)
        {
            ID   = XmlHelper.GetXmlAttribute(nodeNode, "id");
            Name = XmlHelper.GetXmlAttribute(nodeNode, "name");
            SetNodeType(XmlHelper.GetXmlAttribute(nodeNode, "type"));

            XmlNode matrixNode = XmlHelper.GetChildNode(nodeNode, "matrix");

            if (matrixNode != null)
            {
                Matrix = ColladaModel.LoadColladaMatrix(matrixNode);
            }

            foreach (XmlNode instance_geometryNode in nodeNode)
            {
                if (instance_geometryNode.Name == "instance_geometry")
                {
                    if (Instance_Geometry != null)
                    {
                        throw new Exception(
                                  "More then one Instance_Geometry node found, which is not currently implemented!");
                    }

                    string url = XmlHelper.GetXmlAttribute(instance_geometryNode, "url").Substring(1);
                    Instance_Geometry = scene.Model.GetMesh(url);
                }
            }

            foreach (XmlNode childNode in nodeNode)
            {
                if (childNode.Name == "node")
                {
                    ColladaSceneNode node = new ColladaSceneNode(this);
                    Nodes.Add(node);
                    node.LoadNode(childNode);
                }
            }
        }
Пример #27
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            _model = model;

            // Find skin definitions. Multiple skin definitions are supported
            // but they have to work on disjoint sets (relate to different joints)
            XmlNodeList xmlSkins = xmlRoot.SelectNodes(".//skin");

            foreach (XmlNode xmlSkin in xmlSkins)
            {
                ImportSkin(xmlSkin, model);
            }

            // Next import animations from library_animations
            XmlNodeList xmlAnimations = xmlRoot.SelectNodes("/COLLADA/library_animations/animation");

            ImportAnimations(xmlAnimations, model);

            // Import the animation clips library
            XmlNode xmlNode = xmlRoot.SelectSingleNode("/COLLADA/library_animation_clips");

            ImportAnimationClips(xmlNode, model);
        }
Пример #28
0
        public static void TestRenderAnimated()
        {
            TestXNAGame  main  = null;
            SkinnedModel model = null;

            ColladaModel col = null;


            TestXNAGame.Start("TestRenderAnimated",
                              delegate
            {
                main = TestXNAGame.Instance;

                //col = ColladaModel.FromFile( new GameFile( main.RootDirectory + "/Content/Goblin.DAE" ) );
                //col = ColladaModel.FromFile( new GameFile( main.RootDirectory + "/DebugFiles/VerySimpleBones001(disabled).DAE" ) );
                //col = ColladaModel.FromFile( new GameFile( main.RootDirectory + "/Content/TriangleBones002.DAE" ) );
                col = ColladaModel.LoadSimpleCharacterAnim001();
                //col = ColladaModel.LoadSimpleBones001();
                //col = ColladaModel.LoadTriangleBones001();

                model             = SkinnedModelBuilder.LoadSkinnedModel(main, col);
                model.WorldMatrix = Matrix.CreateFromYawPitchRoll(-MathHelper.PiOver2, -MathHelper.PiOver2, 0);
                //model.WorldMatrix = Matrix.Identity;
            },
                              delegate
            {
                main.GraphicsDevice.RenderState.CullMode = CullMode.None;
                if (main.Keyboard.IsKeyPressed(Microsoft.Xna.Framework.Input.Keys.R))
                {
                    model             = SkinnedModelBuilder.LoadSkinnedModel(main, col);
                    model.WorldMatrix = Matrix.Identity;    // Matrix.CreateFromYawPitchRoll( -MathHelper.PiOver2, -MathHelper.PiOver2, 0 );
                }
                model.UpdateAnimation(main.Elapsed);
                model.Render();
                model.RenderBonesLines();
            });
        }
Пример #29
0
        /// <summary>
        /// Imports the COLLADA Model from the given .DAE file into the XNA Content Model.
        /// </summary>
        /// <param name="filename">Path to .DAE file</param>
        /// <param name="context">Context (is not used)</param>
        /// <returns></returns>
        public override NodeContent Import(string filename, ContentImporterContext context)
        {
            boneIndex       = 0;
            importerContext = context;

            // Load the complete collada model which is to be converted / imported
            collada = new ColladaModel(filename);

            //Debugger.Launch();
            //Debugger.Break();

            rootNode          = new NodeContent();
            rootNode.Name     = Path.GetFileNameWithoutExtension(filename);
            rootNode.Identity = new ContentIdentity(filename);

            // The default XNA processor only supports up to 255 joints / bones
            if (collada.Joints.Count < 255)
            {
                CreateBones(CreateAnimations());
            }
            else
            {
                String          helpLink = "";
                ContentIdentity cid      = rootNode.Identity;
                String          msg      = String.Format("Model contains {0} bones. Maximum is 255. " +
                                                         "Skinning Data (Bones and Vertex Channels) will not be imported!",
                                                         collada.Joints.Count);

                importerContext.Logger.LogWarning(helpLink, cid, msg);
                excludeBlendWeights = true;
            }

            CreateMaterials();
            CreateMeshes();

            return(rootNode);
        }
Пример #30
0
        public void Import(XmlNode xmlRoot, ColladaModel model)
        {
            // Find geometry nodes
            XmlNodeList xmlGeometries = xmlRoot.SelectNodes("library_geometries/geometry");

            if (xmlGeometries == null || xmlGeometries.Count == 0)
            {
                throw new ApplicationException("No geometry found");
            }

            ColladaModel existingInstance = model;

            model.Meshes = (from XmlNode xmlGeom in xmlGeometries
                            where xmlGeom.SelectNodes(".//triangles|.//polygons|.//polylist").Count > 0
                            select ImportGeometry(xmlGeom, existingInstance)).ToList();

            // Check for unsupported geometry, silently ignore lines
            if ((from XmlNode xmlGeom in xmlGeometries
                 where xmlGeom.SelectNodes(".//trifangs|.//tristrips").Count > 0
                 select xmlGeom).Any())
            {
                throw new ApplicationException("Only triangles are supported");
            }
        }
Пример #31
0
        List <MeshInstance> ImportMeshInstances(XmlNode xmlScene, ColladaModel model)
        {
            if (model.Meshes.Any() == false)
            {
                throw new Exception("No meshes found");
            }

            List <MeshInstance> meshes = new List <MeshInstance>();

            XmlNode xmlVisualScene = GetVisualScene(xmlScene);

            // Look for geometry instances and determine transformation from bottom up
            XmlNodeList xmlGeometries = xmlVisualScene.SelectNodes(".//instance_geometry");

            foreach (XmlNode xmlGeom in xmlGeometries)
            {
                string geometryId = xmlGeom.Attributes["url"].Value.Substring(1);
                string key        = GetMeshLibKey(xmlGeom, geometryId);

                // Check whether the referenced mesh exists
                if (!model.Meshes.Any(m => m.Name == key))
                {
                    continue;
                }

                MeshInstance mesh = new MeshInstance();
                mesh.MeshName          = key;
                mesh.AbsoluteTransform = CreateAbsoluteTransform(xmlGeom);
                mesh.ParentJoint       = GetParentJoint(xmlGeom, model);

                meshes.Add(mesh);
            }

            // Look for controller instances
            // TODO: Load controller instances and joints correctly!
            XmlNodeList xmlControllerInstances = xmlVisualScene.SelectNodes(".//instance_controller");

            foreach (XmlNode xmlControllerInstance in xmlControllerInstances)
            {
                string meshId = GetMeshId(xmlControllerInstance);
                string key    = GetMeshLibKey(xmlControllerInstance, meshId);

                // Check whether the referenced mesh exists
                if (!model.Meshes.Any(m => m.Name == key))
                {
                    continue;
                }

                MeshInstance mesh = new MeshInstance();
                mesh.MeshName          = key;
                mesh.AbsoluteTransform = CreateAbsoluteTransformFromSkeleton(xmlControllerInstance);
                mesh.ParentJoint       = GetParentJoint(xmlControllerInstance, model);

                meshes.Add(mesh);
            }

            // Check if any meshes have been found
            if (meshes.Count == 0)
            {
                throw new Exception("No mesh instances have been found");
            }

            return(meshes);
        }
Пример #32
0
        List<MeshInstance> ImportMeshInstances(XmlNode xmlScene, ColladaModel model)
        {
            if (model.Meshes.Any() == false)
            {
                throw new Exception("No meshes found");
            }

            List<MeshInstance> meshes = new List<MeshInstance>();

            XmlNode xmlVisualScene = GetVisualScene(xmlScene);

            // Look for geometry instances and determine transformation from bottom up
            XmlNodeList xmlGeometries = xmlVisualScene.SelectNodes(".//instance_geometry");

            foreach (XmlNode xmlGeom in xmlGeometries)
            {
                string geometryId = xmlGeom.Attributes["url"].Value.Substring(1);
                string key = GetMeshLibKey(xmlGeom, geometryId);

                // Check whether the referenced mesh exists
                if (!model.Meshes.Any(m => m.Name == key)) continue;

                MeshInstance mesh = new MeshInstance();
                mesh.MeshName = key;
                mesh.AbsoluteTransform = CreateAbsoluteTransform(xmlGeom);
                mesh.ParentJoint = GetParentJoint(xmlGeom, model);

                meshes.Add(mesh);
            }

            // Look for controller instances
            // TODO: Load controller instances and joints correctly!
            XmlNodeList xmlControllerInstances = xmlVisualScene.SelectNodes(".//instance_controller");

            foreach (XmlNode xmlControllerInstance in xmlControllerInstances)
            {
                string meshId = GetMeshId(xmlControllerInstance);
                string key = GetMeshLibKey(xmlControllerInstance, meshId);

                // Check whether the referenced mesh exists
                if (!model.Meshes.Any(m => m.Name == key)) continue;

                MeshInstance mesh = new MeshInstance();
                mesh.MeshName = key;
                mesh.AbsoluteTransform = CreateAbsoluteTransformFromSkeleton(xmlControllerInstance);
                mesh.ParentJoint = GetParentJoint(xmlControllerInstance, model);

                meshes.Add(mesh);
            }

            // Check if any meshes have been found
            if (meshes.Count == 0)
            {
                throw new Exception("No mesh instances have been found");
            }

            return meshes;
        }
Пример #33
0
        Joint GetParentJoint(XmlNode xmlNode, ColladaModel model)
        {
            XmlNode xmlParent = xmlNode.ParentNode;
            if (xmlParent == null) return null;
            if (xmlParent.Attributes == null || xmlParent.Attributes.Count == 0) return null;

            string name = xmlParent.Attributes["name"] != null
                              ? xmlParent.Attributes["name"].Value
                              : xmlParent.Attributes["id"].Value;

            return model.Joints.Where(j => j.Name.Equals(name)).FirstOrDefault();
        }
Пример #34
0
        /// <summary>
        /// This method extacts skinning information from a skin definition that
        /// refers to the given mesh node. If no skin definition is found jointWeights
        /// and jointIndices are assigned empty arrays. If there is a valid skin
        /// definition this method will output four joint indices per base vertex (Vector4)
        /// and three weights (Vector3). If there are more than four joints assigned to a
        /// vertex only the four most influencial are selected. The indices in the resulting
        /// jointIndices array are referring to positions within the given model's joint
        /// collection. 0 refers to the joint at model.Joints[0], 1 refers to the joint at
        /// model.Joints[1] and so on. If the model contains no joints this method outputs
        /// two empty arrays, just as if no skin defintion existed.
        /// </summary>
        /// <remarks>The outputted Vector3s for jointWeights represent four normalized weights
        /// in three components. The sum of all four weights is 1. The fourth weight is implicitly
        /// defined as (1 - X - Y -Z).</remarks>
        /// <param name="xmlMeshNode">XML mesh node</param>
        /// <param name="model">Model instance with non-empty joint collection</param>
        /// <param name="jointIndices">Array of 4-d vectors representing joint indices</param>
        /// <param name="jointWeights">Array of 3-d vectors representing their respective weights</param>
        protected static void GetJointWeightsAndIndices(XmlNode xmlMeshNode, ColladaModel model,
                                                        out Vector4[] jointIndices, out Vector3[] jointWeights)
        {
            // Look for a skin definition that references this mesh
            XmlNode xmlSkin = xmlMeshNode.SelectSingleNode("/COLLADA/library_controllers/" +
                                                           "controller/skin[@source='#" + xmlMeshNode.ParentNode.Attributes["id"].Value + "']");

            if (xmlSkin == null || model.Joints == null || model.Joints.Count == 0)
            {
                // no skinning information found
                jointIndices = new Vector4[0];
                jointWeights = new Vector3[0];
                return;
            }

            // Read number of vertex weight assignments (this is equivalent to the number of base vertices)
            XmlNode xmlVertexWeights = xmlSkin.SelectSingleNode("vertex_weights");
            int     count            = int.Parse(xmlVertexWeights.Attributes["count"].Value);

            // Read weight source
            XmlNode xmlWeightInput = xmlSkin.SelectSingleNode("vertex_weights/input[@semantic='WEIGHT']");
            Source  weightSource   = Source.FromInput(xmlWeightInput, xmlSkin);
            var     weights        = weightSource.GetData <float>();

            // Read assignments
            XmlNode xmlVertexCount = xmlSkin.SelectSingleNode("vertex_weights/vcount");
            XmlNode xmlVertices    = xmlSkin.SelectSingleNode("vertex_weights/v");

            int[] vcount = XmlUtil.ParseInts(xmlVertexCount.InnerText);
            ContentAssert.AreEqual(vcount.Length, count, "vcount.Length");

            int[] data = XmlUtil.ParseInts(xmlVertices.InnerText);

            // How many items per vertex (this corresponds to the maximum offset of
            // all inputs within vertex_weights)
            int stride = (from XmlNode node in xmlVertexWeights.SelectNodes("input/@offset")
                          select int.Parse(node.Value)).Max() + 1;

            ContentAssert.IsTrue(stride >= 2, "Invalid weight data");

            // It is assumed that joint indices are at offset 0 and their weights at offset 1
            // For each base vertex there is one block of joint-weight assigments
            jointIndices = new Vector4[count];
            jointWeights = new Vector3[count];
            bool reachedEnd = false;

            for (int i = 0, k = 0; i < count; i++)
            {
                // There may be more than 4 weights defined
                List <JointWeightPair> pairs = new List <JointWeightPair>();

                // Add all defined joint-weight pairs
                for (int j = 0; j < vcount[i]; j++)
                {
                    int jointIndex  = data[k + 0];
                    int weightIndex = data[k + 1];

                    pairs.Add(new JointWeightPair(jointIndex, weights[weightIndex]));
                    k += stride;
                }

                // Take the four vertices with greatest influence
                JointWeightPair[] best = (from pair in pairs
                                          orderby pair.Weight descending
                                          select pair).Take(4).ToArray();

                Vector4 curIndices = new Vector4();
                Vector4 curWeights = new Vector4();

                ContentAssert.IsTrue((vcount[i] <= 4 && best.Length == vcount[i]) ||
                                     best.Length == 4, "Invalid weight data", true);

                if (best.Length >= 1)
                {
                    curIndices.X = best[0].JointIndex;
                    curWeights.X = best[0].Weight;
                }

                if (best.Length >= 2)
                {
                    curIndices.Y = best[1].JointIndex;
                    curWeights.Y = best[1].Weight;
                }

                if (best.Length >= 3)
                {
                    curIndices.Z = best[2].JointIndex;
                    curWeights.Z = best[2].Weight;
                }

                if (best.Length == 4)
                {
                    curIndices.W = best[3].JointIndex;
                    curWeights.W = best[3].Weight;
                }

                // Normalize weights (sum must be 1)
                float sum = curWeights.X + curWeights.Y + curWeights.Z + curWeights.Z;
                if (sum > 0)
                {
                    curWeights.X = 1.0f / sum * curWeights.X;
                    curWeights.Y = 1.0f / sum * curWeights.Y;
                    curWeights.Z = 1.0f / sum * curWeights.Z;
                    curWeights.W = 1.0f / sum * curWeights.W;
                }

                jointIndices[i] = curIndices;
                jointWeights[i] = curWeights.XYZ();

                if (k == data.Length)
                {
                    reachedEnd = true;
                }
            }

            ContentAssert.IsTrue(reachedEnd, "Not all weights were read", true);

            // JointIndices are referring to indices in the joint source
            // so every index refers to a name in the source which refers to the
            // actual bone
            XmlNode xmlInput = xmlSkin.SelectSingleNode("vertex_weights/input[@semantic='JOINT']");

            Debug.Assert(xmlInput != null, "No joint input in skin found");

            Source jointSource = Source.FromInput(xmlInput, xmlSkin);
            var    names       = jointSource.GetData <string>();

            // Create dictionary of model bones with source reference type as key
            // (source refers to joints either by name, idref or sidref)
            Dictionary <string, Joint> modelJoints = model.Joints.ToDictionary(j =>
                                                                               j.GetAddressPart(jointSource.ColladaType));

            // Check if the names actually refer to the joints in the dictionary
            if (modelJoints.ContainsKey(names[0]) == false)
            {
                Debug.Assert(model.Joints.All(j =>
                                              j.Name != null || j.GlobalID != null || j.ScopedID != null),
                             "Joints cannot be referenced");

                // As of COLLADA 1.4 "name" can refer to name OR sid attribute!
                // If the former didn't work try the latter);)
                if (jointSource.ColladaType == "name")
                {
                    // Only elements that actually have a sid can be part of the dictionary.
                    // Elements which don't have a SID usually aren't referenced, so they are
                    // not needed in the dictionary anyway
                    modelJoints = model.Joints.Where(j => j.GetAddressPart("sid") != null).
                                  ToDictionary(j => j.GetAddressPart("sid"));
                }

                // If that still didn't help it's hopeless
                if (modelJoints.ContainsKey(names[0]) == false)
                {
                    throw new ApplicationException("Invalid joint references in skin definition");
                }
            }

            try
            {
                // replace index that points to source with index that points to model's joint
                for (int i = 0; i < jointIndices.Length; i++)
                {
                    Vector4 indices = jointIndices[i];

                    // Find indices in model's joint collection
                    indices.X = modelJoints[names[(int)indices.X]].Index;
                    indices.Y = modelJoints[names[(int)indices.Y]].Index;
                    indices.Z = modelJoints[names[(int)indices.Z]].Index;
                    indices.W = modelJoints[names[(int)indices.W]].Index;

                    jointIndices[i] = indices;
                }
            } catch (IndexOutOfRangeException e)
            {
                throw new ApplicationException("Invalid joint indices read");
            }

            // Check data
            bool valid = jointIndices.All(v => Math.Abs((v.X + v.Y + v.Z + (1 - v.X - v.Y - v.Z)) - 1) < 0.001f);

            ContentAssert.IsTrue(valid, "All joint weights must sum up to 1f");
        }
Пример #35
0
        /// <summary>
        /// Returns the mesh referenced by given skin XML node if that mesh exists
        /// in the given model. Otherwise null is returned.
        /// </summary>
        /// <param name="xmlSkin">XML skin node</param>
        /// <param name="model">Model instance</param>
        /// <returns>instance of Mesh or null</returns>
        static Mesh GetMeshFromSkin(XmlNode xmlSkin, ColladaModel model)
        {
            string meshId = xmlSkin.Attributes["source"].Value.Substring(1);
            XmlNode xmlGeom = xmlSkin.OwnerDocument.DocumentElement.
                SelectSingleNode(".//geometry[@id='" + meshId + "']");

            string name = xmlGeom.Attributes["name"] != null
                              ? xmlGeom.Attributes["name"].Value
                              : meshId;

            return (from mesh in model.Meshes
                    where mesh.Name.Equals(name)
                    select mesh).SingleOrDefault();
        }
Пример #36
0
        /// <summary>
        /// Retrieves all the joints referenced by the given skin. The bones are only
        /// references to the bones contained by the given model! While fetching
        /// the bones (by following references in XML) this method updates the
        /// inverse bind-pose matrix of each bone according to the XML INV_BIND_MATRIX
        /// input as found in the XML skin definition.
        /// </summary>
        /// <param name="xmlSkin">XML skin node</param>
        /// <param name="model">Model instance</param>
        /// <returns>Used bones with updated inverse bind-pose matrices</returns>
        static List<Joint> GetUpdatedJointsFromSkin(XmlNode xmlSkin, ColladaModel model)
        {
            if (model.Joints.Count <= 1)
            {
                throw new ArgumentException("Model does not contain any joints");
            }

            // Inverse Bind-Pose Matrices
            XmlNode xmlMatInput = xmlSkin.SelectSingleNode("joints/input[@semantic='INV_BIND_MATRIX']");
            Source matrixSource = Source.FromInput(xmlMatInput, xmlSkin);
            List<Matrix> invBindMatrices = matrixSource.GetData<Matrix>();

            // Joints (as referenced by this skin)
            XmlNode xmlJointInput = xmlSkin.SelectSingleNode("joints/input[@semantic='JOINT']");
            Source jointSource = Source.FromInput(xmlJointInput, xmlSkin);
            List<string> names = jointSource.GetData<string>();
            List<Joint> joints = new List<Joint>(names.Count);
            int i = 0;

            // Dictionary of joints in model by their name
            Dictionary<string, Joint> modelJoints = model.Joints.ToDictionary(j =>
                j.GetAddressPart(jointSource.ColladaType));

            // Check if the names actually refer to the joints in the dictionary
            if (modelJoints.ContainsKey(names[0]) == false)
            {
                // As of COLLADA 1.4 "name" can refer to name OR sid attribute!
                // If the former didn't work try the latter
                if (jointSource.ColladaType == "name")
                {
                    // Only elements that actually have a sid can be part of the dictionary.
                    // Elements which don't have a SID usually aren't referenced, so they are
                    // not needed in the dictionary anyway
                    modelJoints = model.Joints.Where(j => j.GetAddressPart("sid") != null).
                        ToDictionary(j => j.GetAddressPart("sid"));
                }

                // If that still didn't help it's hopeless
                if (modelJoints.ContainsKey(names[0]) == false)
                {
                    throw new ApplicationException("Invalid joint references in skin definition");
                }
            }

            // Look up bones within the model by name from JOINT input)
            foreach (Joint joint in names.Select(name => modelJoints[name]))
            {
                Debug.Assert(joint != null);

                // while we're at it update inverse bind-pose matrix
                joint.InvBindPose = invBindMatrices[i++];

                joints.Add(joint);
            }

            return joints;
        }
Пример #37
0
        static void ImportAnimations(XmlNodeList xmlAnimations, ColladaModel model)
        {
            // Joint dictionary
            Dictionary<string, Joint> joints = model.Joints.ToDictionary(joint => joint.GlobalID);

            // Import single animations
            List<JointAnimation> animations = (from XmlNode xmlAnim in xmlAnimations
                                               where DoesAnimationAffectJoints(joints, xmlAnim)
                                               select ImportAnimation(xmlAnim, joints)).ToList();

            // Combine those affecting the same joint to one animation
            var combined = from c in
                              (from anim in animations
                               where anim.Channels.Length == 1
                               group anim by anim.Channels[0].Target)
                           select CombineAnimations(c);

            // List of those who cannot be joined (because they have multiple channels)
            var rest = from anim in animations where anim.Channels.Length > 1 select anim;

            animations = combined.Union(rest).ToList();

            // TODO: Implement Animation Clips (missing example so far)

            // Try to merge all animations (must be extended to consider animation clips)
            // NOTE: Didn't work for Maya animations, something's still of with them
            if (animations.Count > 1 && false)
            {
                try
                {
                    var animation = MergeAnimations(animations);
                    animations.Clear();
                    animations.Add(animation);
                }
                catch (Exception)
                {
                    // didn't work, ignore
                }
            }

            model.JointAnimations = new JointAnimationList(animations);
        }
Пример #38
0
        public static SkinnedModel LoadSkinnedModel(IXNAGame game, ColladaModel model)
        {
            SkinnedModelBuilder builder = new SkinnedModelBuilder();

            return(builder.CreateSkinnedModel(game, model));
        }
Пример #39
0
        /// <summary>
        /// Imports a piece of geometry, but does only support meshes, no NURBS.
        /// </summary>
        /// <param name="xmlGeometryNode">XML node of the geometry</param>
        /// <exception cref="Exception">Only works with meshes</exception>
        Mesh ImportGeometry(XmlNode xmlGeometryNode, ColladaModel model)
        {
            // Find the mesh node
            XmlNode xmlMeshNode = xmlGeometryNode.SelectSingleNode(".//mesh");

            if (xmlMeshNode == null)
            {
                throw new Exception("No supported geometry (Mesh) found");
            }

            // Determine number of mesh parts
            XmlNodeList xmlTriangles = xmlMeshNode.SelectNodes("triangles|polygons|polylist");

            if (xmlTriangles.Count == 0)
            {
                throw new Exception("No triangles found in mesh. Only triangles are supported");
            }

            if (xmlTriangles[0].Name != "triangles")
            {
                // If there are polygons or a polylist, check that all of them are triangles
                if (xmlTriangles[0].Attributes["vcount"] != null)
                {
                    var vcounts      = XmlUtil.ParseInts(xmlTriangles[0].Attributes["vcount"].Value);
                    var nonTriangles = vcounts.Where(count => count != 3);
                    if (nonTriangles.Any())
                    {
                        throw new Exception("Found polygon with " + nonTriangles.First() +
                                            " elements. Only triangles are supported");
                    }
                }
            }

            // Source data for this mesh used by all mesh parts.
            List <VertexSource> sources = ReadSources(xmlMeshNode);

            Vector4[] jointIndices;
            Vector3[] jointWeights;

            // Skinning Information, if available
            GetJointWeightsAndIndices(xmlMeshNode, model, out jointIndices, out jointWeights);

            if (sources.Count == 0)
            {
                throw new Exception("No data found");
            }

            //-------------------------------------------------------
            // Create Mesh
            //-------------------------------------------------------
            Mesh mesh = new Mesh();

            mesh.Name      = XmlUtil.GetName(xmlGeometryNode);
            mesh.MeshParts = new MeshPart[xmlTriangles.Count];

            // A mesh container for every mesh part, since every mesh part may use different
            // vertex types. This can be optimized in the content processor, if needed
            mesh.VertexContainers = new VertexContainer[xmlTriangles.Count];

            string[] semantics = new string[] { "VERTEX", "COLOR", "NORMAL", "TEXCOORD", "TEXTANGENT", "TEXBINORMAL" };

            //-------------------------------------------------------
            // Create Mesh Parts
            //-------------------------------------------------------
            for (int i = 0; i < xmlTriangles.Count; i++)
            {
                XmlNode    xmlPart      = xmlTriangles[i];
                int        numTriangles = int.Parse(xmlPart.Attributes["count"].Value);
                List <int> indexStream  = new List <int>(numTriangles * 3);

                var pNodes = xmlPart.SelectNodes("p");
                if (pNodes.Count > 1)
                {
                    // Indices are scattered among numTriangles <p> tags
                    foreach (XmlNode p in pNodes)
                    {
                        indexStream.AddRange(XmlUtil.ParseInts(p.InnerText));
                    }
                }
                else
                {
                    // Indices are contained in one <p> tag
                    indexStream.AddRange(XmlUtil.ParseInts(pNodes[0].InnerText));
                }

                int[]    indices = indexStream.ToArray();
                MeshPart part    = new MeshPart();

                try
                {
                    if (xmlPart.Attributes["material"] == null)
                    {
                        throw new Exception("no material attribute found");
                    }
                    part.MaterialName = FindMaterial(xmlGeometryNode, xmlPart.Attributes["material"].Value);
                }
                catch (Exception)
                {
                    // No Material found
                    part.MaterialName = null;
                }

                // Read Vertex Channels
                List <VertexChannel> vertexChannels = new List <VertexChannel>();

                foreach (String semantic in semantics)
                {
                    XmlNode input = xmlPart.SelectSingleNode(".//input[@semantic='" + semantic + "']");
                    if (input == null)
                    {
                        continue;                // no such vertex channel defined
                    }
                    int    offset;
                    String sourceId;

                    if (!input.TryGetAttribute("source", out sourceId))
                    {
                        throw new Exception("Referenced source of input with '" + semantic + "' semantic not found");
                    }
                    if (!input.TryGetAttribute("offset", out offset))
                    {
                        throw new Exception("No offset attribute of input with '" + semantic + "' semantic found");
                    }

                    sourceId = sourceId.Replace("#", "");
                    VertexSource source = sources.Where(s => s.GlobalID.Equals(sourceId)).FirstOrDefault();
                    if (source == null)
                    {
                        if (semantic.Equals("VERTEX"))
                        {
                            sourceId = xmlGeometryNode.SelectSingleNode(".//input[@semantic='POSITION']/@source").InnerText.Substring(1);
                            source   = sources.Where(s => s.GlobalID.Equals(sourceId)).FirstOrDefault();
                        }

                        if (source == null)
                        {
                            throw new Exception("Source '" + sourceId + "' not found");
                        }
                    }

                    VertexElement desc = new VertexElement();
                    desc.Offset              = offset;
                    desc.UsageIndex          = 0;
                    desc.VertexElementFormat = GetVertexElementFormat(source, semantic);
                    desc.VertexElementUsage  = GetVertexElementUsage(semantic);

                    VertexChannel channel = new VertexChannel(source, desc);
                    channel.CopyIndices(indices, offset, numTriangles * 3);
                    vertexChannels.Add(channel);
                }

                var jointChannels = GenerateJointChannels(jointIndices, jointWeights,
                                                          vertexChannels.Where(c => c.Description.VertexElementUsage ==
                                                                               VertexElementUsage.Position).First().Indices);

                if (jointChannels != null)
                {
                    vertexChannels.Add(jointChannels.Item1);
                    vertexChannels.Add(jointChannels.Item2);
                }

                part.Vertices = new VertexContainer(vertexChannels);
                part.Indices  = part.Vertices.Indices;

                mesh.VertexContainers[i] = part.Vertices;
                mesh.MeshParts[i]        = part;
            }

            return(mesh);
        }
Пример #40
0
        /// <summary>
        /// Imports skin information
        /// </summary>
        /// <remarks>Joint weights and indices defined by skins are imported
        /// by GeometryImporter since these values have to be added to the 
        /// vertex container of the meshes.</remarks>
        /// <param name="xmlSkin"></param>
        /// <param name="model"></param>
        static void ImportSkin(XmlNode xmlSkin, ColladaModel model)
        {
            Mesh mesh = GetMeshFromSkin(xmlSkin, model);
            if (mesh == null)
            {
                throw new Exception("Mesh referenced by skin not found");
            }

            // TODO: Take bind_shape_matrix into consideration for animation

            // Read inverse bind-pose matrices and save them in the corresponding joints
            GetUpdatedJointsFromSkin(xmlSkin, model);
        }
Пример #41
0
        private void ImportAnimationClips(XmlNode xmlNode, ColladaModel model)
        {
            if (xmlNode == null || model.JointAnimations == null || !model.JointAnimations.Any())
                return;

            XmlNodeList xmlClips = xmlNode.SelectNodes("animation_clip");
            if (xmlClips == null) return;

            foreach (XmlNode xmlClip in xmlClips)
            {
                // Reference name of the animation clip: name > id > sid
                String name = xmlClip.GetAttributeString("name") ??
                              (xmlClip.GetAttributeString("id") ??
                               xmlClip.GetAttributeString("sid"));

                // Start and end times
                float start = float.Parse(xmlClip.Attributes["start"].Value,
                    CultureInfo.InvariantCulture);

                float end = float.Parse(xmlClip.Attributes["end"].Value,
                    CultureInfo.InvariantCulture);

                // Animations to be played
                XmlNodeList xmlInstances = xmlClip.SelectNodes("instance_animation");
                if (xmlInstances == null) return;

                List<JointAnimation> animations = new List<JointAnimation>();

                foreach (XmlNode xmlInstance in xmlInstances)
                {
                    // Assume url="#id"
                    String id = xmlInstance.GetAttributeString("url").Substring(1);

                    // Find animation with given id
                    var temp = from a in model.JointAnimations
                               where a.GlobalID.Equals("id")
                               select a;

                    animations.AddRange(temp);
                }

                JointAnimationClip clip = new JointAnimationClip(animations.ToArray(),
                    TimeSpan.FromSeconds(start), TimeSpan.FromSeconds(end));

                model.JointAnimationClips.Add(clip);
            }
        }
Пример #42
0
        /// <summary>
        /// Reads the given joints and all of their children recursively. Newly created joints
        /// are appended to the Children collection of the parent (if not null) and to the
        /// Joints collection of the given model.
        /// </summary>
        /// <param name="parent">Parent joint of joints to read</param>
        /// <param name="xmlNodes">XML joint nodes</param>
        /// <param name="model">Model instance with non-null joint collection</param>
        void ReadJoints(Joint parent, IEnumerable <XmlNode> xmlNodes, ColladaModel model)
        {
            bool jointWithoutId = false;

            foreach (XmlNode xmlNode in xmlNodes)
            {
                // Create joint from XML
                Joint joint = new Joint(GetNodeName(xmlNode))
                {
                    Parent    = parent,
                    Transform = CreateNodeTransform(xmlNode),
                    GlobalID  = xmlNode.GetAttributeString("id"),
                    ScopedID  = xmlNode.GetAttributeString("sid")
                };

                // Check if this joint was already added, only possible if ID is set);
                if (!String.IsNullOrEmpty(joint.GlobalID))
                {
                    if (knownJoints.ContainsKey(joint.GlobalID))
                    {
                        continue;
                    }
                    knownJoints.Add(joint.GlobalID, true);
                }
                else
                {
                    // There was a joint without ID
                    jointWithoutId = true;
                }

                // Append this joint to parents' children collection
                if (parent != null)
                {
                    if (parent.Children == null)
                    {
                        parent.Children = new JointList {
                            joint
                        }
                    }
                    ;
                    else
                    {
                        parent.Children.Add(joint);
                    }
                }

                // Add joint to model's joint collection
                joint.Index = model.Joints.Count;
                model.Joints.Add(joint);

                // Read child nodes of this joint
                XmlNodeList xmlChildren = xmlNode.SelectNodes("node");
                if (xmlChildren != null)
                {
                    ReadJoints(joint, xmlChildren.OfType <XmlNode>(), model);
                }
            }

            if (jointWithoutId)
            {
                // There were joints without IDs, these bones could be contained
                // in model's joint collection multiple times
                // TODO: Remove double joints in case of Joint without Id
            }
        }
Пример #43
0
        /// <summary>
        /// Reads the given joints and all of their children recursively. Newly created joints
        /// are appended to the Children collection of the parent (if not null) and to the
        /// Joints collection of the given model.
        /// </summary>
        /// <param name="parent">Parent joint of joints to read</param>
        /// <param name="xmlNodes">XML joint nodes</param>
        /// <param name="model">Model instance with non-null joint collection</param>
        void ReadJoints(Joint parent, IEnumerable<XmlNode> xmlNodes, ColladaModel model)
        {
            bool jointWithoutId = false;

            foreach (XmlNode xmlNode in xmlNodes)
            {
                // Create joint from XML
                Joint joint = new Joint(GetNodeName(xmlNode))
                              {
                                  Parent = parent,
                                  Transform = CreateNodeTransform(xmlNode),
                                  GlobalID = xmlNode.GetAttributeString("id"),
                                  ScopedID = xmlNode.GetAttributeString("sid")
                              };

                // Check if this joint was already added, only possible if ID is set);
                if (!String.IsNullOrEmpty(joint.GlobalID))
                {
                    if (knownJoints.ContainsKey(joint.GlobalID)) continue;
                    knownJoints.Add(joint.GlobalID, true);
                }
                else
                {
                    // There was a joint without ID
                    jointWithoutId = true;
                }

                // Append this joint to parents' children collection
                if (parent != null)
                {
                    if (parent.Children == null)
                        parent.Children = new JointList { joint };
                    else
                        parent.Children.Add(joint);
                }

                // Add joint to model's joint collection
                joint.Index = model.Joints.Count;
                model.Joints.Add(joint);

                // Read child nodes of this joint
                XmlNodeList xmlChildren = xmlNode.SelectNodes("node");
                if (xmlChildren != null)
                {
                    ReadJoints(joint, xmlChildren.OfType<XmlNode>(), model);
                }
            }

            if (jointWithoutId)
            {
                // There were joints without IDs, these bones could be contained
                // in model's joint collection multiple times
                // TODO: Remove double joints in case of Joint without Id
            }
        }