What am i doing wrong? (Recast) menu

Shout-Out

User Tag List

Results 1 to 5 of 5
  1. #1
    haku43's Avatar Member
    Reputation
    3
    Join Date
    Sep 2009
    Posts
    27
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    What am i doing wrong? (Recast)

    Ok so i am able to generate the navigation data, FindNearestPoly and GeneratePath works.
    I make use of wowmapper to extract ADTs, CritterAI to generate InputGeometry and RecastManaged to generate NavMeshData.

    The problem is that path generated is kinda weird. So here my code:

    Read an .obj file, TriangleMesh
    Code:
     public class MeshLoader
        {
          
            private static int parseFace(string[] chunks, int[] data, int n, int vcnt)
            {
                int j = 0;
                for (int i = 0; i < chunks.Length; i++)
                {
                    var s = chunks[i];
                    if (s == "f") continue;
                    int vi = Convert.ToInt32(s);
                    data[j++] = vi < 0 ? vi + vcnt : vi - 1;
                    if (j >= n)
                        return j;
                }
                return j;
            }
    
            public static TriangleMesh LoadMesh(string filepath)
            {
                var verts = new List<Vector3>();
    
                var tris = new List<int>();
    
                var lines = File.ReadAllLines(filepath);
    
                foreach (var line in lines)
                {
                    var chunks = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (chunks[0] == "v")
                    {
                        Vector3 v3 = new Vector3(float.Parse(chunks[1], System.Globalization.CultureInfo.InvariantCulture), float.Parse(chunks[2], System.Globalization.CultureInfo.InvariantCulture), float.Parse(chunks[3], System.Globalization.CultureInfo.InvariantCulture));
                        verts.Add(v3);
                  
                    }
                    if (chunks[0] == "f")
                    {
                        int[] face = new int[32];
                        var m_vertCount = verts.Count;
                        //// Faces
                        var nv = parseFace(chunks, face, 32, m_vertCount);
                        for (int i = 2; i < nv; ++i)
                        {
                            int a = face[0];
                            int b = face[i - 1];
                            int c = face[i];
                            if (a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount || a == b || b == c || c == a)
                            {
                                continue;
                            }
                            tris.AddRange(new int[3] { a, b, c });
                        }
    
    
                    }
    
    
                }
                //var m_triCount = tris.Count;
    
                //var m_normals = new float[m_triCount * 3];
    
                //for (int i = 0; i < m_triCount * 3; i += 3)
                //{
                //    var v0 = verts[tris[i] * 3];
                //    var v1 = verts[tris[i + 1] * 3];
                //    var v2 = verts[tris[i + 2] * 3];
                //    var e0 = new Vector3(v1.x - v0.x, v1.y - v0.y, v1.x - v0.z);
                //    var e1 = new Vector3(v2.x - v0.x, v2.y - v0.y, v2.x - v0.z);
                //    //float[] n = m_normals[i];
                //    //n[0] = e0[1] * e1[2] - e0[2] * e1[1];
                //    //n[1] = e0[2] * e1[0] - e0[0] * e1[2];
                //    //n[2] = e0[0] * e1[1] - e0[1] * e1[0];
                //    //var d = Math.Sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
                //    //if (d > 0)
                //    //{
                //    //    d = 1.0 / d;
                //    //    n[0] *= d;
                //    //    n[1] *= d;
                //    //    n[2] *= d;
                //    //}
                //}
              
                var mesh = new TriangleMesh(verts.ToArray(), verts.Count, tris.ToArray(), tris.Count / 3);
    
                return mesh;
            }
        }
    Build InputGeometry
    Code:
                        var mesh = MeshLoader.LoadMesh(inputFile);
    
                        //// Create an area buffer that assigns the default area id to all triangles.
                        byte[] areas = NMGen.CreateDefaultAreaBuffer(mesh.triCount);
    
                        //// Create the builder.
                        //// All triangles with a slope over 45.5f will be re-assigned to NMGen.NullArea.
                        InputGeometryBuilder gbuilder = InputGeometryBuilder.Create(mesh, areas, 0);
    
                        //// Build in a single step.
                        gbuilder.BuildAll();
    
                        //// Get the result.
                        InputGeometry geom = gbuilder.Result;
    
                        var data = TiledNavigationMesh.BuildAllTiles(geom, tileX, tileY);
    Build 4x4 NavMeshData[,] (16 tiles per ADT)
    Code:
      NavMesh = new NavMesh();
                QueryFilter = new QueryFilter();
                InputGeom = inputGeom;
                NavMeshParams parameters = new NavMeshParams();
                var bounds = new Vector3(inputGeom.BoundsMin.x, inputGeom.BoundsMin.y, inputGeom.BoundsMin.z);
                parameters.Origin = bounds;// new Vector3(-(32 * BuildConfig.TileSize), -(32 * BuildConfig.TileSize), -(32 * BuildConfig.TileSize));//new Vector3(inputGeom.BoundsMin.x, inputGeom.BoundsMin.y, inputGeom.BoundsMin.z);//WorldOrigin; //new Vector3(-(32 * BuildConfig.TileSize), -(32 * BuildConfig.TileSize), -(32 * BuildConfig.TileSize)); //new Vector3(inputGeom.BoundsMin.x, inputGeom.BoundsMin.y, inputGeom.BoundsMin.z);
                parameters.TileWidth = BuildConfig.TileSize * BuildConfig.CellSize;
                parameters.TileHeight = BuildConfig.TileSize * BuildConfig.CellSize;
                parameters.MaxTiles = 16;// BuildConfig.MaxTiles;
                parameters.MaxPolys = 262144;// BuildConfig.MaxPolysPerTile;
                parameters.MaxNodes = NavMeshParamsMaxNodes;
                //parameters.
                var status = NavMesh.Init(parameters);
                if (!status)
                {
                    Console.WriteLine("Failure to init NavMesh.");
                }
    
                float[] bmin = new[] { InputGeom.BoundsMin.x, InputGeom.BoundsMin.y, InputGeom.BoundsMin.z };
                float[] bmax = new[] { InputGeom.BoundsMax.x, InputGeom.BoundsMax.y, InputGeom.BoundsMax.z };
    
    
                //bmin = new float[3];
                //bmax = new float[3];
    
    
                //bmin[0] = WorldOrigin.X + (BuildConfig.TileSize * tileX);
                //bmin[2] = WorldOrigin.Y + (BuildConfig.TileSize * tileY);
                //bmax[0] = WorldOrigin.X + (BuildConfig.TileSize * (tileX + 1));
                //bmax[2] = WorldOrigin.Y + (BuildConfig.TileSize * (tileY + 1));
    
    
    
                int gw = 0;
                int gh = 0;
    
                Recast.CalcGridSize(bmin, bmax, BuildConfig.CellSize, out gw, out gh);
    
                int ts = (int)BuildConfig.TileSize;
                int tw = (gw + ts - 1) / ts;
                int th = (gh + ts - 1) / ts;
                float tcs = BuildConfig.TileSize * BuildConfig.CellSize;
    
                float[] tileBMin = new float[3];
                float[] tileBMax = new float[3];
    
                var parent = new TileIdentifier(tileX, tileY);
    
                NavMeshData[,] allData = new NavMeshData[4, 4];
                 for (int y = 0; y < th; y++)
                {
                    for (int x = 0; x < tw; x++)
                    {
                        tileBMin[0] = bmin[0] + x * tcs;
                        tileBMin[1] = bmin[1];
                        tileBMin[2] = bmin[2] + y * tcs;
    
                        tileBMax[0] = bmin[0] + (x + 1) * tcs;
                        tileBMax[1] = bmax[1];
                        tileBMax[2] = bmin[2] + (y + 1) * tcs;
    
    
                        TileIdentifier identifier = TileIdentifier.GetSubTile(parent, x, y);
                    
                        //Build the tile mesh and return the data to add to the Nav Mesh
                        NavMeshData data = buildTileMesh(identifier.X, identifier.Y, tileBMin, tileBMax);                                
                        if (data != null)
                        {
    
                            NavMesh.RemoveTile(NavMesh.GetTileRefAt(identifier.X, identifier.Y));
    
                            TileReference result = NavMesh.AddTile(data);
    
                            allData[x, y] = data;
    
                            //TODO: Figure out if we need to use the TileReference thats returned.
                            //data.Dispose();
    
    
                        }
                    }
                }
                return GetTileGroupData(allData);
            }
    Building NavMeshData
    Code:
     private static unsafe NavMeshData buildTileMesh(int tx, int ty, float[] bmin, float[] bmax)
            {
                NavMeshData data = null;
    
                Heightfield Heightfield;
                CompactHeightfield CompactHeightfield;
                ContourSet ContourSet;
                PolyMesh PolyMesh;
                PolyMeshDetail PolyMeshDetail;
    
                byte[] areas;
                var trimesh = InputGeom.ExtractMesh(out areas);
    
                float[] verts = Vector3Util.Flatten(trimesh.verts, trimesh.vertCount);
                int nverts = trimesh.vertCount;
                int ntris = trimesh.triCount;
                int[] tris = trimesh.tris;
    
                //TODO: Make 2 defaults for Build Config (BuildConfig.DefaultSimple && BuildCongif.DefaultTiled)
                BuildConfig.BMin = bmin;
                BuildConfig.BMax = bmax;
                BuildConfig.BMin[0] -= BuildConfig.BorderSize * BuildConfig.CellSize;
                BuildConfig.BMin[2] -= BuildConfig.BorderSize * BuildConfig.CellSize;
                BuildConfig.BMax[0] += BuildConfig.BorderSize * BuildConfig.CellSize;
                BuildConfig.BMax[2] += BuildConfig.BorderSize * BuildConfig.CellSize;
    
                if (!Recast.CreateHeightfield(BuildConfig.Width, BuildConfig.Height, BuildConfig.BMin, BuildConfig.BMax, BuildConfig.CellSize, BuildConfig.CellHeight, out Heightfield))
                    return null;
    
                var TriAreas = new byte[ntris];
    
                Recast.MarkWalkableTriangles(BuildConfig.WalkableSlopeAngle, verts, tris, out TriAreas);
                Recast.RasterizeTriangles(verts, tris, TriAreas, Heightfield);
                Recast.FilterLowHangingWalkableObstacles(BuildConfig.WalkableClimb, Heightfield);
                Recast.FilterLedgeSpans(BuildConfig.WalkableHeight, BuildConfig.WalkableClimb, Heightfield);
                Recast.FilterWalkableLowHeightSpans(BuildConfig.WalkableHeight, Heightfield);
    
                if (!Recast.BuildCompactHeightfield(BuildConfig.WalkableHeight, BuildConfig.WalkableClimb, Heightfield, out CompactHeightfield))
                    return null;
    
                if (!Recast.ErodeWalkableArea(BuildConfig.WalkableRadius, CompactHeightfield))
                    return null;
    
                if (!Recast.BuildDistanceField(CompactHeightfield))
                    return null;
    
                if (!Recast.BuildRegions(CompactHeightfield, BuildConfig.BorderSize, BuildConfig.MinRegionArea, BuildConfig.MergeRegionArea))
                    return null;
    
                if (!Recast.BuildContours(CompactHeightfield, BuildConfig.MaxSimplificationError, BuildConfig.MaxEdgeLen, out ContourSet))
                    return null;
    
                if (ContourSet.NConts == 0)
                    return null;
    
                if (!Recast.BuildPolyMesh(ContourSet, BuildConfig.MaxVertsPerPoly, out PolyMesh))
                    return null;
    
                if (!Recast.BuildPolyMeshDetail(PolyMesh, CompactHeightfield, BuildConfig.DetailSampleDistance, BuildConfig.DetailSampleMaxError, out PolyMeshDetail))
                    return null;
    
                if (BuildConfig.MaxVertsPerPoly <= Detour.MaxVertsPerPolygon)
                {
                    for (int i = 0; i < PolyMesh.NVerts; ++i)
                    {
                        PolyMesh.Verts[i * 3] -= (ushort)BuildConfig.BorderSize;
                        PolyMesh.Verts[(i * 3) + 2] -= (ushort)BuildConfig.BorderSize;
                    }
    
                    if (PolyMesh.NVerts >= 0xffff)
                        return null;
    
                    for (int i = 0; i < PolyMesh.NPolys; ++i)
                    {
                        if (PolyMesh.Areas[i] == (byte)DefaultAreaType.RC_WALKABLE_AREA)
                            PolyMesh.Areas[i] = (byte)SamplePolyAreas.SAMPLE_POLYAREA_GROUND;
    
                        if (PolyMesh.Areas[i] == (byte)SamplePolyAreas.SAMPLE_POLYAREA_GROUND || PolyMesh.Areas[i] == (byte)SamplePolyAreas.SAMPLE_POLYAREA_GROUND || PolyMesh.Areas[i] == (byte)SamplePolyAreas.SAMPLE_POLYAREA_GROUND)
                            PolyMesh.Flags[i] = (byte)SamplePolyFlags.SAMPLE_POLYFLAGS_WALK;
    
                        else if (PolyMesh.Areas[i] == (byte)SamplePolyAreas.SAMPLE_POLYAREA_DOOR)
                            PolyMesh.Flags[i] = (byte)SamplePolyFlags.SAMPLE_POLYFLAGS_WALK | (byte)SamplePolyFlags.SAMPLE_POLYFLAGS_DOOR;
                    }
    
                    NavMeshCreateParams parameters = new NavMeshCreateParams();
                    parameters.Verts = PolyMesh.Verts;
                    parameters.VertCount = PolyMesh.NVerts;
                    parameters.Polys = PolyMesh.Polys;
                    parameters.PolyAreas = PolyMesh.Areas;
                    parameters.PolyFlags = PolyMesh.Flags;
                    parameters.PolyCount = PolyMesh.NPolys;
                    parameters.NVP = PolyMesh.NVP;
                    parameters.DetailMeshes = PolyMeshDetail.Meshes;
                    parameters.DetailVerts = PolyMeshDetail.Verts;
                    parameters.DetailVertsCount = PolyMeshDetail.NVerts;
                    parameters.DetailTris = PolyMeshDetail.Tris;
                    parameters.DetailTriCount = PolyMeshDetail.NTris;
                    parameters.OffMeshConCount = 0;
                    parameters.WalkableHeight = BuildConfig.WalkableHeight;
                    parameters.WalkableRadius = BuildConfig.WalkableRadius;
                    parameters.WalkableClimb = BuildConfig.WalkableClimb;
                    parameters.BMin = new Vector3(bmin[0], bmin[1], bmin[2]);
                    parameters.BMax = new Vector3(bmax[0], bmax[1], bmax[2]);
                    parameters.CellSize = BuildConfig.CellSize;
                    parameters.CellHeight = BuildConfig.CellHeight;
                    parameters.TileX = tx;
                    parameters.TileY = ty;
    
                    parameters.TileSize = (int)BuildConfig.TileSize;
    
                    if (!Detour.CreateNavMeshData(parameters, out data))
                        return null;
                }
    
                //Dispose of temporary Recast object's (Can save them if/when needed)
                TriAreas = null;
                Heightfield.Dispose();
                CompactHeightfield.Dispose();
                ContourSet.Dispose();
                PolyMesh.Dispose();
                PolyMeshDetail.Dispose();
    
                return data;
            }
    Code:
       public class BuildConfig
        {
            public float[] BMax { get; set; }
            public float[] BMin { get; set; }
    
            public const int MaxTiles = 4096;
            public const int MaxPolysPerTile = 1024;
            public const int Width = (int)TileSize;
            public const int Height = (int)TileSize;
            public const int MaxVertsPerPoly = 6;
    
    
            public const int TilesPerMapSide = 64;
            public const float TileSize = (1600.0f / 3.0f);
            private const int TileVoxelSize = 1800;
            /// <summary>
            /// The Center of a full 64x64 map
            /// </summary>
            public const float CenterPoint = (TilesPerMapSide / 2f) * TileSize;
            public static readonly int MinRegionArea = (int)Math.Pow(6, 2);//20;
            public static readonly int MergeRegionArea = (int)Math.Pow(12, 2);//40;
    
            public const float CellSize = TileSize / TileVoxelSize;
            public const float CellHeight = 0.3f;
            public const float WalkableSlopeAngle = 50f;
            public const float MaxSimplificationError = 1.3f;
            public const float DetailSampleDistance = 3f;
            public const float DetailSampleMaxError = 1.25f;
    
            /// <summary>
            /// Height of wow toon
            /// </summary>
            private const float WorldUnitWalkableHeight = 2.1f;//1.652778f;
    
            /// <summary>
            /// Maximum height where slope is not considered
            /// </summary>
            private const float WorldUnitWalkableClimb = 1.0f;
    
            /// <summary>
            /// Radius of wow toon
            /// </summary>
            private const float WorldUnitWalkableRadius = 0.6f;//0.2951389f;
    
            public static readonly int WalkableHeight = (int)Math.Round(WorldUnitWalkableHeight / CellHeight);
            public static readonly int WalkableClimb = (int)Math.Round(WorldUnitWalkableClimb / CellHeight);
            public static readonly int WalkableRadius = (int)Math.Round(WorldUnitWalkableRadius / CellSize);
            public static readonly int MaxEdgeLen = WalkableRadius * 8;
            public static readonly int BorderSize = WalkableRadius + 4;
            public static readonly int TileWidth = TileVoxelSize + (BorderSize * 2);
    
        }
    To initialize NavMesh in game:
    Code:
            private static readonly int NavMeshParamsMaxNodes = 2048;//0x12d2d3;
    
            private static readonly int NavMeshParamsMaxPolys = 1024;//0x800;
    
            private static readonly int NavMeshParamsMaxTiles = 4096;//0x4000;
    
            NavMeshParams navMeshParams = new NavMeshParams();                        
            navMeshParams.MaxTiles = NavMeshParamsMaxTiles;
            navMeshParams.MaxPolys = NavMeshParamsMaxPolys;
            navMeshParams.MaxNodes = NavMeshParamsMaxNodes;
            navMeshParams.TileWidth = 133.3333f;
            navMeshParams.TileHeight = 133.3333f;         
            navMeshParams.Origin = Vector3.Zero;
    Then i add 16 tiles per ADT into this NavMesh, and generate path.

    Detour generate path across that column (see Video) and not straight. What am i doing wrong?
    Video link: http://www.dailymotion.com/video/xut...ence-01-1_auto
    Attached Thumbnails Attached Thumbnails What am i doing wrong? (Recast)-untitled-1-jpg  
    Last edited by haku43; 11-03-2012 at 11:48 AM.

    What am i doing wrong? (Recast)
  2. #2
    namreeb's Avatar Legendary

    Reputation
    668
    Join Date
    Sep 2008
    Posts
    1,029
    Thanks G/R
    8/222
    Trade Feedback
    0 (0%)
    Mentioned
    9 Post(s)
    Tagged
    0 Thread(s)
    I am a bit confused here. In the image the path does NOT go through the column. In the video you linked it sure does seem to, however. Can you post a screenshot of the path(s) in the video from the RecastDemo app?

  3. #3
    haku43's Avatar Member
    Reputation
    3
    Join Date
    Sep 2009
    Posts
    27
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The image demonstrates how the path should look like.

  4. #4
    namreeb's Avatar Legendary

    Reputation
    668
    Join Date
    Sep 2008
    Posts
    1,029
    Thanks G/R
    8/222
    Trade Feedback
    0 (0%)
    Mentioned
    9 Post(s)
    Tagged
    0 Thread(s)
    So you're saying you have taken the parameters used in the demo app where you get good paths and duplicated them in your app and are getting different results? That is indeed very odd. When I had this sort of a problem I had to write an in-game rendering functionality so I could render the meshes in-game.

  5. #5
    berlinermauer's Avatar Master Sergeant
    Reputation
    3
    Join Date
    Mar 2010
    Posts
    89
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Take a look at your mesh using meshReaders meshDisplay Utily. I had weird Navigating and in the add I was using 1 based Triangles like RecastDemo wanted, but Recast uses 0based Triangles!

Similar Threads

  1. What am i doing wrong this time?
    By Snailz in forum World of Warcraft Emulator Servers
    Replies: 10
    Last Post: 01-01-2008, 10:49 AM
  2. What am I doing wrong WoW.exe does not appear on WPE.
    By Eliteplague in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 10-30-2007, 04:21 AM
  3. [Question] errr what am i doing wrong?
    By Demonshade in forum WoW ME Questions and Requests
    Replies: 9
    Last Post: 10-10-2007, 04:22 AM
  4. DynDNS help. What am I doing wrong?
    By xxtennisdudexx in forum World of Warcraft Emulator Servers
    Replies: 21
    Last Post: 09-23-2007, 05:23 PM
  5. what am i doing wrong...
    By tiliqua in forum WoW ME Questions and Requests
    Replies: 2
    Last Post: 09-16-2007, 01:18 AM
All times are GMT -5. The time now is 01:16 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search