Exemple #1
0
            /// <inheritdoc/>
            public void Execute(int index)
            {
                int startNeighborIndex = index * numNeighbors;
                int endNeighborIndex   = startNeighborIndex + numNeighbors;

                NodeTransform nt = nodesTransforms[index];

                for (int i = startNeighborIndex; i < endNeighborIndex; ++i)
                {
                    int  neighborIndex = nodesNeighbors[i].neighborIndex;
                    bool valid         = nodesNeighbors[i].isValid;

                    int vertexIndex = index * numNeighbors * 2 + ((i - startNeighborIndex) * 2);

                    indices[vertexIndex]     = vertexIndex;
                    indices[vertexIndex + 1] = vertexIndex + 1;

                    if (!valid)
                    {
                        vertices[vertexIndex]     = float3.zero;
                        vertices[vertexIndex + 1] = float3.zero;
                    }
                    else
                    {
                        NodeTransform ntn = nodesTransforms[neighborIndex];

                        vertices[vertexIndex]     = nt.pos + (nt.up * NodeConnectionVisualNormalOffset);
                        vertices[vertexIndex + 1] = math.lerp(nt.pos + (nt.up * NodeConnectionVisualNormalOffset), ntn.pos + (ntn.up * NodeConnectionVisualNormalOffset), 0.5f);
                    }
                }
            }
Exemple #2
0
            /// <summary>
            /// Get whether it is possible to reach a given neighbor from the given node index.
            /// </summary>
            /// <param name="index"></param>
            /// <param name="neighborIndex"></param>
            /// <returns></returns>
            private bool CanReachNeighbor(int index, int neighborIndex)
            {
                NodeTransform nt  = nodesTransforms[index];
                NodeTransform ntn = nodesTransforms[neighborIndex];

                // the following code will "cut corners", so the path to go over ramps works as intended
                bool canReachNeighbor = false;

                int rowNode     = index / scanSettings.gridWidth;
                int rowNeighbor = neighborIndex / scanSettings.gridWidth;

                bool sameRow = rowNode == rowNeighbor;
                bool sameCol = (index + scanSettings.gridWidth == neighborIndex) || (index - scanSettings.gridWidth == neighborIndex);

                const float dotThreshold = 0.99625f; // anything over is aprox 5 degrees or less in "angle distance"
                float       dotRightsAbs = math.abs(math.dot(nt.right, ntn.right));
                float       dotFwdsAbs   = math.abs(math.dot(nt.fwd, ntn.fwd));

                if ((sameCol && dotRightsAbs >= dotThreshold) || (sameRow && dotFwdsAbs >= dotThreshold))
                {
                    // the node can be reached if the distance in height meets the requirements
                    canReachNeighbor = math.distance(nt.pos.y, ntn.pos.y) <= maxWalkableHeightWithStep;
                }

                return(canReachNeighbor);
            }
Exemple #3
0
            /// <inheritdoc/>
            public void Execute(int index)
            {
                int startNeighborIndex = index * numNeighbors;
                int endNeighborIndex   = startNeighborIndex + numNeighbors;

                NodeTransform nt = nodesTransforms[index];

                for (int i = startNeighborIndex; i < endNeighborIndex; i++)
                {
                    int  neighborIndex = nodesNeighbors[i].neighborIndex;
                    bool valid         = nodesNeighbors[i].isValid;

                    int vertexIndex = index * numNeighbors * 2 + ((i - startNeighborIndex) * 2);

                    indices[vertexIndex]     = vertexIndex;
                    indices[vertexIndex + 1] = vertexIndex + 1;

                    if (!valid)
                    {
                        vertices[vertexIndex]     = Vector3.zero;
                        vertices[vertexIndex + 1] = Vector3.zero;
                    }
                    else
                    {
                        NodeTransform ntn = nodesTransforms[neighborIndex];

                        vertices[vertexIndex]     = nt.Pos + (nt.Up * NodeVisualNormalOffset);
                        vertices[vertexIndex + 1] = Vector3.Lerp(nt.Pos + (nt.Up * NodeVisualNormalOffset), ntn.Pos + (ntn.Up * NodeVisualNormalOffset), 0.5f);
                    }
                }
            }
Exemple #4
0
            /// <inheritdoc/>
            public void Execute(int index)
            {
                NodeTransform nt = nodesTransforms[index];

                // start a bit before the node just in case there's an obstacle overlapping a bit
                Vector3 center = (Vector3)(nt.pos - nt.up * 0.1f);

                // nodes are squares and we don't plan to change it
                float   halfWidth   = NodeHalfSize * boxNodePercentage;
                Vector3 halfExtents = new Vector3(halfWidth, 0.01f, halfWidth);

                commands[index] = new BoxcastCommand(center, halfExtents, (Quaternion)nt.GetRotation(), (Vector3)nt.up, maxCharacterHeight, mask);
            }
Exemple #5
0
            /// <inheritdoc/>
            public void Execute(int index)
            {
                NodeTransform nt = nodesTransforms[index];

                // start a bit before the node just in case there's an obstacle overlapping a bit
                Vector3 center = nt.Pos - nt.Up * 0.1f;

                // nodes are squares and we don't plan to change it
                float   halfWidth   = NodeHalfSize * settings.boxNodePercentage;
                float   halfDepth   = halfWidth;
                Vector3 halfExtents = new Vector3(halfWidth, 0.01f, halfDepth);

                commands[index] = new BoxcastCommand(center, halfExtents, nt.GetRotation(), nt.Up, settings.maxCharacterHeight, settings.mask);
            }
Exemple #6
0
            /// <inheritdoc/>
            public void Execute(int index)
            {
                RaycastHit     hit     = hits[index];
                RaycastCommand command = commands[index];

                // Note: we can't check for collider to be null since reference types are not allowed
                bool validNode = hit.normal != default(Vector3);

                Vector3 pos    = validNode ? hit.point : new Vector3(command.from.x, 0.0f, command.from.z);
                Vector3 normal = validNode ? hit.normal : Vector3.up;

                nodesTransforms[index] = new NodeTransform(pos, normal);
                nodesTypes[index]      = !validNode ? NodeType.Invalid : NodeType.Free;
            }
Exemple #7
0
            /// <inheritdoc/>
            public void Execute(int index)
            {
                RaycastHit     hit     = hits[index];
                RaycastCommand command = commands[index];

                // we can't check for collider to be null since reference types are not allowed
                bool validNode = hit.normal != default(Vector3);

                float3 commandPos = (float3)command.from;

                commandPos.y = 0.0f;

                float3 pos    = validNode ? (float3)hit.point : commandPos;
                float3 normal = validNode ? (float3)hit.normal : math.up();

                nodesTransforms[index] = new NodeTransform(pos, normal);
                nodesTypes[index]      = !validNode ? NodeType.Invalid : NodeType.Free;
            }
Exemple #8
0
        /// <summary>
        /// Adds the nodes debugging.
        /// </summary>
        public void RecalculateDebug()
        {
            DisposeDebugNativeDatastructures();
            int numNodes = gridDepth * gridWidth;

            // prepare the job that calculates the vertices for the neighbor connection lines
            int arrayLength = numNodes * NodeNeighbors * 2;

            connectionsMeshVertices = new NativeArray <Vector3>(arrayLength, Allocator.Persistent);
            connectionsMeshIndices  = new NativeArray <int>(arrayLength, Allocator.Persistent);

            CalculateConnectionMeshJob calcConnectionsMeshJob = new CalculateConnectionMeshJob(NodeNeighbors, nodesTransforms, nodesNeighbors, connectionsMeshVertices, connectionsMeshIndices);
            JobHandle calcConnectionMeshHandle = calcConnectionsMeshJob.Schedule(numNodes, 8);

            // do other required stuff before calling complete so we have actual parallelism
            MeshRenderer mr = Utils.GetOrAddComponent <MeshRenderer>(transform, out bool createdRenderer);

            mr.shadowCastingMode    = ShadowCastingMode.Off;
            mr.sharedMaterial       = nodeConnectionsMaterial;
            mr.lightProbeUsage      = LightProbeUsage.Off;
            mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
            mr.enabled = showNodesConnections;

            MeshFilter filter = Utils.GetOrAddComponent <MeshFilter>(transform, out bool createdFilter);

            filter.sharedMesh = connectionsMesh;

            // the nodes themselves
            nodeBatcher.Clear();

            if (showNodes)
            {
                for (int i = 0; i < numNodes; i++)
                {
                    NodeTransform nt       = nodesTransforms[i];
                    NodeType      nodeType = nodesTypes[i];

                    Color32 c;

                    if (nodeType == NodeType.Invalid)
                    {
                        c = invalidNodeColor;
                    }
                    else if (nodeType == NodeType.OccupiedByObstacle)
                    {
                        c = nonWalkableNodeColor;
                    }
                    else
                    {
                        c = walkableNodeColor;
                    }

                    Vector3   pos = nt.Pos + (nt.Up * NodeVisualNormalOffset);
                    Matrix4x4 trs = Matrix4x4.TRS(pos, nt.GetRotation(), Vector3.one);

                    // batch each node quad debug
                    nodeBatcher.AddItem(c, trs);
                }
            }

            calcConnectionMeshHandle.Complete();

            // set the mesh using the results of the job
            connectionsMesh.SetVertices(calcConnectionsMeshJob.vertices);
            connectionsMesh.SetIndices(calcConnectionsMeshJob.indices, MeshTopology.Lines, 0);
        }