1
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
// Fantasy Adventure Environment
|
||||
// Copyright Staggart Creations
|
||||
// staggart.xyz
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace FAE
|
||||
{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
|
||||
public class TerrainUVUtil : ScriptableObject
|
||||
{
|
||||
|
||||
//Dev
|
||||
public static readonly bool debug = false;
|
||||
|
||||
//Public
|
||||
public enum Workflow
|
||||
{
|
||||
None,
|
||||
Terrain,
|
||||
Mesh
|
||||
}
|
||||
public Workflow workflow = Workflow.None;
|
||||
|
||||
public Bounds meshBounds;
|
||||
public Vector3 pivotPos;
|
||||
|
||||
public float height;
|
||||
public float bottom;
|
||||
public Vector3 size;
|
||||
public Vector3 centerPostion;
|
||||
public Vector3 originPosition;
|
||||
|
||||
public Terrain[] terrains;
|
||||
public MeshRenderer[] meshes;
|
||||
|
||||
public Vector4 terrainScaleOffset;
|
||||
|
||||
public void GetObjectPlanarUV(GameObject[] gameObjects)
|
||||
{
|
||||
//No objects given
|
||||
if (gameObjects.Length == 0)
|
||||
{
|
||||
Debug.LogError("No objects given to render!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Determine workflow
|
||||
if (gameObjects[0].GetComponent<Terrain>())
|
||||
{
|
||||
workflow = Workflow.Terrain;
|
||||
GetTerrainInfo(gameObjects);
|
||||
}
|
||||
else if (gameObjects[0].GetComponent<MeshRenderer>())
|
||||
{
|
||||
workflow = Workflow.Mesh;
|
||||
GetMeshInfo(gameObjects);
|
||||
}
|
||||
//Safeguard
|
||||
else
|
||||
{
|
||||
workflow = Workflow.None;
|
||||
Debug.LogError("Terrain UV Utility: Current object is neither a terrain nor a mesh!");
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (debug)
|
||||
{
|
||||
Debug.Log("Summed size: " + size);
|
||||
Debug.Log("Center position: " + centerPostion);
|
||||
Debug.Log("Origin position:" + originPosition);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void GetMeshInfo(GameObject[] meshObjects)
|
||||
{
|
||||
height = 0;
|
||||
size = Vector3.zero;
|
||||
MeshRenderer mesh;
|
||||
|
||||
//Init mesh terrain array
|
||||
meshes = new MeshRenderer[meshObjects.Length];
|
||||
|
||||
Bounds cornerMeshBounds = new Bounds();
|
||||
|
||||
for (int i = 0; i < meshObjects.Length; i++)
|
||||
{
|
||||
mesh = meshObjects[i].GetComponent<MeshRenderer>();
|
||||
meshBounds = mesh.bounds;
|
||||
|
||||
//Store the bounds of the first, corner, mesh
|
||||
if (i == 0) cornerMeshBounds = meshBounds;
|
||||
|
||||
//Mesh size has to be uniform
|
||||
if (!IsApproximatelyEqual(meshBounds.extents.x, meshBounds.extents.z))
|
||||
{
|
||||
Debug.LogWarningFormat("[PigmentMapGenerator] size of \"{0}\" is not uniform at {1}! This is required for correct results.", mesh.name, meshBounds.extents.x + "x" + meshBounds.extents.z);
|
||||
}
|
||||
|
||||
//Set height to highest terrain
|
||||
if (meshBounds.size.y > height)
|
||||
{
|
||||
height = meshBounds.size.y;
|
||||
}
|
||||
|
||||
//With every terrain, size is increased
|
||||
size.x += meshBounds.size.x;
|
||||
size.z += meshBounds.size.z;
|
||||
}
|
||||
|
||||
size.y = height;
|
||||
|
||||
//Multi-terrain
|
||||
if (meshObjects.Length > 1)
|
||||
{
|
||||
size.x /= Mathf.Sqrt(meshObjects.Length);
|
||||
size.z /= Mathf.Sqrt(meshObjects.Length);
|
||||
originPosition = cornerMeshBounds.min;
|
||||
originPosition.y = meshObjects[0].transform.position.y;
|
||||
centerPostion = new Vector3(cornerMeshBounds.min.x + (size.x / 2), height / 2f, cornerMeshBounds.min.z + (size.z / 2));
|
||||
}
|
||||
//Single terrain
|
||||
else
|
||||
{
|
||||
originPosition = cornerMeshBounds.min;
|
||||
originPosition.y = meshObjects[0].transform.position.y;
|
||||
centerPostion = cornerMeshBounds.center;
|
||||
}
|
||||
|
||||
terrainScaleOffset = new Vector4(size.x, size.z, originPosition.x, originPosition.z);
|
||||
|
||||
Shader.SetGlobalVector("_TerrainUV", terrainScaleOffset);
|
||||
}
|
||||
|
||||
private void GetTerrainInfo(GameObject[] terrainObjects)
|
||||
{
|
||||
height = 0;
|
||||
size = Vector3.zero;
|
||||
Terrain terrain;
|
||||
|
||||
//Init terrain array
|
||||
terrains = new Terrain[terrainObjects.Length];
|
||||
|
||||
for (int i = 0; i < terrainObjects.Length; i++)
|
||||
{
|
||||
|
||||
terrain = terrainObjects[i].GetComponent<Terrain>();
|
||||
terrains[i] = terrain;
|
||||
|
||||
//Terrain size has to be uniform
|
||||
if (!IsApproximatelyEqual(terrain.terrainData.size.x, terrain.terrainData.size.z))
|
||||
{
|
||||
Debug.LogErrorFormat(this.name + ": size of \"{0}\" is not uniform at {1}!", terrain.name, terrain.terrainData.size.x + "x" + terrain.terrainData.size.z);
|
||||
return;
|
||||
}
|
||||
|
||||
//Set height to highest terrain
|
||||
if (terrain.terrainData.size.y > height)
|
||||
{
|
||||
height = terrain.terrainData.size.y;
|
||||
}
|
||||
if (terrains[i].transform.position.y < bottom)
|
||||
{
|
||||
bottom = terrain.transform.position.y;
|
||||
}
|
||||
|
||||
//With every terrain, size is increased
|
||||
size += terrain.terrainData.size;
|
||||
}
|
||||
|
||||
//For multi terrains, divide by square root of num tiles to get total size
|
||||
if (terrainObjects.Length > 1)
|
||||
{
|
||||
size /= Mathf.Sqrt(terrainObjects.Length);
|
||||
}
|
||||
|
||||
//First terrain is considered the corner and origin
|
||||
originPosition = terrains[0].transform.position;
|
||||
|
||||
//Offset origin point by half the size to get center
|
||||
centerPostion = new Vector3(originPosition.x + (size.x / 2f), originPosition.y + (height / 2f), originPosition.z + (size.z / 2f));
|
||||
}
|
||||
|
||||
//Check if values are equal, has error margin for floating point precision
|
||||
private bool IsApproximatelyEqual(float a, float b)
|
||||
{
|
||||
return Mathf.Abs(a - b) < 0.02f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user