959e80cf72
assets upload description.
595 lines
18 KiB
C#
595 lines
18 KiB
C#
using System.Collections.Generic;
|
|
using AwesomeTechnologies.External;
|
|
using AwesomeTechnologies.Shaders;
|
|
using AwesomeTechnologies.VegetationSystem;
|
|
using UnityEngine;
|
|
|
|
namespace AwesomeTechnologies
|
|
{
|
|
public enum MeshType
|
|
{
|
|
Normal,
|
|
Billboard
|
|
}
|
|
|
|
public class MeshUtils
|
|
{
|
|
public static GameObject SelectMeshObject(GameObject go, LODLevel lodLevel)
|
|
{
|
|
return SelectNormalMesh(go, lodLevel);
|
|
}
|
|
|
|
public static Quaternion GetMeshRotation(GameObject go, LODLevel lodLevel)
|
|
{
|
|
GameObject meshGameObject = SelectMeshObject(go, lodLevel);
|
|
if (meshGameObject)
|
|
{
|
|
return Quaternion.Inverse(Quaternion.identity) * meshGameObject.transform.rotation;
|
|
}
|
|
else
|
|
{
|
|
return Quaternion.identity;
|
|
}
|
|
}
|
|
|
|
public static int GetLODCount(GameObject go, IShaderController shaderController)
|
|
{
|
|
LODGroup lodGroup = go.GetComponentInChildren<LODGroup>();
|
|
if (lodGroup)
|
|
{
|
|
LOD[] lods = lodGroup.GetLODs();
|
|
int lodCount = lods.Length;
|
|
|
|
LOD lastLOD = lods[lods.Length - 1];
|
|
foreach (Renderer renderer in lastLOD.renderers)
|
|
{
|
|
if (renderer is BillboardRenderer)
|
|
{
|
|
lodCount -= 1;
|
|
break;
|
|
}
|
|
else if (renderer is MeshRenderer)
|
|
{
|
|
if (shaderController == null) continue;
|
|
|
|
MeshRenderer meshRenderer = renderer as MeshRenderer;
|
|
if (shaderController.MatchBillboardShader(meshRenderer.sharedMaterials))
|
|
{
|
|
lodCount -= 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return lodCount;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static GameObject SelectNormalMesh(GameObject go, LODLevel lodLevel)
|
|
{
|
|
LODGroup lodGroup = go.GetComponentInChildren<LODGroup>();
|
|
if (lodGroup)
|
|
{
|
|
LOD[] lods = lodGroup.GetLODs();
|
|
|
|
int lodIndex = (int)lodLevel;
|
|
lodIndex = Mathf.Clamp(lodIndex, 0, lods.Length - 1);
|
|
|
|
LOD lod = lods[lodIndex];
|
|
if (lod.renderers.Length > 0)
|
|
{
|
|
if (lod.renderers[0].gameObject.GetComponent<BillboardRenderer>())
|
|
{
|
|
if (lodIndex > 0)
|
|
{
|
|
lod = lods[lodIndex - 1];
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
return lod.renderers.Length > 0 ? lod.renderers[0].gameObject : null;
|
|
}
|
|
else
|
|
{
|
|
var meshRenderer = go.GetComponent<MeshRenderer>();
|
|
if (meshRenderer) return meshRenderer.gameObject;
|
|
|
|
meshRenderer = go.GetComponentInChildren<MeshRenderer>();
|
|
if (meshRenderer) return meshRenderer.gameObject;
|
|
return null;
|
|
}
|
|
}
|
|
public static Bounds CalculateBoundsInstantiate(GameObject go)
|
|
{
|
|
if (!go)
|
|
{
|
|
return new Bounds(Vector3.zero, Vector3.one);
|
|
}
|
|
|
|
GameObject originalObject = Object.Instantiate(go);
|
|
originalObject.transform.localScale = Vector3.one;
|
|
originalObject.hideFlags = HideFlags.DontSave;
|
|
Bounds objectBounds = CalculateBounds(originalObject);
|
|
|
|
if (Application.isPlaying)
|
|
{
|
|
Object.Destroy(originalObject);
|
|
}
|
|
else
|
|
{
|
|
Object.DestroyImmediate(originalObject);
|
|
}
|
|
|
|
return objectBounds;
|
|
}
|
|
|
|
public static Bounds CalculateBounds(GameObject go)
|
|
{
|
|
Bounds combinedbounds = new Bounds(go.transform.position, Vector3.zero);
|
|
Renderer[] renderers = go.GetComponentsInChildren<Renderer>();
|
|
foreach (Renderer renderer in renderers)
|
|
{
|
|
if (renderer is SkinnedMeshRenderer)
|
|
{
|
|
SkinnedMeshRenderer skinnedMeshRenderer = renderer as SkinnedMeshRenderer;
|
|
Mesh mesh = new Mesh();
|
|
skinnedMeshRenderer.BakeMesh(mesh);
|
|
Vector3[] vertices = mesh.vertices;
|
|
|
|
for (int i = 0; i <= vertices.Length - 1; i++)
|
|
{
|
|
vertices[i] = skinnedMeshRenderer.transform.TransformPoint(vertices[i]);
|
|
}
|
|
mesh.vertices = vertices;
|
|
mesh.RecalculateBounds();
|
|
Bounds meshBounds = mesh.bounds;
|
|
combinedbounds.Encapsulate(meshBounds);
|
|
}
|
|
else
|
|
{
|
|
combinedbounds.Encapsulate(renderer.bounds);
|
|
}
|
|
}
|
|
return combinedbounds;
|
|
}
|
|
|
|
public static Mesh CreateBoxMesh(float length = 1f, float width = 1f, float height = 1f)
|
|
{
|
|
Mesh mesh = new Mesh();
|
|
mesh.Clear();
|
|
|
|
//const float length = 1f;
|
|
//const float width = 1f;
|
|
//const float height = 1f;
|
|
|
|
#region Vertices
|
|
|
|
Vector3 p0 = new Vector3(-length * .5f, -width * .5f, height * .5f);
|
|
Vector3 p1 = new Vector3(length * .5f, -width * .5f, height * .5f);
|
|
Vector3 p2 = new Vector3(length * .5f, -width * .5f, -height * .5f);
|
|
Vector3 p3 = new Vector3(-length * .5f, -width * .5f, -height * .5f);
|
|
|
|
Vector3 p4 = new Vector3(-length * .5f, width * .5f, height * .5f);
|
|
Vector3 p5 = new Vector3(length * .5f, width * .5f, height * .5f);
|
|
Vector3 p6 = new Vector3(length * .5f, width * .5f, -height * .5f);
|
|
Vector3 p7 = new Vector3(-length * .5f, width * .5f, -height * .5f);
|
|
|
|
Vector3[] vertices =
|
|
{
|
|
// Bottom
|
|
p0, p1, p2, p3,
|
|
|
|
// Left
|
|
p7, p4, p0, p3,
|
|
|
|
// Front
|
|
p4, p5, p1, p0,
|
|
|
|
// Back
|
|
p6, p7, p3, p2,
|
|
|
|
// Right
|
|
p5, p6, p2, p1,
|
|
|
|
// Top
|
|
p7, p6, p5, p4
|
|
};
|
|
|
|
#endregion
|
|
|
|
#region Normales
|
|
|
|
Vector3 up = Vector3.up;
|
|
Vector3 down = Vector3.down;
|
|
Vector3 front = Vector3.forward;
|
|
Vector3 back = Vector3.back;
|
|
Vector3 left = Vector3.left;
|
|
Vector3 right = Vector3.right;
|
|
|
|
Vector3[] normales =
|
|
{
|
|
// Bottom
|
|
down, down, down, down,
|
|
|
|
// Left
|
|
left, left, left, left,
|
|
|
|
// Front
|
|
front, front, front, front,
|
|
|
|
// Back
|
|
back, back, back, back,
|
|
|
|
// Right
|
|
right, right, right, right,
|
|
|
|
// Top
|
|
up, up, up, up
|
|
};
|
|
|
|
#endregion
|
|
|
|
#region UVs
|
|
|
|
UnityEngine.Vector2 _00 = new UnityEngine.Vector2(0f, 0f);
|
|
UnityEngine.Vector2 _10 = new UnityEngine.Vector2(1f, 0f);
|
|
UnityEngine.Vector2 _01 = new UnityEngine.Vector2(0f, 1f);
|
|
UnityEngine.Vector2 _11 = new UnityEngine.Vector2(1f, 1f);
|
|
|
|
UnityEngine.Vector2[] uvs =
|
|
{
|
|
// Bottom
|
|
_11, _01, _00, _10,
|
|
|
|
// Left
|
|
_11, _01, _00, _10,
|
|
|
|
// Front
|
|
_11, _01, _00, _10,
|
|
|
|
// Back
|
|
_11, _01, _00, _10,
|
|
|
|
// Right
|
|
_11, _01, _00, _10,
|
|
|
|
// Top
|
|
_11, _01, _00, _10
|
|
};
|
|
|
|
#endregion
|
|
|
|
#region Triangles
|
|
|
|
int[] triangles =
|
|
{
|
|
// Bottom
|
|
3, 1, 0,
|
|
3, 2, 1,
|
|
|
|
// Left
|
|
3 + 4 * 1, 1 + 4 * 1, 0 + 4 * 1,
|
|
3 + 4 * 1, 2 + 4 * 1, 1 + 4 * 1,
|
|
|
|
// Front
|
|
3 + 4 * 2, 1 + 4 * 2, 0 + 4 * 2,
|
|
3 + 4 * 2, 2 + 4 * 2, 1 + 4 * 2,
|
|
|
|
// Back
|
|
3 + 4 * 3, 1 + 4 * 3, 0 + 4 * 3,
|
|
3 + 4 * 3, 2 + 4 * 3, 1 + 4 * 3,
|
|
|
|
// Right
|
|
3 + 4 * 4, 1 + 4 * 4, 0 + 4 * 4,
|
|
3 + 4 * 4, 2 + 4 * 4, 1 + 4 * 4,
|
|
|
|
// Top
|
|
3 + 4 * 5, 1 + 4 * 5, 0 + 4 * 5,
|
|
3 + 4 * 5, 2 + 4 * 5, 1 + 4 * 5
|
|
};
|
|
|
|
#endregion
|
|
|
|
mesh.vertices = vertices;
|
|
mesh.normals = normales;
|
|
mesh.uv = uvs;
|
|
mesh.triangles = triangles;
|
|
|
|
mesh.RecalculateBounds();
|
|
return mesh;
|
|
}
|
|
|
|
public static Mesh CreateCapsuleMesh(float radius, float height)
|
|
{
|
|
int segments = 24;
|
|
|
|
|
|
if (segments % 2 != 0)
|
|
segments++;
|
|
|
|
// extra vertex on the seam
|
|
int points = segments + 1;
|
|
|
|
// calculate points around a circle
|
|
float[] pX = new float[points];
|
|
float[] pZ = new float[points];
|
|
float[] pY = new float[points];
|
|
float[] pR = new float[points];
|
|
|
|
float calcH = 0f;
|
|
float calcV = 0f;
|
|
|
|
for (int i = 0; i < points; i++)
|
|
{
|
|
pX[i] = Mathf.Sin(calcH * Mathf.Deg2Rad);
|
|
pZ[i] = Mathf.Cos(calcH * Mathf.Deg2Rad);
|
|
pY[i] = Mathf.Cos(calcV * Mathf.Deg2Rad);
|
|
pR[i] = Mathf.Sin(calcV * Mathf.Deg2Rad);
|
|
|
|
calcH += 360f / segments;
|
|
calcV += 180f / segments;
|
|
}
|
|
|
|
|
|
// - Vertices and UVs -
|
|
|
|
Vector3[] vertices = new Vector3[points * (points + 1)];
|
|
UnityEngine.Vector2[] uvs = new UnityEngine.Vector2[vertices.Length];
|
|
int ind = 0;
|
|
|
|
// Y-offset is half the height minus the diameter
|
|
float yOff = (height - radius * 2f) * 0.5f;
|
|
if (yOff < 0)
|
|
yOff = 0;
|
|
|
|
// uv calculations
|
|
float stepX = 1f / (points - 1);
|
|
float uvX, uvY;
|
|
|
|
// Top Hemisphere
|
|
int top = Mathf.CeilToInt(points * 0.5f);
|
|
|
|
for (int y = 0; y < top; y++)
|
|
for (int x = 0; x < points; x++)
|
|
{
|
|
vertices[ind] = new Vector3(pX[x] * pR[y], pY[y], pZ[x] * pR[y]) * radius;
|
|
vertices[ind].y = yOff + vertices[ind].y;
|
|
|
|
uvX = 1f - stepX * x;
|
|
uvY = (vertices[ind].y + height * 0.5f) / height;
|
|
uvs[ind] = new UnityEngine.Vector2(uvX, uvY);
|
|
|
|
ind++;
|
|
}
|
|
|
|
// Bottom Hemisphere
|
|
int btm = Mathf.FloorToInt(points * 0.5f);
|
|
|
|
for (int y = btm; y < points; y++)
|
|
for (int x = 0; x < points; x++)
|
|
{
|
|
vertices[ind] = new Vector3(pX[x] * pR[y], pY[y], pZ[x] * pR[y]) * radius;
|
|
vertices[ind].y = -yOff + vertices[ind].y;
|
|
|
|
uvX = 1f - stepX * x;
|
|
uvY = (vertices[ind].y + height * 0.5f) / height;
|
|
uvs[ind] = new UnityEngine.Vector2(uvX, uvY);
|
|
|
|
ind++;
|
|
}
|
|
|
|
|
|
// - Triangles -
|
|
|
|
int[] triangles = new int[segments * (segments + 1) * 2 * 3];
|
|
|
|
for (int y = 0, t = 0; y < segments + 1; y++)
|
|
for (int x = 0; x < segments; x++, t += 6)
|
|
{
|
|
triangles[t + 0] = (y + 0) * (segments + 1) + x + 0;
|
|
triangles[t + 1] = (y + 1) * (segments + 1) + x + 0;
|
|
triangles[t + 2] = (y + 1) * (segments + 1) + x + 1;
|
|
|
|
triangles[t + 3] = (y + 0) * (segments + 1) + x + 1;
|
|
triangles[t + 4] = (y + 0) * (segments + 1) + x + 0;
|
|
triangles[t + 5] = (y + 1) * (segments + 1) + x + 1;
|
|
}
|
|
|
|
Mesh mesh = new Mesh();
|
|
mesh.Clear();
|
|
|
|
mesh.name = "ProceduralCapsule";
|
|
|
|
mesh.vertices = vertices;
|
|
mesh.uv = uvs;
|
|
mesh.triangles = triangles;
|
|
|
|
mesh.RecalculateBounds();
|
|
mesh.RecalculateNormals();
|
|
return mesh;
|
|
//_capsuleColliderMesh = mesh;
|
|
}
|
|
|
|
public static Mesh CreateSphereMesh(float radius = 1f)
|
|
{
|
|
Mesh mesh = new Mesh();
|
|
mesh.Clear();
|
|
|
|
//float radius = 1f;
|
|
// Longitude |||
|
|
int nbLong = 24;
|
|
// Latitude ---
|
|
int nbLat = 16;
|
|
|
|
#region Vertices
|
|
|
|
Vector3[] vertices = new Vector3[(nbLong + 1) * nbLat + 2];
|
|
float _pi = Mathf.PI;
|
|
var _2Pi = _pi * 2f;
|
|
|
|
vertices[0] = Vector3.up * radius;
|
|
for (int lat = 0; lat < nbLat; lat++)
|
|
{
|
|
float a1 = _pi * (lat + 1) / (nbLat + 1);
|
|
float sin1 = Mathf.Sin(a1);
|
|
float cos1 = Mathf.Cos(a1);
|
|
|
|
for (int lon = 0; lon <= nbLong; lon++)
|
|
{
|
|
float a2 = _2Pi * (lon == nbLong ? 0 : lon) / nbLong;
|
|
float sin2 = Mathf.Sin(a2);
|
|
float cos2 = Mathf.Cos(a2);
|
|
|
|
vertices[lon + lat * (nbLong + 1) + 1] = new Vector3(sin1 * cos2, cos1, sin1 * sin2) * radius;
|
|
}
|
|
}
|
|
vertices[vertices.Length - 1] = Vector3.up * -radius;
|
|
|
|
#endregion
|
|
|
|
#region Normales
|
|
|
|
Vector3[] normales = new Vector3[vertices.Length];
|
|
for (int n = 0; n < vertices.Length; n++)
|
|
normales[n] = vertices[n].normalized;
|
|
|
|
#endregion
|
|
|
|
#region UVs
|
|
|
|
UnityEngine.Vector2[] uvs = new UnityEngine.Vector2[vertices.Length];
|
|
uvs[0] = UnityEngine.Vector2.up;
|
|
uvs[uvs.Length - 1] = UnityEngine.Vector2.zero;
|
|
for (int lat = 0; lat < nbLat; lat++)
|
|
for (int lon = 0; lon <= nbLong; lon++)
|
|
uvs[lon + lat * (nbLong + 1) + 1] =
|
|
new UnityEngine.Vector2((float)lon / nbLong, 1f - (float)(lat + 1) / (nbLat + 1));
|
|
|
|
#endregion
|
|
|
|
#region Triangles
|
|
|
|
int nbFaces = vertices.Length;
|
|
int nbTriangles = nbFaces * 2;
|
|
int nbIndexes = nbTriangles * 3;
|
|
int[] triangles = new int[nbIndexes];
|
|
|
|
//Top Cap
|
|
int i = 0;
|
|
for (int lon = 0; lon < nbLong; lon++)
|
|
{
|
|
triangles[i++] = lon + 2;
|
|
triangles[i++] = lon + 1;
|
|
triangles[i++] = 0;
|
|
}
|
|
|
|
//Middle
|
|
for (int lat = 0; lat < nbLat - 1; lat++)
|
|
for (int lon = 0; lon < nbLong; lon++)
|
|
{
|
|
int current = lon + lat * (nbLong + 1) + 1;
|
|
int next = current + nbLong + 1;
|
|
|
|
triangles[i++] = current;
|
|
triangles[i++] = current + 1;
|
|
triangles[i++] = next + 1;
|
|
|
|
triangles[i++] = current;
|
|
triangles[i++] = next + 1;
|
|
triangles[i++] = next;
|
|
}
|
|
|
|
//Bottom Cap
|
|
for (int lon = 0; lon < nbLong; lon++)
|
|
{
|
|
triangles[i++] = vertices.Length - 1;
|
|
triangles[i++] = vertices.Length - (lon + 2) - 1;
|
|
triangles[i++] = vertices.Length - (lon + 1) - 1;
|
|
}
|
|
|
|
#endregion
|
|
|
|
mesh.vertices = vertices;
|
|
mesh.normals = normales;
|
|
mesh.uv = uvs;
|
|
mesh.triangles = triangles;
|
|
|
|
mesh.RecalculateBounds();
|
|
return mesh;
|
|
}
|
|
|
|
public static Mesh ExtrudeMeshFromPolygon(Vector3[] polygonPoints, float yExtent)
|
|
{
|
|
Vector2[] polyginPoints2D = new Vector2[polygonPoints.Length];
|
|
for (int i = 0; i < polygonPoints.Length; i++)
|
|
{
|
|
polyginPoints2D[i] = new Vector2(polygonPoints[i].x,polygonPoints[i].z);
|
|
}
|
|
Triangulator tr = new Triangulator(polyginPoints2D);
|
|
int[] indices = tr.Triangulate();
|
|
|
|
List<int> indexList = new List<int>();
|
|
|
|
for (int i = 0; i < indices.Length; i += 3)
|
|
{
|
|
indexList.Add(indices[i + 2]);
|
|
indexList.Add(indices[i + 1]);
|
|
indexList.Add(indices[i]);
|
|
}
|
|
|
|
int polygonCount = polygonPoints.Length;
|
|
for (int i = 0; i < indices.Length; i+=3)
|
|
{
|
|
indexList.Add(indices[i] + polygonCount);
|
|
indexList.Add(indices[i + 1] + polygonCount);
|
|
indexList.Add(indices[i + 2] + polygonCount);
|
|
}
|
|
|
|
for (int i = 0; i < polygonPoints.Length -1; i++)
|
|
{
|
|
indexList.Add(i);
|
|
indexList.Add(i + polygonCount);
|
|
indexList.Add(i + 1);
|
|
|
|
indexList.Add(i + polygonCount);
|
|
indexList.Add(i + 1 + polygonCount);
|
|
indexList.Add(i + 1);
|
|
}
|
|
|
|
indexList.Add(polygonCount -1 );
|
|
indexList.Add(polygonCount -1 + polygonCount);
|
|
indexList.Add(0);
|
|
|
|
indexList.Add(polygonCount - 1 + polygonCount);
|
|
indexList.Add(polygonCount);
|
|
indexList.Add(0);
|
|
|
|
List<Vector3> verticeList = new List<Vector3>();
|
|
|
|
for (int i = 0; i < polygonPoints.Length; i++)
|
|
{
|
|
verticeList.Add(new Vector3(polygonPoints[i].x, polygonPoints[i].y - yExtent, polygonPoints[i].z));
|
|
}
|
|
|
|
for (int i = 0; i < polygonPoints.Length; i++)
|
|
{
|
|
verticeList.Add(new Vector3(polygonPoints[i].x, polygonPoints[i].y + yExtent, polygonPoints[i].z));
|
|
}
|
|
|
|
Mesh mesh = new Mesh
|
|
{
|
|
vertices = verticeList.ToArray(),
|
|
triangles = indexList.ToArray()
|
|
};
|
|
mesh.RecalculateNormals();
|
|
mesh.RecalculateBounds();
|
|
return mesh;
|
|
}
|
|
}
|
|
}
|
|
|
|
|