Example #1
0
        // First pass: calculate the transofmration matrix for each vertex
        // here we must associate a matrix with each bone (maybe with each vertex_id??)
        // then we multiply the current_bone matrix with the one we had before
        // (perhaps it was identity, perhaps it was already some matrix (if
        // the bone influences many vertices) )
        // then we store this multiplied matrix.
        // in the render function we get a vertex_id, so we can find the matrix to apply
        // to the vertex, then we send the vertex to OpenGL
        public void RecursiveCalculateVertexTransform(Node nd, Matrix4x4 current)
        {
            Matrix4x4 current_node = current * nd.Transform;

            foreach (int mesh_id in nd.MeshIndices)
            {
                Mesh     cur_mesh  = _scene._inner.Meshes[mesh_id];
                MeshDraw mesh_draw = _mesh_id2mesh_draw[mesh_id];
                foreach (Bone bone in cur_mesh.Bones)
                {
                    // a bone transform is more than by what we need to trasnform the model
                    BoneNode  armature_node   = _scene.GetBoneNode(bone.Name);
                    Matrix4x4 bone_global_mat = armature_node.GlobTrans;
                    /// bind tells the original delta in global coord, so we can find current delta
                    Matrix4x4 bind         = bone.OffsetMatrix;
                    Matrix4x4 delta_roto   = bind * bone_global_mat;
                    Matrix4x4 current_bone = delta_roto * current_node;
                    foreach (var pair in bone.VertexWeights)
                    {
                        // Can apply bone weight here
                        mesh_draw._vertex_id2matrix[pair.VertexID] = current_bone;
                    }
                }
            }
            foreach (Node child in nd.Children)
            {
                RecursiveCalculateVertexTransform(child, current_node);
            }
        }
Example #2
0
 /// <summary>
 /// Function to blend from one keyframe to another.
 /// </summary>
 public void ChangeLocalFixedDataBlend(ActionState st)
 {
     Debug.Assert(0 <= st.KfBlend && st.KfBlend <= 1);
     foreach (NodeAnimationChannel channel in _action.NodeAnimationChannels)
     {
         BoneNode bone_nd = _scene.GetBoneNode(channel.NodeName);
         // now rotation
         tk.Quaternion target_roto = tk.Quaternion.Identity;
         if (channel.RotationKeyCount > st.TargetKeyframe)
         {
             target_roto = channel.RotationKeys[st.TargetKeyframe].Value.eToOpenTK();
         }
         tk.Quaternion start_frame_roto = channel.RotationKeys[st.OriginKeyframe].Value.eToOpenTK();
         tk.Quaternion result_roto      = tk.Quaternion.Slerp(start_frame_roto, target_roto, (float)st.KfBlend);
         // now translation
         tk.Vector3 target_trans = tk.Vector3.Zero;
         if (channel.PositionKeyCount > st.TargetKeyframe)
         {
             target_trans = channel.PositionKeys[st.TargetKeyframe].Value.eToOpenTK();
         }
         tk.Vector3 cur_trans    = channel.PositionKeys[st.OriginKeyframe].Value.eToOpenTK();
         tk.Vector3 result_trans = cur_trans + tk.Vector3.Multiply(target_trans - cur_trans, (float)st.KfBlend);
         // combine rotation and translation
         tk.Matrix4 result = tk.Matrix4.CreateFromQuaternion(result_roto);
         result.Row3.Xyz  = result_trans;
         bone_nd.LocTrans = result.eToAssimp();
     }
 }
        public void UpdateBonePositions(BoneNode nd)
        {
            var     triangle  = _bone_id2triangle[nd._inner.Name];
            Vector3 new_start = nd.GlobalTransform.ExtractTranslation();

            if (nd.Children.Count > 0)
            {
                // this bone's end == the beginning of __any__ child bone
                Vector3 new_end = nd.Children[0].GlobalTransform.ExtractTranslation();
                triangle._start = new_start;
                triangle._end   = new_end;
                foreach (var child_nd in nd.Children)
                {
                    UpdateBonePositions(child_nd);
                }
            }
            else
            {
                // this bone has no children, we don't know where it will end, so we guess.
                // strategy 1: just set a random sensible value for bone
                // strategy 2: get geometric center of the vertices that this bone acts on
                // we have to use the Y-unit vector instead of X because we defined Y_UP
                // in the collada.dae file, so all the matrices work such that direct unit vector is unit Y
                // strategy 3: choose the length of the smallest bone found
                var     delta   = Vector3.TransformVector(Vector3.UnitY, nd.GlobalTransform);
                Vector3 new_end = new_start + Vector3.Multiply(delta, (float)_average_bone_length);
                triangle._start = new_start;
                triangle._end   = new_end;
            }
        }
        public BoneNode BuildBoneNodes(string armature_root_name)
        {
            Node     armature_root = InnerRecurFindNode(_inner.RootNode, armature_root_name);
            BoneNode root          = InnerRecurBuildBones(armature_root);

            return(root);
        }
Example #5
0
        public void LoadScene(byte[] filedata)
        {
            MemoryStream sphere       = new MemoryStream(filedata);
            var          assimp_scene = BuildAssimpScene(sphere, "dae");

            _cur_scene = new SceneWrapper(assimp_scene);
            _cur_scene.NameUnnamedMeshes();
            _cur_scene.NodeNamesAreUnique();
            // load other data
            _action_one = new NodeInterpolator(_cur_scene, _cur_scene._inner.Animations[0]);
            BoneNode armature          = _cur_scene.BuildBoneNodes("Armature");
            string   mesh_default_name = "Cube";
            Node     mesh = _cur_scene.FindNode(mesh_default_name);

            if (mesh == null)
            {
                throw new Exception("Could not find node named " + mesh_default_name);
            }
            ActionState state = new ActionState(_cur_scene._inner.Animations[0]);

            _enttity_one = new Entity(_cur_scene, mesh, armature, state);
            state._owner = _enttity_one;
            _action_one.ApplyAnimation(_enttity_one._armature, _enttity_one._action);
            HasScene = true;
        }
Example #6
0
 // Updates global transforms by walking the hierarchy
 private void ReCalculateGlobalTransform(BoneNode nd)
 {
     nd.GlobalTransform = nd.LocalTransform * nd.Parent.GlobalTransform;
     foreach (var child in nd.Children)
     {
         ReCalculateGlobalTransform(child);
     }
 }
 // make triangles to draw for each bone
 private void MakeBoundingTriangles(BoneNode nd)
 {
     _bone_id2triangle[nd._inner.Name] = new BoneBounds();
     for (int i = 0; i < nd._inner.ChildCount; i++)
     {
         MakeBoundingTriangles(nd.Children[i]);
     }
 }
        public double FindAverageBoneLength(BoneNode nd)
        {
            double len = 0;
            int    qty = 0;

            InnerFindAverageLength(nd, ref len, ref qty);
            return(len / qty);
        }
 /// Build geometry data for node (usually use only for one of the children of scene.RootNode)
 public Geometry(IList <Mesh> scene_meshes, Node nd, BoneNode armature)
 {
     MakeBoundingBoxes(scene_meshes, nd);
     MakeBoundingTriangles(armature);
     _average_bone_length = FindAverageBoneLength(armature);
     UpdateBonePositions(armature);
     EntityBox = new BoundingBoxGroup(_mesh_id2box.Values);
 }
Example #10
0
 // the only public constructor
 // TODO: change the "Node mesh". This should point to MeshDraw object which is unique to each entity.
 public Entity(SceneWrapper sc, Node mesh, BoneNode armature, ActionState state)
 {
     _scene          = sc;
     _node           = mesh;
     _extra_geometry = new Geometry(sc._inner.Meshes, mesh, armature);
     _armature       = armature;
     _action         = state;
     _transform      = new TransformState(Matrix4.Identity, 10, 17);
 }
Example #11
0
        // Update this particular armature to this particular frame in action (to this particular keyframe)
        public void ApplyAnimation(BoneNode armature, ActionState st)
        {
            ChangeLocalFixedDataBlend(st);
            var root_node = armature;

            root_node.GlobalTransform = root_node.LocalTransform * st.GlobalTransform;
            foreach (var child in root_node.Children)
            {
                ReCalculateGlobalTransform(child);
            }
        }
Example #12
0
        private ArmatureTreeNode MakeArmatureTree(Entity ent, BoneNode nd)
        {
            var current = new ArmatureTreeNode(nd._inner.Name);

            current.DrawData = ent._extra_geometry._bone_id2triangle[nd._inner.Name];
            foreach (var child_nd in nd.Children)
            {
                var treeview_child = MakeArmatureTree(ent, child_nd);
                current.Nodes.Add(treeview_child);
            }
            return(current);
        }
Example #13
0
        private BoneNode InnerRecurBuildBones(Node nd)
        {
            var current = new BoneNode(nd);

            current.GlobTrans = GetNodeGlobalTransform(nd);
            current.LocTrans  = nd.Transform;
            // add to dict for faster lookup
            _name2bone_node[nd.Name] = current;
            foreach (var child in nd.Children)
            {
                BoneNode w_child = InnerRecurBuildBones(child);
                w_child.Parent = current;
                current.Children.Add(w_child);
            }
            return(current);
        }
        public void InnerFindAverageLength(BoneNode nd, ref double total_length, ref int bones_count)
        {
            var     triangle   = _bone_id2triangle[nd._inner.Name];
            Vector3 bone_start = nd.GlobalTransform.ExtractTranslation();

            // dont analyse bones with no children
            if (nd.Children.Count > 0)
            {
                // this bone's end == the beginning of __any__ child bone
                Vector3 bone_end = nd.Children[0].GlobalTransform.ExtractTranslation();
                double  len      = (bone_start - bone_end).Length;
                total_length += len;
                bones_count++;
                foreach (var child_nd in nd.Children)
                {
                    InnerFindAverageLength(child_nd, ref total_length, ref bones_count);
                }
            }
        }
Example #15
0
 public ArmatureEntity(Scene sc, BoneNode arma)
 {
     _armature = arma;
     _scene    = sc;
 }