private static void WorldToScene(Scene scene, World_000B world, string textureExtension) { for (int i = 0; i < world.materialList.materialList.Length; i++) { var mat = world.materialList.materialList[i]; scene.Materials.Add(new Material() { ColorDiffuse = new Color4D( mat.materialStruct.color.R / 255f, mat.materialStruct.color.G / 255f, mat.materialStruct.color.B / 255f, mat.materialStruct.color.A / 255f), TextureDiffuse = mat.materialStruct.isTextured != 0 ? new TextureSlot() { FilePath = mat.texture.diffuseTextureName.stringString + textureExtension, TextureType = TextureType.Diffuse } : default,
public static RWSection[] CreateBSPFromAssimp(string fileName, bool flipUVs, bool ignoreMeshColors) { PostProcessSteps pps = PostProcessSteps.Debone | PostProcessSteps.FindInstances | PostProcessSteps.FindInvalidData | PostProcessSteps.OptimizeGraph | PostProcessSteps.OptimizeMeshes | PostProcessSteps.Triangulate | PostProcessSteps.PreTransformVertices; Scene scene = new AssimpContext().ImportFile(fileName, pps); int vertexCount = scene.Meshes.Sum(m => m.VertexCount); int triangleCount = scene.Meshes.Sum(m => m.FaceCount); if (vertexCount > 65535 || triangleCount > 65536) { throw new ArgumentException("Model has too many vertices or triangles. Please import a simpler model."); } List <Vertex3> vertices = new List <Vertex3>(vertexCount); List <RenderWareFile.Color> vColors = new List <RenderWareFile.Color>(vertexCount); List <Vertex2> textCoords = new List <Vertex2>(vertexCount); List <RenderWareFile.Triangle> triangles = new List <RenderWareFile.Triangle>(triangleCount); int totalVertices = 0; foreach (var m in scene.Meshes) { foreach (Vector3D v in m.Vertices) { vertices.Add(new Vertex3(v.X, v.Y, v.Z)); } if (m.HasTextureCoords(0)) { foreach (Vector3D v in m.TextureCoordinateChannels[0]) { textCoords.Add(new Vertex2(v.X, flipUVs ? -v.Y : v.Y)); } } else { for (int i = 0; i < m.VertexCount; i++) { textCoords.Add(new Vertex2()); } } if (m.HasVertexColors(0)) { foreach (Color4D c in m.VertexColorChannels[0]) { vColors.Add(new RenderWareFile.Color( (byte)(c.R * 255), (byte)(c.G * 255), (byte)(c.B * 255), (byte)(c.A * 255))); } } else { for (int i = 0; i < m.VertexCount; i++) { vColors.Add(new RenderWareFile.Color(255, 255, 255, 255)); } } foreach (var t in m.Faces) { triangles.Add(new RenderWareFile.Triangle() { vertex1 = (ushort)(t.Indices[0] + totalVertices), vertex2 = (ushort)(t.Indices[1] + totalVertices), vertex3 = (ushort)(t.Indices[2] + totalVertices), materialIndex = (ushort)m.MaterialIndex }); } totalVertices += m.VertexCount; } if (vertices.Count != textCoords.Count || vertices.Count != vColors.Count) { throw new ArgumentException("Internal error: texture coordinate or vertex color count is different from vertex count."); } triangles = triangles.OrderBy(t => t.materialIndex).ToList(); Vertex3 Max = new Vertex3(vertices[0].X, vertices[0].Y, vertices[0].Z); Vertex3 Min = new Vertex3(vertices[0].X, vertices[0].Y, vertices[0].Z); foreach (Vertex3 i in vertices) { if (i.X > Max.X) { Max.X = i.X; } if (i.Y > Max.Y) { Max.Y = i.Y; } if (i.Z > Max.Z) { Max.Z = i.Z; } if (i.X < Min.X) { Min.X = i.X; } if (i.Y < Min.Y) { Min.Y = i.Y; } if (i.Z < Min.Z) { Min.Z = i.Z; } } Max = new Vertex3(MaximumBoundary, MaximumBoundary, MaximumBoundary); Min = new Vertex3(-MaximumBoundary, -MaximumBoundary, -MaximumBoundary); BinMesh[] binMeshes = new BinMesh[scene.MaterialCount]; Material_0007[] materials = new Material_0007[scene.MaterialCount]; for (int i = 0; i < scene.MaterialCount; i++) { List <int> indices = new List <int>(triangles.Count); foreach (RenderWareFile.Triangle f in triangles) { if (f.materialIndex == i) { indices.Add(f.vertex1); indices.Add(f.vertex2); indices.Add(f.vertex3); } } binMeshes[i] = new BinMesh() { materialIndex = i, indexCount = indices.Count(), vertexIndices = indices.ToArray() }; materials[i] = new Material_0007() { materialStruct = new MaterialStruct_0001() { unusedFlags = 0, color = ignoreMeshColors ? new RenderWareFile.Color(255, 255, 255, 255) : new RenderWareFile.Color( (byte)(scene.Materials[i].ColorDiffuse.R / 255), (byte)(scene.Materials[i].ColorDiffuse.G / 255), (byte)(scene.Materials[i].ColorDiffuse.B / 255), (byte)(scene.Materials[i].ColorDiffuse.A / 255)), unusedInt2 = 0x2DF53E84, isTextured = scene.Materials[i].HasTextureDiffuse ? 1 : 0, ambient = ignoreMeshColors ? 1f : scene.Materials[i].ColorAmbient.A, specular = ignoreMeshColors ? 1f : scene.Materials[i].ColorSpecular.A, diffuse = ignoreMeshColors ? 1f : scene.Materials[i].ColorDiffuse.A }, texture = scene.Materials[i].HasTextureDiffuse ? RWTextureFromAssimpMaterial(scene.Materials[i].TextureDiffuse) : null, materialExtension = new Extension_0003() { extensionSectionList = new List <RWSection>() }, }; } WorldFlags worldFlags = WorldFlags.HasOneSetOfTextCoords | WorldFlags.HasVertexColors | WorldFlags.WorldSectorsOverlap | (WorldFlags)0x00010000; World_000B world = new World_000B() { worldStruct = new WorldStruct_0001() { rootIsWorldSector = 1, inverseOrigin = new Vertex3(-0f, -0f, -0f), numTriangles = (uint)triangleCount, numVertices = (uint)vertexCount, numPlaneSectors = 0, numAtomicSectors = 1, colSectorSize = 0, worldFlags = worldFlags, boxMaximum = Max, boxMinimum = Min, }, materialList = new MaterialList_0008() { materialListStruct = new MaterialListStruct_0001() { materialCount = scene.MaterialCount }, materialList = materials }, firstWorldChunk = new AtomicSector_0009() { atomicSectorStruct = new AtomicSectorStruct_0001() { matListWindowBase = 0, numTriangles = triangleCount, numVertices = vertexCount, boxMaximum = Max, boxMinimum = Min, collSectorPresent = 0x2F50D984, unused = 0, vertexArray = vertices.ToArray(), colorArray = vColors.ToArray(), uvArray = textCoords.ToArray(), triangleArray = triangles.ToArray() }, atomicSectorExtension = new Extension_0003() { extensionSectionList = new List <RWSection>() { new BinMeshPLG_050E() { binMeshHeaderFlags = BinMeshHeaderFlags.TriangleList, numMeshes = binMeshes.Count(), totalIndexCount = binMeshes.Sum(b => b.indexCount), binMeshList = binMeshes }, new CollisionPLG_011D_Scooby() { splits = new Split_Scooby[0], startIndex_amountOfTriangles = new short[][] { new short[] { 0, (short)triangles.Count } }, triangles = TriangleRange(triangles.Count) } } } }, worldExtension = new Extension_0003() }; return(new RWSection[] { world }); }
public static RWSection[] CreateShadowCollisionBSPFile(ModelConverterData data) { Vertex3 Max = new Vertex3(data.VertexList[0].Position.X, data.VertexList[0].Position.Y, data.VertexList[0].Position.Z); Vertex3 Min = new Vertex3(data.VertexList[0].Position.X, data.VertexList[0].Position.Y, data.VertexList[0].Position.Z); foreach (Vertex i in data.VertexList) { if (i.Position.X > Max.X) { Max.X = i.Position.X; } if (i.Position.Y > Max.Y) { Max.Y = i.Position.Y; } if (i.Position.Z > Max.Z) { Max.Z = i.Position.Z; } if (i.Position.X < Min.X) { Min.X = i.Position.X; } if (i.Position.Y < Min.Y) { Min.Y = i.Position.Y; } if (i.Position.Z < Min.Z) { Min.Z = i.Position.Z; } } List <Vertex3> vList = new List <Vertex3>(data.VertexList.Count); foreach (Vertex v in data.VertexList) { vList.Add(new Vertex3(v.Position.X, v.Position.Y, v.Position.Z)); } List <RenderWareFile.Triangle> tList = new List <RenderWareFile.Triangle>(data.TriangleList.Count); foreach (Triangle t in data.TriangleList) { tList.Add(new RenderWareFile.Triangle((ushort)t.MaterialIndex, (ushort)t.vertex1, (ushort)t.vertex2, (ushort)t.vertex3)); } List <BinMesh> binMeshList = new List <BinMesh>(); int TotalNumberOfTristripIndicies = 0; for (int i = 0; i < data.MaterialList.Count; i++) { List <int> indices = new List <int>(); foreach (Triangle f in data.TriangleList) { if (f.MaterialIndex == i) { indices.Add(f.vertex1); indices.Add(f.vertex2); indices.Add(f.vertex3); } } TotalNumberOfTristripIndicies += indices.Count(); binMeshList.Add(new BinMesh { materialIndex = i, indexCount = indices.Count(), vertexIndices = indices.ToArray() }); } // GENERATE COLLISION DATA List <ushort> TriangleIndexList = new List <ushort>(); List <Split> splitlist = new List <Split>(); ushort loop = 0; bool exitloop = false; Split split = new Split(); byte trianglesPerSplit = 200; while (!exitloop) { split = new Split { negativeSector = new Sector() { Max = Max, Min = Min, TriangleIndexList = new List <ushort>(), splitPosition = Max.X, type = SectorType.NegativeX }, positiveSector = new Sector() { Max = Max, Min = Min, TriangleIndexList = new List <ushort>(), splitPosition = Min.X, type = SectorType.PositiveX } }; for (ushort i = (ushort)(trianglesPerSplit * loop); i < tList.Count(); i++) { TriangleIndexList.Add(i); split.negativeSector.TriangleIndexList.Add(i); if (split.negativeSector.TriangleIndexList.Count() == trianglesPerSplit) { split.negativeSector.triangleAmount = trianglesPerSplit; split.negativeSector.referenceIndex = (ushort)(trianglesPerSplit * loop); loop += 1; split.positiveSector.triangleAmount = 0xFF; split.positiveSector.referenceIndex = loop; splitlist.Add(split); split = new Split(); exitloop = false; break; } exitloop = true; } } split.negativeSector.triangleAmount = (byte)split.negativeSector.TriangleIndexList.Count(); split.negativeSector.referenceIndex = (ushort)(trianglesPerSplit * loop); split.positiveSector.triangleAmount = 0; split.positiveSector.referenceIndex = 0; loop += 1; splitlist.Add(split); //Sector sector = new Sector() //{ // Max = Max, // Min = Min, // TriangleIndexList = new List<ushort>() //}; // sector.TriangleIndexList = FindTrianglesInsideNode(vList, tList, sector, TriangleIndexList); // List<ushort> TriangleIndexReferenceList = new List<ushort>(); // List<Split> splitList = new List<Split>(); //PositionOnList = 0; //SplitSector(sector, 20, 0, splitList, TriangleIndexReferenceList, vList, tList); // COLLISION FLAGS Color[] cFlagList = new Color[data.MaterialList.Count]; for (int i = 0; i < cFlagList.Length; i++) { cFlagList[i] = new Color(0x01, 0x00, 0x02, 0x00); string a = data.MaterialList[i].Split('_').Last(); if (a == "c") // ceiling { cFlagList[i] = new Color(0x00, 0x00, 0x00, 0x00); } else if (a == "f") // road floor { cFlagList[i] = new Color(0x01, 0x00, 0x02, 0x00); } else if (a == "fs") // stone floor { cFlagList[i] = new Color(0x01, 0x00, 0x00, 0x60); } else if (a == "fm") // metal floor { cFlagList[i] = new Color(0x01, 0x01, 0x01, 0x10); } else if (a == "t") // triangle jump wall { cFlagList[i] = new Color(0x02, 0x00, 0x00, 0x00); } else if (a == "a") // angle wall { cFlagList[i] = new Color(0x02, 0x01, 0x01, 0x10); } else if (a == "i") // invisible wall { cFlagList[i] = new Color(0x02, 0x02, 0x00, 0x00); } else if (a == "g") // green goo { cFlagList[i] = new Color(0x05, 0x00, 0x02, 0x00); } else if (a == "k") // barrier { cFlagList[i] = new Color(0x08, 0x00, 0x00, 0x00); } else if (a == "i2") // invisible wall at distance { cFlagList[i] = new Color(0x10, 0x00, 0x00, 0x00); } else if (a == "x") // death { cFlagList[i] = new Color(0x20, 0x00, 0x00, 0x00); } else if (a.Count() == 8) { try { cFlagList[i] = Color.FromString(a); } catch { cFlagList[i] = new Color(0x01, 0x00, 0x02, 0x00); } } } List <Color> cFlags = new List <Color>(); foreach (Triangle t in data.TriangleList) { cFlags.Add(cFlagList[t.MaterialIndex]); } // GENERATE RENDERWARE DATA World_000B world = new World_000B { worldStruct = new WorldStruct_0001() { rootIsWorldSector = 1, inverseOrigin = new Vertex3(-0f, -0f, -0f), numTriangles = (uint)data.TriangleList.Count(), numVertices = (uint)data.VertexList.Count(), numPlaneSectors = 0, numAtomicSectors = 1, colSectorSize = 0, worldFlags = WorldFlags.WorldSectorsOverlap,// | WorldFlags.ModulateMaterialColors, //(WorldFlags)0x40000040, boxMaximum = Max, boxMinimum = Min }, materialList = new MaterialList_0008() { materialListStruct = new MaterialListStruct_0001() { materialCount = data.MaterialList.Count() }, materialList = new Material_0007[data.MaterialList.Count()] }, firstWorldChunk = new AtomicSector_0009() { atomicSectorStruct = new AtomicSectorStruct_0001() { matListWindowBase = 0, numTriangles = data.TriangleList.Count(), numVertices = data.VertexList.Count(), boxMaximum = Max, boxMinimum = Min, collSectorPresent = 0x0012f410, unused = 0, vertexArray = vList.ToArray(), colorArray = null, uvArray = null, triangleArray = tList.ToArray() }, atomicSectorExtension = new Extension_0003() { extensionSectionList = new List <RWSection>() { new BinMeshPLG_050E() { binMeshHeaderFlags = BinMeshHeaderFlags.TriangleList, numMeshes = binMeshList.Count(), totalIndexCount = TotalNumberOfTristripIndicies, binMeshList = binMeshList.ToArray() }, new CollisionPLG_011D() { colTree = new ColTree_002C() { colTreeStruct = new ColTreeStruct_0001() { useMap = 1, boxMaximum = Max, boxMinimum = Min, numSplits = splitlist.Count(), numTriangles = TriangleIndexList.Count(), splitArray = splitlist.ToArray(), triangleArray = TriangleIndexList.ToArray(), }, }, unknownValue = 0x00037002 }, new UserDataPLG_011F() { userDataType = 0x02, unknown2 = 0x0A, attribute = "attribute", unknown3 = 0x01, numTriangles = tList.Count(), collisionFlags = cFlags.ToArray(), unknown4 = 0x0D, userData = "FVF.UserData", unknown5 = 0x01, unknown6 = 0x01, unknown7 = 0x3003 } } } }, worldExtension = new Extension_0003() }; for (int i = 0; i < data.MaterialList.Count; i++) { world.materialList.materialList[i] = new Material_0007() { materialStruct = new MaterialStruct_0001() { unusedFlags = 0, color = new Color() { R = 0xFF, G = 0xFF, B = 0xFF, A = 0xFF }, unusedInt2 = 0x01FAE70C, isTextured = 0, ambient = 1f, specular = 1f, diffuse = 1f }, texture = null, materialExtension = new Extension_0003() }; } return(new RWSection[] { world }); }
public static RWSection[] CreateBSPFile(string FileNameForBox, ModelConverterData data) { Vertex3 Max = new Vertex3(data.VertexList[0].Position.X, data.VertexList[0].Position.Y, data.VertexList[0].Position.Z); Vertex3 Min = new Vertex3(data.VertexList[0].Position.X, data.VertexList[0].Position.Y, data.VertexList[0].Position.Z); foreach (Vertex i in data.VertexList) { if (i.Position.X > Max.X) { Max.X = i.Position.X; } if (i.Position.Y > Max.Y) { Max.Y = i.Position.Y; } if (i.Position.Z > Max.Z) { Max.Z = i.Position.Z; } if (i.Position.X < Min.X) { Min.X = i.Position.X; } if (i.Position.Y < Min.Y) { Min.Y = i.Position.Y; } if (i.Position.Z < Min.Z) { Min.Z = i.Position.Z; } } List <Vertex3> vList = new List <Vertex3>(data.VertexList.Count); foreach (Vertex v in data.VertexList) { vList.Add(new Vertex3(v.Position.X, v.Position.Y, v.Position.Z)); } List <RenderWareFile.Color> cList = new List <RenderWareFile.Color>(data.VertexList.Count); foreach (Vertex v in data.VertexList) { cList.Add(new RenderWareFile.Color(v.Color.R, v.Color.G, v.Color.B, v.Color.A)); } List <TextCoord> uvList = new List <TextCoord>(data.VertexList.Count); if (Program.levelEditor.checkBoxFlipUVs.Checked) { foreach (Vertex v in data.VertexList) { uvList.Add(new TextCoord(v.TexCoord.X, v.TexCoord.Y)); } } else { foreach (Vertex v in data.VertexList) { uvList.Add(new TextCoord(v.TexCoord.X, -v.TexCoord.Y)); } } List <RenderWareFile.Triangle> tList = new List <RenderWareFile.Triangle>(data.TriangleList.Count); foreach (Triangle t in data.TriangleList) { tList.Add(new RenderWareFile.Triangle((ushort)t.MaterialIndex, (ushort)t.vertex1, (ushort)t.vertex2, (ushort)t.vertex3)); } List <BinMesh> binMeshList = new List <BinMesh>(); int TotalNumberOfTristripIndicies = 0; if (Program.levelEditor.checkBoxTristrip.Checked) // tristrip generator { for (int i = 0; i < data.MaterialList.Count; i++) { List <Triangle> TriangleStream2 = new List <Triangle>(); foreach (Triangle f in data.TriangleList) { if (f.MaterialIndex == i) { TriangleStream2.Add(f); } } List <List <int> > indexLists = GenerateTristrips(TriangleStream2); foreach (List <int> indices in indexLists) { TotalNumberOfTristripIndicies += indices.Count(); binMeshList.Add(new BinMesh() { materialIndex = i, indexCount = indices.Count(), vertexIndices = indices.ToArray() }); } } } else //trilist generator { for (int i = 0; i < data.MaterialList.Count; i++) { List <int> indices = new List <int>(); foreach (Triangle f in data.TriangleList) { if (f.MaterialIndex == i) { indices.Add(f.vertex1); indices.Add(f.vertex2); indices.Add(f.vertex3); } } TotalNumberOfTristripIndicies += indices.Count(); binMeshList.Add(new BinMesh { materialIndex = i, indexCount = indices.Count(), vertexIndices = indices.ToArray() }); } } WorldFlags worldFlags = WorldFlags.HasOneSetOfTextCoords | WorldFlags.HasVertexColors | WorldFlags.WorldSectorsOverlap | (WorldFlags)0x00010000; worldFlags = Program.levelEditor.checkBoxTristrip.Checked ? worldFlags | WorldFlags.UseTriangleStrips : worldFlags; World_000B world = new World_000B() { worldStruct = new WorldStruct_0001() { rootIsWorldSector = 1, inverseOrigin = new Vertex3(-0f, -0f, -0f), numTriangles = (uint)data.TriangleList.Count(), numVertices = (uint)data.VertexList.Count(), numPlaneSectors = 0, numAtomicSectors = 1, colSectorSize = 0, worldFlags = worldFlags, boxMaximum = Max, boxMinimum = Min, }, materialList = new MaterialList_0008() { materialListStruct = new MaterialListStruct_0001() { materialCount = data.MaterialList.Count() }, materialList = new Material_0007[data.MaterialList.Count()] }, firstWorldChunk = new AtomicSector_0009() { atomicStruct = new AtomicSectorStruct_0001() { matListWindowBase = 0, numTriangles = data.TriangleList.Count(), numVertices = data.VertexList.Count(), boxMaximum = Max, boxMinimum = Min, collSectorPresent = 0x2F50D984, unused = 0, vertexArray = vList.ToArray(), colorArray = cList.ToArray(), uvArray = uvList.ToArray(), triangleArray = tList.ToArray() }, atomicExtension = new Extension_0003() { extensionSectionList = new List <RWSection>() { new BinMeshPLG_050E() { binMeshHeaderFlags = Program.levelEditor.checkBoxTristrip.Checked ? BinMeshHeaderFlags.TriangleStrip : BinMeshHeaderFlags.TriangleList, numMeshes = binMeshList.Count(), totalIndexCount = TotalNumberOfTristripIndicies, binMeshList = binMeshList.ToArray() } } } }, worldExtension = new Extension_0003() }; for (int i = 0; i < data.MaterialList.Count; i++) { world.materialList.materialList[i] = new Material_0007() { materialStruct = new MaterialStruct_0001() { unusedFlags = 0, color = new RenderWareFile.Color() { R = 0xFF, G = 0xFF, B = 0xFF, A = 0xFF }, unusedInt2 = 0x2DF53E84, isTextured = 1, ambient = 1f, specular = 1f, diffuse = 1f }, texture = new Texture_0006() { textureStruct = new TextureStruct_0001() { filterMode = FilterMode.FILTERLINEAR, addressModeU = AddressMode.TEXTUREADDRESSWRAP, addressModeV = AddressMode.TEXTUREADDRESSWRAP, useMipLevels = 1 }, diffuseTextureName = new String_0002() { stringString = data.MaterialList[i] }, alphaTextureName = new String_0002() { stringString = "" }, textureExtension = new Extension_0003() }, materialExtension = new Extension_0003(), }; } return(new RWSection[] { world }); }
public static RWSection[] CreateBSPFromAssimp(string fileName, bool flipUVs) { PostProcessSteps pps = PostProcessSteps.Debone | PostProcessSteps.FindInstances | PostProcessSteps.FindInvalidData | PostProcessSteps.OptimizeGraph | PostProcessSteps.OptimizeMeshes | PostProcessSteps.Triangulate | PostProcessSteps.PreTransformVertices; Scene scene = new AssimpContext().ImportFile(fileName, pps); int vertexCount = scene.Meshes.Sum(m => m.VertexCount); int triangleCount = scene.Meshes.Sum(m => m.FaceCount); if (vertexCount > 65535 || triangleCount > 65536) { throw new ArgumentException("Model has too many vertices or triangles. Please import a simpler model."); } List <Vertex3> vertices = new List <Vertex3>(vertexCount); List <RenderWareFile.Color> vColors = new List <RenderWareFile.Color>(vertexCount); List <Vertex2> textCoords = new List <Vertex2>(vertexCount); List <RenderWareFile.Triangle> triangles = new List <RenderWareFile.Triangle>(triangleCount); int totalVertices = 0; foreach (var m in scene.Meshes) { foreach (Vector3D v in m.Vertices) { vertices.Add(new Vertex3(v.X, v.Y, v.Z)); } if (m.HasTextureCoords(0)) { foreach (Vector3D v in m.TextureCoordinateChannels[0]) { textCoords.Add(new Vertex2(v.X, flipUVs ? -v.Y : v.Y)); } } else { for (int i = 0; i < m.VertexCount; i++) { textCoords.Add(new Vertex2()); } } if (m.HasVertexColors(0)) { foreach (Color4D c in m.VertexColorChannels[0]) { vColors.Add(new RenderWareFile.Color( (byte)(c.R * 255), (byte)(c.G * 255), (byte)(c.B * 255), (byte)(c.A * 255))); } } else { for (int i = 0; i < m.VertexCount; i++) { vColors.Add(new RenderWareFile.Color(255, 255, 255, 255)); } } foreach (var t in m.Faces) { triangles.Add(new RenderWareFile.Triangle() { vertex1 = (ushort)(t.Indices[0] + totalVertices), vertex2 = (ushort)(t.Indices[1] + totalVertices), vertex3 = (ushort)(t.Indices[2] + totalVertices), materialIndex = (ushort)m.MaterialIndex }); } totalVertices += m.VertexCount; } if (vertices.Count != textCoords.Count || vertices.Count != vColors.Count) { throw new ArgumentException("Internal error: texture coordinate or vertex color count is different from vertex count."); } triangles = triangles.OrderBy(t => t.materialIndex).ToList(); Vertex3 Max = new Vertex3(vertices[0].X, vertices[0].Y, vertices[0].Z); Vertex3 Min = new Vertex3(vertices[0].X, vertices[0].Y, vertices[0].Z); foreach (Vertex3 i in vertices) { if (i.X > Max.X) { Max.X = i.X; } if (i.Y > Max.Y) { Max.Y = i.Y; } if (i.Z > Max.Z) { Max.Z = i.Z; } if (i.X < Min.X) { Min.X = i.X; } if (i.Y < Min.Y) { Min.Y = i.Y; } if (i.Z < Min.Z) { Min.Z = i.Z; } } BinMesh[] binMeshes = new BinMesh[scene.MaterialCount]; Material_0007[] materials = new Material_0007[scene.MaterialCount]; for (int i = 0; i < scene.MaterialCount; i++) { List <int> indices = new List <int>(triangles.Count); foreach (RenderWareFile.Triangle f in triangles) { if (f.materialIndex == i) { indices.Add(f.vertex1); indices.Add(f.vertex2); indices.Add(f.vertex3); } } binMeshes[i] = new BinMesh() { materialIndex = i, indexCount = indices.Count(), vertexIndices = indices.ToArray() }; materials[i] = new Material_0007() { materialStruct = new MaterialStruct_0001() { unusedFlags = 0, color = new RenderWareFile.Color( (byte)(scene.Materials[i].ColorDiffuse.R / 255), (byte)(scene.Materials[i].ColorDiffuse.G / 255), (byte)(scene.Materials[i].ColorDiffuse.B / 255), (byte)(scene.Materials[i].ColorDiffuse.A / 255)), unusedInt2 = 0x2DF53E84, isTextured = scene.Materials[i].HasTextureDiffuse ? 1 : 0, ambient = 1f, specular = 1f, diffuse = 1f }, texture = scene.Materials[i].HasTextureDiffuse ? new Texture_0006() { textureStruct = new TextureStruct_0001() // use wrap as default { filterMode = TextureFilterMode.FILTERLINEAR, addressModeU = scene.Materials[i].TextureDiffuse.WrapModeU == TextureWrapMode.Clamp ? TextureAddressMode.TEXTUREADDRESSCLAMP : scene.Materials[i].TextureDiffuse.WrapModeU == TextureWrapMode.Decal ? TextureAddressMode.TEXTUREADDRESSBORDER : scene.Materials[i].TextureDiffuse.WrapModeU == TextureWrapMode.Mirror ? TextureAddressMode.TEXTUREADDRESSMIRROR : TextureAddressMode.TEXTUREADDRESSWRAP, addressModeV = scene.Materials[i].TextureDiffuse.WrapModeV == TextureWrapMode.Clamp ? TextureAddressMode.TEXTUREADDRESSCLAMP : scene.Materials[i].TextureDiffuse.WrapModeV == TextureWrapMode.Decal ? TextureAddressMode.TEXTUREADDRESSBORDER : scene.Materials[i].TextureDiffuse.WrapModeV == TextureWrapMode.Mirror ? TextureAddressMode.TEXTUREADDRESSMIRROR : TextureAddressMode.TEXTUREADDRESSWRAP, useMipLevels = 1 }, diffuseTextureName = new String_0002() { stringString = Path.GetFileNameWithoutExtension(scene.Materials[i].TextureDiffuse.FilePath) }, alphaTextureName = new String_0002() { stringString = "" }, textureExtension = new Extension_0003() } : null, materialExtension = new Extension_0003(), }; } WorldFlags worldFlags = WorldFlags.HasOneSetOfTextCoords | WorldFlags.HasVertexColors | WorldFlags.WorldSectorsOverlap | (WorldFlags)0x00010000; World_000B world = new World_000B() { worldStruct = new WorldStruct_0001() { rootIsWorldSector = 1, inverseOrigin = new Vertex3(-0f, -0f, -0f), numTriangles = (uint)triangleCount, numVertices = (uint)vertexCount, numPlaneSectors = 0, numAtomicSectors = 1, colSectorSize = 0, worldFlags = worldFlags, boxMaximum = Max, boxMinimum = Min, }, materialList = new MaterialList_0008() { materialListStruct = new MaterialListStruct_0001() { materialCount = scene.MaterialCount }, materialList = materials }, firstWorldChunk = new AtomicSector_0009() { atomicSectorStruct = new AtomicSectorStruct_0001() { matListWindowBase = 0, numTriangles = triangleCount, numVertices = vertexCount, boxMaximum = Max, boxMinimum = Min, collSectorPresent = 0x2F50D984, unused = 0, vertexArray = vertices.ToArray(), colorArray = vColors.ToArray(), uvArray = textCoords.ToArray(), triangleArray = triangles.ToArray() }, atomicSectorExtension = new Extension_0003() { extensionSectionList = new List <RWSection>() { new BinMeshPLG_050E() { binMeshHeaderFlags = BinMeshHeaderFlags.TriangleList, numMeshes = binMeshes.Count(), totalIndexCount = binMeshes.Sum(b => b.indexCount), binMeshList = binMeshes } } } }, worldExtension = new Extension_0003() }; return(new RWSection[] { world }); }