// Used for collision rendering public FlverSubmeshRenderer(Model parent, HKX colhkx, HKX.FSNPCustomParamCompressedMeshShape meshdata) { Parent = parent; var coldata = meshdata.GetMeshShapeData(); var tree = coldata.getMeshBVH(); var box = new DbgPrimWireBox(Transform.Default, Vector3.One, Color.Cyan); if (tree != null) { //DebugBVHDraw(tree, box); } var vertices = new VertexPositionColorNormalTangentTexture[coldata.SmallVertices.Size + coldata.LargeVertices.Size]; /*for (int i = 0; i < coldata.SmallVertices.Size; i++) * { * var vert = coldata.SmallVertices.GetArrayData().Elements[i].Decompress(coldata.BoundingBoxMin, coldata.BoundingBoxMax); * vertices[i] = new VertexPositionColorNormalTangentTexture(); * vertices[i].Position = new Vector3(vert.X, vert.Y, vert.Z); * }*/ var largebase = coldata.SmallVertices.Size; for (int i = 0; i < coldata.LargeVertices.Size; i++) { var vert = coldata.LargeVertices.GetArrayData().Elements[i].Decompress(coldata.BoundingBoxMin, coldata.BoundingBoxMax); vertices[i + largebase] = new VertexPositionColorNormalTangentTexture(); vertices[i + largebase].Position = new Vector3(vert.X, vert.Y, vert.Z); } MeshFacesets = new List <FlverSubmeshRendererFaceSet>(); int ch = 0; foreach (var chunk in coldata.Chunks.GetArrayData().Elements) { /*if (ch != 1) * { * ch++; * continue; * } * ch++;*/ /*var tree2 = chunk.getChunkBVH(); * if (tree2 != null) * { * DebugBVHDraw(tree2, box); * }*/ List <ushort> indices = new List <ushort>(); for (int i = 0; i < chunk.ByteIndicesLength; i++) { var tri = coldata.MeshIndices.GetArrayData().Elements[i + chunk.ByteIndicesIndex]; if (tri.Idx2 == tri.Idx3 && tri.Idx1 != tri.Idx2) { if (tri.Idx0 < chunk.VertexIndicesLength) { ushort index = (ushort)((uint)tri.Idx0 + chunk.SmallVerticesBase); indices.Add(index); var vert = coldata.SmallVertices.GetArrayData().Elements[index].Decompress(chunk.SmallVertexScale, chunk.SmallVertexOffset); vertices[index] = new VertexPositionColorNormalTangentTexture(); vertices[index].Position = new Vector3(vert.X, vert.Y, vert.Z); } else { indices.Add((ushort)(coldata.VertexIndices.GetArrayData().Elements[tri.Idx0 + chunk.VertexIndicesIndex - chunk.VertexIndicesLength].data + largebase)); } if (tri.Idx1 < chunk.VertexIndicesLength) { ushort index = (ushort)((uint)tri.Idx1 + chunk.SmallVerticesBase); indices.Add(index); var vert = coldata.SmallVertices.GetArrayData().Elements[index].Decompress(chunk.SmallVertexScale, chunk.SmallVertexOffset); vertices[index] = new VertexPositionColorNormalTangentTexture(); vertices[index].Position = new Vector3(vert.X, vert.Y, vert.Z); } else { indices.Add((ushort)(coldata.VertexIndices.GetArrayData().Elements[tri.Idx1 + chunk.VertexIndicesIndex - chunk.VertexIndicesLength].data + largebase)); } if (tri.Idx2 < chunk.VertexIndicesLength) { ushort index = (ushort)((uint)tri.Idx2 + chunk.SmallVerticesBase); indices.Add(index); var vert = coldata.SmallVertices.GetArrayData().Elements[index].Decompress(chunk.SmallVertexScale, chunk.SmallVertexOffset); vertices[index] = new VertexPositionColorNormalTangentTexture(); vertices[index].Position = new Vector3(vert.X, vert.Y, vert.Z); } else { indices.Add((ushort)(coldata.VertexIndices.GetArrayData().Elements[tri.Idx2 + chunk.VertexIndicesIndex - chunk.VertexIndicesLength].data + largebase)); } } } if (indices.Count > 0) { var newFaceSet = new FlverSubmeshRendererFaceSet() { BackfaceCulling = false, IsTriangleStrip = false, IndexBuffer = new IndexBuffer( GFX.Device, IndexElementSize.SixteenBits, indices.Count, BufferUsage.WriteOnly), IndexCount = indices.Count, }; newFaceSet.IndexBuffer.SetData(indices.Select(x => (ushort)x).ToArray()); MeshFacesets.Add(newFaceSet); } } Bounds = BoundingBox.CreateFromPoints(vertices.Select(x => x.Position)); VertBuffer = new VertexBuffer(GFX.Device, typeof(VertexPositionColorNormalTangentTexture), vertices.Length, BufferUsage.WriteOnly); VertBuffer.SetData(vertices); VertBufferBinding = new VertexBufferBinding(VertBuffer, 0, 0); }
public FlverSubmeshRenderer(Model parent, FLVER flvr, FLVER.Mesh mesh) { Parent = parent; var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(flvr.Materials[mesh.MaterialIndex].MTD); if (shortMaterialName.EndsWith("_Alp") || shortMaterialName.Contains("_Edge") || shortMaterialName.Contains("_Decal") || shortMaterialName.Contains("_Cloth") || shortMaterialName.Contains("_al") || shortMaterialName.Contains("BlendOpacity")) { DrawStep = GFXDrawStep.AlphaEdge; } else { DrawStep = GFXDrawStep.Opaque; } bool hasLightmap = false; foreach (var matParam in flvr.Materials[mesh.MaterialIndex].Textures) { var paramNameCheck = matParam.Type.ToUpper(); // DS3/BB if (paramNameCheck == "G_DIFFUSETEXTURE") { TexNameDiffuse = matParam.Path; } else if (paramNameCheck == "G_SPECULARTEXTURE") { TexNameSpecular = matParam.Path; } else if (paramNameCheck == "G_BUMPMAPTEXTURE") { TexNameNormal = matParam.Path; } else if (paramNameCheck == "G_DOLTEXTURE1") { TexNameDOL1 = matParam.Path; hasLightmap = true; } else if (paramNameCheck == "G_DOLTEXTURE2") { TexNameDOL2 = matParam.Path; } // DS1 params else if (paramNameCheck == "G_DIFFUSE") { TexNameDiffuse = matParam.Path; } else if (paramNameCheck == "G_SPECULAR") { TexNameSpecular = matParam.Path; } else if (paramNameCheck == "G_BUMPMAP") { TexNameNormal = matParam.Path; } else if (paramNameCheck == "G_LIGHTMAP") { TexNameDOL1 = matParam.Path; hasLightmap = true; } // Alternate material params that work as diffuse } // MTD lookup MTD mtd = InterrootLoader.GetMTD(flvr.Materials[mesh.MaterialIndex].MTD); var MeshVertices = new VertexPositionColorNormalTangentTexture[mesh.Vertices.Count]; for (int i = 0; i < mesh.Vertices.Count; i++) { var vert = mesh.Vertices[i]; MeshVertices[i] = new VertexPositionColorNormalTangentTexture(); MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z); if (vert.Normal != null && vert.Tangents != null && vert.Tangents.Count > 0) { MeshVertices[i].Normal = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z)); MeshVertices[i].Tangent = Vector3.Normalize(new Vector3(vert.Tangents[0].X, vert.Tangents[0].Y, vert.Tangents[0].Z)); MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.Tangents[0].W; } if (vert.UVs.Count > 0) { MeshVertices[i].TextureCoordinate = new Vector2(vert.UVs[0].X, vert.UVs[0].Y); if (vert.UVs.Count > 1 && hasLightmap) { if (mtd == null) { // Really stupid heuristic to determine light map UVs without reading mtd files or something if (vert.UVs.Count > 2 && flvr.Materials[mesh.MaterialIndex].Textures.Count > 11) { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[2].X, vert.UVs[2].Y); } else { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y); } } else { // Better heuristic with MTDs int uvindex = mtd.Textures.Find(tex => tex.Type.ToUpper() == "G_LIGHTMAP" || tex.Type.ToUpper() == "G_DOLTEXTURE1").UVNumber; int uvoffset = 1; for (int j = 1; j < uvindex; j++) { if (!mtd.Textures.Any(t => (t.UVNumber == j))) { uvoffset++; } } uvindex -= uvoffset; if (vert.UVs.Count > uvindex) { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[uvindex].X, vert.UVs[uvindex].Y); } else { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y); } } } else { MeshVertices[i].TextureCoordinate2 = Vector2.Zero; } } else { MeshVertices[i].TextureCoordinate = Vector2.Zero; MeshVertices[i].TextureCoordinate2 = Vector2.Zero; } } VertexCount = MeshVertices.Length; MeshFacesets = new List <FlverSubmeshRendererFaceSet>(); foreach (var faceset in mesh.FaceSets) { bool is32bit = faceset.IndexSize == 0x20; var newFaceSet = new FlverSubmeshRendererFaceSet() { BackfaceCulling = faceset.CullBackfaces, IsTriangleStrip = faceset.TriangleStrip, IndexBuffer = new IndexBuffer( GFX.Device, is32bit ? IndexElementSize.ThirtyTwoBits : IndexElementSize.SixteenBits, faceset.Vertices.Length, BufferUsage.WriteOnly), IndexCount = faceset.Vertices.Length, }; if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel1) { newFaceSet.LOD = 1; HasNoLODs = false; } else if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel2) { newFaceSet.LOD = 2; HasNoLODs = false; } if (is32bit) { newFaceSet.IndexBuffer.SetData(faceset.Vertices); } else { newFaceSet.IndexBuffer.SetData(faceset.Vertices.Select(x => (ushort)x).ToArray()); } MeshFacesets.Add(newFaceSet); } Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position)); VertBuffer = new VertexBuffer(GFX.Device, typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly); VertBuffer.SetData(MeshVertices); VertBufferBinding = new VertexBufferBinding(VertBuffer, 0, 0); TryToLoadTextures(); }
/*public FlverSubmeshRenderer(FlverSubmesh f) * { * var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(f.Material.MTDName); * if (shortMaterialName.EndsWith("_Alp") || shortMaterialName.EndsWith("_Edge")) * { * DrawStep = GFXDrawStep.AlphaEdge; * } * else * { * DrawStep = GFXDrawStep.Opaque; * } * * foreach (var matParam in f.Material.Parameters) * { * if (matParam.Name.ToUpper() == "G_DIFFUSE") * TexNameDiffuse = matParam.Value; * else if (matParam.Name.ToUpper() == "G_SPECULAR") * TexNameSpecular = matParam.Value; * else if (matParam.Name.ToUpper() == "G_BUMPMAP") * TexNameNormal = matParam.Value; * } * * var MeshVertices = new VertexPositionColorNormalTangentTexture[f.Vertices.Count]; * for (int i = 0; i < f.Vertices.Count; i++) * { * var vert = f.Vertices[i]; * MeshVertices[i] = new VertexPositionColorNormalTangentTexture(); * * MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z); * * if (vert.Normal != null && vert.BiTangent != null) * { * MeshVertices[i].Normal = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z)); * MeshVertices[i].Tangent = Vector3.Normalize(new Vector3(vert.BiTangent.X, vert.BiTangent.Y, vert.BiTangent.Z)); * MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.BiTangent.W; * } * * if (vert.UVs.Count > 0) * { * MeshVertices[i].TextureCoordinate = vert.UVs[0]; * } * else * { * MeshVertices[i].TextureCoordinate = Vector2.Zero; * } * * // We set the mesh's vertex color to that of a selected mesh. * // The shader with lighting ignores this so it will only show * // up on the primitive shader, which is what is used to draw * // the currently highlighted map piece * MeshVertices[i].Color = Main.SELECTED_MESH_COLOR.ToVector4(); * } * * VertexCount = MeshVertices.Length; * * MeshFacesets = new List<FlverSubmeshRendererFaceSet>(); * * foreach (var faceset in f.FaceSets) * { * var newFaceSet = new FlverSubmeshRendererFaceSet() * { * BackfaceCulling = faceset.CullBackfaces, * IsTriangleStrip = faceset.IsTriangleStrip, * IndexBuffer = new IndexBuffer( * GFX.Device, * IndexElementSize.SixteenBits, * sizeof(short) * faceset.VertexIndices.Count, * BufferUsage.None), * IndexCount = faceset.VertexIndices.Count, * }; * * if (faceset.FlagsLOD1) * { * newFaceSet.LOD = (byte)1; * HasNoLODs = false; * } * else if (faceset.FlagsLOD2) * { * newFaceSet.LOD = (byte)2; * HasNoLODs = false; * } * * newFaceSet.IndexBuffer.SetData(faceset.VertexIndices * .Select(x => * { * if (x == ushort.MaxValue) * return (short)(-1); * else * return (short)x; * }) * .ToArray()); * MeshFacesets.Add(newFaceSet); * } * * Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position)); * * VertBuffer = new VertexBuffer(GFX.Device, * typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly); * VertBuffer.SetData(MeshVertices); * }*/ public FlverSubmeshRenderer(FLVER flvr, FLVER.Mesh mesh) { var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(flvr.Materials[mesh.MaterialIndex].MTD); if (shortMaterialName.EndsWith("_Alp") || shortMaterialName.Contains("_Edge") || shortMaterialName.Contains("_Decal") || shortMaterialName.Contains("_Cloth") || shortMaterialName.Contains("_al") || shortMaterialName.Contains("BlendOpacity")) { DrawStep = GFXDrawStep.AlphaEdge; } else { DrawStep = GFXDrawStep.Opaque; } foreach (var matParam in flvr.Materials[mesh.MaterialIndex].Params) { var paramNameCheck = matParam.Param.ToUpper(); // DS3/BB if (paramNameCheck == "G_DIFFUSETEXTURE") { TexNameDiffuse = matParam.Value; } else if (paramNameCheck == "G_SPECULARTEXTURE") { TexNameSpecular = matParam.Value; } else if (paramNameCheck == "G_BUMPMAPTEXTURE") { TexNameNormal = matParam.Value; } else if (paramNameCheck == "G_DOLTEXTURE1") { TexNameDOL1 = matParam.Value; } else if (paramNameCheck == "G_DOLTEXTURE2") { TexNameDOL2 = matParam.Value; } // DS1 params else if (paramNameCheck == "G_DIFFUSE") { TexNameDiffuse = matParam.Value; } else if (paramNameCheck == "G_SPECULAR") { TexNameSpecular = matParam.Value; } else if (paramNameCheck == "G_BUMPMAP") { TexNameNormal = matParam.Value; } } var MeshVertices = new VertexPositionColorNormalTangentTexture[mesh.VertexGroups[0].Vertices.Count]; for (int i = 0; i < mesh.VertexGroups[0].Vertices.Count; i++) { var vert = mesh.VertexGroups[0].Vertices[i]; MeshVertices[i] = new VertexPositionColorNormalTangentTexture(); MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z); if (vert.Normal != null && vert.Tangents != null && vert.Tangents.Count > 0) { MeshVertices[i].Normal = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z)); MeshVertices[i].Tangent = Vector3.Normalize(new Vector3(vert.Tangents[0].X, vert.Tangents[0].Y, vert.Tangents[0].Z)); MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.Tangents[0].W; } if (vert.UVs.Count > 0) { MeshVertices[i].TextureCoordinate = new Vector2(vert.UVs[0].X, vert.UVs[0].Y); if (vert.UVs.Count > 1) { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y); } else { MeshVertices[i].TextureCoordinate2 = Vector2.Zero; } } else { MeshVertices[i].TextureCoordinate = Vector2.Zero; MeshVertices[i].TextureCoordinate2 = Vector2.Zero; } } VertexCount = MeshVertices.Length; MeshFacesets = new List <FlverSubmeshRendererFaceSet>(); foreach (var faceset in mesh.FaceSets) { bool is32bit = (faceset.IndexSize == 0x20); var newFaceSet = new FlverSubmeshRendererFaceSet() { BackfaceCulling = faceset.CullBackfaces, IsTriangleStrip = faceset.TriangleStrip, IndexBuffer = new IndexBuffer( GFX.Device, is32bit ? IndexElementSize.ThirtyTwoBits : IndexElementSize.SixteenBits, faceset.Vertices.Length, BufferUsage.WriteOnly), IndexCount = faceset.Vertices.Length, }; if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel1) { newFaceSet.LOD = (byte)1; HasNoLODs = false; } else if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel2) { newFaceSet.LOD = (byte)2; HasNoLODs = false; } if (is32bit) { newFaceSet.IndexBuffer.SetData(faceset.Vertices); } else { newFaceSet.IndexBuffer.SetData(faceset.Vertices.Select(x => (ushort)x).ToArray()); } MeshFacesets.Add(newFaceSet); } Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position)); VertBuffer = new VertexBuffer(GFX.Device, typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly); VertBuffer.SetData(MeshVertices); TryToLoadTextures(); }