示例#1
0
        /// <summary>
        /// Voxelizes the triangles from the provided <see cref="ChunkyTriMesh"/> into the
        /// heightfield.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The chunks that are voxelized is controled by the bounds parameters.
        /// </para>
        /// </remarks>
        /// <param name="context">The build context.</param>
        /// <param name="mesh">The mesh.</param>
        /// <param name="boundsMin">The minimum bounds for the mesh query.</param>
        /// <param name="boundsMax">The maximum bounds for the mesh query.</param>
        /// <param name="flagMergeThreshold">
        /// The distance where the walkable flag is favored over the non-walkable flag.
        /// [Limit: >= 0] [Normal: 1]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool AddTriangles(BuildContext context, ChunkyTriMesh mesh
                                 , Vector3 boundsMin, Vector3 boundsMax
                                 , int flagMergeThreshold)
        {
            if (IsDisposed || mesh == null || mesh.IsDisposed)
            {
                return(false);
            }

            List <ChunkyTriMeshNode> nodeList = new List <ChunkyTriMeshNode>();

            int triCount = mesh.GetChunks(boundsMin.x, boundsMin.z
                                          , boundsMax.x, boundsMax.z
                                          , nodeList);

            if (triCount == 0)
            {
                return(true);
            }

            return(HeightfieldEx.nmhfRasterizeNodes(context.root
                                                    , mesh.verts
                                                    , mesh.tris
                                                    , mesh.areas
                                                    , nodeList.ToArray()
                                                    , nodeList.Count
                                                    , root
                                                    , flagMergeThreshold));
        }
示例#2
0
        /// <summary>
        /// Creates a new heightfield object.
        /// </summary>
        /// <param name="width">The width of the field. [Limit: >= 1] [Units: Cells]</param>
        /// <param name="depth">The depth of the field. [Limit: >= 1] [Units: Cells]</param>
        /// <param name="boundsMin">The minimum bounds of the field's AABB. [Units: World]</param>
        /// <param name="boundsMax">The maximum bounds of the field's AABB. [Units: World]</param>
        /// <param name="xzCellSize">
        /// The xz-plane cell size. [Limit:>= <see cref="NMGen.MinCellSize"/>] [Units: World]
        /// </param>
        /// <param name="yCellSize">
        /// The y-axis span increments. [Limit:>= <see cref="NMGen.MinCellSize"/>] [Units: World]
        /// </param>
        /// <returns>The heightfield, or null on error.</returns>
        public static Heightfield Create(int width, int depth
                                         , Vector3 boundsMin, Vector3 boundsMax
                                         , float xzCellSize, float yCellSize)
        {
            if (width < 1 || depth < 1 ||
                !TriangleMesh.IsBoundsValid(boundsMin, boundsMax) ||
                xzCellSize < NMGen.MinCellSize ||
                yCellSize < NMGen.MinCellSize)
            {
                return(null);
            }

            IntPtr root = HeightfieldEx.nmhfAllocField(width, depth
                                                       , ref boundsMin, ref boundsMax, xzCellSize, yCellSize);

            if (root == IntPtr.Zero)
            {
                return(null);
            }

            return(new Heightfield(root
                                   , width, depth
                                   , boundsMin, boundsMax
                                   , xzCellSize, yCellSize));
        }
示例#3
0
 private static float[] GetVector(Vector3 vector, float[] buffer)
 {
     buffer[0] = vector.x;
     buffer[1] = vector.y;
     buffer[2] = vector.z;
     return(buffer);
 }
 private AreaBoxMarker(string name, int priority, byte area
     , Vector3 boundsMin, Vector3 boundsMax)
     : base(name, priority, area)
 {
     mBoundsMin = boundsMin;
     mBoundsMax = boundsMax;
 }
示例#5
0
 /// <summary>
 /// Moves over an off-mesh connection.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method is minimally tested and documented.
 /// </para>
 /// </remarks>
 /// <param name="connectionRef">The connection polygon reference.</param>
 /// <param name="endpointRefs">Polygon endpoint references. [Length: 2]</param>
 /// <param name="startPosition">The start position.</param>
 /// <param name="endPosition">The end position.</param>
 /// <returns>True if the operation succeeded.</returns>
 public bool MoveOverConnection(uint connectionRef, uint[] endpointRefs
                                , Vector3 startPosition, Vector3 endPosition)
 {
     return(PathCorridorEx.dtpcMoveOverOffmeshConnection(mRoot
                                                         , connectionRef, endpointRefs, ref startPosition, ref endPosition, ref mPosition
                                                         , mQuery.root));
 }
示例#6
0
 public static extern NavStatus dtqQueryPolygons(IntPtr query
                                                 , ref Vector3 position
                                                 , ref Vector3 extents
                                                 , IntPtr filter
                                                 , [In, Out] uint[] resultPolyRefs
                                                 , ref int resultCount
                                                 , int maxResult);
示例#7
0
文件: NavUtil.cs 项目: zwong91/Titan
        /// <summary>
        /// Tests that vector interop behaves as expected.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the test is successful the input and return vectors will be equal in value.
        /// </para>
        /// <para>
        /// This method is used to validate that builds using custom vectors behaves correctly
        /// with interop.  (I.e. The custom vector is data compatible.)
        /// </para>
        /// </remarks>
        /// <param name="v">The input vector.</param>
        /// <returns>
        /// A vector equal to the input vector if interop is functioning as expected.
        /// </returns>
        public static Vector3 TestVector(Vector3 v)
        {
            Vector3 result = new Vector3();

            rcn.InteropUtil.dtvlVectorTest(ref v, ref result);
            return(result);
        }
示例#8
0
 public static extern bool dtpcMoveOverOffmeshConnection(IntPtr corridor
                                                         , uint offMeshConRef
                                                         , [In, Out] uint[] refs // size 2
                                                         , ref Vector3 startPos
                                                         , ref Vector3 endPos
                                                         , ref NavmeshPoint resultPos
                                                         , IntPtr navquery);
示例#9
0
 public static extern NavStatus dtqQueryPolygons(IntPtr query
         , ref Vector3 position
         , ref Vector3 extents
         , IntPtr filter
         , [In, Out] uint[] resultPolyRefs
         , ref int resultCount
         , int maxResult);
示例#10
0
        /// <summary>
        /// Creates a new tile set.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The bounds is normally based on the desired origin of the navigation mesh
        /// and the maximum bounds of the input geometry.
        /// </para>
        /// </remarks>
        /// <param name="boundsMin">The minimum AABB bounds of the set.</param>
        /// <param name="boundsMax">The maximum AABB counds of the set.</param>
        /// <param name="config">The shared NMGen configuration.</param>
        /// <param name="geom">The input geometry.</param>
        /// <returns>A new tile set, or null on error.</returns>
        public static TileSetDefinition Create(Vector3 boundsMin, Vector3 boundsMax
                                               , NMGenParams config
                                               , InputGeometry geom)
        {
            if (config == null || !config.IsValid() ||
                !TriangleMesh.IsBoundsValid(boundsMin, boundsMax) ||
                geom == null ||
                config.tileSize <= 0)
            {
                return(null);
            }

            int w;
            int d;

            NMGen.DeriveSizeOfTileGrid(boundsMin, boundsMax
                                       , config.XZCellSize
                                       , config.tileSize
                                       , out w, out d);

            if (w < 1 || d < 1)
            {
                return(null);
            }

            return(new TileSetDefinition(w, d, boundsMin, boundsMax, config, geom));
        }
示例#11
0
 private AreaBoxMarker(string name, int priority, byte area
                       , Vector3 boundsMin, Vector3 boundsMax)
     : base(name, priority, area)
 {
     mBoundsMin = boundsMin;
     mBoundsMax = boundsMax;
 }
示例#12
0
 public static extern NavStatus dtqFindDistanceToWall(IntPtr query
                                                      , NavmeshPoint position
                                                      , float searchRadius
                                                      , IntPtr filter
                                                      , ref float distance
                                                      , ref Vector3 closestPoint
                                                      , ref Vector3 normal);
示例#13
0
        /// <summary>
        /// Normalizes the specified vector such that its length is equal to one. (Costly method!)
        /// </summary>
        /// <param name="v">The vector.</param>
        /// <returns>A normalized vector.</returns>
        public static Vector3 Normalize(Vector3 v)
        {
            float m = (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);

            if (m < MathUtil.Tolerance)
            {
                m = 1;
            }

            v.x /= m;
            v.y /= m;
            v.z /= m;

            if (Math.Abs(v.x) < MathUtil.Tolerance)
            {
                v.x = 0;
            }
            if (Math.Abs(v.y) < MathUtil.Tolerance)
            {
                v.y = 0;
            }
            if (Math.Abs(v.z) < MathUtil.Tolerance)
            {
                v.z = 0;
            }

            return(v);
        }
示例#14
0
 /// <summary>
 /// Derive the width and depth of a cell grid based on the provided parameters.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method does not validate the parameters.
 /// </para>
 /// </remarks>
 /// <param name="boundsMin">The minimum bounds.</param>
 /// <param name="boundsMax">The maximum bounds.</param>
 /// <param name="xzCellSize">
 /// The cell size on the xz-plane. (<see cref="NMGenParams.XZCellSize"/>)
 /// </param>
 /// <param name="width">The number of cells along the x-axis.</param>
 /// <param name="depth">The number of cells along the z-axis.</param>
 public static void DeriveSizeOfCellGrid(Vector3 boundsMin, Vector3 boundsMax
                                         , float xzCellSize
                                         , out int width, out int depth)
 {
     width = (int)((boundsMax.x - boundsMin.x) / xzCellSize + 0.5f);
     depth = (int)((boundsMax.z - boundsMin.z) / xzCellSize + 0.5f);
 }
示例#15
0
        /// <summary>
        /// Gets the distance between the specified points on the xz-plane. (Ignores y-axis.)
        /// </summary>
        /// <param name="u">Vector u.</param>
        /// <param name="v">Vector v.</param>
        /// <returns>The distance between the specified points on the xz-plane.</returns>
        public static float GetDistance2D(Vector3 u, Vector3 v)
        {
            float dx = v.x - u.x;
            float dz = v.z - u.z;

            return((float)Math.Sqrt(dx * dx + dz * dz));
        }
示例#16
0
        /// <summary>
        /// Determines whether or not the two points are within range of each other based on a
        /// xz-plane radius and a y-axis height.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Essentially, one point defines the centroid of the cylinder and the other is
        /// tested for inclusion.  The height test is <c>(Math.Abs(deltaY) &lt; height)</c>
        /// </para>
        /// </remarks>
        /// <param name="a">Point A.</param>
        /// <param name="b">Point B.</param>
        /// <param name="radius">The allowed radius on the xz-plane.</param>
        /// <param name="height">The allowed y-axis delta.</param>
        /// <returns>
        /// True if the two vectors are within the xz-radius and y-height of each other.
        /// </returns>
        public static bool IsInRange(Vector3 a, Vector3 b, float radius, float height)
        {
            Vector3 d = b - a;

            return((d.x * d.x + d.z * d.z) < radius * radius &&
                   Math.Abs(d.y) < height);
        }
示例#17
0
 /// <summary>
 /// Moves the position and target from their curent locations to the desired locations.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Performs an aggregrate operation in the following order:
 /// </para>
 /// <ol>
 /// <li><see cref="MoveTarget"/></li>
 /// <li><see cref="MovePosition"/></li>
 /// </ol>
 /// <para>
 /// See the documentation of the related functions for details on behavior.
 /// </para>
 /// <para>
 /// This method is more efficient than calling the other methods individually.
 /// </para>
 /// </remarks>
 /// <param name="desiredPosition">The desired position.</param>
 /// <param name="desiredTarget">The desired target.</param>
 public void Move(Vector3 desiredPosition, Vector3 desiredTarget)
 {
     mCorners.cornerCount = PathCorridorEx.dtpcMove(mRoot
                                                    , ref desiredPosition, ref desiredTarget, ref mPosition, ref mTarget
                                                    , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
                                                    , mQuery.root, mFilter.root);
 }
示例#18
0
        /// <summary>
        /// Adds an agent to the manager.
        /// </summary>
        /// <param name="position">
        /// The current position of the agent within the navigation mesh.
        /// </param>
        /// <param name="agentParams">The agent configuration.</param>
        /// <returns>
        /// A reference to the agent object created by the manager, or null on error.
        /// </returns>
        public CrowdAgent AddAgent(Vector3 position
                                   , CrowdAgentParams agentParams)
        {
            if (IsDisposed)
            {
                return(null);
            }

            IntPtr ptr = IntPtr.Zero;
            CrowdAgentCoreState initialState = new CrowdAgentCoreState();

            int index = CrowdManagerEx.dtcAddAgent(root
                                                   , ref position
                                                   , ref agentParams
                                                   , ref ptr
                                                   , ref initialState);

            if (index == -1)
            {
                return(null);
            }

            mAgents[index]     = new CrowdAgent(this, ptr, index);
            agentStates[index] = initialState;

            return(mAgents[index]);
        }
示例#19
0
 /// <summary>
 /// Derives the tile grid location based on the provided world space position.
 /// </summary>
 /// <param name="position">Position</param>
 /// <param name="x">The tile's grid x-location.</param>
 /// <param name="z">The tiles's grid z-location.</param>
 public void DeriveTileLocation(Vector3 position
                                , out int x
                                , out int z)
 {
     x = 0;
     z = 0;
     NavmeshEx.dtnmCalcTileLoc(root, ref position, ref x, ref z);
 }
示例#20
0
 public static extern NavStatus dtqFindPathExt(IntPtr query
                                               , ref NavmeshPoint startPosition
                                               , ref NavmeshPoint endPosition
                                               , [In] ref Vector3 extents
                                               , IntPtr filter
                                               , [In, Out] uint[] resultPath
                                               , ref int pathCount
                                               , int maxPath);
示例#21
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="tx">The x-index of the tile within the tile grid. [Limit: >= 0]</param>
 /// <param name="tz">The z-index of the tile within the tile grid. [Limit: >= 0]</param>
 /// <param name="boundsMin">The minimum bounds of the tile.</param>
 /// <param name="boundsMax">The maximum bounds of the tile.</param>
 public NMGenTileParams(int tx, int tz, Vector3 boundsMin, Vector3 boundsMax)
 {
     // Note: Use properties for auto-clamping.
     TileX     = tx;
     TileZ     = tz;
     BoundsMin = boundsMin;
     BoundsMax = boundsMax;
 }
示例#22
0
 private AreaCylinderMarker(string name, int priority, byte area
                            , Vector3 centerBase, float radius, float height)
     : base(name, priority, area)
 {
     mCenterBase = centerBase;
     mRadius     = Math.Max(0, radius);
     mHeight     = Math.Max(0, height);
 }
示例#23
0
 public static extern NavStatus dtqMoveAlongSurface(IntPtr query
                                                    , NavmeshPoint startPosition
                                                    , [In] ref Vector3 endPosition
                                                    , IntPtr filter
                                                    , ref Vector3 resultPosition
                                                    , [In, Out] uint[] visitedPolyRefs
                                                    , ref int visitedCount
                                                    , int maxVisited);
示例#24
0
        /// <summary>
        /// Returns the normal for the  triangle. (Costly method!)
        /// </summary>
        /// <remarks>
        /// <para>
        /// The normal of a triangle is the vector perpendicular to the triangle's plane
        /// with the direction determined by the
        /// <a href="http://en.wikipedia.org/wiki/Right-hand_rule" target="_blank">
        /// right-handed rule</a>.
        /// </para>
        /// </remarks>
        /// <param name="a">Vertex A of triangle ABC.</param>
        /// <param name="b">Vertex B of triangle ABC.</param>
        /// <param name="c">Vertex C of triangle ABC.</param>
        /// <returns>The normal of the  triangle.</returns>
        public static Vector3 GetNormal(Vector3 a, Vector3 b, Vector3 c)
        {
            // Reference:
            // http://en.wikipedia.org/wiki/Surface_normal#Calculating_a_surface_normal
            // N = (B - A) x (C - A) with the final result normalized.

            return(Vector3Util.Normalize(Vector3Util.Cross(b - a, c - a)));
        }
示例#25
0
 private AreaCylinderMarker(string name, int priority, byte area
     , Vector3 centerBase, float radius, float height)
     : base(name, priority, area)
 {
     mCenterBase = centerBase;
     mRadius = Math.Max(0, radius);
     mHeight = Math.Max(0, height);
 }
示例#26
0
 public static extern int dtpcMoveTargetPosition(IntPtr corridor
                                                 , [In] ref Vector3 npos
                                                 , ref NavmeshPoint pos
                                                 , [In, Out] Vector3[] cornerVerts
                                                 , [In, Out] WaypointFlag[] cornerFlags
                                                 , [In, Out] uint[] cornerPolys
                                                 , int maxCorners
                                                 , IntPtr navquery
                                                 , IntPtr filter);
示例#27
0
 public static extern int dtpcOptimizePathVisibilityExt(IntPtr corridor
                                                        , [In] ref Vector3 next
                                                        , float pathOptimizationRange
                                                        , [In, Out] Vector3[] cornerVerts
                                                        , [In, Out] WaypointFlag[] cornerFlags
                                                        , [In, Out] uint[] cornerPolys
                                                        , int maxCorners
                                                        , IntPtr navquery
                                                        , IntPtr filter);
示例#28
0
        /// <summary>
        /// Moves the target from its curent location to the desired location, adjusting the
        /// corridor as needed to reflect the change.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Behavior:
        /// </para>
        /// <ul>
        /// <li>The movement is constrained to the surface of the navigation mesh.</li>
        /// <li>The corridor is automatically adjusted (shorted or lengthened) and
        /// <see cref="Corners"/> updated in order to remain valid.</li>
        /// <li>The new position will be located in the adjusted corridor's last polygon.</li>
        /// </ul>
        /// <para>
        /// The expected use case: The desired target will be 'near' the corridor. What is
        /// considered 'near' depends on local polygon density, query search extents, etc.
        /// </para>
        /// <para>
        /// The resulting target will differ from the desired target if the desired target is
        /// not on the navigation mesh, or it can't be reached using a local search.
        /// </para>
        /// </remarks>
        /// <param name="desiredTarget">The desired target.</param>
        /// <returns>The result of the move.</returns>
        public NavmeshPoint MoveTarget(Vector3 desiredTarget)
        {
            mCorners.cornerCount = PathCorridorEx.dtpcMoveTargetPosition(mRoot
                                                                         , ref desiredTarget, ref mTarget
                                                                         , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
                                                                         , mQuery.root, mFilter.root);

            return(mTarget);
        }
示例#29
0
 /// <summary>
 /// Loads a new path and target into the corridor.
 /// </summary>
 /// <remarks>
 /// <para>
 /// The current position is expected to be within the first
 /// polygon in the path.  The target is expected to be in the last
 /// polygon.
 /// </para>
 /// </remarks>
 /// <param name="target">The target location within the last polygon of the path.</param>
 /// <param name="path">
 /// The path corridor. [(polyRef) * <paramref name="pathCount"/>]
 /// </param>
 /// <param name="pathCount">
 /// The number of polygons in the path.
 /// [Limits: 0 &lt;= value &lt;= <see cref="MaxPathSize"/>]
 /// </param>
 public void SetCorridor(Vector3 target
                         , uint[] path
                         , int pathCount)
 {
     mCorners.cornerCount = PathCorridorEx.dtpcSetCorridor(mRoot
                                                           , ref target, path, pathCount, ref mTarget
                                                           , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
                                                           , mQuery.root, mFilter.root);
 }
示例#30
0
 public static extern NavStatus dtqRaycast(IntPtr query
                                           , NavmeshPoint startPosition
                                           , [In] ref Vector3 endPosition
                                           , IntPtr filter
                                           , ref float hitParameter
                                           , ref Vector3 hitNormal
                                           , [In, Out] uint[] path
                                           , ref int pathCount
                                           , int maxPath);
示例#31
0
 public static extern NavStatus dtqFindLocalNeighbourhood(IntPtr query
                                                          , uint startPolyRef
                                                          , [In] ref Vector3 position
                                                          , float radius
                                                          , IntPtr filter
                                                          , [In, Out] uint[] resultPolyRefs
                                                          , [In, Out] uint[] resultParentRefs
                                                          , ref int resultCount
                                                          , int maxResult);
 private ConnectionSet(Vector3[] verts, float[] radii
     , byte[] dirs, byte[] areas, ushort[] flags, uint[] userIds)
 {
     this.verts = verts;
     this.radii = radii;
     this.dirs = dirs;
     this.areas = areas;
     this.flags = flags;
     this.userIds = userIds;
 }
 private InputGeometryBuilder(ChunkyTriMeshBuilder builder
     , Vector3 boundsMin
     , Vector3 boundsMax
     , bool isThreadSafe)
 {
     mBuilder = builder;
     mBoundsMin = boundsMin;
     mBoundsMax = boundsMax;
     mIsThreadSafe = isThreadSafe;
 }
示例#34
0
 /// <summary>
 /// Constructs and initializes the structure.
 /// </summary>
 /// <param name="origin">The tile space origin.</param>
 /// <param name="tileWidth">The width of each tile. (Along the x-axis.)</param>
 /// <param name="tileDepth">The depth of each tile. (Along the z-axis.)</param>
 /// <param name="maxTiles">
 /// The maximum number of tiles the navigation mesh can contain.
 /// </param>
 /// <param name="maxPolysPerTile">
 /// The maximum number of polygons each tile can contain.
 /// </param>
 public NavmeshParams(Vector3 origin
                      , float tileWidth, float tileDepth
                      , int maxTiles, int maxPolysPerTile)
 {
     this.origin          = origin;
     this.tileWidth       = Math.Max(MinTileSize, tileWidth);
     this.tileDepth       = Math.Max(MinTileSize, tileDepth);
     this.maxTiles        = Math.Max(1, maxTiles);
     this.maxPolysPerTile = Math.Max(1, maxPolysPerTile);
 }
示例#35
0
 private InputGeometryBuilder(ChunkyTriMeshBuilder builder
                              , Vector3 boundsMin
                              , Vector3 boundsMax
                              , bool isThreadSafe)
 {
     mBuilder      = builder;
     mBoundsMin    = boundsMin;
     mBoundsMax    = boundsMax;
     mIsThreadSafe = isThreadSafe;
 }
 private AreaConvexMarker(string name
     , int priority
     , byte area
     , Vector3[] verts
     , float ymin
     , float ymax)
     : base(name, priority, area)
 {
     this.verts = verts;
     this.ymin = ymin;
     this.ymax = ymax;
 }
示例#37
0
 public void Reset()
 {
     contourCount = 0;
     contours = IntPtr.Zero;
     boundsMax = Vector3Util.Zero;
     boundsMin = Vector3Util.Zero;
     xzCellSize = 0;
     yCellSize = 0;
     width = 0;
     depth = 0;
     borderSize = 0;
 }
        /// <summary>
        /// Adds a single triangle.
        /// </summary>
        /// <param name="vertA">Vertex A of triangle ABC.</param>
        /// <param name="vertB">Vertex B of triangle ABC.</param>
        /// <param name="vertC">Vertex C of triangle ABC.</param>
        /// <param name="area">The triangle area.</param>
        public void AddTriangle(Vector3 vertA, Vector3 vertB, Vector3 vertC, byte area)
        {
            mTris.Add(mVerts.Count);
            mVerts.Add(vertA);

            mTris.Add(mVerts.Count);
            mVerts.Add(vertB);

            mTris.Add(mVerts.Count);
            mVerts.Add(vertC);

            mAreas.Add(area);
        }
示例#39
0
 private TileSetDefinition(int width, int depth
     , Vector3 boundsMin, Vector3 boundsMax
     , NMGenParams config
     , InputGeometry geom)
 {
     // Note: The constructor is private, which is why
     // the references are being stored.
     mBaseConfig = config.Clone();
     mGeometry = geom;
     mWidth = width;
     mDepth = depth;
     mBoundsMin = boundsMin;
     mBoundsMax = boundsMax;
 }
示例#40
0
        /// <summary>
        /// Returns a value suitable for comparing the relative area of two triangles. (E.g. 
        /// Is triangle A larger than triangle B.)
        /// </summary>
        /// <remarks>
        /// <para>
        /// The value returned by this method can be converted to an area as follows: 
        /// <c>Area = Math.sqrt(value) / 2</c>
        /// </para>
        /// <para>
        /// Useful for cheaply comparing the size of triangles.
        /// </para>
        /// </remarks>
        /// <param name="a">Vertex A of triangle ABC.</param>
        /// <param name="b">Vertex B of triangle ABC.</param>
        /// <param name="c">Vertex C of triangle ABC.</param>
        /// <returns>A value suitable for comparing the relative area of two triangles.</returns>
        public static float GetAreaComp(Vector3 a, Vector3 b, Vector3 c)
        {
            // References:
            // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles
            
            // Get directional vectors.
            
            Vector3 u = b - a;  // A -> B
            Vector3 v = c - a;  // A -> C

            // Cross product.
            Vector3 n = new Vector3(u.y * v.z - u.z * v.y
                , -u.x * v.z + u.z * v.x
                , u.x * v.y - u.y * v.x);
            
            return Vector3Util.GetLengthSq(n);
        }
        /// <summary>
        /// Returns the <a href="http://en.wikipedia.org/wiki/Centroid" target="_blank">
        /// centroid</a> of a convex polygon.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Behavior is undefined if the polygon is not convex.
        /// </para>
        /// <para>
        /// Behavior is undefined if the vector being overwritten in the out array is a vertex 
        /// in the polygon.  (Can only happen if the vertices and result arrays are the same object.)
        /// </para>
        /// </remarks>
        /// <param name="vertices">
        /// An array of vertices that contains a representation of a polygon with an  arbitrary 
        /// number of sides.  Wrap direction does not matter.
        /// </param>
        /// <param name="startVert">The index of the first vertex in the polygon.</param>
        /// <param name="vertCount">The number of vertices in the polygon.</param>
        /// <param name="result">The array to store the result in.</param>
        /// <param name="resultVert">The index in the result array to store the result.</param>
        /// <returns>A reference to the result argument.</returns>
        public static Vector3[] GetCentroid(Vector3[] vertices
            , int startVert
            , int vertCount
            , Vector3[] result
            , int resultVert)
        {
            // Reference:
            // http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points

            result[resultVert] = new Vector3(0, 0, 0);
            int length = (startVert+vertCount);

            for (int i = startVert; i < length; i++)
            {
                result[resultVert] += vertices[i];
            }

            result[resultVert].x /= vertCount;
            result[resultVert].y /= vertCount;
            result[resultVert].z /= vertCount;

            return result;
        }
示例#42
0
 /// <summary>
 /// Loads a new path and target into the corridor.
 /// </summary>
 /// <remarks>
 /// <para>
 /// The current position is expected to be within the first
 /// polygon in the path.  The target is expected to be in the last 
 /// polygon.
 /// </para>
 /// </remarks>
 /// <param name="target">The target location within the last polygon of the path.</param>
 /// <param name="path">
 /// The path corridor. [(polyRef) * <paramref name="pathCount"/>]
 /// </param>
 /// <param name="pathCount">
 /// The number of polygons in the path. 
 /// [Limits: 0 &lt;= value &lt;= <see cref="MaxPathSize"/>]
 /// </param>
 public void SetCorridor(Vector3 target
     , uint[] path
     , int pathCount)
 {
     mCorners.cornerCount = PathCorridorEx.dtpcSetCorridor(mRoot
         , ref target, path, pathCount, ref mTarget
         , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
         , mQuery.root, mFilter.root);
 }
示例#43
0
 /// <summary>
 /// Moves the position and target from their curent locations to the desired locations.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Performs an aggregrate operation in the following order:
 /// </para>
 /// <ol>
 /// <li><see cref="MoveTarget"/></li>
 /// <li><see cref="MovePosition"/></li>
 /// </ol>
 /// <para>
 /// See the documentation of the related functions for details on behavior.
 /// </para>
 /// <para>
 /// This method is more efficient than calling the other methods individually.
 /// </para>
 /// </remarks>
 /// <param name="desiredPosition">The desired position.</param>
 /// <param name="desiredTarget">The desired target.</param>
 public void Move(Vector3 desiredPosition, Vector3 desiredTarget)
 {
     mCorners.cornerCount = PathCorridorEx.dtpcMove(mRoot
         , ref desiredPosition, ref desiredTarget, ref mPosition, ref mTarget
         , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
         , mQuery.root, mFilter.root);
 }
示例#44
0
        /// <summary>
        /// Moves the target from its curent location to the desired location, adjusting the 
        /// corridor as needed to reflect the change.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Behavior:
        /// </para>
        /// <ul>
        /// <li>The movement is constrained to the surface of the navigation mesh.</li>
        /// <li>The corridor is automatically adjusted (shorted or lengthened) and 
        /// <see cref="Corners"/> updated in order to remain valid.</li>
        /// <li>The new position will be located in the adjusted corridor's last polygon.</li>
        /// </ul>
        /// <para>
        /// The expected use case: The desired target will be 'near' the corridor. What is 
        /// considered 'near' depends on local polygon density, query search extents, etc.
        /// </para>
        /// <para>
        /// The resulting target will differ from the desired target if the desired target is 
        /// not on the navigation mesh, or it can't be reached using a local search.
        /// </para>
        /// </remarks>
        /// <param name="desiredTarget">The desired target.</param>
        /// <returns>The result of the move.</returns>
        public NavmeshPoint MoveTarget(Vector3 desiredTarget)
        {
            mCorners.cornerCount = PathCorridorEx.dtpcMoveTargetPosition(mRoot
                    , ref desiredTarget, ref mTarget
                    , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
                    , mQuery.root, mFilter.root);

            return mTarget;
        }
示例#45
0
 /// <summary>
 /// Moves over an off-mesh connection.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method is minimally tested and documented.
 /// </para>
 /// </remarks>
 /// <param name="connectionRef">The connection polygon reference.</param>
 /// <param name="endpointRefs">Polygon endpoint references. [Length: 2]</param>
 /// <param name="startPosition">The start position.</param>
 /// <param name="endPosition">The end position.</param>
 /// <returns>True if the operation succeeded.</returns>
 public bool MoveOverConnection(uint connectionRef, uint[] endpointRefs
     , Vector3 startPosition, Vector3 endPosition)
 {
     return PathCorridorEx.dtpcMoveOverOffmeshConnection(mRoot
         , connectionRef, endpointRefs, ref startPosition, ref endPosition, ref mPosition
         , mQuery.root);
 }
示例#46
0
 /// <summary>
 /// Attempts to optimize the path if the specified point is visible from the current 
 /// position.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Improves pathfinding appearance when using meshes that contain non-border.
 /// vertices.  (E.g. Tiled meshes and meshes constructed using multiple areas.)
 /// </para>
 /// <para>
 /// The only time <paramref name="updateCorners"/> should be set to false is if a move 
 /// or other optimization method is to be called next. Otherwise the corner data may 
 /// become invalid.
 /// </para>
 /// <para>
 /// Inaccurate locomotion or dynamic obstacle avoidance can force the agent position 
 /// significantly outside the original corridor. Over time this can result in the 
 /// formation of a non-optimal corridor. A non-optimal corridor can also form near
 /// non-border vertices.  (I.e. At tile corners or area transitions.)
 /// </para>
 /// <para>
 /// This function uses an efficient local visibility search to try to optimize the corridor
 /// between the current position and <paramref name="next"/>.
 /// </para>
 /// <para>
 /// The corridor will change only if <paramref name="next"/> is visible from the 
 /// current position and moving directly toward the point is better than following the 
 /// existing path.
 /// </para>
 /// <para>
 /// The more inaccurate the client movement, the more beneficial this method becomes.  
 /// Simply adjust the frequency of the call to match the needs to the client.
 /// </para>
 /// <para>
 /// This method is not suitable for long distance searches.
 /// </para>
 /// </remarks>
 /// <param name="next">The point to search toward.</param>
 /// <param name="optimizationRange">The maximum range to search. [Limit: > 0]</param>
 /// <param name="updateCorners">True if the corners data should be refreshed.</param>
 public void OptimizePathVisibility(Vector3 next, float optimizationRange
     , bool updateCorners)
 {
     if (updateCorners)
     {
         mCorners.cornerCount = PathCorridorEx.dtpcOptimizePathVisibilityExt(mRoot
             , ref next, optimizationRange
             , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length
             , mQuery.root, mFilter.root);
     }
     else
     {
         PathCorridorEx.dtpcOptimizePathVisibility(
             mRoot, ref next, optimizationRange, mQuery.root, mFilter.root);
     }
 }
示例#47
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="polyRef">
 /// The reference of the polygon that contains the point. (Or zero if not known.)
 /// </param>
 /// <param name="point">The location of the point.</param>
 public NavmeshPoint(uint polyRef, Vector3 point)
 {
     this.polyRef = polyRef;
     this.point = point;
 }
示例#48
0
        /// <summary>
        /// Validates the structure and, optionally, the content of the mesh.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The basic structural validation includes null checks, array size checks, etc.
        /// </para>
        /// <para>
        /// The optional content validation checks that the indices refer to valid vertices 
        /// and that triangles do not contain duplicate vertices.
        /// </para>
        /// </remarks>
        /// <param name="verts">The mesh vertices.</param>
        /// <param name="vertCount">The vertex count.</param>
        /// <param name="tris">The triangle indices.</param>
        /// <param name="triCount">The triangle count.</param>
        /// <param name="includeContent">
        /// If true, the content will be checked.  Otherwise only the structure will be checked.
        /// </param>
        /// <returns>True if the validation tests pass.</returns>
        public static bool IsValid(Vector3[] verts, int vertCount
            , int[] tris, int triCount
            , bool includeContent)
        {
            if (tris == null || verts == null
                || triCount * 3 > tris.Length
                || vertCount > verts.Length
                || triCount < 0 || vertCount < 0)
            {
                return false;
            }

            if (includeContent)
            {
                int length = triCount * 3;

                for (int p = 0; p < length; p += 3)
                {
                    int a = tris[p + 0];
                    int b = tris[p + 1];
                    int c = tris[p + 2];

                    if (a < 0 || a >= vertCount
                        || b < 0 || b >= vertCount
                        || c < 0 || c >= vertCount
                        || a == b || b == c || c == a)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
 /// <summary>
 /// Add a connection.
 /// </summary>
 /// <remarks>
 /// <para>
 /// All values are auto-clamped to valid values.
 /// </para>
 /// </remarks>
 /// <param name="start">The connection start point.</param>
 /// <param name="end">The connection end point.</param>
 /// <param name="radius">The radius of the connection vertices.</param>
 /// <param name="isBidirectional">True if the connection can be traversed in both
 /// directions. (Start to end, end to start.)</param>
 /// <param name="area">The connection area id.</param>
 /// <param name="flags">The connection flags.</param>
 /// <param name="userId">The connection user id.</param>
 public void Add(Vector3 start, Vector3 end, float radius
     , bool isBidirectional, byte area, ushort flags, uint userId)
 {
     mVerts.Add(start);
     mVerts.Add(end);
     mRadii.Add(System.Math.Max(MathUtil.Epsilon, radius));
     mDirs.Add((byte)(isBidirectional ? 1 : 0));
     mAreas.Add(NMGen.ClampArea(area));
     mFlags.Add(flags);
     mUserIds.Add(userId);
 }
示例#50
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="start">The start point.</param>
 /// <param name="end">The end point.</param>
 /// <param name="radius">The radius of the start and end points. [Limit: >0]</param>
 /// <param name="isBidDrectional">True if the connection is bi-directional.</param>
 /// <param name="area">The area. [Limit: &lt;= <see cref="Navmesh.MaxArea"/>].</param>
 /// <param name="flags">The connection flags.</param>
 /// <param name="userId">The id of the off-mesh connection. (User defined.)</param>
 public OffMeshConnection(Vector3 start, Vector3 end
     ,float radius, bool isBidDrectional, byte area, ushort flags, uint userId)
 {
     this.start = start;
     this.end = end;
     this.radius = MathUtil.ClampToPositiveNonZero(radius);
     direction = (byte)(isBidDrectional ? 1 : 0);
     this.area = NavUtil.ClampArea(area);
     this.flags = flags;
     this.userId = userId;
 }
 /// <summary>
 /// Creates a connection set.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Connection sets created using this method are not guarenteed to be valid or
 /// safe for threaded builds.
 /// </para>
 /// <para>
 /// The generated connection set will directly reference the construction
 /// parameters.
 /// </para>
 /// </remarks>
 /// <param name="verts">The connection vertices. [(start, end) * connCount]</param>
 /// <param name="radii">The connection radii. [Length: connCount]</param>
 /// <param name="dirs">The connection direction flags. [Length: connCount]</param>
 /// <param name="areas">The connection areas. [Length: connCount]</param>
 /// <param name="flags">The connection flags. [Length: connCount]</param>
 /// <param name="userIds">The connection user ids. [Length: connCount]</param>
 /// <returns>An unsafe connection set.</returns>
 public static ConnectionSet UnsafeCreate(Vector3[] verts, float[] radii
     , byte[] dirs, byte[] areas, ushort[] flags, uint[] userIds)
 {
     return new ConnectionSet(verts
         , radii
         , dirs
         , areas
         , flags
         , userIds);
 }
        /// <summary>
        /// Gets a copy of the vertex buffer.
        /// </summary>
        /// <param name="buffer">
        /// The buffer to load the results into.
        /// [Length: >= <see cref="NavmeshTileHeader.vertCount"/>]
        /// </param>
        /// <returns>The number of vertices returned.</returns>
        public int GetVerts(Vector3[] buffer)
        {
            if (mOwner.IsDisposed || buffer == null)
                return 0;

            return NavmeshTileEx.dtnmGetTileVerts(mTile
                , buffer
                , buffer.Length);
        }
 internal InputGeometry(ChunkyTriMesh mesh, Vector3 boundsMin, Vector3 boundsMax)
 {
     mBoundsMin = boundsMin;
     mBoundsMax = boundsMax;
     mMesh = mesh;
 }
        /// <summary>
        /// Gets the connections whose start vertex is within the specified bounds.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The out parameters will be null if the return result is zero.
        /// </para>
        /// </remarks>
        /// <param name="xmin">The minimum x-axis bounds.</param>
        /// <param name="zmin">The minimum z-axis bounds.</param>
        /// <param name="xmax">The maximum x-axis bounds.</param>
        /// <param name="zmax">The maximum z-axis bounds.</param>
        /// <param name="rverts">The connection vertices. [(start, end) * connCount]</param>
        /// <param name="rradii">The connection radii. [Length: connCount]</param>
        /// <param name="rdirs">The connection direction flags. [Length: connCount]</param>
        /// <param name="rareas">The connection areas. [Length: connCount]</param>
        /// <param name="rflags">The connection flags. [Length: connCount]</param>
        /// <param name="ruserIds">The connection user ids. [Length: connCount]</param>
        /// <returns>The number of connection returned.</returns>
        public int GetConnections(float xmin, float zmin, float xmax, float zmax
            , out Vector3[] rverts, out float[] rradii
            , out byte[] rdirs, out byte[] rareas, out ushort[] rflags, out uint[] ruserIds)
        {
            rverts = null;
            rradii = null;
            rdirs = null;
            rareas = null;
            rflags = null;
            ruserIds = null;

            if (radii.Length == 0)
                return 0;

            List<Vector3> rlverts = new List<Vector3>();
            List<float> rlradii = new List<float>();
            List<byte> rldirs = new List<byte>();
            List<byte> rlareas = new List<byte>();
            List<ushort> rlflags = new List<ushort>();
            List<uint> rluserIds = new List<uint>();

            for (int i = 0; i < radii.Length; i++)
            {
                Vector3 v = verts[i * 2 + 0];
                if (Rectangle2.Contains(xmin, zmin, xmax, zmax, v.x, v.z))
                {
                    rlverts.Add(v);
                    rlverts.Add(verts[i * 2 + 1]);

                    rlradii.Add(radii[i]);
                    rldirs.Add(dirs[i]);
                    rlareas.Add(areas[i]);
                    rlflags.Add(flags[i]);
                    rluserIds.Add(userIds[i]);
                }
            }

            if (rlradii.Count == 0)
                return 0;

            rverts = rlverts.ToArray();
            rradii = rlradii.ToArray();
            rdirs = rldirs.ToArray();
            rareas = rlareas.ToArray();
            rflags = rlflags.ToArray();
            ruserIds = rluserIds.ToArray();

            return rradii.Length;
        }
        /// <summary>
        /// Adds an arbitrary group of triangles.  
        /// </summary>
        /// <remarks>
        /// <para>
        /// All triangles will default to <see cref="NMGen.MaxArea"/> if the 
        /// <paramref name="areas"/> parameter is null.
        /// </para>
        /// </remarks>
        /// <param name="verts">
        /// The triangle vertices. [Length: >= <paramref name="vertCount"/>]
        /// </param>
        /// <param name="vertCount">The number of vertices. [Length: >= 3]</param>
        /// <param name="tris">
        /// The triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount]
        /// [Length: >= 3 * <paramref name="triCount"/>]
        /// </param>
        /// <param name="areas">
        /// The triangle areas. (Optional) [Length: >= <paramref name="triCount"/>]
        /// </param>
        /// <param name="triCount">The number of triangles. [Limit: > 0]</param>
        /// <returns>True if the triangles were successfully added.</returns>
        public bool AddTriangles(Vector3[] verts, int vertCount
            , int[] tris, byte[] areas, int triCount)
        {
            if (triCount < 1 || vertCount < 3
                || verts == null || verts.Length < vertCount
                || tris == null || tris.Length < triCount * 3
                || areas != null && areas.Length < triCount)
            {
                return false;
            }

            if (areas == null)
                areas = NMGen.CreateDefaultAreaBuffer(triCount);

            int iVertOffset = mVerts.Count;

            if (vertCount == verts.Length)
                mVerts.AddRange(verts);
            else
            {
                mVerts.Capacity += vertCount;

                for (int p = 0; p < vertCount; p++)
                {
                    mVerts.Add(verts[p]);
                }
            }

            int length = triCount * 3;

            mTris.Capacity += length;

            for (int p = 0; p < length; p++)
            {
                mTris.Add(tris[p] + iVertOffset);
            }

            if (areas.Length == triCount)
                mAreas.AddRange(areas);
            else
            {
                mAreas.Capacity += triCount;

                for (int i = 0; i < triCount; i++)
                {
                    mAreas.Add(areas[i]);
                }
            }

            return true;
        }
示例#56
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This constructor assigns the provided arrays to the object.  (No copying.)
 /// </para>
 /// </remarks>
 /// <param name="verts">
 /// The vertices. [Length: >= <typeparamref name="vertCount"/>]
 /// </param>
 /// <param name="vertCount">The number of vertices.</param>
 /// <param name="tris">
 /// The triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount]
 /// [Length: >= (<typeparamref name="triCount"/>) * 3]
 /// </param>
 /// <param name="triCount">The number of triangles.</param>
 public TriangleMesh(Vector3[] verts, int vertCount, int[] tris, int triCount)
 {
     this.verts = verts;
     this.vertCount = vertCount;
     this.tris = tris;
     this.triCount = triCount;
 }
示例#57
0
 /// <summary>
 /// True if the minimum bounds is less than the maximum bounds on all axes.
 /// </summary>
 /// <param name="boundsMin">The minimum AABB bounds.</param>
 /// <param name="boundsMax">The maximum AABB bounds.</param>
 /// <returns>
 /// True if the minimum bounds is less than the maximum bounds on all axes.
 /// </returns>
 public static bool IsBoundsValid(Vector3 boundsMin, Vector3 boundsMax)
 {
     return !(boundsMax.x < boundsMin.x
         || boundsMax.y < boundsMin.y
         || boundsMax.z < boundsMin.z);
 }
示例#58
0
 private void Resize()
 {
     vertCount = 0;
     polyCount = 0;
     maxVertsPerPoly = 0;
     boundsMin = Vector3Util.Zero;
     boundsMax = Vector3Util.Zero;
     xzCellSize = 0;
     yCellSize = 0;
     borderSize = 0;
     walkableHeight = 0;
     walkableStep = 0;
     walkableRadius = 0;
     polys = null;
     verts = null;
     areas = null;
     flags = null;
     regions = null;
 }
示例#59
0
        /// <summary>
        /// Gets the AABB bounds of the mesh.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Do not call this method on an uninitialized mesh.
        /// </para>
        /// </remarks>
        /// <param name="boundsMin">The minimum bounds of the mesh.</param>
        /// <param name="boundsMax">The maximum bounds of the mesh.</param>
        public void GetBounds(out Vector3 boundsMin, out Vector3 boundsMax)
        {
            boundsMin = verts[tris[0]];
            boundsMax = verts[tris[0]];

            for (int i = 1; i < triCount * 3; i++)
            {
                Vector3 v = verts[tris[i]];
                boundsMin.x = Math.Min(boundsMin.x, v.x);
                boundsMin.y = Math.Min(boundsMin.y, v.y);
                boundsMin.z = Math.Min(boundsMin.z, v.z);
                boundsMax.x = Math.Max(boundsMax.x, v.x);
                boundsMax.y = Math.Max(boundsMax.y, v.y);
                boundsMax.z = Math.Max(boundsMax.z, v.z);
            }
        }
示例#60
0
        /// <summary>
        /// Creates an array of vectors from the provided navmesh points.
        /// </summary>
        /// <remarks>
        /// <para>
        /// A new array will be created if the <paramref name="target"/> array is null.
        /// </para>
        /// </remarks>
        /// <param name="source">The source array.</param>
        /// <param name="sourceIndex">The start of the copy in the source.</param>
        /// <param name="target">The target of the copy. (Optional)</param>
        /// <param name="targetIndex">The start copy location within the target.</param>
        /// <param name="count">The number of vectors to copy.</param>
        /// <returns>
        /// An array containing the copied vectors. (A reference to <paramref name="target"/>
        /// if it was non-null.)
        /// </returns>
        public static Vector3[] GetPoints(NavmeshPoint[] source, int sourceIndex
            , Vector3[] target, int targetIndex
            , int count)
        {
            if (target == null)
                target = new Vector3[source.Length + targetIndex];

            for (int i = 0; i < count; i++)
            {
                target[targetIndex + i] = source[sourceIndex + i].point;
            }

            return target;
        }