• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by nbatothemax · Mar 03, 2013 at 07:20 PM · textureterrainproceduraltoolsroad

Modify Six Times Nothing Road Tool Script to have a lower wear range

So I grabbed this great procedural road tool from Six Times Nothing from this post. Now when I make the road/path I am getting a range for wear that I can set between 0.5 and 1, but that makes the road too faint in my terrain. I cannot seem to find the line that gives the range for the wear property, can anyone advise me where it is in the script?

You can grab the package with the code from the post and I have posted it below.

 using UnityEngine;
 using System;
 using System.Collections;
 using System.Collections.Generic;
 
 [ExecuteInEditMode()]
 
 public class PathNodeObjects 
 {
     public Vector3 position;
     public float width;
 }
 
 public struct TerrainPathCell
 {
     public float heightAtCell;
     public Vector2 position;
     public bool isAdded;
 };
 
 public class AttachedPathScript : MonoBehaviour 
 {
     // Array of terrain cells for convenience 
     public TerrainPathCell[] terrainCells;
     
     public bool addNodeMode;
     public bool isRoad;
     public bool isFinalized;
     
     public PathNodeObjects[] nodeObjects;
     public Vector3[] nodeObjectVerts; // keeps vertice positions for handles
     
     public GameObject pathMesh;
     public MeshCollider pathCollider;
     
     // central terrian cells
     public ArrayList pathCells;
     public ArrayList totalPathVerts;
     public ArrayList innerPathVerts;
     
     // GUI variables
     public int pathWidth;
     public int pathTexture;
     public bool pathUniform;
     public bool pathFlat;
     public bool showHandles;
     public float pathWear;
     public int pathSmooth;
     
     // name of the terrain that created the path
     public GameObject parentTerrain;
     
     public GameObject terrainObj;
     public Terrain terComponent;
     public TerrainData terData;
     public TerrainCollider terrainCollider;
     public float[,] terrainHeights;
     
     public void Awake()
     {
         terComponent = (Terrain) parentTerrain.GetComponent(typeof(Terrain));
         if(terComponent == null)
             Debug.LogError("This script must be attached to a terrain object - Null reference will be thrown");    
     }
     
     public void NewPath()
     {
         nodeObjects = new PathNodeObjects[0];
         pathCollider = (MeshCollider)pathMesh.AddComponent(typeof(MeshCollider));
         
         terrainObj = parentTerrain;
         terComponent = (Terrain) terrainObj.GetComponent(typeof(Terrain));
         
         if(terComponent == null)
             Debug.LogError("This script must be attached to a terrain object - Null reference will be thrown");
             
         terData = terComponent.terrainData;
         terrainHeights = terData.GetHeights(0, 0, terData.heightmapResolution, terData.heightmapResolution);
         terrainCollider = (TerrainCollider)terrainObj.GetComponent(typeof(TerrainCollider));
     }
     
     public void CreatePathNode(TerrainPathCell nodeCell)
     {
         Vector3 pathPosition = new Vector3((nodeCell.position.x/terData.heightmapResolution) * terData.size.x, nodeCell.heightAtCell * terData.size.y , (nodeCell.position.y/terData.heightmapResolution) * terData.size.z);
         
         AddNode(pathPosition, pathWidth);
         
         if(pathFlat || isRoad)
             CreatePath(pathSmooth, true, false);
         
         else
             CreatePath(pathSmooth, false, false);
     }
     
     public void AddNode(Vector3 position, float width)
     {
         PathNodeObjects newPathNodeObject = new PathNodeObjects();
         int nNodes;
         
         if(nodeObjects == null)
         {
             nodeObjects = new PathNodeObjects[0];
             nNodes = 1;
             newPathNodeObject.position = position;
         }
         
         else
         {
             nNodes = nodeObjects.Length + 1;
             newPathNodeObject.position = position;
         }
 
         PathNodeObjects[] newNodeObjects = new PathNodeObjects[nNodes];
         newPathNodeObject.width = width;
         
         int n = newNodeObjects.Length;
         
         for (int i = 0; i < n; i++) 
         {
             if (i != n - 1) 
             {
                 newNodeObjects[i] = nodeObjects[i];
             } 
             
             else 
             {
                 newNodeObjects[i] = newPathNodeObject;
             }
         }
         
         nodeObjects = newNodeObjects;
     }
     
     public void CreatePath(int smoothingLevel, bool flatten, bool road)
     {
         MeshFilter meshFilter = (MeshFilter)pathMesh.GetComponent(typeof(MeshFilter));
         
         if(meshFilter == null)
             return;
         
         Mesh newMesh = meshFilter.sharedMesh;
         terrainHeights = terData.GetHeights(0, 0, terData.heightmapResolution, terData.heightmapResolution);
         
         pathCells = new ArrayList();
      
         if (newMesh == null) 
         {
             newMesh = new Mesh();
             newMesh.name = "Generated Path Mesh";
             meshFilter.sharedMesh = newMesh;
         } 
       
         else 
             newMesh.Clear();
 
         
         if (nodeObjects == null || nodeObjects.Length < 2) 
         {
             return;
         }
         
         int n = nodeObjects.Length;
 
         int verticesPerNode = 2 * (smoothingLevel + 1) * 2;
         int trianglesPerNode = 6 * (smoothingLevel + 1);
         Vector2[] uvs = new Vector2[(verticesPerNode * (n - 1))];
         Vector3[] newVertices = new Vector3[(verticesPerNode * (n - 1))];
         int[] newTriangles = new int[(trianglesPerNode * (n - 1))];
         nodeObjectVerts = new Vector3[(verticesPerNode * (n - 1))];
         int nextVertex  = 0;
         int nextTriangle = 0;
         int nextUV = 0;
         
         // variables for splines and perpendicular extruded points
         float[] cubicX = new float[n];
         float[] cubicZ = new float[n];
         Vector3 handle1Tween = new Vector3();
         Vector3[] g1 = new Vector3[smoothingLevel+1];
         Vector3[] g2 = new Vector3[smoothingLevel+1];
         Vector3[] g3 = new Vector3[smoothingLevel+1];
         Vector3 oldG2 = new Vector3();
         Vector3 extrudedPointL = new Vector3();
         Vector3 extrudedPointR = new Vector3();
         
         for(int i = 0; i < n; i++)
         {
             cubicX[i] = nodeObjects[i].position.x;
             cubicZ[i] = nodeObjects[i].position.z;
         }
         
         for (int i = 0; i < n; i++) 
         {
             g1 = new Vector3[smoothingLevel+1];
             g2 = new Vector3[smoothingLevel+1];
             g3 = new Vector3[smoothingLevel+1];
             
             extrudedPointL = new Vector3();
             extrudedPointR = new Vector3();
             
             if (i == 0)
             {
                 newVertices[nextVertex] = nodeObjects[0].position;
                 nextVertex++;
                 uvs[0] = new Vector2(0f, 1f);
                 nextUV++;
                 newVertices[nextVertex] = nodeObjects[0].position;
                 nextVertex++;
                 uvs[1] = new Vector2(1f, 1f);
                 nextUV++;
                 
                 continue;
             }
             
             float _widthAtNode = pathWidth;        
             
             // Interpolate points along the path using splines for direction and bezier curves for heights
             for (int j = 0; j < smoothingLevel + 1; j++) 
             {
                 // clone the vertex for uvs
                 if(i == 1)
                 {
                     if(j != 0)
                     {
                         newVertices[nextVertex] = newVertices[nextVertex-2];
                         nextVertex++;
                         
                         newVertices[nextVertex] = newVertices[nextVertex-2];
                         nextVertex++;
                         
                         uvs[nextUV] = new Vector2(0f, 1f);
                         nextUV++;
                         uvs[nextUV] = new Vector2(1f, 1f);
                         nextUV++;
                     }
                     
                     else
                         oldG2 = nodeObjects[0].position;
                 }
                 
                 else
                 {
                     newVertices[nextVertex] = newVertices[nextVertex-2];
                     nextVertex++;
                     
                     newVertices[nextVertex] =newVertices[nextVertex-2];
                     nextVertex++;
                     
                     uvs[nextUV] = new Vector2(0f, 1f);
                     nextUV++;
                     uvs[nextUV] = new Vector2(1f, 1f);
                     nextUV++;
                 }
                 
                 float u = (float)j/(float)(smoothingLevel+1f);
                 
                 Cubic[] X = calcNaturalCubic(n-1, cubicX);
                 Cubic[] Z = calcNaturalCubic(n-1, cubicZ);
                 
                 Vector3 tweenPoint = new Vector3(X[i-1].eval(u), 0f, Z[i-1].eval(u));
                 
                 // Add the current tweenpoint as a path cell
                 TerrainPathCell tC = new TerrainPathCell();
                 tC.position.x = ((tweenPoint.x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution;
                 tC.position.y = ((tweenPoint.z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution;
                 tC.heightAtCell = (tweenPoint.y - parentTerrain.transform.position.y)/terData.size.y;
                 pathCells.Add(tC);
                 
                 // update tweened points
                 g2[j] = tweenPoint;
                 g1[j] = oldG2;
                 g3[j] = g2[j] - g1[j];
                 oldG2 = g2[j];
                 
                 // Create perpendicular points for vertices
                 extrudedPointL = new Vector3(-g3[j].z, 0, g3[j].x);
                 extrudedPointR = new Vector3(g3[j].z, 0, -g3[j].x);
                 extrudedPointL.Normalize();
                 extrudedPointR.Normalize();
                 extrudedPointL *= _widthAtNode;
                 extrudedPointR *= _widthAtNode;
                 
                 // Height at the terrain
                 tweenPoint.y = terrainHeights[(int)(((float)(tweenPoint.z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(tweenPoint.x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y;
 
                 // create vertices at the perpendicular points
                 newVertices[nextVertex] = tweenPoint + extrudedPointR;
                 if(!road)
                     newVertices[nextVertex].y = (((float)terrainHeights[(int)(((float)(newVertices[nextVertex].z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(newVertices[nextVertex].x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y) + newVertices[nextVertex-2].y)/2f;
                 else
                     newVertices[nextVertex].y = (float)terrainHeights[(int)(((float)(newVertices[nextVertex].z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(newVertices[nextVertex].x- parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y;
                 nodeObjectVerts[nextVertex] = newVertices[nextVertex];
                 nextVertex++;
                 
                 newVertices[nextVertex] = tweenPoint + extrudedPointL;
                 if(!road)
                     newVertices[nextVertex].y = (((float)terrainHeights[(int)(((float)(newVertices[nextVertex].z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(newVertices[nextVertex].x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y) + newVertices[nextVertex-2].y)/2f;
                 else
                     newVertices[nextVertex].y = (float)terrainHeights[(int)(((float)(newVertices[nextVertex].z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(newVertices[nextVertex].x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y;
                 nodeObjectVerts[nextVertex] = newVertices[nextVertex];
                 nextVertex++;
 
                 uvs[nextUV] = new Vector2(0f, 0f);
                 nextUV++;
                 uvs[nextUV] = new Vector2(1f, 0f);
                 nextUV++;
                 
                 // used later to update the handles
                 if(i == 1)
                     if(j == 0)
                         handle1Tween = tweenPoint;
 
                 // flatten mesh
                 if(flatten && !road)
                 {
                     if(newVertices[nextVertex-1].y < (newVertices[nextVertex-2].y-0.0f))
                     {
                         extrudedPointL *= 1.5f;
                         extrudedPointR *= 1.2f;
                         newVertices[nextVertex-1] = tweenPoint + extrudedPointL;
                         newVertices[nextVertex-2] = tweenPoint + extrudedPointR;
                         
                         newVertices[nextVertex-1].y = newVertices[nextVertex-2].y;
                     }
                 
                     else if(newVertices[nextVertex-1].y > (newVertices[nextVertex-2].y-0.0f))
                     {
                         extrudedPointR *= 1.5f;
                         extrudedPointL *= 1.2f;
                         newVertices[nextVertex-2] = tweenPoint + extrudedPointR;
                         newVertices[nextVertex-1] = tweenPoint + extrudedPointL;
                         
                         newVertices[nextVertex-2].y = newVertices[nextVertex-1].y;        
                     }
                 }
 
                 // Create triangles...
                 newTriangles[nextTriangle] = (verticesPerNode * (i - 1)) + (4 * j); // 0
                 nextTriangle++;
                 newTriangles[nextTriangle] = (verticesPerNode * (i - 1)) + (4 * j) + 1; // 1
                 nextTriangle++;
                 newTriangles[nextTriangle] = (verticesPerNode * (i - 1)) + (4 * j) + 2; // 2
                 nextTriangle++;
                 newTriangles[nextTriangle] = (verticesPerNode * (i - 1)) + (4 * j) + 1; // 1
                 nextTriangle++;
                 newTriangles[nextTriangle] = (verticesPerNode * (i - 1)) + (4 * j) + 3; // 3
                 nextTriangle++;
                 newTriangles[nextTriangle] = (verticesPerNode * (i - 1)) + (4 * j) + 2; // 2
                 nextTriangle++;
             }
         }
         
         // update handles
         g2[0] = handle1Tween;
         g1[0] = nodeObjects[0].position;
         g3[0] = g2[0] - g1[0];
     
         extrudedPointL = new Vector3(-g3[0].z, 0, g3[0].x);
         extrudedPointR = new Vector3(g3[0].z, 0, -g3[0].x);
         
         extrudedPointL.Normalize();
         extrudedPointR.Normalize();
         extrudedPointL *= nodeObjects[0].width;
         extrudedPointR *= nodeObjects[0].width;
         
         newVertices[0] = nodeObjects[0].position + extrudedPointR;
         newVertices[0].y = terrainHeights[(int)(((float)(newVertices[0].z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(newVertices[0].x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y;
         newVertices[1] = nodeObjects[0].position + extrudedPointL;
         newVertices[1].y = terrainHeights[(int)(((float)(newVertices[1].z - parentTerrain.transform.position.z)/terData.size.z) * terData.heightmapResolution), (int)(((float)(newVertices[1].x - parentTerrain.transform.position.x)/terData.size.x) * terData.heightmapResolution)] * terData.size.y + parentTerrain.transform.position.y;
         
         if(road)
         {
             for(int i = 0; i < newVertices.Length; i++)
             {
                 newVertices[i].y = terComponent.SampleHeight(newVertices[i]) + (0.05f) + parentTerrain.transform.position.y;
             }
         }
         
         newMesh.vertices = newVertices;
         newMesh.triangles = newTriangles;
         
         newMesh.uv =  uvs;
         
         Vector3[] myNormals = new Vector3[newMesh.vertexCount];
         for(int p = 0; p < newMesh.vertexCount; p++)
         {
             myNormals[p] = Vector3.up;
         }
 
         newMesh.normals = myNormals;
         
         TangentSolver(newMesh);
 
 //        newMesh.RecalculateNormals();
         pathCollider.sharedMesh = meshFilter.sharedMesh;
         pathCollider.smoothSphereCollisions = true;
         
         // we don't want to see the mesh
         if(!road)
             pathMesh.renderer.enabled = false;
         else
             pathMesh.renderer.enabled = true;
         
         transform.localScale = new Vector3(1,1,1);
     }
     
     public bool FinalizePath()
     {
         transform.localScale = new Vector3(1,1,1);
         
         if(terData.alphamapLayers > pathTexture || isRoad)
         {
             float[,] tempLRheightmap = terData.GetHeights(0, 0, terData.heightmapResolution, terData.heightmapResolution);
             
             float[,,] alphamap = terData.GetAlphamaps(0, 0, terData.alphamapWidth, terData.alphamapHeight);
             float[,,] preWornCells = terData.GetAlphamaps(0, 0, terData.alphamapWidth, terData.alphamapHeight);
             
             innerPathVerts = new ArrayList();
             totalPathVerts = new ArrayList();
             ArrayList roadVerts = new ArrayList();
             ArrayList wearCells = new ArrayList();
             Vector3 returnCollision = new Vector3();
             
             pathMesh.transform.Translate(0f, -150f, 0f);
             
             pathWidth +=  6;
             
             if(pathFlat || isRoad)
                 CreatePath(30, true, false);
             else
                 CreatePath(30, false, false);
             
             foreach(TerrainPathCell tC in terrainCells)
             {
                 RaycastHit raycastHit = new RaycastHit();
                 Ray pathRay = new Ray(new Vector3((float)((tC.position.x * terData.size.x)/terData.heightmapResolution) + parentTerrain.transform.position.x, (float)tC.heightAtCell * terData.size.y + parentTerrain.transform.position.y, (float)((tC.position.y* terData.size.z)/terData.heightmapResolution) + parentTerrain.transform.position.z), -Vector3.up);
                 
                 if(pathCollider.Raycast(pathRay, out raycastHit, Mathf.Infinity))
                 {
                     innerPathVerts.Add(tC);
                 }
             }
             
 //            int detailRadius = (int)((float)terData.detailResolution/(terData.heightmapResolution-1));
             
             /* Removed because Unity 3.0 doesn't allow it :((
             
             // Remove trees and details from path
             foreach(TerrainPathCell tC in innerPathVerts)
             {
                 for(int i = 0; i < terData.detailPrototypes.Length; i++)
                 {
                     int[,] detailLayer = terData.GetDetailLayer(0, 0, terData.detailResolution, terData.detailResolution, i);
 
                     for(int j = -detailRadius+1; j < detailRadius; j++)
                     {
                         for(int k = -detailRadius+1; k < detailRadius; k++)
                         {
                             detailLayer[(int)(((float)tC.position.y/terData.heightmapResolution) * terData.detailResolution) + j, (int)(((float)tC.position.x/terData.heightmapResolution) * terData.detailResolution) + k] = 0;
                         }
                     }
                     terData.SetDetailLayer(0, 0, i, detailLayer);
                 }
                 
                 for(int i = 0; i < terData.treePrototypes.Length; i++)
                 {
                     terComponent.RemoveTrees(new Vector3(((float)tC.position.x/terData.heightmapResolution), ((float)tC.position.y/terData.heightmapResolution)), ((float)5f/terData.size.x), i);
                 }
             }
 
             terData.RecalculateTreePositions();
             */
             
             if(isRoad)
             {
                 pathWidth -=  7;
                 
                 if(pathFlat || isRoad)
                     CreatePath(30, true, false);
                 else
                     CreatePath(30, false, false);
                 
                 foreach(TerrainPathCell tC in terrainCells)
                 {
                     RaycastHit raycastHit = new RaycastHit();
                     Ray pathRay = new Ray(new Vector3((float)((tC.position.x * terData.size.x)/terData.heightmapResolution) + parentTerrain.transform.position.x, (float)tC.heightAtCell * terData.size.y + parentTerrain.transform.position.y, (float)((tC.position.y * terData.size.z)/terData.heightmapResolution) + parentTerrain.transform.position.z), -Vector3.up);
                     
                     if(pathCollider.Raycast(pathRay, out raycastHit, Mathf.Infinity))
                     {
                         roadVerts.Add(tC);
                     }
                 }
                 
                 pathWidth += 7;
             }
             
             pathWidth +=  8;
             
             if(pathFlat || isRoad)
                 CreatePath(30, true, false);
             else
                 CreatePath(30, false, false);
         
             foreach(TerrainPathCell tC in terrainCells)
             {
                 RaycastHit raycastHit = new RaycastHit();
                 Ray pathRay = new Ray(new Vector3((float)((tC.position.x * terData.size.x)/terData.heightmapResolution) + parentTerrain.transform.position.x, (float)tC.heightAtCell * terData.size.y + parentTerrain.transform.position.y, (float)((tC.position.y * terData.size.z)/terData.heightmapResolution) + parentTerrain.transform.position.z), -Vector3.up);
                 
                 if(pathCollider.Raycast(pathRay, out raycastHit, Mathf.Infinity))
                 {
                     returnCollision = raycastHit.point;
                     returnCollision.y = (returnCollision.y - parentTerrain.transform.position.y)/terData.size.y;
                     
                     if(pathFlat || isRoad)
                     {
                         tempLRheightmap[(int)(tC.position.y), (int)(tC.position.x)] = returnCollision.y + ((float)(150.00f/terData.size.y));
                     }
                     
                     totalPathVerts.Add(tC);
                 }
             }
             
             if(isRoad)
                 pathWidth -= 12;
             else
                 pathWidth -= 8;
             
             if(pathFlat || isRoad)
                 CreatePath(100, true, false);
             else
                 CreatePath(100, false, false);
             
             ArrayList totalPathVerts2 = new ArrayList();
             
             if(!isRoad)
             {
                 // After getting the terrain cells for terrain deformation, now get the ones for texturing
                 foreach(TerrainPathCell tC in terrainCells)
                 {
                     RaycastHit raycastHit = new RaycastHit();
                     Ray pathRay = new Ray(new Vector3((float)((tC.position.x * terData.size.x)/terData.heightmapResolution) + parentTerrain.transform.position.x, (float)tC.heightAtCell * terData.size.y + parentTerrain.transform.position.y, (float)((tC.position.y * terData.size.x)/terData.heightmapResolution) + parentTerrain.transform.position.z), -Vector3.up);
                     
                     if(pathCollider.Raycast(pathRay, out raycastHit, Mathf.Infinity))
                     {
                         totalPathVerts2.Add(tC);
                     }
                 }
                 
                 pathMesh.transform.Translate(0f, 150f, 0f);
                 
                 foreach(TerrainPathCell tC in totalPathVerts2)
                 {
                     float closestDistance = 100f;
                     float distanceFromPath = 0;
 
                     foreach(TerrainPathCell pV in pathCells)
                     {
                         distanceFromPath = (float)Mathf.Sqrt((float)Mathf.Pow((pV.position.x - tC.position.x), 2f) + Mathf.Pow((pV.position.y - tC.position.y), 2f));
                         
                         if(distanceFromPath < closestDistance)
                         {
                             closestDistance = distanceFromPath;
                         }
                     }
                     
                     // draw actual path
                     float blendAmount;
                     float randomBlendAdd = UnityEngine.Random.Range(0.0f, 0.5f);
                     
                     blendAmount = (float)closestDistance/(pathWidth/2f);
                     
                     if(blendAmount>1.0f)
                         blendAmount = 1.0f;
                     
                     if(blendAmount<0.0f)
                         blendAmount = 0.0f;
                     
                     if(!pathUniform)
                     {
                         blendAmount += randomBlendAdd;
                         
                         if(blendAmount>1.0f)
                         blendAmount = 1.0f;
                         
                         if(blendAmount<0.0f)
                             blendAmount = 0.0f;
                     }
                     
                     for(int i = 0; i < terData.alphamapLayers; i++)
                     {
                         if(alphamap[Convert.ToInt32((tC.position.y/terData.heightmapResolution) * terData.alphamapResolution), Convert.ToInt32((tC.position.x/terData.heightmapResolution) * terData.alphamapResolution), i] > 0.0f)
                         {
                             Vector3 wearCell = new Vector3(Convert.ToInt32((tC.position.y/terData.heightmapResolution) * terData.alphamapResolution), Convert.ToInt32((tC.position.x/terData.heightmapResolution) * terData.alphamapResolution), 0f);
                             
                             wearCells.Add(wearCell);
 
                             alphamap[Convert.ToInt32((tC.position.y/terData.heightmapResolution) * terData.alphamapResolution), Convert.ToInt32((tC.position.x/terData.heightmapResolution) * terData.alphamapResolution), i]  *= blendAmount;
                         }
                     }
 
                     alphamap[Convert.ToInt32((tC.position.y/terData.heightmapResolution) * terData.alphamapResolution), Convert.ToInt32((tC.position.x/terData.heightmapResolution) * terData.alphamapResolution), pathTexture] += (1f- blendAmount);
                 }
                 
                 if(!pathUniform)
                 {
                     foreach(Vector3 wc in wearCells)
                     {
                         float newValue = 0.0f;
                         float value = 0.0f;
                         
                         for(int i = 0; i < terData.alphamapLayers; i++)
                         {
                             if(i == pathTexture)
                             {
                                 value = alphamap[(int)wc.x, (int)wc.y, i] ;
                                 alphamap[(int)wc.x, (int)wc.y, i]  -= (1.0f - pathWear);
                                 
                                 if(alphamap[(int)wc.x, (int)wc.y, i] < preWornCells[(int)wc.x, (int)wc.y, i])
                                 {
                                     alphamap[(int)wc.x, (int)wc.y, i] = preWornCells[(int)wc.x, (int)wc.y, i];
                                 }
                                 
                                 if(alphamap[(int)wc.x, (int)wc.y, i]  < 0f)
                                     alphamap[(int)wc.x, (int)wc.y, i]  = 0.0f;
                                 
                                 newValue = alphamap[(int)wc.x, (int)wc.y, i] ;
                             }
                         }
                         
                         for(int i = 0; i < terData.alphamapLayers; i++)
                         {
                             if(i != pathTexture)
                             {
                                 alphamap[(int)wc.x, (int)wc.y, i]  = alphamap[(int)wc.x, (int)wc.y, i]  + ((value - newValue) * (alphamap[(int)wc.x, (int)wc.y, i]  / (1.0f - value)));
                                 
                                 if(alphamap[(int)wc.x, (int)wc.y, i]  > 1.0f)
                                     alphamap[(int)wc.x, (int)wc.y, i]  = 1.0f;
                             }
                             
                             if(alphamap[(int)wc.x, (int)wc.y, i]  < 0f)
                                     alphamap[(int)wc.x, (int)wc.y, i]  = 0.0f;
                             if(alphamap[(int)wc.x, (int)wc.y, i]  > 1.0f)
                                     alphamap[(int)wc.x, (int)wc.y, i]  = 1.0f;
                         }
                     }
                 }
                 
                 terData.SetAlphamaps(0, 0, alphamap);
             }
             
             else
                 pathMesh.transform.Translate(0f, 150f, 0f);
             
             terData.SetHeights(0, 0, tempLRheightmap);
             
             if(!isRoad)
             {
                 if(pathFlat)
                     CreatePath(pathSmooth, true, false);
                 else
                     CreatePath(pathSmooth, false, false);
             }
             
             else
             {
                 // Perhaps a bit of an aggressive smooth routine ;)
                 AreaSmooth(innerPathVerts,  1.0f, false);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
             
                 AreaSmooth(innerPathVerts,  1.0f, false);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 AreaSmooth(totalPathVerts,  1.0f, true);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 AreaSmooth(totalPathVerts,  1.0f, true);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 AreaSmooth(innerPathVerts,  1.0f, false);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                     
                 float[,] newTerrainHeights = terData.GetHeights(0, 0, terData.heightmapResolution, terData.heightmapResolution);
                 foreach(TerrainPathCell pv in roadVerts)
                 {
                     if(pathWidth < 10)
                         newTerrainHeights[(int)pv.position.y, (int)pv.position.x] -= 0.007f;
                     
                     else
                         newTerrainHeights[(int)pv.position.y, (int)pv.position.x] -= 0.002f;
                 }
                 terData.SetHeights(0, 0, newTerrainHeights);
                 
                 
                 AreaSmooth(innerPathVerts,  1.0f, false);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 AreaSmooth(innerPathVerts,  1.0f, false);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 AreaSmooth(innerPathVerts,  1.0f, false);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 AreaSmooth(totalPathVerts,  1.0f, true);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                     
                 AreaSmooth(totalPathVerts,  1.0f, true);
                 
                 foreach(TerrainPathCell tv in totalPathVerts)
                     terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 
                 if(pathWidth > 10)
                 {
                     AreaSmooth(innerPathVerts,  1.0f, false);
                 
                     foreach(TerrainPathCell tv in totalPathVerts)
                         terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                         
                         AreaSmooth(innerPathVerts,  1.0f, false);
                     
                     foreach(TerrainPathCell tv in totalPathVerts)
                         terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                         
                         AreaSmooth(innerPathVerts,  1.0f, false);
                     
                     foreach(TerrainPathCell tv in totalPathVerts)
                         terrainCells[Convert.ToInt32((tv.position.y) + ((tv.position.x) * (terData.heightmapResolution)))].isAdded = false;
                 }
                 
                 CreatePath(pathSmooth, true, true);
             }
             
             terData.SetAlphamaps(0, 0, alphamap);
             
             isFinalized = true;
             Debug.Log("Now that you have finalized your road, it is advised that you delete the 'Attached Path Script' component of this game object to avoid corrupting it in the future");
             return true;
         }
         
         else
         {
             Debug.LogError("Invalid texture prototype - please correct and re-finalize");
             return false;
         }
     }
     
     public void AreaSmooth(ArrayList terrainList, float blendAmount, bool exclusion)
     {
         TerrainPathCell tc;
         TerrainPathCell lh;
         
         float[,] blendLRheightmap = terData.GetHeights(0, 0, terData.heightmapResolution, terData.heightmapResolution);
         
         if(exclusion)
             foreach(TerrainPathCell tC in innerPathVerts)
             {        
                 terrainCells[Convert.ToInt32((tC.position.y) + ((tC.position.x) * (terData.heightmapResolution)))].isAdded = true;    
             }
         
         for(int i = 0; i < terrainList.Count; i++)
         {
             tc = (TerrainPathCell)terrainList[i];
             ArrayList locals = new ArrayList();
             
             if(exclusion)
                 for(int x = 2; x > -3; x--)
                 {
                     for(int y =  2; y > -3; y--)
                     {                
                         if(terrainCells[Convert.ToInt32((tc.position.y + y) + ((tc.position.x+x) * (terData.heightmapResolution)))].isAdded == false)
                         {
                             locals.Add(terrainCells[Convert.ToInt32((tc.position.y + y) + ((tc.position.x+x) * (terData.heightmapResolution)))]);
                             terrainCells[Convert.ToInt32((tc.position.y + y) + ((tc.position.x+x) * (terData.heightmapResolution)))].isAdded = true;
                         }
                     }
                 }
             
             else
                 for(int x = 0; x > -1; x--)
                 {
                     for(int y =  0; y > -1; y--)
                     {                
                         if(terrainCells[Convert.ToInt32((tc.position.y + y) + ((tc.position.x+x) * (terData.heightmapResolution)))].isAdded == false)
                         {
                             locals.Add(terrainCells[Convert.ToInt32((tc.position.y + y) + ((tc.position.x+x) * (terData.heightmapResolution)))]);
                             terrainCells[Convert.ToInt32((tc.position.y + y) + ((tc.position.x+x) * (terData.heightmapResolution)))].isAdded = true;
                         }
                     }
                 }
                 
             for(int p = 0; p < locals.Count; p++)
             {
                 lh = (TerrainPathCell)locals[p];
                 ArrayList localHeights = new ArrayList();
                 float cumulativeHeights = 0f;
                 
                 // Get all immediate neighbors 
                 for(int x = 1; x > -2; x--)
                 {
                     for(int y =  1; y > -2; y--)
                     {
                         localHeights.Add(terrainCells[Convert.ToInt32((lh.position.y + y) + ((lh.position.x+x) * (terData.heightmapResolution)))]);
                     }
                 }
                 
                 foreach(TerrainPathCell lH in localHeights)
                 {
                     cumulativeHeights += blendLRheightmap[(int)lH.position.y, (int)lH.position.x];
                 }
                 
                 blendLRheightmap[(int)(lh.position.y), (int)(lh.position.x)] = (terrainHeights[(int)lh.position.y, (int)lh.position.x] * (1f-blendAmount)) + ( ((float)cumulativeHeights/((Mathf.Pow(((float)1f*2f + 1f), 2f)) - 0f)) * blendAmount);
             }
         }
         
         terData.SetHeights(0, 0, blendLRheightmap);
         
         if(!isRoad)
         {
             if(pathFlat)
                 CreatePath(pathSmooth, true, false);
             else
                 CreatePath(pathSmooth, false, false);
         }
         
         else if (isRoad && isFinalized)
             CreatePath(pathSmooth, true, true);
         
         else if (isRoad && !isFinalized)
             CreatePath(pathSmooth, true, false);
     }
     
     public void OnDrawGizmos()
     {
         if(showHandles)
         {
             if(nodeObjectVerts != null)
                 if (nodeObjectVerts.Length > 0) 
                 {
                     int n = nodeObjectVerts.Length;
                     for (int i = 0; i < n; i++) 
                     {
                         // Handles...
                         Gizmos.color = Color.white;
                         Gizmos.DrawLine(transform.TransformPoint(nodeObjectVerts[i] + new Vector3(-0.5f, 0, 0)), transform.TransformPoint(nodeObjectVerts[i]  + new Vector3(0.5f, 0, 0)));
                         Gizmos.DrawLine(transform.TransformPoint(nodeObjectVerts[i]  + new Vector3(0, -0.5f, 0)), transform.TransformPoint(nodeObjectVerts[i]  + new Vector3(0, 0.5f, 0)));
                         Gizmos.DrawLine(transform.TransformPoint(nodeObjectVerts[i]  + new Vector3(0, 0, -0.5f)), transform.TransformPoint(nodeObjectVerts[i]  + new Vector3(0, 0, 0.5f)));
                     }
                 }
         }
     }
     
     public void TangentSolver(Mesh theMesh)
     {
         int vertexCount = theMesh.vertexCount;
         Vector3[] vertices = theMesh.vertices;
         Vector3[] normals = theMesh.normals;
         Vector2[] texcoords = theMesh.uv;
         int[] triangles = theMesh.triangles;
         int triangleCount = triangles.Length/3;
         Vector4[] tangents = new Vector4[vertexCount];
         Vector3[] tan1 = new Vector3[vertexCount];
         Vector3[] tan2 = new Vector3[vertexCount];
         int tri = 0;
         
         int i1, i2, i3;
         Vector3 v1, v2, v3, w1, w2, w3, sdir, tdir;
         float x1, x2, y1, y2, z1, z2, s1, s2, t1, t2, r;
         for (int i = 0; i < (triangleCount); i++)
         {
             i1 = triangles[tri];
             i2 = triangles[tri+1];
             i3 = triangles[tri+2];
 
             v1 = vertices[i1];
             v2 = vertices[i2];
             v3 = vertices[i3];
 
             w1 = texcoords[i1];
             w2 = texcoords[i2];
             w3 = texcoords[i3];
 
             x1 = v2.x - v1.x;
             x2 = v3.x - v1.x;
             y1 = v2.y - v1.y;
             y2 = v3.y - v1.y;
             z1 = v2.z - v1.z;
             z2 = v3.z - v1.z;
 
             s1 = w2.x - w1.x;
             s2 = w3.x - w1.x;
             t1 = w2.y - w1.y;
             t2 = w3.y - w1.y;
 
             r = 1.0f / (s1 * t2 - s2 * t1);
             sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
             tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
 
             tan1[i1] += sdir;
             tan1[i2] += sdir;
             tan1[i3] += sdir;
 
             tan2[i1] += tdir;
             tan2[i2] += tdir;
             tan2[i3] += tdir;
 
             tri += 3;
         }
         
         for (int i = 0; i < (vertexCount); i++)
         {
             Vector3 n = normals[i];
             Vector3 t = tan1[i];
 
             // Gram-Schmidt orthogonalize
             Vector3.OrthoNormalize(ref n, ref t);
 
             tangents[i].x  = t.x;
             tangents[i].y  = t.y;
             tangents[i].z  = t.z;
 
             // Calculate handedness
             tangents[i].w = ( Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f ) ? -1.0f : 1.0f;
         }       
         
         theMesh.tangents = tangents;
     }
     
     public Cubic[] calcNaturalCubic(int n, float[] x) 
     {
         float[] gamma = new float[n+1];
         float[] delta = new float[n+1];
         float[] D = new float[n+1];
         int i;
     
         gamma[0] = 1.0f/2.0f;
         
         for ( i = 1; i < n; i++) 
         {
           gamma[i] = 1/(4-gamma[i-1]);
         }
         
         gamma[n] = 1/(2-gamma[n-1]);
         
         delta[0] = 3*(x[1]-x[0])*gamma[0];
         
         for ( i = 1; i < n; i++) 
         {
           delta[i] = (3*(x[i+1]-x[i-1])-delta[i-1])*gamma[i];
         }
         
         delta[n] = (3*(x[n]-x[n-1])-delta[n-1])*gamma[n];
         
         D[n] = delta[n];
         
         for ( i = n-1; i >= 0; i--) 
         {
           D[i] = delta[i] - gamma[i]*D[i+1];
         }
         
         Cubic[] C = new Cubic[n+1];
         for ( i = 0; i < n; i++) {
           C[i] = new Cubic((float)x[i], D[i], 3*(x[i+1] - x[i]) - 2*D[i] - D[i+1],
                    2*(x[i] - x[i+1]) + D[i] + D[i+1]);
         }
             
         return C;
     }
 }
 
 public class Cubic
 {
   float a,b,c,d;        
 
   public Cubic(float a, float b, float c, float d){
     this.a = a;
     this.b = b;
     this.c = c;
     this.d = d;
   }
   
   public float eval(float u) 
   {
     return (((d*u) + c)*u + b)*u + a;
   }
 }
 
     
 


Comment

People who like this

0 Show 0
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Terrain Procedural Texturing based on height? 4 Answers

Terrain Toolkit and Texturing via Code HELP! 1 Answer

Assigning Textures to Terrain at Runtime 2 Answers

Procedural Texturing on Multiple Terrain Mesh 1 Answer

Adding multiple textures to a procedurally generated terrain mesh? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges