Skip to content

Instantly share code, notes, and snippets.

@n-yoda
Created December 21, 2015 04:49
Show Gist options
  • Save n-yoda/eb006687b124a5201592 to your computer and use it in GitHub Desktop.
Save n-yoda/eb006687b124a5201592 to your computer and use it in GitHub Desktop.
UnityのTerrainの平行移動とか
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
public class TerrainEditor : EditorWindow
{
int moveX = 10;
int moveY = 10;
int width, height;
public TerrainData target;
[MenuItem("Window/Terrain Editor")]
static void OpenTerrainEditor()
{
var window = EditorWindow.GetWindow<TerrainEditor>("Terrain Editor");
window.target = Selection.activeObject as TerrainData;
}
void OnGUI()
{
target = EditorGUILayout.ObjectField(target, typeof(TerrainData), false) as TerrainData;
if (target != null)
{
EditorGUILayout.LabelField("Size", "(" + target.heightmapWidth + ", " + target.heightmapHeight + ")");
moveX = EditorGUILayout.IntField("Move X", moveX);
moveY = EditorGUILayout.IntField("Move Y", moveY);
if (GUILayout.Button("Move"))
{
MoveTerrain(target, moveX, moveY);
}
}
}
public static void MoveTerrain(TerrainData terrain, int x, int y)
{
var so = new SerializedObject(terrain);
var editeds = new List<UnityEngine.Object>();
// Undo
var textures = so.FindProperty("m_SplatDatabase.m_AlphaTextures");
for (int i = 0; i < textures.arraySize; i++)
{
editeds.Add(textures.GetArrayElementAtIndex(i).objectReferenceValue);
}
editeds.Add(terrain);
Undo.RecordObjects(editeds.ToArray(), "Move Terrain");
// Move Hightmap
var w = terrain.heightmapWidth;
var h = terrain.heightmapHeight;
var heights = terrain.GetHeights(0, 0, w, h);
terrain.SetHeights(0, 0, MoveHeights(heights, w, h, x, y));
// Move Trees
var moveU = (float)x / w;
var moveV = (float)y / h;
var trees = terrain.treeInstances;
for (int i = 0; i < trees.Length; i++)
{
trees[i].position += new Vector3(moveU, 0f, moveV);
}
terrain.treeInstances = trees.Where(tree =>
0f <= tree.position.x && tree.position.x <= 1f
&& 0f <= tree.position.z && tree.position.z <= 1f).ToArray();
// Move Details
// Move Splat
for (int i = 0; i < textures.arraySize; i++)
{
var tex = textures.GetArrayElementAtIndex(i).objectReferenceValue as Texture2D;
editeds.Add(tex);
MoveTexture(tex, moveU, moveV);
}
}
static float[,] MoveHeights(float[,] map,
int width, int height, int moveX, int moveY)
{
var result = new float[width, height];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var srcX = x - moveX;
var srcY = y - moveY;
if (0 <= srcX && srcX < width && 0 <= srcY && srcY < height)
result[y, x] = map[srcY, srcX];
else
result[y, x] = 0;
}
}
return result;
}
static void MoveTexture(Texture2D texture, float u, float v)
{
Color[] colors = new Color[texture.width * texture.height];
var uUnit = 1f / texture.width;
var vUnit = 1f / texture.height;
for (int y = 0; y < texture.width; y++)
{
for (int x = 0; x < texture.height; x++)
{
var dst = y * texture.width + x;
var srcU = (x + 0.5f) * uUnit - u;
var srcV = (y + 0.5f) * vUnit - v;
colors[dst] = texture.GetPixelBilinear(srcU, srcV);
}
}
texture.SetPixels(colors);
texture.Apply();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment