Exemplo n.º 1
0
 /// <summary>
 /// Crear un modelo adjunto a un hueso
 /// </summary>
 /// <param name="model">Modelo a adjuntar</param>
 /// <param name="bone">Hueso al cual adjuntarse</param>
 /// <param name="offset">Offset desde el cual el modelo sigue al hueso</param>
 public TgcSkeletalBoneAttach(TgcMesh mesh, TgcSkeletalBone bone, Matrix offset)
 {
     this.bone = bone;
     this.mesh = mesh;
     this.offset = offset;
     updateValues();
 }
Exemplo n.º 2
0
 /// <summary>
 /// Actualizar los vertices de la malla segun las posiciones del los huesos del esqueleto
 /// </summary>
 protected void updateMeshVertices()
 {
     //Precalcular la multiplicación para llevar a un vertice a Bone-Space y luego transformarlo segun el hueso
     //Estas matrices se envian luego al Vertex Shader para hacer skinning en GPU
     for (int i = 0; i < bones.Length; i++)
     {
         TgcSkeletalBone bone = bones[i];
         boneSpaceFinalTransforms[i] = bone.MatInversePose * bone.MatFinal;
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Prepara una nueva animacion para ser ejecutada
        /// </summary>
        protected void initAnimationSettings(string animationName, bool playLoop, float userFrameRate)
        {
            isAnimating      = true;
            currentAnimation = animations[animationName];
            this.playLoop    = playLoop;
            currentTime      = 0;
            currentFrame     = 0;

            //Cambiar BoundingBox
            boundingBox = currentAnimation.BoundingBox;
            updateBoundingBox();

            //Si el usuario no especifico un FrameRate, tomar el default de la animacion
            if (userFrameRate == -1f)
            {
                frameRate = (float)currentAnimation.FrameRate;
            }
            else
            {
                frameRate = userFrameRate;
            }

            //La duracion de la animacion.
            animationTimeLenght = ((float)currentAnimation.FramesCount - 1) / frameRate;


            //Configurar postura inicial de los huesos
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                if (!currentAnimation.hasFrames(i))
                {
                    throw new Exception("El hueso " + bone.Name + " no posee KeyFrames");
                }

                //Determinar matriz local inicial
                TgcSkeletalAnimationFrame firstFrame = currentAnimation.BoneFrames[i][0];
                bone.MatLocal = Matrix.RotationQuaternion(firstFrame.Rotation) * Matrix.Translation(firstFrame.Position);

                //Multiplicar por matriz del padre, si tiene
                if (bone.ParentBone != null)
                {
                    bone.MatFinal = bone.MatLocal * bone.ParentBone.MatFinal;
                }
                else
                {
                    bone.MatFinal = bone.MatLocal;
                }
            }


            //Ajustar vertices a posicion inicial del esqueleto
            updateMeshVertices();
        }
Exemplo n.º 4
0
        /// <summary>
        /// Actualiza la posicion de cada hueso del esqueleto segun sus KeyFrames de la animacion
        /// </summary>
        protected void updateSkeleton()
        {
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                //Tomar el frame actual para este hueso
                List <TgcSkeletalAnimationFrame> boneFrames = currentAnimation.BoneFrames[i];

                //Solo hay un frame, no hacer nada, ya se hizo en el init de la animacion
                if (boneFrames.Count == 1)
                {
                    continue;
                }

                //Obtener cuadro actual segun el tiempo transcurrido
                float currentFrameF = currentTime * frameRate;
                //Ve a que KeyFrame le corresponde
                int keyFrameIdx = getCurrentFrameBone(boneFrames, currentFrameF);
                this.currentFrame = keyFrameIdx;

                //Armar un intervalo entre el proximo KeyFrame y el anterior
                TgcSkeletalAnimationFrame frame1 = boneFrames[keyFrameIdx - 1];
                TgcSkeletalAnimationFrame frame2 = boneFrames[keyFrameIdx];

                //Calcular la cantidad que hay interpolar en base al la diferencia entre cuadros
                float framesDiff         = frame2.Frame - frame1.Frame;
                float interpolationValue = (currentFrameF - frame1.Frame) / framesDiff;

                //Interpolar traslacion
                Vector3 frameTranslation = (frame2.Position - frame1.Position) * interpolationValue + frame1.Position;

                //Interpolar rotacion con SLERP
                Quaternion quatFrameRotation = Quaternion.Slerp(frame1.Rotation, frame2.Rotation, interpolationValue);

                //Unir ambas transformaciones de este frame
                Matrix frameMatrix = Matrix.RotationQuaternion(quatFrameRotation) * Matrix.Translation(frameTranslation);

                //Multiplicar por la matriz del padre, si tiene
                if (bone.ParentBone != null)
                {
                    bone.MatFinal = frameMatrix * bone.ParentBone.MatFinal;
                }
                else
                {
                    bone.MatFinal = frameMatrix;
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Cargar Weights de vertices
        /// </summary>
        /// <param name="meshData"></param>
        /// <returns></returns>
        private TgcSkeletalVertexWeight[] loadVerticesWeights(TgcSkeletalMeshData meshData, TgcSkeletalBone[] bones)
        {
            //Crear un array de Weights para cada uno de los vertices de la malla
            TgcSkeletalVertexWeight[] weights = new TgcSkeletalVertexWeight[meshData.verticesCoordinates.Length / 3];
            float[] vertexWeightTotals        = new float[weights.Length];
            for (int i = 0; i < weights.Length; i++)
            {
                weights[i]            = new TgcSkeletalVertexWeight();
                vertexWeightTotals[i] = 0;
            }

            //Cargar los weights de cada vertice
            int weightsCount = meshData.verticesWeights.Length / 3;

            for (int i = 0; i < weightsCount; i++)
            {
                int   vertexIdx = (int)meshData.verticesWeights[i * 3];
                int   boneIdx   = (int)meshData.verticesWeights[i * 3 + 1];
                float weightVal = meshData.verticesWeights[i * 3 + 2];

                TgcSkeletalBone bone = bones[boneIdx];
                TgcSkeletalVertexWeight.BoneWeight weight = new TgcSkeletalVertexWeight.BoneWeight(bone, weightVal);

                weights[vertexIdx].Weights.Add(weight);

                //acumular total de weight para ese vertice, para luego poder normalizar
                vertexWeightTotals[vertexIdx] += weightVal;
            }

            //Normalizar weights de cada vertice
            for (int i = 0; i < weights.Length; i++)
            {
                TgcSkeletalVertexWeight vertexWeight = weights[i];
                float vTotal = vertexWeightTotals[i];

                //Normalizar cada valor segun el total acumulado en el vertice
                foreach (TgcSkeletalVertexWeight.BoneWeight w in vertexWeight.Weights)
                {
                    w.Weight = w.Weight / vTotal;
                }
            }

            return(weights);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Configuracion inicial del esquleto
        /// </summary>
        protected void setupSkeleton()
        {
            //Actualizar jerarquia
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                //Es hijo o padre
                if (bone.ParentBone == null)
                {
                    bone.MatFinal = bone.MatLocal;
                }
                else
                {
                    //Multiplicar por la matriz del padre
                    bone.MatFinal = bone.MatLocal * bone.ParentBone.MatFinal;
                }

                //Almacenar la inversa de la posicion original del hueso, para la referencia inicial de los vertices
                bone.MatInversePose = Matrix.Invert(bone.MatFinal);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Crea mallas a modo Debug para visualizar la configuración del esqueleto
        /// </summary>
        public void buildSkletonMesh()
        {
            //Crear array para dibujar los huesos y joints
            Color   jointsColor = Color.Violet;
            Color   bonesColor  = Color.Yellow;
            Vector3 jointsSize  = new Vector3(2, 2, 2);
            Vector3 ceroVec     = new Vector3(0, 0, 0);

            skeletonRenderJoints = new TgcBox[bones.Length];
            skeletonRenderBones  = new TgcLine[bones.Length];
            int boneColor = Color.Yellow.ToArgb();

            //Actualizar jerarquia
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBone bone = bones[i];

                //Es hijo o padre
                if (bone.ParentBone == null)
                {
                    skeletonRenderBones[i] = null;
                }
                else
                {
                    //Crear linea de hueso para renderziar esqueleto
                    TgcLine boneLine = new TgcLine();
                    boneLine.PStart        = TgcVectorUtils.transform(ceroVec, bone.MatFinal);
                    boneLine.PEnd          = TgcVectorUtils.transform(ceroVec, bone.ParentBone.MatFinal);
                    boneLine.Color         = bonesColor;
                    skeletonRenderBones[i] = boneLine;
                }
                //Crear malla de Joint para renderizar el esqueleto
                TgcBox jointBox = TgcBox.fromSize(jointsSize, jointsColor);
                jointBox.AutoTransformEnable = false;
                skeletonRenderJoints[i]      = jointBox;
            }
        }
Exemplo n.º 8
0
 /// <summary>
 /// Crea una nueva malla.
 /// </summary>
 /// <param name="mesh">Mesh de DirectX</param>
 /// <param name="renderType">Formato de renderizado de la malla</param>
 /// <param name="bones">Datos de los huesos</param>
 public TgcSkeletalMesh(Mesh mesh, string name, MeshRenderType renderType, TgcSkeletalBone[] bones)
 {
     this.initData(mesh, name, renderType, bones);
 }
Exemplo n.º 9
0
 public BoneWeight(TgcSkeletalBone bone, float weight)
 {
     this.bone = bone;
     this.weight = weight;
 }
Exemplo n.º 10
0
 public TgcSkeletalMesh createNewMesh(Mesh d3dMesh, string meshName, TgcSkeletalMesh.MeshRenderType renderType, TgcSkeletalBone[] bones)
 {
     return new TgcSkeletalMesh(d3dMesh, meshName, renderType, bones);
 }
Exemplo n.º 11
0
        /// <summary>
        /// Cargar Weights de vertices
        /// </summary>
        /// <param name="meshData"></param>
        /// <returns></returns>
        private TgcSkeletalVertexWeight[] loadVerticesWeights(TgcSkeletalMeshData meshData, TgcSkeletalBone[] bones)
        {
            int maxWeights = 4;
            TgcSkeletalVertexWeight.BoneWeight.GreaterComparer weightComparer = new TgcSkeletalVertexWeight.BoneWeight.GreaterComparer();

            //Crear un array de Weights para cada uno de los vertices de la malla
            TgcSkeletalVertexWeight[] weights = new TgcSkeletalVertexWeight[meshData.verticesCoordinates.Length / 3];
            for (int i = 0; i < weights.Length; i++)
			{
			    weights[i] = new TgcSkeletalVertexWeight();
			}

            //Cargar los weights de cada vertice
            int weightsCount = meshData.verticesWeights.Length / 3;
            for (int i = 0; i < weightsCount; i++)
            {
                int vertexIdx = (int)meshData.verticesWeights[i * 3];
                int boneIdx = (int)meshData.verticesWeights[i * 3 + 1];
                float weightVal = meshData.verticesWeights[i * 3 + 2];

                TgcSkeletalBone bone = bones[boneIdx];
                TgcSkeletalVertexWeight.BoneWeight weight = new TgcSkeletalVertexWeight.BoneWeight(bone, weightVal);

                weights[vertexIdx].Weights.Add(weight);
            }

            //Normalizar weights de cada vertice
            for (int i = 0; i < weights.Length; i++)
            {
                TgcSkeletalVertexWeight vertexWeight = weights[i];

                //Se soportan hasta 4 weights por vertice. Si hay mas se quitan y se reparten las influencias entre el resto de los huesos
                if (vertexWeight.Weights.Count > maxWeights)
                {
                    //Ordenar por weight de menor a mayor y luego revertir, para que quede de mayor a menor peso
                    vertexWeight.Weights.Sort(weightComparer);
                    vertexWeight.Weights.Reverse();
                    
                    //Quitar los ultimos los weight que superan 4
                    while (vertexWeight.Weights.Count > maxWeights)
                    {
                        vertexWeight.Weights.RemoveAt(vertexWeight.Weights.Count - 1);
                    }
                }

                //Sumar el total de todos los weights de este vertice
                float weightTotal = 0;
                foreach (TgcSkeletalVertexWeight.BoneWeight w in vertexWeight.Weights)
                {
                    weightTotal += w.Weight;
                }

                //Normalizar cada valor segun el total acumulado en el vertice
                foreach (TgcSkeletalVertexWeight.BoneWeight w in vertexWeight.Weights)
                {
                    w.Weight = w.Weight / weightTotal;
                }
            }

            return weights;
        }
Exemplo n.º 12
0
        /// <summary>
        /// Cargar estructura de esqueleto
        /// </summary>
        private TgcSkeletalBone[] loadSkeleton(TgcSkeletalMeshData meshData)
        {
            //Crear huesos
            TgcSkeletalBone[] bones = new TgcSkeletalBone[meshData.bones.Length];
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBoneData boneData = meshData.bones[i];

                TgcSkeletalBone bone = new TgcSkeletalBone(i, boneData.name,
                    new Vector3(boneData.startPosition[0], boneData.startPosition[1], boneData.startPosition[2]),
                    new Quaternion(boneData.startRotation[0], boneData.startRotation[1], boneData.startRotation[2], boneData.startRotation[3])
                    );
                bones[i] = bone;
            }

            //Cargar padres en huesos
            for (int i = 0; i < bones.Length; i++)
            {
                TgcSkeletalBoneData boneData = meshData.bones[i];
                if (boneData.parentId == -1)
                {
                    bones[i].ParentBone = null;
                }
                else
                {
                    bones[i].ParentBone = bones[boneData.parentId];
                }
            }

            return bones;
        }
Exemplo n.º 13
0
        /// <summary>
        /// Cargar Weights de vertices
        /// </summary>
        /// <param name="meshData"></param>
        /// <returns></returns>
        private TgcSkeletalVertexWeight[] loadVerticesWeights(TgcSkeletalMeshData meshData, TgcSkeletalBone[] bones)
        {
            //Crear un array de Weights para cada uno de los vertices de la malla
            TgcSkeletalVertexWeight[] weights = new TgcSkeletalVertexWeight[meshData.verticesCoordinates.Length / 3];
            float[] vertexWeightTotals = new float[weights.Length];
            for (int i = 0; i < weights.Length; i++)
            {
                weights[i] = new TgcSkeletalVertexWeight();
                vertexWeightTotals[i] = 0;
            }

            //Cargar los weights de cada vertice
            int weightsCount = meshData.verticesWeights.Length / 3;
            for (int i = 0; i < weightsCount; i++)
            {
                int vertexIdx = (int)meshData.verticesWeights[i * 3];
                int boneIdx = (int)meshData.verticesWeights[i * 3 + 1];
                float weightVal = meshData.verticesWeights[i * 3 + 2];

                TgcSkeletalBone bone = bones[boneIdx];
                TgcSkeletalVertexWeight.BoneWeight weight = new TgcSkeletalVertexWeight.BoneWeight(bone, weightVal);

                weights[vertexIdx].Weights.Add(weight);

                //acumular total de weight para ese vertice, para luego poder normalizar
                vertexWeightTotals[vertexIdx] += weightVal;
            }

            //Normalizar weights de cada vertice
            for (int i = 0; i < weights.Length; i++)
            {
                TgcSkeletalVertexWeight vertexWeight = weights[i];
                float vTotal = vertexWeightTotals[i];

                //Normalizar cada valor segun el total acumulado en el vertice
                foreach (TgcSkeletalVertexWeight.BoneWeight w in vertexWeight.Weights)
                {
                    w.Weight = w.Weight / vTotal;
                }
            }

            return weights;
        }
Exemplo n.º 14
0
        /// <summary>
        /// Cargar datos iniciales
        /// </summary>
        protected void initData(Mesh mesh, string name, MeshRenderType renderType, TgcSkeletalBone[] bones)
        {
            this.d3dMesh = mesh;
            this.name = name;
            this.renderType = renderType;
            this.enabled = false;
            this.autoUpdateBoundingBox = true;
            this.bones = bones;
            this.attachments = new List<TgcSkeletalBoneAttach>();
            this.meshInstances = new List<TgcSkeletalMesh>();
            this.renderSkeleton = false;
            this.alphaBlendEnable = false;

            //variables de movimiento
            this.autoTransformEnable = true;
            this.translation = new Vector3(0f, 0f, 0f);
            this.rotation = new Vector3(0f, 0f, 0f);
            this.scale = new Vector3(1f, 1f, 1f);
            this.transform = Matrix.Identity;

            //variables de animacion
            this.isAnimating = false;
            this.currentAnimation = null;
            this.playLoop = false;
            this.frameRate = 0f;
            this.currentTime = 0f;
            this.animationTimeLenght = 0f;
            this.currentFrame = 0;
            this.animations = new Dictionary<string, TgcSkeletalAnimation>();

            //Matrices de huesos
            this.boneSpaceFinalTransforms = new Matrix[MAX_BONE_COUNT];

            //Shader
            vertexDeclaration = new VertexDeclaration(mesh.Device, mesh.Declaration);
            this.effect = GuiController.Instance.Shaders.TgcSkeletalMeshShader;
            this.technique = GuiController.Instance.Shaders.getTgcSkeletalMeshTechnique(this.renderType);

            //acomodar huesos
            setupSkeleton();
        }
Exemplo n.º 15
0
 /// <summary>
 /// Crea una nueva malla.
 /// </summary>
 /// <param name="mesh">Mesh de DirectX</param>
 /// <param name="renderType">Formato de renderizado de la malla</param>
 /// <param name="origData">Datos originales de la malla que hay almacenar</param>
 /// <param name="bones">Datos de los huesos</param>
 /// <param name="verticesWeights">Datos de los Weights para cada vertice</param>
 public TgcSkeletalMesh(Mesh mesh, string name, MeshRenderType renderType, OriginalData origData, TgcSkeletalBone[] bones, TgcSkeletalVertexWeight[] verticesWeights)
 {
     this.initData(mesh, name, renderType, origData, bones, verticesWeights);
 }
Exemplo n.º 16
0
        /// <summary>
        /// Cargar datos iniciales
        /// </summary>
        protected void initData(Mesh mesh, string name, MeshRenderType renderType, OriginalData originalData, TgcSkeletalBone[] bones, TgcSkeletalVertexWeight[] verticesWeights)
        {
            this.d3dMesh = mesh;
            this.name = name;
            this.renderType = renderType;
            this.originalData = originalData;
            this.enabled = false;
            this.autoUpdateBoundingBox = true;
            this.bones = bones;
            this.verticesWeights = verticesWeights;
            this.attachments = new List<TgcSkeletalBoneAttach>();
            this.meshInstances = new List<TgcSkeletalMesh>();
            this.renderSkeleton = false;
            this.alphaBlendEnable = false;

            //Crear vertexDeclaration
            vertexDeclaration = new VertexDeclaration(mesh.Device, mesh.Declaration);

            //variables de movimiento
            this.autoTransformEnable = true;
            this.translation = new Vector3(0f, 0f, 0f);
            this.rotation = new Vector3(0f, 0f, 0f);
            this.scale = new Vector3(1f, 1f, 1f);
            this.transform = Matrix.Identity;

            //variables de animacion
            this.isAnimating = false;
            this.currentAnimation = null;
            this.playLoop = false;
            this.frameRate = 0f;
            this.currentTime = 0f;
            this.animationTimeLenght = 0f;
            this.currentFrame = 0;
            this.animations = new Dictionary<string, TgcSkeletalAnimation>();

            //acomodar huesos
            setupSkeleton();
        }
 public BoneWeight(TgcSkeletalBone bone, float weight)
 {
     this.bone   = bone;
     this.weight = weight;
 }
Exemplo n.º 18
0
 public TgcSkeletalMesh createNewMesh(Mesh d3dMesh, string meshName, TgcSkeletalMesh.MeshRenderType renderType, TgcSkeletalMesh.OriginalData origData, TgcSkeletalBone[] bones, TgcSkeletalVertexWeight[] verticesWeights)
 {
     return new TgcSkeletalMesh(d3dMesh, meshName, renderType, origData, bones, verticesWeights);
 }
 /// <summary>
 /// Primer constructor de TgcSkeletalMesh.
 /// No se hace nada, solo se llama al constructor del padre.
 /// </summary>
 public MyCustomMesh(Mesh mesh, string name, MeshRenderType renderType, TgcSkeletalBone[] bones)
     : base(mesh, name, renderType, bones)
 {
 }
Exemplo n.º 20
0
        /// <summary>
        /// Cargar Weights de vertices
        /// </summary>
        /// <param name="meshData"></param>
        /// <returns></returns>
        private TgcSkeletalVertexWeight[] loadVerticesWeights(TgcSkeletalMeshData meshData, TgcSkeletalBone[] bones)
        {
            int maxWeights = 4;

            TgcSkeletalVertexWeight.BoneWeight.GreaterComparer weightComparer = new TgcSkeletalVertexWeight.BoneWeight.GreaterComparer();

            //Crear un array de Weights para cada uno de los vertices de la malla
            TgcSkeletalVertexWeight[] weights = new TgcSkeletalVertexWeight[meshData.verticesCoordinates.Length / 3];
            for (int i = 0; i < weights.Length; i++)
            {
                weights[i] = new TgcSkeletalVertexWeight();
            }

            //Cargar los weights de cada vertice
            int weightsCount = meshData.verticesWeights.Length / 3;

            for (int i = 0; i < weightsCount; i++)
            {
                int   vertexIdx = (int)meshData.verticesWeights[i * 3];
                int   boneIdx   = (int)meshData.verticesWeights[i * 3 + 1];
                float weightVal = meshData.verticesWeights[i * 3 + 2];

                TgcSkeletalBone bone = bones[boneIdx];
                TgcSkeletalVertexWeight.BoneWeight weight = new TgcSkeletalVertexWeight.BoneWeight(bone, weightVal);

                weights[vertexIdx].Weights.Add(weight);
            }

            //Normalizar weights de cada vertice
            for (int i = 0; i < weights.Length; i++)
            {
                TgcSkeletalVertexWeight vertexWeight = weights[i];

                //Se soportan hasta 4 weights por vertice. Si hay mas se quitan y se reparten las influencias entre el resto de los huesos
                if (vertexWeight.Weights.Count > maxWeights)
                {
                    //Ordenar por weight de menor a mayor y luego revertir, para que quede de mayor a menor peso
                    vertexWeight.Weights.Sort(weightComparer);
                    vertexWeight.Weights.Reverse();

                    //Quitar los ultimos los weight que superan 4
                    while (vertexWeight.Weights.Count > maxWeights)
                    {
                        vertexWeight.Weights.RemoveAt(vertexWeight.Weights.Count - 1);
                    }
                }

                //Sumar el total de todos los weights de este vertice
                float weightTotal = 0;
                foreach (TgcSkeletalVertexWeight.BoneWeight w in vertexWeight.Weights)
                {
                    weightTotal += w.Weight;
                }

                //Normalizar cada valor segun el total acumulado en el vertice
                foreach (TgcSkeletalVertexWeight.BoneWeight w in vertexWeight.Weights)
                {
                    w.Weight = w.Weight / weightTotal;
                }
            }

            return(weights);
        }