Firstborn/Assets/AwesomeTechnologies/VegetationStudioPro/Runtime/BillboardSystem/BillboardGenerator.cs

198 lines
7.3 KiB
C#
Raw Permalink Normal View History

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<Vector3> verticeArray = billboardInstance.VerticeList;
NativeArray<int> indexArray = billboardInstance.IndexList;
NativeArray<Vector2> uvArray = billboardInstance.UvList;
NativeArray<Vector2> uv2Array = billboardInstance.Uv2List;
NativeArray<Vector2> uv3Array = billboardInstance.Uv3List;
NativeArray<Vector3> 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<MatrixInstance> InstanceList;
public NativeList<Vector3> VerticeList;
public NativeList<int> IndexList;
public NativeList<Vector2> UvList;
public NativeList<Vector2> Uv2List;
public NativeList<Vector2> Uv3List;
public NativeList<Vector3> 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);
}
}
}
}