public void Execute(int index) { if (!m_recompute) { return; } //Compute whether a vertex is convex or concave //as well as its direction ObstacleVertexData v = m_inputObstacles[index]; float2 pos = v.pos, nextPos = m_inputObstacles[v.next].pos, prevPos = m_inputObstacles[v.prev].pos; ObstacleInfos infos = m_inputObstacleInfos[v.infos]; if (infos.length == 2)//infos.edge || { v.convex = true; } else { v.convex = LeftOf(prevPos, pos, nextPos) >= 0.0f; } v.dir = normalize(nextPos - pos); m_referenceObstacles[index] = v; }
public void Execute(int index) { RaycastData raycast = m_inputRaycasts[index]; RaycastResult result = new RaycastResult() { hitAgent = -1, hitObstacle = -1, dynamicObstacle = false }; RaycastFilter filter = raycast.filter; if (filter == 0) { m_results[index] = result; return; } float2 r_position = raycast.position, r_dir = raycast.direction, hitLocation; float a_bottom = raycast.baseline, a_top = a_bottom, a_sqRange = lengthsq(raycast.distance); Segment2D raySegment = new Segment2D(raycast.position, raycast.position + raycast.direction * raycast.distance), segment; UIntPair pair = new UIntPair(0, 0); ObstacleVertexData otherVertex; bool twoSidedCast = raycast.twoSided, alreadyCovered = false, hit; #region static obstacles if ((filter & RaycastFilter.OBSTACLE_STATIC) != 0) { NativeList <int> staticObstacleNeighbors = new NativeList <int>(10, Allocator.Temp); if (m_staticObstacleTree.Length > 0) { QueryObstacleTreeRecursive(ref raycast, ref a_sqRange, 0, ref staticObstacleNeighbors, ref m_staticObstacles, ref m_staticRefObstacles, ref m_staticObstacleInfos, ref m_staticObstacleTree); } NativeHashMap <UIntPair, bool> coveredStaticEdges = new NativeHashMap <UIntPair, bool>(m_staticObstacleTree.Length * 2, Allocator.Temp); for (int i = 0; i < staticObstacleNeighbors.Length; ++i) { ObstacleVertexData vertex = m_staticObstacles[staticObstacleNeighbors[i]]; ObstacleInfos infos = m_staticObstacleInfos[vertex.infos]; pair = new UIntPair(vertex.index, vertex.next); alreadyCovered = coveredStaticEdges.TryGetValue(pair, out hit); if (!alreadyCovered) { otherVertex = m_staticRefObstacles[vertex.next]; segment = new Segment2D(vertex.pos, otherVertex.pos); alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f); if (!alreadyCovered) { if (raySegment.IsIntersecting(segment, out hitLocation)) { //Rays intersecting ! if (result.hitObstacle == -1 || distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D)) { result.hitObstacleLocation2D = hitLocation; result.hitObstacle = infos.index; } } } coveredStaticEdges.TryAdd(pair, true); } pair = new UIntPair(vertex.index, vertex.prev); alreadyCovered = coveredStaticEdges.ContainsKey(pair); if (!alreadyCovered) { otherVertex = m_staticRefObstacles[vertex.prev]; segment = new Segment2D(vertex.pos, otherVertex.pos); alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f); if (!alreadyCovered) { if (raySegment.IsIntersecting(segment, out hitLocation)) { //Rays intersecting ! if (result.hitObstacle == -1 || distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D)) { result.hitObstacleLocation2D = hitLocation; result.hitObstacle = infos.index; } } } coveredStaticEdges.TryAdd(pair, true); } } staticObstacleNeighbors.Dispose(); coveredStaticEdges.Dispose(); } #endregion #region dynamic obstacles if ((filter & RaycastFilter.OBSTACLE_DYNAMIC) != 0) { NativeList <int> dynObstacleNeighbors = new NativeList <int>(10, Allocator.Temp); if (m_dynObstacleTree.Length > 0) { QueryObstacleTreeRecursive(ref raycast, ref a_sqRange, 0, ref dynObstacleNeighbors, ref m_dynObstacles, ref m_dynRefObstacles, ref m_dynObstacleInfos, ref m_dynObstacleTree); } NativeHashMap <UIntPair, bool> coveredDynEdges = new NativeHashMap <UIntPair, bool>(m_dynObstacleTree.Length * 2, Allocator.Temp); for (int i = 0; i < dynObstacleNeighbors.Length; ++i) { ObstacleVertexData vertex = m_dynObstacles[dynObstacleNeighbors[i]]; ObstacleInfos infos = m_dynObstacleInfos[vertex.infos]; pair = new UIntPair(vertex.index, vertex.next); alreadyCovered = coveredDynEdges.TryGetValue(pair, out hit); if (!alreadyCovered) { otherVertex = m_dynRefObstacles[vertex.next]; segment = new Segment2D(vertex.pos, otherVertex.pos); alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f); if (!alreadyCovered) { if (raySegment.IsIntersecting(segment, out hitLocation)) { //Rays intersecting ! if (result.hitObstacle == -1 || distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D)) { result.hitObstacleLocation2D = hitLocation; result.hitObstacle = infos.index; result.dynamicObstacle = true; } } } coveredDynEdges.TryAdd(pair, true); } pair = new UIntPair(vertex.index, vertex.prev); alreadyCovered = coveredDynEdges.ContainsKey(pair); if (!alreadyCovered) { otherVertex = m_dynRefObstacles[vertex.prev]; segment = new Segment2D(vertex.pos, otherVertex.pos); alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f); if (!alreadyCovered) { if (raySegment.IsIntersecting(segment, out hitLocation)) { //Rays intersecting ! if (result.hitObstacle == -1 || distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D)) { result.hitObstacleLocation2D = hitLocation; result.hitObstacle = infos.index; result.dynamicObstacle = true; } } } coveredDynEdges.TryAdd(pair, true); } } dynObstacleNeighbors.Dispose(); coveredDynEdges.Dispose(); } #endregion #region Agents if ((filter & RaycastFilter.AGENTS) != 0) { NativeList <int> agentNeighbors = new NativeList <int>(10, Allocator.Temp); float radSq = a_sqRange + lengthsq(m_maxAgentRadius); if (m_inputAgents.Length > 0) { QueryAgentTreeRecursive(ref raycast, ref radSq, 0, ref agentNeighbors); } AgentData agent; int iResult, agentIndex; float2 center, i1, i2, rayEnd = r_position + normalize(r_dir) * raycast.distance; float a_radius, a_sqRadius, cx, cy, Ax = r_position.x, Ay = r_position.y, Bx = rayEnd.x, By = rayEnd.y, dx = Bx - Ax, dy = By - Ay, magA = dx * dx + dy * dy, distSq; int TryGetIntersection(out float2 intersection1, out float2 intersection2) { float magB = 2f * (dx * (Ax - cx) + dy * (Ay - cy)), magC = (Ax - cx) * (Ax - cx) + (Ay - cy) * (Ay - cy) - a_sqRadius, det = magB * magB - 4f * magA * magC, sqDet, t; if ((magA <= float.Epsilon) || (det < 0f)) { // No real solutions. intersection1 = float2(float.NaN, float.NaN); intersection2 = float2(float.NaN, float.NaN); return(0); } if (det == 0) { // One solution. t = -magB / (2f * magA); intersection1 = float2(Ax + t * dx, Ay + t * dy); intersection2 = float2(float.NaN, float.NaN); return(1); } else { // Two solutions. sqDet = sqrt(det); t = ((-magB + sqDet) / (2f * magA)); intersection1 = float2(Ax + t * dx, Ay + t * dy); t = ((-magB - sqDet) / (2f * magA)); intersection2 = float2(Ax + t * dx, Ay + t * dy); return(2); } } for (int i = 0; i < agentNeighbors.Length; ++i) { agentIndex = agentNeighbors[i]; agent = m_inputAgents[agentIndex]; center = agent.position; cx = center.x; cy = center.y; a_radius = agent.radius; a_sqRadius = a_radius * a_radius; if (dot(center - r_position, r_dir) < 0f) { continue; } iResult = TryGetIntersection(out i1, out i2); if (iResult == 0) { continue; } distSq = distancesq(r_position, i1); if (distSq < a_sqRange && (result.hitAgent == -1 || distSq < distancesq(r_position, result.hitAgentLocation2D)) && IsBetween(r_position, center, i1)) { result.hitAgentLocation2D = i1; result.hitAgent = agentIndex; } if (iResult == 2) { distSq = distancesq(r_position, i2); if (distSq < a_sqRange && (result.hitAgent == -1 || distSq < distancesq(r_position, result.hitAgentLocation2D)) && IsBetween(r_position, center, i2)) { result.hitAgentLocation2D = i2; result.hitAgent = agentIndex; } } } agentNeighbors.Dispose(); } #endregion if (m_plane == AxisPair.XY) { float baseline = raycast.worldPosition.z; if (result.hitAgent != -1) { result.hitAgentLocation = float3(result.hitAgentLocation2D, baseline); } if (result.hitObstacle != -1) { result.hitObstacleLocation = float3(result.hitObstacleLocation2D, baseline); } } else { float baseline = raycast.worldPosition.y; if (result.hitAgent != -1) { result.hitAgentLocation = float3(result.hitAgentLocation2D.x, baseline, result.hitAgentLocation2D.y); } if (result.hitObstacle != -1) { result.hitObstacleLocation = float3(result.hitObstacleLocation2D.x, baseline, result.hitObstacleLocation2D.y); } } m_results[index] = result; }