コード例 #1
0
        void RefreshNineChunks(VoxelChunk chunk, bool forceMeshRefresh = false)
        {
            if (chunk == null)
            {
                return;
            }

            int chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(chunk.position.x / CHUNK_SIZE, chunk.position.y / CHUNK_SIZE, chunk.position.z / CHUNK_SIZE, out chunkX, out chunkY, out chunkZ);

            VoxelChunk neighbour;

            for (int y = -1; y <= 1; y++)
            {
                for (int z = -1; z <= 1; z++)
                {
                    for (int x = -1; x <= 1; x++)
                    {
                        GetChunkFast(chunkX + x, chunkY + y, chunkZ + z, out neighbour);
                        if (neighbour != null)
                        {
                            ChunkRequestRefresh(neighbour, true, forceMeshRefresh);
                        }
                    }
                }
            }
        }
コード例 #2
0
        void RefreshNineChunks(VoxelChunk chunk)
        {
            if (chunk == null)
            {
                return;
            }

            Vector3 position = chunk.position;
            int     chunkX   = FastMath.FloorToInt(position.x / 16f);
            int     chunkY   = FastMath.FloorToInt(position.y / 16f);
            int     chunkZ   = FastMath.FloorToInt(position.z / 16f);

            VoxelChunk neighbour;

            for (int y = -1; y <= 1; y++)
            {
                for (int z = -1; z <= 1; z++)
                {
                    for (int x = -1; x <= 1; x++)
                    {
                        GetChunkFast(chunkX + x, chunkY + y, chunkZ + z, out neighbour);
                        if (neighbour != null)
                        {
                            ChunkRequestRefresh(neighbour, true, false);
                        }
                    }
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Gets the octree from a position and clears the explored flag to ensure that area can be refreshed again.
        /// Optionally remove the chunk from cache.
        /// </summary>
        void SetChunkOctreeIsDirty(Vector3 position, bool removeFromCache)
        {
            int chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(position.x / 16f, position.y / 16f, position.z / 16f, out chunkX, out chunkY, out chunkZ);
            int         existingChunkHash = GetChunkHash(chunkX, chunkY, chunkZ);
            CachedChunk cachedChunk;

            if (cachedChunks.TryGetValue(existingChunkHash, out cachedChunk))
            {
                Octree octree = cachedChunk.octree;
                while (octree != null)
                {
                    octree.explored = false;
                    if (octree.parent != null)
                    {
                        octree.parent.exploredChildren--;
                    }
                    octree = octree.parent;
                }
                if (removeFromCache)
                {
                    cachedChunks.Remove(existingChunkHash);
                }
            }
        }
コード例 #4
0
        void RefreshNineChunksMeshes(VoxelChunk chunk)
        {
            Vector3 position = chunk.position;
            int     chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(position.x / CHUNK_SIZE, position.y / CHUNK_SIZE, position.z / CHUNK_SIZE, out chunkX, out chunkY, out chunkZ);

            VoxelChunk neighbour;

            for (int y = -1; y <= 1; y++)
            {
                for (int z = -1; z <= 1; z++)
                {
                    for (int x = -1; x <= 1; x++)
                    {
                        if (y == 0 && x == 0 && z == 0)
                        {
                            continue;
                        }
                        GetChunkFast(chunkX + x, chunkY + y, chunkZ + z, out neighbour);
                        if (neighbour != null && neighbour != chunk)
                        {
                            ChunkRequestRefresh(neighbour, false, true);
                        }
                    }
                }
            }
            ChunkRequestRefresh(chunk, false, true);
        }
コード例 #5
0
        void UpdateVoxelHighlight()
        {
            if (voxelHighlightBuilder == null)
            {
                voxelHighlightBuilder = Instantiate <GameObject> (Resources.Load <GameObject> ("VoxelPlay/Prefabs/VoxelHighlight"));
            }

            Vector3 rawPos;

            if (crosshairOnBlock)
            {
                rawPos = crosshairHitInfo.voxelCenter + crosshairHitInfo.normal;
            }
            else
            {
                rawPos = m_Camera.transform.position + m_Camera.transform.forward * 4f;
            }

            // Bound check
            for (int i = 0; i < 50; i++)
            {
                if (limitBounds.Contains(rawPos))
                {
                    break;
                }
                rawPos -= m_Camera.transform.forward * 0.1f;
            }

            rawPos.x = FastMath.FloorToInt(rawPos.x) + 0.5f;
            if (rawPos.x > limitBounds.max.x)
            {
                rawPos.x = limitBounds.max.x - 0.5f;
            }
            if (rawPos.x < limitBounds.min.x)
            {
                rawPos.x = limitBounds.min.x + 0.5f;
            }
            rawPos.y = FastMath.FloorToInt(rawPos.y) + 0.5f;
            if (rawPos.y > limitBounds.max.y)
            {
                rawPos.y = limitBounds.max.y - 0.5f;
            }
            if (rawPos.y < limitBounds.min.y)
            {
                rawPos.y = limitBounds.min.y + 0.5f;
            }
            rawPos.z = FastMath.FloorToInt(rawPos.z) + 0.5f;
            if (rawPos.z > limitBounds.max.z)
            {
                rawPos.z = limitBounds.max.z - 0.5f;
            }
            if (rawPos.z < limitBounds.min.z)
            {
                rawPos.z = limitBounds.min.z + 0.5f;
            }
            voxelHighlightBuilder.transform.position = rawPos;
        }
コード例 #6
0
        VoxelChunk GetChunkOrCreate(Vector3 position)
        {
            int        x = FastMath.FloorToInt(position.x / 16);
            int        y = FastMath.FloorToInt(position.y / 16);
            int        z = FastMath.FloorToInt(position.z / 16);
            VoxelChunk chunk;

            GetChunkFast(x, y, z, out chunk, true);
            return(chunk);
        }
コード例 #7
0
        VoxelChunk GetChunkOrCreate(Vector3 position)
        {
            int x, y, z;

            FastMath.FloorToInt(position.x / 16, position.y / 16, position.z / 16, out x, out y, out z);
            VoxelChunk chunk;

            GetChunkFast(x, y, z, out chunk, true);
            return(chunk);
        }
コード例 #8
0
        VoxelChunk GetChunkOrCreate(Vector3 position)
        {
            int x, y, z;

            FastMath.FloorToInt(position.x / VoxelPlayEnvironment.CHUNK_SIZE, position.y / VoxelPlayEnvironment.CHUNK_SIZE, position.z / VoxelPlayEnvironment.CHUNK_SIZE, out x, out y, out z);
            VoxelChunk chunk;

            GetChunkFast(x, y, z, out chunk, true);
            return(chunk);
        }
コード例 #9
0
        void CheckNearChunks(Vector3 position)
        {
            if (!checkNearChunks)
            {
                return;
            }
            int chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(position.x / 16f, position.y / 16f, position.z / 16f, out chunkX, out chunkY, out chunkZ);
            if (lastChunkX != chunkX || lastChunkY != chunkY || lastChunkZ != chunkZ)
            {
                lastChunkX = chunkX;
                lastChunkY = chunkY;
                lastChunkZ = chunkZ;
                env.ChunkCheckArea(position, chunkExtents, renderChunks);
            }
        }
コード例 #10
0
        /// <summary>
        /// Paints the terrain inside the chunk defined by its central "position"
        /// </summary>
        /// <returns><c>true</c>, if terrain was painted, <c>false</c> otherwise.</returns>
        public override bool PaintChunk(VoxelChunk chunk)
        {
            int chunkBottomPos = FastMath.FloorToInt(chunk.position.y - VoxelPlayEnvironment.CHUNK_HALF_SIZE);

            if (chunkBottomPos >= altitude)
            {
                return(false);                // does not have contents
            }

            // Voxel Color (checker board style)
            Color32 voxelColor;
            uint    chance = (((uint)chunk.position.x + (uint)chunk.position.z) / VoxelPlayEnvironment.CHUNK_SIZE) % 2;

            if (chance == 1)
            {
                voxelColor = voxelColor1;
            }
            else
            {
                voxelColor = voxelColor2;
            }

            // a chunk is made of 16x16x16 voxels - calculate the last voxel position in the array to be filled
            // constant ONE_Y_ROW equals to the number of voxels in an horizontal slice (ie. 16*16 voxels per row)
            int maxY      = altitude - chunkBottomPos;
            int lastVoxel = maxY * ONE_Y_ROW;

            if (lastVoxel >= chunk.voxels.Length)
            {
                lastVoxel = chunk.voxels.Length;
            }

            // Fill the chunk.voxels 3D array with voxels
            for (int k = 0; k < lastVoxel; k++)
            {
                chunk.voxels [k].Set(terrainVoxel, voxelColor);
            }

            // For correct light illumination, specify if this chunk on surface level
            int chunkTopPos = (int)chunk.position.y + VoxelPlayEnvironment.CHUNK_HALF_SIZE;

            chunk.isAboveSurface = chunkTopPos >= altitude;

            return(true);            // true = > this chunk has contents
        }
コード例 #11
0
        void CheckNearChunks(Vector3 position)
        {
            if (!checkNearChunks)
            {
                return;
            }
            int chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(position.x / VoxelPlayEnvironment.CHUNK_SIZE, position.y / VoxelPlayEnvironment.CHUNK_SIZE, position.z / VoxelPlayEnvironment.CHUNK_SIZE, out chunkX, out chunkY, out chunkZ);
            if (lastChunkX != chunkX || lastChunkY != chunkY || lastChunkZ != chunkZ)
            {
                lastChunkX = chunkX;
                lastChunkY = chunkY;
                lastChunkZ = chunkZ;
                // Ensure area is rendered
                env.ChunkCheckArea(position, chunkExtents, renderChunks);
            }
        }
コード例 #12
0
        /// <summary>
        /// Checks if there's a voxel at given position.
        /// </summary>
        /// <returns><c>true</c>, if collision was checked, <c>false</c> otherwise.</returns>
        /// <param name="position">Position.</param>
        public bool CheckCollision(Vector3 position)
        {
            int        x     = FastMath.FloorToInt(position.x / 16);
            int        y     = FastMath.FloorToInt(position.y / 16);
            int        z     = FastMath.FloorToInt(position.z / 16);
            VoxelChunk chunk = GetChunkOrCreate(x, y, z);

            if (chunk != null)
            {
                Voxel[] voxels     = chunk.voxels;
                int     py         = (int)(position.y - y * 16);     // FastMath.FloorToInt (position.y) - y * 16;
                int     pz         = (int)(position.z - z * 16);     // FastMath.FloorToInt (position.z) - z * 16;
                int     px         = (int)(position.x - x * 16);     // FastMath.FloorToInt (position.x) - x * 16;
                int     voxelIndex = py * ONE_Y_ROW + pz * ONE_Z_ROW + px;
                return(voxels [voxelIndex].hasContent == 1 && voxelDefinitions [voxels [voxelIndex].typeIndex].navigatable);
            }
            return(false);
        }
コード例 #13
0
        void LateUpdate()
        {
            if (!env.initialized)
            {
                return;
            }

            // Check if position has changed since previous
            Vector3 position = transform.position;
            int     x, y, z;

            FastMath.FloorToInt(position.x, position.y, position.z, out x, out y, out z);

            if (lastX != x || lastY != y || lastZ != z)
            {
                requireUpdateLighting = true;

                lastPosition = position;
                lastX        = x;
                lastY        = y;
                lastZ        = z;

                if (forceUnstuck)
                {
                    Vector3 pos = transform.position;
                    pos.y += 0.1f;
                    if (env.CheckCollision(pos))
                    {
                        float deltaY = FastMath.FloorToInt(pos.y) + 1f - pos.y;
                        pos.y += deltaY + 0.01f;
                        transform.position = pos;
                        lastX--;
                    }
                }

                CheckNearChunks(position);
            }
            if (requireUpdateLighting)
            {
                requireUpdateLighting = false;
                UpdateLightingNow();
            }
        }
コード例 #14
0
        /// <summary>
        /// Gets heightmap info for 16x16 positions in a chunk
        /// </summary>
        /// <returns>The height map info.</returns>
        /// <param name="x">The x coordinate of the left-most position of the chunk.</param>
        /// <param name="z">The z coordinate of the back-most position of the chunk.</param>
        /// <param name="heightChunkData">An array of HeightMapInfo structs to be filled with data. The size of the array must be 16*16.</param>
        public void GetHeightMapInfoFast(float x, float z, HeightMapInfo[] heightChunkData)
        {
            int ix = FastMath.FloorToInt(x);
            int iz = FastMath.FloorToInt(z);
            VoxelPlayTerrainGenerator tg = world.terrainGenerator;

            HeightMapInfo[] heights;
            int             heightsIndex;

            for (int zz = 0; zz < 16; zz++)
            {
                for (int xx = 0; xx < 16; xx++)
                {
                    if (!heightMapCache.TryGetValue(ix + xx, iz + zz, out heights, out heightsIndex))
                    {
                        float altitude, moisture;
                        tg.GetHeightAndMoisture(ix + xx, iz + zz, out altitude, out moisture);
                        if (altitude > 1f)
                        {
                            altitude = 1f;
                        }
                        else if (altitude < 0f)
                        {
                            altitude = 0f;
                        }
                        if (moisture > 1f)
                        {
                            moisture = 1f;
                        }
                        else if (moisture < 0f)
                        {
                            moisture = 0f;
                        }
                        int biomeIndex = (int)(altitude * 20) * 21 + (int)(moisture * 20f);
                        heights [heightsIndex].groundLevel = (int)(altitude * tg.maxHeight);
                        heights [heightsIndex].moisture    = moisture;
                        heights [heightsIndex].biome       = biomeLookUp [biomeIndex];
                    }
                    heightChunkData [zz * 16 + xx] = heights [heightsIndex];
                }
            }
        }
コード例 #15
0
        void LateUpdate()
        {
            if (!env.initialized)
            {
                return;
            }

            // Check if position has changed since previous
            Vector3 position = transform.position;

            int x = FastMath.FloorToInt(position.x);
            int y = FastMath.FloorToInt(position.y);
            int z = FastMath.FloorToInt(position.z);

            if (lastX == x && lastY == y && lastZ == z)
            {
                return;
            }

            lastPosition = position;
            lastX        = x;
            lastY        = y;
            lastZ        = z;

            UpdateLighting();

            if (forceUnstuck)
            {
                Vector3 pos = transform.position;
                pos.y += 0.1f;
                if (env.CheckCollision(pos))
                {
                    float deltaY = FastMath.FloorToInt(pos.y) + 1f - pos.y;
                    pos.y += deltaY + 0.01f;
                    transform.position = pos;
                    lastX--;
                }
            }

            CheckNearChunks(position);
        }
        void ChunkRequestRefresh(Bounds bounds, bool clearLightmap, bool refreshMesh)
        {
            Vector3 position;
            Vector3 min = bounds.min;
            int     xmin, ymin, zmin;

            FastMath.FloorToInt(min.x / CHUNK_SIZE, min.y / CHUNK_SIZE, min.z / CHUNK_SIZE, out xmin, out ymin, out zmin);
            xmin *= CHUNK_SIZE;
            ymin *= CHUNK_SIZE;
            zmin *= CHUNK_SIZE;
            Vector3 max = bounds.max;
            int     xmax, ymax, zmax;

            FastMath.FloorToInt(max.x / CHUNK_SIZE, max.y / CHUNK_SIZE, max.z / CHUNK_SIZE, out xmax, out ymax, out zmax);
            xmax *= CHUNK_SIZE;
            ymax *= CHUNK_SIZE;
            zmax *= CHUNK_SIZE;

            for (int y = ymax; y >= ymin; y -= CHUNK_SIZE)
            {
                position.y = y;
                for (int z = zmin; z <= zmax; z += CHUNK_SIZE)
                {
                    position.z = z;
                    for (int x = xmin; x <= xmax; x += CHUNK_SIZE)
                    {
                        position.x = x;
                        VoxelChunk chunk;
                        if (GetChunk(position, out chunk, true))
                        {
                            ChunkRequestRefresh(chunk, clearLightmap, refreshMesh);
                        }
                    }
                }
            }
        }
コード例 #17
0
        /// <summary>
        /// Gets heightmap info on a given position. This method only works at runtime. Use GetTerainInfo() in Editor.
        /// </summary>
        /// <returns>The height map info.</returns>
        /// <param name="x">The x coordinate.</param>
        /// <param name="z">The z coordinate.</param>
        public HeightMapInfo GetHeightMapInfoFast(float x, float z)
        {
            int ix = FastMath.FloorToInt(x);
            int iz = FastMath.FloorToInt(z);

            HeightMapInfo[] heights;
            int             heightsIndex;

            if (!heightMapCache.TryGetValue(ix, iz, out heights, out heightsIndex))
            {
                float altitude, moisture;
                VoxelPlayTerrainGenerator tg = world.terrainGenerator;
                tg.GetHeightAndMoisture(x, z, out altitude, out moisture);
                if (altitude > 1f)
                {
                    altitude = 1f;
                }
                else if (altitude < 0f)
                {
                    altitude = 0f;
                }
                if (moisture > 1f)
                {
                    moisture = 1f;
                }
                else if (moisture < 0f)
                {
                    moisture = 0f;
                }
                int biomeIndex = (int)(altitude * 20) * 21 + (int)(moisture * 20f);
                heights [heightsIndex].groundLevel = (int)(altitude * tg.maxHeight);
                heights [heightsIndex].moisture    = moisture;
                heights [heightsIndex].biome       = biomeLookUp [biomeIndex];
            }
            return(heights [heightsIndex]);
        }
コード例 #18
0
        /// <summary>
        /// Move worms
        /// </summary>
        public override bool DoWork(long endTime)
        {
            int count = worms.Count;

            if (count == 0)
            {
                return(false);
            }

            for (int k = 0; k < count; k++)
            {
                env.STAGE = 3000;
                HoleWorm worm = worms [k];
                uint     xx   = (uint)worm.head.x % texSize;
                worm.ax += noiseValues [xx];
                if (worm.ax > 1f)
                {
                    worm.ax = 1f;
                }
                else if (worm.ax < -1f)
                {
                    worm.ax = -1f;
                }
                worm.head.x += worm.ax;
                uint yy = (uint)worm.head.y % texSize;
                worm.ay += noiseValues [yy];
                if (worm.ay > 1f)
                {
                    worm.ay = 1f;
                }
                else if (worm.ay < -1f)
                {
                    worm.ay = -1f;
                }
                worm.head.y += worm.ay;
                uint zz = (uint)worm.head.z % texSize;
                worm.az += noiseValues [zz];
                if (worm.az > 1f)
                {
                    worm.az = 1f;
                }
                else if (worm.az < -1f)
                {
                    worm.az = -1f;
                }
                worm.head.z += worm.az;
                int ix = (int)(worm.head.x);
                int iy = (int)(worm.head.y);
                int iz = (int)(worm.head.z);
                env.STAGE = 3001;
                if (ix != worm.lastX || iy != worm.lastY || iz != worm.lastZ)
                {
                    worm.lastX = ix;
                    worm.lastY = iy;
                    worm.lastZ = iz;

                    // keep this order of assignment to improve randomization
                    int minx = ix - (caveBorder++ & 5);
                    int miny = iy - (caveBorder++ & 5);
                    int maxx = ix + (caveBorder++ & 5);
                    int minz = iz - (caveBorder++ & 5);
                    int maxy = iy + (caveBorder++ & 5);
                    int maxz = iz + (caveBorder++ & 5);
                    int mx   = (maxx + minx) / 2;
                    int my   = (maxy + miny) / 2;
                    int mz   = (maxz + minz) / 2;

                    VoxelChunk chunk = null;
                    int        lastChunkX = int.MinValue, lastChunkY = int.MinValue, lastChunkZ = int.MinValue;
                    for (int y = miny; y < maxy; y++)
                    {
                        int chunkY      = FastMath.FloorToInt(y / 16f);
                        int py          = (int)(y - chunkY * 16);
                        int voxelIndexY = py * ONE_Y_ROW;
                        for (int z = minz; z < maxz; z++)
                        {
                            int chunkZ      = FastMath.FloorToInt(z / 16f);
                            int pz          = (int)(z - chunkZ * 16);
                            int voxelIndexZ = voxelIndexY + pz * ONE_Z_ROW;
                            for (int x = minx; x < maxx; x++)
                            {
                                int dx = x - mx;
                                int dy = y - my;
                                int dz = z - mz;
                                if (dx * dx + dy * dy + dz * dz > 23)
                                {
                                    continue;
                                }
                                int chunkX = FastMath.FloorToInt(x / 16f);
                                if (chunkX != lastChunkX || chunkY != lastChunkY || chunkZ != lastChunkZ)
                                {
                                    lastChunkX = chunkX;
                                    lastChunkY = chunkY;
                                    lastChunkZ = chunkZ;
                                    env.STAGE  = 3004;
                                    chunk      = env.GetChunkUnpopulated(chunkX, chunkY, chunkZ);
                                    env.STAGE  = 3005;
                                    if (chunk.isPopulated)
                                    {
                                        worm.life = 0;
                                        y         = maxy;
                                        z         = maxz;
                                        break;
                                    }
                                    // mark the chunk as modified by this detail generator
                                    SetChunkIsDirty(chunk);
                                }

                                int px         = (int)(x - chunkX * 16);
                                int voxelIndex = voxelIndexZ + px;
                                chunk.voxels [voxelIndex].hasContent = 2;
                            }
                        }
                    }
                    worm.life--;
                    if (worm.life <= 0)
                    {
                        env.STAGE = 3007;
                        worms.RemoveAt(k);
                        env.STAGE = 0;
                        return(true);
                    }
                }
                worms [k] = worm;

                long elapsed = env.stopWatch.ElapsedMilliseconds;
                if (elapsed >= endTime)
                {
                    break;
                }
            }
            env.STAGE = 0;
            return(true);
        }
コード例 #19
0
        /// <summary>
        /// Performs the voxel damage.
        /// </summary>
        /// <returns>The actual damage taken by the voxe.</returns>
        /// <param name="hitInfo">Hit info.</param>
        /// <param name="damage">Damage.</param>
        /// <param name="addParticles">If set to <c>true</c> add particles.</param>
        int DamageVoxelFast(ref VoxelHitInfo hitInfo, int damage, bool addParticles, bool playSound, bool allowDamageEvent = true)
        {
            VoxelChunk chunk = hitInfo.chunk;

            if (hitInfo.voxel.typeIndex == 0)
            {
                return(0);
            }
            VoxelDefinition voxelType = hitInfo.voxel.type;
            byte            voxelTypeResistancePoints = voxelType.resistancePoints;

            if (buildMode)
            {
                if (damage > 0)
                {
                    damage = 255;
                }
            }
            else
            {
                if (voxelTypeResistancePoints == (byte)0)
                {
                    damage = 0;
                }
                else if (voxelTypeResistancePoints == (byte)255)
                {
                    if (playSound)
                    {
                        PlayImpactSound(hitInfo.voxel.type.impactSound, hitInfo.voxelCenter);
                    }
                    damage = 0;
                }
            }

            if (allowDamageEvent && OnVoxelDamaged != null)
            {
                OnVoxelDamaged(chunk, hitInfo.voxelIndex, ref damage);
            }

            if (damage == 0)
            {
                return(0);
            }

            // Gets ambient light near surface
            float voxelLight = GetVoxelLight(hitInfo.point + hitInfo.normal * 0.5f);

            // Get voxel damage indicator GO's name
            bool             destroyed            = voxelType.renderType == RenderType.CutoutCross;
            int              resistancePointsLeft = 0;
            VoxelPlaceholder placeholder          = null;

            if (!destroyed)
            {
                placeholder          = GetVoxelPlaceholder(chunk, hitInfo.voxelIndex, true);
                resistancePointsLeft = placeholder.resistancePointsLeft - damage;
                if (resistancePointsLeft < 0)
                {
                    resistancePointsLeft = 0;
                    destroyed            = true;
                }
                placeholder.resistancePointsLeft = resistancePointsLeft;
            }

            if (voxelType.renderType == RenderType.Empty)
            {
                addParticles = false;
            }

            int particlesAmount;

            if (destroyed)
            {
                // Add recoverable voxel on the scene (not for vegetation)
                if (voxelType.renderType != RenderType.Empty && voxelType.renderType != RenderType.CutoutCross && voxelType.canBeCollected && !buildMode)
                {
                    bool create = true;

                    if (OnVoxelBeforeDropItem != null)
                    {
                        OnVoxelBeforeDropItem(chunk, hitInfo, out create);
                    }
                    if (create)
                    {
                        CreateRecoverableVoxel(hitInfo.voxelCenter, voxelDefinitions [hitInfo.voxel.typeIndex], hitInfo.voxel.color);
                    }
                }

                // Destroy the voxel
                VoxelDestroyFast(chunk, hitInfo.voxelIndex);

                // Check if grass is on top and remove it as well
                VoxelChunk topChunk;
                int        topIndex;
                if (GetVoxelIndex(hitInfo.voxelCenter + Misc.vector3up, out topChunk, out topIndex, false))
                {
                    if (topChunk.voxels [topIndex].typeIndex != 0 && voxelDefinitions [topChunk.voxels [topIndex].typeIndex].renderType == RenderType.CutoutCross)
                    {
                        byte light = topChunk.voxels [topIndex].lightMesh;
                        topChunk.voxels [topIndex].Clear(light);
                        topChunk.modified = true;
                    }
                }

                // Max particles
                particlesAmount = 20;

                if (playSound)
                {
                    PlayDestructionSound(voxelDefinitions [hitInfo.voxel.typeIndex].destructionSound, hitInfo.voxelCenter);
                }
            }
            else
            {
                // Add damage indicator
                if (placeholder == null)
                {
                    placeholder = GetVoxelPlaceholder(chunk, hitInfo.voxelIndex, true);
                }
                if (placeholder.damageIndicator == null)
                {
                    if (damagedVoxelPrefab == null)
                    {
                        damagedVoxelPrefab = Resources.Load <GameObject> ("VoxelPlay/Prefabs/DamagedVoxel");
                    }
                    GameObject g = Instantiate <GameObject> (damagedVoxelPrefab);
                    g.name = DAMAGE_INDICATOR;
                    Transform tDamageIndicator = g.transform;
                    placeholder.damageIndicator = tDamageIndicator.GetComponent <Renderer> ();
                    tDamageIndicator.SetParent(placeholder.transform, false);
                    tDamageIndicator.localPosition = placeholder.bounds.center;
                    tDamageIndicator.localScale    = placeholder.bounds.size * 1.001f;
                }

                int textureIndex = FastMath.FloorToInt((5f * resistancePointsLeft) / voxelTypeResistancePoints);
                if (world.voxelDamageTextures.Length > 0)
                {
                    if (textureIndex >= world.voxelDamageTextures.Length)
                    {
                        textureIndex = world.voxelDamageTextures.Length - 1;
                    }
                    Material mi = placeholder.damageIndicatorMaterial;                     // gets a copy of material the first time it's used
                    mi.mainTexture = world.voxelDamageTextures [textureIndex];
                    mi.SetFloat("_VoxelLight", voxelLight);
                    placeholder.damageIndicator.enabled = true;
                }

                // Particle amount depending of damage
                particlesAmount = (6 - textureIndex) + 3;

                // Sets health recovery for the voxel
                placeholder.StartHealthRecovery(chunk, hitInfo.voxelIndex, world.damageDuration);

                if (playSound)
                {
                    PlayImpactSound(voxelDefinitions [hitInfo.voxel.typeIndex].impactSound, hitInfo.voxelCenter);
                }
            }

            // Add random particles
            if (!addParticles)
            {
                particlesAmount = 0;
            }
            for (int k = 0; k < particlesAmount; k++)
            {
                int ppeIndex = GetParticleFromPool();
                if (ppeIndex < 0)
                {
                    continue;
                }

                // Scale of particle
                Renderer particleRenderer = particlePool [ppeIndex].renderer;
                if (destroyed)
                {
                    if (voxelType.renderType == RenderType.CutoutCross)                         // smaller particles for vegetation
                    {
                        particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.03f, 0.04f);
                    }
                    else
                    {
                        particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.04f, 0.1f);
                    }
                }
                else
                {
                    particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.03f, 0.06f);
                }

                // Set particle texture
                Material instanceMat = particleRenderer.sharedMaterial;
                SetParticleMaterialTextures(instanceMat, voxelDefinitions [hitInfo.voxel.typeIndex], hitInfo.voxel.color);
                instanceMat.mainTextureOffset = new Vector2(Random.value, Random.value);
                instanceMat.mainTextureScale  = Misc.vector2one * 0.05f;
                instanceMat.SetFloat("_VoxelLight", voxelLight);
                instanceMat.SetFloat("_FlashDelay", 0);

                // Set position
                Rigidbody rb = particlePool [ppeIndex].rigidBody;
                if (destroyed)
                {
                    Vector3 expelDir = Random.insideUnitSphere;
                    Vector3 pos      = hitInfo.voxelCenter + expelDir;
                    particleRenderer.transform.position = pos;
                    rb.AddForce(expelDir * (Random.value * 125f));
                }
                else
                {
                    Vector3 pos = hitInfo.point;
                    Vector3 v1  = new Vector3(-hitInfo.normal.y, hitInfo.normal.z, hitInfo.normal.x);
                    Vector3 v2  = new Vector3(-hitInfo.normal.z, hitInfo.normal.x, hitInfo.normal.y);
                    Vector3 dx  = (Random.value - 0.5f) * 0.7f * v1;
                    Vector3 dy  = (Random.value - 0.5f) * 0.7f * v2;
                    particleRenderer.transform.position = pos + hitInfo.normal * 0.001f + dx + dy;
                    rb.AddForce(cameraMain.transform.forward * (Random.value * -125f));
                }
                rb.AddForce(Misc.vector3up * 25f);
                rb.AddTorque(Random.onUnitSphere * 100f);
                rb.useGravity = true;

                // Self-destruct
                particlePool [ppeIndex].destructionTime = Time.time + 2.5f + Random.value;
            }

            return(damage);
        }
コード例 #20
0
        VoxelChunk RayCastFastVoxel(Vector3 origin, Vector3 direction, out VoxelHitInfo hitInfo, float maxDistance = 0, bool createChunksIfNeeded = false, byte minOpaque = 0)
        {
#if DEBUG_RAYCAST
            GameObject o;
#endif

            float maxDistanceSqr = maxDistance == 0 ? 1000 * 1000 : maxDistance * maxDistance;

            // Ray march throuch chunks until hit one loaded chunk
            Vector3    position = origin;
            VoxelChunk chunk    = null;
            hitInfo            = new VoxelHitInfo();
            hitInfo.voxelIndex = -1;

            Vector3 viewDirSign = new Vector3(Mathf.Sign(direction.x), Mathf.Sign(direction.y), Mathf.Sign(direction.z));
            Vector3 viewSign    = (viewDirSign + Misc.vector3one) * 0.5f;          // 0 = left, 1 = right

            float vxz, vzy, vxy;
            if (direction.y != 0)
            {
                float a = direction.x / direction.y;
                float b = direction.z / direction.y;
                vxz = Mathf.Sqrt(1f + a * a + b * b);
            }
            else
            {
                vxz = 1000000f;
            }
            if (direction.x != 0)
            {
                float a = direction.z / direction.x;
                float b = direction.y / direction.x;
                vzy = Mathf.Sqrt(1f + a * a + b * b);
            }
            else
            {
                vzy = 1000000f;
            }
            if (direction.z != 0)
            {
                float a = direction.x / direction.z;
                float b = direction.y / direction.z;
                vxy = Mathf.Sqrt(1f + a * a + b * b);
            }
            else
            {
                vxy = 1000000f;
            }

            Vector3 v3                = new Vector3(vzy, vxz, vxy);
            Vector3 viewSign16        = viewSign * 16f;
            Vector3 viewDirSignOffset = viewDirSign * 0.002f;

            int     chunkX, chunkY, chunkZ;
            int     chunkCount = 0;
            float   t;
            Vector3 normal = Misc.vector3zero, db;
//			bool notFirstVoxel = false;

            while (chunkCount++ < 500)               // safety counter to avoid any potential infinite loop

            // Check max distance
            {
                float distSqr = (position.x - origin.x) * (position.x - origin.x) + (position.y - origin.y) * (position.y - origin.y) + (position.z - origin.z) * (position.z - origin.z);
                if (distSqr > maxDistanceSqr)
                {
                    return(null);
                }


#if DEBUG_RAYCAST
                o = GameObject.CreatePrimitive(PrimitiveType.Cube);
                o.transform.localScale = Misc.Vector3one * 0.15f;
                o.transform.position   = position;
                DestroyImmediate(o.GetComponent <Collider>());
                o.GetComponent <Renderer>().material.color = Color.blue;
#endif

                chunkX = FastMath.FloorToInt(position.x / 16f);
                chunkY = FastMath.FloorToInt(position.y / 16f);
                chunkZ = FastMath.FloorToInt(position.z / 16f);

                chunk = null;
                if (createChunksIfNeeded)
                {
                    chunk = GetChunkOrCreate(chunkX, chunkY, chunkZ);
                }
                else
                {
                    int x00  = WORLD_SIZE_DEPTH * WORLD_SIZE_HEIGHT * (chunkX + WORLD_SIZE_WIDTH);
                    int y00  = WORLD_SIZE_DEPTH * (chunkY + WORLD_SIZE_HEIGHT);
                    int hash = x00 + y00 + chunkZ;
                    chunk = GetChunkIfExists(hash);
                }

                chunkX *= 16;
                chunkY *= 16;
                chunkZ *= 16;

                if (chunk)
                {
                    // Ray-march through chunk
                    Voxel[] voxels     = chunk.voxels;
                    Vector3 inPosition = position;

                    for (int k = 0; k < 64; k++)
                    {
#if DEBUG_RAYCAST
                        o = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                        o.transform.localScale = Misc.Vector3one * 0.1f;
                        o.transform.position   = inPosition;
                        DestroyImmediate(o.GetComponent <Collider>());
                        o.GetComponent <Renderer>().material.color = Color.yellow;
#endif

                        // Check voxel content
                        int fy = FastMath.FloorToInt(inPosition.y);
                        int py = fy - chunkY;
                        int fz = FastMath.FloorToInt(inPosition.z);
                        int pz = fz - chunkZ;
                        int fx = FastMath.FloorToInt(inPosition.x);
                        int px = fx - chunkX;
                        if (px < 0 || px > 15 || py < 0 || py > 15 || pz < 0 || pz > 15)
                        {
                            break;
                        }

                        int voxelIndex = py * ONE_Y_ROW + pz * ONE_Z_ROW + px;
                        if (voxels [voxelIndex].hasContent == 1 && !voxels [voxelIndex].type.ignoresRayCast && (minOpaque == 255 || voxels [voxelIndex].opaque >= minOpaque))
                        {
                            VoxelDefinition vd = voxelDefinitions [voxels [voxelIndex].typeIndex];
                            if (vd.renderType != RenderType.Custom || !vd.modelUsesCollider)
                            {
                                // Check max distance
                                distSqr = (inPosition.x - origin.x) * (inPosition.x - origin.x) + (inPosition.y - origin.y) * (inPosition.y - origin.y) + (inPosition.z - origin.z) * (inPosition.z - origin.z);
                                if (distSqr > maxDistanceSqr)
                                {
                                    return(null);
                                }

                                // Check water level or grass height
                                float voxelHeight = 0;
                                if (vd.renderType == RenderType.Water)
                                {
                                    voxelHeight = voxels [voxelIndex].GetWaterLevel() / 15f;
                                }
                                else if (vd.renderType == RenderType.CutoutCross)
                                {
                                    voxelHeight = vd.scale.y;
                                }
                                bool    hit         = true;
                                Vector3 voxelCenter = new Vector3(chunkX + px + 0.5f, chunkY + py + 0.5f, chunkZ + pz + 0.5f);
                                Vector3 localHitPos = inPosition - voxelCenter;
                                if (voxelHeight > 0 && voxelHeight < 1f && direction.y != 0)
                                {
                                    t = localHitPos.y + 0.5f - voxelHeight;
                                    if (t > 0)
                                    {
                                        t            = t * Mathf.Sqrt(1 + (direction.x * direction.x + direction.z * direction.z) / (direction.y * direction.y));
                                        localHitPos += t * direction;
                                        hit          = localHitPos.x >= -0.5f && localHitPos.x <= 0.5f && localHitPos.z >= -0.5f && localHitPos.z <= 0.5f;
                                    }
                                }
                                if (hit)
                                {
                                    hitInfo             = new VoxelHitInfo();
                                    hitInfo.chunk       = chunk;
                                    hitInfo.voxel       = voxels [voxelIndex];
                                    hitInfo.point       = inPosition - normal;
                                    hitInfo.distance    = Mathf.Sqrt(distSqr);
                                    hitInfo.voxelIndex  = voxelIndex;
                                    hitInfo.voxelCenter = voxelCenter;
                                    if (localHitPos.y >= 0.495)
                                    {
                                        hitInfo.normal = Misc.vector3up;
                                    }
                                    else if (localHitPos.y <= -0.495)
                                    {
                                        hitInfo.normal = Misc.vector3down;
                                    }
                                    else if (localHitPos.x < -0.495)
                                    {
                                        hitInfo.normal = Misc.vector3left;
                                    }
                                    else if (localHitPos.x > 0.495)
                                    {
                                        hitInfo.normal = Misc.vector3right;
                                    }
                                    else if (localHitPos.z < -0.495)
                                    {
                                        hitInfo.normal = Misc.vector3back;
                                    }
                                    else if (localHitPos.z > 0.495)
                                    {
                                        hitInfo.normal = Misc.vector3forward;
                                    }

#if DEBUG_RAYCAST
                                    o = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                                    o.transform.localScale = Misc.Vector3one * 0.15f;
                                    o.transform.position   = inPosition;
                                    DestroyImmediate(o.GetComponent <Collider>());
                                    o.GetComponent <Renderer>().material.color = Color.red;
#endif

                                    return(chunk);
                                }
                            }
                        }

                        db.x = (fx + viewSign.x - inPosition.x) * v3.x;
                        db.y = (fy + viewSign.y - inPosition.y) * v3.y;
                        db.z = (fz + viewSign.z - inPosition.z) * v3.z;

                        db.x = db.x < 0 ? -db.x : db.x;
                        db.y = db.y < 0 ? -db.y : db.y;
                        db.z = db.z < 0 ? -db.z : db.z;

                        t        = db.x;
                        normal.x = viewDirSignOffset.x;
                        normal.y = 0;
                        normal.z = 0;
                        if (db.y < t)
                        {
                            t        = db.y;
                            normal.x = 0;
                            normal.y = viewDirSignOffset.y;
                        }
                        if (db.z < t)
                        {
                            t        = db.z;
                            normal.x = 0;
                            normal.y = 0;
                            normal.z = viewDirSignOffset.z;
                        }

                        inPosition.x += direction.x * t + normal.x;
                        inPosition.y += direction.y * t + normal.y;
                        inPosition.z += direction.z * t + normal.z;

//						notFirstVoxel = true;
                    }
                }

                db.x = (chunkX + viewSign16.x - position.x) * v3.x;
                db.y = (chunkY + viewSign16.y - position.y) * v3.y;
                db.z = (chunkZ + viewSign16.z - position.z) * v3.z;

                db.x = db.x < 0 ? -db.x : db.x;
                db.y = db.y < 0 ? -db.y : db.y;
                db.z = db.z < 0 ? -db.z : db.z;

                t        = db.x;
                normal.x = viewDirSignOffset.x;
                normal.y = 0;
                normal.z = 0;
                if (db.y < t)
                {
                    t        = db.y;
                    normal.x = 0;
                    normal.y = viewDirSignOffset.y;
                }
                if (db.z < t)
                {
                    t        = db.z;
                    normal.x = 0;
                    normal.y = 0;
                    normal.z = viewDirSignOffset.z;
                }

                position.x += direction.x * t + normal.x;
                position.y += direction.y * t + normal.y;
                position.z += direction.z * t + normal.z;

//				notFirstVoxel = true;
            }
            return(null);
        }
コード例 #21
0
 void GetChunkCoordinates(Vector3 position, out int chunkX, out int chunkY, out int chunkZ)
 {
     FastMath.FloorToInt(position.x / VoxelPlayEnvironment.CHUNK_SIZE, position.y / VoxelPlayEnvironment.CHUNK_SIZE, position.z / VoxelPlayEnvironment.CHUNK_SIZE, out chunkX, out chunkY, out chunkZ);
 }
コード例 #22
0
 void GetChunkCoordinates(Vector3 position, out int chunkX, out int chunkY, out int chunkZ)
 {
     chunkX = FastMath.FloorToInt(position.x / 16);
     chunkY = FastMath.FloorToInt(position.y / 16);
     chunkZ = FastMath.FloorToInt(position.z / 16);
 }
コード例 #23
0
        void CheckWaterStatus()
        {
            Vector3 nearClipPos = m_Camera.transform.position + m_Camera.transform.forward * (m_Camera.nearClipPlane + 0.001f);

            if (nearClipPos.x == lastNearClipPosX && nearClipPos.y == lastNearClipPosY && nearClipPos.z == lastNearClipPosZ)
            {
                return;
            }

            lastNearClipPosX = (int)nearClipPos.x;
            lastNearClipPosY = (int)nearClipPos.y;
            lastNearClipPosZ = (int)nearClipPos.z;

            bool wasInWater = isInWater;

            isInWater    = false;
            isSwimming   = false;
            isUnderwater = false;

            // Check water on character controller position
            VoxelChunk chunk;
            int        voxelIndex;
            Voxel      voxelCh;

            if (env.GetVoxelIndex(curPos, out chunk, out voxelIndex, false))
            {
                voxelCh = chunk.voxels [voxelIndex];
            }
            else
            {
                voxelCh = Voxel.Empty;
            }
            VoxelDefinition voxelChType = env.voxelDefinitions [voxelCh.typeIndex];

            if (voxelCh.hasContent == 1)
            {
                CheckEnterTrigger(chunk, voxelIndex);
                CheckDamage(voxelChType);
            }

            // Safety check; if voxel at character position is solid, move character on top of terrain
            if (voxelCh.isSolid)
            {
                Unstuck(false);
            }
            else
            {
                // Check if water surrounds camera
                Voxel           voxelCamera     = env.GetVoxel(nearClipPos, false);
                VoxelDefinition voxelCameraType = env.voxelDefinitions [voxelCamera.typeIndex];
                if (voxelCamera.hasContent == 1)
                {
                    CheckEnterTrigger(chunk, voxelIndex);
                    CheckDamage(voxelCameraType);
                }

                if (voxelCamera.GetWaterLevel() > 7)
                {
                    // More water on top?
                    Vector3 pos1Up = nearClipPos;
                    pos1Up.y += 1f;
                    Voxel voxel1Up = env.GetVoxel(pos1Up);
                    if (voxel1Up.GetWaterLevel() > 0)
                    {
                        isUnderwater  = true;
                        waterLevelTop = nearClipPos.y + 1f;
                    }
                    else
                    {
                        waterLevelTop = FastMath.FloorToInt(nearClipPos.y) + 0.9f;
                        isUnderwater  = nearClipPos.y < waterLevelTop;
                        isSwimming    = !isUnderwater;
                    }
                    underWaterMat.color = voxelCameraType.diveColor;
                }
                else if (voxelCh.GetWaterLevel() > 7)                      // type == env.world.waterVoxel) {
                {
                    isSwimming          = true;
                    waterLevelTop       = FastMath.FloorToInt(curPos.y) + 0.9f;
                    underWaterMat.color = voxelChType.diveColor;
                }
                underWaterMat.SetFloat("_WaterLevel", waterLevelTop);
            }

            isInWater = isSwimming || isUnderwater;
            if (crouch != null)
            {
                // move camera a bit down to simulate swimming position
                if (!wasInWater && isInWater)
                {
                    PlayWaterSplashSound();
                    crouch.localPosition = Misc.vector3down * 0.6f;                     // crouch
                }
                else if (wasInWater && !isInWater)
                {
                    crouch.localPosition = Misc.vector3zero;
                }
            }

            // Show/hide underwater panel
            if (isInWater && !underwaterPanel.activeSelf)
            {
                underwaterPanel.SetActive(true);
            }
            else if (!isInWater && underwaterPanel.activeSelf)
            {
                underwaterPanel.SetActive(false);
            }
        }
        void CheckChunksInRange(long endTime)
        {
            if (cachedChunks == null)
            {
                return;
            }

            int chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(currentAnchorPos.x / CHUNK_SIZE, currentAnchorPos.y / CHUNK_SIZE, currentAnchorPos.z / CHUNK_SIZE, out chunkX, out chunkY, out chunkZ);
            int chunkDeltaX = chunkX - lastChunkX;
            int chunkDeltaY = chunkY - lastChunkY;
            int chunkDeltaZ = chunkZ - lastChunkZ;

            bool checkOnlyBorders = true;

            if (chunkDeltaX < -1 || chunkDeltaX > 1 || chunkDeltaY < -1 || chunkDeltaY > 1 || chunkDeltaZ < -1 || chunkDeltaZ > 1)
            {
                checkOnlyBorders = false;
            }
            lastChunkX = chunkX;
            lastChunkY = chunkY;
            lastChunkZ = chunkZ;

            bool deltaXZChanged = chunkDeltaX != 0 || chunkDeltaZ != 0;

            if (!constructorMode && (deltaXZChanged || chunkDeltaY != 0))
            {
                if (deltaXZChanged)
                {
                    TriggerFarChunksUnloadCheck();
                }

                // Anchor has entered a new chunk
                if (OnPlayerEnterChunk != null)
                {
                    OnPlayerEnterChunk();
                }

                // Inform detail generators
                if (worldHasDetailGenerators)
                {
                    for (int k = 0; k < world.detailGenerators.Length; k++)
                    {
                        if (world.detailGenerators [k].enabled)
                        {
                            world.detailGenerators [k].ExploreArea(currentAnchorPos, checkOnlyBorders, endTime);
                        }
                    }
                }
            }

            // Check new chunks to render
            if (checkOnlyBorders)
            {
                int chunksXZDistance = _visibleChunksDistance;
                int chunksYDistance  = Mathf.Min(_visibleChunksDistance, 8);
                visible_xmin = chunkX - chunksXZDistance;
                visible_xmax = chunkX + chunksXZDistance;
                visible_zmin = chunkZ - chunksXZDistance;
                visible_zmax = chunkZ + chunksXZDistance;
                visible_ymin = chunkY - chunksYDistance;
                visible_ymax = chunkY + chunksYDistance;
                CheckNewChunksInFrustum(endTime);
            }
            else
            {
                visible_xmin = chunkX - forceChunkDistance;
                visible_xmax = chunkX + forceChunkDistance;
                visible_zmin = chunkZ - forceChunkDistance;
                visible_zmax = chunkZ + forceChunkDistance;
                visible_ymin = chunkY - forceChunkDistance;
                visible_ymax = chunkY + forceChunkDistance;
                CheckNewNearChunks();
                shouldCheckChunksInFrustum = true;
            }
        }
コード例 #25
0
 void GetChunkCoordinates(Vector3 position, out int chunkX, out int chunkY, out int chunkZ)
 {
     FastMath.FloorToInt(position.x / 16f, position.y / 16f, position.z / 16f, out chunkX, out chunkY, out chunkZ);
 }
コード例 #26
0
        void CheckChunksInRange(long endTime)
        {
            if (cachedChunks == null)
            {
                return;
            }

            int chunkX      = FastMath.FloorToInt(currentCamPos.x / 16f);
            int chunkY      = FastMath.FloorToInt(currentCamPos.y / 16f);
            int chunkZ      = FastMath.FloorToInt(currentCamPos.z / 16f);
            int chunkDeltaX = chunkX - lastChunkX;
            int chunkDeltaY = chunkY - lastChunkY;
            int chunkDeltaZ = chunkZ - lastChunkZ;

            bool checkOnlyBorders = true;

            if (chunkDeltaX < -1 || chunkDeltaX > 1)
            {
                checkOnlyBorders = false;
            }
            else if (chunkDeltaY < -1 || chunkDeltaY > 1)
            {
                checkOnlyBorders = false;
            }
            else if (chunkDeltaZ < -1 || chunkDeltaZ > 1)
            {
                checkOnlyBorders = false;
            }
            lastChunkX = chunkX;
            lastChunkY = chunkY;
            lastChunkZ = chunkZ;

            if (!constructorMode && (chunkDeltaX != 0 || chunkDeltaY != 0 || chunkDeltaZ != 0))
            {
                // Inform detail generators
                if (worldHasDetailGenerators)
                {
                    for (int k = 0; k < world.detailGenerators.Length; k++)
                    {
                        if (world.detailGenerators [k].enabled)
                        {
                            world.detailGenerators [k].ExploreArea(currentCamPos, checkOnlyBorders);
                        }
                    }
                }
            }

            // Check new chunks to render
            if (checkOnlyBorders)
            {
                int chunksXZDistance = _visibleChunksDistance;
                int chunksYDistance  = Mathf.Min(_visibleChunksDistance, 8);
                visible_xmin = chunkX - chunksXZDistance;
                visible_xmax = chunkX + chunksXZDistance;
                visible_zmin = chunkZ - chunksXZDistance;
                visible_zmax = chunkZ + chunksXZDistance;
                visible_ymin = chunkY - chunksYDistance;
                visible_ymax = chunkY + chunksYDistance;
                CheckNewChunksInFrustum(endTime);
            }
            else
            {
                visible_xmin = chunkX - forceChunkDistance;
                visible_xmax = chunkX + forceChunkDistance;
                visible_zmin = chunkZ - forceChunkDistance;
                visible_zmax = chunkZ + forceChunkDistance;
                visible_ymin = chunkY - forceChunkDistance;
                visible_ymax = chunkY + forceChunkDistance;
                CheckNewNearChunks();
                shouldCheckChunksInFrustum = true;
            }
        }
コード例 #27
0
        void GenerateChunkMeshDataOneJob(MeshingThread thread)
        {
            lock (thread.indicesUpdating)
            {
                thread.meshJobMeshDataGenerationIndex++;
                if (thread.meshJobMeshDataGenerationIndex >= thread.meshJobs.Length)
                {
                    thread.meshJobMeshDataGenerationIndex = 0;
                }
            }

            VoxelChunk chunk = thread.meshJobs [thread.meshJobMeshDataGenerationIndex].chunk;

            Voxel [] [] chunk9 = thread.chunk9;
            chunk9 [13] = chunk.voxels;
            Voxel [] emptyChunk = chunk.isAboveSurface ? emptyChunkAboveTerrain : emptyChunkUnderground;
            int      chunkX, chunkY, chunkZ;

            FastMath.FloorToInt(chunk.position.x / CHUNK_SIZE, chunk.position.y / CHUNK_SIZE, chunk.position.z / CHUNK_SIZE, out chunkX, out chunkY, out chunkZ);

            // Reset bit field; inconclusive neighbours are those neighbours which are undefined when an adjacent chunk is rendered. We mark it so then it's finally rendered, we re-render the adjacent chunk. This is required if the new chunk can
            // break holes on the edge of the chunk while no lighting is entering the chunk or global illumination is disabled (yes, it's an edge case but must be addressed to avoid gaps in those cases).
            chunk.inconclusiveNeighbours = 0; //(byte)(chunk.inconclusiveNeighbours & ~CHUNK_IS_INCONCLUSIVE);

            VoxelChunk [] neighbourChunks = thread.neighbourChunks;
            neighbourChunks [13] = chunk;
            thread.allowAO       = enableSmoothLighting && !draftModeActive; // AO is disabled on edges of world to reduce vertex count
            for (int c = 0, y = -1; y <= 1; y++)
            {
                int yy = chunkY + y;
                for (int z = -1; z <= 1; z++)
                {
                    int zz = chunkZ + z;
                    for (int x = -1; x <= 1; x++, c++)
                    {
                        if (y == 0 && z == 0 && x == 0)
                        {
                            continue;
                        }
                        int        xx = chunkX + x;
                        VoxelChunk neighbour;
                        if (GetChunkFast(xx, yy, zz, out neighbour, false) && (neighbour.isPopulated || neighbour.isRendered))
                        {
                            chunk9 [c] = neighbour.voxels;
                        }
                        else
                        {
                            chunk.inconclusiveNeighbours |= inconclusiveNeighbourTable [c];
                            chunk9 [c] = emptyChunk;
                            if (y == 0 && !chunk.modified)
                            {
                                // if this chunk has no neighbours horizontally and is not modified, it's probably an edge chunk.
                                // in this case, disable AO so the entire edge wall can be rendered using a single quad thanks to greedy meshing
                                thread.allowAO = false;
                            }
                        }
                        neighbourChunks [c] = neighbour;
                    }
                }
            }
#if USES_SEE_THROUGH
            lock (seeThroughLock) {
                // Hide voxels marked as hidden
                for (int c = 0; c < neighbourChunks.Length; c++)
                {
                    ToggleHiddenVoxels(neighbourChunks [c], false);
                }
#endif

            thread.GenerateMeshData();

#if USES_SEE_THROUGH
            // Reactivate hidden voxels
            for (int c = 0; c < neighbourChunks.Length; c++)
            {
                ToggleHiddenVoxels(neighbourChunks [c], true);
            }
        }
#endif
        }
コード例 #28
0
        void GenerateChunkMeshDataOneJob()
        {
            meshJobMeshDataGenerationIndex++;
            if (meshJobMeshDataGenerationIndex >= meshJobs.Length)
            {
                meshJobMeshDataGenerationIndex = 0;
            }

            VoxelChunk chunk = meshJobs [meshJobMeshDataGenerationIndex].chunk;

            chunk9 [13] = chunk.voxels;
            Voxel[] emptyChunk = chunk.isAboveSurface ? emptyChunkAboveTerrain : emptyChunkUnderground;
            int     chunkX     = FastMath.FloorToInt(chunk.position.x / 16);
            int     chunkY     = FastMath.FloorToInt(chunk.position.y / 16);
            int     chunkZ     = FastMath.FloorToInt(chunk.position.z / 16);

            // Reset bit field; inconclusive neighbours are those neighbours which are undefined when an adjacent chunk is rendered. We mark it so then it's finally rendered, we re-render the adjacent chunk. This is required if the new chunk can
            // break holes on the edge of the chunk while no lighting is entering the chunk or global illumination is disabled (yes, it's an edge case but must be addressed to avoid gaps in those cases).
            chunk.inconclusiveNeighbours = 0;             //(byte)(chunk.inconclusiveNeighbours & ~CHUNK_IS_INCONCLUSIVE);

            for (int c = 0, y = -1; y <= 1; y++)
            {
                int yy = chunkY + y;
                for (int z = -1; z <= 1; z++)
                {
                    int zz = chunkZ + z;
                    for (int x = -1; x <= 1; x++, c++)
                    {
                        if (y == 0 && z == 0 && x == 0)
                        {
                            continue;
                        }
                        int        xx = chunkX + x;
                        VoxelChunk neighbour;
                        if (GetChunkFast(xx, yy, zz, out neighbour, false) && (neighbour.isPopulated || neighbour.isRendered))
                        {
                            chunk9 [c] = neighbour.voxels;
                        }
                        else
                        {
                            chunk.inconclusiveNeighbours |= inconclusiveNeighbourTable [c];
                            chunk9 [c] = emptyChunk;
                        }
                    }
                }
            }

            // clear buffers

            if (effectiveUseGeometryShaders)
            {
                for (int j = 0; j < MAX_MATERIALS_PER_CHUNK; j++)
                {
                    tempGeoIndices [j].Clear();
                    meshJobs [meshJobMeshDataGenerationIndex].buffers [j].indicesCount = 0;
                }
                GenerateMeshData_Geo(meshJobMeshDataGenerationIndex);
            }
            else
            {
                for (int j = 0; j < MAX_MATERIALS_PER_CHUNK; j++)
                {
                    if (meshJobs [meshJobMeshDataGenerationIndex].buffers [j].indicesCount > 0)
                    {
                        meshJobs [meshJobMeshDataGenerationIndex].buffers [j].indices.Clear();
                        meshJobs [meshJobMeshDataGenerationIndex].buffers [j].indicesCount = 0;
                    }
                }
                GenerateMeshData_Triangle(meshJobMeshDataGenerationIndex);
            }
        }