Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Copy terrain texture to another splat;

Discussion in 'Scripting' started by nbg_yalta, Jul 1, 2014.

  1. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    Hi all, I'm trying to copy, to be clear - replace one texture of terrain with another.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TerrainAdjust : MonoBehaviour {
    6.  
    7.    public int sourceIndex;
    8.    public int targetIndex;
    9.  
    10.    private Terrain myTerrain;
    11.    SplatPrototype[] newSplat;
    12.  
    13.    public void CopyTerrainTexture()
    14.    {
    15.      myTerrain = GetComponent<Terrain>();
    16.      newSplat = new SplatPrototype[myTerrain.terrainData.splatPrototypes.Length];
    17.      newSplat = myTerrain.terrainData.splatPrototypes;
    18.      newSplat[targetIndex].texture = myTerrain.terrainData.splatPrototypes[sourceIndex].texture;
    19.      myTerrain.terrainData.splatPrototypes = newSplat;
    20.    }
    21.    
    22. }
    23.  
    I've done it by using indexes of terrain textures, but what I realy want to do is copy source texture's coordinates and its alpha on the terrain, and apply it to the target one. Would be appreciated for any help.
     
  2. judah4

    judah4

    Joined:
    Feb 6, 2011
    Posts:
    256
    You would need to access the terrain's alphamaps and edit the other one's.
    Code (CSharp):
    1. float[, ,] splatmapData = myTerrain.terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
    2. terrain2.terrainData.SetAlphamaps(0, 0, splatmapData);
    This sets all the alphamaps. To set only one texture, you would need to empty the float array except for the index of the splatPrototype. The float[ , , } is indexed by the texture coordinates, and then the index so you can access it
    Code (CSharp):
    1. splatmapData[xCoord, yCoord, splatIndex];
     
    Last edited: Jul 1, 2014
  3. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    Where do I get xCoord and yCoord? would it be something like:

    Code (csharp):
    1.  
    2. float[, ,] splatmapData = myTerrain.terrainData.GetAlphamaps(0, 0, myTerrain.terrainData.alphamapWidth, myTerrain.terrainData.alphamapHeight);
    3. splatmapData[xCoord - ?, yCoord - ?, targetIndex] = splatmapData[xCoord - ?, yCoord - ?, sourceIndex];
    4. myTerrain.terrainData.SetAlphamaps(???);
    5.  
    Sorry... just can't figure it out (
     
  4. judah4

    judah4

    Joined:
    Feb 6, 2011
    Posts:
    256
    Something like

    Code (CSharp):
    1.    
    2. float[,,] terrainSplat = myTerrain.terrainData.GetAlphamaps(0, 0, myTerrain.terrainData.alphamapWidth, myTerrain.terrainData.alphamapHeight);
    3. float[,,] splatmapData = new float[myTerrain.terrainData.alphamapWidth, myTerrain.terrainData.alphamapHeight,terrainData.alphamapLayers];
    4.  
    5.      int xCoordMax = myTerrain.terrainData.alphamapWidth;
    6.      int yCoordMax = myTerrain.terrainData.alphamapHeight;
    7.      int splatLayers = myTerrain.terrainData.alphamapLayers;
    8.              
    9.       for(int xCoord = 0; xCoord < xCoordMax ; xCoord ++) {
    10.            for(int yCoord = 0; yCoord < yCoordMax ; yCoord ++) {
    11.               for(int splat = 0; splat < splatLayers ; splat ++) {
    12.                    splatmapData [yCoord , xCoord , splat ] = terrainSplat[yCoord , xCoord , splat ];    //Unity stores their terrain coords where the world z access is the first value and the world x access is the second.
    13.               }
    14.           }
    15.       }
    16.        newTerrain.terrainData.SetAlphamaps(0, 0, splatmapData );     //assign the new splat to the other terrain
    17.  
    18.  
    That's how you could write all the splats. if you want only one texture, find the index of that splat and instead of looping the splat variable, assign it that index.

    Here's the link to the api http://docs.unity3d.com/ScriptReference/TerrainData.html
     
  5. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    Code (csharp):
    1.  
    2. for(int xCoord = 0; xCoord < xCoordMax ; xCoord ++)
    3.      {
    4.        for(int yCoord = 0; yCoord < yCoordMax ; yCoord ++)
    5.        {
    6.          splatmapData [yCoord , xCoord , targetIndex] = terrainSplat[yCoord , xCoord , sourceIndex];
    7.          }
    8.        }
    9.      }
    10.  
    The problem with only 1 texture, its override all other data with solid black...
    I've tried to save all other data like this
    Code (csharp):
    1.  
    2. for(int xCoord = 0; xCoord < xCoordMax ; xCoord ++)
    3.      {
    4.        for(int yCoord = 0; yCoord < yCoordMax ; yCoord ++)
    5.        {
    6.          for(int splat = 0; splat < splatLayers ; splat ++)
    7.          {
    8.            if(splat != targetIndex-1)
    9.              splatmapData [yCoord , xCoord , splat ] = terrainSplat[yCoord , xCoord , splat ];
    10.            else
    11.              splatmapData [yCoord , xCoord , splat] = terrainSplat[yCoord , xCoord , sourceIndex-1];
    12.          }
    13.        }
    14.      }
    15.  
    And it works, but after apply, targetTexture become white...
    Before:

    After:


    Looks like it stack or somrthing... if remove source texture it will be ok, so the only problem is this brighting
     
    Last edited: Jul 3, 2014
  6. judah4

    judah4

    Joined:
    Feb 6, 2011
    Posts:
    256
    Instead of rewriting all the splats, you could get the data from the new terrain
    Code (CSharp):
    1. splatmapData  = newTerrain.terrainData.GetAlphamaps(0, 0, newTerrain.terrainData.alphamapWidth, newTerrain.terrainData.alphamapHeight);
    And then just assign the single layer with
    Code (CSharp):
    1.  
    2. for(int xCoord = 0; xCoord < xCoordMax ; xCoord ++)
    3.      {
    4.        for(int yCoord = 0; yCoord < yCoordMax ; yCoord ++)
    5.        {
    6.          splatmapData [yCoord , xCoord , targetIndex] = terrainSplat[yCoord , xCoord , sourceIndex];
    7.          }
    8.        }
    9.      }
    You're close!
     
  7. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    I am completely confused... where do I get newTerrain? should I create new one? I've tried, but got the same splatmap, with solid black instead other textures data... I'm sorry for being such a nub
     
  8. judah4

    judah4

    Joined:
    Feb 6, 2011
    Posts:
    256
    oh. I thought you were copying from one terrain to another. Can you post a larger snippet of you code so I understand what your doing exactly?