Exemple #1
0
        public IEnumerable <WMOScene> GenerateWMOs()
        {
            if (MCRW == null || ADT.MODF == null)
            {
                yield break;
            }

            var drawn = new HashSet <uint>();

            for (var i = 0; i < MCRW.MODFEntryIndex.Length; i++)
            {
                var wmo = ADT.MODF.Entries[MCRW.MODFEntryIndex[i]];
                if (drawn.Contains(wmo.UniqueId))
                {
                    continue;
                }
                drawn.Add(wmo.UniqueId);

                if (wmo.MWIDEntryIndex >= ADT.ModelPaths.Count)
                {
                    continue;
                }

                var path  = ADT.ModelPaths[(int)wmo.MWIDEntryIndex];
                var model = new WMORoot(path);

                yield return(GenerateWMOScene(wmo, model));
            }
        }
Exemple #2
0
 public void AddDungeon(WMORoot model, MODF.MODFEntry def)
 {
     var verts = new List<Vector3>();
     var inds = new List<Triangle<uint>>();
     MapChunk.InsertWMOGeometry(def, model, verts, inds);
     AddGeometry(verts, inds);
 }
Exemple #3
0
 public static WMOScene GenerateWMOScene(MODF.MODFEntry wmoDefinition, WMORoot model)
 {
     return(new WMOScene
     {
         Terrain = model.Groups.Select(g => g.GenerateTerrain(wmoDefinition)).OfType <Mesh>() ?? Enumerable.Empty <Mesh>(),
         Doodads = model.GenerateDoodads(wmoDefinition.DoodadSet, wmoDefinition).OfType <Mesh>() ?? Enumerable.Empty <Mesh>(),
         Liquids = model.Groups.Select(g => g.GenerateLiquid(wmoDefinition)).OfType <Mesh>() ?? Enumerable.Empty <Mesh>(),
     });
 }
Exemple #4
0
        private void GenerateWMOs()
        {
            if (ADT.Type != ADTType.Objects || ADT.MODF == null)
            {
                return;
            }

            var drawn = new HashSet <uint>();

            for (int i = 0; i < MCRW.MODFEntryIndex.Length; i++)
            {
                var wmo = ADT.MODF.Entries[MCRW.MODFEntryIndex[i]];
                if (drawn.Contains(wmo.UniqueId))
                {
                    continue;
                }
                drawn.Add(wmo.UniqueId);

                if (wmo.MWIDEntryIndex >= ADT.ModelPaths.Count)
                {
                    continue;
                }

                var path  = ADT.ModelPaths[(int)wmo.MWIDEntryIndex];
                var model = new WMORoot(path);

                if (WMOVertices == null)
                {
                    WMOVertices = new List <Vector3>(1000);
                }
                if (WMOIndices == null)
                {
                    WMOIndices = new List <Triangle <uint> >(1000);
                }

                InsertWMOGeometry(wmo, model, WMOVertices, WMOIndices);
            }
        }
Exemple #5
0
        public void GenerateGlobalModel()
        {
            ModelFile = MWMO.Filenames.FirstOrDefault().Value;
            if (string.IsNullOrEmpty(ModelFile))
            {
                return;
            }

            GlobalModel = new WMORoot(ModelFile);
            if (GlobalModel == null)
            {
                return;
            }

            var placementEntry = MODF.Entries.FirstOrDefault();

            if (placementEntry == null)
            {
                return;
            }

            ModelScene = MapChunk.GenerateWMOScene(placementEntry, GlobalModel)
                         .Transform(Matrix4.CreateRotationX((float)(-Math.PI / 2.0f)));
        }
Exemple #6
0
        public static void InsertWMOGeometry(MODF.MODFEntry wmo, WMORoot model, List <Vector3> vertices, List <Triangle <uint> > indices)
        {
            var transform = Transformation.GetTransform(wmo.Position, wmo.Rotation);

            foreach (var group in model.Groups)
            {
                var vo = (uint)vertices.Count;
                foreach (var v in group.MOVT.Vertices)
                {
                    vertices.Add((Vector3)Vector3.Transform(v, transform));
                }

                for (int i = 0; i < group.MOVI.Indices.Length; i++)
                {
                    if (((byte)group.MOPY.Entries[i].Flags & 0x04) != 0 && group.MOPY.Entries[i].MaterialId != 0xFF)
                    {
                        continue;
                    }

                    var idx = group.MOVI.Indices[i];
                    indices.Add(new Triangle <uint>(TriangleType.Wmo, vo + idx.V0, vo + idx.V1, vo + idx.V2));
                }
            }

            if (wmo.DoodadSet >= 0 && wmo.DoodadSet < model.MODS.Entries.Length)
            {
                var set       = model.MODS.Entries[wmo.DoodadSet];
                var instances = new List <MODD.MODDEntry>((int)set.nDoodads);
                for (uint i = set.FirstInstanceIndex; i < (set.nDoodads + set.FirstInstanceIndex); i++)
                {
                    if (i >= model.MODD.Entries.Length)
                    {
                        break;
                    }
                    instances.Add(model.MODD.Entries[(int)i]);
                }

                foreach (var instance in instances)
                {
                    string path;
                    if (!model.MODN.Filenames.TryGetValue(instance.ofsMODN, out path))
                    {
                        continue;
                    }

                    var doodad = new M2(path);
                    if (!doodad.IsCollidable)
                    {
                        continue;
                    }

                    var doodadTransform = Transformation.GetWmoDoodadTransform(instance, wmo);
                    var vo = (uint)vertices.Count;
                    foreach (var v in doodad.Vertices)
                    {
                        vertices.Add((Vector3)Vector3.Transform(v, doodadTransform));
                    }
                    foreach (var t in doodad.Indices)
                    {
                        indices.Add(new Triangle <uint>(TriangleType.Doodad, t.V0 + vo, t.V1 + vo, t.V2 + vo));
                    }
                }
            }

            foreach (var group in model.Groups)
            {
                if ((group.LiquidVertices == null || group.LiquidVertices.Count == 0) || (group.LiquidIndices == null || group.LiquidIndices.Count == 0))
                {
                    continue;
                }

                var vo = (uint)vertices.Count;
                foreach (var v in group.LiquidVertices)
                {
                    vertices.Add((Vector3)Vector3.Transform(v, transform));
                }
                foreach (var t in group.LiquidIndices)
                {
                    indices.Add(new Triangle <uint>(t.Type, t.V1 + vo, t.V0 + vo, t.V2 + vo));
                }
            }
        }
Exemple #7
0
        public static void InsertWMOGeometry(MODF.MODFEntry wmo, WMORoot model, List<Vector3> vertices, List<Triangle<uint>> indices)
        {
            var transform = Transformation.GetTransform(wmo.Position, wmo.Rotation);
            foreach (var group in model.Groups)
            {
                var vo = (uint)vertices.Count;
                foreach (var v in group.MOVT.Vertices)
                    vertices.Add((Vector3)Vector3.Transform(v, transform));

                for (int i = 0; i < group.MOVI.Indices.Length; i++)
                {
                    if (((byte)group.MOPY.Entries[i].Flags & 0x04) != 0 && group.MOPY.Entries[i].MaterialId != 0xFF)
                        continue;

                    var idx = group.MOVI.Indices[i];
                    indices.Add(new Triangle<uint>(TriangleType.Wmo, vo + idx.V0, vo + idx.V1, vo + idx.V2));
                }
            }

            if (wmo.DoodadSet >= 0 && wmo.DoodadSet < model.MODS.Entries.Length)
            {
                var set = model.MODS.Entries[wmo.DoodadSet];
                var instances = new List<MODD.MODDEntry>((int)set.nDoodads);
                for (uint i = set.FirstInstanceIndex; i < (set.nDoodads + set.FirstInstanceIndex); i++)
                {
                    if (i >= model.MODD.Entries.Length)
                        break;
                    instances.Add(model.MODD.Entries[(int)i]);
                }

                foreach (var instance in instances)
                {
                    string path;
                    if (!model.MODN.Filenames.TryGetValue(instance.ofsMODN, out path))
                        continue;

                    var doodad = new M2(path);
                    if (!doodad.IsCollidable)
                        continue;

                    var doodadTransform = Transformation.GetWmoDoodadTransform(instance, wmo);
                    var vo = (uint)vertices.Count;
                    foreach (var v in doodad.Vertices)
                        vertices.Add((Vector3)Vector3.Transform(v, doodadTransform));
                    foreach (var t in doodad.Indices)
                        indices.Add(new Triangle<uint>(TriangleType.Doodad, t.V0 + vo, t.V1 + vo, t.V2 + vo));
                }
            }

            foreach (var group in model.Groups)
            {
                if ((group.LiquidVertices == null || group.LiquidVertices.Count == 0) || (group.LiquidIndices == null || group.LiquidIndices.Count == 0))
                    continue;

                var vo = (uint)vertices.Count;
                foreach (var v in group.LiquidVertices)
                    vertices.Add((Vector3)Vector3.Transform(v, transform));
                foreach (var t in group.LiquidIndices)
                    indices.Add(new Triangle<uint>(t.Type, t.V1 + vo, t.V0 + vo, t.V2 + vo));
            }
        }
Exemple #8
0
        private void GenerateWMOs()
        {
            if (ADT.Type != ADTType.Objects || ADT.MODF == null)
                return;

            var drawn = new HashSet<uint>();
            for (int i = 0; i < MCRW.MODFEntryIndex.Length; i++)
            {
                var wmo = ADT.MODF.Entries[MCRW.MODFEntryIndex[i]];
                if (drawn.Contains(wmo.UniqueId))
                    continue;
                drawn.Add(wmo.UniqueId);

                if (wmo.MWIDEntryIndex >= ADT.ModelPaths.Count)
                    continue;

                var path = ADT.ModelPaths[(int)wmo.MWIDEntryIndex];
                var model = new WMORoot(path);

                if (WMOVertices == null)
                    WMOVertices = new List<Vector3>(1000);
                if (WMOIndices == null)
                    WMOIndices = new List<Triangle<uint>>(1000);

                InsertWMOGeometry(wmo, model, WMOVertices, WMOIndices);
            }
        }
Exemple #9
0
        static void ReadWMO()
        {
            const string path = @"World\wmo\Northrend\HowlingFjord\DaggercapCave.wmo";
            var wmo = new WMORoot(path);
            using (var sw = new StreamWriter(Path.GetFileNameWithoutExtension(path) + ".obj", false))
            {
                //sw.WriteLine("o " + filename);
                var nf = System.Globalization.CultureInfo.InvariantCulture.NumberFormat;
                int vo = 0;
                foreach (var g in wmo.Groups)
                {
                    foreach (var v in g.MOVT.Vertices)
                        sw.WriteLine("v " + v.X.ToString(nf) + " " + v.Z.ToString(nf) + " " + v.Y.ToString(nf));
                    foreach (var t in g.MOVI.Indices)
                        sw.WriteLine("f " + (t.V0 + vo + 1) + " " + (t.V1 + vo + 1) + " " + (t.V2 + vo + 1));
                    vo += g.MOVT.Vertices.Count();

                    if (g.LiquidVertices == null || g.LiquidIndices == null)
                        continue;

                    foreach (var v in g.LiquidVertices)
                        sw.WriteLine("v " + v.X.ToString(nf) + " " + v.Z.ToString(nf) + " " + v.Y.ToString(nf));
                    foreach (var t in g.LiquidIndices)
                        sw.WriteLine("f " + (t.V0 + vo + 1) + " " + (t.V1 + vo + 1) + " " + (t.V2 + vo + 1));
                    vo += g.LiquidVertices.Count;
                }
            }
        }
Exemple #10
0
        public byte[] Build()
        {
            var wdt = new WDT("World\\maps\\" + Dungeon + "\\" + Dungeon + ".wdt");

            if (!wdt.IsGlobalModel || !wdt.IsValid)
                return null;



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



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

            Geometry.SaveWavefrontObject($"{Dungeon}.obj");
            Context = new RecastContext();

            // get raw geometry - lots of slowness here
            float[] vertices;
            int[] triangles;
            byte[] areas;
            Geometry.GetRawData(out vertices, out triangles, out areas);
            Geometry.Indices.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");

   

            // 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);

          

            // 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);

           

            // 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");

         

            hf.Delete();

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

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

            // 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");
          

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

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

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

            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;
            }        
            pmesh.Delete();
            dmesh.Delete();
           

            if (Directory.Exists(Dungeon))
                Directory.Delete(Dungeon, true);
            Directory.CreateDirectory(Dungeon);
            
            if (meshData != null)
                File.WriteAllBytes(Dungeon + "\\" + Dungeon + ".dmesh", meshData);

            return meshData;
        }