/// <summary> /// Build final model using immutable parts and given matrices. /// </summary> /// <returns></returns> public Kkdf2MdlxBuiltModel ProcessVerticesAndBuildModel(Matrix[] matrices) { var models = new SortedDictionary <Tuple <int, bool>, Model>(); var exportedMesh = new ExportedMesh(); { int vertexBaseIndex = 0; int uvBaseIndex = 0; VertexRef[] ringBuffer = new VertexRef[4]; int ringIndex = 0; int[] triangleOrder = new int[] { 1, 3, 2 }; foreach (ImmutableMesh mesh in immultableMeshList) { for (int x = 0; x < mesh.indexAssignmentList.Length; x++) { var indexAssign = mesh.indexAssignmentList[x]; VertexRef vertexRef = new VertexRef( vertexBaseIndex + indexAssign.indexToVertexAssignment, uvBaseIndex + x ); ringBuffer[ringIndex] = vertexRef; ringIndex = (ringIndex + 1) & 3; int flag = indexAssign.vertexFlag; if (flag == 0x20 || flag == 0x00) { var triRef = new TriangleRef(mesh.textureIndex, mesh.isOpaque, ringBuffer[(ringIndex - triangleOrder[0]) & 3], ringBuffer[(ringIndex - triangleOrder[1]) & 3], ringBuffer[(ringIndex - triangleOrder[2]) & 3] ); exportedMesh.triangleRefList.Add(triRef); } if (flag == 0x30 || flag == 0x00) { var triRef = new TriangleRef(mesh.textureIndex, mesh.isOpaque, ringBuffer[(ringIndex - triangleOrder[0]) & 3], ringBuffer[(ringIndex - triangleOrder[2]) & 3], ringBuffer[(ringIndex - triangleOrder[1]) & 3] ); exportedMesh.triangleRefList.Add(triRef); } } exportedMesh.positionList.AddRange( mesh.vertexAssignmentsList.Select( vertexAssigns => { Vector3 finalPos = Vector3.Zero; if (vertexAssigns.Length == 1) { // single joint finalPos = TransformCoordinate( VCUt.V4To3( vertexAssigns[0].rawPos ), matrices[vertexAssigns[0].matrixIndex] ); } else { // multiple joints, using rawPos.W as blend weights foreach (VertexAssignment vertexAssign in vertexAssigns) { finalPos += VCUt.V4To3( Transform( vertexAssign.rawPos, matrices[vertexAssign.matrixIndex] ) ); } } return(finalPos); } ) ); exportedMesh.uvList.AddRange( mesh.indexAssignmentList .Select(indexAssign => indexAssign.uv) ); vertexBaseIndex += mesh.vertexAssignmentsList.Length; uvBaseIndex += mesh.indexAssignmentList.Length; } } { int triangleRefCount = exportedMesh.triangleRefList.Count; for (int triIndex = 0; triIndex < triangleRefCount; triIndex++) { TriangleRef triRef = exportedMesh.triangleRefList[triIndex]; Tuple <int, bool> modelKey = new Tuple <int, bool>(triRef.textureIndex, triRef.isOpaque); Model model; if (models.TryGetValue(modelKey, out model) == false) { models[modelKey] = model = new Model(); } for (int i = 0; i < triRef.list.Length; i++) { VertexRef vertRef = triRef.list[i]; Vector3 pos = exportedMesh.positionList[vertRef.vertexIndex]; Vector2 uv = exportedMesh.uvList[vertRef.uvIndex]; model.Vertices.Add(new CustomVertex.PositionColoredTextured(pos, -1, uv.X, uv.Y)); } } } return(new Kkdf2MdlxBuiltModel { textureIndexBasedModelDict = models, parser = this, }); }
/// <summary> /// Build final model using immutable parts and given matrices. /// </summary> /// <returns></returns> public List <MeshDescriptor> ProcessVerticesAndBuildModel(Matrix4x4[] matrices) { var exportedMesh = new ExportedMesh(); { int vertexBaseIndex = 0; int uvBaseIndex = 0; VertexRef[] ringBuffer = new VertexRef[4]; int ringIndex = 0; int[] triangleOrder = new int[] { 1, 3, 2 }; foreach (ImmutableMesh mesh in immultableMeshList) { var part = new ExportedMesh.Part { meshRef = mesh, }; for (int x = 0; x < mesh.indexAssignmentList.Length; x++) { var indexAssign = mesh.indexAssignmentList[x]; VertexRef vertexRef = new VertexRef( vertexBaseIndex + indexAssign.indexToVertexAssignment, uvBaseIndex + x ); ringBuffer[ringIndex] = vertexRef; ringIndex = (ringIndex + 1) & 3; int flag = indexAssign.vertexFlag; if (flag == 0x20 || flag == 0x00) { var triRef = new TriangleRef( ringBuffer[(ringIndex - triangleOrder[0]) & 3], ringBuffer[(ringIndex - triangleOrder[1]) & 3], ringBuffer[(ringIndex - triangleOrder[2]) & 3] ); part.triangleRefList.Add(triRef); } if (flag == 0x30 || flag == 0x00) { var triRef = new TriangleRef( ringBuffer[(ringIndex - triangleOrder[0]) & 3], ringBuffer[(ringIndex - triangleOrder[2]) & 3], ringBuffer[(ringIndex - triangleOrder[1]) & 3] ); part.triangleRefList.Add(triRef); } } exportedMesh.positionList.AddRange( mesh.vertexAssignmentsList.Select( vertexAssigns => { Vector3 finalPos = Vector3.Zero; if (vertexAssigns.Length == 1) { // single joint finalPos = Vector3.Transform( VCUt.V4To3( vertexAssigns[0].rawPos ), matrices[vertexAssigns[0].matrixIndex] ); } else { // multiple joints, using rawPos.W as blend weights foreach (VertexAssignment vertexAssign in vertexAssigns) { finalPos += VCUt.V4To3( Vector4.Transform( vertexAssign.rawPos, matrices[vertexAssign.matrixIndex] ) ); } } return(finalPos); } ) ); exportedMesh.uvList.AddRange( mesh.indexAssignmentList .Select(indexAssign => indexAssign.uv) ); exportedMesh.partList.Add(part); vertexBaseIndex += mesh.vertexAssignmentsList.Length; uvBaseIndex += mesh.indexAssignmentList.Length; } } var newList = new List <MeshDescriptor>(); foreach (var part in exportedMesh.partList) { var vertices = new List <CustomVertex.PositionColoredTextured>(); var indices = new List <int>(); int triangleRefCount = part.triangleRefList.Count; for (int triIndex = 0; triIndex < triangleRefCount; triIndex++) { TriangleRef triRef = part.triangleRefList[triIndex]; for (int i = 0; i < triRef.list.Length; i++) { VertexRef vertRef = triRef.list[i]; Vector3 pos = exportedMesh.positionList[vertRef.vertexIndex]; Vector2 uv = exportedMesh.uvList[vertRef.uvIndex]; indices.Add(vertices.Count); vertices.Add(new CustomVertex.PositionColoredTextured(pos, -1, uv.X, uv.Y)); } } newList.Add( new MeshDescriptor { IsOpaque = part.meshRef.isOpaque, TextureIndex = part.meshRef.textureIndex, Vertices = vertices.ToArray(), Indices = indices.ToArray(), } ); } return(newList); }