using AwesomeTechnologies.BillboardSystem; using AwesomeTechnologies.Utility; using AwesomeTechnologies.VegetationSystem; using Unity.Burst; using Unity.Collections; using Unity.Jobs; using UnityEngine; using UnityEngine.Rendering; namespace AwesomeTechnologies.Billboards { public class BillboardGenerator { public static Mesh CreateMeshFromBillboardInstance(BillboardInstance billboardInstance) { NativeArray verticeArray = billboardInstance.VerticeList; NativeArray indexArray = billboardInstance.IndexList; NativeArray uvArray = billboardInstance.UvList; NativeArray uv2Array = billboardInstance.Uv2List; NativeArray uv3Array = billboardInstance.Uv3List; NativeArray normalArray = billboardInstance.NormalList; Vector3[] vertices = new Vector3[billboardInstance.VerticeList.Length]; int[] indices = new int[billboardInstance.IndexList.Length]; Vector2[] uvs = new Vector2[billboardInstance.UvList.Length]; Vector2[] uv2S = new Vector2[billboardInstance.Uv2List.Length]; Vector2[] uv3S = new Vector2[billboardInstance.Uv3List.Length]; Vector3[] normals = new Vector3[billboardInstance.NormalList.Length]; verticeArray.CopyToFast(vertices); indexArray.CopyToFast(indices); uvArray.CopyToFast(uvs); uv2Array.CopyToFast(uv2S); uv3Array.CopyToFast(uv3S); normalArray.CopyToFast(normals); var newMesh = new Mesh { hideFlags = HideFlags.DontSave, subMeshCount = 1, indexFormat = IndexFormat.UInt32, vertices = vertices }; newMesh.SetIndices(indices, MeshTopology.Triangles, 0, false); newMesh.uv = uvs; newMesh.uv2 = uv2S; newMesh.uv3 = uv3S; newMesh.normals = normals; //TODO add bounds manually from billboard cell bounds //TODO replace with nativearray direct when unity adds interface. newMesh.RecalculateBounds(); return newMesh; } [BurstCompile(CompileSynchronously = true)] public struct CreateBillboardMeshJob : IJob { [ReadOnly] public NativeList InstanceList; public NativeList VerticeList; public NativeList IndexList; public NativeList UvList; public NativeList Uv2List; public NativeList Uv3List; public NativeList NormalList; public float BoundsYExtent; public float VegetationItemSize; private Vector3 _srcVert0; private Vector3 _srcVert1; private Vector3 _srcVert2; private Vector3 _srcVert3; private Vector2 _srcUVs0; private Vector2 _srcUVs1; private Vector2 _srcUVs2; private Vector2 _srcUVs3; private int _srcIndex0; private int _srcIndex1; private int _srcIndex2; private int _srcIndex3; private int _srcIndex4; private int _srcIndex5; public void Execute() { SetupData(); int vertIndex = 0; for (int i = 0; i <= InstanceList.Length - 1; i++) { MatrixInstance matrixInstance = InstanceList[i]; Vector3 scale = ExtractScaleFromMatrix(matrixInstance.Matrix) / 2f; Vector3 position = ExtractTranslationFromMatrix(matrixInstance.Matrix) + new Vector3(0, BoundsYExtent * scale.y * 2, 0); Quaternion rotation = ExtractRotationFromMatrix(matrixInstance.Matrix); VerticeList.Add(position); VerticeList.Add(position); VerticeList.Add(position); VerticeList.Add(position); NormalList.Add(_srcVert0); NormalList.Add(_srcVert1); NormalList.Add(_srcVert2); NormalList.Add(_srcVert3); UvList.Add(_srcUVs0); UvList.Add(_srcUVs1); UvList.Add(_srcUVs2); UvList.Add(_srcUVs3); var rotationVector = new Vector2((360f - rotation.eulerAngles.y) / 360f, 1f); Uv2List.Add(rotationVector); Uv2List.Add(rotationVector); Uv2List.Add(rotationVector); Uv2List.Add(rotationVector); Vector2 scaleAndVFix; scaleAndVFix.x = VegetationItemSize * scale.x * 2f; //scaleAndVFix.y = -(BoundsYExtent * scale.y); scaleAndVFix.y = -(BoundsYExtent * scale.y * 2); Uv3List.Add(scaleAndVFix); Uv3List.Add(scaleAndVFix); Uv3List.Add(scaleAndVFix); Uv3List.Add(scaleAndVFix); IndexList.Add(_srcIndex0 + vertIndex); IndexList.Add(_srcIndex1 + vertIndex); IndexList.Add(_srcIndex2 + vertIndex); IndexList.Add(_srcIndex3 + vertIndex); IndexList.Add(_srcIndex4 + vertIndex); IndexList.Add(_srcIndex5 + vertIndex); vertIndex += 4; } } void SetupData() { _srcVert0 = new Vector3(-0.5f, -0.5f, 0); _srcVert1 = new Vector3(0.5f, 0.5f, 0); _srcVert2 = new Vector3(0.5f, -0.5f, 0); _srcVert3 = new Vector3(-0.5f, 0.5f, 0); _srcUVs0 = new Vector2(0f, 0f); _srcUVs1 = new Vector2(1f, 1f); _srcUVs2 = new Vector2(1f, 0f); _srcUVs3 = new Vector2(0f, 1); _srcIndex0 = 0; _srcIndex1 = 1; _srcIndex2 = 2; _srcIndex3 = 1; _srcIndex4 = 0; _srcIndex5 = 3; } Vector3 ExtractTranslationFromMatrix(Matrix4x4 matrix) { Vector3 translate; translate.x = matrix.m03; translate.y = matrix.m13; translate.z = matrix.m23; return translate; } public static Vector3 ExtractScaleFromMatrix(Matrix4x4 matrix) { return new Vector3(matrix.GetColumn(0).magnitude, matrix.GetColumn(1).magnitude, matrix.GetColumn(2).magnitude); } public static Quaternion ExtractRotationFromMatrix(Matrix4x4 matrix) { Vector3 forward; forward.x = matrix.m02; forward.y = matrix.m12; forward.z = matrix.m22; if (forward == Vector3.zero) return Quaternion.identity; Vector3 upwards; upwards.x = matrix.m01; upwards.y = matrix.m11; upwards.z = matrix.m21; return Quaternion.LookRotation(forward, upwards); } } } }