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 (Listfile.TryGetFileDataID(filename, out var filedataid)) { if (WoWFormatLib.Utils.CASC.FileExists(filedataid)) { var modelreader = new M2Reader(); modelreader.LoadM2(filedataid); cache.models.Add(filename, modelreader.model); model = modelreader.model; } else { throw new Exception("Model " + filename + " does not exist!"); } } else { throw new Exception("Filename " + filename + " does not exist in listfile!"); } } 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 = 528732; 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 = 528732; break; } // Not set in TXID if (textureFileDataID == 0) { textureFileDataID = 528732; } 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 = 528732; 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 { if (Listfile.FilenameToFDID.TryGetValue(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.Replace('\\', '/').ToLower(), out var filedataid)) { textureFileDataID = filedataid; } else { textureFileDataID = 528732; } } 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(); 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 Renderer.Structs.WorldModel LoadWMO(string filename, CacheStorage cache, int shaderProgram) { if (cache.worldModelBatches.ContainsKey(filename)) { return(cache.worldModelBatches[filename]); } var wmo = new WoWFormatLib.Structs.WMO.WMO(); if (cache.worldModels.ContainsKey(filename)) { wmo = cache.worldModels[filename]; } else { if (!Listfile.TryGetFileDataID(filename, out uint fileDataID)) { CASCLib.Logger.WriteLine("Could not get filedataid for " + filename); } //Load WMO from file if (WoWFormatLib.Utils.CASC.FileExists(fileDataID)) { var wmofile = new WMOReader().LoadWMO(fileDataID); cache.worldModels.Add(filename, wmofile); wmo = cache.worldModels[filename]; } else { throw new Exception("WMO " + filename + " does not exist!"); } } if (wmo.group.Count() == 0) { CASCLib.Logger.WriteLine("WMO has no groups: ", filename); 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()] }; var groupNames = new string[wmo.group.Count()]; for (var 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); var wmovertices = new Renderer.Structs.M2Vertex[wmo.group[g].mogp.vertices.Count()]; for (var 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 (var 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); var wmoindicelist = new List <uint>(); for (var 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 (var 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; if (wmo.textures == null) { if (WoWFormatLib.Utils.CASC.FileExists(wmo.materials[i].texture1)) { wmobatch.mats[i].textureID1 = BLPLoader.LoadTexture(wmo.materials[i].texture1, cache); } if (WoWFormatLib.Utils.CASC.FileExists(wmo.materials[i].texture2)) { wmobatch.mats[i].textureID2 = BLPLoader.LoadTexture(wmo.materials[i].texture2, cache); } if (WoWFormatLib.Utils.CASC.FileExists(wmo.materials[i].texture3)) { wmobatch.mats[i].textureID3 = BLPLoader.LoadTexture(wmo.materials[i].texture3, cache); } } else { for (var 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 (var i = 0; i < wmo.doodadDefinitions.Count(); i++) { if (wmo.doodadNames != null) { for (var j = 0; j < wmo.doodadNames.Count(); j++) { if (wmo.doodadDefinitions[i].offset == wmo.doodadNames[j].startOffset) { wmobatch.doodads[i].filename = wmo.doodadNames[j].filename; } } } else { wmobatch.doodads[i].filedataid = wmo.doodadDefinitions[i].offset; } 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]); } var numRenderbatches = 0; //Get total amount of render batches for (var 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]; var rb = 0; for (var g = 0; g < wmo.group.Count(); g++) { var group = wmo.group[g]; if (group.mogp.renderBatches == null) { continue; } for (var 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 (var 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); }
private static uint MISSING_TEXTURE_ID = 186184; // textures/shanecube.blp public static Renderer.Structs.DoodadBatch LoadM2(string fileName, int shaderProgram) { fileName = fileName.ToLower().Replace(".mdx", ".m2"); fileName = fileName.ToLower().Replace(".mdl", ".m2"); M2Model model = new M2Model(); if (Listfile.TryGetFileDataID(fileName, out var fileDataID)) { if (WoWFormatLib.Utils.CASC.FileExists(fileDataID)) { var modelReader = new M2Reader(); modelReader.LoadM2(fileDataID); model = modelReader.model; } else { throw new Exception("Model " + fileName + " does not exist!"); } } else { throw new Exception("Filename " + fileName + " does not exist in listfile!"); } if (model.boundingbox == null) { throw new Exception("Model does not contain bounding box: " + fileName); } var doodadBatch = 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) { throw new Exception("Model does not contain textures: " + fileName); } if (model.skins == null) { throw new Exception("Model does not contain skins: " + fileName); } // Textures doodadBatch.mats = new Renderer.Structs.Material[model.textures.Count()]; for (var i = 0; i < model.textures.Count(); i++) { uint textureFileDataID = DEFAULT_TEXTURE_ID; doodadBatch.mats[i].flags = model.textures[i].flags; switch (model.textures[i].type) { case 0: // NONE 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: // TEX_COMPONENT_SKIN case 2: // TEX_COMPONENT_OBJECT_SKIN case 11: // TEX_COMPONENT_MONSTER_1 break; } // Not set in TXID if (textureFileDataID == 0) { textureFileDataID = DEFAULT_TEXTURE_ID; } if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID)) { textureFileDataID = MISSING_TEXTURE_ID; } doodadBatch.mats[i].textureID = BLPLoader.LoadTexture(textureFileDataID); doodadBatch.mats[i].filename = textureFileDataID.ToString(); } // Submeshes doodadBatch.submeshes = new Renderer.Structs.Submesh[model.skins[0].submeshes.Count()]; for (var i = 0; i < model.skins[0].submeshes.Count(); i++) { doodadBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle; doodadBatch.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) { doodadBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode; uint textureFileDataID = DEFAULT_TEXTURE_ID; if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID)) { textureFileDataID = MISSING_TEXTURE_ID; } 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 { if (Listfile.FilenameToFDID.TryGetValue(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.Replace('\\', '/').ToLower(), out var filedataid)) { textureFileDataID = filedataid; } else { textureFileDataID = DEFAULT_TEXTURE_ID; if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID)) { textureFileDataID = MISSING_TEXTURE_ID; } } } if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID)) { textureFileDataID = MISSING_TEXTURE_ID; } doodadBatch.submeshes[i].material = (uint)BLPLoader.LoadTexture(textureFileDataID); } } } doodadBatch.vao = GL.GenVertexArray(); GL.BindVertexArray(doodadBatch.vao); // Vertices & indices doodadBatch.vertexBuffer = GL.GenBuffer(); doodadBatch.indiceBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, doodadBatch.vertexBuffer); GL.BindBuffer(BufferTarget.ElementArrayBuffer, doodadBatch.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(); doodadBatch.indices = modelindices; GL.BindBuffer(BufferTarget.ElementArrayBuffer, doodadBatch.indiceBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(doodadBatch.indices.Length * sizeof(uint)), doodadBatch.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, doodadBatch.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); return(doodadBatch); }
public static Terrain LoadADT(Structs.MapTile mapTile, int shaderProgram, bool loadModels = false) { ADT adt = new ADT(); Terrain result = new Terrain(); ADTReader adtReader = new ADTReader(); Listfile.FDIDToFilename.TryGetValue(mapTile.wdtFileDataID, out string wdtFilename); adtReader.LoadADT(mapTile.wdtFileDataID, mapTile.tileX, mapTile.tileY, true, wdtFilename); adt = adtReader.adtfile; 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]); 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]); } else { material.heightTexture = BLPLoader.LoadTexture(adt.heightTextureFileDataIDs[ti]); } } 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]); 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]); } else { material.heightTexture = BLPLoader.LoadTexture(heightName); } } 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 layerMaterials = 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)); } Material curMat; if (adt.diffuseTextureFileDataIDs == null) { if (adt.textures.filenames == null) { throw new Exception("ADT has no textures?"); } var texFileDataID = WoWFormatLib.Utils.CASC.getFileDataIdByName(adt.textures.filenames[adt.texChunks[c].layers[li].textureId]); layerMaterials.Add((uint)BLPLoader.LoadTexture(texFileDataID)); curMat = materials.Where(material => material.filename == adt.textures.filenames[adt.texChunks[c].layers[li].textureId]).Single(); } else { layerMaterials.Add((uint)BLPLoader.LoadTexture(adt.diffuseTextureFileDataIDs[adt.texChunks[c].layers[li].textureId])); 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 = layerMaterials.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 }); M2Loader.LoadM2(modelFileName, 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!"); } 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 = WMOLoader.LoadWMO(wmoFileName, shaderProgram) }); } } result.renderBatches = renderBatches.ToArray(); result.doodads = doodads.ToArray(); result.worldModelBatches = worldModelBatches.ToArray(); return(result); }