public GetInterpolatedNormal ( float x, float y ) : |
||
x | float | |
y | float | |
리턴 |
/// <summary> /// </summary> /// <param name="terrainData"></param> /// <param name="position">Location in the XZ plane (not the XY plane!)</param> /// <param name="sphereRadius"></param> /// <returns></returns> private static Vector3 AdjustSpawnPositionForTerrainShape(TerrainData terrainData, Vector2 position, float sphereRadius) { var height = terrainData.GetInterpolatedHeight(position.x, position.y); var normal = terrainData.GetInterpolatedNormal(position.x, position.y); var offsetAlongNormal = normal * sphereRadius; var positionOnTerrain = new Vector3(position.x, height, position.y); return positionOnTerrain + offsetAlongNormal; }
private static Texture2D GenerateTerrainNormalTexture(TerrainData data, int width, int height) { Texture2D normalTex = null; #if UNITY_EDITOR string normalTexturePath = UnityEditor.AssetDatabase.GetAssetPath(data); foreach (var asset in UnityEditor.AssetDatabase.LoadAllAssetsAtPath(normalTexturePath)) { if (asset.name.Contains("NormalMap")) { normalTex = asset as Texture2D; break; } } #endif // if its null, it's not created yet if (normalTex == null || normalTex.width != width || normalTex.height != height) { bool overwrite = normalTex != null; if (!overwrite) { normalTex = new Texture2D(width, height, TextureFormat.RGBA32, false); #if UNITY_EDITOR normalTex.name = "NormalMap"; UnityEditor.AssetDatabase.AddObjectToAsset(normalTex, data); UnityEditor.AssetDatabase.ImportAsset(normalTexturePath); #endif } else { normalTex.Resize(width, height); } } Color[] normalData = new Color[normalTex.width * normalTex.height]; for (int x = 0; x < normalTex.width; x++) { for (int y = 0; y < normalTex.height; y++) { float xCoord = x / (float)normalTex.width; float yCoord = y / (float)normalTex.width; Vector3 normal = data.GetInterpolatedNormal(xCoord, yCoord); int index = x + y * normalTex.width; normalData[index].r = normal.x; normalData[index].g = normal.y; normalData[index].b = normal.z; } } normalTex.SetPixels(normalData); normalTex.Apply(); return normalTex; }
void OnGUI() { if (finalize) { // select created texture Selection.activeObject=AssetDatabase.LoadAssetAtPath(save_path, typeof(Texture2D)); finalize=false; } EditorGUILayout.Space(); sourceTerrain = EditorGUILayout.ObjectField("Source Terrain Data", sourceTerrain, typeof(TerrainData), false) as TerrainData; EditorGUILayout.Space(); if (sourceTerrain) { bool render_flag=false; bool render_flag_npot=false; if (GUILayout.Button("Render heights")) { render_flag=true; } if (GUILayout.Button("Render heights (NPOT exact size 2^n+1)")) { render_flag_npot=true; } if (render_flag || render_flag_npot) { rendered_tex=new Texture2D(sourceTerrain.heightmapResolution-(render_flag_npot ? 0:1), sourceTerrain.heightmapResolution-(render_flag_npot ? 0:1), TextureFormat.RGBA32, false, true); Color32[] cols=new Color32[rendered_tex.width * rendered_tex.height]; for( int x = 0; x < rendered_tex.width; x++ ) { for( int y = 0; y < rendered_tex.height; y++ ) { float _x = 1.0f*x/(rendered_tex.width-1); float _y = 1.0f*y/(rendered_tex.height-1); int _hiP,_loP; float hgt = sourceTerrain.GetInterpolatedHeight( _x,_y )/sourceTerrain.size.y; _hiP = Mathf.FloorToInt( hgt*255.0f ); _loP = Mathf.FloorToInt( (hgt*255.0f - _hiP)*255.0f ); int _Nx, _Nz; Vector3 norm = sourceTerrain.GetInterpolatedNormal( _x,_y ); _Nx = Mathf.RoundToInt( Mathf.Clamp01(norm.x*0.5f+0.5f)*255.0f ); _Nz = Mathf.RoundToInt( Mathf.Clamp01(norm.z*0.5f+0.5f)*255.0f ); cols[y * rendered_tex.width + x] = new Color32( (byte)_hiP, (byte)_loP, (byte)_Nx, (byte)_Nz ); } } rendered_tex.SetPixels32(cols); rendered_tex.Apply(false,false); if (Selection.activeObject is Texture2D && AssetDatabase.GetAssetPath(Selection.activeObject as Texture2D)!="") { save_path=AssetDatabase.GetAssetPath(Selection.activeObject as Texture2D); directory=Path.GetDirectoryName(save_path); file=Path.GetFileNameWithoutExtension(save_path)+".png"; } else { if (save_path=="") { directory=Path.GetDirectoryName(AssetDatabase.GetAssetPath(sourceTerrain)); file=Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(sourceTerrain))+".png"; } } } } if (rendered_tex) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Height(RG) & normal(BA) texture", GUILayout.MinWidth(200)); EditorGUILayout.ObjectField(rendered_tex, typeof(Texture2D), false, GUILayout.MinWidth(150), GUILayout.MinHeight(150), GUILayout.MaxWidth(150), GUILayout.MaxHeight(150)); EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Save texture")) { if (save_path=="") { directory=Path.GetDirectoryName(AssetDatabase.GetAssetPath(sourceTerrain)); file=Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(sourceTerrain))+".png"; } SaveTexture(directory, file); } } }
/// <summary> /// Generate textures for the terrain /// </summary> float[,,] GenerateAlphaMap(TerrainData data) { //make sure textures have been set if (_splatPrototypes.Length < 1) { return null; } //create map var width = data.alphamapWidth; var height = data.alphamapHeight; var layers = data.alphamapLayers - 1; //ignore the road layer var alphamap = new float[width, height, layers + 1]; for (int x = 0; x < width; ++x) { for (int z = 0; z < height; ++z) { var xNorm = (float)x / (float)width; var zNorm = (float)z / (float)height; //sample height at this location var h = data.GetHeight(z, x); //get normalized coordinates relative to the overall terrain dimensions var normal = data.GetInterpolatedNormal(zNorm, xNorm); //get steepnes at the coordinate var angle = data.GetSteepness(zNorm, xNorm); var weights = new float[layers]; if (layers > 1) { weights[0] = 0.5f; } if (layers > 2) { //more influence at steep heights weights[1] = angle / 90f; } if (layers > 3 && h < 0.4f) { weights[2] = 1f; } float sum = weights.Sum(); //go over all terrain textures for (int i = 1; i < layers; i++) { //normalize weights[i - 1] /= sum; //set weight for correct texture alphamap[x, z, i] = weights[i - 1]; } } } return alphamap; }