static GMX_Parser.MESH CreateMesh(Model model, Shape curShape) { var attributes = model.VertexData.Attributes; var mesh = new GMX_Parser.MESH(); mesh.IndexGroup = new GMX_Parser.INDX(); mesh.VertexGroup = new GMX_Parser.VERT(); mesh.VMapGroup = new GMX_Parser.VMAP(); List <GMX_Parser.Vertex> vertices = new List <GMX_Parser.Vertex>(); List <ushort> indices = new List <ushort>(); List <ushort> boneindices = new List <ushort>(); List <ushort> vmapindices = new List <ushort>(); ushort vertexID = 0; uint vertexStride = 0; if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx)) { vertexStride += 4; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Position)) { vertexStride += 12; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal)) { vertexStride += 12; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0)) { vertexStride += 4; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color1)) { vertexStride += 4; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0)) { vertexStride += 8; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex1)) { vertexStride += 8; } uint[] matrices = new uint[10]; uint matrixStart = 0; foreach (Packet pack in curShape.Packets) { for (int i = 0; i < pack.MatrixIndices.Count; i++) { if (pack.MatrixIndices[i] != -1) { matrices[i] = (uint)pack.MatrixIndices[i]; } } foreach (Primitive prim in pack.Primitives) { List <Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim); for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3) { indices.AddRange(new ushort[] { (ushort)(vertexID + 2), (ushort)(vertexID + 1), vertexID }); for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++) { var gmxVertex = new GMX_Parser.Vertex(); Vertex vert = triVertices[triIndex + triVertIndex]; var position = attributes.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)]; if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal)) { gmxVertex.Normal = attributes.Normals[(int)vert.GetAttributeIndex(GXVertexAttribute.Normal)]; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0)) { var color = attributes.Color_0[(int)vert.GetAttributeIndex(GXVertexAttribute.Color0)]; gmxVertex.Color = new OpenTK.Vector4(color.R, color.G, color.B, color.A); } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0)) { gmxVertex.TexCoord0 = attributes.TexCoord_0[(int)vert.GetAttributeIndex(GXVertexAttribute.Tex0)]; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex1)) { gmxVertex.TexCoord1 = attributes.TexCoord_1[(int)vert.GetAttributeIndex(GXVertexAttribute.Tex1)]; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx)) { gmxVertex.MatrixID = (uint)(matrixStart + vert.PositionMatrixIDxIndex); } gmxVertex.Position = position; vertices.Add(gmxVertex); } } } matrixStart += 10; } indices.Clear(); //Now optmize the indices Dictionary <GMX_Parser.Vertex, int> verticesNew = new Dictionary <GMX_Parser.Vertex, int>(); foreach (var v in vertices) { if (!verticesNew.ContainsKey(v)) { verticesNew.Add(v, verticesNew.Count); } if (verticesNew.ContainsKey(v)) { indices.Add((ushort)verticesNew[v]); } } vertices = verticesNew.Keys.ToList(); foreach (var v in vertices) { vmapindices.Add(0); vmapindices.Add(0); } mesh.VMapGroup.Indices = vmapindices.ToArray(); mesh.VertexSize = (ushort)vertexStride; mesh.VertexCount = (ushort)vertices.Count; mesh.VertexGroup.Vertices = vertices; mesh.FaceCount = (uint)indices.Count; mesh.IndexGroup.Indices = indices.ToArray(); mesh.SkinningFlags = 0; if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx)) { mesh.SkinningFlags = 20; } return(mesh); }
private void LoadBMD(Model model) { Nodes.Clear(); ShapeFolder = new TreeNode("Shapes"); SkeletonFolder = new TreeNode("Skeleton"); MaterialFolder = new TreeNode("Materials"); TextureFolder = new BMDTextureFolder("Textures"); Nodes.Add(ShapeFolder); Nodes.Add(MaterialFolder); Nodes.Add(SkeletonFolder); Nodes.Add(TextureFolder); BMDFile = model; FillSkeleton(BMDFile.Scenegraph, Skeleton, BMDFile.Joints.FlatSkeleton); foreach (var bone in Skeleton.bones) { if (bone.Parent == null) { SkeletonFolder.Nodes.Add(bone); } } for (int i = 0; i < BMDFile.Shapes.Shapes.Count; i++) { var curShape = BMDFile.Shapes.Shapes[i]; var mat = new BMDMaterialWrapper(BMDFile.Materials.GetMaterial(i), BMDFile); MaterialFolder.Nodes.Add(mat); var shpWrapper = new BMDShapeWrapper(curShape, BMDFile, mat); shpWrapper.Text = $"Shape {i}"; ShapeFolder.Nodes.Add(shpWrapper); Renderer.Meshes.Add(shpWrapper); var polyGroup = new STGenericPolygonGroup(); shpWrapper.PolygonGroups.Add(polyGroup); var VertexAttributes = BMDFile.VertexData.Attributes; int vertexID = 0; int packetID = 0; foreach (var att in curShape.Descriptor.Attributes) { shpWrapper.Nodes.Add($"Attribute {att.Key} {att.Value.Item1}"); } foreach (SuperBMDLib.Geometry.Packet pack in curShape.Packets) { int primID = 0; foreach (SuperBMDLib.Geometry.Primitive prim in pack.Primitives) { List <SuperBMDLib.Geometry.Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim); for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3) { polyGroup.faces.AddRange(new int[] { vertexID + 2, vertexID + 1, vertexID }); for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++) { SuperBMDLib.Geometry.Vertex vert = triVertices[triIndex + triVertIndex]; Vertex vertex = new Vertex(); vertex.pos = VertexAttributes.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)]; shpWrapper.vertices.Add(vertex); if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal)) { vertex.nrm = VertexAttributes.Normals[(int)vert.NormalIndex]; } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0)) { var color0 = VertexAttributes.Color_0[(int)vert.Color0Index]; vertex.col = new OpenTK.Vector4(color0.R, color0.G, color0.B, color0.A); } for (int j = 0; j < vert.VertexWeight.WeightCount; j++) { vertex.boneWeights.Add(vert.VertexWeight.Weights[j]); vertex.boneIds.Add(vert.VertexWeight.BoneIndices[j]); } if (vert.VertexWeight.WeightCount == 1) { if (BMDFile.SkinningEnvelopes.InverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0]) { Matrix4 test = BMDFile.SkinningEnvelopes.InverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted(); test.Transpose(); vertex.pos = OpenTK.Vector3.TransformPosition(vertex.pos, test); vertex.nrm = OpenTK.Vector3.TransformNormal(vertex.nrm, test); } else { vertex.pos = OpenTK.Vector3.TransformPosition(vertex.pos, BMDFile.Joints.FlatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix); vertex.nrm = OpenTK.Vector3.TransformNormal(vertex.nrm, BMDFile.Joints.FlatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix); } } for (int texCoordNum = 0; texCoordNum < 8; texCoordNum++) { if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0 + texCoordNum)) { switch (texCoordNum) { case 0: vertex.uv0 = VertexAttributes.TexCoord_0[(int)vert.TexCoord0Index]; break; case 1: vertex.uv1 = VertexAttributes.TexCoord_0[(int)vert.TexCoord0Index]; break; case 2: vertex.uv2 = VertexAttributes.TexCoord_0[(int)vert.TexCoord0Index]; break; } } } vertexID++; } } primID++; } packetID++; } } CorrectMaterialIndices(Renderer.Meshes, BMDFile.Scenegraph, BMDFile.Materials); for (int i = 0; i < BMDFile.Textures.Textures.Count; i++) { var texWrapper = new BMDTextureWrapper(BMDFile.Textures.Textures[i]); TextureFolder.Nodes.Add(texWrapper); Renderer.TextureList.Add(texWrapper); } }
public void FillScene(Scene scene, VertexData vertData, List <Rigging.Bone> flatSkeleton, List <Matrix4> inverseBindMatrices) { for (int i = 0; i < Shapes.Count; i++) { Mesh mesh = new Mesh($"mesh_{ i }", PrimitiveType.Triangle); mesh.MaterialIndex = i; int vertexID = 0; Shape curShape = Shapes[i]; foreach (Packet pack in curShape.Packets) { foreach (Primitive prim in pack.Primitives) { List <Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim); for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3) { Face newFace = new Face(new int[] { vertexID + 2, vertexID + 1, vertexID }); mesh.Faces.Add(newFace); for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++) { Vertex vert = triVertices[triIndex + triVertIndex]; for (int j = 0; j < vert.VertexWeight.WeightCount; j++) { Rigging.Bone curWeightBone = flatSkeleton[vert.VertexWeight.BoneIndices[j]]; int assBoneIndex = mesh.Bones.FindIndex(x => x.Name == curWeightBone.Name); if (assBoneIndex == -1) { Assimp.Bone newBone = new Assimp.Bone(); newBone.Name = curWeightBone.Name; newBone.OffsetMatrix = curWeightBone.InverseBindMatrix.ToMatrix4x4(); mesh.Bones.Add(newBone); assBoneIndex = mesh.Bones.IndexOf(newBone); } mesh.Bones[assBoneIndex].VertexWeights.Add(new VertexWeight(vertexID, vert.VertexWeight.Weights[j])); } OpenTK.Vector3 posVec = vertData.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)]; OpenTK.Vector4 openTKVec = new Vector4(posVec.X, posVec.Y, posVec.Z, 1); Vector3D vertVec = new Vector3D(openTKVec.X, openTKVec.Y, openTKVec.Z); if (vert.VertexWeight.WeightCount == 1) { if (inverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0]) { Matrix4 test = inverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted(); test.Transpose(); Vector4 trans = OpenTK.Vector4.Transform(openTKVec, test); vertVec = new Vector3D(trans.X, trans.Y, trans.Z); } else { Vector4 trans = OpenTK.Vector4.Transform(openTKVec, flatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix); vertVec = new Vector3D(trans.X, trans.Y, trans.Z); } } /*else * { * Matrix4 finalMatrix = Matrix4.Zero; * * for (int m = 0; m < vert.VertexWeight.WeightCount; m++) * { * Matrix4 sm1 = inverseBindMatrices[vert.VertexWeight.BoneIndices[m]]; * //sm1.Transpose(); * Matrix4 sm2 = flatSkeleton[vert.VertexWeight.BoneIndices[m]].TransformationMatrix; * //sm2.Transpose(); * * finalMatrix += Matrix4.Mult(sm1, vert.VertexWeight.Weights[m]); * } * * Vector4 final = Vector4.Transform(openTKVec, finalMatrix); * * vertVec = new Vector3D(final.X, final.Y, final.Z); * }*/ mesh.Vertices.Add(vertVec); if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal)) { mesh.Normals.Add(vertData.Normals[(int)vert.NormalIndex].ToVector3D()); } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0)) { mesh.VertexColorChannels[0].Add(vertData.Color_0[(int)vert.Color0Index].ToColor4D()); } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color1)) { mesh.VertexColorChannels[1].Add(vertData.Color_1[(int)vert.Color1Index].ToColor4D()); } for (int texCoordNum = 0; texCoordNum < 8; texCoordNum++) { if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0 + texCoordNum)) { Vector3D texCoord = new Vector3D(); switch (texCoordNum) { case 0: texCoord = vertData.TexCoord_0[(int)vert.TexCoord0Index].ToVector2D(); break; case 1: texCoord = vertData.TexCoord_1[(int)vert.TexCoord1Index].ToVector2D(); break; case 2: texCoord = vertData.TexCoord_2[(int)vert.TexCoord2Index].ToVector2D(); break; case 3: texCoord = vertData.TexCoord_3[(int)vert.TexCoord3Index].ToVector2D(); break; case 4: texCoord = vertData.TexCoord_4[(int)vert.TexCoord4Index].ToVector2D(); break; case 5: texCoord = vertData.TexCoord_5[(int)vert.TexCoord5Index].ToVector2D(); break; case 6: texCoord = vertData.TexCoord_6[(int)vert.TexCoord6Index].ToVector2D(); break; case 7: texCoord = vertData.TexCoord_7[(int)vert.TexCoord7Index].ToVector2D(); break; } mesh.TextureCoordinateChannels[texCoordNum].Add(texCoord); } } vertexID++; } } } } scene.Meshes.Add(mesh); } }
public void FillScene(Scene scene, VertexData vertData, List <Rigging.Bone> flatSkeleton, List <Matrix4> inverseBindMatrices) { for (int i = 0; i < Shapes.Count; i++) { int vertexID = 0; Shape curShape = Shapes[i]; Console.Write("Mesh " + i + ": "); string meshname = $"mesh_{ i }"; switch (curShape.MatrixType) { case MatrixType.BillboardX: meshname += "_BillX"; Console.Write("Billboarding Detected! "); break; case MatrixType.BillboardXY: meshname += "_BillXY"; Console.Write("Billboarding Detected! "); break; default: break; } Mesh mesh = new Mesh($"mesh_{ i }", PrimitiveType.Triangle); mesh.MaterialIndex = i; foreach (Packet pack in curShape.Packets) { foreach (Primitive prim in pack.Primitives) { List <Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim); for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3) { Face newFace = new Face(new int[] { vertexID + 2, vertexID + 1, vertexID }); mesh.Faces.Add(newFace); for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++) { Vertex vert = triVertices[triIndex + triVertIndex]; for (int j = 0; j < vert.VertexWeight.WeightCount; j++) { Rigging.Bone curWeightBone = flatSkeleton[vert.VertexWeight.BoneIndices[j]]; int assBoneIndex = mesh.Bones.FindIndex(x => x.Name == curWeightBone.Name); if (assBoneIndex == -1) { Assimp.Bone newBone = new Assimp.Bone(); newBone.Name = curWeightBone.Name; newBone.OffsetMatrix = curWeightBone.InverseBindMatrix.ToMatrix4x4(); mesh.Bones.Add(newBone); assBoneIndex = mesh.Bones.IndexOf(newBone); } mesh.Bones[assBoneIndex].VertexWeights.Add(new VertexWeight(vertexID, vert.VertexWeight.Weights[j])); } OpenTK.Vector3 posVec = vertData.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)]; OpenTK.Vector4 openTKVec = new Vector4(posVec.X, posVec.Y, posVec.Z, 1); Vector3D vertVec = new Vector3D(openTKVec.X, openTKVec.Y, openTKVec.Z); if (vert.VertexWeight.WeightCount == 1) { if (inverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0]) { Matrix4 test = inverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted(); test.Transpose(); Vector4 trans = OpenTK.Vector4.Transform(openTKVec, test); vertVec = new Vector3D(trans.X, trans.Y, trans.Z); } else { Vector4 trans = OpenTK.Vector4.Transform(openTKVec, flatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix); vertVec = new Vector3D(trans.X, trans.Y, trans.Z); } } mesh.Vertices.Add(vertVec); if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal)) { OpenTK.Vector3 nrmVec = vertData.Normals[(int)vert.NormalIndex]; OpenTK.Vector4 openTKNrm = new Vector4(nrmVec.X, nrmVec.Y, nrmVec.Z, 1); Vector3D vertNrm = new Vector3D(nrmVec.X, nrmVec.Y, nrmVec.Z); if (vert.VertexWeight.WeightCount == 1) { if (inverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0]) { Matrix4 test = inverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted(); vertNrm = Vector3.TransformNormalInverse(nrmVec, test).ToVector3D(); } else { Vector4 trans = OpenTK.Vector4.Transform(openTKNrm, flatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix); vertNrm = new Vector3D(trans.X, trans.Y, trans.Z); } } mesh.Normals.Add(vertNrm); } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0)) { mesh.VertexColorChannels[0].Add(vertData.Color_0[(int)vert.Color0Index].ToColor4D()); } if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color1)) { mesh.VertexColorChannels[1].Add(vertData.Color_1[(int)vert.Color1Index].ToColor4D()); } for (int texCoordNum = 0; texCoordNum < 8; texCoordNum++) { if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0 + texCoordNum)) { Vector3D texCoord = new Vector3D(); switch (texCoordNum) { case 0: texCoord = vertData.TexCoord_0[(int)vert.TexCoord0Index].ToVector2D(); break; case 1: texCoord = vertData.TexCoord_1[(int)vert.TexCoord1Index].ToVector2D(); break; case 2: texCoord = vertData.TexCoord_2[(int)vert.TexCoord2Index].ToVector2D(); break; case 3: texCoord = vertData.TexCoord_3[(int)vert.TexCoord3Index].ToVector2D(); break; case 4: texCoord = vertData.TexCoord_4[(int)vert.TexCoord4Index].ToVector2D(); break; case 5: texCoord = vertData.TexCoord_5[(int)vert.TexCoord5Index].ToVector2D(); break; case 6: texCoord = vertData.TexCoord_6[(int)vert.TexCoord6Index].ToVector2D(); break; case 7: texCoord = vertData.TexCoord_7[(int)vert.TexCoord7Index].ToVector2D(); break; } mesh.TextureCoordinateChannels[texCoordNum].Add(texCoord); } } vertexID++; } } } Console.Write("..."); } scene.Meshes.Add(mesh); Console.Write("✓"); Console.WriteLine(); } }