Beispiel #1
0
        public static void LoadM2(string filename, CacheStorage cache, int shaderProgram)
        {
            filename = filename.ToLower().Replace(".mdx", ".m2");
            filename = filename.ToLower().Replace(".mdl", ".m2");

            if (cache.doodadBatches.ContainsKey(filename))
            {
                return;
            }

            var model = new WoWFormatLib.Structs.M2.M2Model();

            if (cache.models.ContainsKey(filename))
            {
                model = cache.models[filename];
            }
            else
            {
                if (WoWFormatLib.Utils.CASC.FileExists(filename))
                {
                    var modelreader = new M2Reader();
                    modelreader.LoadM2(filename);
                    cache.models.Add(filename, modelreader.model);
                    model = modelreader.model;
                }
                else
                {
                    throw new Exception("Model " + filename + " does not exist!");
                }
            }

            if (model.boundingbox == null)
            {
                CASCLib.Logger.WriteLine("Error during loading file: {0}, bounding box is not defined", filename);
                return;
            }

            var ddBatch = new Renderer.Structs.DoodadBatch()
            {
                boundingBox = new Renderer.Structs.BoundingBox()
                {
                    min = new Vector3(model.boundingbox[0].X, model.boundingbox[0].Y, model.boundingbox[0].Z),
                    max = new Vector3(model.boundingbox[1].X, model.boundingbox[1].Y, model.boundingbox[1].Z)
                }
            };

            if (model.textures == null)
            {
                CASCLib.Logger.WriteLine("Error during loading file: {0}, model has no textures", filename);
                return;
            }

            if (model.skins == null)
            {
                CASCLib.Logger.WriteLine("Error during loading file: {0}, model has no skins", filename);
                return;
            }

            // Textures
            ddBatch.mats = new Renderer.Structs.Material[model.textures.Count()];

            for (var i = 0; i < model.textures.Count(); i++)
            {
                uint textureFileDataID = 372993;
                ddBatch.mats[i].flags = model.textures[i].flags;

                switch (model.textures[i].type)
                {
                case 0:
                    if (model.textureFileDataIDs != null && model.textureFileDataIDs.Length > 0 && model.textureFileDataIDs[i] != 0)
                    {
                        textureFileDataID = model.textureFileDataIDs[i];
                    }
                    else
                    {
                        textureFileDataID = WoWFormatLib.Utils.CASC.getFileDataIdByName(model.textures[i].filename);
                    }
                    break;

                case 1:
                case 2:
                case 11:
                default:
                    textureFileDataID = 372993;
                    break;
                }

                // Not set in TXID
                if (textureFileDataID == 0)
                {
                    textureFileDataID = 372993;
                }

                ddBatch.mats[i].textureID = BLPLoader.LoadTexture(textureFileDataID, cache);
                ddBatch.mats[i].filename  = textureFileDataID.ToString();
            }

            // Submeshes
            ddBatch.submeshes = new Renderer.Structs.Submesh[model.skins[0].submeshes.Count()];
            for (var i = 0; i < model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character"))
                {
                    if (model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                ddBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle;
                ddBatch.submeshes[i].numFaces  = model.skins[0].submeshes[i].nTriangles;
                for (var tu = 0; tu < model.skins[0].textureunit.Count(); tu++)
                {
                    if (model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        ddBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode;

                        uint textureFileDataID = 372993;

                        if (model.textureFileDataIDs != null && model.textureFileDataIDs.Length > 0 && model.textureFileDataIDs[model.texlookup[model.skins[0].textureunit[tu].texture].textureID] != 0)
                        {
                            textureFileDataID = model.textureFileDataIDs[model.texlookup[model.skins[0].textureunit[tu].texture].textureID];
                        }
                        else
                        {
                            textureFileDataID = WoWFormatLib.Utils.CASC.getFileDataIdByName(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename);
                        }

                        if (!cache.materials.ContainsKey(textureFileDataID))
                        {
                            throw new Exception("MaterialCache does not have texture " + textureFileDataID);
                        }

                        ddBatch.submeshes[i].material = (uint)cache.materials[textureFileDataID];
                    }
                }
            }

            ddBatch.vao = GL.GenVertexArray();
            GL.BindVertexArray(ddBatch.vao);

            // Vertices & indices
            ddBatch.vertexBuffer = GL.GenBuffer();
            ddBatch.indiceBuffer = GL.GenBuffer();

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

            var modelindicelist = new List <uint>();

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

            var modelindices = modelindicelist.ToArray();

            //Console.WriteLine(modelindicelist.Count() + " indices!");
            ddBatch.indices = modelindices;

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

            var modelvertices = new Renderer.Structs.M2Vertex[model.vertices.Count()];

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

            //Set pointers in buffer
            //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
            //GL.EnableVertexAttribArray(normalAttrib);
            //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 0);

            var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");

            GL.EnableVertexAttribArray(texCoordAttrib);
            GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 3);

            var posAttrib = GL.GetAttribLocation(shaderProgram, "position");

            GL.EnableVertexAttribArray(posAttrib);
            GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 5);
            cache.doodadBatches.Add(filename, ddBatch);
        }
        public static Terrain LoadADT(string filename, CacheStorage cache, int shaderProgram, bool loadModels = false)
        {
            var adt = new WoWFormatLib.Structs.ADT.ADT();

            var result = new Terrain();

            //Load ADT from file
            if (WoWFormatLib.Utils.CASC.FileExists(filename))
            {
                var adtreader = new ADTReader();
                adtreader.LoadADT(filename);
                adt = adtreader.adtfile;
            }
            else
            {
                throw new Exception("ADT " + filename + " does not exist!");
            }

            var TileSize    = 1600.0f / 3.0f;   //533.333
            var ChunkSize   = TileSize / 16.0f; //33.333
            var UnitSize    = ChunkSize / 8.0f; //4.166666
            var MapMidPoint = 32.0f / ChunkSize;

            var verticelist = new List <Vertex>();
            var indicelist  = new List <int>();

            result.vao = GL.GenVertexArray();
            GL.BindVertexArray(result.vao);

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

            var materials = new List <Material>();

            if (adt.textures.filenames == null)
            {
                for (var ti = 0; ti < adt.diffuseTextureFileDataIDs.Count(); ti++)
                {
                    var material = new Material();
                    material.filename  = adt.diffuseTextureFileDataIDs[ti].ToString();
                    material.textureID = BLPLoader.LoadTexture(adt.diffuseTextureFileDataIDs[ti], cache);

                    if (adt.texParams != null && adt.texParams.Count() >= ti)
                    {
                        material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4);
                        if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0)
                        {
                            material.heightScale  = adt.texParams[ti].height;
                            material.heightOffset = adt.texParams[ti].offset;

                            if (!WoWFormatLib.Utils.CASC.FileExists(adt.heightTextureFileDataIDs[ti]))
                            {
                                Console.WriteLine("Height texture: " + adt.heightTextureFileDataIDs[ti] + " does not exist! Falling back to original texture (hack)..");
                                material.heightTexture = BLPLoader.LoadTexture(adt.diffuseTextureFileDataIDs[ti], cache);
                            }
                            else
                            {
                                material.heightTexture = BLPLoader.LoadTexture(adt.heightTextureFileDataIDs[ti], cache);
                            }
                        }
                        else
                        {
                            material.heightScale  = 0.0f;
                            material.heightOffset = 1.0f;
                        }
                    }
                    else
                    {
                        material.heightScale  = 0.0f;
                        material.heightOffset = 1.0f;
                        material.scale        = 1.0f;
                    }
                    materials.Add(material);
                }
            }
            else
            {
                for (var ti = 0; ti < adt.textures.filenames.Count(); ti++)
                {
                    var material = new Material();
                    material.filename  = adt.textures.filenames[ti];
                    material.textureID = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);

                    if (adt.texParams != null && adt.texParams.Count() >= ti)
                    {
                        material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4);
                        if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0)
                        {
                            material.heightScale  = adt.texParams[ti].height;
                            material.heightOffset = adt.texParams[ti].offset;

                            var heightName = adt.textures.filenames[ti].Replace(".blp", "_h.blp");
                            if (!WoWFormatLib.Utils.CASC.FileExists(heightName))
                            {
                                Console.WriteLine("Height texture: " + heightName + " does not exist! Falling back to original texture (hack)..");
                                material.heightTexture = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);
                            }
                            else
                            {
                                material.heightTexture = BLPLoader.LoadTexture(heightName, cache);
                            }
                        }
                        else
                        {
                            material.heightScale  = 0.0f;
                            material.heightOffset = 1.0f;
                        }
                    }
                    else
                    {
                        material.heightScale  = 0.0f;
                        material.heightOffset = 1.0f;
                        material.scale        = 1.0f;
                    }
                    materials.Add(material);
                }
            }


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

            var renderBatches = new List <RenderBatch>();

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

                var off = verticelist.Count();

                var batch = new RenderBatch();

                batch.groupID = c;

                for (int i = 0, idx = 0; i < 17; i++)
                {
                    for (var j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                    {
                        var 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)
                        {
                            v.Color = new Vector4(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f, chunk.vertexShading.alpha[idx] / 255.0f);
                        }
                        else
                        {
                            v.Color = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);
                        }

                        v.TexCoord = new Vector2((j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, (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;
                        }

                        verticelist.Add(v);
                    }
                }

                result.startPos = verticelist[0];

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

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

                batch.heightScales  = new Vector4();
                batch.heightOffsets = new Vector4();

                for (var li = 0; li < adt.texChunks[c].layers.Count(); li++)
                {
                    if (adt.texChunks[c].alphaLayer != null)
                    {
                        alphalayermats.Add(BLPLoader.GenerateAlphaTexture(adt.texChunks[c].alphaLayer[li].layer));
                    }

                    layermats.Add((uint)cache.materials[adt.diffuseTextureFileDataIDs[adt.texChunks[c].layers[li].textureId]]);

                    var curMat = materials.Where(material => material.filename == adt.diffuseTextureFileDataIDs[adt.texChunks[c].layers[li].textureId].ToString()).Single();

                    layerscales.Add(curMat.scale);
                    layerheights.Add(curMat.heightTexture);

                    batch.heightScales[li]  = curMat.heightScale;
                    batch.heightOffsets[li] = curMat.heightOffset;
                }

                batch.materialID        = layermats.ToArray();
                batch.alphaMaterialID   = alphalayermats.ToArray();
                batch.scales            = layerscales.ToArray();
                batch.heightMaterialIDs = layerheights.ToArray();

                var indices  = indicelist.ToArray();
                var vertices = verticelist.ToArray();

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

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

                var colorAttrib = GL.GetAttribLocation(shaderProgram, "color");
                GL.EnableVertexAttribArray(colorAttrib);
                GL.VertexAttribPointer(colorAttrib, 4, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 3);

                var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");
                GL.EnableVertexAttribArray(texCoordAttrib);
                GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 7);

                var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
                GL.EnableVertexAttribArray(posAttrib);
                GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 9);

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

                renderBatches.Add(batch);
            }

            var doodads           = new List <Doodad>();
            var worldModelBatches = new List <WorldModelBatch>();

            if (loadModels)
            {
                for (var mi = 0; mi < adt.objects.models.entries.Count(); mi++)
                {
                    Console.WriteLine("Loading model #" + mi);

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

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

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

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

                for (var wmi = 0; wmi < adt.objects.worldModels.entries.Count(); wmi++)
                {
                    var wmofilename = "";

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

                    for (var wmfi = 0; wmfi < adt.objects.wmoNames.offsets.Count(); wmfi++)
                    {
                        if (adt.objects.wmoNames.offsets[wmfi] == mwid)
                        {
                            wmofilename = adt.objects.wmoNames.filenames[wmfi].ToLower();
                            break;
                        }
                    }

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

                    if (!cache.worldModelBatches.ContainsKey(wmofilename))
                    {
                        WMOLoader.LoadWMO(wmofilename, cache, shaderProgram);
                    }

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

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

            cache.terrain.Add(filename, result);
            return(result);
        }
Beispiel #3
0
        public static Renderer.Structs.WorldModel LoadWMO(string filename, CacheStorage cache, int shaderProgram)
        {
            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.cascHandler.FileExists(filename))
                {
                    var wmoreader = new WMOReader();
                    wmoreader.LoadWMO(filename, false);
                    cache.worldModels.Add(filename, wmoreader.wmofile);
                    wmo = wmoreader.wmofile;
                }
                else
                {
                    throw new Exception("WMO " + filename + " does not exist!");
                }
            }

            if (wmo.group.Count() == 0)
            {
                throw new Exception("Broken WMO! Report to developer (mail [email protected]) with this filename: " + filename);
            }

            var wmobatch = new Renderer.Structs.WorldModel()
            {
                groupBatches = new Renderer.Structs.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].vao          = GL.GenVertexArray();
                wmobatch.groupBatches[g].vertexBuffer = GL.GenBuffer();
                wmobatch.groupBatches[g].indiceBuffer = GL.GenBuffer();

                GL.BindVertexArray(wmobatch.groupBatches[g].vao);

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

                Renderer.Structs.M2Vertex[] wmovertices = new Renderer.Structs.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);

                //Set pointers in buffer
                //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
                //GL.EnableVertexAttribArray(normalAttrib);
                //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 0);

                var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");
                GL.EnableVertexAttribArray(texCoordAttrib);
                GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 3);

                var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
                GL.EnableVertexAttribArray(posAttrib);
                GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 5);

                //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 Renderer.Structs.Material[wmo.materials.Count()];
            for (int i = 0; i < wmo.materials.Count(); i++)
            {
                wmobatch.mats[i].texture1 = wmo.materials[i].texture1;
                wmobatch.mats[i].texture2 = wmo.materials[i].texture2;
                wmobatch.mats[i].texture3 = wmo.materials[i].texture3;

                for (int ti = 0; ti < wmo.textures.Count(); ti++)
                {
                    if (wmo.textures[ti].startOffset == wmo.materials[i].texture1)
                    {
                        wmobatch.mats[i].textureID1 = BLPLoader.LoadTexture(wmo.textures[ti].filename, cache);
                    }

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

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

            wmobatch.doodads = new Renderer.Structs.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 Renderer.Structs.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;
                    }

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

                        if (wmo.materials[matID].texture2 == wmobatch.mats[ti].texture2)
                        {
                            wmobatch.wmoRenderBatch[rb].materialID[1] = (uint)wmobatch.mats[ti].textureID2;
                        }

                        if (wmo.materials[matID].texture3 == wmobatch.mats[ti].texture3)
                        {
                            wmobatch.wmoRenderBatch[rb].materialID[2] = (uint)wmobatch.mats[ti].textureID3;
                        }
                    }

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

            return(wmobatch);
        }
Beispiel #4
0
        public static void LoadM2(string filename, CacheStorage cache, int shaderProgram)
        {
            filename = filename.ToLower().Replace(".mdx", ".m2");
            filename = filename.ToLower().Replace(".mdl", ".m2");

            if (cache.doodadBatches.ContainsKey(filename))
            {
                return;
            }

            WoWFormatLib.Structs.M2.M2Model model = new WoWFormatLib.Structs.M2.M2Model();

            if (cache.models.ContainsKey(filename))
            {
                model = cache.models[filename];
            }
            else
            {
                if (WoWFormatLib.Utils.CASC.cascHandler.FileExists(filename))
                {
                    var modelreader = new M2Reader();
                    modelreader.LoadM2(filename);
                    cache.models.Add(filename, modelreader.model);
                    model = modelreader.model;
                }
                else
                {
                    throw new Exception("Model " + filename + " does not exist!");
                }
            }

            var ddBatch = new Renderer.Structs.DoodadBatch()
            {
                boundingBox = new Renderer.Structs.BoundingBox()
                {
                    min = new Vector3(model.boundingbox[0].X, model.boundingbox[0].Y, model.boundingbox[0].Z),
                    max = new Vector3(model.boundingbox[1].X, model.boundingbox[1].Y, model.boundingbox[1].Z)
                }
            };

            // Textures
            ddBatch.mats = new Renderer.Structs.Material[model.textures.Count()];

            for (int i = 0; i < model.textures.Count(); i++)
            {
                string texturefilename = model.textures[i].filename;
                ddBatch.mats[i].flags = model.textures[i].flags;

                switch (model.textures[i].type)
                {
                case 0:
                    // Console.WriteLine("      Texture given in file!");
                    texturefilename = model.textures[i].filename;
                    break;

                case 1:
                    // string[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)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.cascHandler.FileExists(System.IO.Path.ChangeExtension(filename, ".blp")))
                    {
                        texturefilename = System.IO.Path.ChangeExtension(filename, ".blp");
                    }
                    else
                    {
                        //Console.WriteLine("      Type 2 does not exist!");
                        //needs lookup?
                    }
                    break;

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

                default:
                    //Console.WriteLine("      Falling back to placeholder texture");
                    texturefilename = "Dungeons\\Textures\\testing\\COLOR_13.blp";
                    break;
                }
                ddBatch.mats[i].textureID = BLPLoader.LoadTexture(texturefilename, cache);
                ddBatch.mats[i].filename  = texturefilename;
            }

            // Submeshes
            ddBatch.submeshes = new Renderer.Structs.Submesh[model.skins[0].submeshes.Count()];
            for (int i = 0; i < model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character"))
                {
                    if (model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                ddBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle;
                ddBatch.submeshes[i].numFaces  = model.skins[0].submeshes[i].nTriangles;
                for (int tu = 0; tu < model.skins[0].textureunit.Count(); tu++)
                {
                    if (model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        ddBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        if (!cache.materials.ContainsKey(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower()))
                        {
                            throw new Exception("MaterialCache does not have texture " + model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower());
                        }

                        ddBatch.submeshes[i].material = (uint)cache.materials[model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower()];
                    }
                }
            }

            ddBatch.vao = GL.GenVertexArray();
            GL.BindVertexArray(ddBatch.vao);

            // Vertices & indices
            ddBatch.vertexBuffer = GL.GenBuffer();
            ddBatch.indiceBuffer = GL.GenBuffer();

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

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

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

            uint[] modelindices = modelindicelist.ToArray();

            //Console.WriteLine(modelindicelist.Count() + " indices!");
            ddBatch.indices = modelindices;

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

            Renderer.Structs.M2Vertex[] modelvertices = new Renderer.Structs.M2Vertex[model.vertices.Count()];

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

            //Set pointers in buffer
            //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
            //GL.EnableVertexAttribArray(normalAttrib);
            //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 0);

            var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");

            GL.EnableVertexAttribArray(texCoordAttrib);
            GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 3);

            var posAttrib = GL.GetAttribLocation(shaderProgram, "position");

            GL.EnableVertexAttribArray(posAttrib);
            GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 5);
            cache.doodadBatches.Add(filename, ddBatch);
        }
Beispiel #5
0
        public static Terrain LoadADT(string filename, CacheStorage cache, int shaderProgram)
        {
            WoWFormatLib.Structs.ADT.ADT adt = new WoWFormatLib.Structs.ADT.ADT();

            Terrain result = new Terrain();

            //Load ADT from file
            if (WoWFormatLib.Utils.CASC.cascHandler.FileExists(filename))
            {
                var adtreader = new ADTReader();
                adtreader.LoadADT(filename);
                adt = adtreader.adtfile;
            }
            else
            {
                throw new Exception("ADT " + filename + " does not exist!");
            }

            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666
            float MapMidPoint = 32.0f / ChunkSize;

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

            result.vao = GL.GenVertexArray();
            GL.BindVertexArray(result.vao);

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

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

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

                if (adt.texParams != null && adt.texParams.Count() >= ti)
                {
                    material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4);
                    if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0)
                    {
                        material.heightScale  = adt.texParams[ti].height;
                        material.heightOffset = adt.texParams[ti].offset;

                        var heightName = adt.textures.filenames[ti].Replace(".blp", "_h.blp");
                        if (!WoWFormatLib.Utils.CASC.cascHandler.FileExists(heightName))
                        {
                            Console.WriteLine("Height texture: " + heightName + " does not exist! Falling back to original texture (hack)..");
                            material.heightTexture = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);
                        }
                        else
                        {
                            material.heightTexture = BLPLoader.LoadTexture(heightName, cache);
                        }
                    }
                    else
                    {
                        material.heightScale  = 0.0f;
                        material.heightOffset = 1.0f;
                    }
                }
                else
                {
                    material.heightScale  = 0.0f;
                    material.heightOffset = 1.0f;
                    material.scale        = 1.0f;
                }
                materials.Add(material);
            }

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

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

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

                int off = verticelist.Count();

                RenderBatch batch = new RenderBatch();

                batch.groupID = c;

                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)
                        {
                            v.Color = new Vector4(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f, chunk.vertexShading.alpha[idx] / 255.0f);
                        }
                        else
                        {
                            v.Color = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);
                        }

                        v.TexCoord = new Vector2((j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, (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;
                        }

                        verticelist.Add(v);
                    }
                }

                result.startPos = verticelist[0];

                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;

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

                batch.heightScales  = new Vector4();
                batch.heightOffsets = new Vector4();

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

                    var curMat = materials.Where(material => material.filename == adt.textures.filenames[adt.texChunks[c].layers[li].textureId]).Single();

                    layerscales.Add(curMat.scale);
                    layerheights.Add(curMat.heightTexture);

                    batch.heightScales[li]  = curMat.heightScale;
                    batch.heightOffsets[li] = curMat.heightOffset;
                }

                batch.materialID        = layermats.ToArray();
                batch.alphaMaterialID   = alphalayermats.ToArray();
                batch.scales            = layerscales.ToArray();
                batch.heightMaterialIDs = layerheights.ToArray();

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

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

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

                var colorAttrib = GL.GetAttribLocation(shaderProgram, "color");
                GL.EnableVertexAttribArray(colorAttrib);
                GL.VertexAttribPointer(colorAttrib, 4, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 3);

                var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");
                GL.EnableVertexAttribArray(texCoordAttrib);
                GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 7);

                var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
                GL.EnableVertexAttribArray(posAttrib);
                GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 9);

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

                renderBatches.Add(batch);
            }

            result.renderBatches = renderBatches.ToArray();
            //result.doodads = doodads.ToArray();
            //result.worldModelBatches = worldModelBatches.ToArray();

            cache.terrain.Add(filename, result);
            return(result);
        }