internal void ExecuteSpawn()
            {
                lock (this)
                {
                    if (m_removeQueued || !m_spawnQueued)
                    {
                        return;
                    }
                    if (VoxelMap == null)
                    {
                        var mat = MatrixD.CreateFromQuaternion(Rotation);
                        mat.Translation = WorldPosition;
                        var genSeed = WorldPosition.GetHashCode();
                        if (VoxelUtility.TryFindAsteroidSeed(ref genSeed, Size, SeedSpecs.ProhibitsOre, SeedSpecs.RequiresOre, 10) || !SeedSpecs.ExcludeInvalid)
                        {
                            VoxelMap = VoxelUtility.SpawnAsteroid(new MyPositionAndOrientation(mat),
                                                                  VoxelUtility.CreateProceduralAsteroidProvider(genSeed, Size));
                            VoxelMap.OnPhysicsChanged += MarkForSave;
                        }
                    }

                    m_spawnQueued  = false;
                    m_removeQueued = false;
                }
            }
Beispiel #2
0
        public void Execute(int index)
        {
            int  position  = surfaceVoxelsIndex[index];
            int3 position3 = VoxelUtility.Index1ToIndex3(position);

            Debug.Assert(surfaceVoxels.TryGetValue(position, out bool v));

            int noNeighborCount_Debug = 0;

            int3[] neighborPosition3 = new int3[] {
                position3 + new int3(1, 0, 0),
                position3 + new int3(-1, 0, 0),
                position3 + new int3(0, 1, 0),
                position3 + new int3(0, -1, 0),
                position3 + new int3(0, 0, 1),
                position3 + new int3(0, 0, -1)
            };

            foreach (var neighborPos in neighborPosition3)
            {
                if (!surfaceVoxels.TryGetValue(VoxelUtility.Index3ToIndex1(neighborPos), out bool v1))
                {
                    int surface = VoxelUtility.GetSurfaceIndex(position3, neighborPos);
                    surfaceFaces.TryAdd(surface, true);
                    noNeighborCount_Debug++;
                }
            }

            if (noNeighborCount_Debug == 6)
            {
                Debug.LogError("No neighboring voxel for " + position3);
            }
        }
Beispiel #3
0
    private void CheckRaycastHit()
    {
        var rayPosition = CachedTransform.position + Vector3.forward * RAY_LENGTH;

        if (VoxelUtility.VoxelRayCast(CachedTransform.position, transform.TransformDirection(Vector3.forward), out var voxel, RAY_LENGTH))
        {
            rayPosition      = voxel.HitPosition;
            _currentHitVoxel = voxel.VoxelInfo;
        }
        public override bool TickAfterSimulationRoundRobin()
        {
            ProceduralBody body;

            if (_addQueue.TryDequeue(out body))
            {
                var generatorDef =
                    MyDefinitionManagerBase.Static.GetDefinition <MyPlanetGeneratorDefinition>(body.GeneratorId);
                body.Result = VoxelUtility.SpawnPlanet(body.Position.Translation, generatorDef, body.Seed, (float)body.Radius, body.Name);
                return(true);
            }
            return(false);
        }
Beispiel #5
0
    private void Awake()
    {
        _cameraTransform = _camera.transform;

        _voxelGeometryController    = new VoxelGeometryController(8, GetMaxVerticesCount());
        _voxelBuilderController     = new VoxelBuilderController();
        _voxelPhysicsController     = new VoxelPhysicsController();
        _fallingConstructionFactory = new FallingConstructionFactory(_fallingChunksTransform, 32);

        _camera.Hitted += OnHitted;

        var magicaVoxelReader = new MagicaReader();
        var path       = GetPathInStreamingAssets(_volumePath);
        var magicaFile = magicaVoxelReader.LoadFile(path);

        _voxelModel = magicaFile.ToModel(_volumeSize);

        var chunkSize   = _chunkSize;
        var chunksCount = _chunkDrawSize.x * _chunkDrawSize.y * _chunkDrawSize.z;

        Debug.Log($"chunksCount = {chunksCount}");

        for (var i = 0; i < chunksCount; i++)
        {
            var chunkPositionNormalized = VoxelUtility.GetVoxelPosition(i, _chunkDrawSize);
            var chunkIndex      = VoxelChunkUtility.GetIndex(chunkPositionNormalized);
            var chunkPosition   = chunkPositionNormalized * chunkSize;
            var chunkGameObject = new GameObject();
            var chunkView       = chunkGameObject.AddComponent <VolumeChunk>();

            chunkGameObject.name = $"VolumeChunk[{i}]";

            chunkView.SetPosition(new Vector3(chunkPosition.x, chunkPosition.y, chunkPosition.z));
            chunkView.SetParent(_volumeChunksTransform);
            chunkView.SetMaterial(_chunkMaterial);
            chunkView.SetLayer(VolumeChunk.VolumeLayer);

            _chunks[chunkIndex] = chunkView;

            var geometryRequest = GetGeometryRequestById(chunkIndex);
            _chunkRequestQueue.Push(geometryRequest);
        }

        _chunkRenderer = new VoxelChunkRenderer(_cameraTransform, _chunks, _volumeSize, _chunkSize, _chunkDrawSize);
        _chunkRenderer.ChunkUpdated += OnChunkUpdated;
    }
        public static VoxelGeometryVolumeRequest CreateVolumeRequest(int chunkIndex,
                                                                     Vector3Int chunkSize, VoxelModel model, Vector3Int chunkDimensions)
        {
            var position = VoxelUtility.GetVoxelPosition(chunkIndex, chunkDimensions);

            var request = new VoxelGeometryVolumeRequest
            {
                chunkPosition         = new Vector3Int(position.x, position.y, position.z),
                chunkSize             = chunkSize,
                scale                 = 1f,
                pivot                 = new Vector3(0.0f, 0.0f, 0.0f),
                model                 = model,
                faceColorMultipliers  = FaceColorMultipliers,
                edgeColorMultiplier   = new Vector3(0.07f, 0.08f, 0.12f),
                cornerColorMultiplier = new Vector3(-0.14f, -0.25f, -0.4f)
            };

            return(request);
        }
Beispiel #7
0
        public void Execute(int index)
        {
            int xGrid = index / totalGridCount.y; //[0,totalGridCount.x)
            int yGrid = index % totalGridCount.y;

            bool inside = false;

            for (int z = 0; z != totalGridCount.z - 1; ++z)
            {
                int faceIndex = VoxelUtility.GetSurfaceIndex(new int3(xGrid, yGrid, z), new int3(xGrid, yGrid, z + 1));
                if (surfaceFaces.TryGetValue(faceIndex, out bool v))
                {
                    inside = !inside;
                }
                if (inside)
                {
                    volumeVoxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(xGrid, yGrid, z + 1)), true);
                }
            }
        }
Beispiel #8
0
        public void Iterate_Over_KeysWithRefs()
        {
            var count      = 10;
            var dictionary = GetDictionary();

            var sw = Stopwatch.StartNew();

            for (var i = 0; i < count; i++)
            {
                foreach (var key in dictionary.Keys)
                {
                    var     position = VoxelUtility.GetPositionByHash(key);
                    var     index    = VoxelUtility.GetVoxelIndex(position, _voxelsSize);
                    ref var voxel    = ref _voxels[index];
                    var     color    = voxel.colorIndex;

                    voxel.data       = 0;
                    voxel.colorIndex = 0;
                }
            }
Beispiel #9
0
    public static VoxelModel ToModel(this MagicaFile magicaFile, Vector3Int volumeSize)
    {
        var magicaChunks = magicaFile.Chunks;
        var volume       = new VoxelModel(volumeSize, magicaFile.Palette);

        var minPosition = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue);
        var maxPosition = new Vector3Int(int.MinValue, int.MinValue, int.MinValue);
        var magicaSize  = new Vector3();

        for (var chunkIndex = 0; chunkIndex < magicaChunks.Length; chunkIndex++)
        {
            var magicaChunk     = magicaChunks[chunkIndex];
            var defaultPosition = magicaChunk.position;
            var chunkSize       = magicaChunk.size;
            var chunkPosition   = defaultPosition - chunkSize / 2;

            magicaChunk.position = chunkPosition;

            for (var i = 0; i < 3; i++)
            {
                if (chunkPosition[i] < minPosition[i])
                {
                    minPosition[i] = chunkPosition[i];
                }
            }

            for (var i = 0; i < 3; i++)
            {
                if (chunkPosition[i] + chunkSize[i] > maxPosition[i])
                {
                    maxPosition[i] = chunkPosition[i] + chunkSize[i];
                }
            }

            for (var i = 0; i < 3; i++)
            {
                magicaSize[i] = maxPosition[i] - minPosition[i];
            }

            magicaChunks[chunkIndex] = magicaChunk;
        }

        foreach (var chunk in magicaChunks)
        {
            var voxels             = chunk.voxels;
            var chunkPosition      = new Vector3Int(chunk.position.x, chunk.position.y, chunk.position.z);
            var positionAdjustment = chunkPosition - minPosition;
            var rotation           = chunk.rotation;
            var size = chunk.size;

            foreach (var magicaVoxel in voxels)
            {
                var voxelPosition = new Vector3Int(magicaVoxel.x, magicaVoxel.y, magicaVoxel.z);

                for (var i = 0; i < 3; i++)
                {
                    var multiplier = rotation[i];

                    if (multiplier != 1)
                    {
                        var value = voxelPosition[i] * multiplier;
                        voxelPosition[i] = size[i] + value - 1;
                    }
                }

                var position = voxelPosition + positionAdjustment;
                var index    = VoxelUtility.GetVoxelIndex(position, volumeSize);

                var voxel = new VoxelEntity
                {
                    colorIndex = magicaVoxel.colorIndex,
                    data       = 100
                };

                volume.SetVoxel(index, voxel);
            }
        }

        return(volume);
    }
Beispiel #10
0
        private void coverVoxelsWithTriangleEdge(float3 A, float3 B)
        {
            int3   aVoxelIndex  = VoxelUtility.PosToIndex3(A);
            int3   bVoxelIndex  = VoxelUtility.PosToIndex3(B);
            int    aVoxelIndex1 = VoxelUtility.Index3ToIndex1(aVoxelIndex);
            int    bVoxeklndex1 = VoxelUtility.Index3ToIndex1(bVoxelIndex);
            float3 aVoxelCenter = VoxelUtility.Index3ToPos(aVoxelIndex);
            float3 bVoxelCenter = VoxelUtility.Index3ToPos(bVoxelIndex);

            if (aVoxelIndex.x == bVoxelIndex.x && aVoxelIndex.y == bVoxelIndex.y ||
                aVoxelIndex.x == bVoxelIndex.x && aVoxelIndex.z == bVoxelIndex.z ||
                aVoxelIndex.y == bVoxelIndex.y && aVoxelIndex.z == bVoxelIndex.z)
            {
                /*Same Grid or 6-neighbor*/
                voxels.TryAdd(aVoxelIndex1, true);
                voxels.TryAdd(bVoxeklndex1, true);
                return;
            }

            if (aVoxelIndex.x == bVoxelIndex.x)
            {
                /*yz plane neighbor */
                float2 xy = LinePlaneIntersect(A, B, 'z', 0.5f * (aVoxelCenter.z + bVoxelCenter.z));
                float  x  = xy.x;
                float  y  = xy.y;

                //if (!(A.x <= x && x <= B.x || B.x <= x && x <= A.x)){
                //    Debug.Log(A + "<>" + B + "<>" + aVoxelCenter + "<>" + bVoxelCenter + " -> " + x);
                //}
                //Debug.Assert(A.x <= x && x <= B.x || B.x <= x && x <= A.x);
                int connector;
                if (math.abs(y - A.y) < math.abs(y - B.y))
                {
                    connector = VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, aVoxelIndex.y, bVoxelIndex.z));
                }
                else
                {
                    connector = VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, bVoxelIndex.y, aVoxelIndex.z));
                }
                voxels.TryAdd(connector, true);
                return;
            }

            if (aVoxelIndex.y == bVoxelIndex.y)
            {
                /*xz plane neighbor */
                float2 yz = LinePlaneIntersect(A, B, 'x', 0.5f * (aVoxelCenter.x + bVoxelCenter.x));
                float  y  = yz.x;
                float  z  = yz.y;
                //Debug.Assert(A.y <= y && y <= B.y || B.y <= y && y <= A.y);
                int connector;
                if (math.abs(z - A.z) < math.abs(z - B.z))
                {
                    connector = VoxelUtility.Index3ToIndex1(new int3(bVoxelIndex.x, aVoxelIndex.y, aVoxelIndex.z));
                }
                else
                {
                    connector = VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, aVoxelIndex.y, bVoxelIndex.z));
                }
                voxels.TryAdd(connector, true);
                return;
            }

            if (aVoxelIndex.z == bVoxelIndex.z)
            {
                /*xy plane neighbor */
                float2 xz = LinePlaneIntersect(A, B, 'y', 0.5f * (aVoxelCenter.y + bVoxelCenter.y));
                float  x  = xz.x;
                float  z  = xz.y;
                //Debug.Assert(A.z <= z && z <= B.z || B.z <= z && z <= A.z);
                int connector;
                if (math.abs(x - A.x) < math.abs(x - B.x))
                {
                    connector = VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, bVoxelIndex.y, aVoxelIndex.z));
                }
                else
                {
                    connector = VoxelUtility.Index3ToIndex1(new int3(bVoxelIndex.x, aVoxelIndex.y, aVoxelIndex.z));
                }
                voxels.TryAdd(connector, true);
                return;
            }

            /*3D diagonal */
            float2 _yz = LinePlaneIntersect(A, B, 'x', 0.5f * (aVoxelCenter.x + bVoxelCenter.x));

            if (RectContains(new float2(aVoxelCenter.y, aVoxelCenter.z), _yz))
            {
                /*baa */
                voxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(bVoxelIndex.x, aVoxelIndex.y, aVoxelIndex.z)), true);
            }
            else
            {
                if (RectContains(new float2(bVoxelCenter.y, bVoxelCenter.z), _yz))
                {
                    /*abb */
                    voxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, bVoxelIndex.y, bVoxelIndex.z)), true);
                }
            }

            float2 _xz = LinePlaneIntersect(A, B, 'y', 0.5f * (aVoxelCenter.y + bVoxelCenter.y));

            if (RectContains(new float2(aVoxelCenter.x, aVoxelCenter.z), _xz))
            {
                /*aba */
                voxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, bVoxelIndex.y, aVoxelIndex.z)), true);
            }
            else
            {
                if (RectContains(new float2(bVoxelCenter.x, bVoxelCenter.z), _xz))
                {
                    /*bab */
                    voxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(bVoxelIndex.x, aVoxelIndex.y, bVoxelIndex.z)), true);
                }
            }

            float2 _xy = LinePlaneIntersect(A, B, 'z', 0.5f * (aVoxelCenter.z + bVoxelCenter.z));

            if (RectContains(new float2(aVoxelCenter.x, aVoxelCenter.y), _xy))
            {
                /*aab */
                voxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(aVoxelIndex.x, aVoxelIndex.y, bVoxelIndex.z)), true);
            }
            else
            {
                if (RectContains(new float2(bVoxelCenter.x, bVoxelCenter.y), _xy))
                {
                    /*bba */
                    voxels.TryAdd(VoxelUtility.Index3ToIndex1(new int3(bVoxelIndex.x, bVoxelIndex.y, aVoxelIndex.z)), true);
                }
            }
        }
Beispiel #11
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var voxelArray = volumetric ? volumePosArray : surfacePosArray;

        int existingCount = newGroup.CalculateLength() + movingGroup.CalculateLength() + finishedGroup.CalculateLength();
        int incAmount     = math.min((int)math.ceil(voxelArray.Length / minDuration * Time.deltaTime), voxelArray.Length - existingCount);

        //Debug.Log(finishedGroup.CalculateLength() + " finished");

        if (finishedGroup.CalculateLength() == voxelArray.Length)
        {
            Debug.Log("Finished");
            return(inputDeps);
        }

        //When there's too much moving job, stop adding new objects
        if (movingGroup.CalculateLength() >= maxMovingNumber)
        {
            incAmount = 0;
        }

        // Move
        NativeHashMap <Entity, bool> reachedTargetVoxel = new NativeHashMap <Entity, bool>(movingGroup.CalculateLength(), Allocator.TempJob);
        var moveJob = new MoveVoxel {
            finishedOutput = reachedTargetVoxel.ToConcurrent(),
            deltaTime      = Time.deltaTime,
            lerpSpeed      = randomGenerater,
            tolerance      = voxelSize * 0.1f,
        };
        JobHandle moveHandle = moveJob.Schedule(movingGroup, inputDeps);

        moveHandle.Complete();

        // Spawn
        var entities = new NativeArray <Entity>(incAmount, Allocator.TempJob);

        EntityManager.Instantiate(voxelPrefab, entities);
        var spawnPositions = new NativeArray <float3>(incAmount, Allocator.TempJob);

        GeneratePoints.RandomPointsInUnitSphere(spawnPositions);

        int spawnBase = finishedGroup.CalculateLength() + movingGroup.CalculateLength();

        for (int i = 0; i != incAmount; ++i)
        {
            RenderMesh m = EntityManager.GetSharedComponentData <RenderMesh>(entities[i]);
            m.material = VoxelUtility.GetMaterial(VoxelUtility.Index1ToPos(voxelArray[i + spawnBase]).y);
            EntityManager.SetSharedComponentData(entities[i], m);

            EntityManager.SetComponentData(entities[i], new Voxel {
                targetPosition = VoxelUtility.Index1ToPos(voxelArray[i + spawnBase])
            });

            Vector3 rdnCenter  = spawnPositions[i];
            float3  rdnCenterf = VoxelUtility.BBoxCenter + (float3)rdnCenter * VoxelUtility.DiagonalLength;

            var localToWorld = new LocalToWorld
            {
                Value = float4x4.TRS(
                    rdnCenterf,
                    quaternion.Euler(
                        UnityEngine.Random.Range(0.0f, 360f),
                        UnityEngine.Random.Range(0.0f, 360f),
                        UnityEngine.Random.Range(0.0f, 360f)),
                    new float3(voxelSize, voxelSize, voxelSize))
            };

            EntityManager.SetComponentData(entities[i], localToWorld);
        }

        EntityManager.RemoveComponent(entities, ComponentType.ReadWrite <NewVoxel>());
        EntityManager.AddComponent(entities, ComponentType.ReadWrite <MovingVoxel>());

        var justReachedVoxels = reachedTargetVoxel.GetKeyArray(Allocator.TempJob);

        EntityManager.RemoveComponent(justReachedVoxels, ComponentType.ReadWrite <MovingVoxel>());

        entities.Dispose();
        reachedTargetVoxel.Dispose();
        justReachedVoxels.Dispose();
        spawnPositions.Dispose();

        return(moveHandle);
    }
Beispiel #12
0
    protected override void OnCreateManager()
    {
        //Comment this in Build version
        // UnityEditor.SceneView.FocusWindowIfItsOpen(typeof(UnityEditor.SceneView));

        randomGenerater = new Unity.Mathematics.Random(1);

        modelPrefab = Resources.Load <GameObject>(modelName);
        modelMesh   = ((MeshFilter)modelPrefab.GetComponentInChildren(typeof(MeshFilter))).sharedMesh;

        VoxelUtility.Init(modelMesh, voxelSize, bottomColor, topColor);
        VoxelUtility.Describe();

        float3[] f3Vertex    = modelMesh.vertices.ToList().ConvertAll(input => new float3(input.x, input.y, input.z)).ToArray();
        var      meshVertexs = new NativeArray <float3>(f3Vertex, Allocator.TempJob);

        int3[] i3Triangle = new int3[modelMesh.triangles.Length / 3];

        int[] tri = modelMesh.triangles;
        for (int i = 0; i != i3Triangle.Length; ++i)
        {
            i3Triangle[i].x = tri[i * 3];
            i3Triangle[i].y = tri[i * 3 + 1];
            i3Triangle[i].z = tri[i * 3 + 2];
        }

        var meshTriangles = new NativeArray <int3>(i3Triangle, Allocator.TempJob);

        hashMap = new NativeHashMap <int, bool>(VoxelUtility.TotalGridsCount, Allocator.TempJob);

        var HashTriangleToVoxelJob = new HashTriangleToVoxel {
            vertexs   = meshVertexs,
            triangles = meshTriangles,
            voxels    = hashMap.ToConcurrent(),
        };

        JobHandle toSurfaceVoxelHandle = HashTriangleToVoxelJob.Schedule(i3Triangle.Length, 64);

        toSurfaceVoxelHandle.Complete();
        surfacePosArray = hashMap.GetKeyArray(Allocator.Persistent); // Length = # surface voxels

        /*End of step a */
        NativeHashMap <int, bool> surfaceHashMap = new NativeHashMap <int, bool>(VoxelUtility.TotalGridsCount * 3, Allocator.TempJob);
        var HashVoxelCommonFaceJob = new HashSurfaceVoxelUnCommonFace {
            surfaceVoxels      = hashMap,
            surfaceVoxelsIndex = surfacePosArray,
            surfaceFaces       = surfaceHashMap.ToConcurrent()
        };
        JobHandle toSurfaceFaceHandle = HashVoxelCommonFaceJob.Schedule(surfacePosArray.Length, 64, toSurfaceVoxelHandle);

        toSurfaceFaceHandle.Complete();

        Debug.Log("# Face Before removal: NumFace = " + surfaceHashMap.Length + " \nNumV= " + hashMap.Length);
        RemoveOneConsecutiveSurface(ref surfaceHashMap);
        Debug.Log("Faces Count After removal: " + surfaceHashMap.Length);

        /*End of step c*/
        int3 totalGridsCount = VoxelUtility.CalculateTotalGrids;
        NativeHashMap <int, bool> volumeHashMap = new NativeHashMap <int, bool>(VoxelUtility.TotalGridsCount, Allocator.TempJob);
        var castRayToVolumeJob = new CastRayToVolume {
            surfaceFaces   = surfaceHashMap,
            volumeVoxels   = volumeHashMap.ToConcurrent(),
            totalGridCount = totalGridsCount
        };
        JobHandle castRayHandle = castRayToVolumeJob.Schedule(totalGridsCount.x * totalGridsCount.y, 64, toSurfaceFaceHandle);

        castRayHandle.Complete();

        volumePosArray = volumeHashMap.GetKeyArray(Allocator.Persistent);
        Debug.Log("Surface voxels Count: " + surfacePosArray.Length);
        Debug.Log("Volume voxels Count: " + volumePosArray.Length);

        meshVertexs.Dispose();
        meshTriangles.Dispose();
        hashMap.Dispose();
        surfaceHashMap.Dispose();
        volumeHashMap.Dispose();

        if (randomOrder)
        {
            Shuffle(surfacePosArray);
            Shuffle(volumePosArray);
        }
        voxelPrefab = Resources.Load <GameObject>("Voxel");

        newGroup = GetEntityQuery(new EntityQueryDesc
        {
            All     = new [] { ComponentType.ReadWrite <Voxel>(), ComponentType.ReadWrite <LocalToWorld>(), ComponentType.ReadWrite <NewVoxel>() },
            Options = EntityQueryOptions.Default
        });

        movingGroup = GetEntityQuery(new EntityQueryDesc
        {
            All     = new [] { ComponentType.ReadWrite <Voxel>(), ComponentType.ReadWrite <LocalToWorld>(), ComponentType.ReadWrite <MovingVoxel>() },
            Options = EntityQueryOptions.Default
        });

        finishedGroup = GetEntityQuery(new EntityQueryDesc
        {
            All     = new [] { ComponentType.ReadWrite <Voxel>(), ComponentType.ReadWrite <LocalToWorld>() },
            None    = new ComponentType[] { ComponentType.ReadWrite <MovingVoxel>(), ComponentType.ReadWrite <NewVoxel>() },
            Options = EntityQueryOptions.Default
        });
    }
Beispiel #13
0
    void RemoveOneConsecutiveSurface(ref NativeHashMap <int, bool> hashmap)
    {
        NativeHashMap <int, bool> removedSurface = new NativeHashMap <int, bool>(hashmap.Capacity, Allocator.TempJob);

        var keys   = hashmap.GetKeyArray(Allocator.TempJob);
        int index1 = keys[0];

        keys.Dispose();

        Queue <int> toBeRemoved = new Queue <int>();

        toBeRemoved.Enqueue(index1);
        //Debug.Log("Removal starts from " + VoxelUtility.getFacePosition(index1));

        while (toBeRemoved.Count > 0)
        {
            int workingIndex = toBeRemoved.Dequeue();
            hashmap.Remove(workingIndex);
            removedSurface.TryAdd(workingIndex, true);
            int3 voxel1, voxel2;
            (voxel1, voxel2) = VoxelUtility.SurfaceIndexToVoxels(workingIndex);

            int3[] neighborInc = new int3[4];
            if (voxel1.x != voxel2.x)
            {
                neighborInc[0] = new int3(0, 1, 0);
                neighborInc[1] = new int3(0, -1, 0);
                neighborInc[2] = new int3(0, 0, 1);
                neighborInc[3] = new int3(0, 0, -1);
            }
            if (voxel1.y != voxel2.y)
            {
                neighborInc[0] = new int3(1, 0, 0);
                neighborInc[1] = new int3(-1, 0, 0);
                neighborInc[2] = new int3(0, 0, 1);
                neighborInc[3] = new int3(0, 0, -1);
            }
            if (voxel1.z != voxel2.z)
            {
                neighborInc[0] = new int3(1, 0, 0);
                neighborInc[1] = new int3(-1, 0, 0);
                neighborInc[2] = new int3(0, 1, 0);
                neighborInc[3] = new int3(0, -1, 0);
            }
            foreach (int3 voxel in new int3[] { voxel1, voxel2 })
            {
                foreach (int3 inc in neighborInc)
                {
                    int3 candidateNeighbor = voxel + inc;
                    int  candidateFace     = VoxelUtility.GetSurfaceIndex(voxel, candidateNeighbor);
                    if (hashmap.TryGetValue(candidateFace, out bool v))
                    {
                        if (v)
                        {
                            // only enqueue newly discovered neighbor
                            toBeRemoved.Enqueue(candidateFace);

                            // set face's flag to False: it has already be put into queue
                            hashmap.Remove(candidateFace);
                            hashmap.TryAdd(candidateFace, false);
                        }
                    }
                }
            }
            foreach (int3 inc in neighborInc)
            {
                int3 voxel1Offseted = voxel1 + inc;
                int3 voxel2Offseted = voxel2 + inc;
                int  candidateFace  = VoxelUtility.GetSurfaceIndex(voxel1Offseted, voxel2Offseted);
                if (hashmap.TryGetValue(candidateFace, out bool v))
                {
                    if (v)
                    {
                        // only enqueue newly discovered neighbor
                        toBeRemoved.Enqueue(candidateFace);

                        // set face's flag to False: it has already be put into queue
                        hashmap.Remove(candidateFace);
                        hashmap.TryAdd(candidateFace, false);
                    }
                }
            }
        }
        if (hashmap.Length < removedSurface.Length)
        {
            hashmap.Dispose();
            hashmap = removedSurface;
        }
        else
        {
            removedSurface.Dispose();
        }
    }
Beispiel #14
0
    public VoxelHitInfo GetHitInfo(RaycastHit hit)
    {
        var direction = _meshRayCastUseCase.HitDirection.Value;

        return(new VoxelHitInfo(this, hit.point, VoxelUtility.DirectionalCenterPoint(CachedTransform.position, direction), direction));
    }