Beispiel #1
0
        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,
Beispiel #2
0
        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 });
        }