/// <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); }
/// <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; }
/// <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); }
/// <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 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> /// 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; }
/// <summary> /// Crea un mesh sin texturas, solo con VertexColors /// </summary> /// <param name="meshData"></param> private TgcSkeletalMesh crearMeshSoloColor(TgcSkeletalMeshData meshData) { //Crear Mesh Mesh mesh = new Mesh(meshData.coordinatesIndices.Length / 3, meshData.coordinatesIndices.Length, MeshFlags.Managed, VertexColorVertexElements, device); //Cargar esqueleto TgcSkeletalBone[] bones = loadSkeleton(meshData); TgcSkeletalVertexWeight[] verticesWeights = loadVerticesWeights(meshData, bones); //Cargar VertexBuffer using (VertexBuffer vb = mesh.VertexBuffer) { GraphicsStream data = vb.Lock(0, 0, LockFlags.None); for (int j = 0; j < meshData.coordinatesIndices.Length; j++) { VertexColorVertex v = new VertexColorVertex(); //vertices int coordIdx = meshData.coordinatesIndices[j] * 3; v.Position = new Vector3( meshData.verticesCoordinates[coordIdx], meshData.verticesCoordinates[coordIdx + 1], meshData.verticesCoordinates[coordIdx + 2] ); //color int colorIdx = meshData.colorIndices[j]; v.Color = meshData.verticesColors[colorIdx]; //normal if (meshData.verticesNormals != null) { v.Normal = new Vector3( meshData.verticesNormals[coordIdx], meshData.verticesNormals[coordIdx + 1], meshData.verticesNormals[coordIdx + 2] ); } else { v.Normal = new Vector3(0, 0, 0); } //tangent if (meshData.verticesTangents != null) { v.Tangent = new Vector3( meshData.verticesTangents[coordIdx], meshData.verticesTangents[coordIdx + 1], meshData.verticesTangents[coordIdx + 2] ); } else { v.Tangent = new Vector3(0, 0, 0); } //binormal if (meshData.verticesBinormals != null) { v.Binormal = new Vector3( meshData.verticesBinormals[coordIdx], meshData.verticesBinormals[coordIdx + 1], meshData.verticesBinormals[coordIdx + 2] ); } else { v.Binormal = new Vector3(0, 0, 0); } //BlendWeights y BlendIndices TgcSkeletalVertexWeight vWeight = verticesWeights[meshData.coordinatesIndices[j]]; vWeight.createVector4WeightsAndIndices(out v.BlendWeights, out v.BlendIndices); data.Write(v); } vb.Unlock(); } //Cargar indexBuffer en forma plana using (IndexBuffer ib = mesh.IndexBuffer) { short[] indices = new short[meshData.coordinatesIndices.Length]; for (int i = 0; i < indices.Length; i++) { indices[i] = (short)i; } ib.SetData(indices, 0, LockFlags.None); } //Crear mesh de TGC TgcSkeletalMesh tgcMesh = meshFactory.createNewMesh(mesh, meshData.name, TgcSkeletalMesh.MeshRenderType.VERTEX_COLOR, bones); return(tgcMesh); }
/// <summary> /// Crea un mesh con uno o varios DiffuseMap /// </summary> /// <returns></returns> private TgcSkeletalMesh crearMeshDiffuseMap(TgcSkeletalLoaderMaterialAux[] materialsArray, TgcSkeletalMeshData meshData) { //Crear Mesh Mesh mesh = new Mesh(meshData.coordinatesIndices.Length / 3, meshData.coordinatesIndices.Length, MeshFlags.Managed, DiffuseMapVertexElements, device); //Cargar esqueleto TgcSkeletalBone[] bones = loadSkeleton(meshData); TgcSkeletalVertexWeight[] verticesWeights = loadVerticesWeights(meshData, bones); //Cargar VertexBuffer using (VertexBuffer vb = mesh.VertexBuffer) { GraphicsStream data = vb.Lock(0, 0, LockFlags.None); for (int j = 0; j < meshData.coordinatesIndices.Length; j++) { DiffuseMapVertex v = new DiffuseMapVertex(); //vertices int coordIdx = meshData.coordinatesIndices[j] * 3; v.Position = new Vector3( meshData.verticesCoordinates[coordIdx], meshData.verticesCoordinates[coordIdx + 1], meshData.verticesCoordinates[coordIdx + 2] ); //texture coordinates diffuseMap int texCoordIdx = meshData.texCoordinatesIndices[j] * 2; v.Tu = meshData.textureCoordinates[texCoordIdx]; v.Tv = meshData.textureCoordinates[texCoordIdx + 1]; //color int colorIdx = meshData.colorIndices[j]; v.Color = meshData.verticesColors[colorIdx]; //normal if (meshData.verticesNormals != null) { v.Normal = new Vector3( meshData.verticesNormals[coordIdx], meshData.verticesNormals[coordIdx + 1], meshData.verticesNormals[coordIdx + 2] ); } else { v.Normal = new Vector3(0, 0, 0); } //tangent if (meshData.verticesTangents != null) { v.Tangent = new Vector3( meshData.verticesTangents[coordIdx], meshData.verticesTangents[coordIdx + 1], meshData.verticesTangents[coordIdx + 2] ); } else { v.Tangent = new Vector3(0, 0, 0); } //binormal if (meshData.verticesBinormals != null) { v.Binormal = new Vector3( meshData.verticesBinormals[coordIdx], meshData.verticesBinormals[coordIdx + 1], meshData.verticesBinormals[coordIdx + 2] ); } else { v.Binormal = new Vector3(0, 0, 0); } //BlendWeights y BlendIndices TgcSkeletalVertexWeight vWeight = verticesWeights[meshData.coordinatesIndices[j]]; vWeight.createVector4WeightsAndIndices(out v.BlendWeights, out v.BlendIndices); data.Write(v); } vb.Unlock(); } //Cargar IndexBuffer en forma plana using (IndexBuffer ib = mesh.IndexBuffer) { short[] indices = new short[meshData.coordinatesIndices.Length]; for (int j = 0; j < indices.Length; j++) { indices[j] = (short)j; } ib.SetData(indices, 0, LockFlags.None); } //Configurar Material y Textura para un solo SubSet TgcSkeletalLoaderMaterialAux matAux = materialsArray[meshData.materialId]; Material[] meshMaterials; TgcTexture[] meshTextures; if (matAux.subMaterials == null) { meshMaterials = new Material[] { matAux.materialId }; meshTextures = new TgcTexture[] { matAux.texture }; } //Configurar Material y Textura para varios SubSet else { //Cargar attributeBuffer con los id de las texturas de cada triángulo int[] attributeBuffer = mesh.LockAttributeBufferArray(LockFlags.None); Array.Copy(meshData.materialsIds, attributeBuffer, attributeBuffer.Length); mesh.UnlockAttributeBuffer(attributeBuffer); //Cargar array de Materials y Texturas meshMaterials = new Material[matAux.subMaterials.Length]; meshTextures = new TgcTexture[matAux.subMaterials.Length]; for (int m = 0; m < matAux.subMaterials.Length; m++) { meshMaterials[m] = matAux.subMaterials[m].materialId; meshTextures[m] = matAux.subMaterials[m].texture; } } //Crear mesh de TGC TgcSkeletalMesh tgcMesh = meshFactory.createNewMesh(mesh, meshData.name, TgcSkeletalMesh.MeshRenderType.DIFFUSE_MAP, bones); tgcMesh.Materials = meshMaterials; tgcMesh.DiffuseMaps = meshTextures; return(tgcMesh); }
/// <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); }