예제 #1
0
        public static void exportWMO(string file, BackgroundWorker exportworker = null)
        {
            if(exportworker == null)
            {
                exportworker = new BackgroundWorker();
            }

            Console.WriteLine("Loading WMO file..");

            exportworker.ReportProgress(5, "Reading WMO..");

            var outdir = ConfigurationManager.AppSettings["outdir"];
            WMOReader reader = new WMOReader();
            reader.LoadWMO(file);

            // TODO: Support doodads!
            for (int i = 0; i < reader.wmofile.doodadNames.Count(); i++)
            {
                //Console.WriteLine(reader.wmofile.doodadNames[i].filename);
                //reader.wmofile.doodadDefinitions[i].
                //reader.wmofile.doodadDefinitions[i].
            }

            exportworker.ReportProgress(30, "Reading WMO..");

            uint totalVertices = 0;

            var groups = new Structs.WMOGroup[reader.wmofile.group.Count()];

            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                if (reader.wmofile.group[g].mogp.vertices == null) { continue; }
                for (int i = 0; i < reader.wmofile.groupNames.Count(); i++)
                {
                    if (reader.wmofile.group[g].mogp.nameOffset == reader.wmofile.groupNames[i].offset)
                    {
                        groups[g].name = reader.wmofile.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal") { continue; }

                groups[g].verticeOffset = totalVertices;
                groups[g].vertices = new Structs.Vertex[reader.wmofile.group[g].mogp.vertices.Count()];

                for (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    groups[g].vertices[i].Position = new Vector3(reader.wmofile.group[g].mogp.vertices[i].vector.X * -1, reader.wmofile.group[g].mogp.vertices[i].vector.Z, reader.wmofile.group[g].mogp.vertices[i].vector.Y);
                    groups[g].vertices[i].Normal = new Vector3(reader.wmofile.group[g].mogp.normals[i].normal.X, reader.wmofile.group[g].mogp.normals[i].normal.Z, reader.wmofile.group[g].mogp.normals[i].normal.Y);
                    groups[g].vertices[i].TexCoord = new Vector2(reader.wmofile.group[g].mogp.textureCoords[0][i].X, reader.wmofile.group[g].mogp.textureCoords[0][i].Y);
                    totalVertices++;
                }

                var indicelist = new List<uint>();

                for (int i = 0; i < reader.wmofile.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(reader.wmofile.group[g].mogp.indices[i].indice);
                }

                groups[g].indices = indicelist.ToArray();
            }

            exportworker.ReportProgress(55, "Exporting textures..");

            // Create output directory
            if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file))))
            {
                Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file)));
            }

            var mtlsb = new StringBuilder();
            var textureID = 0;

            var materials = new Structs.Material[reader.wmofile.materials.Count()];
            for (int i = 0; i < reader.wmofile.materials.Count(); i++)
            {
                for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++)
                {
                    if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1)
                    {
                        //materials[i].textureID = BLPLoader.LoadTexture(reader.wmofile.textures[ti].filename, cache);
                        materials[i].textureID = textureID + i;
                        materials[i].filename = Path.GetFileNameWithoutExtension(reader.wmofile.textures[ti].filename);
                        if (reader.wmofile.materials[i].blendMode == 0)
                        {
                            materials[i].transparent = false;
                        }
                        else
                        {
                            materials[i].transparent = true;
                        }

                        var blpreader = new BLPReader();

                        blpreader.LoadBLP(reader.wmofile.textures[ti].filename);

                        try
                        {
                            blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png"));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }

                        textureID++;
                    }
                }
            }

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 2\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");
                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }
            }

            File.WriteAllText(Path.Combine(outdir, file.Replace(".wmo", ".mtl")), mtlsb.ToString());

            exportworker.ReportProgress(75, "Exporting model..");

            int numRenderbatches = 0;
            //Get total amount of render batches
            for (int i = 0; i < reader.wmofile.group.Count(); i++)
            {
                if (reader.wmofile.group[i].mogp.renderBatches == null) { continue; }
                numRenderbatches = numRenderbatches + reader.wmofile.group[i].mogp.renderBatches.Count();
            }


            int rb = 0;
            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                var group = reader.wmofile.group[g];
                if (group.mogp.renderBatches == null) { continue; }
                for (int i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    var batch = group.mogp.renderBatches[i];

                    groups[g].renderBatches[rb].firstFace = batch.firstFace;
                    groups[g].renderBatches[rb].numFaces = batch.numFaces;

                    if (batch.flags == 2)
                    {
                        groups[g].renderBatches[rb].materialID = (uint)batch.possibleBox2_3;
                    }
                    else
                    {
                        groups[g].renderBatches[rb].materialID = batch.materialID;
                    }
                    groups[g].renderBatches[rb].blendType = reader.wmofile.materials[batch.materialID].blendMode;
                    groups[g].renderBatches[rb].groupID = (uint)g;
                    rb++;
                }
            }

            exportworker.ReportProgress(95, "Writing files..");

            var objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".wmo", ".obj")));
            objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file);
            objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file) + ".mtl");

            foreach (var group in groups)
            {
                if (group.vertices == null) { continue; }
                objsw.WriteLine("g " + group.name);

                foreach (var vertex in group.vertices)
                {
                    objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                    objsw.WriteLine("vt " + vertex.TexCoord.X + " " + -vertex.TexCoord.Y);
                    objsw.WriteLine("vn " + vertex.Normal.X + " " + vertex.Normal.Y + " " + vertex.Normal.Z);
                }

                var indices = group.indices;

                foreach (var renderbatch in group.renderBatches)
                {
                    var i = renderbatch.firstFace;
                    if (renderbatch.numFaces > 0)
                    {
                        objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                        objsw.WriteLine("s 1");
                        while (i < (renderbatch.firstFace + renderbatch.numFaces))
                        {
                            objsw.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1));
                            i = i + 3;
                        }
                    }
                }
            }
            objsw.Close();
            Console.WriteLine("Done loading WMO file!");
        }
예제 #2
0
        private void LoadWMO(string modelpath)
        {
            Console.WriteLine("Loading WMO file..");
            WMOReader reader = new WMOReader();
            string filename = modelpath;
            //Load WMO
            reader.LoadWMO(filename);

            //Enable Vertex Arrays
            GL.EnableClientState(ArrayCap.VertexArray);
            //Enable Normal Arrays
            GL.EnableClientState(ArrayCap.NormalArray);
            //Enable TexCoord arrays
            GL.EnableClientState(ArrayCap.TextureCoordArray);

            //Set up buffer IDs
            VBOid = new uint[(reader.wmofile.group.Count() * 2) + 2];
            GL.GenBuffers((reader.wmofile.group.Count() * 2) + 2, VBOid);

            for (int i = 0; i < reader.wmofile.doodadNames.Count(); i++)
            {
                //Console.WriteLine(reader.wmofile.doodadNames[i].filename);
            }

            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                if (reader.wmofile.group[g].mogp.vertices == null) { continue; }
                //Switch to Vertex buffer
                GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[g * 2]);

                Vertex[] vertices = new Vertex[reader.wmofile.group[g].mogp.vertices.Count()];

                for (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    vertices[i].Position = new Vector3(reader.wmofile.group[g].mogp.vertices[i].vector.X, reader.wmofile.group[g].mogp.vertices[i].vector.Z, reader.wmofile.group[g].mogp.vertices[i].vector.Y);
                    vertices[i].Normal = new Vector3(reader.wmofile.group[g].mogp.normals[i].normal.X, reader.wmofile.group[g].mogp.normals[i].normal.Z, reader.wmofile.group[g].mogp.normals[i].normal.Y);
                    vertices[i].TexCoord = new Vector2(reader.wmofile.group[g].mogp.textureCoords[0][i].X, reader.wmofile.group[g].mogp.textureCoords[0][i].Y);
                }

                //Push to buffer
                GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * 8 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                //Switch to Index buffer
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[(g * 2) + 1]);

                List<uint> indicelist = new List<uint>();
                for (int i = 0; i < reader.wmofile.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(reader.wmofile.group[g].mogp.indices[i].indice);
                }

                uint[] indices = indicelist.ToArray();

                //Push to buffer
                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(uint)), indices, BufferUsageHint.StaticDraw);
            }

            GL.Enable(EnableCap.Texture2D);

            materials = new Material[reader.wmofile.materials.Count()];
            for (int i = 0; i < reader.wmofile.materials.Count(); i++)
            {
                for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++)
                {

                    if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1)
                    {
                        materials[i].textureID = BLPLoader.LoadTexture(reader.wmofile.textures[ti].filename, cache);
                        materials[i].filename = reader.wmofile.textures[ti].filename;
                    }
                }
            }

            int numRenderbatches = 0;
            //Get total amount of render batches
            for (int i = 0; i < reader.wmofile.group.Count(); i++)
            {
                if (reader.wmofile.group[i].mogp.renderBatches == null) { continue; }
                numRenderbatches = numRenderbatches + reader.wmofile.group[i].mogp.renderBatches.Count();
            }

            renderbatches = new RenderBatch[numRenderbatches];

            int rb = 0;
            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                var group = reader.wmofile.group[g];
                if (group.mogp.renderBatches == null) { continue; }
                for (int i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    renderbatches[rb].firstFace = group.mogp.renderBatches[i].firstFace;
                    renderbatches[rb].numFaces = group.mogp.renderBatches[i].numFaces;
                    renderbatches[rb].materialID = group.mogp.renderBatches[i].materialID;
                    renderbatches[rb].blendType = reader.wmofile.materials[group.mogp.renderBatches[i].materialID].blendMode;
                    renderbatches[rb].groupID = (uint)g;
                    rb++;
                }
            }

            Console.WriteLine("  " + reader.wmofile.group.Count() + " skins");
            Console.WriteLine("  " + materials.Count() + " materials");
            Console.WriteLine("  " + renderbatches.Count() + " renderbatches");
            Console.WriteLine("  " + reader.wmofile.group[0].mogp.vertices.Count() + " vertices");
            Console.WriteLine("Done loading WMO file!");

            gLoaded = true;
            isWMO = true;
        }
예제 #3
0
파일: WMO.cs 프로젝트: Ser0ja/WoWFormatTest
        public void Compile(string wmoname)
        {
            WMOReader wmoreader = new WMOReader();
            wmoreader.LoadWMO(wmoname);

            WoWFormatLib.Structs.WMO.WMO wmo = wmoreader.wmofile;

            Console.WriteLine(wmoname);

            if (wmo.group.Count() == 0)
            {
                Console.WriteLine("WMO " + wmoname + " has no groups! Skipping..");
                return;
            }

            int wmo_minx = 999999999;
            int wmo_maxx = 0;
            int wmo_miny = 999999999;
            int wmo_maxy = 0;
            int numtiles = 0;
            //Determine min max offset
            for (int i = 0; i < wmo.group.Count(); i++)
            {
                string groupid = i.ToString().PadLeft(3, '0');

                double drawx1 = wmo.groupInfo[i].boundingBox1.X * 2;
                double drawy1 = wmo.groupInfo[i].boundingBox1.Y * 2;

                double drawx2 = wmo.groupInfo[i].boundingBox2.X * 2;
                double drawy2 = wmo.groupInfo[i].boundingBox2.Y * 2;

                if (drawx1 < wmo_minx) { wmo_minx = (int)drawx1; }
                if (drawx1 > wmo_maxx) { wmo_maxx = (int)drawx1; }

                if (drawy1 < wmo_miny) { wmo_miny = (int)drawy1; }
                if (drawy1 > wmo_maxy) { wmo_maxy = (int)drawy1; }

                if (drawx2 < wmo_minx) { wmo_minx = (int)drawx2; }
                if (drawx2 > wmo_maxx) { wmo_maxx = (int)drawx2; }

                if (drawy2 < wmo_miny) { wmo_minx = (int)drawy2; }
                if (drawy2 > wmo_maxy) { wmo_maxx = (int)drawy2; }
            }

            int wmoresx = 0;
            int wmoresy = 0;
            //Determine image height
            for (int i = 0; i < wmo.group.Count(); i++)
            {
                string groupid = i.ToString().PadLeft(3, '0');

                double drawx1 = wmo.groupInfo[i].boundingBox1.X * 2;
                double drawy1 = wmo.groupInfo[i].boundingBox1.Y * 2;

                double drawx2 = wmo.groupInfo[i].boundingBox2.X * 2;
                double drawy2 = wmo.groupInfo[i].boundingBox2.Y * 2;

                int greenx1 = (int)drawx1 + Math.Abs(wmo_minx);
                int greeny1 = (int)drawy1 + Math.Abs(wmo_miny);

                int greenx2 = (int)drawx2 + Math.Abs(wmo_minx);
                int greeny2 = (int)drawy2 + Math.Abs(wmo_miny);

                if (greenx2 > wmoresx) { wmoresx = greenx2; }
                if (greeny2 > wmoresy) { wmoresy = greeny2; }
            }

            if (wmoresx == 0 || wmoresy == 0)
            {
                Console.WriteLine("WMO " + wmoname + " has invalid calculated resolution (" + wmoresx + "x" + wmoresy + ")");
                return;
            }

            Bitmap wmobmp = new Bitmap(wmoresx, wmoresy);
            Graphics wmog = Graphics.FromImage(wmobmp);

            /*
            string wmodirname = Path.GetDirectoryName(wmoname.Replace("World" + Path.DirectorySeparatorChar, String.Empty));

            if (!Directory.Exists(Path.Combine(basedir, "World", "Minimaps", wmodirname + Path.DirectorySeparatorChar)))
            {
                Console.WriteLine("WMO has no minimaps directory (" + Path.Combine(basedir, "World", "Minimaps", wmodirname + Path.DirectorySeparatorChar) + "). Skipping..");
                return;
            }
            */

            for (int i = 0; i < wmo.group.Count(); i++)
            {
                string groupid = i.ToString().PadLeft(3, '0');

                double drawx1 = wmo.groupInfo[i].boundingBox1.X * 2;
                double drawy1 = wmo.groupInfo[i].boundingBox1.Y * 2;

                double drawx2 = wmo.groupInfo[i].boundingBox2.X * 2;
                double drawy2 = wmo.groupInfo[i].boundingBox2.Y * 2;

                int greenx1 = (int)drawx1 + Math.Abs(wmo_minx);
                int greeny1 = (int)drawy1 + Math.Abs(wmo_miny);

                int greenx2 = (int)drawx2 + Math.Abs(wmo_minx);
                int greeny2 = (int)drawy2 + Math.Abs(wmo_miny);

                /*
                //Check if minimaps wmo dir for this even exists

                string wmogroupfilename = Path.GetFileNameWithoutExtension(wmoname) + "_" + groupid;
                string[] filePaths = Directory.GetFiles(Path.Combine(basedir, "World", "Minimaps", wmodirname + Path.DirectorySeparatorChar), wmogroupfilename + "*");

                //check if there are any minimap blps for this group
                if (filePaths.Count() == 0)
                {
                    Console.WriteLine("WMO has no blps in minimap directory. Skipping..");
                    continue;
                }
                */
                Bitmap minimapbmp = CompileGroup(wmoname, groupid);

                if (minimapbmp.Width > 1)
                {
                    wmog.DrawImage(minimapbmp, greenx1, (wmoresy - (greeny1 + (greeny2 - greeny1)) + (greeny2 - greeny1)), new Rectangle(0, minimapbmp.Height, (greenx2 - greenx1), -(greeny2 - greeny1)), GraphicsUnit.Pixel);
                }
                numtiles++;
                minimapbmp.Dispose();
            }

            wmog.Dispose();

            if (numtiles > 0) //check if it even compiled anything
            {
                Directory.CreateDirectory("done" + Path.DirectorySeparatorChar + "WMO" + Path.DirectorySeparatorChar + Path.GetDirectoryName(wmoname));
                wmobmp.Save("done" + Path.DirectorySeparatorChar + "WMO" + Path.DirectorySeparatorChar + Path.Combine(wmoname) + ".png");
            }
            else
            {
                Console.WriteLine("WMO has no minimaps. Skipping..");
            }
        }
예제 #4
0
        public void LoadWMO()
        {
            WMOReader reader = new WMOReader(basedir);
            reader.LoadWMO(modelPath);

            WMOMaterial[] materials = new WMOMaterial[reader.wmofile.materials.Count()];
            for (int i = 0; i < reader.wmofile.materials.Count(); i++)
            {
                for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++)
                {
                    if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1)
                    {
                        Texture2D texture;
                        var blp = new BLPReader(basedir);
                        blp.LoadBLP(reader.wmofile.textures[ti].filename);
                        if (blp.bmp == null)
                        {
                            texture = Texture2D.FromFile<Texture2D>(device, "missingtexture.jpg");
                        }
                        else
                        {
                            MemoryStream s = new MemoryStream();
                            blp.bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png);
                            s.Seek(0, SeekOrigin.Begin);
                            texture = Texture2D.FromMemory<Texture2D>(device, s.ToArray());
                            s.Dispose();
                        }
                        materials[i].materialID = (uint)i;
                        materials[i].filename = reader.wmofile.textures[ti].filename;
                        materials[i].texture = texture;
                    }
                }
            }

            WoWWMOGroup[] groups = new WoWWMOGroup[reader.wmofile.header.nGroups];

            for (int i = 0; i < reader.wmofile.header.nGroups; i++)
            {
                groups[i] = LoadGroupWMO(reader.wmofile.group[i]);
            }

            wmo.materials = materials;
            wmo.groups = groups;
        }
예제 #5
0
        public static TerrainWindow.WorldModel LoadWMO(string filename, CacheStorage cache)
        {
            if (cache.worldModelBatches.ContainsKey(filename))
            {
                return cache.worldModelBatches[filename];
            }

            WoWFormatLib.Structs.WMO.WMO wmo = new WoWFormatLib.Structs.WMO.WMO();

            if (cache.worldModels.ContainsKey(filename))
            {
                wmo = cache.worldModels[filename];
            }
            else
            {
                //Load WMO from file
                if (WoWFormatLib.Utils.CASC.FileExists(filename))
                {
                    var wmoreader = new WMOReader();
                    wmoreader.LoadWMO(filename);
                    cache.worldModels.Add(filename, wmoreader.wmofile);
                    wmo = wmoreader.wmofile;
                }
                else
                {
                    throw new Exception("WMO " + filename + " does not exist!");
                }
            }

            var wmobatch = new TerrainWindow.WorldModel();

            wmobatch.groupBatches = new TerrainWindow.WorldModelGroupBatches[wmo.group.Count()];

            string[] groupNames = new string[wmo.group.Count()];

            for (int g = 0; g < wmo.group.Count(); g++)
            {
                if (wmo.group[g].mogp.vertices == null) { continue; }

                wmobatch.groupBatches[g].vertexBuffer = GL.GenBuffer();
                wmobatch.groupBatches[g].indiceBuffer = GL.GenBuffer();

                GL.BindBuffer(BufferTarget.ArrayBuffer, wmobatch.groupBatches[g].vertexBuffer);

                TerrainWindow.M2Vertex[] wmovertices = new TerrainWindow.M2Vertex[wmo.group[g].mogp.vertices.Count()];

                for (int i = 0; i < wmo.groupNames.Count(); i++)
                {
                    if (wmo.group[g].mogp.nameOffset == wmo.groupNames[i].offset)
                    {
                        groupNames[g] = wmo.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groupNames[g] == "antiportal") { continue; }

                for (int i = 0; i < wmo.group[g].mogp.vertices.Count(); i++)
                {
                    wmovertices[i].Position = new Vector3(wmo.group[g].mogp.vertices[i].vector.X, wmo.group[g].mogp.vertices[i].vector.Y, wmo.group[g].mogp.vertices[i].vector.Z);
                    wmovertices[i].Normal = new Vector3(wmo.group[g].mogp.normals[i].normal.X, wmo.group[g].mogp.normals[i].normal.Y, wmo.group[g].mogp.normals[i].normal.Z);
                    if (wmo.group[g].mogp.textureCoords[0] == null)
                    {
                        wmovertices[i].TexCoord = new Vector2(0.0f, 0.0f);
                    }
                    else
                    {
                        wmovertices[i].TexCoord = new Vector2(wmo.group[g].mogp.textureCoords[0][i].X, wmo.group[g].mogp.textureCoords[0][i].Y);
                    }
                }

                //Push to buffer
                GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(wmovertices.Length * 8 * sizeof(float)), wmovertices, BufferUsageHint.StaticDraw);

                //Switch to Index buffer
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, wmobatch.groupBatches[g].indiceBuffer);

                List<uint> wmoindicelist = new List<uint>();
                for (int i = 0; i < wmo.group[g].mogp.indices.Count(); i++)
                {
                    wmoindicelist.Add(wmo.group[g].mogp.indices[i].indice);
                }

                wmobatch.groupBatches[g].indices = wmoindicelist.ToArray();

                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(wmobatch.groupBatches[g].indices.Length * sizeof(uint)), wmobatch.groupBatches[g].indices, BufferUsageHint.StaticDraw);
            }

            GL.Enable(EnableCap.Texture2D);

            wmobatch.mats = new TerrainWindow.Material[wmo.materials.Count()];
            for (int i = 0; i < wmo.materials.Count(); i++)
            {
                for (int ti = 0; ti < wmo.textures.Count(); ti++)
                {

                    if (wmo.textures[ti].startOffset == wmo.materials[i].texture1)
                    {
                        wmobatch.mats[i].texture1 = wmo.materials[i].texture1;
                        wmobatch.mats[i].textureID = BLPLoader.LoadTexture(wmo.textures[ti].filename, cache);
                        wmobatch.mats[i].filename = wmo.textures[ti].filename;
                    }
                }
            }

            wmobatch.doodads = new TerrainWindow.WMODoodad[wmo.doodadDefinitions.Count()];

            for(int i = 0; i < wmo.doodadDefinitions.Count(); i++)
            {
                for(int j = 0; j < wmo.doodadNames.Count(); j++)
                {
                    if (wmo.doodadDefinitions[i].offset == wmo.doodadNames[j].startOffset)
                    {
                        wmobatch.doodads[i].filename = wmo.doodadNames[j].filename;
                        M2Loader.LoadM2(wmobatch.doodads[i].filename, cache);
                    }
                }
                wmobatch.doodads[i].flags = wmo.doodadDefinitions[i].flags;
                wmobatch.doodads[i].position = new Vector3(wmo.doodadDefinitions[i].position.X, wmo.doodadDefinitions[i].position.Y, wmo.doodadDefinitions[i].position.Z);
                wmobatch.doodads[i].rotation = new Quaternion(wmo.doodadDefinitions[i].rotation.X, wmo.doodadDefinitions[i].rotation.Y, wmo.doodadDefinitions[i].rotation.Z, wmo.doodadDefinitions[i].rotation.W);
                wmobatch.doodads[i].scale = wmo.doodadDefinitions[i].scale;
                wmobatch.doodads[i].color = new Vector4(wmo.doodadDefinitions[i].color[0], wmo.doodadDefinitions[i].color[1], wmo.doodadDefinitions[i].color[2], wmo.doodadDefinitions[i].color[3]);
            }

            int numRenderbatches = 0;
            //Get total amount of render batches
            for (int i = 0; i < wmo.group.Count(); i++)
            {
                if (wmo.group[i].mogp.renderBatches == null) { continue; }
                numRenderbatches = numRenderbatches + wmo.group[i].mogp.renderBatches.Count();
            }

            wmobatch.wmoRenderBatch = new TerrainWindow.RenderBatch[numRenderbatches];

            int rb = 0;
            for (int g = 0; g < wmo.group.Count(); g++)
            {
                var group = wmo.group[g];
                if (group.mogp.renderBatches == null) { continue; }
                for (int i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    wmobatch.wmoRenderBatch[rb].firstFace = group.mogp.renderBatches[i].firstFace;
                    wmobatch.wmoRenderBatch[rb].numFaces = group.mogp.renderBatches[i].numFaces;
                    uint matID = 0;

                    if (group.mogp.renderBatches[i].flags == 2)
                    {
                        matID = (uint) group.mogp.renderBatches[i].possibleBox2_3;
                    }
                    else
                    {
                        matID = group.mogp.renderBatches[i].materialID;
                    }

                    for (int ti = 0; ti < wmobatch.mats.Count(); ti++)
                    {
                        if (wmo.materials[matID].texture1 == wmobatch.mats[ti].texture1)
                        {
                            wmobatch.wmoRenderBatch[rb].materialID = new uint[] { (uint)wmobatch.mats[ti].textureID };
                        }
                    }

                    wmobatch.wmoRenderBatch[rb].blendType = wmo.materials[group.mogp.renderBatches[i].materialID].blendMode;
                    wmobatch.wmoRenderBatch[rb].groupID = (uint)g;
                    rb++;
                }
            }
            cache.worldModelBatches.Add(filename, wmobatch);

            return wmobatch;
        }