private MeshDesc BuildMeshDesc(string name, Material material, List <Vertex> vertices, List <Face> faces) { MeshDesc meshDesc = new MeshDesc(); meshDesc.name = name; meshDesc.vertices = new MeshDesc.Vertex[vertices.Count]; for (int i = 0; i < vertices.Count; i++) { MeshDesc.Vertex v = new MeshDesc.Vertex(); v.position = vertices[i].coord; v.normal = vertices[i].normal; v.texCoords = new Vector2[] { vertices[i].texCoord }; v.color = vertices[i].color; v.boneIndicesGlobal = new short[] { 0, 0, 0, 0 }; v.boneIndicesLocal = new short[] { 0, 0, 0, 0 }; v.boneWeights = new float[] { 1, 0, 0, 0 }; meshDesc.vertices[i] = v; } meshDesc.indices = new ushort[faces.Count * 3]; int j = 0; for (int i = 0; i < faces.Count; i++) { meshDesc.indices[j + 0] = (ushort)faces[i].vertexIndices[0]; meshDesc.indices[j + 1] = (ushort)faces[i].vertexIndices[1]; meshDesc.indices[j + 2] = (ushort)faces[i].vertexIndices[2]; j += 3; } meshDesc.boneIndexMap = new short[] { 0 }; meshDesc.uvLayerCount = 1; CalculateTangents(meshDesc); MeshDesc.Texture textureDiffuse = new MeshDesc.Texture(); textureDiffuse.filename = material.textureDiffuse; textureDiffuse.uvLayerIndex = 0; MeshDesc.Texture textureLightmap = null; MeshDesc.Texture textureNormal = null; if (material.textureNormal != null) { textureNormal = new MeshDesc.Texture(); textureNormal.filename = material.textureNormal; textureNormal.uvLayerIndex = 0; } MeshDesc.Texture textureSpecular = null; if (material.textureSpecular != null) { textureSpecular = new MeshDesc.Texture(); textureSpecular.filename = material.textureSpecular; textureSpecular.uvLayerIndex = 0; } meshDesc.textures = new MeshDesc.Texture[] { textureDiffuse, textureLightmap, textureNormal, textureSpecular }; meshDesc.renderParams = new object[] { material.specular }; meshDesc.isShadeless = material.ambient > 0.99f; return(meshDesc); }
private static void RegisterVertex(MeshDesc.Vertex vertex, Dictionary <MeshDesc.Vertex, ushort> vertexMap, List <MeshDesc.Vertex> vertexList, List <ushort> indices) { ushort index; if (!vertexMap.TryGetValue(vertex, out index)) { index = (ushort)vertexList.Count; vertexMap[vertex] = index; vertexList.Add(vertex); } indices.Add(index); }
public static void TransformVertex( MeshDesc.Vertex vertex, Matrix worldMatrix, Matrix[] boneMatrices, short[] boneIndexMap, out Vector3 position, out Vector3 normal) { Matrix m = boneMatrices[boneIndexMap[vertex.boneIndicesLocal[0]]] * vertex.boneWeights[0] + boneMatrices[boneIndexMap[vertex.boneIndicesLocal[1]]] * vertex.boneWeights[1] + boneMatrices[boneIndexMap[vertex.boneIndicesLocal[2]]] * vertex.boneWeights[2] + boneMatrices[boneIndexMap[vertex.boneIndicesLocal[3]]] * vertex.boneWeights[3]; m *= worldMatrix; position = Vector3.Transform(vertex.position, m); m.M41 = 0; m.M42 = 0; m.M43 = 0; normal = Vector3.Transform(vertex.normal, m); }
private static bool BelongsToThorGauntletRight(MeshDesc.Vertex vertex) { return(vertex.position.Y > 1.25 && vertex.position.X < 0); }
private static bool BelongsToThorBelt(MeshDesc.Vertex vertex) { return(vertex.position.Y < 1.25); }
public static void SplitThorWireframe(Model model) { MeshDesc meshDesc = model.GetMeshDesc("thorwireframe"); if (meshDesc == null) { return; } model.RemoveMeshDesc(meshDesc.name); Dictionary <MeshDesc.Vertex, ushort> vertexMapBelt = new Dictionary <MeshDesc.Vertex, ushort>(); Dictionary <MeshDesc.Vertex, ushort> vertexMapGauntletLeft = new Dictionary <MeshDesc.Vertex, ushort>(); Dictionary <MeshDesc.Vertex, ushort> vertexMapGauntletRight = new Dictionary <MeshDesc.Vertex, ushort>(); List <MeshDesc.Vertex> vertexListBelt = new List <MeshDesc.Vertex>(); List <MeshDesc.Vertex> vertexListGauntletLeft = new List <MeshDesc.Vertex>(); List <MeshDesc.Vertex> vertexListGauntletRight = new List <MeshDesc.Vertex>(); List <ushort> indicesBelt = new List <ushort>(); List <ushort> indicesGauntletLeft = new List <ushort>(); List <ushort> indicesGauntletRight = new List <ushort>(); for (int i = 0; i < meshDesc.indices.Length; i += 3) { ushort i1 = meshDesc.indices[i + 0]; ushort i2 = meshDesc.indices[i + 1]; ushort i3 = meshDesc.indices[i + 2]; MeshDesc.Vertex v1 = meshDesc.vertices[i1]; MeshDesc.Vertex v2 = meshDesc.vertices[i2]; MeshDesc.Vertex v3 = meshDesc.vertices[i3]; if (BelongsToThorBelt(v1) || BelongsToThorBelt(v2) || BelongsToThorBelt(v3)) { RegisterVertex(v1, vertexMapBelt, vertexListBelt, indicesBelt); RegisterVertex(v2, vertexMapBelt, vertexListBelt, indicesBelt); RegisterVertex(v3, vertexMapBelt, vertexListBelt, indicesBelt); } if (BelongsToThorGauntletLeft(v1) || BelongsToThorGauntletLeft(v2) || BelongsToThorGauntletLeft(v3)) { RegisterVertex(v1, vertexMapGauntletLeft, vertexListGauntletLeft, indicesGauntletLeft); RegisterVertex(v2, vertexMapGauntletLeft, vertexListGauntletLeft, indicesGauntletLeft); RegisterVertex(v3, vertexMapGauntletLeft, vertexListGauntletLeft, indicesGauntletLeft); } if (BelongsToThorGauntletRight(v1) || BelongsToThorGauntletRight(v2) || BelongsToThorGauntletRight(v3)) { RegisterVertex(v1, vertexMapGauntletRight, vertexListGauntletRight, indicesGauntletRight); RegisterVertex(v2, vertexMapGauntletRight, vertexListGauntletRight, indicesGauntletRight); RegisterVertex(v3, vertexMapGauntletRight, vertexListGauntletRight, indicesGauntletRight); } } MeshDesc meshDescBelt = DeriveMeshDesc(meshDesc, "thorglowbelt", vertexListBelt.ToArray(), indicesBelt.ToArray()); MeshDesc meshDescGauntletLeft = DeriveMeshDesc(meshDesc, "thorglowgauntletleft", vertexListGauntletLeft.ToArray(), indicesGauntletLeft.ToArray()); MeshDesc meshDescGauntletRight = DeriveMeshDesc(meshDesc, "thorglowgauntletright", vertexListGauntletRight.ToArray(), indicesGauntletRight.ToArray()); if (meshDescBelt.vertices.Length > 0) { model.AddMeshDesc(meshDescBelt); } if (meshDescGauntletLeft.vertices.Length > 0) { model.AddMeshDesc(meshDescGauntletLeft); } if (meshDescGauntletRight.vertices.Length > 0) { model.AddMeshDesc(meshDescGauntletRight); } }
private MeshDesc LoadMesh(BinaryReader file, bool hasArmature) { MeshDesc mesh = new MeshDesc(); mesh.name = file.ReadString(); int uvLayerCount = file.ReadInt32(); mesh.uvLayerCount = uvLayerCount; int textureCount = file.ReadInt32(); mesh.textures = new MeshDesc.Texture[textureCount]; for (int textureID = 0; textureID < textureCount; textureID++) { MeshDesc.Texture texture = new MeshDesc.Texture(); texture.filename = file.ReadString(); texture.uvLayerIndex = file.ReadInt32(); mesh.textures[textureID] = texture; } Dictionary <short, short> boneIndexDict = new Dictionary <short, short>(); List <short> boneIndexMap = new List <short>(); int vertexCount = file.ReadInt32(); mesh.vertices = new MeshDesc.Vertex[vertexCount]; for (int vertexID = 0; vertexID < vertexCount; vertexID++) { MeshDesc.Vertex vertex = new MeshDesc.Vertex(); float positionX = file.ReadSingle(); float positionY = file.ReadSingle(); float positionZ = file.ReadSingle(); vertex.position = new Vector3(positionX, positionY, positionZ); float normalX = file.ReadSingle(); float normalY = file.ReadSingle(); float normalZ = file.ReadSingle(); vertex.normal = new Vector3(normalX, normalY, normalZ); float colorR = file.ReadByte() / 255.0f; float colorG = file.ReadByte() / 255.0f; float colorB = file.ReadByte() / 255.0f; float colorA = file.ReadByte() / 255.0f; vertex.color = new Vector4(colorR, colorG, colorB, 1.0f); vertex.texCoords = new Vector2[uvLayerCount]; for (int uvLayerID = 0; uvLayerID < uvLayerCount; uvLayerID++) { float texCoordX = file.ReadSingle(); float texCoordY = file.ReadSingle(); vertex.texCoords[uvLayerID] = new Vector2(texCoordX, texCoordY); } vertex.tangents = new Vector4[uvLayerCount]; for (int uvLayerID = 0; uvLayerID < uvLayerCount; uvLayerID++) { float tangentX = file.ReadSingle(); float tangentY = file.ReadSingle(); float tangentZ = file.ReadSingle(); float tangentW = file.ReadSingle(); vertex.tangents[uvLayerID] = new Vector4(tangentX, tangentY, tangentZ, tangentW); } if (hasArmature) { vertex.boneIndicesGlobal = new short[4]; vertex.boneIndicesLocal = new short[4]; for (int i = 0; i < 4; i++) { vertex.boneIndicesGlobal[i] = file.ReadInt16(); } vertex.boneWeights = new float[4]; float weightSum = 0; for (int i = 0; i < 4; i++) { float weight = file.ReadSingle(); vertex.boneWeights[i] = weight; weightSum += weight; } if (weightSum == 0) { vertex.boneWeights[0] = 1.0f; } else { if (weightSum != 1.0f) { for (int i = 0; i < 4; i++) { vertex.boneWeights[i] /= weightSum; } } } short indexDefault = -1; for (int i = 0; i < 4; i++) { if (vertex.boneWeights[i] > 0) { indexDefault = vertex.boneIndicesGlobal[i]; break; } } for (int i = 0; i < 4; i++) { short indexGlobal = vertex.boneIndicesGlobal[i]; if (vertex.boneWeights[i] == 0) { indexGlobal = indexDefault; } short indexLocal; if (!boneIndexDict.TryGetValue(indexGlobal, out indexLocal)) { indexLocal = (short)boneIndexMap.Count; boneIndexDict[indexGlobal] = indexLocal; boneIndexMap.Add(indexGlobal); } vertex.boneIndicesLocal[i] = indexLocal; } } mesh.vertices[vertexID] = vertex; } mesh.boneIndexMap = boneIndexMap.ToArray(); int faceCount = file.ReadInt32(); mesh.indices = new ushort[faceCount * 3]; int index = 0; for (int faceID = 0; faceID < faceCount; faceID++) { mesh.indices[index + 0] = (ushort)file.ReadInt32(); mesh.indices[index + 1] = (ushort)file.ReadInt32(); mesh.indices[index + 2] = (ushort)file.ReadInt32(); index += 3; } return(mesh); }
private void CalculateTangents(MeshDesc meshDesc) { Vector3[,] tangentsU = new Vector3[meshDesc.vertices.Length, meshDesc.uvLayerCount]; Vector3[,] tangentsV = new Vector3[meshDesc.vertices.Length, meshDesc.uvLayerCount]; for (int vertexID = 0; vertexID < meshDesc.vertices.Length; vertexID++) { MeshDesc.Vertex vertex = meshDesc.vertices[vertexID]; vertex.tangents = new Vector4[meshDesc.uvLayerCount]; for (int uvLayerID = 0; uvLayerID < meshDesc.uvLayerCount; uvLayerID++) { tangentsU[vertexID, uvLayerID] = Vector3.Zero; tangentsV[vertexID, uvLayerID] = Vector3.Zero; } } for (int uvLayerID = 0; uvLayerID < meshDesc.uvLayerCount; uvLayerID++) { for (int i = 0; i < meshDesc.indices.Length; i += 3) { int vertexID0 = meshDesc.indices[i + 0]; int vertexID1 = meshDesc.indices[i + 1]; int vertexID2 = meshDesc.indices[i + 2]; MeshDesc.Vertex v0 = meshDesc.vertices[vertexID0]; MeshDesc.Vertex v1 = meshDesc.vertices[vertexID1]; MeshDesc.Vertex v2 = meshDesc.vertices[vertexID2]; Vector3 p0 = v0.position; Vector3 p1 = v1.position; Vector3 p2 = v2.position; Vector3 q1 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); Vector3 q2 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); float s1 = v1.texCoords[uvLayerID].X - v0.texCoords[uvLayerID].X; float t1 = v1.texCoords[uvLayerID].Y - v0.texCoords[uvLayerID].Y; float s2 = v2.texCoords[uvLayerID].X - v0.texCoords[uvLayerID].X; float t2 = v2.texCoords[uvLayerID].Y - v0.texCoords[uvLayerID].Y; float d = s1 * t2 - s2 * t1; if (d == 0) { continue; } float k = 1 / d; Vector3 faceTangentU = new Vector3( (t2 * q1.X - t1 * q2.X) * k, (t2 * q1.Y - t1 * q2.Y) * k, (t2 * q1.Z - t1 * q2.Z) * k); Vector3 faceTangentV = new Vector3( (s1 * q2.X - s2 * q1.X) * k, (s1 * q2.Y - s2 * q1.Y) * k, (s1 * q2.Z - s2 * q1.Z) * k); if (faceTangentU.Length() > 0) { faceTangentU.Normalize(); } if (faceTangentV.Length() > 0) { faceTangentV.Normalize(); } tangentsU[vertexID0, uvLayerID] += faceTangentU; tangentsU[vertexID1, uvLayerID] += faceTangentU; tangentsU[vertexID2, uvLayerID] += faceTangentU; tangentsV[vertexID0, uvLayerID] += faceTangentV; tangentsV[vertexID1, uvLayerID] += faceTangentV; tangentsV[vertexID2, uvLayerID] += faceTangentV; } } for (int vertexID = 0; vertexID < meshDesc.vertices.Length; vertexID++) { MeshDesc.Vertex vertex = meshDesc.vertices[vertexID]; vertex.tangents = new Vector4[meshDesc.uvLayerCount]; Vector3 normal = vertex.normal; for (int uvLayerID = 0; uvLayerID < meshDesc.uvLayerCount; uvLayerID++) { Vector3 tangentU = tangentsU[vertexID, uvLayerID]; Vector3 tangentV = tangentsV[vertexID, uvLayerID]; if (tangentU.Length() > 0) { tangentU.Normalize(); } if (tangentV.Length() > 0) { tangentV.Normalize(); } Vector3 tangent = tangentU - normal * (normal * tangentU); if (tangent.Length() > 0) { tangent.Normalize(); } float w = Vector3.Dot(Vector3.Cross(normal, tangentU), tangentV) > 0 ? 1 : -1; vertex.tangents[uvLayerID] = new Vector4(tangent.X, tangent.Y, tangent.Z, w); } } }