/// <summary>
        /// World position to block-local voxel coordinate.
        /// </summary>
        public static VectorI3 WorldToBlockVoxel(Vector3 WorldPosition)
        {
            VectorI3 voxel = new VectorI3();
            double   x     = (((double)WorldPosition.x % HighPrecision.kBlockSize) * HighPrecision.kOneOverVoxelSize);
            double   y     = (((double)WorldPosition.y % HighPrecision.kBlockSize) * HighPrecision.kOneOverVoxelSize);
            double   z     = (((double)WorldPosition.z % HighPrecision.kBlockSize) * HighPrecision.kOneOverVoxelSize);

            if (x < 0)
            {
                voxel.x = (int)x - 1 + kVoxelsPerBlock;
            }
            else
            {
                voxel.x = (int)x;
            }

            if (y < 0)
            {
                voxel.y = (int)y - 1 + kVoxelsPerBlock;
            }
            else
            {
                voxel.y = (int)y;
            }

            if (z < 0)
            {
                voxel.z = (int)z - 1 + kVoxelsPerBlock;
            }
            else
            {
                voxel.z = (int)z;
            }
            return(voxel);
        }
 public VectorI4(VectorI3 vector)
 {
     this.x = vector.x;
     this.y = vector.y;
     this.z = vector.z;
     w      = 0;
 }
        /// <summary>
        /// Clamp block-local coordinates to [0, kVoxelsPerBlock) range and adjust block.
        /// </summary>
        public static VectorI3 ClampBlockVoxel(VectorI3 block, ref int vx, ref int vy, ref int vz)
        {
            while (vx < 0)
            {
                vx += kVoxelsPerBlock;
                --block.x;
            }
            while (vx >= kVoxelsPerBlock)
            {
                vx -= kVoxelsPerBlock;
                ++block.x;
            }
            while (vy < 0)
            {
                vy += kVoxelsPerBlock;
                --block.y;
            }
            while (vy >= kVoxelsPerBlock)
            {
                vy -= kVoxelsPerBlock;
                ++block.y;
            }
            while (vz < 0)
            {
                vz += kVoxelsPerBlock;
                --block.z;
            }
            while (vz >= kVoxelsPerBlock)
            {
                vz -= kVoxelsPerBlock;
                ++block.z;
            }

            return(block);
        }
        /// <summary>
        /// Initializes array of blocks and the neighbour references in blocks and chunks.
        /// </summary>
        public void Initialize()
        {
            _worldApi = GetComponent <WorldApi>();

            // initialize arrays
            _blocks = new Block[_worldApi.SizeX * _worldApi.SizeY * _worldApi.SizeZ];

            _worldApi.Initialize(_blocks);

            for (int blockX = 0; blockX < _worldApi.SizeX; blockX++)
            {
                for (int blockY = 0; blockY < _worldApi.SizeY; blockY++)
                {
                    for (int blockZ = 0; blockZ < _worldApi.SizeZ; blockZ++)
                    {
                        int blockId = blockX * _worldApi.SizeZ * _worldApi.SizeY + blockY * _worldApi.SizeZ + blockZ;

                        VectorI3 coords = new VectorI3(blockX, blockY, blockZ);

                        Block block = new GameObject($"Block ({blockX}, {blockY}, {blockZ})").AddComponent <Block>();
                        _blocks[blockId] = block;

                        block.Initialize(blockId, transform, _worldApi, coords);
                    }
                }
            }

            InitializeBlockReferences();

            for (int blockId = 0; blockId < _blocks.Length; blockId++)
            {
                _blocks[blockId].InitializeChunkReferences();
            }
        }
 public static ICollection <VectorI3> Clone(VectorI3 vectorI3, int count)
 {
     return
         (Enumerable
          .Range(0, count)
          .Select(_ => Clone(vectorI3))
          .ToList());
 }
        /// <summary>
        /// Global voxel coordinate to world position of origin of the voxel.
        /// </summary>
        public static Vector3 VoxelToWorld(VectorI3 voxel)
        {
            //double helps but does not eliminate precision problems
            float x = (float)(voxel.x * HighPrecision.kVoxelSize);
            float y = (float)(voxel.y * HighPrecision.kVoxelSize);
            float z = (float)(voxel.z * HighPrecision.kVoxelSize);

            return(new Vector3(x, y, z));
        }
        /// <summary>
        /// Clamp block-local coordinates to [0, kVoxelsPerBlock) range and adjust block.
        /// </summary>
        public static VectorI3 ClampBlockVoxel(VectorI3 block, ref VectorI3 voxel)
        {
            int vx = voxel.x;
            int vy = voxel.y;
            int vz = voxel.z;

            block   = ClampBlockVoxel(block, ref vx, ref vy, ref vz);
            voxel.x = vx;
            voxel.y = vy;
            voxel.z = vz;
            return(block);
        }
 public static VectorI3 Clone(VectorI3 vectorI3)
 {
     return
         (vectorI3 != null ?
          new VectorI3
     {
         X = vectorI3.X,
         Y = vectorI3.Y,
         Z = vectorI3.Z
     }
         : null);
 }
Exemple #9
0
    private Mesh GetMesh(Vector3 chunkWorldPos, bool solid, Viscosity viscosity = default)
    {
        _vertices.Clear();
        _triangles.Clear();

        for (int voxelId = 0; voxelId < WorldGridInfo.kTotalVoxelsInChunk; voxelId++)
        {
            VectorI3 posI = WorldGridInfo.VoxelIdToChunkVoxel(voxelId);
            Vector3  pos  = new Vector3(posI.x, posI.y, posI.z);

            _cubeVertices[0] = pos + new Vector3(0, 0, 1);
            _cubeVertices[1] = pos + new Vector3(1, 0, 1);
            _cubeVertices[2] = pos + new Vector3(1, 0, 0);
            _cubeVertices[3] = pos + new Vector3(0, 0, 0);
            _cubeVertices[4] = pos + new Vector3(0, 1, 1);
            _cubeVertices[5] = pos + new Vector3(1, 1, 1);
            _cubeVertices[6] = pos + new Vector3(1, 1, 0);
            _cubeVertices[7] = pos + new Vector3(0, 1, 0);

            for (int i = 0; i < _cubeVertices.Length; i++)
            {
                pos = _cubeVertices[i] + Vector3.one;
                Voxel voxel = _borderedChunk[(int)(pos.x * Chunk.kColumnBordered + pos.y * Chunk.kRowBordered + pos.z)];

                _cubeVertices[i] *= WorldGridInfo.kVoxelSize;
                _cubeVertices[i] += chunkWorldPos;

                if (solid)
                {
                    _cubeValues[i] = !_worldApi.IsBorder(in _cubeVertices[i]) ? voxel.Solid * Voxel.kByteToFloat : 0;
                }
                else
                {
                    _cubeValues[i] = voxel.Viscosity == (byte)viscosity ? voxel.Fluid * Voxel.kByteToFloat : 0;
                }
            }

            Polygonise();
        }

        Mesh mesh = new Mesh();

        mesh.vertices  = new List <Vector3>(_vertices.Keys).ToArray();
        mesh.triangles = _triangles.ToArray();
        mesh.RecalculateNormals();

        return(mesh);
    }
        /// <summary>
        /// Clamp block-local voxel coordinates into range [0, kVoxelsPerBlocks) and return the offset in blocks used.
        /// </summary>
        /// <remarks>
        /// Works values that are less than kVoxelPerBlock distant from range.
        /// </remarks>
        public static bool ClampBlockVoxel(ref int vx, ref int vy, ref int vz, out VectorI3 offset)
        {
            bool rv = false;

            offset = default(VectorI3);
            if (vx >= WorldGridInfo.kVoxelsPerBlock)
            {
                vx      -= WorldGridInfo.kVoxelsPerBlock;
                offset.x = 1;
                rv       = true;
            }
            else if (vx < 0)
            {
                vx      += WorldGridInfo.kVoxelsPerBlock;
                offset.x = -1;
                rv       = true;
            }

            if (vy >= WorldGridInfo.kVoxelsPerBlock)
            {
                offset.y = 1;
                vy      -= WorldGridInfo.kVoxelsPerBlock;
                rv       = true;
            }
            else if (vy < 0)
            {
                offset.y = -1;
                vy      += WorldGridInfo.kVoxelsPerBlock;
                rv       = true;
            }

            if (vz >= WorldGridInfo.kVoxelsPerBlock)
            {
                offset.z = 1;
                vz      -= WorldGridInfo.kVoxelsPerBlock;
                rv       = true;
            }
            else if (vz < 0)
            {
                offset.z = -1;
                vz      += WorldGridInfo.kVoxelsPerBlock;
                rv       = true;
            }

            return(rv);
        }
        /// <summary>
        /// Initialize array of voxels and chunks.
        /// </summary>
        public void Initialize(int id, Transform parent, WorldApi worldApi, VectorI3 coords)
        {
            Id = id;
            transform.parent = parent;
            Coords           = coords;

            worldApi.GetBlockWorldPos(id, out Vector3 worldPos);
            WorldPos = worldPos;

            Chunks  = new Chunk[WorldGridInfo.kTotalChunksInBlock];
            _voxels = new NativeArray <Voxel>(WorldGridInfo.kTotalVoxelsInBlock, Unity.Collections.Allocator.Persistent);

            SimData            = new FluidBlockSimData(this);
            SimData.ReadVoxels = _voxels;

            for (int chunkX = 0; chunkX < WorldGridInfo.kChunksPerBlock; chunkX++)
            {
                for (int chunkY = 0; chunkY < WorldGridInfo.kChunksPerBlock; chunkY++)
                {
                    for (int chunkZ = 0; chunkZ < WorldGridInfo.kChunksPerBlock; chunkZ++)
                    {
                        int chunkId = chunkX * WorldGridInfo.kChunksPerBlock * WorldGridInfo.kChunksPerBlock + chunkY * WorldGridInfo.kChunksPerBlock + chunkZ;

                        Chunk chunk = new GameObject($"Chunk ({chunkX}, {chunkY}, {chunkZ})").AddComponent <Chunk>();
                        Chunks[chunkId] = chunk;

                        chunk.Initialize(chunkId, transform, worldApi, this);

                        for (int voxelX = 0; voxelX < WorldGridInfo.kVoxelsPerChunk; voxelX++)
                        {
                            for (int voxelY = 0; voxelY < WorldGridInfo.kVoxelsPerChunk; voxelY++)
                            {
                                for (int voxelZ = 0; voxelZ < WorldGridInfo.kVoxelsPerChunk; voxelZ++)
                                {
                                    int voxelId = voxelX * WorldGridInfo.kVoxelsPerChunk * WorldGridInfo.kVoxelsPerChunk + voxelY * WorldGridInfo.kVoxelsPerChunk + voxelZ;

                                    _voxels.GetWritable(chunkId, voxelId).Valid = true;
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// World space bounds of a block.
        /// </summary>
        public static Bounds BlockBounds(VectorI3 block)
        {
            Vector3 size = new Vector3(kBlockSize, kBlockSize, kBlockSize);

            return(new Bounds(BlockToWorld(block) + size * 0.5f, size));
        }
 /// <summary>
 /// World space block origin from block coordinates.
 /// </summary>
 public static Vector3 BlockToWorld(VectorI3 blockCoordinates)
 {
     return(new Vector3(blockCoordinates.x * kBlockSize, blockCoordinates.y * kBlockSize, blockCoordinates.z * kBlockSize));
 }
 public static VectorI3 Clone(this VectorI3 vectorI3)
 {
     return(BlueprintScrappinUtil.Clone(vectorI3));
 }
 public static ICollection <VectorI3> Clone(this VectorI3 vectorI3, int count)
 {
     return(BlueprintScrappinUtil.Clone(vectorI3, count));
 }