Advertisement
Guest User

Untitled

a guest
Jul 24th, 2014
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.10 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. using Cubiquity;
  5.  
  6. public class ClickToCarveTerrainVolume : MonoBehaviour
  7. {
  8.     private TerrainVolume terrainVolume;
  9.    
  10.     // Bit of a hack - we want to detect mouse clicks rather than the mouse simply being down,
  11.     // but we can't use OnMouseDown because the voxel terrain doesn't have a collider (the
  12.     // individual pieces do, but not the parent). So we define a click as the mouse being down
  13.     // but not being down on the previous frame. We'll fix this better in the future...
  14.     private bool isMouseAlreadyDown = false;
  15.    
  16.     // Use this for initialization
  17.     void Start ()
  18.     {
  19.         // We'll store a reference to the colored cubes volume so we can interact with it later.
  20.         terrainVolume = gameObject.GetComponent<TerrainVolume>();
  21.         if(terrainVolume == null)
  22.         {
  23.             Debug.LogError("This 'ClickToCarveTerrainVolume' script should be attached to a game object with a TerrainVolume component");
  24.         }
  25.     }
  26.    
  27.     // Update is called once per frame
  28.     void Update ()
  29.     {
  30.         // Bail out if we're not attached to a terrain.
  31.         if(terrainVolume == null)
  32.         {
  33.             return;
  34.         }
  35.        
  36.         // If the mouse btton is down and it was not down last frame
  37.         // then we consider this a click, and do our destruction.
  38.         if(Input.GetMouseButton(0))
  39.         {
  40.             if(!isMouseAlreadyDown)
  41.             {
  42.                 // Build a ray based on the current mouse position
  43.                 Vector2 mousePos = Input.mousePosition;
  44.                 Ray ray = Camera.main.ScreenPointToRay(new Vector3(mousePos.x, mousePos.y, 0));            
  45.                
  46.                 // Perform the raycasting.
  47.                 PickSurfaceResult pickResult;
  48.                 bool hit = Picking.PickSurface(terrainVolume, ray, 1000.0f, out pickResult);
  49.                
  50.                 // If we hit a solid voxel then create an explosion at this point.
  51.                 if(hit)
  52.                 {                  
  53.                     int range = 10;
  54.                     CountVoxels((int)pickResult.volumeSpacePos.x, (int)pickResult.volumeSpacePos.y, (int)pickResult.volumeSpacePos.z, range);
  55.                     DestroyVoxels((int)pickResult.volumeSpacePos.x, (int)pickResult.volumeSpacePos.y, (int)pickResult.volumeSpacePos.z, range);
  56.                     CountVoxels((int)pickResult.volumeSpacePos.x, (int)pickResult.volumeSpacePos.y, (int)pickResult.volumeSpacePos.z, range);
  57.                 }
  58.                
  59.                 // Set this flag so the click won't be processed again next frame.
  60.                 isMouseAlreadyDown = true;
  61.             }
  62.         }
  63.         else
  64.         {
  65.             // Clear the flag while we wait for a click.
  66.             isMouseAlreadyDown = false;
  67.         }
  68.     }
  69.    
  70.     void DestroyVoxels(int xPos, int yPos, int zPos, int range)
  71.     {
  72.         // Initialise outside the loop, but we'll use it later.
  73.         int rangeSquared = range * range;
  74.         MaterialSet emptyMaterialSet = new MaterialSet();
  75.        
  76.         // Iterage over every voxel in a cubic region defined by the received position (the center) and
  77.         // the range. It is quite possible that this will be hundreds or even thousands of voxels.
  78.         for(int z = zPos - range; z < zPos + range; z++)
  79.         {
  80.             for(int y = yPos - range; y < yPos + range; y++)
  81.             {
  82.                 for(int x = xPos - range; x < xPos + range; x++)
  83.                 {          
  84.                     // Compute the distance from the current voxel to the center of our explosion.
  85.                     int xDistance = x - xPos;
  86.                     int yDistance = y - yPos;
  87.                     int zDistance = z - zPos;
  88.                    
  89.                     // Working with squared distances avoids costly square root operations.
  90.                     int distSquared = xDistance * xDistance + yDistance * yDistance + zDistance * zDistance;
  91.                    
  92.                     // We're iterating over a cubic region, but we want our explosion to be spherical. Therefore
  93.                     // we only further consider voxels which are within the required range of our explosion center.
  94.                     // The corners of the cubic region we are iterating over will fail the following test.
  95.                     if(distSquared < rangeSquared)
  96.                     {  
  97.                         terrainVolume.data.SetVoxel(x, y, z, emptyMaterialSet);
  98.                     }
  99.                 }
  100.             }
  101.         }
  102.        
  103.         range += 2;
  104.        
  105.         TerrainVolumeEditor.BlurTerrainVolume(terrainVolume, new Region(xPos - range, yPos - range, zPos - range, xPos + range, yPos + range, zPos + range));
  106.         //TerrainVolumeEditor.BlurTerrainVolume(terrainVolume, new Region(xPos - range, yPos - range, zPos - range, xPos + range, yPos + range, zPos + range));
  107.         //TerrainVolumeEditor.BlurTerrainVolume(terrainVolume, new Region(xPos - range, yPos - range, zPos - range, xPos + range, yPos + range, zPos + range));
  108.     }
  109.  
  110.     void CountVoxels(int xPos, int yPos, int zPos, int range)
  111.     {
  112.         // Initialise outside the loop, but we'll use it later.
  113.         int rangeSquared = range * range;
  114.  
  115.         int totalMaterialWeight = 0;
  116.         int noOfSolidVoxels = 0;
  117.         int noOfEmptyVoxels = 0;
  118.        
  119.         // Iterage over every voxel in a cubic region defined by the received position (the center) and
  120.         // the range. It is quite possible that this will be hundreds or even thousands of voxels.
  121.         for(int z = zPos - range; z < zPos + range; z++)
  122.         {
  123.             for(int y = yPos - range; y < yPos + range; y++)
  124.             {
  125.                 for(int x = xPos - range; x < xPos + range; x++)
  126.                 {          
  127.                     // Compute the distance from the current voxel to the center of our explosion.
  128.                     int xDistance = x - xPos;
  129.                     int yDistance = y - yPos;
  130.                     int zDistance = z - zPos;
  131.                    
  132.                     // Working with squared distances avoids costly square root operations.
  133.                     int distSquared = xDistance * xDistance + yDistance * yDistance + zDistance * zDistance;
  134.                    
  135.                     // We're iterating over a cubic region, but we want our explosion to be spherical. Therefore
  136.                     // we only further consider voxels which are within the required range of our explosion center.
  137.                     // The corners of the cubic region we are iterating over will fail the following test.
  138.                     if(distSquared < rangeSquared)
  139.                     {  
  140.                         int sumOfWeightsForThisVoxel = 0;
  141.                         MaterialSet material = terrainVolume.data.GetVoxel(x, y, z);
  142.                         for (uint i = 0; i < 8; i++)
  143.                         {
  144.                             sumOfWeightsForThisVoxel += material.weights[i];
  145.                         }
  146.  
  147.                         totalMaterialWeight += sumOfWeightsForThisVoxel;
  148.  
  149.                         if(sumOfWeightsForThisVoxel > 127)
  150.                         {
  151.                             noOfSolidVoxels ++;
  152.                         }
  153.                         else
  154.                         {
  155.                             noOfEmptyVoxels++;
  156.                         }
  157.                     }
  158.                 }
  159.             }
  160.         }
  161.  
  162.         Debug.Log ("Found " + noOfSolidVoxels + " solid voxels and " + noOfEmptyVoxels + " empty voxels. Total amount of material was " + totalMaterialWeight + ".");
  163.     }
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement