示例#1
0
        private void LoadMap(string map, int centerx, int centery, int distance)
        {
            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this times 0.5 ends up being pixelspercoord on minimap
            float MapMidPoint = 32.0f / ChunkSize;

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);

            List <Vertex> verticelist = new List <Vertex>();
            List <Int32>  indicelist  = new List <Int32>();

            GL.Enable(EnableCap.Texture2D);

            worker.ReportProgress(0, "Loading ADT..");
            for (int x = centerx; x < centerx + distance; x++)
            {
                for (int y = centery; y < centery + distance; y++)
                {
                    string filename = "world\\maps\\" + map + "\\" + map + "_" + y + "_" + x + ".adt";

                    if (WoWFormatLib.Utils.CASC.FileExists(filename))
                    {
                        ADTReader reader = new ADTReader();
                        reader.LoadADT(filename);

                        Terrain adt = new Terrain();

                        adt.vertexBuffer = GL.GenBuffer();
                        adt.indiceBuffer = GL.GenBuffer();

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);

                        List <Material> materials = new List <Material>();

                        //Check if textures are already loaded or not, multiple ADTs close together probably use the same ones mostly
                        //for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++)
                        //{

                        /*
                         * Material material = new Material();
                         * material.filename = reader.adtfile.textures.filenames[ti];
                         * material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache);*/

                        /* MAPTEXTURE TEXTURE HACKFIX STUFF STARTS HERE */
                        Material material = new Material();
                        material.filename  = filename.Replace("maps", "maptextures").Replace(".adt", ".blp");
                        material.textureID = BLPLoader.LoadTexture(filename.Replace("maps", "maptextures").Replace(".adt", ".blp"), cache);
                        /* MAPTEXTURE TEXTURE HACKFIX STUFF STOPS HERE */

                        materials.Add(material);
                        //}


                        var initialChunkY = reader.adtfile.chunks[0].header.position.Y;
                        var initialChunkX = reader.adtfile.chunks[0].header.position.X;

                        List <RenderBatch> renderBatches = new List <RenderBatch>();

                        for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                        {
                            var chunk = reader.adtfile.chunks[c];

                            int off = verticelist.Count();

                            RenderBatch batch = new RenderBatch();

                            for (int i = 0, idx = 0; i < 17; i++)
                            {
                                for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                                {
                                    //var v = new Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, -(chunk.header.position.X - (i * UnitSize * 0.5f)));
                                    Vertex v = new Vertex();
                                    v.Normal = new Vector3(chunk.normals.normal_0[idx], chunk.normals.normal_1[idx], chunk.normals.normal_2[idx]);
                                    if (chunk.vertexShading.red != null && chunk.vertexShading.red[idx] != 127)
                                    {
                                        v.Color = new Vector3(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f);
                                        //v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                    }
                                    else
                                    {
                                        v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                    }

                                    // Commented out for maptexture hack
                                    //v.TexCoord = new Vector2(((float)j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, ((float)i * 0.5f) / 8f);

                                    v.Position = new Vector3(chunk.header.position.X - (i * UnitSize * 0.5f), chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z);

                                    if ((i % 2) != 0)
                                    {
                                        v.Position.Y -= 0.5f * UnitSize;
                                    }

                                    //Maptexture hackfix
                                    v.TexCoord = new Vector2(-(v.Position.Y - initialChunkX) / TileSize, -(v.Position.X - initialChunkY) / TileSize);

                                    verticelist.Add(v);
                                }
                            }

                            batch.firstFace = (uint)indicelist.Count();
                            for (int j = 9; j < 145; j++)
                            {
                                indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                                indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                                indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                                indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                                if ((j + 1) % (9 + 8) == 0)
                                {
                                    j += 9;
                                }
                            }
                            batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                            //if (!cache.materials.ContainsKey(reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower()))
                            //{
                            //    throw new Exception("MaterialCache does not have texture " + reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower());
                            //}

                            //Commented out for maptexture hackfix

                            /*
                             * var layermats = new List<uint>();
                             * var alphalayermats = new List<int>();
                             *
                             * for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                             * {
                             *  if(reader.adtfile.texChunks[c].alphaLayer != null){
                             *      alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer));
                             *  }
                             *  layermats.Add((uint)cache.materials[reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower()]);
                             * }
                             *
                             * batch.materialID = layermats.ToArray();
                             * batch.alphaMaterialID = alphalayermats.ToArray();
                             *
                             */
                            var layermats = new List <uint>();
                            layermats.Add((uint)material.textureID);
                            batch.materialID = layermats.ToArray();
                            renderBatches.Add(batch);
                        }

                        List <Doodad> doodads = new List <Doodad>();

                        for (int mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++)
                        {
                            Console.WriteLine("Loading model #" + mi);

                            var modelentry = reader.adtfile.objects.models.entries[mi];
                            var mmid       = reader.adtfile.objects.m2NameOffsets.offsets[modelentry.mmidEntry];

                            var modelfilename = "";
                            for (int mmi = 0; mmi < reader.adtfile.objects.m2Names.offsets.Count(); mmi++)
                            {
                                if (reader.adtfile.objects.m2Names.offsets[mmi] == mmid)
                                {
                                    modelfilename = reader.adtfile.objects.m2Names.filenames[mmi].ToLower();
                                }
                            }

                            var doodad = new Doodad();
                            doodad.filename = modelfilename;
                            doodad.position = new Vector3(-(modelentry.position.X - 17066), modelentry.position.Y, -(modelentry.position.Z - 17066));
                            doodad.rotation = new Vector3(modelentry.rotation.X, modelentry.rotation.Y, modelentry.rotation.Z);
                            doodad.scale    = modelentry.scale;
                            doodads.Add(doodad);

                            if (cache.doodadBatches.ContainsKey(modelfilename))
                            {
                                continue;
                            }

                            M2Loader.LoadM2(modelfilename, cache);
                        }

                        List <WorldModelBatch> worldModelBatches = new List <WorldModelBatch>();

                        // WMO loading goes here
                        for (int wmi = 0; wmi < reader.adtfile.objects.worldModels.entries.Count(); wmi++)
                        {
                            Console.WriteLine("Loading WMO #" + wmi);
                            string wmofilename = "";

                            var wmodelentry = reader.adtfile.objects.worldModels.entries[wmi];
                            var mwid        = reader.adtfile.objects.wmoNameOffsets.offsets[wmodelentry.mwidEntry];

                            for (int wmfi = 0; wmfi < reader.adtfile.objects.wmoNames.offsets.Count(); wmfi++)
                            {
                                if (reader.adtfile.objects.wmoNames.offsets[wmfi] == mwid)
                                {
                                    wmofilename = reader.adtfile.objects.wmoNames.filenames[wmfi].ToLower();
                                }
                            }

                            if (wmofilename.Length == 0)
                            {
                                throw new Exception("Unable to find filename for WMO!");
                            }

                            WorldModelBatch wmobatch = new WorldModelBatch();
                            wmobatch.position   = new Vector3(-(wmodelentry.position.X - 17066.666f), wmodelentry.position.Y, -(wmodelentry.position.Z - 17066.666f));
                            wmobatch.rotation   = new Vector3(wmodelentry.rotation.X, wmodelentry.rotation.Y, wmodelentry.rotation.Z);
                            wmobatch.worldModel = WMOLoader.LoadWMO(wmofilename, cache);
                            worldModelBatches.Add(wmobatch);
                        }

                        adt.renderBatches     = renderBatches.ToArray();
                        adt.doodads           = doodads.ToArray();
                        adt.worldModelBatches = worldModelBatches.ToArray();

                        int[]    indices  = indicelist.ToArray();
                        Vertex[] vertices = verticelist.ToArray();

                        Console.WriteLine("Vertices in array: " + vertices.Count()); //37120, correct

                        //indices = indicelist.ToArray();
                        Console.WriteLine("Indices in array: " + indices.Count()); //196608, should be 65.5k which is 196608 / 3. in triangles so its correct?

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * 11 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);
                        GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);

                        int verticeBufferSize = 0;
                        int indiceBufferSize  = 0;

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out verticeBufferSize);

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.indiceBuffer);
                        GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out indiceBufferSize);

                        Console.WriteLine("Vertices in buffer: " + verticeBufferSize / 11 / sizeof(float));
                        Console.WriteLine("Indices in buffer: " + indiceBufferSize / sizeof(int));

                        adts.Add(adt);
                    }
                }
            }
        }
示例#2
0
        private void LoadM2(string modelpath)
        {
            if (!WoWFormatLib.Utils.CASC.FileExists(modelpath))
            {
                throw new Exception("Model does not exist!");
            }

            worker.ReportProgress(0, "Loading model..");

            M2Reader reader = new M2Reader();

            string filename = modelpath;

            reader.LoadM2(filename);
            VBOid = new uint[2];
            GL.GenBuffers(2, VBOid);

            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[1]);

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);

            worker.ReportProgress(20, "Reading model indices..");

            List <uint> indicelist = new List <uint>();

            for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                indicelist.Add(reader.model.skins[0].triangles[i].pt1);
                indicelist.Add(reader.model.skins[0].triangles[i].pt2);
                indicelist.Add(reader.model.skins[0].triangles[i].pt3);
            }

            uint[] indices = indicelist.ToArray();

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[1]);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(uint)), indices, BufferUsageHint.StaticDraw);

            worker.ReportProgress(30, "Reading model vertices..");

            Vertex[] vertices = new Vertex[reader.model.vertices.Count()];

            for (int i = 0; i < reader.model.vertices.Count(); i++)
            {
                vertices[i].Position = new Vector3(reader.model.vertices[i].position.X, reader.model.vertices[i].position.Z, reader.model.vertices[i].position.Y * -1);
                vertices[i].Normal   = new Vector3(reader.model.vertices[i].normal.X, reader.model.vertices[i].normal.Z, reader.model.vertices[i].normal.Y);
                vertices[i].TexCoord = new Vector2(reader.model.vertices[i].textureCoordX, reader.model.vertices[i].textureCoordY);
            }
            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * 8 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

            GL.Enable(EnableCap.Texture2D);

            worker.ReportProgress(40, "Loading textures..");

            materials = new Material[reader.model.textures.Count()];
            for (int i = 0; i < reader.model.textures.Count(); i++)
            {
                Console.WriteLine("Loading texture " + i);
                string texturefilename = @"dungeons\textures\testing\color_13.blp";
                materials[i].flags = reader.model.textures[i].flags;
                Console.WriteLine("      Requires type " + reader.model.textures[i].type + " texture");
                switch (reader.model.textures[i].type)
                {
                case 0:
                    Console.WriteLine("      Texture given in file!");
                    texturefilename = reader.model.textures[i].filename;
                    break;

                case 1:
                    string[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)reader.model.textures[i].type, i);
                    if (csfilenames.Count() > 0)
                    {
                        texturefilename = csfilenames[0];
                    }
                    else
                    {
                        Console.WriteLine("      No type 1 texture found, falling back to placeholder texture");
                    }
                    break;

                case 2:
                    if (WoWFormatLib.Utils.CASC.FileExists(Path.ChangeExtension(modelpath, ".blp")))
                    {
                        Console.WriteLine("      BLP exists!");
                        texturefilename = Path.ChangeExtension(modelpath, ".blp");
                    }
                    else
                    {
                        Console.WriteLine("      Type 2 does not exist!");
                        //needs lookup?
                    }
                    break;

                case 11:
                    string[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)reader.model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Count(); ti++)
                    {
                        if (WoWFormatLib.Utils.CASC.FileExists(modelpath.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp")))
                        {
                            texturefilename = modelpath.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp");
                        }
                    }
                    break;

                default:
                    Console.WriteLine("      Falling back to placeholder texture");
                    break;
                }

                Console.WriteLine("      Eventual filename is " + texturefilename);
                materials[i].textureID = BLPLoader.LoadTexture(texturefilename, cache);
                materials[i].filename  = texturefilename;
            }

            worker.ReportProgress(60, "Loading renderbatches..");
            renderbatches = new RenderBatch[reader.model.skins[0].submeshes.Count()];
            for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (reader.model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!reader.model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }

                    Console.WriteLine("Loading submesh " + reader.model.skins[0].submeshes[i].submeshID + "(" + reader.model.skins[0].submeshes[i].unk2 + ")");
                }

                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            worker.ReportProgress(100, "Done.");

            gLoaded = true;
        }
示例#3
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++)
                {
                    var batch = group.mogp.renderBatches[i];
                    renderbatches[rb].firstFace = batch.firstFace;
                    renderbatches[rb].numFaces  = batch.numFaces;
                    if (batch.flags == 2)
                    {
                        renderbatches[rb].materialID = (uint)group.mogp.renderBatches[i].possibleBox2_3;
                    }
                    else
                    {
                        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;
        }
示例#4
0
        private void LoadMap(string map, int centerx, int centery, int distance)
        {
            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this times 0.5 ends up being pixelspercoord on minimap
            float MapMidPoint = 32.0f / ChunkSize;

            List <Vertex> verticelist = new List <Vertex>();
            List <Int32>  indicelist  = new List <Int32>();

            worker.ReportProgress(0, "Loading ADT..");
            for (int x = centerx; x < centerx + distance; x++)
            {
                for (int y = centery; y < centery + distance; y++)
                {
                    string filename = "world\\maps\\" + map + "\\" + map + "_" + x + "_" + y + ".adt";

                    if (!WoWFormatLib.Utils.CASC.FileExists(filename))
                    {
                        continue;
                    }
                    ADTReader reader = new ADTReader();
                    reader.LoadADT(filename);

                    Terrain adt = new Terrain();

                    List <Material> materials = new List <Material>();

                    for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++)
                    {
                        Material material = new Material();
                        material.filename  = reader.adtfile.textures.filenames[ti];
                        material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache);
                        materials.Add(material);
                    }

                    var initialChunkY = reader.adtfile.chunks[0].header.position.Y;
                    var initialChunkX = reader.adtfile.chunks[0].header.position.X;

                    List <RenderBatch> renderBatches = new List <RenderBatch>();

                    for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                    {
                        var chunk = reader.adtfile.chunks[c];

                        int off = verticelist.Count();

                        RenderBatch batch = new RenderBatch();

                        for (int i = 0, idx = 0; i < 17; i++)
                        {
                            for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                            {
                                Vertex v = new Vertex();
                                v.Normal = new Vector3(chunk.normals.normal_0[idx], chunk.normals.normal_1[idx], chunk.normals.normal_2[idx]);
                                if (chunk.vertexShading.red != null && chunk.vertexShading.red[idx] != 127)
                                {
                                    v.Color = new Vector3(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f);
                                }
                                else
                                {
                                    v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                }

                                v.TexCoord      = new Vector2(j + ((i % 2) != 0 ? 0.5f : 0.0f), i * 0.5f);
                                v.TexCoordAlpha = new Vector2(j / 8.0f + ((i % 2) != 0 ? (0.5f / 8.0f) : 0), i / 16.0f);

                                v.Position = new Vector3(chunk.header.position.X - (i * UnitSize * 0.5f), chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z);

                                if ((i % 2) != 0)
                                {
                                    v.Position.Y -= 0.5f * UnitSize;
                                }

                                verticelist.Add(v);
                            }
                        }

                        batch.firstFace = (uint)indicelist.Count();
                        for (int j = 9; j < 145; j++)
                        {
                            indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                            indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                            indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                            indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                            if ((j + 1) % (9 + 8) == 0)
                            {
                                j += 9;
                            }
                        }
                        batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                        if (reader.adtfile.texChunks[c].layers.Count() != 0)
                        {
                            if (!cache.materials.ContainsKey(reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower()))
                            {
                                throw new Exception("MaterialCache does not have texture " + reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower());
                            }

                            var layermats      = new List <uint>();
                            var alphalayermats = new List <int>();

                            for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                            {
                                if (reader.adtfile.texChunks[c].alphaLayer != null)
                                {
                                    alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer));
                                }
                                layermats.Add((uint)cache.materials[reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower()]);
                            }

                            batch.materialID      = layermats.ToArray();
                            batch.alphaMaterialID = alphalayermats.ToArray();
                        }


                        renderBatches.Add(batch);
                    }

                    List <Doodad> doodads = new List <Doodad>();

                    for (int mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++)
                    {
                        Console.WriteLine("Loading model #" + mi);

                        var modelentry = reader.adtfile.objects.models.entries[mi];
                        var mmid       = reader.adtfile.objects.m2NameOffsets.offsets[modelentry.mmidEntry];

                        var modelfilename = "";
                        for (int mmi = 0; mmi < reader.adtfile.objects.m2Names.offsets.Count(); mmi++)
                        {
                            if (reader.adtfile.objects.m2Names.offsets[mmi] == mmid)
                            {
                                modelfilename = reader.adtfile.objects.m2Names.filenames[mmi].ToLower();
                            }
                        }

                        var doodad = new Doodad();
                        doodad.filename = modelfilename;
                        doodad.position = new Vector3(-(modelentry.position.X - 17066), modelentry.position.Y, -(modelentry.position.Z - 17066));
                        doodad.rotation = new Vector3(modelentry.rotation.X, modelentry.rotation.Y, modelentry.rotation.Z);
                        doodad.scale    = modelentry.scale;
                        doodads.Add(doodad);

                        if (!cache.doodadBatches.ContainsKey(modelfilename))
                        {
                            M2Loader.LoadM2(modelfilename, cache, modelShader);
                        }
                    }

                    List <WorldModelBatch> worldModelBatches = new List <WorldModelBatch>();

                    for (int wmi = 0; wmi < reader.adtfile.objects.worldModels.entries.Count(); wmi++)
                    {
                        string wmofilename = "";

                        var wmodelentry = reader.adtfile.objects.worldModels.entries[wmi];
                        var mwid        = reader.adtfile.objects.wmoNameOffsets.offsets[wmodelentry.mwidEntry];

                        for (int wmfi = 0; wmfi < reader.adtfile.objects.wmoNames.offsets.Count(); wmfi++)
                        {
                            if (reader.adtfile.objects.wmoNames.offsets[wmfi] == mwid)
                            {
                                wmofilename = reader.adtfile.objects.wmoNames.filenames[wmfi].ToLower();
                            }
                        }

                        if (wmofilename.Length == 0)
                        {
                            throw new Exception("Unable to find filename for WMO!");
                        }

                        Console.WriteLine("Loading WMO #" + wmi + " (" + wmofilename + ")");

                        WorldModelBatch wmobatch = new WorldModelBatch();
                        wmobatch.position   = new Vector3(-(wmodelentry.position.X - 17066.666f), wmodelentry.position.Y, -(wmodelentry.position.Z - 17066.666f));
                        wmobatch.rotation   = new Vector3(wmodelentry.rotation.X, wmodelentry.rotation.Y, wmodelentry.rotation.Z);
                        wmobatch.worldModel = WMOLoader.LoadWMO(wmofilename, cache, modelShader);
                        worldModelBatches.Add(wmobatch);
                    }

                    GL.BindVertexArray(0);
                    //GL.UseProgram(terrainShader);

                    adt.renderBatches     = renderBatches.ToArray();
                    adt.doodads           = doodads.ToArray();
                    adt.worldModelBatches = worldModelBatches.ToArray();

                    adt.vao = GL.GenVertexArray();
                    Console.WriteLine("Generated ADT VAO " + adt.vao);
                    GL.BindVertexArray(adt.vao);

                    adt.vertexBuffer = GL.GenBuffer();
                    adt.indiceBuffer = GL.GenBuffer();

                    GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);

                    adt.renderBatches = renderBatches.ToArray();

                    int[]    indices  = indicelist.ToArray();
                    Vertex[] vertices = verticelist.ToArray();

                    Console.WriteLine("Vertices in array: " + vertices.Count()); //37120, correct
                    Console.WriteLine("Indices in array: " + indices.Count());   //196608, should be 65.5k which is 196608 / 3. in triangles so its correct?

                    GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * 13 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);
                    GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);

                    int verticeBufferSize = 0;
                    int indiceBufferSize  = 0;

                    GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                    GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out verticeBufferSize);

                    GL.BindBuffer(BufferTarget.ArrayBuffer, adt.indiceBuffer);
                    GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out indiceBufferSize);

                    Console.WriteLine("Vertices in buffer: " + verticeBufferSize / 13 / sizeof(float));
                    Console.WriteLine("Indices in buffer: " + indiceBufferSize / sizeof(int));

                    GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);

                    // var normalLoc = GL.GetAttribLocation(shaderProgram, "vNormal");
                    // GL.VertexAttribPointer(normalLoc, 3, VertexAttribPointerType.Float, false, 11 * sizeof(float), 0);

                    var colorLoc = GL.GetAttribLocation(terrainShader, "vColor");
                    if (colorLoc != -1)
                    {
                        GL.VertexAttribPointer(colorLoc, 3, VertexAttribPointerType.Float, false, 13 * sizeof(float), 3 * sizeof(float));
                    }

                    var texCoordLoc = GL.GetAttribLocation(terrainShader, "vTexCoord");
                    GL.EnableVertexAttribArray(texCoordLoc);
                    GL.VertexAttribPointer(texCoordLoc, 2, VertexAttribPointerType.Float, false, 13 * sizeof(float), 6 * sizeof(float));

                    var texCoordAlphaLoc = GL.GetAttribLocation(terrainShader, "vTexCoordAlpha");
                    GL.EnableVertexAttribArray(texCoordAlphaLoc);
                    GL.VertexAttribPointer(texCoordAlphaLoc, 2, VertexAttribPointerType.Float, false, 13 * sizeof(float), 8 * sizeof(float));

                    var posLoc = GL.GetAttribLocation(terrainShader, "vPosition");
                    GL.EnableVertexAttribArray(posLoc);
                    GL.VertexAttribPointer(posLoc, 3, VertexAttribPointerType.Float, false, 13 * sizeof(float), 10 * sizeof(float));

                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);

                    GL.BindVertexArray(0);

                    adts.Add(adt);
                }
            }
        }