public void SetVertexWeights(EVP1 envelopes, DRW1 drawList) { for (int i = 0; i < Shapes.Count; i++) { for (int j = 0; j < Shapes[i].Packets.Count; j++) { foreach (Primitive prim in Shapes[i].Packets[j].Primitives) { foreach (Vertex vert in prim.Vertices) { if (Shapes[i].Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx)) { int drw1Index = Shapes[i].Packets[j].MatrixIndices[(int)vert.PositionMatrixIDxIndex]; int curPacketIndex = j; while (drw1Index == -1) { curPacketIndex--; drw1Index = Shapes[i].Packets[curPacketIndex].MatrixIndices[(int)vert.PositionMatrixIDxIndex]; } if (drawList.WeightTypeCheck[(int)drw1Index]) { int evp1Index = drawList.Indices[(int)drw1Index]; vert.SetWeight(envelopes.Weights[evp1Index]); } else { Weight vertWeight = new Weight(); vertWeight.AddWeight(1.0f, drawList.Indices[(int)drw1Index]); vert.SetWeight(vertWeight); } } else { Weight vertWeight = new Weight(); vertWeight.AddWeight(1.0f, drawList.Indices[Shapes[i].Packets[j].MatrixIndices[0]]); vert.SetWeight(vertWeight); } } } } } }
public EVP1(EndianBinaryReader reader, int offset) { Weights = new List <Weight>(); InverseBindMatrices = new List <Matrix4>(); reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin); reader.SkipInt32(); int evp1Size = reader.ReadInt32(); int entryCount = reader.ReadInt16(); reader.SkipInt16(); int weightCountsOffset = reader.ReadInt32(); int boneIndicesOffset = reader.ReadInt32(); int weightDataOffset = reader.ReadInt32(); int inverseBindMatricesOffset = reader.ReadInt32(); List <int> counts = new List <int>(); List <float> weights = new List <float>(); List <int> indices = new List <int>(); for (int i = 0; i < entryCount; i++) { counts.Add(reader.ReadByte()); } reader.BaseStream.Seek(boneIndicesOffset + offset, System.IO.SeekOrigin.Begin); for (int i = 0; i < entryCount; i++) { for (int j = 0; j < counts[i]; j++) { indices.Add(reader.ReadInt16()); } } reader.BaseStream.Seek(weightDataOffset + offset, System.IO.SeekOrigin.Begin); for (int i = 0; i < entryCount; i++) { for (int j = 0; j < counts[i]; j++) { weights.Add(reader.ReadSingle()); } } int totalRead = 0; for (int i = 0; i < entryCount; i++) { Weight weight = new Weight(); for (int j = 0; j < counts[i]; j++) { weight.AddWeight(weights[totalRead + j], indices[totalRead + j]); } Weights.Add(weight); totalRead += counts[i]; } reader.BaseStream.Seek(inverseBindMatricesOffset + offset, System.IO.SeekOrigin.Begin); int matrixCount = (evp1Size - inverseBindMatricesOffset) / 48; for (int i = 0; i < matrixCount; i++) { Matrix3x4 invBind = new Matrix3x4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); InverseBindMatrices.Add(new Matrix4(invBind.Row0, invBind.Row1, invBind.Row2, Vector4.UnitW)); } reader.BaseStream.Seek(offset + evp1Size, System.IO.SeekOrigin.Begin); }
public static HsfFile Import(STGenericScene scene, ImportSettings settings) { HsfFile hsf = new HsfFile(); var root = ObjectDataSection.CreateNewObject(ObjectType.Root); hsf.ObjectData.Objects.Add(root); hsf.ObjectData.ObjectNames.Add("Root"); foreach (var tex in scene.Models[0].Textures) { Console.WriteLine($"tex {tex.Name}"); var newtex = CreateTexture(tex); newtex.Name = tex.Name; hsf.Textures.Add(newtex); } if (hsf.Textures.Count == 0) { } var newtex2 = CreateTexture(new GenericBitmapTexture("dummy.png")); newtex2.Name = "dummy"; hsf.Textures.Add(newtex2); hsf.FogData.Count = 1; hsf.FogData.ColorStart = new Vector4(77, 77, 77, 128); hsf.FogData.ColorEnd = new Vector4(255, 0, 0, 255); hsf.FogData.Start = 0; hsf.FogData.End = 10000; Console.WriteLine("Importing Models"); foreach (var model in scene.Models) { foreach (var material in model.GetMaterials()) { var mat = HSF_MaterialConverter.Import($"mat1.json"); mat.MaterialData.VertexMode = 2; mat.Name = material.Name; hsf.Materials.Add(mat); if (material.TextureMaps.Count > 0) { var texMap = material.TextureMaps[0].Name; int index = hsf.Textures.FindIndex(x => x.Name == texMap); if (index != -1) { mat.Textures[0].Item2.TextureIndex = index; } } mat.Textures[0].Item2.WrapS = 1; mat.Textures[0].Item2.WrapT = 1; } if (hsf.Materials.Count == 0) { var mat = HSF_MaterialConverter.Import($"mat1.json"); mat.MaterialData.VertexMode = 2; mat.Name = "Basic"; hsf.Materials.Add(mat); } foreach (var mesh in model.Meshes) { root.ChildrenCount += 1; List <Vector3> positions = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> texCoords = new List <Vector2>(); List <Vector4> colors = new List <Vector4>(); for (int v = 0; v < mesh.Vertices.Count; v++) { var vertex = mesh.Vertices[v]; if (!positions.Contains(vertex.Position)) { positions.Add(vertex.Position); } if (!normals.Contains(vertex.Normal)) { normals.Add(vertex.Normal); } if (vertex.Colors.Length > 0) { if (!colors.Contains(vertex.Colors[0])) { colors.Add(vertex.Colors[0]); } } if (vertex.TexCoords.Length > 0) { if (!texCoords.Contains(vertex.TexCoords[0])) { texCoords.Add(vertex.TexCoords[0]); } } } var bounding = GenerateBoundingBox(mesh); ObjectData objData = ObjectDataSection.CreateNewObject(ObjectType.Mesh); objData.CullBoxMax = bounding.Max; objData.CullBoxMin = bounding.Min; objData.AttributeIndex = 0; objData.ParentIndex = 0; hsf.ObjectData.Objects.Add(objData); hsf.ObjectData.ObjectNames.Add(mesh.Name); Mesh msh = new Mesh(objData, mesh.Name); msh.Positions.AddRange(positions); msh.Normals.AddRange(normals); msh.TexCoords.AddRange(texCoords); msh.Colors.AddRange(colors); foreach (var group in mesh.PolygonGroups) { int materialIndex = 0; if (group.MaterialIndex != -1 && hsf.Materials.Count > group.MaterialIndex) { materialIndex = group.MaterialIndex; } byte mode = 2; if (colors.Count > 0) { mode = 5; } hsf.Materials[materialIndex].MaterialData.VertexMode = mode; Weight[] weightList = new Weight[mesh.Vertices.Count]; for (int i = 0; i < mesh.Vertices.Count; i++) { Weight vertWeight = new Weight(); for (int j = 0; j < mesh.Vertices[i].BoneIndices.Count; j++) { int boneId = mesh.Vertices[i].BoneIndices[j]; float boneWeight = mesh.Vertices[i].BoneWeights[j]; vertWeight.AddWeight(boneWeight, boneId); } weightList[i] = vertWeight; } List <PrimitiveBrawl> primlist = new List <PrimitiveBrawl>(); //Turn triangle set into triangle strips if (settings.UseTriStrips) { TriStripper stripper = new TriStripper(mesh.Faces.ToArray(), weightList); primlist = stripper.Strip(); } else { primlist = new List <PrimitiveBrawl>(); for (int i = 0; i < mesh.Faces.Count; i++) { PrimitiveBrawl prim = new PrimitiveBrawl(PrimType.TriangleList); // Trilist prim.Indices.Add(mesh.Faces[i++]); prim.Indices.Add(mesh.Faces[i++]); prim.Indices.Add(mesh.Faces[i]); primlist.Add(prim); } } foreach (var primitive in primlist) { PrimitiveObject prim = new PrimitiveObject(); prim.Type = PrimitiveType.Triangle; if (settings.UseTriStrips) { prim.Type = PrimitiveType.TriangleStrip; } prim.Flags = 0; prim.NbtData = new OpenTK.Vector3(1, 0, 0); if (hsf.Materials.Count > materialIndex) { prim.MaterialIndex = materialIndex; } if (settings.UseTriStrips) { prim.Vertices = new VertexGroup[primitive.Indices.Count + 1]; } else { prim.Vertices = new VertexGroup[4]; prim.Vertices[3] = new VertexGroup(); //Empty last grou } msh.Primitives.Add(prim); if (prim.Type == PrimitiveType.TriangleStrip) { for (int i = 0; i < 3; i++) { var vertexIndex = (int)primitive.Indices[i]; var vertex = mesh.Vertices[vertexIndex]; short colorIndex = -1; short texCoordIndex = -1; short positionIndex = (short)positions.IndexOf(vertex.Position); short normaIndex = (short)normals.IndexOf(vertex.Normal); if (vertex.Colors.Length > 0) { colorIndex = (short)colors.IndexOf(vertex.Colors[0]); } if (vertex.TexCoords.Length > 0) { texCoordIndex = (short)texCoords.IndexOf(vertex.TexCoords[0]); } prim.Vertices[i] = new VertexGroup() { PositionIndex = positionIndex, UVIndex = texCoordIndex, ColorIndex = colorIndex, NormalIndex = normaIndex, }; } prim.Vertices[3] = new VertexGroup(); for (int i = 4; i < prim.Vertices.Length; i++) { var vertexIndex = (int)primitive.Indices[i - 1]; var vertex = mesh.Vertices[vertexIndex]; short colorIndex = -1; short texCoordIndex = -1; short positionIndex = (short)positions.IndexOf(vertex.Position); short normaIndex = (short)normals.IndexOf(vertex.Normal); if (vertex.Colors.Length > 0) { colorIndex = (short)colors.IndexOf(vertex.Colors[0]); } if (vertex.TexCoords.Length > 0) { texCoordIndex = (short)texCoords.IndexOf(vertex.TexCoords[0]); } prim.Vertices[i] = new VertexGroup() { PositionIndex = positionIndex, UVIndex = texCoordIndex, ColorIndex = colorIndex, NormalIndex = normaIndex, }; } } else { for (int i = 0; i < primitive.Indices.Count; i++) { var vertexIndex = (int)primitive.Indices[i]; var vertex = mesh.Vertices[vertexIndex]; short colorIndex = -1; short texCoordIndex = -1; short positionIndex = (short)positions.IndexOf(vertex.Position); short normaIndex = (short)normals.IndexOf(vertex.Normal); if (vertex.Colors.Length > 0) { colorIndex = (short)colors.IndexOf(vertex.Colors[0]); } if (vertex.TexCoords.Length > 0) { texCoordIndex = (short)texCoords.IndexOf(vertex.TexCoords[0]); } prim.Vertices[i] = new VertexGroup() { PositionIndex = positionIndex, UVIndex = texCoordIndex, ColorIndex = colorIndex, NormalIndex = normaIndex, }; } } } } hsf.Meshes.Add(msh); } } Console.WriteLine("Finished generating HSF binary!"); return(hsf); }
public void ProcessVerticesWithWeights(Mesh mesh, VertexData vertData, Dictionary <string, int> boneNames, EVP1 envelopes, DRW1 partialWeight, bool doStrip = true) { Weight[] weights = new Weight[mesh.Vertices.Count]; for (int i = 0; i < mesh.Vertices.Count; i++) { int vertexid = i; Weight vertWeight = new Weight(); foreach (Assimp.Bone bone in mesh.Bones) { foreach (VertexWeight weight in bone.VertexWeights) { if (weight.VertexID == vertexid) { vertWeight.AddWeight(weight.Weight, boneNames[bone.Name]); } } } vertWeight.reorderBones(); weights[vertexid] = vertWeight; } //Primitive prim = new Primitive(Enums.GXPrimitiveType.Triangles); List <Enums.GXVertexAttribute> activeAttribs = Descriptor.GetActiveAttributes(); AttributeData.SetAttributesFromList(activeAttribs); uint[] triindices = MakeTriIndexList(mesh); List <PrimitiveBrawl> primlist; if (doStrip) { //Console.WriteLine("Calculating triangle strips for Weighted"); TriStripper stripper = new TriStripper(triindices, weights); primlist = stripper.Strip(); } else { //Console.WriteLine("Calculating triangle list for Weighted"); primlist = new List <PrimitiveBrawl>(); PrimitiveBrawl prim = new PrimitiveBrawl(PrimType.TriangleList); // Trilist foreach (uint index in triindices) { prim.Indices.Add(index); } primlist.Add(prim); } //Console.WriteLine(String.Format("Done, {0} primitives", primlist.Count)); Packet pack = new Packet(); List <Weight> packetWeights = new List <Weight>(); int numMatrices = 0; foreach (PrimitiveBrawl primbrawl in primlist) { int numNewMatricesForFirstThreeVerts = 0; if (!packetWeights.Contains(weights[primbrawl.Indices[0]])) { numNewMatricesForFirstThreeVerts++; } if (!packetWeights.Contains(weights[primbrawl.Indices[1]])) { numNewMatricesForFirstThreeVerts++; } if (!packetWeights.Contains(weights[primbrawl.Indices[2]])) { numNewMatricesForFirstThreeVerts++; } if (numMatrices + numNewMatricesForFirstThreeVerts > MaxMatricesPerPacket) { // We won't be able to fit even the first 3 vertices of this primitive without going over the matrix limit. // So we need to start a new packet. packetWeights.Clear(); numMatrices = 0; Packets.Add(pack); pack = new Packet(); } Primitive prim = new Primitive((Enums.GXPrimitiveType)primbrawl.Type); int currvert = -1; int maxvert = primbrawl.Indices.Count - 1; Enums.GXPrimitiveType primtype = (Enums.GXPrimitiveType)primbrawl.Type; if (primtype == Enums.GXPrimitiveType.TriangleStrip) { //Console.WriteLine("Doing Tristrip"); foreach (int vertIndex in primbrawl.Indices) { currvert++; Weight vertWeight = weights[vertIndex]; int oldmat = numMatrices; if (!packetWeights.Contains(vertWeight)) { packetWeights.Add(vertWeight); numMatrices++; } //Console.WriteLine(String.Format("Added {0} matrices, is now {1}", numMatrices - oldmat, numMatrices)); // There are too many matrices, we need to create a new packet if (numMatrices > MaxMatricesPerPacket) { // If we break up and the resulting TriStrip becomes invalid, // then we need to handle those cases. //Console.WriteLine(String.Format("Breaking up because over the limit: {0}", numMatrices)); if (prim.PrimitiveType == Enums.GXPrimitiveType.TriangleStrip) { Debug.Assert(prim.Vertices.Count >= 3); } else if (prim.PrimitiveType == Enums.GXPrimitiveType.Triangles) { Debug.Assert(prim.Vertices.Count % 3 == 0); } pack.Primitives.Add(prim); Primitive newprim = new Primitive(Enums.GXPrimitiveType.TriangleStrip); Vertex prev3 = new Vertex(prim.Vertices[prim.Vertices.Count - 3]); Vertex prev2 = new Vertex(prim.Vertices[prim.Vertices.Count - 2]); Vertex prev = new Vertex(prim.Vertices[prim.Vertices.Count - 1]); bool isOdd = currvert % 2 != 0; if (isOdd) { // Need to preserve whether each vertex is even or odd inside the triangle strip. // Do this by adding an extra vertex from the previous packet to the start of this one. newprim.Vertices.Add(prev3); } newprim.Vertices.Add(prev2); newprim.Vertices.Add(prev); prim = newprim; packetWeights.Clear(); numMatrices = 0; Packets.Add(pack); Packet oldPack = pack; pack = new Packet(); // Calculate matrices for current packet in case we added vertices foreach (Vertex vertex in prim.Vertices) { if (!packetWeights.Contains(vertex.VertexWeight)) { packetWeights.Add(vertex.VertexWeight); numMatrices++; } // Re-add the matrix index for the duplicated verts to the new packet. // And recalculate the matrix index index in each vert's attribute data. uint oldMatrixIndexIndex = vertex.GetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx); int matrixIndex = oldPack.MatrixIndices[(int)oldMatrixIndexIndex]; if (!pack.MatrixIndices.Contains(matrixIndex)) { pack.MatrixIndices.Add(matrixIndex); } vertex.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(matrixIndex)); } if (!packetWeights.Contains(vertWeight)) { packetWeights.Add(vertWeight); numMatrices++; } } Vertex vert = new Vertex(); Weight curWeight = vertWeight; vert.SetWeight(curWeight); foreach (Enums.GXVertexAttribute attrib in activeAttribs) { switch (attrib) { case Enums.GXVertexAttribute.PositionMatrixIdx: int newMatrixIndex = -1; if (curWeight.WeightCount == 1) { newMatrixIndex = partialWeight.MeshWeights.IndexOf(curWeight); } else { if (!envelopes.Weights.Contains(curWeight)) { envelopes.Weights.Add(curWeight); } int envIndex = envelopes.Weights.IndexOf(curWeight); int drwIndex = partialWeight.MeshWeights.IndexOf(curWeight); if (drwIndex == -1) { throw new System.Exception($"Model has unweighted vertices in mesh \"{mesh.Name}\". Please weight all vertices to at least one bone."); } newMatrixIndex = drwIndex; partialWeight.Indices[drwIndex] = envIndex; } if (!pack.MatrixIndices.Contains(newMatrixIndex)) { pack.MatrixIndices.Add(newMatrixIndex); } vert.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(newMatrixIndex)); break; case Enums.GXVertexAttribute.Position: List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position); Vector3 vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3(); if (curWeight.WeightCount == 1) { Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]]; Vector3 transVec = Vector3.TransformPosition(vertPos, ibm); if (!posData.Contains(transVec)) { posData.Add(transVec); } AttributeData.Positions.Add(transVec); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(transVec)); } else { if (!posData.Contains(vertPos)) { posData.Add(vertPos); } AttributeData.Positions.Add(vertPos); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos)); } break; case Enums.GXVertexAttribute.Normal: List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal); Vector3 vertNrm = mesh.Normals[vertIndex].ToOpenTKVector3(); if (curWeight.WeightCount == 1) { Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]]; vertNrm = Vector3.TransformNormal(vertNrm, ibm); if (!normData.Contains(vertNrm)) { normData.Add(vertNrm); } } else { if (!normData.Contains(vertNrm)) { normData.Add(vertNrm); } } AttributeData.Normals.Add(vertNrm); vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm)); break; case Enums.GXVertexAttribute.Color0: case Enums.GXVertexAttribute.Color1: int colNo = (int)attrib - 11; List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo); Color vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA(); if (colNo == 0) { AttributeData.Color_0.Add(vertCol); } else { AttributeData.Color_1.Add(vertCol); } vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol)); break; case Enums.GXVertexAttribute.Tex0: case Enums.GXVertexAttribute.Tex1: case Enums.GXVertexAttribute.Tex2: case Enums.GXVertexAttribute.Tex3: case Enums.GXVertexAttribute.Tex4: case Enums.GXVertexAttribute.Tex5: case Enums.GXVertexAttribute.Tex6: case Enums.GXVertexAttribute.Tex7: int texNo = (int)attrib - 13; List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo); Vector2 vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2(); vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y); switch (texNo) { case 0: AttributeData.TexCoord_0.Add(vertTexCoord); break; case 1: AttributeData.TexCoord_1.Add(vertTexCoord); break; case 2: AttributeData.TexCoord_2.Add(vertTexCoord); break; case 3: AttributeData.TexCoord_3.Add(vertTexCoord); break; case 4: AttributeData.TexCoord_4.Add(vertTexCoord); break; case 5: AttributeData.TexCoord_5.Add(vertTexCoord); break; case 6: AttributeData.TexCoord_6.Add(vertTexCoord); break; case 7: AttributeData.TexCoord_7.Add(vertTexCoord); break; } vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord)); break; } } prim.Vertices.Add(vert); } } else if (primtype == Enums.GXPrimitiveType.Triangles) { for (int j = 0; j < primbrawl.Indices.Count / 3; j++) { int vert1Index = (int)primbrawl.Indices[j * 3 + 0]; int vert2Index = (int)primbrawl.Indices[j * 3 + 1]; int vert3Index = (int)primbrawl.Indices[j * 3 + 2]; Weight vert1Weight = weights[vert1Index]; Weight vert2Weight = weights[vert2Index]; Weight vert3Weight = weights[vert3Index]; int oldcount = numMatrices; if (!packetWeights.Contains(vert1Weight)) { packetWeights.Add(vert1Weight); numMatrices++; } if (!packetWeights.Contains(vert2Weight)) { packetWeights.Add(vert2Weight); numMatrices++; } if (!packetWeights.Contains(vert3Weight)) { packetWeights.Add(vert3Weight); numMatrices++; } // There are too many matrices, we need to create a new packet if (numMatrices > MaxMatricesPerPacket) { //Console.WriteLine(String.Format("Making new packet because previous one would have {0}", numMatrices)); //Console.WriteLine(oldcount); pack.Primitives.Add(prim); Packets.Add(pack); prim = new Primitive(Enums.GXPrimitiveType.Triangles); pack = new Packet(); packetWeights.Clear(); numMatrices = 0; if (!packetWeights.Contains(vert1Weight)) { packetWeights.Add(vert1Weight); numMatrices++; } if (!packetWeights.Contains(vert2Weight)) { packetWeights.Add(vert2Weight); numMatrices++; } if (!packetWeights.Contains(vert3Weight)) { packetWeights.Add(vert3Weight); numMatrices++; } } int[] vertexIndexArray = new int[] { vert1Index, vert2Index, vert3Index }; Weight[] vertWeightArray = new Weight[] { vert1Weight, vert2Weight, vert3Weight }; for (int i = 0; i < 3; i++) { Vertex vert = new Vertex(); int vertIndex = vertexIndexArray[i]; Weight curWeight = vertWeightArray[i]; vert.SetWeight(curWeight); foreach (Enums.GXVertexAttribute attrib in activeAttribs) { switch (attrib) { case Enums.GXVertexAttribute.PositionMatrixIdx: int newMatrixIndex = -1; if (curWeight.WeightCount == 1) { newMatrixIndex = partialWeight.MeshWeights.IndexOf(curWeight); } else { if (!envelopes.Weights.Contains(curWeight)) { envelopes.Weights.Add(curWeight); } int envIndex = envelopes.Weights.IndexOf(curWeight); int drwIndex = partialWeight.MeshWeights.IndexOf(curWeight); if (drwIndex == -1) { throw new System.Exception($"Model has unweighted vertices in mesh \"{mesh.Name}\". Please weight all vertices to at least one bone."); } newMatrixIndex = drwIndex; partialWeight.Indices[drwIndex] = envIndex; } if (!pack.MatrixIndices.Contains(newMatrixIndex)) { pack.MatrixIndices.Add(newMatrixIndex); } vert.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(newMatrixIndex)); break; case Enums.GXVertexAttribute.Position: List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position); Vector3 vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3(); if (curWeight.WeightCount == 1) { Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]]; Vector3 transVec = Vector3.TransformPosition(vertPos, ibm); if (!posData.Contains(transVec)) { posData.Add(transVec); } AttributeData.Positions.Add(transVec); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(transVec)); } else { if (!posData.Contains(vertPos)) { posData.Add(vertPos); } AttributeData.Positions.Add(vertPos); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos)); } break; case Enums.GXVertexAttribute.Normal: List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal); Vector3 vertNrm = mesh.Normals[vertIndex].ToOpenTKVector3(); if (curWeight.WeightCount == 1) { Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]]; vertNrm = Vector3.TransformNormal(vertNrm, ibm); if (!normData.Contains(vertNrm)) { normData.Add(vertNrm); } } else { if (!normData.Contains(vertNrm)) { normData.Add(vertNrm); } } AttributeData.Normals.Add(vertNrm); vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm)); break; case Enums.GXVertexAttribute.Color0: case Enums.GXVertexAttribute.Color1: int colNo = (int)attrib - 11; List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo); Color vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA(); if (colNo == 0) { AttributeData.Color_0.Add(vertCol); } else { AttributeData.Color_1.Add(vertCol); } vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol)); break; case Enums.GXVertexAttribute.Tex0: case Enums.GXVertexAttribute.Tex1: case Enums.GXVertexAttribute.Tex2: case Enums.GXVertexAttribute.Tex3: case Enums.GXVertexAttribute.Tex4: case Enums.GXVertexAttribute.Tex5: case Enums.GXVertexAttribute.Tex6: case Enums.GXVertexAttribute.Tex7: int texNo = (int)attrib - 13; List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo); Vector2 vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2(); vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y); switch (texNo) { case 0: AttributeData.TexCoord_0.Add(vertTexCoord); break; case 1: AttributeData.TexCoord_1.Add(vertTexCoord); break; case 2: AttributeData.TexCoord_2.Add(vertTexCoord); break; case 3: AttributeData.TexCoord_3.Add(vertTexCoord); break; case 4: AttributeData.TexCoord_4.Add(vertTexCoord); break; case 5: AttributeData.TexCoord_5.Add(vertTexCoord); break; case 6: AttributeData.TexCoord_6.Add(vertTexCoord); break; case 7: AttributeData.TexCoord_7.Add(vertTexCoord); break; } vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord)); break; } } prim.Vertices.Add(vert); } } } /* * if (prim.PrimitiveType == Enums.GXPrimitiveType.TriangleStrip) { * Debug.Assert(prim.Vertices.Count >= 3); * } * else if (prim.PrimitiveType == Enums.GXPrimitiveType.Triangles) { * Debug.Assert(prim.Vertices.Count % 3 == 0); * }*/ //Console.WriteLine(String.Format("We had this many matrices: {0}", numMatrices)); pack.Primitives.Add(prim); } Packets.Add(pack); int mostmatrices = 0; if (true) { List <Weight> packWeights = new List <Weight>(); foreach (Packet packet in Packets) { int matrices = 0; foreach (Primitive prim in packet.Primitives) { foreach (Vertex vert in prim.Vertices) { if (!packWeights.Contains(vert.VertexWeight)) { packWeights.Add(vert.VertexWeight); matrices++; } } if (prim.PrimitiveType == Enums.GXPrimitiveType.TriangleStrip) { Debug.Assert(prim.Vertices.Count >= 3); } else if (prim.PrimitiveType == Enums.GXPrimitiveType.Triangles) { Debug.Assert(prim.Vertices.Count % 3 == 0); } } if (matrices > mostmatrices) { mostmatrices = matrices; } //Debug.Assert(matrices <= MaxMatricesPerPacket); //Console.WriteLine(matrices); packWeights.Clear(); } } //Console.WriteLine(String.Format("Most matrices: {0}", mostmatrices)); }
public void ProcessVerticesWithoutWeights(Mesh mesh, VertexData vertData) { Packet pack = new Packet(); List <Enums.GXVertexAttribute> activeAttribs = Descriptor.GetActiveAttributes(); AttributeData.SetAttributesFromList(activeAttribs); //Console.WriteLine("Calculating triangle strips"); uint[] triindices = MakeTriIndexList(mesh); TriStripper stripper = new TriStripper(triindices); List <PrimitiveBrawl> primlist = stripper.Strip(); //Console.WriteLine(String.Format("Done, {0} primitives", primlist.Count)); foreach (PrimitiveBrawl primbrawl in primlist) { //Primitive prim = new Primitive(Enums.GXPrimitiveType.TriangleStrip); Primitive prim = new Primitive((Enums.GXPrimitiveType)primbrawl.Type); //Console.WriteLine(String.Format("Primitive type {0}", (Enums.GXPrimitiveType)primbrawl.Type)); foreach (int vertIndex in primbrawl.Indices) { Vertex vert = new Vertex(); Weight rootWeight = new Weight(); rootWeight.AddWeight(1.0f, 0); vert.SetWeight(rootWeight); //int vertIndex = face.Indices[i]; foreach (Enums.GXVertexAttribute attrib in activeAttribs) { switch (attrib) { case Enums.GXVertexAttribute.Position: List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position); Vector3 vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3(); if (!posData.Contains(vertPos)) { posData.Add(vertPos); } AttributeData.Positions.Add(vertPos); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos)); break; case Enums.GXVertexAttribute.Normal: List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal); Vector3 vertNrm = mesh.Normals[vertIndex].ToOpenTKVector3(); if (!normData.Contains(vertNrm)) { normData.Add(vertNrm); } AttributeData.Normals.Add(vertNrm); vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm)); break; case Enums.GXVertexAttribute.Color0: case Enums.GXVertexAttribute.Color1: int colNo = (int)attrib - 11; List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo); Color vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA(); if (colNo == 0) { AttributeData.Color_0.Add(vertCol); } else { AttributeData.Color_1.Add(vertCol); } vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol)); break; case Enums.GXVertexAttribute.Tex0: case Enums.GXVertexAttribute.Tex1: case Enums.GXVertexAttribute.Tex2: case Enums.GXVertexAttribute.Tex3: case Enums.GXVertexAttribute.Tex4: case Enums.GXVertexAttribute.Tex5: case Enums.GXVertexAttribute.Tex6: case Enums.GXVertexAttribute.Tex7: int texNo = (int)attrib - 13; List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo); Vector2 vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2(); vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y); switch (texNo) { case 0: AttributeData.TexCoord_0.Add(vertTexCoord); break; case 1: AttributeData.TexCoord_1.Add(vertTexCoord); break; case 2: AttributeData.TexCoord_2.Add(vertTexCoord); break; case 3: AttributeData.TexCoord_3.Add(vertTexCoord); break; case 4: AttributeData.TexCoord_4.Add(vertTexCoord); break; case 5: AttributeData.TexCoord_5.Add(vertTexCoord); break; case 6: AttributeData.TexCoord_6.Add(vertTexCoord); break; case 7: AttributeData.TexCoord_7.Add(vertTexCoord); break; } vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord)); break; } } //triindices[vertIndex] = 1; prim.Vertices.Add(vert); } pack.Primitives.Add(prim); } pack.MatrixIndices.Add(0); Packets.Add(pack); Bounds.GetBoundsValues(AttributeData.Positions); }
public void ProcessVerticesWithoutWeights(Mesh mesh, VertexData vertData) { Packet pack = new Packet(); Primitive prim = new Primitive(Enums.GXPrimitiveType.Triangles); List <Enums.GXVertexAttribute> activeAttribs = Descriptor.GetActiveAttributes(); AttributeData.SetAttributesFromList(activeAttribs); foreach (Face face in mesh.Faces) { for (int i = 0; i < 3; i++) { Vertex vert = new Vertex(); Weight rootWeight = new Weight(); rootWeight.AddWeight(1.0f, 0); vert.SetWeight(rootWeight); int vertIndex = face.Indices[i]; foreach (Enums.GXVertexAttribute attrib in activeAttribs) { switch (attrib) { case Enums.GXVertexAttribute.Position: List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position); Vector3 vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3(); AttributeData.Positions.Add(vertPos); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos)); break; case Enums.GXVertexAttribute.Normal: List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal); Vector3 vertNrm = mesh.Normals[vertIndex].ToOpenTKVector3(); AttributeData.Normals.Add(vertNrm); vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm)); break; case Enums.GXVertexAttribute.Color0: case Enums.GXVertexAttribute.Color1: int colNo = (int)attrib - 11; List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo); Color vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA(); if (colNo == 0) { AttributeData.Color_0.Add(vertCol); } else { AttributeData.Color_1.Add(vertCol); } vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol)); break; case Enums.GXVertexAttribute.Tex0: case Enums.GXVertexAttribute.Tex1: case Enums.GXVertexAttribute.Tex2: case Enums.GXVertexAttribute.Tex3: case Enums.GXVertexAttribute.Tex4: case Enums.GXVertexAttribute.Tex5: case Enums.GXVertexAttribute.Tex6: case Enums.GXVertexAttribute.Tex7: int texNo = (int)attrib - 13; List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo); Vector2 vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2(); vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y); switch (texNo) { case 0: AttributeData.TexCoord_0.Add(vertTexCoord); break; case 1: AttributeData.TexCoord_1.Add(vertTexCoord); break; case 2: AttributeData.TexCoord_2.Add(vertTexCoord); break; case 3: AttributeData.TexCoord_3.Add(vertTexCoord); break; case 4: AttributeData.TexCoord_4.Add(vertTexCoord); break; case 5: AttributeData.TexCoord_5.Add(vertTexCoord); break; case 6: AttributeData.TexCoord_6.Add(vertTexCoord); break; case 7: AttributeData.TexCoord_7.Add(vertTexCoord); break; } vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord)); break; } } prim.Vertices.Add(vert); } } pack.Primitives.Add(prim); pack.MatrixIndices.Add(0); Packets.Add(pack); Bounds.GetBoundsValues(AttributeData.Positions); }
public void ProcessVerticesWithWeights(Mesh mesh, VertexData vertData, Dictionary <string, int> boneNames, EVP1 envelopes, DRW1 partialWeight) { Packet pack = new Packet(); Primitive prim = new Primitive(Enums.GXPrimitiveType.Triangles); List <Enums.GXVertexAttribute> activeAttribs = Descriptor.GetActiveAttributes(); AttributeData.SetAttributesFromList(activeAttribs); List <Weight> packetWeights = new List <Weight>(); int numMatrices = 0; foreach (Face face in mesh.Faces) { int vert1Index = face.Indices[0]; int vert2Index = face.Indices[1]; int vert3Index = face.Indices[2]; Weight vert1Weight = new Weight(); Weight vert2Weight = new Weight(); Weight vert3Weight = new Weight(); // Get the weights for this tri's vertices foreach (Assimp.Bone bone in mesh.Bones) { foreach (VertexWeight weight in bone.VertexWeights) { if (weight.VertexID == vert1Index) { vert1Weight.AddWeight(weight.Weight, boneNames[bone.Name]); } if (weight.VertexID == vert2Index) { vert2Weight.AddWeight(weight.Weight, boneNames[bone.Name]); } if (weight.VertexID == vert3Index) { vert3Weight.AddWeight(weight.Weight, boneNames[bone.Name]); } } } if (!packetWeights.Contains(vert1Weight)) { numMatrices += vert1Weight.WeightCount; } if (!packetWeights.Contains(vert2Weight)) { numMatrices += vert2Weight.WeightCount; } if (!packetWeights.Contains(vert3Weight)) { numMatrices += vert1Weight.WeightCount; } // There are too many matrices, we need to create a new packet if (numMatrices > 10) { pack.Primitives.Add(prim); Packets.Add(pack); prim = new Primitive(Enums.GXPrimitiveType.Triangles); pack = new Packet(); packetWeights.Clear(); numMatrices = 0; packetWeights.Add(vert1Weight); packetWeights.Add(vert2Weight); packetWeights.Add(vert3Weight); if (!packetWeights.Contains(vert1Weight)) { numMatrices += vert1Weight.WeightCount; } if (!packetWeights.Contains(vert2Weight)) { numMatrices += vert2Weight.WeightCount; } if (!packetWeights.Contains(vert3Weight)) { numMatrices += vert1Weight.WeightCount; } } // Matrix count is below 10, we can continue using the current packet else { if (!packetWeights.Contains(vert1Weight)) { packetWeights.Add(vert1Weight); } if (!packetWeights.Contains(vert2Weight)) { packetWeights.Add(vert2Weight); } if (!packetWeights.Contains(vert3Weight)) { packetWeights.Add(vert3Weight); } } int[] vertexIndexArray = new int[] { vert1Index, vert2Index, vert3Index }; Weight[] vertWeightArray = new Weight[] { vert1Weight, vert2Weight, vert3Weight }; for (int i = 0; i < 3; i++) { Vertex vert = new Vertex(); int vertIndex = vertexIndexArray[i]; Weight curWeight = vertWeightArray[i]; vert.SetWeight(curWeight); foreach (Enums.GXVertexAttribute attrib in activeAttribs) { switch (attrib) { case Enums.GXVertexAttribute.PositionMatrixIdx: int newMatrixIndex = -1; if (curWeight.WeightCount == 1) { newMatrixIndex = partialWeight.MeshWeights.IndexOf(curWeight); } else { if (!envelopes.Weights.Contains(curWeight)) { envelopes.Weights.Add(curWeight); } int envIndex = envelopes.Weights.IndexOf(curWeight); int drwIndex = partialWeight.MeshWeights.IndexOf(curWeight); newMatrixIndex = drwIndex; partialWeight.Indices[drwIndex] = envIndex; } if (!pack.MatrixIndices.Contains(newMatrixIndex)) { pack.MatrixIndices.Add(newMatrixIndex); } vert.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(newMatrixIndex)); break; case Enums.GXVertexAttribute.Position: List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position); Vector3 vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3(); if (curWeight.WeightCount == 1) { Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]]; Vector3 transVec = Vector3.TransformPosition(vertPos, ibm); posData.Add(transVec); AttributeData.Positions.Add(transVec); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(transVec)); } else { AttributeData.Positions.Add(vertPos); vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos)); } break; case Enums.GXVertexAttribute.Normal: List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal); Vector3 vertNrm = mesh.Normals[vertIndex].ToOpenTKVector3(); AttributeData.Normals.Add(vertNrm); vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm)); break; case Enums.GXVertexAttribute.Color0: case Enums.GXVertexAttribute.Color1: int colNo = (int)attrib - 11; List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo); Color vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA(); if (colNo == 0) { AttributeData.Color_0.Add(vertCol); } else { AttributeData.Color_1.Add(vertCol); } vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol)); break; case Enums.GXVertexAttribute.Tex0: case Enums.GXVertexAttribute.Tex1: case Enums.GXVertexAttribute.Tex2: case Enums.GXVertexAttribute.Tex3: case Enums.GXVertexAttribute.Tex4: case Enums.GXVertexAttribute.Tex5: case Enums.GXVertexAttribute.Tex6: case Enums.GXVertexAttribute.Tex7: int texNo = (int)attrib - 13; List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo); Vector2 vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2(); vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y); switch (texNo) { case 0: AttributeData.TexCoord_0.Add(vertTexCoord); break; case 1: AttributeData.TexCoord_1.Add(vertTexCoord); break; case 2: AttributeData.TexCoord_2.Add(vertTexCoord); break; case 3: AttributeData.TexCoord_3.Add(vertTexCoord); break; case 4: AttributeData.TexCoord_4.Add(vertTexCoord); break; case 5: AttributeData.TexCoord_5.Add(vertTexCoord); break; case 6: AttributeData.TexCoord_6.Add(vertTexCoord); break; case 7: AttributeData.TexCoord_7.Add(vertTexCoord); break; } vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord)); break; } } prim.Vertices.Add(vert); } } pack.Primitives.Add(prim); Packets.Add(pack); }