Example #1
0
 public void AddDungeon(WorldModelRoot model, WorldModelHandler.WorldModelDefinition def)
 {
     var verts = new List<Vector3>();
     var tris = new List<Triangle<uint>>();
     WorldModelHandler.InsertModelGeometry(verts, tris, def, model);
     AddData(verts, tris);
 }
Example #2
0
 public void TestDungeonWithWater()
 {
     MpqManager.Initialize("S:\\World of Warcraft");
     var wdt = new WDT("world\\maps\\orgrimmarinstance\\orgrimmarinstance.wdt");
     Assert.IsTrue(wdt.IsValid && wdt.IsGlobalModel);
     var file = wdt.ModelFile;
     var model = new WorldModelRoot(file);
     var verts = new System.Collections.Generic.List<Vector3>();
     var tris = new System.Collections.Generic.List<Triangle<uint>>();
     WorldModelHandler.InsertModelGeometry(verts, tris, wdt.ModelDefinition, model);
     Assert.IsFalse(verts.Any(v => float.IsNaN(v.X) || float.IsNaN(v.Y) || float.IsNaN(v.Z)));
 }
Example #3
0
        protected override void LoadContent()
        {
            var model = new WorldModelRoot(_path);
            var verts = new List<Vector3>();
            var tris = new List<Triangle<uint>>();
            WorldModelHandler.InsertModelGeometry(verts, tris, _def, model);
            SaveMeshToDisk(verts, tris);
            meshDisplay.Game.Camera.Camera.Position = new Vector3(verts[0].Y, verts[0].Z, verts[0].X);

            _drawer = new GeometryDrawer();
            _drawer.Initialize(Game, Color.Red, verts, tris);

            _effect = new BasicEffect(GraphicsDevice);
            _depthState = new DepthStencilState { DepthBufferEnable = true };
        }
Example #4
0
        protected override void ProcessInternal(ChunkedData subChunks)
        {
            if (!IsSane)
                return;

            var wmoReferencesChunk = subChunks.GetChunkByName("MCRW");
            if (wmoReferencesChunk == null)
                return;
            var stream = wmoReferencesChunk.GetStream();
            var reader = new BinaryReader(stream);
            var refCount = (int)(wmoReferencesChunk.Length / 4);
            for (int i = 0; i < refCount; i++)
            {
                int index = reader.ReadInt32();
                if (index < 0 || index >= _definitions.Count)
                    continue;

                var wmo = _definitions[index];

                if (_drawn.Contains(wmo.UniqueId))
                    continue;
                _drawn.Add(wmo.UniqueId);

                if (wmo.MwidIndex >= _paths.Count)
                    continue;

                var path = _paths[(int) wmo.MwidIndex];
                var model = Cache.WorldModel.Get(path);
                if (model == null)
                {
                    model = new WorldModelRoot(path);
                    Cache.WorldModel.Insert(path, model);
                }

                if (Vertices == null)
                    Vertices = new List<Vector3>(1000);
                if (Triangles == null)
                    Triangles = new List<Triangle<uint>>(1000);

                InsertModelGeometry(Vertices, Triangles, wmo, model);
            }
        }
        public static void InsertModelGeometry(List<Vector3> vertices, List<Triangle<uint>> triangles, WorldModelDefinition def, WorldModelRoot root)
        {
            var transformation = Transformation.GetTransformation(def);

            foreach (var group in root.Groups)
            {
                int vertOffset = vertices.Count;
                vertices.AddRange(group.Vertices.Select(vert => Vector3.Transform(vert, transformation).ToVector3()));

                for (int i = 0; i < group.Triangles.Length; i++)
                {
                    // only include collidable tris
                    if ((group.TriangleFlags[i] & 0x04) != 0 && group.TriangleMaterials[i] != 0xFF)
                        continue;

                    var tri = group.Triangles[i];
                    triangles.Add(new Triangle<uint>(TriangleType.Wmo, (uint) (tri.V0 + vertOffset),
                                                     (uint) (tri.V1 + vertOffset),
                                                     (uint) (tri.V2 + vertOffset)));
                }
            }

            if (def.DoodadSet >= 0 && def.DoodadSet < root.DoodadSets.Count)
            {
                var set = root.DoodadSets[def.DoodadSet];
                var instances = new List<DoodadInstance>((int)set.CountInstances);
                for (uint i = set.FirstInstanceIndex; i < (set.CountInstances + set.FirstInstanceIndex); i++)
                {
                    if (i >= root.DoodadInstances.Count)
                        break;
                    instances.Add(root.DoodadInstances[(int)i]);
                }

                foreach (var instance in instances)
                {
                    var model = Cache.Model.Get(instance.File);
                    if (model == null)
                    {
                        model = new Model(instance.File);
                        Cache.Model.Insert(instance.File, model);
                    }

                    if (!model.IsCollidable)
                        continue;
                    var doodadTransformation = Transformation.GetWmoDoodadTransformation(instance, def);
                    int vertOffset = vertices.Count;
                    vertices.AddRange(model.Vertices.Select(vert => Vector3.Transform(vert, doodadTransformation).ToVector3()));
                    foreach (var tri in model.Triangles)
                        triangles.Add(new Triangle<uint>(TriangleType.Wmo, (uint) (tri.V0 + vertOffset),
                                                         (uint) (tri.V1 + vertOffset), (uint) (tri.V2 + vertOffset)));
                }
            }

            foreach (var group in root.Groups)
            {
                if (!group.HasLiquidData)
                    continue;

                for (int y = 0; y < group.LiquidDataHeader.Height; y++)
                {
                    for (int x = 0; x < group.LiquidDataHeader.Width; x++)
                    {
                        if (!group.LiquidDataGeometry.ShouldRender(x, y))
                            continue;

                        var vertOffset = (uint)vertices.Count;
                        vertices.Add(GetLiquidVert(transformation, group.LiquidDataHeader.BaseLocation,
                                                   group.LiquidDataGeometry.HeightMap[x, y], x, y));
                        vertices.Add(GetLiquidVert(transformation, group.LiquidDataHeader.BaseLocation,
                                                   group.LiquidDataGeometry.HeightMap[x + 1, y], x + 1, y));
                        vertices.Add(GetLiquidVert(transformation, group.LiquidDataHeader.BaseLocation,
                                                   group.LiquidDataGeometry.HeightMap[x, y + 1], x, y + 1));
                        vertices.Add(GetLiquidVert(transformation, group.LiquidDataHeader.BaseLocation,
                                                   group.LiquidDataGeometry.HeightMap[x + 1, y + 1], x + 1, y + 1));

                        triangles.Add(new Triangle<uint>(TriangleType.Water, vertOffset, vertOffset + 2, vertOffset + 1));
                        triangles.Add(new Triangle<uint>(TriangleType.Water, vertOffset + 2, vertOffset + 3,
                                                         vertOffset + 1));

                    }
                }
            }
        }
Example #6
0
 public void TestGameWmo()
 {
     MpqManager.Initialize("S:\\WoW");
     var root = new WorldModelRoot("world\\wmo\\Northrend\\Battleground\\ND_BG_Keep01.wmo");
 }
Example #7
0
        public byte[] Build(BaseLog log)
        {
            var wdt = new WDT("World\\maps\\" + Dungeon + "\\" + Dungeon + ".wdt");
            if (!wdt.IsGlobalModel || !wdt.IsValid)
                return null;

            InitializeProgress(12);

            Geometry = new Geometry {Transform = true};
            var model = new WorldModelRoot(wdt.ModelFile);
            Geometry.AddDungeon(model, wdt.ModelDefinition);

            CompleteWorkUnit();

            if (Geometry.Vertices.Count == 0 && Geometry.Triangles.Count == 0)
                throw new InvalidOperationException("Can't build mesh with empty geometry");

            Log = log;
            Context = new RecastContext();
            Context.SetContextHandler(Log);

            // get raw geometry - lots of slowness here
            float[] vertices;
            int[] triangles;
            byte[] areas;
            Geometry.GetRawData(out vertices, out triangles, out areas);
            Geometry.Triangles.Clear();

            float[] bmin, bmax;
            Geometry.CalculateBoundingBox(out bmin, out bmax);
            Geometry.Vertices.Clear();

            // Allocate voxel heightfield where we rasterize our input data to.
            Heightfield hf;
            int width, height;
            Recast.CalcGridSize(bmin, bmax, Config.CellSize, out width, out height);
            if (!Context.CreateHeightfield(out hf, width, height, bmin, bmax, Config.CellSize, Config.CellHeight))
                throw new OutOfMemoryException("CreateHeightfield ran out of memory");

            CompleteWorkUnit();

            // Find triangles which are walkable based on their slope and rasterize them.
            Context.ClearUnwalkableTriangles(Config.WalkableSlopeAngle, ref vertices, ref triangles, areas);
            Context.RasterizeTriangles(ref vertices, ref triangles, ref areas, hf, Config.WalkableClimb);

            CompleteWorkUnit();

            // Once all geometry is rasterized, we do initial pass of filtering to
            // remove unwanted overhangs caused by the conservative rasterization
            // as well as filter spans where the character cannot possibly stand.
            Context.FilterLowHangingWalkableObstacles(Config.WalkableClimb, hf);
            Context.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb, hf);
            Context.FilterWalkableLowHeightSpans(Config.WalkableHeight, hf);

            CompleteWorkUnit();

            // Compact the heightfield so that it is faster to handle from now on.
            // This will result in more cache coherent data as well as the neighbours
            // between walkable cells will be calculated.
            CompactHeightfield chf;
            if (!Context.BuildCompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, hf, out chf))
                throw new OutOfMemoryException("BuildCompactHeightfield ran out of memory");

            CompleteWorkUnit();

            hf.Delete();

            // Erode the walkable area by agent radius.
            if (!Context.ErodeWalkableArea(Config.WalkableRadius, chf))
                throw new OutOfMemoryException("ErodeWalkableArea ran out of memory");
            CompleteWorkUnit();

            // Prepare for region partitioning, by calculating distance field along the walkable surface.
            if (!Context.BuildDistanceField(chf))
                throw new OutOfMemoryException("BuildDistanceField ran out of memory");
            CompleteWorkUnit();

            // Partition the walkable surface into simple regions without holes.
            if (!Context.BuildRegions(chf, Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea))
                throw new OutOfMemoryException("BuildRegions ran out of memory");
            CompleteWorkUnit();

            // Create contours.
            ContourSet cset;
            if (!Context.BuildContours(chf, Config.MaxSimplificationError, Config.MaxEdgeLength, out cset))
                throw new OutOfMemoryException("BuildContours ran out of memory");
            CompleteWorkUnit();

            // Build polygon navmesh from the contours.
            PolyMesh pmesh;
            if (!Context.BuildPolyMesh(cset, Config.MaxVertsPerPoly, out pmesh))
                throw new OutOfMemoryException("BuildPolyMesh ran out of memory");
            CompleteWorkUnit();

            // Build detail mesh.
            PolyMeshDetail dmesh;
            if (!Context.BuildPolyMeshDetail(pmesh, chf, Config.DetailSampleDistance, Config.DetailSampleMaxError, out dmesh))
                throw new OutOfMemoryException("BuildPolyMeshDetail ran out of memory");
            CompleteWorkUnit();

            chf.Delete();
            cset.Delete();

            // Set flags according to area types (e.g. Swim for Water)
            pmesh.MarkAll();

            byte[] meshData;
            if (!Detour.CreateNavMeshData(out meshData, pmesh, dmesh, 0, 0, bmin, bmax, Config.WorldWalkableHeight, Config.WorldWalkableRadius, Config.WorldWalkableClimb, Config.CellSize, Config.CellHeight, Config.TileWidth, null))
            {
                pmesh.Delete();
                dmesh.Delete();
                return null;
            }
            
            CompleteWorkUnit();
            pmesh.Delete();
            dmesh.Delete();
            return meshData;
        }