Exemplo n.º 1
0
    bool CrearVoxel(float px, float py, float pz, string pnombre)
    {
        
        //Creacion del voxel la db
        TerrainVolumeData volumeData = VolumeData.CreateEmptyVolumeData<TerrainVolumeData>(new Region(0, 0, 0, Ancho - 1, Altura - 1, Profundidad - 1), @DirectorioLocal + NombreMapa+"/"+pnombre + ".vdb");
        MaterialSet materialSet = new MaterialSet();

        double DifAltura = Altura - Altura * 0.9;
        for (int z = 0; z < Profundidad; z++)
        {
            for (int y = 0; y < (int)DifAltura; y++)
            {
                for (int x = 0; x < Ancho; x++)
                {
                    materialSet.weights[0] = (byte)255;
                    volumeData.SetVoxel(x, y, z, materialSet);
                }
            }
        }
        volumeData.CommitChanges();
        //asignacion del prefab

        GameObject VoxelTemporal = Instantiate(VoxelPrefab) as GameObject;
        VoxelTemporal.name = pnombre;
        VoxelTemporal.transform.GetChild(0).GetComponent<TerrainVolume>().data=volumeData;
       VoxelTemporal.transform.GetChild(1).Translate(Ancho/2, (float)DifAltura, Profundidad/2);

        VoxelTemporal.transform.position = new Vector3(px,py,pz);
        
        MapaVoxels.Add(pnombre, VoxelTemporal);
            VoxelActual = VoxelTemporal;
            ClaveActual = pnombre;
        
        return false;
    }
Exemplo n.º 2
0
        private void CreateAVolumeDB()
        {
            System.Random randomIntGenerator = new System.Random();
            int           randomInt          = randomIntGenerator.Next();
            string        saveLocation       = Paths.voxelDatabases + "/Matt-test" + randomInt + ".vdb";
            var           volumeBounds       = new Region(Vector3i.zero, size);

            ColoredCubesVolumeData data = VolumeData.CreateEmptyVolumeData <ColoredCubesVolumeData>(volumeBounds, null); // saveLocation);

            var coloredCubeVolume = GetComponent <ColoredCubesVolume>();

            coloredCubeVolume.data = data;

            float invRockScale = 1f / noiseScale;

            MaterialSet materialSet = new MaterialSet();

            // It's best to create these outside of the loop.
            QuantizedColor red   = new QuantizedColor(255, 0, 0, 255);
            QuantizedColor blue  = new QuantizedColor(122, 122, 255, 255);
            QuantizedColor gray  = new QuantizedColor(127, 127, 127, 255);
            QuantizedColor white = new QuantizedColor(255, 255, 255, 255);

            // Iterate over every voxel of our volume
            for (int z = 0; z < size.x; z++)
            {
                for (int y = 0; y < size.y; y++)
                {
                    for (int x = 0; x < size.z; x++)
                    {
                        // Simplex noise is quite high frequency. We scale the sample position to reduce this.
                        float sampleX = (float)x * invRockScale;
                        float sampleY = (float)y * invRockScale;
                        float sampleZ = (float)z * invRockScale;

                        // range -1 to +1
                        float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleY, sampleZ);

                        simplexNoiseValue -= y / size.y * .75f;
                        // mul by 5 and clamp?

                        //simplexNoiseValue *= 5f;
                        //simplexNoiseValue = Mathf.Clamp(simplexNoiseValue, -.5f, .5f);
                        //simplexNoiseValue += .5f;
                        //simplexNoiseValue *= 255;

                        if (simplexNoiseValue > 0f)
                        {
                            data.SetVoxel(x, y, z, blue);
                        }
                    }
                }
            }
            data.CommitChanges();

            Debug.Log("Voxel db saved to: " + saveLocation);
        }
Exemplo n.º 3
0
 /// Sets the material weights of the specified position.
 /**
  * \param x The 'x' position of the voxel to set.
  * \param y The 'y' position of the voxel to set.
  * \param z The 'z' position of the voxel to set.
  * \param materialSet The material weights the voxel should be set to.
  */
 public void SetVoxel(int x, int y, int z, MaterialSet materialSet)
 {
     // The initialization can fail (bad filename, database locked, etc), so the volume handle could still be null.
     if(volumeHandle.HasValue)
     {
         if(x >= enclosingRegion.lowerCorner.x && y >= enclosingRegion.lowerCorner.y && z >= enclosingRegion.lowerCorner.z
             && x <= enclosingRegion.upperCorner.x && y <= enclosingRegion.upperCorner.y && z <= enclosingRegion.upperCorner.z)
         {
             CubiquityDLL.SetVoxel(volumeHandle.Value, x, y, z, materialSet);
         }
     }
 }
Exemplo n.º 4
0
        /// Sets the material weights of the specified position.

        /**
         * \param x The 'x' position of the voxel to set.
         * \param y The 'y' position of the voxel to set.
         * \param z The 'z' position of the voxel to set.
         * \param materialSet The material weights the voxel should be set to.
         */
        public void SetVoxel(int x, int y, int z, MaterialSet materialSet)
        {
            // The initialization can fail (bad filename, database locked, etc), so the volume handle could still be null.
            if (volumeHandle.HasValue)
            {
                if (x >= enclosingRegion.lowerCorner.x && y >= enclosingRegion.lowerCorner.y && z >= enclosingRegion.lowerCorner.z &&
                    x <= enclosingRegion.upperCorner.x && y <= enclosingRegion.upperCorner.y && z <= enclosingRegion.upperCorner.z)
                {
                    CubiquityDLL.SetVoxel(volumeHandle.Value, x, y, z, materialSet);
                }
            }
        }
Exemplo n.º 5
0
	// Use this for initialization
	void Start ()
    {
        // Dimensions of our volume.
        int width = 64;
        int height = 64;
        int depth = 64;

        TerrainVolumeData volumeData = VolumeData.CreateEmptyVolumeData<TerrainVolumeData>(new Region(0, 0, 0, width - 1, height - 1, depth - 1));

        float noiseScale = 32.0f;
        float invNoiseScale = 1.0f / noiseScale;

        // Let's keep the allocation outside of the loop.
        MaterialSet materialSet = new MaterialSet();

        // Iterate over each voxel and assign a value to it
        for (int z = 0; z < depth; z++)
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    // Simplex noise is quite high frequency. We scale the sample position to reduce this.
                    float sampleX = (float)x * invNoiseScale;
                    float sampleY = (float)y * invNoiseScale;
                    float sampleZ = (float)z * invNoiseScale;

                    // Get the noise value for the current position.
                    // Returned value should be in the range -1 to +1.
                    float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleY, sampleZ);

                    // Cubiquity material weights need to be in the range 0 - 255.
                    simplexNoiseValue += 1.0f; // Now it's 0.0 to 2.0
                    simplexNoiseValue *= 127.5f; // Now it's 0.0 to 255.0

                    materialSet.weights[0] = (byte)simplexNoiseValue;

                    // We can now write our computed voxel value into the volume.
                    volumeData.SetVoxel(x, y, z, materialSet);
                }
            }
        }

        //Add the required volume component.
        TerrainVolume terrainVolume = gameObject.AddComponent<TerrainVolume>();

        // Set the provided data.
        terrainVolume.data = volumeData;

        // Add the renderer
        gameObject.AddComponent<TerrainVolumeRenderer>();
	}
        /// Gets the material weights of the specified position.

        /**
         * \param x The 'x' position of the voxel to get.
         * \param y The 'y' position of the voxel to get.
         * \param z The 'z' position of the voxel to get.
         * \return The material weights of the voxel.
         */
        public MaterialSet GetVoxel(int x, int y, int z)
        {
            // The initialization can fail (bad filename, database locked, etc), so the volume handle could still be null.
            MaterialSet materialSet;

            if (volumeHandle.HasValue)
            {
                CubiquityDLL.GetVoxelMC(volumeHandle.Value, x, y, z, out materialSet);
            }
            else
            {
                materialSet = new MaterialSet();
            }

            return(materialSet);
        }
Exemplo n.º 7
0
	TerrainVolumeData crearVolumenData(string direccion)
	{
		TerrainVolumeData volumeData = VolumeData.CreateEmptyVolumeData<TerrainVolumeData>(new Region(0, 0, 0, width - 1, height - 1, depth - 1),@"C:\CS-UCSP\Evolcraft\"+ direccion+".vdb");
		numObjects++;
		//Si no recibe un path, crea solo un temporal. Caso contrario, evalua si es un path relativo o no...
		MaterialSet materialSet = new MaterialSet();

		for (int z = 0; z < depth; z++)
		{
			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					materialSet.weights[0] = (byte)255;  
					volumeData.SetVoxel(x, y, z, materialSet);
				}
			}
		}
		volumeData.CommitChanges ();

		return volumeData;
	}
	void DestroyVoxels(int xPos, int yPos, int zPos, int range)
	{
		// Initialise outside the loop, but we'll use it later.
		int rangeSquared = range * range;
		MaterialSet emptyMaterialSet = new MaterialSet();
		
		// Iterage over every voxel in a cubic region defined by the received position (the center) and
		// the range. It is quite possible that this will be hundreds or even thousands of voxels.
		for(int z = zPos - range; z < zPos + range; z++) 
		{
			for(int y = yPos - range; y < yPos + range; y++)
			{
				for(int x = xPos - range; x < xPos + range; x++)
				{			
					// Compute the distance from the current voxel to the center of our explosion.
					int xDistance = x - xPos;
					int yDistance = y - yPos;
					int zDistance = z - zPos;
					
					// Working with squared distances avoids costly square root operations.
					int distSquared = xDistance * xDistance + yDistance * yDistance + zDistance * zDistance;
					
					// We're iterating over a cubic region, but we want our explosion to be spherical. Therefore 
					// we only further consider voxels which are within the required range of our explosion center. 
					// The corners of the cubic region we are iterating over will fail the following test.
					if(distSquared < rangeSquared)
					{	
						terrainVolume.data.SetVoxel(x, y, z, emptyMaterialSet);
					}
				}
			}
		}
		
		range += 2;
		
		TerrainVolumeEditor.BlurTerrainVolume(terrainVolume, new Region(xPos - range, yPos - range, zPos - range, xPos + range, yPos + range, zPos + range));
		//TerrainVolumeEditor.BlurTerrainVolume(terrainVolume, new Region(xPos - range, yPos - range, zPos - range, xPos + range, yPos + range, zPos + range));
		//TerrainVolumeEditor.BlurTerrainVolume(terrainVolume, new Region(xPos - range, yPos - range, zPos - range, xPos + range, yPos + range, zPos + range));
	}
Exemplo n.º 9
0
        void Create3DSimplexNoiseVolumeVDB()
        {
            // Randomize the filename incase the file already exists
            System.Random randomIntGenerator = new System.Random();
            int randomInt = randomIntGenerator.Next();
            string saveLocation = Paths.voxelDatabases + "/3d-simplex-noise-" + randomInt + ".vdb";

            // The size of the volume we will generate
            int width = 256;
            int height = 256;
            int depth = 256;

            TerrainVolumeData data = VolumeData.CreateEmptyVolumeData<TerrainVolumeData>(new Region(0, 0, 0, width - 1, height - 1, depth - 1), saveLocation);

            // This scale factor comtrols the size of the rocks which are generated.
            float rockScale = 32.0f;
            float invRockScale = 1.0f / rockScale;

            // Let's keep the allocation outside of the loop.
            MaterialSet materialSet = new MaterialSet();

            // Iterate over every voxel of our volume
            for (int z = 0; z < depth; z++)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        // Make sure we don't have anything left in here from the previous voxel
                        materialSet.weights[0] = 0;
                        materialSet.weights[1] = 0;
                        materialSet.weights[2] = 0;

                        // Simplex noise is quite high frequency. We scale the sample position to reduce this.
                        float sampleX = (float)x * invRockScale;
                        float sampleY = (float)y * invRockScale;
                        float sampleZ = (float)z * invRockScale;

                        // Get the noise value for the current position.
                        // Returned value should be in the range -1 to +1.
                        float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleY, sampleZ);

                        // Cubiquity renders anything below the threshold as empty and anythng above as solid, but
                        // in general it is easiest if empty space is completly empty and solid space is completly
                        // solid. The exception to this is the region near our surface, where a gentle transition helps
                        // obtain smooth shading. By scaling by a large number and then clamping we achieve this effect
                        // of making most voxels fully solid or fully empty except near the surface..
                        simplexNoiseValue *= 5.0f;
                        simplexNoiseValue = Mathf.Clamp(simplexNoiseValue, -0.5f, 0.5f);

                        // Go back to the range 0.0 to 1.0;
                        simplexNoiseValue += 0.5f;

                        // And then to 0 to 255, ready to convert into a byte.
                        simplexNoiseValue *= 255;

                        // Write the final value value into the first material channel (the one with the rock texture).
                        // The value being written is usually 0 (empty) or 255 (solid) except around the transition.
                        materialSet.weights[0] = (byte)simplexNoiseValue;

                        // We can now write our computed voxel value into the volume.
                        data.SetVoxel(x, y, z, materialSet);
                    }
                }
            }

            // We need to commit this so that the changes made by the previous,line are actually written
            // to the voxel database. Otherwise they are just kept in temporary storage and will be lost.
            data.CommitChanges();

            Debug.Log("Voxel database has been saved to '" + saveLocation + "'");
        }
Exemplo n.º 10
0
        void Create2DSimplexNoiseVolumeVDB()
        {
            // Randomize the filename incase the file already exists
            System.Random randomIntGenerator = new System.Random();
            int randomInt = randomIntGenerator.Next();
            string saveLocation = Paths.voxelDatabases + "/2d-simplex-noise-" + randomInt + ".vdb";

            // The size of the volume we will generate
            int width = 256;
            int height = 32;
            int depth = 256;

            TerrainVolumeData data = VolumeData.CreateEmptyVolumeData<TerrainVolumeData>(new Region(0, 0, 0, width - 1, height - 1, depth - 1), saveLocation);

            // This scale factor comtrols the size of the rocks which are generated.
            float rockScale = 32.0f;
            float invRockScale = 1.0f / rockScale;

            // Let's keep the allocation outside of the loop.
            MaterialSet materialSet = new MaterialSet();

            // Iterate over every voxel of our volume
            for (int z = 0; z < depth; z++)
            {
                for (int x = 0; x < width; x++)
                {
                    // Simplex noise is quite high frequency. We scale the sample position to reduce this.
                    float sampleX = (float)x * invRockScale;
                    float sampleZ = (float)z * invRockScale;

                    // Get the noise value for the current position.
                    // Returned value should be in the range -1 to +1.
                    float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleZ);

                    simplexNoiseValue += 1.0f;
                    simplexNoiseValue *= 16.0f;

                    for (int y = 0; y < height; y++)
                    {
                        // Make sure we don't have anything left in here from the previous voxel
                        materialSet.weights[0] = 0;
                        materialSet.weights[1] = 0;
                        materialSet.weights[2] = 0;

                        if (y < simplexNoiseValue)
                        {
                            // Write the final value value into the first material channel (the one with the rock texture).
                            // The value being written is usually 0 (empty) or 255 (solid) except around the transition.
                            materialSet.weights[0] = (byte)255;
                        }

                        // We can now write our computed voxel value into the volume.
                        data.SetVoxel(x, y, z, materialSet);
                    }
                }
            }

            // We need to commit this so that the changes made by the previous,line are actually written
            // to the voxel database. Otherwise they are just kept in temporary storage and will be lost.
            data.CommitChanges();

            Debug.Log("Voxel database has been saved to '" + saveLocation + "'");
        }
Exemplo n.º 11
0
        void Create3DSimplexNoiseVolumeVDB()
        {
            // Randomize the filename incase the file already exists
            System.Random randomIntGenerator = new System.Random();
            int           randomInt          = randomIntGenerator.Next();
            string        saveLocation       = Paths.voxelDatabases + "/3d-simplex-noise-" + randomInt + ".vdb";

            // The size of the volume we will generate
            int width  = 256;
            int height = 256;
            int depth  = 256;

            TerrainVolumeData data = VolumeData.CreateEmptyVolumeData <TerrainVolumeData>(new Region(0, 0, 0, width - 1, height - 1, depth - 1), saveLocation);

            // This scale factor comtrols the size of the rocks which are generated.
            float rockScale    = 32.0f;
            float invRockScale = 1.0f / rockScale;

            // Let's keep the allocation outside of the loop.
            MaterialSet materialSet = new MaterialSet();

            // Iterate over every voxel of our volume
            for (int z = 0; z < depth; z++)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        // Make sure we don't have anything left in here from the previous voxel
                        materialSet.weights[0] = 0;
                        materialSet.weights[1] = 0;
                        materialSet.weights[2] = 0;

                        // Simplex noise is quite high frequency. We scale the sample position to reduce this.
                        float sampleX = (float)x * invRockScale;
                        float sampleY = (float)y * invRockScale;
                        float sampleZ = (float)z * invRockScale;

                        // Get the noise value for the current position.
                        // Returned value should be in the range -1 to +1.
                        float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleY, sampleZ);

                        // Cubiquity renders anything below the threshold as empty and anythng above as solid, but
                        // in general it is easiest if empty space is completly empty and solid space is completly
                        // solid. The exception to this is the region near our surface, where a gentle transition helps
                        // obtain smooth shading. By scaling by a large number and then clamping we achieve this effect
                        // of making most voxels fully solid or fully empty except near the surface..
                        simplexNoiseValue *= 5.0f;
                        simplexNoiseValue  = Mathf.Clamp(simplexNoiseValue, -0.5f, 0.5f);

                        // Go back to the range 0.0 to 1.0;
                        simplexNoiseValue += 0.5f;

                        // And then to 0 to 255, ready to convert into a byte.
                        simplexNoiseValue *= 255;

                        // Write the final value value into the first material channel (the one with the rock texture).
                        // The value being written is usually 0 (empty) or 255 (solid) except around the transition.
                        materialSet.weights[0] = (byte)simplexNoiseValue;

                        // We can now write our computed voxel value into the volume.
                        data.SetVoxel(x, y, z, materialSet);
                    }
                }
            }

            // We need to commit this so that the changes made by the previous,line are actually written
            // to the voxel database. Otherwise they are just kept in temporary storage and will be lost.
            data.CommitChanges();

            Debug.Log("Voxel database has been saved to '" + saveLocation + "'");
        }
Exemplo n.º 12
0
        void Create2DSimplexNoiseVolumeVDB()
        {
            // Randomize the filename incase the file already exists
            System.Random randomIntGenerator = new System.Random();
            int           randomInt          = randomIntGenerator.Next();
            string        saveLocation       = Paths.voxelDatabases + "/2d-simplex-noise-" + randomInt + ".vdb";

            // The size of the volume we will generate
            int width  = 256;
            int height = 32;
            int depth  = 256;

            TerrainVolumeData data = VolumeData.CreateEmptyVolumeData <TerrainVolumeData>(new Region(0, 0, 0, width - 1, height - 1, depth - 1), saveLocation);

            // This scale factor comtrols the size of the rocks which are generated.
            float rockScale    = 32.0f;
            float invRockScale = 1.0f / rockScale;

            // Let's keep the allocation outside of the loop.
            MaterialSet materialSet = new MaterialSet();

            // Iterate over every voxel of our volume
            for (int z = 0; z < depth; z++)
            {
                for (int x = 0; x < width; x++)
                {
                    // Simplex noise is quite high frequency. We scale the sample position to reduce this.
                    float sampleX = (float)x * invRockScale;
                    float sampleZ = (float)z * invRockScale;

                    // Get the noise value for the current position.
                    // Returned value should be in the range -1 to +1.
                    float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleZ);

                    simplexNoiseValue += 1.0f;
                    simplexNoiseValue *= 16.0f;

                    for (int y = 0; y < height; y++)
                    {
                        // Make sure we don't have anything left in here from the previous voxel
                        materialSet.weights[0] = 0;
                        materialSet.weights[1] = 0;
                        materialSet.weights[2] = 0;

                        if (y < simplexNoiseValue)
                        {
                            // Write the final value value into the first material channel (the one with the rock texture).
                            // The value being written is usually 0 (empty) or 255 (solid) except around the transition.
                            materialSet.weights[0] = (byte)255;
                        }

                        // We can now write our computed voxel value into the volume.
                        data.SetVoxel(x, y, z, materialSet);
                    }
                }
            }

            // We need to commit this so that the changes made by the previous,line are actually written
            // to the voxel database. Otherwise they are just kept in temporary storage and will be lost.
            data.CommitChanges();

            Debug.Log("Voxel database has been saved to '" + saveLocation + "'");
        }
		public static void GeneratePlanet(TerrainVolumeData volumeData, float planetRadius, float mat1Radius, float mat2Radius, float mat3Radius)
		{
			Region volumeBounds = volumeData.enclosingRegion;
			MaterialSet materialSet = new MaterialSet();
			
			for(int z = volumeBounds.lowerCorner.z; z <= volumeBounds.upperCorner.z; z++)
			{
				for(int y = volumeBounds.lowerCorner.y; y <= volumeBounds.upperCorner.y; y++)
				{
					for(int x = volumeBounds.lowerCorner.x; x <= volumeBounds.upperCorner.x; x++)
					{
						// We are going to compute our density value based on the distance of a voxel from the center of our planet.
						// This is a function which (by definition) is zero at the center of the planet and has a smoothly increasing
						// value as we move away from the center.
						//
						// Note: For efficiency we could probably adapt this to work with squared distances (thereby eliminating
						// the square root operation), but we'd like to keep this example as intuitive as possible.
						float distFromCenter = Mathf.Sqrt(x * x + y * y + z * z);
						
						// We actually want our volume to have high values in the center and low values as we move out, because our
						// eath should be a solid sphere surrounded by empty space. If we invert the distance then this is a step in
						// the right direction. We still have zero in the center, but lower (negative) values as we move out.
						float density = -distFromCenter;
						
						// By adding the 'planetRadius' we now have a function which starts at 'planetRadius' and still decreases as it
						// moves out. The function passes through zero at a distance of 'planetRadius' and then continues do decrease
						// as it gets even further out.
						density += planetRadius;
						
						// Ideally we would like our final density value to be '255' for voxels inside the planet and '0' for voxels
						// outside the planet. At the surface there should be a transition but this should occur not too quickly and
						// not too slowly, as both of these will result in a jagged appearance to the mesh.
						//
						// We probably want the transition to occur over a few voxels, whereas it currently occurs over 255 voxels
						// because it was derived from the distance. By scaling the density field we effectivly compress the rate
						// at which it changes at the surface. We also make the center much too high and the outside very low, but
						// we will clamp these to the corect range later.
						//
						// Note: You can try commenting out or changing the value on this line to see the effect it has.
						density *= 50;
						
						// Until now we've been defining our density field as if the threshold was at zero, with positive densities
						// being solid and negative densities being empty. But actually Cubiquity operates on the range 0 to 255, and
						// uses a threashold of 127 to decide where to place the generated surface.  Therefore we shift and clamp our
						// density value and store it in a byte.
						density += 127;						
						byte densityAsByte = (byte)(Mathf.Clamp(density, 0, 255));
						
						if(distFromCenter < mat3Radius)
						{
							materialSet.weights[0] = 0;
							materialSet.weights[1] = 0;
							materialSet.weights[2] = 0;
							materialSet.weights[3] = densityAsByte;
						}
						else if(distFromCenter < mat2Radius)
						{
							materialSet.weights[0] = 0;
							materialSet.weights[1] = 0;
							materialSet.weights[2] = densityAsByte;
							materialSet.weights[3] = 0;
						}
						else if(distFromCenter < mat1Radius)
						{
							materialSet.weights[0] = 0;
							materialSet.weights[1] = densityAsByte;
							materialSet.weights[2] = 0;
							materialSet.weights[3] = 0;
						}
						else //Surface material
						{
							materialSet.weights[0] = densityAsByte;
							materialSet.weights[1] = 0;
							materialSet.weights[2] = 0;
							materialSet.weights[3] = 0;
						}
						
						volumeData.SetVoxel(x, y, z, materialSet);
						
					}
				}
			}
		}
Exemplo n.º 14
0
        public static void GeneratePlanet(TerrainVolumeData volumeData, float planetRadius, float mat1Radius, float mat2Radius, float mat3Radius)
        {
            Region      volumeBounds = volumeData.enclosingRegion;
            MaterialSet materialSet  = new MaterialSet();

            for (int z = volumeBounds.lowerCorner.z; z <= volumeBounds.upperCorner.z; z++)
            {
                for (int y = volumeBounds.lowerCorner.y; y <= volumeBounds.upperCorner.y; y++)
                {
                    for (int x = volumeBounds.lowerCorner.x; x <= volumeBounds.upperCorner.x; x++)
                    {
                        // We are going to compute our density value based on the distance of a voxel from the center of our planet.
                        // This is a function which (by definition) is zero at the center of the planet and has a smoothly increasing
                        // value as we move away from the center.
                        //
                        // Note: For efficiency we could probably adapt this to work with squared distances (thereby eliminating
                        // the square root operation), but we'd like to keep this example as intuitive as possible.
                        float distFromCenter = Mathf.Sqrt(x * x + y * y + z * z);

                        // We actually want our volume to have high values in the center and low values as we move out, because our
                        // eath should be a solid sphere surrounded by empty space. If we invert the distance then this is a step in
                        // the right direction. We still have zero in the center, but lower (negative) values as we move out.
                        float density = -distFromCenter;

                        // By adding the 'planetRadius' we now have a function which starts at 'planetRadius' and still decreases as it
                        // moves out. The function passes through zero at a distance of 'planetRadius' and then continues do decrease
                        // as it gets even further out.
                        density += planetRadius;

                        // Ideally we would like our final density value to be '255' for voxels inside the planet and '0' for voxels
                        // outside the planet. At the surface there should be a transition but this should occur not too quickly and
                        // not too slowly, as both of these will result in a jagged appearance to the mesh.
                        //
                        // We probably want the transition to occur over a few voxels, whereas it currently occurs over 255 voxels
                        // because it was derived from the distance. By scaling the density field we effectivly compress the rate
                        // at which it changes at the surface. We also make the center much too high and the outside very low, but
                        // we will clamp these to the corect range later.
                        //
                        // Note: You can try commenting out or changing the value on this line to see the effect it has.
                        density *= 50;

                        // Until now we've been defining our density field as if the threshold was at zero, with positive densities
                        // being solid and negative densities being empty. But actually Cubiquity operates on the range 0 to 255, and
                        // uses a threashold of 127 to decide where to place the generated surface.  Therefore we shift and clamp our
                        // density value and store it in a byte.
                        density += 127;
                        byte densityAsByte = (byte)(Mathf.Clamp(density, 0, 255));

                        if (distFromCenter < mat3Radius)
                        {
                            materialSet.weights[0] = 0;
                            materialSet.weights[1] = 0;
                            materialSet.weights[2] = 0;
                            materialSet.weights[3] = densityAsByte;
                        }
                        else if (distFromCenter < mat2Radius)
                        {
                            materialSet.weights[0] = 0;
                            materialSet.weights[1] = 0;
                            materialSet.weights[2] = densityAsByte;
                            materialSet.weights[3] = 0;
                        }
                        else if (distFromCenter < mat1Radius)
                        {
                            materialSet.weights[0] = 0;
                            materialSet.weights[1] = densityAsByte;
                            materialSet.weights[2] = 0;
                            materialSet.weights[3] = 0;
                        }
                        else //Surface material
                        {
                            materialSet.weights[0] = densityAsByte;
                            materialSet.weights[1] = 0;
                            materialSet.weights[2] = 0;
                            materialSet.weights[3] = 0;
                        }

                        volumeData.SetVoxel(x, y, z, materialSet);
                    }
                }
            }
        }
	// Use this for initialization
	void Start()
	{
		// The size of the volume we will generate
		int width = 128;
		int height = 32;
		int depth = 128;
		
		// FIXME - Where should we delete this?
		/// [DoxygenSnippet-CreateEmptyTerrainVolumeData]
		//Create an empty TerrainVolumeData with dimensions width * height * depth
		TerrainVolumeData data = VolumeData.CreateEmptyVolumeData<TerrainVolumeData>(new Region(0, 0, 0, width-1, height-1, depth-1));
		/// [DoxygenSnippet-CreateEmptyTerrainVolumeData]
		
		TerrainVolume volume = GetComponent<TerrainVolume>();
		TerrainVolumeRenderer volumeRenderer = GetComponent<TerrainVolumeRenderer>();
		
		volume.data = data;
		
		// This example looks better if we adjust the scaling factors on the textures.
		volumeRenderer.material.SetTextureScale("_Tex0", new Vector2(0.062f, 0.062f));
		volumeRenderer.material.SetTextureScale("_Tex1", new Vector2(0.125f, 0.125f));	
		volumeRenderer.material.SetTextureScale("_Tex2", new Vector2(0.125f, 0.125f));
		
		// At this point our volume is set up and ready to use. The remaining code is responsible
		// for iterating over all the voxels and filling them according to our noise functions.
		
		// This scale factor comtrols the size of the rocks which are generated.
		float rockScale = 32.0f;		
		float invRockScale = 1.0f / rockScale;
		
		// Let's keep the allocation outside of the loop.
		MaterialSet materialSet = new MaterialSet();
		
		// Iterate over every voxel of our volume
		for(int z = 0; z < depth; z++)
		{
			for(int y = height-1; y > 0; y--)
			{
				for(int x = 0; x < width; x++)
				{
					// Make sure we don't have anything left in here from the previous voxel
					materialSet.weights[0] = 0;
					materialSet.weights[1] = 0;
					materialSet.weights[2] = 0;
					
					// Simplex noise is quite high frequency. We scale the sample position to reduce this.
					float sampleX = (float)x * invRockScale;
					float sampleY = (float)y * invRockScale;
					float sampleZ = (float)z * invRockScale;
					
					// Get the noise value for the current position.
					// Returned value should be in the range -1 to +1.
					float simplexNoiseValue = SimplexNoise.Noise.Generate(sampleX, sampleY, sampleZ);
					
					// We want to fade off the noise towards the top of the volume (so that the rocks don't go
					// up to the sky) adn add extra material near the bottom of the volume (to create a floor).
					// This altitude value is initially in the range from 0 to +1.
					float altitude = (float)(y + 1) / (float)height;
					
					// Map the altitude to the range -1.0 to +1.0...
					altitude = (altitude * 2.0f) - 1.0f;
					
					// Subtract the altitude from the noise. This adds
					// material near the ground and subtracts it higher up.					
					simplexNoiseValue -= altitude;
					
					// After combining our noise value and our altitude we now have values between -2.0 and 2.0.
					// Cubiquity renders anything below the threshold as empty and anythng above as solid, but
					// in general it is easiest if empty space is completly empty and solid space is completly
					// solid. The exception to this is the region near our surface, where a gentle transition helps
					// obtain smooth shading. By scaling by a large number and then clamping we achieve this effect
					// of making most voxels fully solid or fully empty except near the surface..
					simplexNoiseValue *= 5.0f;
					simplexNoiseValue = Mathf.Clamp(simplexNoiseValue, -0.5f, 0.5f);
					
					// Go back to the range 0.0 to 1.0;
					simplexNoiseValue += 0.5f;
					
					// And then to 0 to 255, ready to convert into a byte.
					simplexNoiseValue *= 255;
					
					// Write the final value value into the third material channel (the one with the rock texture).
					// The value being written is usually 0 (empty) or 255 (solid) except around the transition.
					materialSet.weights[2] = (byte)simplexNoiseValue;
					
					
					// Lastly we write soil or grass voxels into the volume to create a level floor between the rocks.
					// This means we want to set the sum of the materials to 255 if the voxel is below the floor height.
					// We don't want to interfere with the rocks on the transition between the material so we work out
					// how much extra we have to add to get to 255 and then add that to either soil or grass.
					byte excess = (byte)(255 - materialSet.weights[2]);					
					if(y < 11)
					{
						// Add to soil material channel.
						materialSet.weights[1] = excess;
					}
					else if(y < 12)
					{
						// Add to grass material channel.
						materialSet.weights[0] = excess;
					}
					
					// We can now write our computed voxel value into the volume.
					data.SetVoxel(x, y, z, materialSet);
				}
			}
		}
	}