/// <summary> /// Loads the specified WMO group file from the archives and deserialize it. /// </summary> /// <param name="fileReference">The archive reference to the model group.</param> /// <returns>A WMO object, containing just the specified model group.</returns> public static WMO LoadWorldModelGroup(FileReference fileReference) { if (fileReference == null) { throw new ArgumentNullException(nameof(fileReference)); } // Get the file name of the root object string modelRootPath = fileReference.FilePath.Remove(fileReference.FilePath.Length - 8, 4); WMO worldModel; // Extract it and load just this model group try { byte[] rootData = fileReference.Context.Assets.ExtractFile(modelRootPath); worldModel = new WMO(rootData); byte[] modelGroupData = fileReference.Extract(); worldModel.AddModelGroup(new ModelGroup(modelGroupData)); } catch (FileNotFoundException fex) { Log.Warn($"Failed to load the model group \"{fileReference.FilePath}\": {fex}"); throw; } catch (InvalidFileSectorTableException fex) { Log.Warn($"Failed to load the model group \"{fileReference.FilePath}\" due to an invalid sector table (\"{fex}\")"); throw; } return(worldModel); }
/// <summary> /// Loads the specified WMO group file from the archives and deserialize it. /// </summary> /// <param name="fileReference">The archive reference to the model group.</param> /// <returns>A WMO object, containing just the specified model group.</returns> public static WMO LoadWorldModelGroup(FileReference fileReference) { // Get the file name of the root object string modelRootPath = fileReference.FilePath.Remove(fileReference.FilePath.Length - 8, 4); // Extract it and load just this model group try { byte[] fileData = fileReference.PackageGroup.ExtractFile(modelRootPath); if (fileData != null) { WMO worldModel = new WMO(fileData); byte[] modelGroupData = fileReference.Extract(); if (modelGroupData != null) { worldModel.AddModelGroup(new ModelGroup(modelGroupData)); } return(worldModel); } } catch (InvalidFileSectorTableException fex) { Log.Warn( $"Failed to load the model group \"{fileReference.FilePath}\" due to an invalid sector table (\"{fex.Message}\")."); return(null); } return(null); }
/// <summary> /// Initializes a new instance of the <see cref="RenderableWorldModel"/> class. /// </summary> /// <param name="inModel">The model to render.</param> /// <param name="gameContext">The game context.</param> public RenderableWorldModel(WMO inModel, WarcraftGameContext gameContext) { this.Model = inModel; this.GameContext = gameContext; this.ActorTransform = new Transform(); this.IsInitialized = false; }
/// <summary> /// Creates a renderable object from the specified WMO object, and the specified package group it belongs to. /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// /// The <see cref="IRenderable"/> constructors commonly make extensive use of OpenGL methods. /// </summary> /// <param name="worldModel">The model object.</param> /// <param name="fileReference">The package group it belongs to.</param> /// <returns>An encapsulated renderable OpenGL object.</returns> public static IRenderable CreateRenderableWorldModel(WMO worldModel, FileReference fileReference) { if (worldModel == null) { return(null); } IRenderable renderableWorldModel = new RenderableWorldModel(worldModel, fileReference.PackageGroup); return(renderableWorldModel); }
/// <summary> /// Creates a renderable object from the specified WMO object, and the specified package group it belongs to. /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// The <see cref="IRenderable"/> constructors commonly make extensive use of OpenGL methods. /// </summary> /// <param name="worldModel">The model object.</param> /// <param name="fileReference">The package group it belongs to.</param> /// <param name="version">The contextually relevant version.</param> /// <returns>An encapsulated renderable OpenGL object.</returns> public static IRenderable CreateRenderableWorldModel(WMO worldModel, FileReference fileReference, WarcraftVersion version) { if (worldModel == null) { return(null); } IRenderable renderableWorldModel = new RenderableWorldModel(worldModel, fileReference.PackageGroup, version); return(renderableWorldModel); }
/// <summary> /// Initializes a new instance of the <see cref="RenderableWorldModel"/> class. /// </summary> public RenderableWorldModel(WMO inModel, PackageGroup inPackageGroup) { this.Model = inModel; this.ModelPackageGroup = inPackageGroup; this.ActorTransform = new Transform ( new Vector3(0.0f, 0.0f, 0.0f), Quaternion.FromAxisAngle(Vector3.UnitX, MathHelper.Pi), new Vector3(1.0f, 1.0f, 1.0f) ); this.IsInitialized = false; Initialize(); }
/// <summary> /// Creates a renderable object from the specified WMO object, and the specified package group it belongs to. /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// The <see cref="IRenderable"/> constructors commonly make extensive use of OpenGL methods. /// </summary> /// <param name="worldModel">The model object.</param> /// <param name="fileReference">The reference it was constructed from.</param> /// <returns>An encapsulated renderable OpenGL object.</returns> public static IRenderable CreateRenderableWorldModel(WMO worldModel, FileReference fileReference) { var warcraftContext = fileReference.Context as WarcraftGameContext; if (warcraftContext == null) { // TODO: This is bad practice. Refactor throw new ArgumentException("The given context must be a warcraft-typed context.", nameof(fileReference.Context)); } RenderableWorldModel renderableWorldModel = new RenderableWorldModel(worldModel, warcraftContext); renderableWorldModel.LoadDoodads(); return(renderableWorldModel); }
/// <summary> /// TODO: Refactor this and LoadWorldModelGroup /// Loads the specified WMO file from the archives and deserialize it. /// </summary> /// <param name="fileReference">The archive reference to the WMO root object.</param> /// <returns>A WMO object.</returns> public static WMO LoadWorldModel(FileReference fileReference) { try { byte[] fileData = fileReference.Extract(); if (fileData != null) { WMO worldModel = new WMO(fileData); string modelPathWithoutExtension = Path.GetFileNameWithoutExtension(fileReference.FilePath); for (int i = 0; i < worldModel.GroupCount; ++i) { // Extract the groups as well string modelGroupPath = $"{modelPathWithoutExtension}_{i:D3}.wmo"; try { byte[] modelGroupData = fileReference.PackageGroup.ExtractFile(modelGroupPath); if (modelGroupData != null) { worldModel.AddModelGroup(new ModelGroup(modelGroupData)); } } catch (InvalidFileSectorTableException fex) { Log.Warn( $"Failed to load the model group \"{modelGroupPath}\" due to an invalid sector table (\"{fex.Message}\")."); return(null); } } return(worldModel); } } catch (InvalidFileSectorTableException fex) { Log.Warn( $"Failed to load the model \"{fileReference.FilePath}\" due to an invalid sector table (\"{fex.Message}\")."); return(null); } return(null); }
/// <summary> /// Loads the specified WMO file from the archives and deserialize it. /// </summary> /// <param name="fileReference">The archive reference to the WMO root object.</param> /// <returns>A WMO object.</returns> public static WMO LoadWorldModel(FileReference fileReference) { if (fileReference == null) { throw new ArgumentNullException(nameof(fileReference)); } WMO worldModel; try { var fileData = fileReference.Extract(); worldModel = new WMO(fileData); var modelPathWithoutExtension = $"{fileReference.FileDirectory.Replace('/', '\\')}\\" + $"{Path.GetFileNameWithoutExtension(fileReference.Filename)}"; for (var i = 0; i < worldModel.GroupCount; ++i) { // Extract the groups as well var modelGroupPath = $"{modelPathWithoutExtension}_{i:D3}.wmo"; try { var modelGroupData = fileReference.Context.Assets.ExtractFile(modelGroupPath); worldModel.AddModelGroup(new ModelGroup(modelGroupData)); } catch (FileNotFoundException fex) { Log.Warn($"Failed to load model group \"{modelGroupPath}\": {fex}."); throw; } } } catch (InvalidFileSectorTableException fex) { Log.Warn ( $"Failed to load the model \"{fileReference.FilePath}\" due to an invalid sector table " + $"(\"{fex.Message}\")." ); throw; } return(worldModel); }
/// <summary> /// Initializes a new instance of the <see cref="RenderableWorldModel"/> class. /// </summary> /// <param name="inModel">The model to render.</param> /// <param name="inPackageGroup">The package group the model belongs to.</param> /// <param name="inVersion">The game version of the package group.</param> public RenderableWorldModel(WMO inModel, PackageGroup inPackageGroup, WarcraftVersion inVersion) { this.Model = inModel; this.ModelPackageGroup = inPackageGroup; this.DatabaseProvider = new ClientDatabaseProvider(inVersion, this.ModelPackageGroup); this.ActorTransform = new Transform ( new Vector3(0.0f, 0.0f, 0.0f), Quaternion.FromAxisAngle(Vector3.UnitX, MathHelper.Pi), new Vector3(1.0f, 1.0f, 1.0f) ); this.IsInitialized = false; Initialize(); }
public void ParseWMOBlock() { WMO.Load(currentWMOdatapath, currentWMOuniqueID, currentWMOposition, currentWMOrotation, currentWMOscale); }
public void SelectWMOModel(WMO.WMOHitInformation wmoHit) { mMdxResult = null; mWmoResult = wmoHit; mSelectionBox.UpdateSelectionBox(wmoHit.Model.BoundingBox, wmoHit.ModelMatrix); if (mModelMover != null) mModelMover.ModelChanged -= mSelectionBox.UpdateMatrix; mModelMover = new WMO.WMOModelMover(wmoHit); mModelMover.ModelChanged += (matrix) => { mSelectionBox.UpdateMatrix(matrix); if (mCurrentSelection != null) mCurrentSelection.ModelPosition = new SlimDX.Vector3(matrix.M41, matrix.M42, matrix.M43); }; var modelOverlay = Game.GameManager.GraphicsThread.GetOverlay<UI.Overlays.ModelInfoOverlay>(); if (modelOverlay != null) modelOverlay.UpdateModel(wmoHit); else { modelOverlay = new UI.Overlays.ModelInfoOverlay(wmoHit); Game.GameManager.GraphicsThread.PushOverlay(modelOverlay); } ModelSelectionInfo info = new ModelSelectionInfo() { ModelName = wmoHit.Model.FileName, ModelMover = mModelMover, ModelPosition = new SlimDX.Vector3(wmoHit.ModelMatrix.M41, wmoHit.ModelMatrix.M42, wmoHit.ModelMatrix.M43) }; mCurrentSelection = info; if (ModelSelected != null) ModelSelected(info); }
private void GetChunkData(TriangleCollection triangles, int chunk_x, int chunk_y, SparseMatrix3D <WMO> instances) { if (chunk_x < 0) { return; } if (chunk_y < 0) { return; } if (chunk_x > 63) { return; } if (chunk_y > 63) { return; } if (triangles == null) { return; } if (wdtf == null) { return; } if (wdt == null) { return; } wdtf.LoadMapTile(chunk_x, chunk_y); MapTile t = wdt.maptiles[chunk_x, chunk_y]; if (t != null) { //System.Diagnostics.Debug.Write(" render"); // Map tiles for (int ci = 0; ci < 16; ci++) { for (int cj = 0; cj < 16; cj++) { MapChunk c = t.chunks[ci, cj]; if (c != null) { AddTriangles(triangles, c); } } } // World objects foreach (WMOInstance wi in t.wmois) { if (wi != null && wi.wmo != null) { String fn = wi.wmo.fileName; int last = fn.LastIndexOf('\\'); fn = fn.Substring(last + 1); // logger.WriteLine(" wmo: " + fn + " at " + wi.pos); if (fn != null) { WMO old = instances.Get((int)wi.pos.x, (int)wi.pos.y, (int)wi.pos.z); if (old == wi.wmo) { //logger.WriteLine("Already got " + fn); } else { instances.Set((int)wi.pos.x, (int)wi.pos.y, (int)wi.pos.z, wi.wmo); AddTriangles(triangles, wi); } } } } foreach (ModelInstance mi in t.modelis) { if (mi != null && mi.model != null) { String fn = mi.model.fileName; int last = fn.LastIndexOf('\\'); // fn = fn.Substring(last + 1); //logger.WriteLine(" wmi: " + fn + " at " + mi.pos); AddTriangles(triangles, mi); //logger.WriteLine(" model: " + fn); } } logger.WriteLine("wee"); /*logger.WriteLine( * String.Format(" Triangles - Map: {0,6} Objects: {1,6} Models: {2,6}", * map_triangles.GetNumberOfTriangles(), * obj_triangles.GetNumberOfTriangles(), * model_triangles.GetNumberOfTriangles())); */ } logger.WriteLine(" done"); wdt.maptiles[chunk_x, chunk_y] = null; // clear it atain //myChunk.triangles.ClearVertexMatrix(); // not needed anymore //return myChunk; }
private void GetChunkData(TriangleCollection triangles, int chunk_x, int chunk_y, SparseMatrix3D <WMO> instances) { if (chunk_x < 0) { return; } if (chunk_y < 0) { return; } if (chunk_x > 63) { return; } if (chunk_y > 63) { return; } /* * if (chunkCache[chunk_x, chunk_y] != null) * { * chunkCache[chunk_x, chunk_y].LRU = NOW++; * return chunkCache[chunk_x, chunk_y]; * } * else * { * EvictFromChunkCache(); * } * * * float max_x = ChunkReader.ZEROPOINT - (float)(chunk_y) * ChunkReader.TILESIZE; * float max_y = ChunkReader.ZEROPOINT - (float)(chunk_x) * ChunkReader.TILESIZE; * float min_x = max_x - ChunkReader.TILESIZE; * float min_y = max_y - ChunkReader.TILESIZE; * * * ChunkData myChunk = new ChunkData(); * myChunk.LRU = NOW++; * chunkCache[chunk_x, chunk_y] = myChunk; * chunkCacheItems++; * * TriangleCollection triangles = new TriangleCollection(); * myChunk.triangles = triangles; * triangles.SetLimits(min_x, min_y, -1E30f, max_x, max_y, 1E30f); */ //Console.WriteLine("x " + max_x + " y " + max_y); // Console.Write(String.Format(" Tile {0,2} {1,2}", chunk_x, chunk_y)); // Console.Write(" load"); if (triangles == null) { return; } if (wdtf == null) { return; } if (wdt == null) { return; } wdtf.LoadMapTile(chunk_x, chunk_y); MapTile t = wdt.maptiles[chunk_x, chunk_y]; if (t != null) { //Console.Write(" render"); // Map tiles for (int ci = 0; ci < 16; ci++) { for (int cj = 0; cj < 16; cj++) { MapChunk c = t.chunks[ci, cj]; if (c != null) { AddTriangles(triangles, c); } } } // World objects foreach (WMOInstance wi in t.wmois) { if (wi != null && wi.wmo != null) { String fn = wi.wmo.fileName; int last = fn.LastIndexOf('\\'); fn = fn.Substring(last + 1); // Console.WriteLine(" wmo: " + fn + " at " + wi.pos); if (fn != null) { WMO old = instances.Get((int)wi.pos.x, (int)wi.pos.y, (int)wi.pos.z); if (old == wi.wmo) { //Console.WriteLine("Already got " + fn); } else { instances.Set((int)wi.pos.x, (int)wi.pos.y, (int)wi.pos.z, wi.wmo); AddTriangles(triangles, wi); } } } } foreach (ModelInstance mi in t.modelis) { if (mi != null && mi.model != null) { String fn = mi.model.fileName; int last = fn.LastIndexOf('\\'); // fn = fn.Substring(last + 1); //Console.WriteLine(" wmi: " + fn + " at " + mi.pos); AddTriangles(triangles, mi); //Console.WriteLine(" model: " + fn); } } Console.WriteLine("wee"); /*Console.WriteLine( * String.Format(" Triangles - Map: {0,6} Objects: {1,6} Models: {2,6}", * map_triangles.GetNumberOfTriangles(), * obj_triangles.GetNumberOfTriangles(), * model_triangles.GetNumberOfTriangles())); */ } Console.WriteLine(" done"); wdt.maptiles[chunk_x, chunk_y] = null; // clear it atain //myChunk.triangles.ClearVertexMatrix(); // not needed anymore //return myChunk; }
public static TileObjects<WMO> ReadTileBuildings(BinaryReader reader) { var magix = reader.ReadString(); if (magix != fileType) { Console.WriteLine("Invalid file format, suckah!"); return null; } WMO[] wmos; var numBuildings = reader.ReadUInt16(); if (numBuildings > 0) { wmos = new WMO[numBuildings]; for (var i = 0; i < numBuildings; i++) { wmos[i] = ReadBuilding(reader); } } else { wmos = new WMO[0]; } return new TileObjects<WMO>(wmos); }
void AddTriangles(TriangleCollection s, WMOInstance wi) { float dx = wi.pos.x; float dy = wi.pos.y; float dz = wi.pos.z; float dir_x = wi.dir.x; float dir_y = wi.dir.y; float dir_z = wi.dir.z; WMO wmo = wi.wmo; foreach (WMOGroup g in wmo.groups) { int[] vertices = new int[g.nVertices]; for (int i = 0; i < g.nVertices; i++) { int off = i * 3; float x = g.vertices[off]; float y = g.vertices[off + 2]; float z = g.vertices[off + 1]; rotate(x, z, (dir_y - 90), out x, out z); rotate(x, y, dir_z, out x, out y); rotate(y, z, -dir_x, out y, out z); float xx = x + dx; float yy = y + dy; float zz = -z + dz; float finalx = ChunkReader.ZEROPOINT - zz; float finaly = ChunkReader.ZEROPOINT - xx; float finalz = yy; vertices[i] = s.AddVertex(finalx, finaly, finalz); } // Console.WriteLine("nTriangles: " + g.nTriangles); for (int i = 0; i < g.nTriangles; i++) { //if ((g.materials[i] & 0x1000) != 0) { int off = i * 3; int i0 = vertices[g.triangles[off]]; int i1 = vertices[g.triangles[off + 1]]; int i2 = vertices[g.triangles[off + 2]]; int t = s.AddTriangle(i0, i1, i2, ChunkedTriangleCollection.TriangleFlagObject); //if(t != -1) s.SetTriangleExtra(t, g.materials[0], 0, 0); } } } int doodadset = wi.doodadset; if (doodadset < wmo.nDoodadSets) { uint firstDoodad = wmo.doodads[doodadset].firstInstance; uint nDoodads = wmo.doodads[doodadset].nInstances; for (uint i = 0; i < nDoodads; i++) { uint d = firstDoodad + i; ModelInstance mi = wmo.doodadInstances[d]; if (mi != null) { //Console.WriteLine("I got model " + mi.model.fileName + " at " + mi.pos); //AddTrianglesGroupDoodads(s, mi, wi.dir, wi.pos, 0.0f); } } } }
public static WMO ReadBuilding(BinaryReader reader) { var building = new WMO { Bounds = reader.ReadBoundingBox(), RotationModelY = reader.ReadSingle(), WorldPos = reader.ReadVector3() }; WMOSubGroup[] groups; var numGroups = reader.ReadUInt16(); if (numGroups > 0) { groups = new WMOSubGroup[numGroups]; for (var i = 0; i < numGroups; i++) { groups[i] = ReadBuildingGroup(reader); } } else { groups = null; } building.BuildingGroups = groups; return building; }
public void ParseWMOBlock() { WMO.Load(currentWMOFileDataId, currentWMOuniqueID, currentWMOposition, currentWMOrotation, currentWMOscale, CascHandler); }
private void AddTriangles(TriangleCollection s, WMOInstance wi) { float dx = wi.pos.x; float dy = wi.pos.y; float dz = wi.pos.z; float dir_x = wi.dir.z; float dir_y = wi.dir.y - 90; float dir_z = -wi.dir.x; logger.WriteLine("modeli: " + dir_x + " " + dir_y + " " + dir_z); WMO wmo = wi.wmo; foreach (WMOGroup g in wmo.groups) { sequence++; int[] vertices = new int[g.nVertices]; float minx = float.MaxValue; float miny = float.MaxValue; float minz = float.MaxValue; float maxx = float.MinValue; float maxy = float.MinValue; float maxz = float.MinValue; for (int i = 0; i < g.nVertices; i++) { int off = i * 3; float x = g.vertices[off]; float y = g.vertices[off + 2]; float z = g.vertices[off + 1]; rotate(z, y, dir_x, out z, out y); rotate(x, y, dir_z, out x, out y); rotate(x, z, dir_y, out x, out z); float xx = x + dx; float yy = y + dy; float zz = -z + dz; float finalx = ChunkReader.ZEROPOINT - zz; float finaly = ChunkReader.ZEROPOINT - xx; float finalz = yy; vertices[i] = s.AddVertex(finalx, finaly, finalz); if (finalx < minx) { minx = finalx; } if (finaly < miny) { miny = finalx; } if (finalz < minz) { minz = finalx; } if (finalx > maxx) { maxx = finalx; } if (finaly > maxy) { maxy = finalx; } if (finalz > maxz) { maxz = finalx; } } logger.WriteLine("AddTriangles: x(" + minx + " - " + maxx + ") y(" + miny + " - " + maxy + ") z(" + minz + " - " + maxz + ")"); for (int i = 0; i < g.nTriangles; i++) { //if ((g.materials[i] & 0x1000) != 0) { int off = i * 3; int i0 = vertices[g.triangles[off]]; int i1 = vertices[g.triangles[off + 1]]; int i2 = vertices[g.triangles[off + 2]]; int t = s.AddTriangle(i0, i1, i2, ChunkedTriangleCollection.TriangleFlagObject, sequence); //if(t != -1) s.SetTriangleExtra(t, g.materials[0], 0, 0); } } } int doodadset = wi.doodadset; if (doodadset < wmo.nDoodadSets) { uint firstDoodad = wmo.doodads[doodadset].firstInstance; uint nDoodads = wmo.doodads[doodadset].nInstances; for (uint i = 0; i < nDoodads; i++) { uint d = firstDoodad + i; ModelInstance mi = wmo.doodadInstances[d]; if (mi != null) { //logger.WriteLine("I got model " + mi.model.fileName + " at " + mi.pos); //AddTrianglesGroupDoodads(s, mi, wi.dir, wi.pos, 0.0f); // DOes not work :( } } } }
private static void ReadBuildings(BinaryReader br, TreeReference<WMO> tree) { var numBuildings = br.ReadInt32(); for (var i = 0; i < numBuildings; i++) { var bounds = br.ReadBoundingBox(); var invRot = br.ReadSingle(); var matrix = Matrix.CreateRotationY(((-1.0f*(invRot - 90)))*RadiansPerDegree); var center = br.ReadVector3(); WMOGroup[] groups; var numGroups = br.ReadInt32(); if (numGroups > 0) { groups = new WMOGroup[numGroups]; for (var j = 0; j < numGroups; j++) { groups[j] = ReadBuildingGroup(br); } } else { groups = null; } var building = new WMO { Bounds = bounds, Center = center, InverseRotation = matrix, WmoGroups = groups }; tree.Tree.Insert(building); } }