Пример #1
0
        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;
        }
Пример #2
0
        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;
        }