Пример #1
0
        private void GenerateTerrain(int seed)
        {
            if (terrainManager != null)
                if (terrainManager.cellsInitialized > 0
                    && (terrainManager.cellsInitialized < terrainManager.terrainCells.Length))
                    return; // currently generating terrain

            terrainManager = new TerrainManager((int)terrainRes, (int)cellRes);
            terrainManager.InitializeCells();
            terrainManager.Initialized = false;
            terrainManager.cellsInitialized = 0;

            //set texture scale for shader
            if (terrainDrawContext != null)
                SetTextureScale();

            object terrainLock = new object();

            terrainGenerationTimer = new Stopwatch();
            terrainGenerationTimer.Start();

            vertexCount = 0;

            // generate terrain
            Thread terrainProcessing = new Thread(delegate()
                {
                    terrainManager.ForEachCell((pos, cell) =>
                    {
                        // do each cell in its own thread
                        Thread t = new Thread(delegate()
                        {
                            // generate perlin 3d noise
                            Vector3 noiseOffset = pos;
                            noiseOffset.Y *= -1;
                            cell.PerlinNoise(noiseOffset * cellRes, terrainNoiseDensity, seed);
                            // generate mesh for the cell
                            TerrainCellMesh mesh = new TerrainCellMesh(terrainManager.GetCell(pos), pos);
                            mesh.Calculate(cubicTerrain, GraphicsDevice);
                            if (mesh == null)
                            {
                                throw new Exception("Problem generating mesh from volume!");
                            }
                            terrainManager.terrainCellMeshes[(int)pos.X, (int)pos.Y, (int)pos.Z] = mesh;

                            /*
                            terrainManager.terrainCells[(int)pos.X, (int)pos.Y, (int)pos.Z].ForEach(voxelPos =>
                                terrainManager.terrainCells[(int)pos.X, (int)pos.Y, (int)pos.Z].setDensityAt(voxelPos, 255));

                            //terrainManager.terrainCells[(int)pos.X, (int)pos.Y, (int)pos.Z].CreateSphere(19, 255);
                            terrainManager.terrainCellMeshes[(int)pos.X, (int)pos.Y, (int)pos.Z] = new TerrainCellMesh(terrainManager.GetCell(pos), pos);
                            terrainManager.terrainCellMeshes[(int)pos.X, (int)pos.Y, (int)pos.Z].Calculate();
                            */
                            lock (terrainLock)
                            {
                                terrainManager.cellsInitialized++;
                                if (mesh.VerticesNormal != null)
                                {
                                    vertexCount += mesh.VerticesNormal.Length;
                                    //triangleCount += mesh.Indices.Length / 3;
                                }
                            }
                        });
                        t.IsBackground = true;
                        t.Start();
                    });
                });
            terrainProcessing.IsBackground = true;
            terrainProcessing.Start();

            /*
            // test sphere
            terrainManager.terrainCells[0, 0, 0].CreateSphere(18, 255);
            terrainManager.terrainCellMeshes[0, 0, 0] = new TerrainCellMesh(terrainManager.GetCell(0, 0, 0));
            terrainManager.terrainCellMeshes[0, 0, 0].Calculate();
            terrainManager.Initialized = true;*/
        }
Пример #2
0
        private void GenerateTerrain(int seed)
        {
            if (terrainManager != null)
                if (terrainManager.cellsInitialized > 0
                    && (terrainManager.cellsInitialized < terrainManager.terrainCells.Length))
                    return; // currently generating terrain

            const int initialCellRes = 16;
            const int initialTerrainRes = 4;
            terrainManager = new TerrainManager(initialTerrainRes, initialCellRes);
            terrainManager.InitializeCells();

            // set initialization state to false until we're actually done generating the cells
            terrainManager.Initialized = false;
            terrainManager.cellsInitialized = 0;

            //set texture scale for shader
            //if (terrainDrawContext != null)
                //SetTriplanarTextureScale();

            object terrainLock = new object();

            terrainGenerationTimer = new Stopwatch();
            terrainGenerationTimer.Start();

            // generate terrain
            Thread terrainProcessing = new Thread(delegate()
            {
                terrainManager.ForEachCell((cellPos, cell) =>
                {
                    // do each cell in its own thread
                    var t = Task.Factory.StartNew(() =>
                        {
                            // generate perlin 3d noise
                            Vector3 noiseOffset = cellPos;
                            noiseOffset.Y *= -1;
                            cell.PerlinNoise(noiseOffset * terrainManager.cellDimensions.X, terrainNoiseDensity, seed);

                            TerrainCellMesh mesh = new TerrainCellMesh(cell, cellPos, terrainManager.cellGap);
                            mesh.Calculate(terrainManager.cubicTerrain);
                            if (mesh == null)
                            {
                                throw new Exception("Problem generating mesh from volume!");
                            }

                            // calculate convex hull
                            mesh.CalculatePhysicsHull();
                            // add mesh's convex hull to the physics sim
                            world.AddBody(mesh.RigidBody);

                            lock (terrainLock)
                            {
                                terrainManager.terrainCellMeshes[(int)cellPos.X, (int)cellPos.Y, (int)cellPos.Z] = mesh;
                                if (mesh.Vertices != null)
                                    terrainManager.vertexCount += mesh.Vertices.Count;

                                terrainManager.cellsInitialized++;
                            }

                            //drawToRenderTarget.Add(new DrawRotated(terrainManager.terrainCellMeshes[(int)pos.X, (int)pos.Y, (int)pos.Z]));
                        });
                });

                // for each cell, create overlapping data with
                // neighboring cells so we can avoid ugly border seams
                // then, generate a mesh for each cell
                /*
                cell.ForEach(innerPos =>
                    {
                        if ((cellPos.X != 0) && (innerPos.X == 0))
                        {
                            // get neighbor cell border density
                            VolumeDensity8 neighborCell = terrainManager.GetCell(cellPos.X - 1, cellPos.Y, cellPos.Z);
                            byte density = neighborCell.getVoxelAt(cell.getWidth(), innerPos.Y, innerPos.Z).getDensity();
                            //byte density2 = cell.getVoxelAt(innerPos).getDensity();
                            //density = (byte)((density + density2) / 2);
                            // set current cell border to match
                            cell.setDensityAt(innerPos.X - 1, innerPos.Y, innerPos.Z, density);
                        }

                        if ((cellPos.X != terrainManager.terrainDimensions.X)
                            && (innerPos.X == cell.getWidth()))
                        {
                            // get neighbor cell border density
                            VolumeDensity8 neighborCell = terrainManager.GetCell(cellPos.X + 1, cellPos.Y, cellPos.Z);
                            byte density = neighborCell.getVoxelAt(0, innerPos.Y, innerPos.Z).getDensity();
                            //byte density2 = cell.getVoxelAt(innerPos).getDensity();
                            //density = (byte)((density + density2) / 2);
                            // set current cell border to match
                            cell.setDensityAt(innerPos.X + 1, innerPos.Y, innerPos.Z, density);
                        }

                        if ((cellPos.Y != 0) && (innerPos.Y == 0))
                        {
                            // get neighbor cell border density
                            VolumeDensity8 neighborCell = terrainManager.GetCell(cellPos.X, cellPos.Y - 1, cellPos.Z);
                            byte density = neighborCell.getVoxelAt(innerPos.X, cell.getHeight(), innerPos.Z).getDensity();
                            //byte density2 = cell.getVoxelAt(innerPos).getDensity();
                            //density = (byte)((density + density2) / 2);
                            // set current cell border to match
                            cell.setDensityAt(innerPos.X, innerPos.Y - 1, innerPos.Z, density);
                        }

                        if ((cellPos.Y != terrainManager.terrainDimensions.Y)
                            && (innerPos.Y == cell.getHeight()))
                        {
                            // get neighbor cell border density
                            VolumeDensity8 neighborCell = terrainManager.GetCell(cellPos.X, cellPos.Y + 1, cellPos.Z);
                            byte density = neighborCell.getVoxelAt(innerPos.X, 0, innerPos.Z).getDensity();
                            //byte density2 = cell.getVoxelAt(innerPos).getDensity();
                            //density = (byte)((density + density2) / 2);
                            // set current cell border to match
                            cell.setDensityAt(innerPos.X, innerPos.Y + 1, innerPos.Z, density);
                        }

                        if ((cellPos.Z != 0) && (innerPos.Z == 0))
                        {
                            // get neighbor cell border density
                            VolumeDensity8 neighborCell = terrainManager.GetCell(cellPos.X, cellPos.Y, cellPos.Z - 1);
                            byte density = neighborCell.getVoxelAt(innerPos.X, innerPos.Y, cell.getDepth()).getDensity();
                            //byte density2 = cell.getVoxelAt(innerPos).getDensity();
                            //density = (byte)((density + density2) / 2);
                            // set current cell border to match
                            cell.setDensityAt(innerPos.X, innerPos.Y, innerPos.Z - 1, density);
                        }
                        if ((cellPos.Z != terrainManager.terrainDimensions.Z)
                            && (innerPos.Z == cell.getDepth()))
                        {
                            // get neighbor cell border density
                            VolumeDensity8 neighborCell = terrainManager.GetCell(cellPos.X, cellPos.Y, cellPos.Z + 1);
                            byte density = neighborCell.getVoxelAt(innerPos.X, innerPos.Y, 0).getDensity();
                            //byte density2 = cell.getVoxelAt(innerPos).getDensity();
                            //density = (byte)((density + density2) / 2);
                            // set current cell border to match
                            cell.setDensityAt(innerPos.X, innerPos.Y, innerPos.Z + 1, density);
                        }
                    });*/

            });
            terrainProcessing.IsBackground = true;
            terrainProcessing.Start();
            drawToRenderTarget.Add(terrainManager);
        }