コード例 #1
0
 /// <summary>
 /// Find shortest path for every position on grid to target position
 /// </summary>
 /// <param name="targetDirections">Result table of all shortest paths for every position on grid to targetPosition</param>
 /// <param name="rowCount">Height of grid</param>
 /// <param name="targetPosition">Generate all shortest paths to this position.</param>
 /// <param name="gridWalls">Table representing walls/obstacles in grid. See: CartesianGridMovement</param>
 public static void CalculateShortestPathsToTarget(NativeArray <byte> targetDirections, NativeArray <int> targetDistances, int rowCount, CartesianGridCoordinates targetPosition, CartesianGridOnCubeFace cubeFace, byte *gridWalls, float4x4 *faceLocalToLocal)
 {
     CalculateShortestWalkableDistancesToTarget(targetDistances, rowCount, gridWalls, targetPosition, cubeFace, faceLocalToLocal);
     CalculateShortestPathGivenDistancesToTarget(targetDirections, rowCount, targetDistances, gridWalls, faceLocalToLocal);
 }
コード例 #2
0
    static void CalculateShortestWalkableDistancesToTargetInner(NativeArray <int> targetDistances, int rowCount, byte *gridWalls, float4x4 *faceLocalToLocal, UnsafeBitArray pending, UnsafeBitArray closed, UnsafeRingQueue <int> open)
    {
        var cellCount     = rowCount * rowCount;
        var maxPathLength = 6 * (cellCount + 1);

        while (open.Length > 0)
        {
            var cellIndex    = open.Dequeue();
            var cellPosition = CartesianGridOnCubeUtility.CellFaceCoordinates(cellIndex, rowCount);
            var faceIndex    = CartesianGridOnCubeUtility.CellFaceIndex(cellIndex, rowCount);

            var rowStride           = (rowCount + 1) / 2;
            var faceStride          = rowCount * rowStride;
            var faceGridWallsOffset = faceIndex * faceStride;

            var validDirections = CartesianGridMovement.ValidDirections(cellPosition, rowCount, rowCount, gridWalls + faceGridWallsOffset);
            var validNorth      = ((validDirections & (byte)CartesianGridDirectionBit.North) != 0);
            var validSouth      = ((validDirections & (byte)CartesianGridDirectionBit.South) != 0);
            var validWest       = ((validDirections & (byte)CartesianGridDirectionBit.West) != 0);
            var validEast       = ((validDirections & (byte)CartesianGridDirectionBit.East) != 0);

            var cellIndexNorth = CartesianGridOnCubeUtility.CellIndexNorth(cellIndex, rowCount, faceLocalToLocal);
            var cellIndexSouth = CartesianGridOnCubeUtility.CellIndexSouth(cellIndex, rowCount, faceLocalToLocal);
            var cellIndexWest  = CartesianGridOnCubeUtility.CellIndexWest(cellIndex, rowCount, faceLocalToLocal);
            var cellIndexEast  = CartesianGridOnCubeUtility.CellIndexEast(cellIndex, rowCount, faceLocalToLocal);

            var distanceNorth = maxPathLength;
            var distanceSouth = maxPathLength;
            var distanceEast  = maxPathLength;
            var distanceWest  = maxPathLength;

            var closedNorth = false;
            var closedSouth = false;
            var closedWest  = false;
            var closedEast  = false;

            if (validNorth)
            {
                if (closed.IsSet(cellIndexNorth))
                {
                    distanceNorth = targetDistances[cellIndexNorth];
                    closedNorth   = true;
                }
                else if (!pending.IsSet(cellIndexNorth))
                {
                    open.Enqueue(cellIndexNorth);
                    pending.Set(cellIndexNorth, true);
                }
            }

            if (validSouth)
            {
                if (closed.IsSet(cellIndexSouth))
                {
                    distanceSouth = targetDistances[cellIndexSouth];
                    closedSouth   = true;
                }
                else if (!pending.IsSet(cellIndexSouth))
                {
                    open.Enqueue(cellIndexSouth);
                    pending.Set(cellIndexSouth, true);
                }
            }

            if (validWest)
            {
                if (closed.IsSet(cellIndexWest))
                {
                    distanceWest = targetDistances[cellIndexWest];
                    closedWest   = true;
                }
                else if (!pending.IsSet(cellIndexWest))
                {
                    open.Enqueue(cellIndexWest);
                    pending.Set(cellIndexWest, true);
                }
            }

            if (validEast)
            {
                if (closed.IsSet(cellIndexEast))
                {
                    distanceEast = targetDistances[cellIndexEast];
                    closedEast   = true;
                }
                else if (!pending.IsSet(cellIndexEast))
                {
                    open.Enqueue(cellIndexEast);
                    pending.Set(cellIndexEast, true);
                }
            }

            var closedNeighbor = closedNorth || closedSouth || closedWest || closedEast;
            Assert.IsTrue(closedNeighbor);

            var bestDist = math.cmin(new int4(distanceNorth, distanceSouth, distanceEast, distanceWest)) + 1;
            Assert.IsFalse(bestDist > (maxPathLength + 1));

            targetDistances[cellIndex] = bestDist;
            closed.Set(cellIndex, true);
        }
    }
コード例 #3
0
        void VisiblePartial(int index)
        {
            var chunk                    = Chunks[index];
            var chunkEntityCount         = chunk.Count;
            var chunkVisibleCount        = 0;
            var chunkLODs                = chunk.GetNativeArray(MeshLODComponentType);
            var chunkBounds              = chunk.GetNativeArray(WorldMeshRenderBoundsType);
            var hasMeshLODComponentType  = chunkLODs.Length > 0;
            var hasWorldMeshRenderBounds = chunkBounds.Length > 0;

            float4x4 *dstPtr = GetVisibleOutputBuffer(chunk);
            float4x4 *srcPtr = GetLocalToWorldSourceBuffer(chunk);

            if (srcPtr == null)
            {
                return;
            }

            // 00 (-WorldMeshRenderBounds -MeshLODComponentType)
            if ((!hasWorldMeshRenderBounds) && (!hasMeshLODComponentType))
            {
                for (int i = 0; i < chunkEntityCount; i++)
                {
                    UnsafeUtility.MemCpy(dstPtr + chunkVisibleCount + i, srcPtr + i, UnsafeUtility.SizeOf <float4x4>());
                }

                chunkVisibleCount = chunkEntityCount;
            }
            // 01 (-WorldMeshRenderBounds +MeshLODComponentType)
            else if ((!hasWorldMeshRenderBounds) && (hasMeshLODComponentType))
            {
                for (int i = 0; i < chunkEntityCount; i++)
                {
                    var instanceLOD      = chunkLODs[i];
                    var instanceLODValid = (ActiveLODGroupMask[instanceLOD.Group].LODMask & instanceLOD.LODMask) != 0;
                    if (instanceLODValid)
                    {
                        UnsafeUtility.MemCpy(dstPtr + chunkVisibleCount, srcPtr + i, UnsafeUtility.SizeOf <float4x4>());
                        chunkVisibleCount++;
                    }
                }
            }
            // 10 (+WorldMeshRenderBounds -MeshLODComponentType)
            else if ((hasWorldMeshRenderBounds) && (!hasMeshLODComponentType))
            {
                for (int i = 0; i < chunkEntityCount; i++)
                {
                    var instanceBounds    = chunkBounds[i];
                    var instanceCullValid = (Planes.Inside(instanceBounds) != FrustumPlanes.InsideResult.Out);

                    if (instanceCullValid)
                    {
                        UnsafeUtility.MemCpy(dstPtr + chunkVisibleCount, srcPtr + i, UnsafeUtility.SizeOf <float4x4>());
                        chunkVisibleCount++;
                    }
                }
            }
            // 11 (+WorldMeshRenderBounds +MeshLODComponentType)
            else
            {
                for (int i = 0; i < chunkEntityCount; i++)
                {
                    var instanceLOD      = chunkLODs[i];
                    var instanceLODValid = (ActiveLODGroupMask[instanceLOD.Group].LODMask & instanceLOD.LODMask) != 0;
                    if (instanceLODValid)
                    {
                        var instanceBounds    = chunkBounds[i];
                        var instanceCullValid = (Planes.Inside(instanceBounds) != FrustumPlanes.InsideResult.Out);
                        if (instanceCullValid)
                        {
                            UnsafeUtility.MemCpy(dstPtr + chunkVisibleCount, srcPtr + i, UnsafeUtility.SizeOf <float4x4>());
                            chunkVisibleCount++;
                        }
                    }
                }
            }

            ChunkVisibleCount[index] = chunkVisibleCount;
        }
コード例 #4
0
    // Sample valid neighboring distances from point.
    // - Smallest distance less than current position's distance is best next path to target.
    // - May result in more than one best direction (any of NSWE)
    // - May result in no best direction if on island (result=0xff)
    static void CalculateShortestPathGivenDistancesToTarget(NativeArray <byte> targetDirections, int rowCount, NativeArray <int> cellDistances, byte *gridWalls, float4x4 *faceLocalToLocal)
    {
        var cellCount     = rowCount * rowCount;
        var maxPathLength = 6 * (cellCount + 1);

        for (int i = 0; i < targetDirections.Length; i++)
        {
            targetDirections[i] = 0;
        }

        for (var cellIndex = 0; cellIndex < (6 * cellCount); cellIndex++)
        {
            var cellPosition = CartesianGridOnCubeUtility.CellFaceCoordinates(cellIndex, rowCount);
            var faceIndex    = CartesianGridOnCubeUtility.CellFaceIndex(cellIndex, rowCount);

            var rowStride           = (rowCount + 1) / 2;
            var faceStride          = rowCount * rowStride;
            var faceGridWallsOffset = faceIndex * faceStride;

            var validDirections = CartesianGridMovement.ValidDirections(cellPosition, rowCount, rowCount, gridWalls + faceGridWallsOffset);
            var validNorth      = ((validDirections & (byte)CartesianGridDirectionBit.North) != 0);
            var validSouth      = ((validDirections & (byte)CartesianGridDirectionBit.South) != 0);
            var validWest       = ((validDirections & (byte)CartesianGridDirectionBit.West) != 0);
            var validEast       = ((validDirections & (byte)CartesianGridDirectionBit.East) != 0);

            var cellIndexNorth = CartesianGridOnCubeUtility.CellIndexNorth(cellIndex, rowCount, faceLocalToLocal);
            var cellIndexSouth = CartesianGridOnCubeUtility.CellIndexSouth(cellIndex, rowCount, faceLocalToLocal);
            var cellIndexWest  = CartesianGridOnCubeUtility.CellIndexWest(cellIndex, rowCount, faceLocalToLocal);
            var cellIndexEast  = CartesianGridOnCubeUtility.CellIndexEast(cellIndex, rowCount, faceLocalToLocal);

            var distanceNorth = maxPathLength;
            var distanceSouth = maxPathLength;
            var distanceEast  = maxPathLength;
            var distanceWest  = maxPathLength;

            if (validNorth)
            {
                distanceNorth = cellDistances[cellIndexNorth];
            }
            if (validSouth)
            {
                distanceSouth = cellDistances[cellIndexSouth];
            }
            if (validWest)
            {
                distanceWest = cellDistances[cellIndexWest];
            }
            if (validEast)
            {
                distanceEast = cellDistances[cellIndexEast];
            }

            var bestDist = math.cmin(new int4(distanceNorth, distanceSouth, distanceEast, distanceWest));
            var dist     = cellDistances[cellIndex];

            if ((bestDist < dist) && (bestDist < maxPathLength))
            {
                var bestDir = 0;
                if (distanceNorth == bestDist)
                {
                    bestDir |= (byte)CartesianGridDirectionBit.North;
                }
                if (distanceSouth == bestDist)
                {
                    bestDir |= (byte)CartesianGridDirectionBit.South;
                }
                if (distanceWest == bestDist)
                {
                    bestDir |= (byte)CartesianGridDirectionBit.West;
                }
                if (distanceEast == bestDist)
                {
                    bestDir |= (byte)CartesianGridDirectionBit.East;
                }

                var targetDirectionsIndex = (faceIndex * faceStride) + (cellPosition.y * rowStride) + (cellPosition.x / 2);

                targetDirections[targetDirectionsIndex] |= (byte)(bestDir << (4 * (cellPosition.x & 1)));
            }
        }
    }
    // Simple grassfire to calculate shortest distance along path to target position for every position.
    // - i.e. breadth-first expansion from target position.
    static void CalculateShortestWalkableDistancesToTarget(NativeArray <int> targetDistances, int rowCount, byte *gridWalls, CartesianGridCoordinates targetPosition, CartesianGridOnCubeFace cubeFace, float4x4 *faceLocalToLocal)
    {
        var cellCount = rowCount * rowCount;
        var closed    = new UnsafeBitArray(6 * cellCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
        var pending   = new UnsafeBitArray(6 * cellCount, Allocator.Temp, NativeArrayOptions.ClearMemory);
        var open      = new UnsafeRingQueue <int>(6 * cellCount, Allocator.Temp);

        var faceIndex           = cubeFace.Value;
        var faceTargetCellIndex = (targetPosition.y * rowCount) + targetPosition.x;

        for (int i = 0; i < targetDistances.Length; i++)
        {
            targetDistances[i] = -1;
        }

        var targetCellIndex = (faceIndex * cellCount) + faceTargetCellIndex;

        targetDistances[targetCellIndex] = 0;

        pending.Set(targetCellIndex, true);
        closed.Set(targetCellIndex, true);

        var cellIndexNorth = CartesianGridOnCubeUtility.CellIndexNorth(targetCellIndex, rowCount, faceLocalToLocal);
        var cellIndexSouth = CartesianGridOnCubeUtility.CellIndexSouth(targetCellIndex, rowCount, faceLocalToLocal);
        var cellIndexWest  = CartesianGridOnCubeUtility.CellIndexWest(targetCellIndex, rowCount, faceLocalToLocal);
        var cellIndexEast  = CartesianGridOnCubeUtility.CellIndexEast(targetCellIndex, rowCount, faceLocalToLocal);

        var rowStride           = (rowCount + 1) / 2;
        var faceStride          = rowCount * rowStride;
        var faceGridWallsOffset = faceIndex * faceStride;

        var validDirections = CartesianGridMovement.ValidDirections(targetPosition, rowCount, rowCount, gridWalls + faceGridWallsOffset);
        var validNorth      = ((validDirections & (byte)CartesianGridDirectionBit.North) != 0);
        var validSouth      = ((validDirections & (byte)CartesianGridDirectionBit.South) != 0);
        var validWest       = ((validDirections & (byte)CartesianGridDirectionBit.West) != 0);
        var validEast       = ((validDirections & (byte)CartesianGridDirectionBit.East) != 0);

        if (validNorth)
        {
            open.Enqueue(cellIndexNorth);
            pending.Set(cellIndexNorth, true);
        }

        if (validSouth)
        {
            open.Enqueue(cellIndexSouth);
            pending.Set(cellIndexSouth, true);
        }

        if (validWest)
        {
            open.Enqueue(cellIndexWest);
            pending.Set(cellIndexWest, true);
        }

        if (validEast)
        {
            open.Enqueue(cellIndexEast);
            pending.Set(cellIndexEast, true);
        }

        CalculateShortestWalkableDistancesToTargetInner(targetDistances, rowCount, gridWalls, faceLocalToLocal, pending, closed, open);

        closed.Dispose();
        pending.Dispose();
        open.Dispose();
    }
    public static void FillCubeFaceTransforms(int rowCount, float4x4 *faceLocalToWorld, float4x4 *faceWorldToLocal, float4x4 *faceLocalToLocal)
    {
        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
        {
            ref var localToWorld = ref m_FaceLocalToWorldRotation[faceIndex];

            // Translate along normal of face by width
            localToWorld.c3.xyz = localToWorld.c1.xyz * rowCount * 0.5f;

            faceLocalToWorld[faceIndex] = localToWorld;
            faceWorldToLocal[faceIndex] = math.fastinverse(faceLocalToWorld[faceIndex]);
        }
コード例 #7
0
        public static NativeList <RayIntersectResult> RayIntersectToMesh(int *triangles, int triangleCount, MeshAppdata *appdatas, float3 origin, float3 dir, float4x4 *transformMatrix, Allocator alloc)
        {
            NativeList <RayIntersectResult> allResults = new NativeList <RayIntersectResult>(triangleCount, alloc);
            RayIntersectJob jb = new RayIntersectJob
            {
                appdatas        = appdatas,
                dir             = dir,
                origin          = origin,
                results         = allResults,
                triangles       = triangles,
                transformMatrix = transformMatrix
            };

            jb.Schedule(triangleCount, max(1, triangleCount / 10)).Complete();
            return(allResults);
        }
コード例 #8
0
        public static bool RayIntersectToMesh(int *triangles, int triangleCount, MeshAppdata *appdatas, float3 origin, float3 dir, float4x4 *transformMatrix, out RayIntersectResult result)
        {
            NativeList <RayIntersectResult> allResults = new NativeList <RayIntersectResult>(triangleCount, Allocator.Temp);
            RayIntersectJob jb = new RayIntersectJob
            {
                appdatas        = appdatas,
                dir             = dir,
                origin          = origin,
                results         = allResults,
                triangles       = triangles,
                transformMatrix = transformMatrix
            };

            jb.Schedule(triangleCount, max(1, triangleCount / 10)).Complete();
            if (allResults.Length <= 0)
            {
                result = new RayIntersectResult();
                return(false);
            }
            float minT  = allResults[0].t;
            int   index = 0;

            for (int i = 1; i < allResults.Length; ++i)
            {
                if (minT > allResults[i].t)
                {
                    index = i;
                }
            }
            result = allResults[index];
            return(true);
        }
コード例 #9
0
 public static unsafe void TestIdentityFloat4x4(float4x4 *mat)
 {
     *mat = float4x4.identity;
 }
コード例 #10
0
 public static unsafe void TestStaticLoad(float4x4 *mat)
 {
     *mat = StaticMat;
 }
コード例 #11
0
 public static unsafe void TestLookAt(float4x4 *mat)
 {
     *mat = float4x4.LookAt(new float3(0, 0, 1), new float3(0, 1, 0), new float3(1, 0, 0));
 }