/// <summary> /// Builds a straight path and gets the point farthest along the path that does not exceed /// the specified maximum number of polygons. /// </summary> /// <remarks> /// <para>Limits:</para> /// <ul> /// <li>The path must exist and both the start and goal points must be within the path.</li> /// <li> /// The goal's polygon reference must be in or after the start points polygon reference. /// </li> /// </ul> /// <para> /// <b>Special Case:</b>The result will exceed <paramref name="maxLength"/> if the /// first straight path point is greater than <paramref name="maxLength"/> from the start /// point. /// </para> /// </remarks> /// <param name="start">The start point within the current path.</param> /// <param name="goal">The end point located in or after the start point polygon.</param> /// <param name="maxLength"> /// The maximum allowed number of polygons between the start and target. [Limit: >= 1] /// </param> /// <param name="target">The resulting target point.</param> /// <returns>The straight path index of the target point, or -1 on error.</returns> public int GetLocalTarget(NavmeshPoint start, NavmeshPoint goal, int maxLength , NavmeshQuery query , out NavmeshPoint target) { if (NavUtil.Failed(BuildStraightPath(start, goal, query))) { target = new NavmeshPoint(); return(-1); } int targetIndex = straightCount; // Will be decremented. int iStart = FindPolyRef(0, start.polyRef); // Start at the end of the straight path and search back toward // the start until the number of polygons is less than // maxLength. uint targetRef = 0; do { targetIndex--; targetRef = (straightPath[targetIndex] == 0 ? goal.polyRef : straightPath[targetIndex]); }while (FindPolyRefReverse(iStart, targetRef) - iStart + 1 > maxLength && targetIndex > 0); target = new NavmeshPoint(targetRef, straightPoints[targetIndex]); return(targetIndex); }
List <Entity> itemAttached;//Item that attached to character public CharacterController( Camera cam, NavmeshQuery query, Scene physicsScene, string meshName, ModCharacterSkinDfnXML skin, bool isBot, Mogre.Vector3 initPosition) { camera = cam; this.controlled = !isBot; itemAttached = new List <Entity>(); this.sceneMgr = cam.SceneManager; charaMeshName = meshName; this.physicsScene = physicsScene; physics = physicsScene.Physics; cotrollerManager = physics.ControllerManager; this.query = query; setupBody(initPosition); if (controlled) { setupCamera(cam); } this.skin = skin; setupAnimations(); setupPhysics(); }
//使用现有路径从起点到目标点建立标准的直接路径 public NavStatus BuildStraightPath(NavmeshPoint start, NavmeshPoint goal, NavmeshQuery query) { int iStart = FindPolyRef(0, start.polyRef); int iGoal = -1; if (iStart != -1) { iGoal = FindPolyRefReverse(iStart, goal.polyRef); } if (iGoal == -1) { return(NavStatus.Failure | NavStatus.InvalidParam); } //NavmeshQuery是直通C++的底层寻路 Array.Clear(straightPoints, 0, straightPoints.Length); NavStatus status = query.GetStraightPath(start.point, goal.point , path, iStart, iGoal - iStart + 1 , straightPoints, straightFlags, straightPath, out straightCount); if (straightCount == 0) { return(NavStatus.Failure); } return(status); }
/// <summary> /// Immediately frees all unmanaged resources allocated by the object. /// </summary> public override void RequestDisposal() { // There are no managed or local allocations. if (root != IntPtr.Zero) { mFilter.RequestDisposal(); mFilter = null; mGrid.Dispose(); mGrid = null; mQuery.RequestDisposal(); mQuery = null; mNavmesh = null; mMaxAgentRadius = -1; agentStates = null; for (int i = 0; i < mAgents.Length; i++) { if (mAgents[i] == null) { continue; } mAgents[i].Dispose(); mAgents[i] = null; } CrowdManagerEx.dtcDetourCrowdFree(root); root = IntPtr.Zero; } }
private static Color GetStandardColor(uint polyRef, int polyArea, int colorId , NavmeshQuery query, uint[] markPolys, int markPolyCount) { Color result; if ((query != null && query.IsInClosedList(polyRef)) || IsInList(polyRef, markPolys, markPolyCount) != -1) { result = polygonOverlayColor; } else { if (colorId == -1) { if (polyArea == 0) { result = new Color(0, 0.75f, 1, surfaceAlpha); } else { result = ColorUtil.IntToColor(polyArea, surfaceAlpha); } } else { result = ColorUtil.IntToColor(colorId, surfaceAlpha); } } return(result); }
/// <summary> /// Copy constructor. /// </summary> /// <param name="copy">The group to copy.</param> /// <param name="cloneFilter"> /// If true, the filter will be cloned. Otherwise it will be referenced. /// </param> public NavGroup(NavGroup copy, bool cloneFilter) { this.mesh = copy.mesh; this.query = copy.query; this.crowd = copy.crowd; this.filter = (cloneFilter ? copy.filter.Clone() : copy.filter); this.extents = copy.extents; }
/// <summary> /// Draws a debug visualization of the navigation mesh with the closed nodes highlighted. /// </summary> /// <param name="mesh">The mesh to draw.</param> /// <param name="query">The query which provides the list of closed nodes.</param> public static void Draw(Navmesh mesh, NavmeshQuery query) { int count = mesh.GetMaxTiles(); for (int i = 0; i < count; i++) { Draw(mesh.GetTile(i), query, null, 0, i); } }
/// <summary> /// Constructor. /// </summary> /// <param name="mesh">The navigation mesh used by the query.</param> /// <param name="query">A navigation mesh query.</param> /// <param name="crowd">A crowd.</param> /// <param name="filter">The filter to use with the query.</param> /// <param name="extents">The extents to use with the query.</param> /// <param name="cloneFilter"> /// If true, the filter will be cloned rather than referenced. /// </param> public NavGroup(Navmesh mesh, NavmeshQuery query, CrowdManager crowd , NavmeshQueryFilter filter, Vector3 extents , bool cloneFilter) { this.mesh = mesh; this.query = query; this.crowd = crowd; this.filter = (cloneFilter ? filter.Clone() : filter); this.extents = extents; }
public void Create(Navmesh navmesh) { this._navmesh = navmesh; //一定要保存起来,Navmesh的析构函数会把非托管内存的指针清掉!! NavStatus status = NavmeshQuery.Create(navmesh, 2048, out this._query); if (status != NavStatus.Sucess) { LLogger.Error(status); } }
public Pathfinder(Navmesh navMesh) { _navMesh = navMesh; _filter = new NavmeshQueryFilter(); if (NavUtil.Failed(NavmeshQuery.Create(_navMesh, 1000, out _query))) { throw new Exception("NavQuery failed"); } _pathCorridor = new PathCorridor(1000, 1000, _query, _filter); }
private void Clear() { if (m_Query != null) { m_Query.RequestDisposal(); m_Query = null; } if (m_NavMesh != null) { m_NavMesh.RequestDisposal(); m_NavMesh = null; } }
//从池子里面获取通道,如果没有就需要建立一个(目前都是在NavAgent里面处理的) public PathCorridor GetCorridor(NavmeshPoint position, NavmeshQuery query, NavmeshQueryFilter filter) { if (mCorridors.Count > 0) { PathCorridor corr = mCorridors.Pop(); if (PathCorridor.LoadLocals(corr, position, query, filter)) { return(corr); } return(null); } return(new PathCorridor(mMaxPathSize, mMaxStraightPathSize, query, filter)); }
public List <Waypoint> GenerateWaypointsBetweenTwoPoints(Navmesh navmesh, Vector3 startPos, Vector3 endPos) { List <Waypoint> waypoints = new List <Waypoint>(); NavmeshQuery query; var status = NavmeshQuery.Create(navmesh, 1024, out query); if (!NavUtil.Failed(status)) { org.critterai.Vector3 navStartPointVect; org.critterai.Vector3 navEndPointVect; var navStartPointStatus = query.GetNearestPoint(1, new org.critterai.Vector3(startPos.x, startPos.y, startPos.z), out navStartPointVect); var navEndPointStatus = query.GetNearestPoint(1, new org.critterai.Vector3(startPos.x, startPos.y, startPos.z), out navEndPointVect); if (navStartPointStatus == NavStatus.Sucess && navEndPointStatus == NavStatus.Sucess) { NavmeshPoint navStartPoint = new NavmeshPoint(1, new org.critterai.Vector3(startPos.x, startPos.y, startPos.z)); NavmeshPoint navEndPoint = new NavmeshPoint(1, new org.critterai.Vector3(endPos.x, endPos.y, endPos.z)); uint[] path = new uint[1024]; int pathCount; status = query.FindPath(navStartPoint, navEndPoint, new NavmeshQueryFilter(), path, out pathCount); if (!NavUtil.Failed(status)) { const int MaxStraightPath = 4; int wpCount; org.critterai.Vector3[] wpPoints = new org.critterai.Vector3[MaxStraightPath]; uint[] wpPath = new uint[MaxStraightPath]; WaypointFlag[] wpFlags = new WaypointFlag[MaxStraightPath]; status = query.GetStraightPath(navStartPoint.point, navEndPoint.point , path, 0, pathCount, wpPoints, wpFlags, wpPath , out wpCount); if (!NavUtil.Failed(status) && wpCount > 0) { foreach (var wp in wpPoints) { Mogre.Vector3 wayPointPos = new Vector3(wp.x, wp.y, wp.z); waypoints.Add(new Waypoint(wayPointPos, new Vector3())); } } } } } return(waypoints); }
/// <summary> /// Constructor. /// </summary> /// <remarks> /// <para> /// <b>Important:</b> The <see cref="Reset"/> method must be called before the corridor /// can be used. (That is how the position is set.) /// </para> /// <para> /// Due to internal optimizations, the maximum number of detectable corners will be /// <c>(<paramref name="maxCorners"/> - 1)</c>. /// </para> /// <para>The query and filter parameters can be set to null. This supports the ability /// to create pools of re-usable path corridor objects. But it means that care needs to /// be taken not to use the corridor until query and filter objects have been set. /// See <see cref="ReleaseLocals"/> and <see cref="LoadLocals"/> for pool related utility /// functions. /// </para> /// </remarks> /// <param name="maxPathSize"> /// The maximum path size that can be handled by the object. [Limit: >= 1] /// </param> /// <param name="maxCorners"> /// The maximum number of corners the corner buffer can hold. [Limit: >= 2] /// </param> /// <param name="query">The query to be used by the corridor.</param> /// <param name="filter">The query filter to be used by the corridor.</param> public PathCorridor(int maxPathSize, int maxCorners , NavmeshQuery query, NavmeshQueryFilter filter) { maxPathSize = Math.Max(1, maxPathSize); mRoot = PathCorridorEx.dtpcAlloc(maxPathSize); if (mRoot == IntPtr.Zero) { mMaxPathSize = 0; return; } mQuery = query; mFilter = filter; mMaxPathSize = maxPathSize; mCorners = new CornerData(Math.Max(2, maxCorners)); }
/// <summary> /// Sets the specified resources and resets the corridor. /// </summary> /// <remarks> /// <para> /// This method is useful when pooling path corridors for use by mulitple clients. /// </para> /// <para> /// See <see cref="Reset"/> for information on the effect of the reset. /// </para> /// <para> /// Existing references will be replaced by the new references. /// </para> /// <para> /// This method cannot be used to set references to null. Attempting to do so will result /// in a failure. /// </para> /// </remarks> /// <param name="corridor">The corridor to update.</param> /// <param name="position">The position to reset to corridor to.</param> /// <param name="query">The query object to use.</param> /// <param name="filter">The filter object to use.</param> /// <returns>True if successful.</returns> public static bool LoadLocals(PathCorridor corridor, NavmeshPoint position , NavmeshQuery query, NavmeshQueryFilter filter) { // Basic checks first. if (position.polyRef == 0 || corridor == null || query == null || filter == null) { return(false); } // Validate optional parameters. // Assign and reset. corridor.mQuery = query; corridor.mFilter = filter; corridor.Reset(position); return(true); }
private CrowdManager(IntPtr crowd, Navmesh navmesh, int maxAgents, float maxAgentRadius) : base(AllocType.External) { mMaxAgentRadius = maxAgentRadius; mNavmesh = navmesh; root = crowd; mAgents = new CrowdAgent[maxAgents]; agentStates = new CrowdAgentCoreState[maxAgents]; IntPtr ptr = CrowdManagerEx.dtcGetFilter(root); mFilter = new NavmeshQueryFilter(ptr, AllocType.ExternallyManaged); ptr = CrowdManagerEx.dtcGetGrid(root); mGrid = new CrowdProximityGrid(ptr); ptr = CrowdManagerEx.dtcGetNavMeshQuery(root); mQuery = new NavmeshQuery(ptr, true, AllocType.ExternallyManaged); }
/// <summary> /// Gets a standard corridor from the pool. (Or creates one if none is available.) /// </summary> /// <remarks> /// <para> /// The corridor maximum path will equal <see cref="MaxPathSize"/>, and maximum corners /// will equal <see cref="MaxStraightPathSize"/> . /// </para> /// </remarks> /// <param name="query">The query to assign to the corridor.</param> /// <param name="filter">The filter to assign to the corridor.</param> /// <returns>A standard corridor, or null on error.</returns> public PathCorridor GetCorridor(NavmeshPoint position, NavmeshQuery query, NavmeshQueryFilter filter) { if (mCorridors.Count > 0) { PathCorridor corr = mCorridors.Pop(); if (PathCorridor.LoadLocals(corr, position, query, filter)) return corr; return null; } return new PathCorridor(mMaxPathSize, mMaxStraightPathSize, query, filter); }
public void Dispose() { this._query = null; this._navmesh = null; //让gc调用析构函数 }
public void CreateQuery(float fMoveSpeed, float fTurnSpeed) { this.mTurnSpeed = fTurnSpeed; this.mMoveSpeed = fMoveSpeed; NavStatus status = NavmeshQuery.Create(navmesh, mMaxQueryNodes, out query); if ((status & NavStatus.Sucess) == 0) { Debug.LogError( fileName + ": Aborted initialization. Failed query creation: " + status.ToString()); mCrowdManager = null; return; } mCrowdManager = CrowdManager.Create(mMaxCrowdAgents, mMaxAgentRadius, navmesh); if (mCrowdManager == null) { Debug.LogError(fileName + ": Aborted initialization. Failed crowd creation."); } CrowdAvoidanceParams mCrowdParam = CrowdAvoidanceParams.CreateStandardMedium(); mCrowdManager.SetAvoidanceConfig(0, mCrowdParam); mCrowdAgentParams = new CrowdAgentParams(); mCrowdAgentParams.avoidanceType = 0; mCrowdAgentParams.collisionQueryRange = 3.2f; mCrowdAgentParams.height = 1.8f; mCrowdAgentParams.maxAcceleration = 8.0f; mCrowdAgentParams.maxSpeed = this.mMoveSpeed; mCrowdAgentParams.pathOptimizationRange = 12.0f; mCrowdAgentParams.radius = 1.0f; mCrowdAgentParams.separationWeight = 2.0f; mCrowdAgentParams.updateFlags = CrowdUpdateFlags.AnticipateTurns | CrowdUpdateFlags.ObstacleAvoidance | CrowdUpdateFlags.CrowdSeparation | CrowdUpdateFlags.OptimizeVis | CrowdUpdateFlags.OptimizeTopo; polyResult = new uint[300]; pointResult = new Vector3[300]; tileBufferPoints = new Vector3[3000]; pointResultBuffer = new Vector3[300]; polyResultBuffer = new uint[300]; NavmeshTile tile = navmesh.GetTile(0); int count = tile.GetVerts(tileBufferPoints); Debug.Log("Tile " + tile.GetTileRef() + " count:" + count); if (count > 3000) { tileBufferPoints = new Vector3[count]; } tileBufferRef = -1; //NavmeshPoly[] polys=new NavmeshPoly[3000]; //int polyCount; //polyCount=tile.GetPolys(polys); //for (int i = 0; i < polyCount; i++) //{ // NavmeshPoly poly = polys[i]; // //if (poly.Type == NavmeshPolyType.OffMeshConnection) // { // Debug.Log("Poly" + i+"type"+poly.Type.ToString()); // } //} }
public NavManager CreateManager() { if (!(mNavmeshData && NavmeshData.HasNavmesh)) { Debug.LogError(name + ": Aborted initialization. Navigation mesh not available."); return(null); } if (!mAvoidanceSet || !mGroupsSettings) { Debug.LogError( name + ": Aborted initialization. Avoidance and/or agent groups not available."); return(null); } Navmesh navmesh = NavmeshData.GetNavmesh(); NavmeshQuery query; NavStatus status = NavmeshQuery.Create(navmesh, mMaxQueryNodes, out query); if ((status & NavStatus.Sucess) == 0) { Debug.LogError( name + ": Aborted initialization. Failed query creation: " + status.ToString()); return(null); } CrowdManager crowd = CrowdManager.Create(mMaxCrowdAgents, mMaxAgentRadius, navmesh); if (crowd == null) { Debug.LogError(name + ": Aborted initialization. Failed crowd creation."); return(null); } for (int i = 0; i < CrowdManager.MaxAvoidanceParams; i++) { crowd.SetAvoidanceConfig(i, mAvoidanceSet[i]); } NavGroup mGroup = new NavGroup(navmesh, query, crowd, crowd.QueryFilter, mExtents, false); int count = mGroupsSettings.GroupCount; Dictionary <byte, NavAgentGroup> mAgentGroups = new Dictionary <byte, NavAgentGroup>(count); for (int i = 0; i < count; i++) { byte groupId; NavAgentGroup group = mGroupsSettings.CreateAgentGroup(i, mMaxPath, mMaxStraightPath, out groupId); group.angleAt = mAngleAt; group.heightTolerance = mHeightTolerance; group.radiusAt = mRadiusAt; group.radiusNear = mRadiusNear; group.turnThreshold = mTurnThreshold; mAgentGroups.Add(groupId, group); } return(NavManager.Create(mMaxAgents, mGroup, mAgentGroups)); }
//创作一个新的直接路径,并且沿路获取点 public int GetLocalTarget(NavmeshPoint start, NavmeshPoint goal, int maxLength, NavmeshQuery query, out NavmeshPoint target) { if (NavUtil.Failed(BuildStraightPath(start, goal, query))) { target = new NavmeshPoint(); return(-1); } int targetIndex = straightCount; int iStart = FindPolyRef(0, start.polyRef); uint targetRef = 0; do { targetIndex--; targetRef = (straightPath[targetIndex] == 0 ? goal.polyRef : straightPath[targetIndex]); }while (FindPolyRefReverse(iStart, targetRef) - iStart + 1 > maxLength && targetIndex > 0); target = new NavmeshPoint(targetRef, straightPoints[targetIndex]); return(targetIndex); }
/// <summary> /// Builds a standard straight path from the start to the goal point using the exiting path. /// </summary> /// <remarks> /// <para>Limits:</para> /// <ul> /// <li>The path must exist and both the start and goal points must be within the path.</li> /// <li> /// The goal's polygon reference must be in or after the start points polygon reference. /// </li> /// </ul> /// </remarks> /// <param name="start">The start point.</param> /// <param name="goal">The goal point.</param> /// <returns>The status of the operation.</returns> public NavStatus BuildStraightPath(NavmeshPoint start, NavmeshPoint goal, NavmeshQuery query) { int iStart = FindPolyRef(0, start.polyRef); int iGoal = -1; if (iStart != -1) iGoal = FindPolyRefReverse(iStart, goal.polyRef); if (iGoal == -1) return (NavStatus.Failure | NavStatus.InvalidParam); NavStatus status = query.GetStraightPath(start.point, goal.point , path, iStart, iGoal - iStart + 1 , straightPoints, straightFlags, straightPath, out straightCount); if (straightCount == 0) return NavStatus.Failure; return status; }
/// <summary> /// Draws a debug visualization of an individual navmesh tile. /// </summary> /// <remarks> /// <para> /// The tile will be checked to see if it is in use before it is drawn. So there is no /// need for caller to do so. /// </para> /// </remarks> private static void Draw(NavmeshTile tile , NavmeshQuery query, uint[] markPolys, int markPolyCount , int colorId) { NavmeshTileHeader header = tile.GetHeader(); // Keep this check. Less trouble for clients. if (header.polyCount < 1) return; DebugDraw.SimpleMaterial.SetPass(0); uint polyBase = tile.GetBasePolyRef(); NavmeshPoly[] polys = new NavmeshPoly[header.polyCount]; tile.GetPolys(polys); Vector3[] verts = new Vector3[header.vertCount]; tile.GetVerts(verts); NavmeshDetailMesh[] meshes = new NavmeshDetailMesh[header.detailMeshCount]; tile.GetDetailMeshes(meshes); byte[] detailTris = new byte[header.detailTriCount * 4]; tile.GetDetailTris(detailTris); Vector3[] detailVerts = new Vector3[header.detailVertCount]; tile.GetDetailVerts(detailVerts); GL.Begin(GL.TRIANGLES); for (int i = 0; i < header.polyCount; i++) { NavmeshPoly poly = polys[i]; if (poly.Type == NavmeshPolyType.OffMeshConnection) continue; NavmeshDetailMesh mesh = meshes[i]; Color color = GetStandardColor(polyBase | (uint)i , poly.Area, colorId , query, markPolys, markPolyCount); GL.Color(color); for (int j = 0; j < mesh.triCount; j++) { int pTri = (int)(mesh.triBase + j) * 4; for (int k = 0; k < 3; k++) { // Note: iVert and pVert refer to different // arrays. int iVert = detailTris[pTri + k]; if (iVert < poly.vertCount) { // Get the vertex from the main vertices. int pVert = poly.indices[iVert]; GL.Vertex(verts[pVert]); } else { // Get the vertex from the detail vertices. int pVert = (int) (mesh.vertBase + iVert - poly.vertCount); GL.Vertex(detailVerts[pVert]); } } } } GL.End(); NavmeshLink[] links = new NavmeshLink[header.maxLinkCount]; tile.GetLinks(links); GL.Begin(GL.LINES); DrawPolyBoundaries(header , polys , verts , meshes , detailTris , detailVerts , links , new Color(0, 0.2f, 0.25f, 0.13f) , true); DrawPolyBoundaries(header , polys , verts , meshes , detailTris , detailVerts , links , new Color(0.65f, 0.2f, 0, 0.9f) , false); if (header.connCount == 0) { GL.End(); return; } NavmeshConnection[] conns = new NavmeshConnection[header.connCount]; tile.GetConnections(conns); for (int i = 0; i < header.polyCount; i++) { NavmeshPoly poly = polys[i]; if (poly.Type != NavmeshPolyType.OffMeshConnection) continue; Color color = GetStandardColor(polyBase | (uint)i , poly.Area, colorId , query, markPolys, markPolyCount); // Note: Alpha of less than one doesn't look good because connections tend to // overlay a lot of geometry, resulting is off color transitions. color.a = 1; GL.Color(color); NavmeshConnection conn = conns[i - header.connBase]; Vector3 va = verts[poly.indices[0]]; Vector3 vb = verts[poly.indices[1]]; // Check to see if start and end end-points have links. bool startSet = false; bool endSet = false; for (uint k = poly.firstLink; k != Navmesh.NullLink; k = links[k].next) { if (links[k].edge == 0) startSet = true; if (links[k].edge == 1) endSet = true; } // For linked endpoints: Draw a line between on-mesh location and endpoint, // and draw circle at the endpoint. // For un-linked endpoints: Draw a small red x-marker. if (startSet) { GL.Vertex(va); GL.Vertex(conn.endpoints[0]); DebugDraw.AppendCircle(conn.endpoints[0], conn.radius); } else { GL.Color(Color.red); DebugDraw.AppendXMarker(conn.endpoints[0], 0.1f); GL.Color(color); } if (endSet) { GL.Vertex(vb); GL.Vertex(conn.endpoints[1]); DebugDraw.AppendCircle(conn.endpoints[1], conn.radius); } else { GL.Color(Color.red); DebugDraw.AppendXMarker(conn.endpoints[1], 0.1f); GL.Color(color); } DebugDraw.AppendArc(conn.endpoints[0], conn.endpoints[1] , 0.25f , conn.IsBiDirectional ? 0.6f : 0 , 0.6f); } GL.End(); }
private static Color GetStandardColor(uint polyRef, int polyArea, int colorId , NavmeshQuery query, uint[] markPolys, int markPolyCount) { Color result; if ((query != null && query.IsInClosedList(polyRef)) || IsInList(polyRef, markPolys, markPolyCount) != -1) { result = polygonOverlayColor; } else { if (colorId == -1) { if (polyArea == 0) result = new Color(0, 0.75f, 1, surfaceAlpha); else result = ColorUtil.IntToColor(polyArea, surfaceAlpha); } else result = ColorUtil.IntToColor(colorId, surfaceAlpha); } return result; }
/// <summary> /// Draws a debug visualization of an individual navmesh tile. /// </summary> /// <remarks> /// <para> /// The tile will be checked to see if it is in use before it is drawn. So there is no /// need for caller to do so. /// </para> /// </remarks> private static void Draw(NavmeshTile tile , NavmeshQuery query, uint[] markPolys, int markPolyCount , int colorId) { NavmeshTileHeader header = tile.GetHeader(); // Keep this check. Less trouble for clients. if (header.polyCount < 1) { return; } DebugDraw.SimpleMaterial.SetPass(0); uint polyBase = tile.GetBasePolyRef(); NavmeshPoly[] polys = new NavmeshPoly[header.polyCount]; tile.GetPolys(polys); Vector3[] verts = new Vector3[header.vertCount]; tile.GetVerts(verts); NavmeshDetailMesh[] meshes = new NavmeshDetailMesh[header.detailMeshCount]; tile.GetDetailMeshes(meshes); byte[] detailTris = new byte[header.detailTriCount * 4]; tile.GetDetailTris(detailTris); Vector3[] detailVerts = new Vector3[header.detailVertCount]; tile.GetDetailVerts(detailVerts); GL.Begin(GL.TRIANGLES); for (int i = 0; i < header.polyCount; i++) { NavmeshPoly poly = polys[i]; if (poly.Type == NavmeshPolyType.OffMeshConnection) { continue; } NavmeshDetailMesh mesh = meshes[i]; Color color = GetStandardColor(polyBase | (uint)i , poly.Area, colorId , query, markPolys, markPolyCount); GL.Color(color); for (int j = 0; j < mesh.triCount; j++) { int pTri = (int)(mesh.triBase + j) * 4; for (int k = 0; k < 3; k++) { // Note: iVert and pVert refer to different // arrays. int iVert = detailTris[pTri + k]; if (iVert < poly.vertCount) { // Get the vertex from the main vertices. int pVert = poly.indices[iVert]; GL.Vertex(verts[pVert]); } else { // Get the vertex from the detail vertices. int pVert = (int) (mesh.vertBase + iVert - poly.vertCount); GL.Vertex(detailVerts[pVert]); } } } } GL.End(); NavmeshLink[] links = new NavmeshLink[header.maxLinkCount]; tile.GetLinks(links); GL.Begin(GL.LINES); DrawPolyBoundaries(header , polys , verts , meshes , detailTris , detailVerts , links , new Color(0, 0.2f, 0.25f, 0.13f) , true); DrawPolyBoundaries(header , polys , verts , meshes , detailTris , detailVerts , links , new Color(0.65f, 0.2f, 0, 0.9f) , false); if (header.connCount == 0) { GL.End(); return; } NavmeshConnection[] conns = new NavmeshConnection[header.connCount]; tile.GetConnections(conns); for (int i = 0; i < header.polyCount; i++) { NavmeshPoly poly = polys[i]; if (poly.Type != NavmeshPolyType.OffMeshConnection) { continue; } Color color = GetStandardColor(polyBase | (uint)i , poly.Area, colorId , query, markPolys, markPolyCount); // Note: Alpha of less than one doesn't look good because connections tend to // overlay a lot of geometry, resulting is off color transitions. color.a = 1; GL.Color(color); NavmeshConnection conn = conns[i - header.connBase]; Vector3 va = verts[poly.indices[0]]; Vector3 vb = verts[poly.indices[1]]; // Check to see if start and end end-points have links. bool startSet = false; bool endSet = false; for (uint k = poly.firstLink; k != Navmesh.NullLink; k = links[k].next) { if (links[k].edge == 0) { startSet = true; } if (links[k].edge == 1) { endSet = true; } } // For linked endpoints: Draw a line between on-mesh location and endpoint, // and draw circle at the endpoint. // For un-linked endpoints: Draw a small red x-marker. if (startSet) { GL.Vertex(va); GL.Vertex(conn.endpoints[0]); DebugDraw.AppendCircle(conn.endpoints[0], conn.radius); } else { GL.Color(Color.red); DebugDraw.AppendXMarker(conn.endpoints[0], 0.1f); GL.Color(color); } if (endSet) { GL.Vertex(vb); GL.Vertex(conn.endpoints[1]); DebugDraw.AppendCircle(conn.endpoints[1], conn.radius); } else { GL.Color(Color.red); DebugDraw.AppendXMarker(conn.endpoints[1], 0.1f); GL.Color(color); } DebugDraw.AppendArc(conn.endpoints[0], conn.endpoints[1] , 0.25f , conn.IsBiDirectional ? 0.6f : 0 , 0.6f); } GL.End(); }
/// <summary> /// Builds a straight path and gets the point farthest along the path that does not exceed /// the specified maximum number of polygons. /// </summary> /// <remarks> /// <para>Limits:</para> /// <ul> /// <li>The path must exist and both the start and goal points must be within the path.</li> /// <li> /// The goal's polygon reference must be in or after the start points polygon reference. /// </li> /// </ul> /// <para> /// <b>Special Case:</b>The result will exceed <paramref name="maxLength"/> if the /// first straight path point is greater than <paramref name="maxLength"/> from the start /// point. /// </para> /// </remarks> /// <param name="start">The start point within the current path.</param> /// <param name="goal">The end point located in or after the start point polygon.</param> /// <param name="maxLength"> /// The maximum allowed number of polygons between the start and target. [Limit: >= 1] /// </param> /// <param name="target">The resulting target point.</param> /// <returns>The straight path index of the target point, or -1 on error.</returns> public int GetLocalTarget(NavmeshPoint start, NavmeshPoint goal, int maxLength , NavmeshQuery query , out NavmeshPoint target) { if (NavUtil.Failed(BuildStraightPath(start, goal, query))) { target = new NavmeshPoint(); return -1; } int targetIndex = straightCount; // Will be decremented. int iStart = FindPolyRef(0, start.polyRef); // Start at the end of the straight path and search back toward // the start until the number of polygons is less than // maxLength. uint targetRef = 0; do { targetIndex--; targetRef = (straightPath[targetIndex] == 0 ? goal.polyRef : straightPath[targetIndex]); } while (FindPolyRefReverse(iStart, targetRef) - iStart + 1 > maxLength && targetIndex > 0); target = new NavmeshPoint(targetRef, straightPoints[targetIndex]); return targetIndex; }
public void createScene() { // set background and some fog AdvancedMogreFramework.Singleton.m_pViewport.BackgroundColour = new ColourValue(1.0f, 1.0f, 0.8f); m_pSceneMgr.SetFog(FogMode.FOG_LINEAR, new ColourValue(1.0f, 1.0f, 0.8f), 0, 15, 100); // set shadow properties m_pSceneMgr.ShadowTechnique = ShadowTechnique.SHADOWTYPE_TEXTURE_MODULATIVE; m_pSceneMgr.ShadowColour = new ColourValue(0.5f, 0.5f, 0.5f); m_pSceneMgr.SetShadowTextureSize(1024); m_pSceneMgr.ShadowTextureCount = 1; // disable default camera control so the character can do its own m_pCameraMan.setStyle(CameraStyle.CS_MANUAL); // use a small amount of ambient lighting m_pSceneMgr.AmbientLight = new ColourValue(0.3f, 0.3f, 0.3f); // add a bright light above the scene Light light = m_pSceneMgr.CreateLight(); light.Type = (Light.LightTypes.LT_POINT); light.Position = new Mogre.Vector3(-10, 40, 20); light.SpecularColour = ColourValue.White; // create a floor mesh resource MeshManager.Singleton.CreatePlane("floor", ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, new Plane(Mogre.Vector3.UNIT_Y, 0), 100, 100, 10, 10, true, 1, 10, 10, Mogre.Vector3.UNIT_Z); // create a floor entity, give it a material, and place it at the origin SceneProp floorSceneProp = new SceneProp( this, m_pSceneMgr, m_pSceneMgr.RootSceneNode, physicsScene, "Floor", "floor" ); floorSceneProp.SetMaterialName("Examples/Rockwall"); //Navmesh Navmesh floorNavMesh = MeshToNavmesh.LoadNavmesh(floorSceneProp.Entity); NavmeshQuery query; NavmeshPoint retStartPoint; NavmeshPoint retEndPoint; org.critterai.Vector3 pointStart = new org.critterai.Vector3(0, 0, 0); org.critterai.Vector3 pointEnd = new org.critterai.Vector3(0, 0, 0); org.critterai.Vector3 extents = new org.critterai.Vector3(2, 2, 2); NavStatus status = NavmeshQuery.Create(floorNavMesh, 100, out query); Console.WriteLine("Status returned when NavmeshQuery was built: " + status); NavmeshQueryFilter filter = new NavmeshQueryFilter(); filter.IncludeFlags = 1; status = query.GetNearestPoint(pointStart, extents, filter, out retStartPoint); Console.WriteLine("\nStatus of startPoint GetNearestPoint: " + status); status = query.GetNearestPoint(pointEnd, extents, filter, out retEndPoint); Console.WriteLine("\nStatus of endPoint GetNearestPoint: " + status); uint[] path = new uint[100]; int pathCount; status = query.FindPath(retStartPoint, retEndPoint, filter, path, out pathCount); Console.WriteLine("\nStatus of Find path: " + status); // create our character controller m_pChara = new SinbadCharacterController(this, physicsScene, m_pCamera, new Mogre.Vector3(0, 5, 0), 0); SinbadCharacterController bot1 = new SinbadCharacterController(this, physicsScene, m_pCamera, new Mogre.Vector3(-10, 5, 0), 1, false); SinbadCharacterController bot2 = new SinbadCharacterController(this, physicsScene, m_pCamera, new Mogre.Vector3(0, 5, -10), 2, false); SinbadCharacterController bot3 = new SinbadCharacterController(this, physicsScene, m_pCamera, new Mogre.Vector3(10, 5, 0), 3, false); agents.Add(m_pChara); agents.Add(bot1); agents.Add(bot2); agents.Add(bot3); AdvancedMogreFramework.Singleton.m_pTrayMgr.toggleAdvancedFrameStats(); StringVector items = new StringVector(); items.Insert(items.Count, "Help"); ParamsPanel help = AdvancedMogreFramework.Singleton.m_pTrayMgr.createParamsPanel(TrayLocation.TL_TOPLEFT, "HelpMessage", 100, items); help.setParamValue("Help", "H / F1"); }
public NavManager CreateManager() { CheckCrowdAvoidanceSet(); if (!(mNavmeshData && NavmeshData.HasNavmesh)) { Debug.LogError("Aborted initialization. Navigation mesh not available."); return(null); } //Debug.Log("NavmeshData-------"+ NavmeshData); Navmesh navmesh = NavmeshData.GetNavmesh(); if (navmesh == null) { NavStatus theStatus = Navmesh.Create(navMeshData, out navmesh); Debug.Log("Navmesh.Create ---->" + theStatus + "---->" + (int)(theStatus & NavStatus.Sucess)); if (NavUtil.Failed(theStatus)) { Debug.LogError("NavUtil.Failed(Navmesh.Create(navMeshData, out navmesh) Fail!"); } Debug.Log("--------------------\n" + navMeshData + "---" + navMeshData.Length + "\n-----------------\nNavmesh-------" + navmesh); } if (navmesh == null) { Debug.LogError(" navmesh is null"); return(null); } NavmeshQuery query; NavStatus status = NavmeshQuery.Create(navmesh, mMaxQueryNodes, out query); if ((status & NavStatus.Sucess) == 0) { Debug.LogError(" Aborted initialization. Failed query creation: " + status.ToString()); return(null); } CrowdManager crowd = CrowdManager.Create(mMaxCrowdAgents, mMaxAgentRadius, navmesh); if (crowd == null) { Debug.LogError("Aborted initialization. Failed crowd creation."); return(null); } for (int i = 0; i < CrowdManager.MaxAvoidanceParams; i++) { crowd.SetAvoidanceConfig(i, CrowdAvoidanceConfig[i]); } NavGroup mGroup = new NavGroup(navmesh, query, crowd, crowd.QueryFilter, mExtents, false); int count = AgentGroupSettingManager.GetGroupCount(); Dictionary <byte, NavAgentGroups> mAgentGroups = new Dictionary <byte, NavAgentGroups>(count); for (int i = 0; i < count; i++) { byte groupId; NavAgentGroups group = AgentGroupSettingManager.CreateAgentGroup(i, mMaxPath, mMaxStraightPath, out groupId); group.angleAt = mAngleAt; group.heightTolerance = mHeightTolerance; group.turnThreshold = mTurnThreshold; mAgentGroups.Add(groupId, group); } return(NavManager.Create(mMaxAgents, mGroup, mAgentGroups)); }