Exemplo n.º 1
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
        }
        /// <summary>
        /// Move worms
        /// </summary>
        public override bool DoWork(long endTime)
        {
            int count = worms.Count;

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

            for (int p = 0; p < 1000; p++)
            {
                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          = y - chunkY * 16;
                            int voxelIndexY = py * ONE_Y_ROW;
                            for (int z = minz; z < maxz; z++)
                            {
                                int chunkZ      = FastMath.FloorToInt(z / 16f);
                                int pz          = 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         = 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);
        }
Exemplo n.º 3
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
            {
                AnnotateNonCollidingPosition(curPos);
                // 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);
            }

            // Check if underground and adjust camera near clip plane
            float alt = env.GetTerrainHeight(nearClipPos);

            if (nearClipPos.y < alt)
            {
                if (env.cameraMain.nearClipPlane > 0.081f)
                {
                    lastUserCameraNearClipPlane  = env.cameraMain.nearClipPlane;
                    env.cameraMain.nearClipPlane = 0.08f;
                }
            }
            else if (env.cameraMain.nearClipPlane < lastUserCameraNearClipPlane)
            {
                env.cameraMain.nearClipPlane = lastUserCameraNearClipPlane;
            }
        }