public bool Raycast(Point3d start, Point3d end, out float t) { NavRef startNavRef = ComputeNavRefAtPoint(start); NavRef endNavRef = ComputeNavRefAtPoint(end); return(Raycast(start, startNavRef, end, endNavRef, out t)); }
public NavRef ComputeNavRefAtPoint(Point2d point) { NavRef navRef = null; if (m_boundingBox.ContainsPoint2d(point)) { if (m_navCells.Length > 0) { float cellSize = GameConstants.NAV_MESH_WORLD_UNITS_SIZE; uint colomnIndex = (uint)((point.x - m_boundingBox.Min.x) / cellSize); uint rowIndex = (uint)((m_boundingBox.Max.y - point.y) / cellSize); uint cellIndex = GetNavCellIndex(rowIndex, colomnIndex); if (m_navCells[cellIndex].connectivityId != EMPTY_NAV_CELL) { navRef = new NavRef((int)cellIndex, m_roomKey); } else { navRef = new NavRef(); } } else { // The whole nav mesh is one big nav cell navRef = new NavRef(0, m_roomKey); } } else { navRef = new NavRef(); } return(navRef); }
private void ComputeSmoothedPath() { // Convert the raw path steps into a proper path step sequence // Always add the first step m_finalPath.Add(new PathStep(m_startNavRef, m_startPosition)); // Add a step at the midpoint between each neighboring nav-cell in the path for (uint rawStepIndex = 1; rawStepIndex < m_rawPath.Count; rawStepIndex++) { NavRef previousNavRef = m_rawPath[(int)rawStepIndex - 1]; NavRef currentNavRef = m_rawPath[(int)rawStepIndex]; Point3d portalLeft, portalRight; if (m_navMesh.ComputePortalPoints( previousNavRef, currentNavRef, out portalLeft, out portalRight)) { Point3d portalMidpoint = Point3d.Interpolate(portalLeft, portalRight, 0.5F); m_finalPath.Add(new PathStep(currentNavRef, portalMidpoint)); } } // Always add the lest step m_finalPath.Add(new PathStep(m_endNavRef, m_endPosition)); // TODO: Remove the extraneous path steps using funnel algorithm + ray casting m_state = eState.complete; }
public bool PointCanSeeOtherPoint(Point3d a, Point3d b) { NavRef navRefA = ComputeNavRefAtPoint(a); NavRef navRefB = ComputeNavRefAtPoint(b); return(NavRefCanSeeOtherNavRef(navRefA, navRefB)); }
public ContextOverlayView(ContextOverlayController contextOverlayController) { m_contextOverlayController = contextOverlayController; m_hotspotWidgets = new List<HotspotWidget>(); m_currentNavRef = new NavRef(-1, null); CurrentHotspot = null; m_style= contextOverlayController.ParentController.contextOverlayStyle; }
// Helper Functions private void ResetRequest() { m_navMesh = null; m_roomKey = null; m_startPosition = new Point3d(); m_endPosition = new Point3d(); m_startNavRef = null; m_endNavRef = null; }
public int GetNavRefConnectivityID(NavRef navRef) { int connectivityID = EMPTY_NAV_CELL; if (navRef.IsValid) { connectivityID = GetNavCellConnectivityID((uint)navRef.NavCellIndex); } return(connectivityID); }
public bool AreNavRefsConnected(NavRef navRefA, NavRef navRefB) { bool areConnected = false; if (navRefA.IsValid && navRefB.IsValid) { areConnected = navRefA.NavRoomKey.Equals(navRefB.NavRoomKey) && ((navRefA.NavCellIndex == navRefB.NavCellIndex) || (m_navCells[navRefA.NavCellIndex].connectivityId == m_navCells[navRefB.NavCellIndex].connectivityId)); } return(areConnected); }
private void BuildNavCellPotentiallyVisibleSet() { if (m_nonEmptyNavCellCount > 0) { // Only need PVS information on non-empty nav cells m_pvs = new PotentiallyVisibleSet(m_nonEmptyNavCellCount); // Raycast from each non-empty nav cell... for (int startNavCellIndex = 0; startNavCellIndex < m_navCells.Length; ++startNavCellIndex) { NavRef startNavRef = new NavRef(startNavCellIndex, m_roomKey); NavCell startNavCell = m_navCells[startNavCellIndex]; if (startNavCell.connectivityId != EMPTY_NAV_CELL) { // ... to every other non-empty nav cell for (int endNavCellIndex = 0; endNavCellIndex < m_navCells.Length; ++endNavCellIndex) { NavCell endNavCell = m_navCells[endNavCellIndex]; if (startNavCellIndex != endNavCellIndex && endNavCell.connectivityId != EMPTY_NAV_CELL) { NavRef endNavRef = new NavRef(endNavCellIndex, m_roomKey); Point3d start = ComputeNavCellCenter((uint)startNavCellIndex); Point3d end = ComputeNavCellCenter((uint)endNavCellIndex); float t; bool hit = Raycast(start, startNavRef, end, endNavRef, out t); // Mark visibility in the PVS where the raycast succeeds if (!hit) { m_pvs.SetCellCanSeeOtherCell((uint)startNavCell.pvsCellIndex, (uint)endNavCell.pvsCellIndex); } } } } } } }
private void ComputeEndpoints() { m_startNavRef = m_navMesh.ComputeNavRefAtPoint(m_startPosition); m_endNavRef = m_navMesh.ComputeNavRefAtPoint(m_endPosition); if (m_startNavRef.IsValid) { if (m_endNavRef.IsValid) { if (m_navMesh.AreNavRefsConnected(m_startNavRef, m_endNavRef)) { if (m_startNavRef.Equals(m_endNavRef)) { // We can head directly to the destination m_finalPath.Add(new PathStep(m_startNavRef, m_startPosition)); m_finalPath.Add(new PathStep(m_endNavRef, m_endPosition)); m_state = eState.complete; } else { // We have to do the expensive query m_state = eState.setup_raw_path; } } else { m_state = eState.complete; m_resultCode = eResult.failed_start_off_nav_mesh; } } else { m_state = eState.complete; m_resultCode = eResult.failed_end_off_nav_mesh; } } else { m_state = eState.complete; m_resultCode = eResult.failed_start_off_nav_mesh; } }
public uint[] ComputeNavCellsInRadius(Point3d center, float radius, bool include_center) { List <uint> navCells = new List <uint>(); NavRef centerRef = ComputeNavRefAtPoint(center); float radius_squared = radius * radius; if (centerRef.NavCellIndex != EMPTY_NAV_CELL) { uint centerCellIndex = (uint)centerRef.NavCellIndex; uint centerColomn = GetNavCellColomn(centerCellIndex); uint centerRow = GetNavCellRow(centerCellIndex); uint radiusInCells = (uint)Math.Ceiling(radius / GameConstants.NAV_MESH_WORLD_UNITS_SIZE); uint minColomnIndex = (centerColomn >= radiusInCells) ? centerColomn - radiusInCells : 0; uint maxColomnIndex = Math.Min(centerColomn + radiusInCells, m_colomnCount - 1); uint minRowIndex = (centerRow >= radiusInCells) ? centerRow - radiusInCells : 0; uint maxRowIndex = Math.Min(centerRow + radiusInCells, m_rowCount - 1); for (uint row = minRowIndex; row <= maxRowIndex; ++row) { for (uint colomn = minColomnIndex; colomn <= maxColomnIndex; ++colomn) { uint cellIndex = GetNavCellIndex(row, colomn); if ((cellIndex != centerCellIndex || include_center) && m_navCells[cellIndex].connectivityId == m_navCells[centerCellIndex].connectivityId) { Point3d cellCenter = ComputeNavCellCenter(cellIndex); if (Point3d.DistanceSquared(cellCenter, center) <= radius_squared) { navCells.Add(cellIndex); } } } } } return(navCells.ToArray()); }
public bool NavRefCanSeeOtherNavRef(NavRef navRefA, NavRef navRefB) { bool canSee = false; if (navRefA.IsValid && navRefB.IsValid) { canSee = true; if (m_pvs != null) { NavCell navCellA = m_navCells[navRefA.NavCellIndex]; NavCell navCellB = m_navCells[navRefB.NavCellIndex]; canSee = m_pvs.CanCellSeeOtherCell( (uint)navCellA.pvsCellIndex, (uint)navCellB.pvsCellIndex); } } return(canSee); }
public bool NavRefCanSeeOtherNavRef(NavRef navRefA, NavRef navRefB) { bool canSee = false; if (navRefA.IsValid && navRefB.IsValid) { canSee = true; if (m_pvs != null) { NavCell navCellA = m_navCells[navRefA.NavCellIndex]; NavCell navCellB = m_navCells[navRefB.NavCellIndex]; canSee = m_pvs.CanCellSeeOtherCell( (uint)navCellA.pvsCellIndex, (uint)navCellB.pvsCellIndex); } } return canSee; }
public int GetNavRefConnectivityID(NavRef navRef) { int connectivityID = EMPTY_NAV_CELL; if (navRef.IsValid) { connectivityID = GetNavCellConnectivityID((uint)navRef.NavCellIndex); } return connectivityID; }
private void UpdateCurrentNavRef() { SessionData sessionData = SessionData.GetInstance(); GameData gameData = sessionData.CurrentGameData; RoomData roomData = gameData.GetCachedRoomData(gameData.CurrentRoomKey); if (roomData != null) { AsyncRPGSharedLib.Navigation.NavMesh navMesh = roomData.StaticRoomData.NavMesh; Point2d pixelPoint = WidgetEventDispatcher.GetMousePosition(); Point3d roomPoint = GameConstants.ConvertPixelPositionToRoomPosition(pixelPoint); m_currentNavRef = navMesh.ComputeNavRefAtPoint(roomPoint); } }
public PathStep(NavRef navRef, Point3d point) { m_navRef = new NavRef(navRef.NavCellIndex, navRef.NavRoomKey); m_point = new Point3d(point); }
public bool Raycast( Point3d start, NavRef startNavRef, Point3d end, NavRef endNavRef, out float t) { bool hit = false; if (!startNavRef.IsValid || !endNavRef.IsValid) { hit = true; t = 0.0f; } else if (startNavRef.Equals(endNavRef)) { hit = false; t = 1.0f; } else { uint maxRaycastIteration = m_rowCount + m_colomnCount; uint iterationCount = 0; NavRef currentNavRef = startNavRef; AABB2d currentNavCellBounds = ComputeNavCellBounds2d((uint)currentNavRef.NavCellIndex); Point2d start2d = start.ToPoint2d(); Vector2d rayDirection = (end - start).ToVector2d(); float tEpsilon = MathConstants.POSITIONAL_EPSILON / rayDirection.Magnitude(); t = 0.0f; while (t < 1.0f && !hit) { float clipMinT = 0.0f; float clipMaxT = 0.0f; // Compute where the ray exists the bounding box of the cell if (!currentNavCellBounds.ClipRay( start2d, rayDirection, out clipMinT, out clipMaxT)) { // If we failed to clip against the bounds that we were suppose to be inside of, // just use the current t and rely on the positional epsilon advancement to get // us back on track Debug.Assert(false, "Raycast didn't clip against box it was suppose to intersect"); clipMinT = t; clipMaxT = t; } if (clipMaxT < 1.0f) { // If we haven't gotten to the end of the ray yet, try to advance to the next nav cell Point2d newTestPoint = start2d + rayDirection * (clipMaxT + tEpsilon); // Find the adjacent neighboring cell, if any currentNavRef = ComputeNavRefAtPoint(newTestPoint); if (currentNavRef.IsValid) { currentNavCellBounds = ComputeNavCellBounds2d((uint)currentNavRef.NavCellIndex); if (currentNavRef.Equals(endNavRef)) { t = 1.0f; hit = false; } else { t = Math.Min(clipMaxT + tEpsilon, 1.0f); hit = false; } } else { t = clipMaxT; hit = true; } } else { // Made it all the way to the end without hitting anything t = 1.0f; hit = false; } // Safety iteration max to prevent infinite loops iterationCount++; if (iterationCount > maxRaycastIteration) { // Something funky happened. Just assume we can see to the end Debug.Assert(false, "Raycast hit iteration limit"); t = 1.0f; hit = false; break; } } } return(hit); }
public bool Raycast( Point3d start, NavRef startNavRef, Point3d end, NavRef endNavRef, out float t) { bool hit = false; if (!startNavRef.IsValid || !endNavRef.IsValid) { hit = true; t = 0.0f; } else if (startNavRef.Equals(endNavRef)) { hit = false; t = 1.0f; } else { uint maxRaycastIteration = m_rowCount + m_colomnCount; uint iterationCount = 0; NavRef currentNavRef = startNavRef; AABB2d currentNavCellBounds = ComputeNavCellBounds2d((uint)currentNavRef.NavCellIndex); Point2d start2d = start.ToPoint2d(); Vector2d rayDirection = (end - start).ToVector2d(); float tEpsilon = MathConstants.POSITIONAL_EPSILON / rayDirection.Magnitude(); t = 0.0f; while (t < 1.0f && !hit) { float clipMinT = 0.0f; float clipMaxT = 0.0f; // Compute where the ray exists the bounding box of the cell if (!currentNavCellBounds.ClipRay( start2d, rayDirection, out clipMinT, out clipMaxT)) { // If we failed to clip against the bounds that we were suppose to be inside of, // just use the current t and rely on the positional epsilon advancement to get // us back on track Debug.Assert(false, "Raycast didn't clip against box it was suppose to intersect"); clipMinT = t; clipMaxT = t; } if (clipMaxT < 1.0f) { // If we haven't gotten to the end of the ray yet, try to advance to the next nav cell Point2d newTestPoint = start2d + rayDirection * (clipMaxT + tEpsilon); // Find the adjacent neighboring cell, if any currentNavRef = ComputeNavRefAtPoint(newTestPoint); if (currentNavRef.IsValid) { currentNavCellBounds = ComputeNavCellBounds2d((uint)currentNavRef.NavCellIndex); if (currentNavRef.Equals(endNavRef)) { t = 1.0f; hit = false; } else { t = Math.Min(clipMaxT + tEpsilon, 1.0f); hit = false; } } else { t = clipMaxT; hit = true; } } else { // Made it all the way to the end without hitting anything t = 1.0f; hit = false; } // Safety iteration max to prevent infinite loops iterationCount++; if (iterationCount > maxRaycastIteration) { // Something funky happened. Just assume we can see to the end Debug.Assert(false, "Raycast hit iteration limit"); t = 1.0f; hit = false; break; } } } return hit; }
public bool ComputePortalPoints(NavRef fromNavRef, NavRef toNavRef, out Point3d portalLeft, out Point3d portalRight) { bool validPortal = false; if (fromNavRef.IsValid && toNavRef.IsValid && fromNavRef.NavRoomKey.Equals(toNavRef.NavRoomKey)) { uint fromColomn = GetNavCellColomn((uint)fromNavRef.NavCellIndex); uint fromRow = GetNavCellRow((uint)fromNavRef.NavCellIndex); uint toColomn = GetNavCellColomn((uint)toNavRef.NavCellIndex); uint toRow = GetNavCellRow((uint)toNavRef.NavCellIndex); // toNavRef is to the right of the fromNavRef (+X) if (toColomn == fromColomn + 1 && toRow == fromRow) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.right, out portalLeft, out portalRight); } // toNavRef is to the left of the fromNavRef (-X) else if (toColomn == fromColomn - 1 && toRow == fromRow) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.left, out portalLeft, out portalRight); } // toNavRef is below fromNavRef (-Y) else if (toRow == fromRow + 1 && toColomn == fromColomn) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.down, out portalLeft, out portalRight); } // toNavRef is above fromNavRef (+Y) else if (toRow == fromRow - 1 && toColomn == fromColomn) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.up, out portalLeft, out portalRight); } else { portalLeft = new Point3d(); portalRight = new Point3d(); } } else { portalLeft = new Point3d(); portalRight = new Point3d(); } return validPortal; }
public NavRef ComputeNavRefAtPoint(Point2d point) { NavRef navRef = null; if (m_boundingBox.ContainsPoint2d(point)) { if (m_navCells.Length > 0) { float cellSize = GameConstants.NAV_MESH_WORLD_UNITS_SIZE; uint colomnIndex = (uint)((point.x - m_boundingBox.Min.x) / cellSize); uint rowIndex = (uint)((m_boundingBox.Max.y - point.y) / cellSize); uint cellIndex = GetNavCellIndex(rowIndex, colomnIndex); if (m_navCells[cellIndex].connectivityId != EMPTY_NAV_CELL) { navRef = new NavRef((int)cellIndex, m_roomKey); } else { navRef = new NavRef(); } } else { // The whole nav mesh is one big nav cell navRef = new NavRef(0, m_roomKey); } } else { navRef = new NavRef(); } return navRef; }
public bool ComputePortalPoints(NavRef fromNavRef, NavRef toNavRef, out Point3d portalLeft, out Point3d portalRight) { bool validPortal = false; if (fromNavRef.IsValid && toNavRef.IsValid && fromNavRef.NavRoomKey.Equals(toNavRef.NavRoomKey)) { uint fromColomn = GetNavCellColomn((uint)fromNavRef.NavCellIndex); uint fromRow = GetNavCellRow((uint)fromNavRef.NavCellIndex); uint toColomn = GetNavCellColomn((uint)toNavRef.NavCellIndex); uint toRow = GetNavCellRow((uint)toNavRef.NavCellIndex); // toNavRef is to the right of the fromNavRef (+X) if (toColomn == fromColomn + 1 && toRow == fromRow) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.right, out portalLeft, out portalRight); } // toNavRef is to the left of the fromNavRef (-X) else if (toColomn == fromColomn - 1 && toRow == fromRow) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.left, out portalLeft, out portalRight); } // toNavRef is below fromNavRef (-Y) else if (toRow == fromRow + 1 && toColomn == fromColomn) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.down, out portalLeft, out portalRight); } // toNavRef is above fromNavRef (+Y) else if (toRow == fromRow - 1 && toColomn == fromColomn) { validPortal = ComputePointsOnNavCellSide( (uint)fromNavRef.NavCellIndex, MathConstants.eDirection.up, out portalLeft, out portalRight); } else { portalLeft = new Point3d(); portalRight = new Point3d(); } } else { portalLeft = new Point3d(); portalRight = new Point3d(); } return(validPortal); }
public bool AreNavRefsConnected(NavRef navRefA, NavRef navRefB) { bool areConnected = false; if (navRefA.IsValid && navRefB.IsValid) { areConnected = navRefA.NavRoomKey.Equals(navRefB.NavRoomKey) && ((navRefA.NavCellIndex == navRefB.NavCellIndex) || (m_navCells[navRefA.NavCellIndex].connectivityId == m_navCells[navRefB.NavCellIndex].connectivityId)); } return areConnected; }