去掉obi,使用自写绳索
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13ef5aa25fc194dda8d453b36a50e5d0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,316 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IMeshDataProvider
|
||||
{
|
||||
Mesh sourceMesh { get; }
|
||||
uint meshInstances { get; }
|
||||
|
||||
int vertexCount { get; }
|
||||
int triangleCount { get; }
|
||||
|
||||
void GetVertices(List<Vector3> vertices);
|
||||
void GetNormals(List<Vector3> normals);
|
||||
void GetTangents(List<Vector4> tangents);
|
||||
void GetColors(List<Color> colors);
|
||||
void GetUVs(int channel, List<Vector2> uvs);
|
||||
|
||||
void GetTriangles(List<int> triangles);
|
||||
}
|
||||
|
||||
public class MeshDataBatch
|
||||
{
|
||||
public struct MeshData
|
||||
{
|
||||
public int firstVertex;
|
||||
public int vertexCount;
|
||||
|
||||
public int firstTriangle;
|
||||
public int triangleCount;
|
||||
}
|
||||
|
||||
private Dictionary<Mesh, int> meshToIndex;
|
||||
|
||||
// per mesh data:
|
||||
public ObiNativeList<MeshData> meshData;
|
||||
|
||||
public ObiNativeList<Vector3> restPositions;
|
||||
public ObiNativeList<Vector3> restNormals;
|
||||
public ObiNativeList<Vector4> restTangents;
|
||||
public ObiNativeList<Color> restColors;
|
||||
public ObiNativeList<Vector2> uv;
|
||||
public ObiNativeList<Vector2> uv2;
|
||||
public ObiNativeList<Vector2> uv3;
|
||||
public ObiNativeList<Vector2> uv4;
|
||||
public ObiNativeList<int> triangles;
|
||||
|
||||
private List<Vector3> tempVertices;
|
||||
private List<Vector3> tempNormals;
|
||||
private List<Vector4> tempTangents;
|
||||
private List<Color> tempColors;
|
||||
private List<Vector2> tempUV;
|
||||
private List<Vector2> tempUV2;
|
||||
private List<Vector2> tempUV3;
|
||||
private List<Vector2> tempUV4;
|
||||
private List<int> tempTriangles;
|
||||
|
||||
public int Count { get { return meshData.count; } }
|
||||
|
||||
public MeshDataBatch()
|
||||
{
|
||||
meshToIndex = new Dictionary<Mesh, int>();
|
||||
meshData = new ObiNativeList<MeshData>();
|
||||
|
||||
InitializeTempData();
|
||||
InitializeDynamicData();
|
||||
InitializeStaticData();
|
||||
}
|
||||
|
||||
public void InitializeTempData()
|
||||
{
|
||||
tempVertices = new List<Vector3>();
|
||||
tempNormals = new List<Vector3>();
|
||||
tempTangents = new List<Vector4>();
|
||||
tempColors = new List<Color>();
|
||||
|
||||
tempUV = new List<Vector2>();
|
||||
tempUV2 = new List<Vector2>();
|
||||
tempUV3 = new List<Vector2>();
|
||||
tempUV4 = new List<Vector2>();
|
||||
tempTriangles = new List<int>();
|
||||
}
|
||||
|
||||
public void InitializeDynamicData()
|
||||
{
|
||||
if (restPositions == null)
|
||||
restPositions = new ObiNativeList<Vector3>();
|
||||
|
||||
if (restNormals == null)
|
||||
restNormals = new ObiNativeList<Vector3>();
|
||||
|
||||
if (restTangents == null)
|
||||
restTangents = new ObiNativeList<Vector4>();
|
||||
|
||||
if (restColors == null)
|
||||
restColors = new ObiNativeList<Color>();
|
||||
}
|
||||
|
||||
public void InitializeStaticData()
|
||||
{
|
||||
if (uv == null)
|
||||
uv = new ObiNativeList<Vector2>();
|
||||
|
||||
if (uv2 == null)
|
||||
uv2 = new ObiNativeList<Vector2>();
|
||||
|
||||
if (uv3 == null)
|
||||
uv3 = new ObiNativeList<Vector2>();
|
||||
|
||||
if (uv4 == null)
|
||||
uv4 = new ObiNativeList<Vector2>();
|
||||
|
||||
if (triangles == null)
|
||||
triangles = new ObiNativeList<int>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (meshData != null) meshData.Dispose();
|
||||
DisposeOfTempData();
|
||||
DisposeOfDynamicData();
|
||||
DisposeOfStaticData();
|
||||
}
|
||||
|
||||
public void DisposeOfTempData()
|
||||
{
|
||||
tempVertices = null;
|
||||
tempNormals = null;
|
||||
tempTangents = null;
|
||||
tempColors = null;
|
||||
|
||||
tempUV = null;
|
||||
tempUV2 = null;
|
||||
tempUV3 = null;
|
||||
tempUV4 = null;
|
||||
tempTriangles = null;
|
||||
}
|
||||
|
||||
public void DisposeOfDynamicData()
|
||||
{
|
||||
if (restPositions != null) restPositions.Dispose(); restPositions = null;
|
||||
if (restNormals != null) restNormals.Dispose(); restNormals = null;
|
||||
if (restTangents != null) restTangents.Dispose(); restTangents = null;
|
||||
if (restColors != null) restColors.Dispose(); restColors = null;
|
||||
}
|
||||
|
||||
public void DisposeOfStaticData()
|
||||
{
|
||||
if (uv != null) uv.Dispose(); uv = null;
|
||||
if (uv2 != null) uv2.Dispose(); uv2 = null;
|
||||
if (uv3 != null) uv3.Dispose(); uv3 = null;
|
||||
if (uv4 != null) uv4.Dispose(); uv4 = null;
|
||||
if (triangles != null) triangles.Dispose(); triangles = null;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (meshToIndex != null) meshToIndex.Clear();
|
||||
if (meshData != null) meshData.Clear();
|
||||
|
||||
if (restPositions != null) restPositions.Clear();
|
||||
if (restNormals != null) restNormals.Clear();
|
||||
if (restTangents != null) restTangents.Clear();
|
||||
if (restColors != null) restColors.Clear();
|
||||
if (uv != null) uv.Clear();
|
||||
if (uv2 != null) uv2.Clear();
|
||||
if (uv3 != null) uv3.Clear();
|
||||
if (uv4 != null) uv4.Clear();
|
||||
if (triangles != null) triangles.Clear();
|
||||
}
|
||||
|
||||
public int AddMesh(IMeshDataProvider meshProvider)
|
||||
{
|
||||
if (!meshToIndex.TryGetValue(meshProvider.sourceMesh, out int index))
|
||||
{
|
||||
index = meshData.count;
|
||||
meshToIndex[meshProvider.sourceMesh] = index;
|
||||
|
||||
meshProvider.GetVertices(tempVertices);
|
||||
meshProvider.GetNormals(tempNormals);
|
||||
meshProvider.GetTangents(tempTangents);
|
||||
meshProvider.GetColors(tempColors);
|
||||
|
||||
meshProvider.GetUVs(0, tempUV);
|
||||
meshProvider.GetUVs(1, tempUV2);
|
||||
meshProvider.GetUVs(2, tempUV3);
|
||||
meshProvider.GetUVs(3, tempUV4);
|
||||
|
||||
meshProvider.GetTriangles(tempTriangles);
|
||||
|
||||
if (tempTangents.Count == 0)
|
||||
tempTangents.AddRange(Enumerable.Repeat(Vector4.zero, tempVertices.Count));
|
||||
|
||||
if (tempColors.Count == 0)
|
||||
tempColors.AddRange(Enumerable.Repeat(Color.white, tempVertices.Count));
|
||||
|
||||
if (tempUV.Count == 0)
|
||||
tempUV.AddRange(Enumerable.Repeat(Vector2.zero, tempVertices.Count));
|
||||
|
||||
if (tempUV2.Count == 0)
|
||||
tempUV2.AddRange(Enumerable.Repeat(Vector2.zero, tempVertices.Count));
|
||||
|
||||
if (tempUV3.Count == 0)
|
||||
tempUV3.AddRange(Enumerable.Repeat(Vector2.zero, tempVertices.Count));
|
||||
|
||||
if (tempUV4.Count == 0)
|
||||
tempUV4.AddRange(Enumerable.Repeat(Vector2.zero, tempVertices.Count));
|
||||
|
||||
meshData.Add(new MeshData
|
||||
{
|
||||
firstVertex = restPositions.count,
|
||||
vertexCount = tempVertices.Count,
|
||||
|
||||
firstTriangle = triangles.count,
|
||||
triangleCount = tempTriangles.Count
|
||||
});
|
||||
|
||||
restPositions.AddRange(tempVertices);
|
||||
restNormals.AddRange(tempNormals);
|
||||
restTangents.AddRange(tempTangents);
|
||||
restColors.AddRange(tempColors);
|
||||
uv.AddRange(tempUV);
|
||||
uv2.AddRange(tempUV2);
|
||||
uv3.AddRange(tempUV3);
|
||||
uv4.AddRange(tempUV4);
|
||||
triangles.AddRange(tempTriangles);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
public void PrepareForCompute()
|
||||
{
|
||||
meshData.AsComputeBuffer<MeshData>();
|
||||
restPositions.AsComputeBuffer<Vector3>();
|
||||
restNormals.AsComputeBuffer<Vector3>();
|
||||
restTangents.AsComputeBuffer<Vector4>();
|
||||
restColors.AsComputeBuffer<Color>();
|
||||
}
|
||||
|
||||
public int GetVertexCount(int meshIndex)
|
||||
{
|
||||
return meshData[meshIndex].vertexCount;
|
||||
}
|
||||
|
||||
public int GetTriangleCount(int meshIndex)
|
||||
{
|
||||
return meshData[meshIndex].triangleCount;
|
||||
}
|
||||
|
||||
public NativeSlice<Vector3> GetVertices(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return restPositions.AsNativeArray<Vector3>().Slice(start,count);
|
||||
}
|
||||
|
||||
public NativeSlice<Vector3> GetNormals(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return restNormals.AsNativeArray<Vector3>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<Vector4> GetTangents(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return restTangents.AsNativeArray<Vector4>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<Color> GetColors(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return restColors.AsNativeArray<Color>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<Vector2> GetUV(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return uv.AsNativeArray<Vector2>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<Vector2> GetUV2(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return uv2.AsNativeArray<Vector2>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<Vector2> GetUV3(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return uv3.AsNativeArray<Vector2>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<Vector2> GetUV4(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstVertex;
|
||||
int count = meshData[meshIndex].vertexCount;
|
||||
return uv4.AsNativeArray<Vector2>().Slice(start, count);
|
||||
}
|
||||
|
||||
public NativeSlice<int> GetTriangles(int meshIndex)
|
||||
{
|
||||
int start = meshData[meshIndex].firstTriangle;
|
||||
int count = meshData[meshIndex].triangleCount;
|
||||
return triangles.AsNativeArray<int>().Slice(start, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51631a4146e8e4501adcbe8ff6f039c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,117 +0,0 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class SkeletonDataBatch
|
||||
{
|
||||
public struct SkeletonData
|
||||
{
|
||||
public int firstBone;
|
||||
public int boneCount;
|
||||
}
|
||||
|
||||
// per skinMap data:
|
||||
public ObiNativeList<SkeletonData> skeletonData;
|
||||
public ObiNativeList<Matrix4x4> world2Solver;
|
||||
|
||||
// bone data:
|
||||
public ObiNativeList<Vector3> bonePositions;
|
||||
public ObiNativeList<Quaternion> boneRotations;
|
||||
public ObiNativeList<Vector3> boneScales;
|
||||
|
||||
public int Count { get { return skeletonData.count; } }
|
||||
|
||||
public SkeletonDataBatch()
|
||||
{
|
||||
skeletonData = new ObiNativeList<SkeletonData>();
|
||||
world2Solver = new ObiNativeList<Matrix4x4>();
|
||||
|
||||
bonePositions = new ObiNativeList<Vector3>();
|
||||
boneRotations = new ObiNativeList<Quaternion>();
|
||||
boneScales = new ObiNativeList<Vector3>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
skeletonData.Dispose();
|
||||
world2Solver.Dispose();
|
||||
|
||||
bonePositions.Dispose();
|
||||
boneRotations.Dispose();
|
||||
boneScales.Dispose();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
skeletonData.Clear();
|
||||
world2Solver.Clear();
|
||||
|
||||
bonePositions.Clear();
|
||||
boneRotations.Clear();
|
||||
boneScales.Clear();
|
||||
}
|
||||
|
||||
public int AddSkeleton(Transform[] bones, Matrix4x4 worldToSolver)
|
||||
{
|
||||
var data = new SkeletonData
|
||||
{
|
||||
firstBone = bonePositions.count,
|
||||
};
|
||||
|
||||
foreach (var bone in bones)
|
||||
{
|
||||
if (bone != null)
|
||||
{
|
||||
bonePositions.Add(bone.position);
|
||||
boneRotations.Add(bone.rotation);
|
||||
boneScales.Add(bone.localScale);
|
||||
}
|
||||
}
|
||||
|
||||
data.boneCount = bonePositions.count;
|
||||
|
||||
skeletonData.Add(data);
|
||||
world2Solver.Add(worldToSolver);
|
||||
|
||||
return skeletonData.count - 1;
|
||||
}
|
||||
|
||||
public void PrepareForCompute()
|
||||
{
|
||||
skeletonData.SafeAsComputeBuffer<SkeletonData>();
|
||||
world2Solver.SafeAsComputeBuffer<Matrix4x4>();
|
||||
bonePositions.SafeAsComputeBuffer<Vector3>();
|
||||
boneRotations.SafeAsComputeBuffer<Quaternion>();
|
||||
boneScales.SafeAsComputeBuffer<Vector3>();
|
||||
}
|
||||
|
||||
public void SetBoneTransform(int index, int boneIndex, Transform transform)
|
||||
{
|
||||
if (transform != null)
|
||||
{
|
||||
var i = skeletonData[index].firstBone + boneIndex;
|
||||
bonePositions[i] = transform.position;
|
||||
boneScales[i] = transform.lossyScale;
|
||||
boneRotations[i] = transform.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateBoneTransformsCompute()
|
||||
{
|
||||
bonePositions.Upload();
|
||||
boneScales.Upload();
|
||||
boneRotations.Upload();
|
||||
}
|
||||
|
||||
public Matrix4x4 GetWorldToSolverTransform(int index)
|
||||
{
|
||||
return world2Solver[index];
|
||||
}
|
||||
|
||||
public void SetWorldToSolverTransform(int index, Matrix4x4 trfm)
|
||||
{
|
||||
world2Solver[index] = trfm;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b609b47dfb88424c9ae3e32c64bfaeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,10 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface ISurfaceChunkUser
|
||||
{
|
||||
uint usedChunkCount { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e544f8db79af4a6a91df85c5df0dee7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IActorRenderer
|
||||
{
|
||||
public ObiActor actor
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ObiActorRenderer<T> : IActorRenderer, ObiRenderer<T> where T : ObiActorRenderer<T>
|
||||
{
|
||||
public void EnableRenderer()
|
||||
{
|
||||
actor.OnBlueprintLoaded += ObiActorRenderer_OnBlueprintLoaded;
|
||||
actor.OnBlueprintUnloaded += ObiActorRenderer_OnBlueprintUnloaded;
|
||||
|
||||
if (actor.isLoaded)
|
||||
RegisterRenderer(actor.solver);
|
||||
}
|
||||
|
||||
public void DisableRenderer()
|
||||
{
|
||||
if (actor.isLoaded)
|
||||
UnregisterRenderer(actor.solver);
|
||||
|
||||
actor.OnBlueprintLoaded -= ObiActorRenderer_OnBlueprintLoaded;
|
||||
actor.OnBlueprintUnloaded -= ObiActorRenderer_OnBlueprintUnloaded;
|
||||
}
|
||||
|
||||
public void SetRendererDirty(Oni.RenderingSystemType type)
|
||||
{
|
||||
if (actor != null)
|
||||
actor.SetRenderingDirty(type);
|
||||
}
|
||||
|
||||
private void ObiActorRenderer_OnBlueprintLoaded(ObiActor act, ObiActorBlueprint blueprint)
|
||||
{
|
||||
RegisterRenderer(act.solver);
|
||||
}
|
||||
|
||||
protected void ObiActorRenderer_OnBlueprintUnloaded(ObiActor act, ObiActorBlueprint blueprint)
|
||||
{
|
||||
UnregisterRenderer(act.solver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f86d1462578d497182bb58c20b89d42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,166 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[AddComponentMenu("Physics/Obi/Obi Distance Field Renderer", 1003)]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiCollider))]
|
||||
public class ObiDistanceFieldRenderer : MonoBehaviour
|
||||
{
|
||||
public enum Axis
|
||||
{
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2,
|
||||
}
|
||||
|
||||
public Axis axis;
|
||||
[Range(0, 1)]
|
||||
public float slice = 0.25f;
|
||||
public float maxDistance = 0.5f;
|
||||
|
||||
private ObiCollider unityCollider;
|
||||
private Material material;
|
||||
private Mesh planeMesh;
|
||||
private Texture2D cutawayTexture;
|
||||
|
||||
private float sampleSize;
|
||||
private int sampleCount;
|
||||
|
||||
private Color boundsColor = new Color(1, 1, 1, 0.5f);
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
unityCollider = GetComponent<ObiCollider>();
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
material = GameObject.Instantiate(Resources.Load<Material>("ObiMaterials/DistanceFields/DistanceFieldRendering"));
|
||||
material.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
private void Cleanup()
|
||||
{
|
||||
GameObject.DestroyImmediate(cutawayTexture);
|
||||
GameObject.DestroyImmediate(planeMesh);
|
||||
GameObject.DestroyImmediate(material);
|
||||
}
|
||||
|
||||
private void ResizeTexture()
|
||||
{
|
||||
|
||||
if (cutawayTexture == null)
|
||||
{
|
||||
cutawayTexture = new Texture2D(sampleCount, sampleCount, TextureFormat.RHalf, false);
|
||||
cutawayTexture.wrapMode = TextureWrapMode.Clamp;
|
||||
cutawayTexture.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
else
|
||||
cutawayTexture.Reinitialize(sampleCount, sampleCount);
|
||||
}
|
||||
|
||||
private void CreatePlaneMesh(ObiDistanceField field)
|
||||
{
|
||||
|
||||
if (field != null && planeMesh == null)
|
||||
{
|
||||
|
||||
float uvBorder = (1 - field.FieldBounds.size[0] / (sampleSize * sampleCount)) * 0.5f;
|
||||
|
||||
planeMesh = new Mesh();
|
||||
|
||||
planeMesh.vertices = new Vector3[]{new Vector3(-0.5f,-0.5f,0),
|
||||
new Vector3(0.5f,-0.5f,0),
|
||||
new Vector3(-0.5f,0.5f,0),
|
||||
new Vector3(0.5f,0.5f,0)};
|
||||
|
||||
planeMesh.uv = new Vector2[]{new Vector2(uvBorder,uvBorder),
|
||||
new Vector2(1-uvBorder,uvBorder),
|
||||
new Vector2(uvBorder,1-uvBorder),
|
||||
new Vector2(1-uvBorder,1-uvBorder)};
|
||||
|
||||
planeMesh.normals = new Vector3[] { -Vector3.forward, -Vector3.forward, -Vector3.forward, -Vector3.forward };
|
||||
planeMesh.triangles = new int[] { 0, 2, 1, 2, 3, 1 };
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshCutawayTexture(ObiDistanceField field)
|
||||
{
|
||||
if (field == null)
|
||||
return;
|
||||
|
||||
Bounds b = field.FieldBounds;
|
||||
sampleSize = field.EffectiveSampleSize;
|
||||
sampleCount = (int)(b.size[0] / sampleSize) + 1;
|
||||
|
||||
CreatePlaneMesh(field);
|
||||
ResizeTexture();
|
||||
|
||||
float sweep = (sampleCount * slice) * sampleSize;
|
||||
Vector3 origin = b.center - b.extents;
|
||||
|
||||
for (int x = 0; x < sampleCount; ++x)
|
||||
for (int y = 0; y < sampleCount; ++y)
|
||||
{
|
||||
Vector3 offset = Vector3.zero;
|
||||
switch (axis)
|
||||
{
|
||||
case Axis.X: offset = new Vector3(sweep, y * sampleSize, x * sampleSize); break;
|
||||
case Axis.Y: offset = new Vector3(x * sampleSize, sweep, y * sampleSize); break;
|
||||
case Axis.Z: offset = new Vector3(x * sampleSize, y * sampleSize, sweep); break;
|
||||
}
|
||||
|
||||
float distance = ASDF.Sample(field.nodes, origin + offset);
|
||||
|
||||
float value = ObiUtils.Remap(distance, -maxDistance, maxDistance, 0, 1);
|
||||
|
||||
cutawayTexture.SetPixel(x, y, new Color(value, 0, 0));
|
||||
}
|
||||
cutawayTexture.Apply();
|
||||
}
|
||||
|
||||
private void DrawCutawayPlane(ObiDistanceField field, Matrix4x4 matrix)
|
||||
{
|
||||
|
||||
if (field == null)
|
||||
return;
|
||||
|
||||
RefreshCutawayTexture(field);
|
||||
|
||||
material.mainTexture = cutawayTexture;
|
||||
material.SetPass(0);
|
||||
|
||||
Quaternion rotation = Quaternion.identity;
|
||||
Vector3 offset = Vector3.zero;
|
||||
offset[(int)axis] = field.FieldBounds.size[0];
|
||||
|
||||
if (axis == Axis.Y)
|
||||
rotation = Quaternion.Euler(90, 0, 0);
|
||||
else if (axis == Axis.X)
|
||||
rotation = Quaternion.Euler(0, -90, 0);
|
||||
|
||||
Matrix4x4 sc = Matrix4x4.TRS(field.FieldBounds.center + offset * (slice - 0.5f), rotation, Vector3.one * field.FieldBounds.size[0]);
|
||||
Graphics.DrawMeshNow(planeMesh, matrix * sc);
|
||||
|
||||
}
|
||||
|
||||
public void OnDrawGizmos()
|
||||
{
|
||||
if (unityCollider != null && unityCollider.distanceField != null && unityCollider.distanceField.Initialized && material != null)
|
||||
{
|
||||
DrawCutawayPlane(unityCollider.distanceField, transform.localToWorldMatrix);
|
||||
Gizmos.color = boundsColor;
|
||||
Gizmos.DrawWireCube(unityCollider.distanceField.FieldBounds.center, unityCollider.distanceField.FieldBounds.size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 382f1f06ad1a84a9f8fb3a60b50dd9b7
|
||||
timeCreated: 1516041863
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 41cb9d55de5b24458b45e5465606249a, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,96 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Profiling;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DiffuseParticleVertex
|
||||
{
|
||||
public Vector4 pos;
|
||||
public Vector3 offset;
|
||||
public Vector4 color;
|
||||
public Vector4 velocity;
|
||||
public Vector4 attributes;
|
||||
}
|
||||
|
||||
public class ObiFoamRenderSystem : RenderSystem<ObiFoamGenerator>
|
||||
{
|
||||
public Oni.RenderingSystemType typeEnum { get => Oni.RenderingSystemType.FoamParticles; }
|
||||
|
||||
public RendererSet<ObiFoamGenerator> renderers { get; } = new RendererSet<ObiFoamGenerator>();
|
||||
public bool isSetup => true;
|
||||
|
||||
protected VertexAttributeDescriptor[] layout =
|
||||
{
|
||||
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 4),
|
||||
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
|
||||
new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.Float32, 4),
|
||||
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 4), // velocity
|
||||
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float32, 4), // attributes
|
||||
};
|
||||
|
||||
static protected ProfilerMarker m_SetupRenderMarker = new ProfilerMarker("SetupSurfaceMeshing");
|
||||
static protected ProfilerMarker m_RenderMarker = new ProfilerMarker("SurfaceMeshing");
|
||||
|
||||
protected HashSet<Camera> cameras = new HashSet<Camera>();
|
||||
protected MaterialPropertyBlock matProps;
|
||||
|
||||
protected ObiSolver m_Solver;
|
||||
public ProceduralRenderBatch<DiffuseParticleVertex> renderBatch;
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
System.Action<ScriptableRenderContext, Camera> renderCallback;
|
||||
#endif
|
||||
|
||||
// must be done before fluid meshing.
|
||||
public uint tier
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public ObiFoamRenderSystem(ObiSolver solver)
|
||||
{
|
||||
m_Solver = solver;
|
||||
matProps = new MaterialPropertyBlock();
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
renderCallback = new System.Action<ScriptableRenderContext, Camera>((cntxt, cam) => { RenderFromCamera(cam); });
|
||||
RenderPipelineManager.beginCameraRendering += renderCallback;
|
||||
#endif
|
||||
Camera.onPreCull += RenderFromCamera;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
RenderPipelineManager.beginCameraRendering -= renderCallback;
|
||||
#endif
|
||||
Camera.onPreCull -= RenderFromCamera;
|
||||
|
||||
renderBatch.Dispose();
|
||||
cameras.Clear();
|
||||
}
|
||||
|
||||
public void RenderFromCamera(Camera camera)
|
||||
{
|
||||
cameras.Add(camera);
|
||||
}
|
||||
|
||||
public virtual void Setup()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Step()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Render()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96d883432ef854a8598e264c73232bdc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,151 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Rendering;
|
||||
using Unity.Collections;
|
||||
using Unity.Profiling;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public abstract class ObiInstancedParticleRenderSystem : RenderSystem<ObiInstancedParticleRenderer>
|
||||
{
|
||||
public Oni.RenderingSystemType typeEnum { get => Oni.RenderingSystemType.InstancedParticles; }
|
||||
|
||||
public RendererSet<ObiInstancedParticleRenderer> renderers { get; } = new RendererSet<ObiInstancedParticleRenderer>();
|
||||
public bool isSetup => activeParticles != null;
|
||||
|
||||
|
||||
static protected ProfilerMarker m_SetupRenderMarker = new ProfilerMarker("SetupParticleRendering");
|
||||
static protected ProfilerMarker m_RenderMarker = new ProfilerMarker("ParticleRendering");
|
||||
|
||||
protected ObiSolver m_Solver;
|
||||
|
||||
protected List<InstancedRenderBatch> batchList = new List<InstancedRenderBatch>();
|
||||
|
||||
protected ObiNativeList<int> activeParticles;
|
||||
protected ObiNativeList<int> rendererIndex;
|
||||
protected ObiNativeList<ParticleRendererData> rendererData;
|
||||
|
||||
protected ObiNativeList<Matrix4x4> instanceTransforms;
|
||||
protected ObiNativeList<Matrix4x4> invInstanceTransforms;
|
||||
protected ObiNativeList<Vector4> instanceColors;
|
||||
|
||||
public ObiInstancedParticleRenderSystem(ObiSolver solver)
|
||||
{
|
||||
m_Solver = solver;
|
||||
|
||||
activeParticles = new ObiNativeList<int>();
|
||||
rendererIndex = new ObiNativeList<int>();
|
||||
rendererData = new ObiNativeList<ParticleRendererData>();
|
||||
instanceTransforms = new ObiNativeList<Matrix4x4>();
|
||||
invInstanceTransforms = new ObiNativeList<Matrix4x4>();
|
||||
instanceColors = new ObiNativeList<Vector4>();
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
batchList[i].Dispose();
|
||||
batchList.Clear();
|
||||
|
||||
if (activeParticles != null)
|
||||
activeParticles.Dispose();
|
||||
if (rendererData != null)
|
||||
rendererData.Dispose();
|
||||
if (rendererIndex != null)
|
||||
rendererIndex.Dispose();
|
||||
if (instanceTransforms != null)
|
||||
instanceTransforms.Dispose();
|
||||
if (invInstanceTransforms != null)
|
||||
invInstanceTransforms.Dispose();
|
||||
if (instanceColors != null)
|
||||
instanceColors.Dispose();
|
||||
}
|
||||
|
||||
protected virtual void Clear()
|
||||
{
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
batchList[i].Dispose();
|
||||
batchList.Clear();
|
||||
|
||||
activeParticles.Clear();
|
||||
rendererData.Clear();
|
||||
rendererIndex.Clear();
|
||||
instanceTransforms.Clear();
|
||||
invInstanceTransforms.Clear();
|
||||
instanceColors.Clear();
|
||||
}
|
||||
|
||||
protected virtual void CreateBatches()
|
||||
{
|
||||
// generate batches:
|
||||
for (int i = 0; i < renderers.Count; ++i)
|
||||
{
|
||||
renderers[i].renderParameters.layer = renderers[i].gameObject.layer;
|
||||
|
||||
// Create multiple batches of at most maxInstancesPerBatch particles each:
|
||||
int instanceCount = 0;
|
||||
while (instanceCount < renderers[i].actor.particleCount)
|
||||
{
|
||||
var batch = new InstancedRenderBatch(i, renderers[i].mesh, renderers[i].material, renderers[i].renderParameters);
|
||||
batch.firstInstance = instanceCount;
|
||||
batch.instanceCount = Mathf.Min(renderers[i].actor.particleCount - instanceCount, Constants.maxInstancesPerBatch);
|
||||
instanceCount += batch.instanceCount;
|
||||
batchList.Add(batch);
|
||||
}
|
||||
}
|
||||
|
||||
// sort batches:
|
||||
batchList.Sort();
|
||||
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
{
|
||||
var batch = batchList[i];
|
||||
var renderer = renderers[batch.firstRenderer];
|
||||
int particlesSoFar = activeParticles.count;
|
||||
|
||||
// add active particles here, respecting batch order:
|
||||
activeParticles.AddRange(renderer.actor.solverIndices, batch.firstInstance, batch.instanceCount);
|
||||
rendererIndex.AddReplicate(i, batch.instanceCount);
|
||||
rendererData.Add(new ParticleRendererData(renderer.instanceColor, renderer.instanceScale));
|
||||
|
||||
batch.firstInstance = particlesSoFar;
|
||||
}
|
||||
|
||||
instanceTransforms.ResizeUninitialized(activeParticles.count);
|
||||
invInstanceTransforms.ResizeUninitialized(activeParticles.count);
|
||||
instanceColors.ResizeUninitialized(activeParticles.count);
|
||||
}
|
||||
|
||||
protected virtual void CloseBatches()
|
||||
{
|
||||
// Initialize each batch:
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
batchList[i].Initialize();
|
||||
}
|
||||
|
||||
public virtual void Setup()
|
||||
{
|
||||
using (m_SetupRenderMarker.Auto())
|
||||
{
|
||||
Clear();
|
||||
|
||||
CreateBatches();
|
||||
|
||||
ObiUtils.MergeBatches(batchList);
|
||||
|
||||
CloseBatches();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Step()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Render()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd33018010abc46be9ac6cc091142ccf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,63 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Profiling;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[AddComponentMenu("Physics/Obi/Obi Instanced Particle Renderer", 1001)]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiActor))]
|
||||
public class ObiInstancedParticleRenderer : MonoBehaviour, ObiActorRenderer<ObiInstancedParticleRenderer>
|
||||
{
|
||||
public Mesh mesh;
|
||||
public Material material;
|
||||
public RenderBatchParams renderParameters = new RenderBatchParams(true);
|
||||
public Color instanceColor = Color.white;
|
||||
public float instanceScale = 1;
|
||||
|
||||
public ObiActor actor { get; private set; }
|
||||
|
||||
void Awake()
|
||||
{
|
||||
actor = GetComponent<ObiActor>();
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
((ObiActorRenderer<ObiInstancedParticleRenderer>)this).EnableRenderer();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
((ObiActorRenderer<ObiInstancedParticleRenderer>)this).DisableRenderer();
|
||||
}
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
((ObiActorRenderer<ObiInstancedParticleRenderer>)this).SetRendererDirty(Oni.RenderingSystemType.InstancedParticles);
|
||||
}
|
||||
|
||||
RenderSystem<ObiInstancedParticleRenderer> ObiRenderer<ObiInstancedParticleRenderer>.CreateRenderSystem(ObiSolver solver)
|
||||
{
|
||||
switch (solver.backendType)
|
||||
{
|
||||
|
||||
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
case ObiSolver.BackendType.Burst: return new BurstInstancedParticleRenderSystem(solver);
|
||||
#endif
|
||||
case ObiSolver.BackendType.Compute:
|
||||
default:
|
||||
|
||||
if (SystemInfo.supportsComputeShaders)
|
||||
return new ComputeInstancedParticleRenderSystem(solver);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 356b834afda224f73a26e39580b330f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
- material: {fileID: 2100000, guid: 2b7dfa8ebb76247318ce5b7df4b97484, type: 2}
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: f424a87c9f03240c2870a664731ac9aa, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,145 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Rendering;
|
||||
using Unity.Profiling;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ParticleVertex
|
||||
{
|
||||
public Vector4 pos;
|
||||
public Vector3 offset;
|
||||
public Vector4 color;
|
||||
public Vector4 b1;
|
||||
public Vector4 b2;
|
||||
public Vector4 b3;
|
||||
}
|
||||
|
||||
public abstract class ObiParticleRenderSystem : RenderSystem<ObiParticleRenderer>
|
||||
{
|
||||
public Oni.RenderingSystemType typeEnum { get => Oni.RenderingSystemType.Particles; }
|
||||
|
||||
public RendererSet<ObiParticleRenderer> renderers { get; } = new RendererSet<ObiParticleRenderer>();
|
||||
public bool isSetup => activeParticles != null;
|
||||
|
||||
protected VertexAttributeDescriptor[] layout =
|
||||
{
|
||||
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 4),
|
||||
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
|
||||
new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.Float32, 4),
|
||||
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 4),
|
||||
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float32, 4),
|
||||
new VertexAttributeDescriptor(VertexAttribute.TexCoord2, VertexAttributeFormat.Float32, 4)
|
||||
};
|
||||
|
||||
static protected ProfilerMarker m_SetupRenderMarker = new ProfilerMarker("SetupParticleRendering");
|
||||
static protected ProfilerMarker m_RenderMarker = new ProfilerMarker("ParticleRendering");
|
||||
|
||||
protected ObiSolver m_Solver;
|
||||
|
||||
protected List<ProceduralRenderBatch<ParticleVertex>> batchList = new List<ProceduralRenderBatch<ParticleVertex>>();
|
||||
|
||||
protected ObiNativeList<int> activeParticles;
|
||||
protected ObiNativeList<int> rendererIndex;
|
||||
protected ObiNativeList<ParticleRendererData> rendererData;
|
||||
|
||||
public ObiParticleRenderSystem(ObiSolver solver)
|
||||
{
|
||||
m_Solver = solver;
|
||||
|
||||
activeParticles = new ObiNativeList<int>();
|
||||
rendererIndex = new ObiNativeList<int>();
|
||||
rendererData = new ObiNativeList<ParticleRendererData>();
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
batchList[i].Dispose();
|
||||
batchList.Clear();
|
||||
|
||||
if (activeParticles != null)
|
||||
activeParticles.Dispose();
|
||||
if (rendererData != null)
|
||||
rendererData.Dispose();
|
||||
if (rendererIndex != null)
|
||||
rendererIndex.Dispose();
|
||||
}
|
||||
|
||||
protected virtual void Clear()
|
||||
{
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
batchList[i].Dispose();
|
||||
batchList.Clear();
|
||||
|
||||
activeParticles.Clear();
|
||||
rendererData.Clear();
|
||||
rendererIndex.Clear();
|
||||
}
|
||||
|
||||
protected virtual void CreateBatches()
|
||||
{
|
||||
// generate batches:
|
||||
for (int i = 0; i < renderers.Count; ++i)
|
||||
{
|
||||
renderers[i].renderParameters.layer = renderers[i].gameObject.layer;
|
||||
batchList.Add(new ProceduralRenderBatch<ParticleVertex>(i, renderers[i].material, renderers[i].renderParameters));
|
||||
}
|
||||
|
||||
// sort batches:
|
||||
batchList.Sort();
|
||||
|
||||
int particleCount = 0;
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
{
|
||||
var batch = batchList[i];
|
||||
var renderer = renderers[batch.firstRenderer];
|
||||
int actorParticleCount = renderer.actor.particleCount;
|
||||
|
||||
batch.vertexCount += actorParticleCount * 4;
|
||||
batch.triangleCount += actorParticleCount * 2;
|
||||
|
||||
batch.firstParticle = particleCount;
|
||||
particleCount += actorParticleCount;
|
||||
|
||||
// add particles here, respecting batch order:
|
||||
activeParticles.AddRange(renderer.actor.solverIndices, actorParticleCount);
|
||||
rendererData.Add(new ParticleRendererData(renderer.particleColor, renderer.radiusScale));
|
||||
rendererIndex.AddReplicate(i, actorParticleCount);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CloseBatches()
|
||||
{
|
||||
// Initialize each batch:
|
||||
for (int i = 0; i < batchList.Count; ++i)
|
||||
batchList[i].Initialize(layout);
|
||||
}
|
||||
|
||||
public virtual void Setup()
|
||||
{
|
||||
using (m_SetupRenderMarker.Auto())
|
||||
{
|
||||
Clear();
|
||||
|
||||
CreateBatches();
|
||||
|
||||
ObiUtils.MergeBatches(batchList);
|
||||
|
||||
CloseBatches();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Step()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Render()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e36441d408a548d29fbc80dfa4fffc1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,78 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IParticleRenderer
|
||||
{
|
||||
public ObiActor actor { get; }
|
||||
public Color particleColor { get; }
|
||||
public float radiusScale { get; }
|
||||
}
|
||||
|
||||
public struct ParticleRendererData
|
||||
{
|
||||
public Color color;
|
||||
public float radiusScale;
|
||||
|
||||
public ParticleRendererData(Color color, float radiusScale)
|
||||
{
|
||||
this.color = color;
|
||||
this.radiusScale = radiusScale;
|
||||
}
|
||||
}
|
||||
|
||||
[AddComponentMenu("Physics/Obi/Obi Particle Renderer", 1000)]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiActor))]
|
||||
public class ObiParticleRenderer : MonoBehaviour, IParticleRenderer, ObiActorRenderer<ObiParticleRenderer>
|
||||
{
|
||||
public Material material;
|
||||
public RenderBatchParams renderParameters = new RenderBatchParams(true);
|
||||
|
||||
[field: SerializeField]
|
||||
public Color particleColor { get; set; } = Color.white;
|
||||
|
||||
[field: SerializeField]
|
||||
public float radiusScale { get; set; } = 1;
|
||||
|
||||
public ObiActor actor { get; private set; }
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
actor = GetComponent<ObiActor>();
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
((ObiActorRenderer<ObiParticleRenderer>)this).EnableRenderer();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
((ObiActorRenderer<ObiParticleRenderer>)this).DisableRenderer();
|
||||
}
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
((ObiActorRenderer<ObiParticleRenderer>)this).SetRendererDirty(Oni.RenderingSystemType.Particles);
|
||||
}
|
||||
|
||||
RenderSystem<ObiParticleRenderer> ObiRenderer<ObiParticleRenderer>.CreateRenderSystem(ObiSolver solver)
|
||||
{
|
||||
switch (solver.backendType)
|
||||
{
|
||||
|
||||
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
case ObiSolver.BackendType.Burst: return new BurstParticleRenderSystem(solver);
|
||||
#endif
|
||||
case ObiSolver.BackendType.Compute:
|
||||
default:
|
||||
|
||||
if (SystemInfo.supportsComputeShaders)
|
||||
return new ComputeParticleRenderSystem(solver);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8b45ebbf86be4df6b0e6cd933812af2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- material: {fileID: 2100000, guid: fb88690dea2394644849cde5abd037f9, type: 2}
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: f424a87c9f03240c2870a664731ac9aa, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,65 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface ObiRenderer<T> where T : ObiRenderer<T>
|
||||
{
|
||||
protected RenderSystem<T> CreateRenderSystem(ObiSolver solver);
|
||||
|
||||
public bool ValidateRenderer() { return true; }
|
||||
public void CleanupRenderer() { }
|
||||
|
||||
protected bool UnregisterRenderer(ObiSolver solver)
|
||||
{
|
||||
CleanupRenderer();
|
||||
|
||||
// try to get a render system from the solver:
|
||||
var system = solver.GetRenderSystem<T>();
|
||||
|
||||
// if there's an existing render system for this kind of renderer,
|
||||
// unregister from it.
|
||||
if (system != null && system.RemoveRenderer((T)this))
|
||||
{
|
||||
// if the render system is empty, destroy it:
|
||||
if (system.isEmpty)
|
||||
{
|
||||
solver.UnregisterRenderSystem(system);
|
||||
system.Dispose();
|
||||
}
|
||||
|
||||
solver.dirtyRendering |= (int)system.typeEnum;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected bool RegisterRenderer(ObiSolver solver)
|
||||
{
|
||||
if (ValidateRenderer())
|
||||
{
|
||||
// try to get a render system from the solver:
|
||||
var system = solver.GetRenderSystem<T>();
|
||||
|
||||
// if no appropiate system has been created yet, create it:
|
||||
if (system == null)
|
||||
{
|
||||
system = CreateRenderSystem(solver) as RenderSystem<T>;
|
||||
solver.RegisterRenderSystem(system);
|
||||
}
|
||||
|
||||
// register in the renderer:
|
||||
if (system != null)
|
||||
{
|
||||
if (system.AddRenderer((T)this))
|
||||
{
|
||||
solver.dirtyRendering |= (int)system.typeEnum;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d4f237ec9acf4df0a30d5a0139e0f36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,164 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Profiling;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ParticleImpostorRendering
|
||||
{
|
||||
static ProfilerMarker m_ParticlesToMeshPerfMarker = new ProfilerMarker("ParticlesToMesh");
|
||||
|
||||
private List<Mesh> meshes = new List<Mesh>();
|
||||
|
||||
private List<Vector3> vertices = new List<Vector3>(4000);
|
||||
private List<Vector3> normals = new List<Vector3>(4000);
|
||||
private List<Color> colors = new List<Color>(4000);
|
||||
private List<int> triangles = new List<int>(6000);
|
||||
|
||||
private List<Vector4> anisotropy1 = new List<Vector4>(4000);
|
||||
private List<Vector4> anisotropy2 = new List<Vector4>(4000);
|
||||
private List<Vector4> anisotropy3 = new List<Vector4>(4000);
|
||||
|
||||
int particlesPerDrawcall = 0;
|
||||
int drawcallCount;
|
||||
|
||||
private Vector3 particleOffset0 = new Vector3(1, 1, 0);
|
||||
private Vector3 particleOffset1 = new Vector3(-1, 1, 0);
|
||||
private Vector3 particleOffset2 = new Vector3(-1, -1, 0);
|
||||
private Vector3 particleOffset3 = new Vector3(1, -1, 0);
|
||||
|
||||
public IEnumerable<Mesh> Meshes
|
||||
{
|
||||
get { return meshes.AsReadOnly(); }
|
||||
}
|
||||
|
||||
private void Apply(Mesh mesh)
|
||||
{
|
||||
mesh.Clear();
|
||||
mesh.SetVertices(vertices);
|
||||
mesh.SetNormals(normals);
|
||||
mesh.SetColors(colors);
|
||||
mesh.SetUVs(0, anisotropy1);
|
||||
mesh.SetUVs(1, anisotropy2);
|
||||
mesh.SetUVs(2, anisotropy3);
|
||||
mesh.SetTriangles(triangles, 0, true);
|
||||
}
|
||||
|
||||
public void ClearMeshes()
|
||||
{
|
||||
foreach (Mesh mesh in meshes)
|
||||
GameObject.DestroyImmediate(mesh);
|
||||
meshes.Clear();
|
||||
}
|
||||
|
||||
public void UpdateMeshes(IObiParticleCollection collection, bool[] visible = null, Color[] tint = null)
|
||||
{
|
||||
using (m_ParticlesToMeshPerfMarker.Auto())
|
||||
{
|
||||
|
||||
// figure out the size of our drawcall arrays:
|
||||
particlesPerDrawcall = Constants.maxVertsPerMesh / 4;
|
||||
drawcallCount = collection.activeParticleCount / particlesPerDrawcall + 1;
|
||||
particlesPerDrawcall = Mathf.Min(particlesPerDrawcall, collection.activeParticleCount);
|
||||
|
||||
// If the amount of meshes we need to draw the particles has changed:
|
||||
if (drawcallCount != meshes.Count)
|
||||
{
|
||||
|
||||
// Re-generate meshes:
|
||||
ClearMeshes();
|
||||
for (int i = 0; i < drawcallCount; i++)
|
||||
{
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.name = "Particle impostors";
|
||||
mesh.hideFlags = HideFlags.HideAndDontSave;
|
||||
meshes.Add(mesh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vector3 position;
|
||||
Vector4 basis1 = new Vector4(1, 0, 0, 0);
|
||||
Vector4 basis2 = new Vector4(0, 1, 0, 0);
|
||||
Vector4 basis3 = new Vector4(0, 0, 1, 0);
|
||||
Color color;
|
||||
|
||||
int visibleLength = visible != null ? visible.Length : 0;
|
||||
int tintLength = tint != null ? tint.Length : 0;
|
||||
|
||||
//Convert particle data to mesh geometry:
|
||||
for (int i = 0; i < drawcallCount; i++)
|
||||
{
|
||||
|
||||
// Clear all arrays
|
||||
vertices.Clear();
|
||||
normals.Clear();
|
||||
colors.Clear();
|
||||
triangles.Clear();
|
||||
anisotropy1.Clear();
|
||||
anisotropy2.Clear();
|
||||
anisotropy3.Clear();
|
||||
|
||||
int index = 0;
|
||||
int limit = Mathf.Min((i + 1) * particlesPerDrawcall, collection.activeParticleCount);
|
||||
|
||||
for (int j = i * particlesPerDrawcall; j < limit; ++j)
|
||||
{
|
||||
if (j < visibleLength && !visible[j])
|
||||
continue;
|
||||
|
||||
int runtimeIndex = collection.GetParticleRuntimeIndex(j);
|
||||
position = collection.GetParticlePosition(runtimeIndex);
|
||||
collection.GetParticleAnisotropy(runtimeIndex, ref basis1, ref basis2, ref basis3);
|
||||
color = collection.GetParticleColor(runtimeIndex);
|
||||
|
||||
if (j < tintLength)
|
||||
color *= tint[j];
|
||||
|
||||
vertices.Add(position);
|
||||
vertices.Add(position);
|
||||
vertices.Add(position);
|
||||
vertices.Add(position);
|
||||
|
||||
normals.Add(particleOffset0);
|
||||
normals.Add(particleOffset1);
|
||||
normals.Add(particleOffset2);
|
||||
normals.Add(particleOffset3);
|
||||
|
||||
colors.Add(color);
|
||||
colors.Add(color);
|
||||
colors.Add(color);
|
||||
colors.Add(color);
|
||||
|
||||
anisotropy1.Add(basis1);
|
||||
anisotropy1.Add(basis1);
|
||||
anisotropy1.Add(basis1);
|
||||
anisotropy1.Add(basis1);
|
||||
|
||||
anisotropy2.Add(basis2);
|
||||
anisotropy2.Add(basis2);
|
||||
anisotropy2.Add(basis2);
|
||||
anisotropy2.Add(basis2);
|
||||
|
||||
anisotropy3.Add(basis3);
|
||||
anisotropy3.Add(basis3);
|
||||
anisotropy3.Add(basis3);
|
||||
anisotropy3.Add(basis3);
|
||||
|
||||
triangles.Add(index + 2);
|
||||
triangles.Add(index + 1);
|
||||
triangles.Add(index);
|
||||
triangles.Add(index + 3);
|
||||
triangles.Add(index + 2);
|
||||
triangles.Add(index);
|
||||
|
||||
index += 4;
|
||||
}
|
||||
|
||||
Apply(meshes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf17f48345c0f42a9a419ec65398dcd8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f9c5efc94e964016b39c7778b3af164
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,368 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DynamicBatchVertex
|
||||
{
|
||||
public Vector3 pos;
|
||||
public Vector3 normal;
|
||||
public Vector4 tangent;
|
||||
public Vector4 color;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct StaticBatchVertex
|
||||
{
|
||||
public Vector2 uv;
|
||||
public Vector2 uv2;
|
||||
public Vector2 uv3;
|
||||
public Vector2 uv4;
|
||||
}
|
||||
|
||||
public class DynamicRenderBatch<T> : IRenderBatch where T : IMeshDataProvider, IActorRenderer
|
||||
{
|
||||
private VertexAttributeDescriptor[] vertexLayout;
|
||||
|
||||
private RenderBatchParams renderBatchParams;
|
||||
public RenderParams renderParams { get; private set; }
|
||||
|
||||
public Material[] materials;
|
||||
public Mesh mesh;
|
||||
|
||||
public int firstRenderer;
|
||||
public int rendererCount;
|
||||
|
||||
public ObiNativeList<int> vertexToRenderer; // for each vertex in the batch, index of its renderer
|
||||
public ObiNativeList<int> particleToRenderer; // for each particle in the batch, index of its renderer
|
||||
|
||||
public ObiNativeList<int> particleIndices; // solver indices for all renderers in the batch
|
||||
|
||||
public ObiNativeList<DynamicBatchVertex> dynamicVertexData;
|
||||
public ObiNativeList<StaticBatchVertex> staticVertexData;
|
||||
public ObiNativeList<int> triangles;
|
||||
|
||||
public GraphicsBuffer gpuVertexBuffer;
|
||||
|
||||
public int vertexCount;
|
||||
public int triangleCount => triangles.count / 3;
|
||||
public int particleCount => particleIndices.count;
|
||||
|
||||
public DynamicRenderBatch(int rendererIndex, int vertexCount, Material[] materials, RenderBatchParams param)
|
||||
{
|
||||
this.renderBatchParams = param;
|
||||
this.materials = materials;
|
||||
this.vertexCount = vertexCount;
|
||||
|
||||
this.firstRenderer = rendererIndex;
|
||||
this.rendererCount = 1;
|
||||
}
|
||||
|
||||
public void Initialize(List<T> renderers,
|
||||
MeshDataBatch meshData,
|
||||
ObiNativeList<int> meshIndices,
|
||||
VertexAttributeDescriptor[] layout,
|
||||
bool gpu = false)
|
||||
{
|
||||
renderParams = renderBatchParams.ToRenderParams();
|
||||
vertexLayout = layout;
|
||||
|
||||
mesh = new Mesh();
|
||||
|
||||
vertexToRenderer = new ObiNativeList<int>();
|
||||
particleToRenderer = new ObiNativeList<int>();
|
||||
particleIndices = new ObiNativeList<int>();
|
||||
|
||||
dynamicVertexData = new ObiNativeList<DynamicBatchVertex>();
|
||||
staticVertexData = new ObiNativeList<StaticBatchVertex>();
|
||||
triangles = new ObiNativeList<int>();
|
||||
|
||||
// there will be exactly one submesh per material in the output batch.
|
||||
// so we iterate trough materials, and for each one, build a submesh by merging the
|
||||
// renderer's submeshes. If a renderer has less submeshes than materials, reuse the last one.
|
||||
|
||||
SubMeshDescriptor[] descriptors = new SubMeshDescriptor[materials.Length];
|
||||
|
||||
for (int m = 0; m < materials.Length; ++m)
|
||||
{
|
||||
int vertexOffset = 0;
|
||||
var desc = new SubMeshDescriptor();
|
||||
desc.indexStart = triangles.count;
|
||||
|
||||
for (int i = firstRenderer; i < firstRenderer + rendererCount; ++i)
|
||||
{
|
||||
var renderer = renderers[i];
|
||||
int meshIndex = meshIndices[i];
|
||||
int submeshIndex = Mathf.Min(m, renderer.sourceMesh.subMeshCount - 1);
|
||||
var submeshInfo = renderer.sourceMesh.GetSubMesh(submeshIndex);
|
||||
|
||||
var meshTriangles = meshData.GetTriangles(meshIndex);
|
||||
for (int k = 0; k < renderer.meshInstances; ++k)
|
||||
{
|
||||
// append submesh triangles:
|
||||
for (int t = submeshInfo.indexStart; t < submeshInfo.indexStart + submeshInfo.indexCount; ++t)
|
||||
triangles.Add(vertexOffset + meshTriangles[t]);
|
||||
|
||||
vertexOffset += meshData.GetVertexCount(meshIndex);
|
||||
}
|
||||
}
|
||||
|
||||
desc.indexCount = triangles.count - desc.indexStart;
|
||||
descriptors[m] = desc;
|
||||
}
|
||||
|
||||
// vertices:
|
||||
for (int i = firstRenderer; i < firstRenderer + rendererCount; ++i)
|
||||
{
|
||||
var renderer = renderers[i];
|
||||
int meshIndex = meshIndices[i];
|
||||
|
||||
int vCount = meshData.GetVertexCount(meshIndex);
|
||||
|
||||
for (int k = 0; k < renderer.meshInstances; ++k)
|
||||
{
|
||||
vertexToRenderer.AddReplicate(i, vCount);
|
||||
particleToRenderer.AddReplicate(i, renderer.actor.solverIndices.count);
|
||||
particleIndices.AddRange(renderer.actor.solverIndices);
|
||||
|
||||
var verts = meshData.GetVertices(meshIndex);
|
||||
var norms = meshData.GetNormals(meshIndex);
|
||||
var tan = meshData.GetTangents(meshIndex);
|
||||
var col = meshData.GetColors(meshIndex);
|
||||
|
||||
var uv = meshData.GetUV(meshIndex);
|
||||
var uv2 = meshData.GetUV2(meshIndex);
|
||||
var uv3 = meshData.GetUV3(meshIndex);
|
||||
var uv4 = meshData.GetUV4(meshIndex);
|
||||
|
||||
for (int j = 0; j < vCount; ++j)
|
||||
{
|
||||
dynamicVertexData.Add(new DynamicBatchVertex
|
||||
{
|
||||
pos = verts[j],
|
||||
normal = norms[j],
|
||||
tangent = tan[j],
|
||||
color = j < col.Length ? (Vector4)col[j] : Vector4.one
|
||||
});
|
||||
|
||||
staticVertexData.Add(new StaticBatchVertex
|
||||
{
|
||||
uv = j < uv.Length ? uv[j] : Vector2.zero,
|
||||
uv2 = j < uv2.Length ? uv2[j] : Vector2.zero,
|
||||
uv3 = j < uv3.Length ? uv3[j] : Vector2.zero,
|
||||
uv4 = j < uv4.Length ? uv4[j] : Vector2.zero,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup combined mesh:
|
||||
mesh.SetVertexBufferParams(vertexCount, layout);
|
||||
mesh.SetIndexBufferParams(triangles.count, IndexFormat.UInt32);
|
||||
|
||||
mesh.SetVertexBufferData(dynamicVertexData.AsNativeArray<DynamicBatchVertex>(), 0, 0, dynamicVertexData.count, 0, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
mesh.SetVertexBufferData(staticVertexData.AsNativeArray<StaticBatchVertex>(), 0, 0, staticVertexData.count, 1, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
mesh.SetIndexBufferData(triangles.AsNativeArray<int>(), 0, 0, triangles.count, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
// set submeshes:
|
||||
mesh.subMeshCount = materials.Length;
|
||||
for (int m = 0; m < materials.Length; ++m)
|
||||
mesh.SetSubMesh(m, descriptors[m], MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
if (gpu)
|
||||
{
|
||||
dynamicVertexData.Dispose();
|
||||
|
||||
mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
|
||||
|
||||
// meshes with no vertices will have no vertex buffer, and Unity will throw an exception.
|
||||
try
|
||||
{
|
||||
if (mesh.vertexCount > 0)
|
||||
{
|
||||
gpuVertexBuffer ??= mesh.GetVertexBuffer(0);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
particleIndices.AsComputeBuffer<int>();
|
||||
vertexToRenderer.AsComputeBuffer<int>();
|
||||
particleToRenderer.AsComputeBuffer<int>();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (vertexToRenderer != null)
|
||||
vertexToRenderer.Dispose();
|
||||
if (particleToRenderer != null)
|
||||
particleToRenderer.Dispose();
|
||||
|
||||
if (particleIndices != null)
|
||||
particleIndices.Dispose();
|
||||
|
||||
if (dynamicVertexData != null)
|
||||
dynamicVertexData.Dispose();
|
||||
if (staticVertexData != null)
|
||||
staticVertexData.Dispose();
|
||||
if (triangles != null)
|
||||
triangles.Dispose();
|
||||
|
||||
gpuVertexBuffer?.Dispose();
|
||||
gpuVertexBuffer = null;
|
||||
|
||||
GameObject.DestroyImmediate(mesh);
|
||||
}
|
||||
|
||||
public bool TryMergeWith(IRenderBatch other)
|
||||
{
|
||||
var pbatch = other as DynamicRenderBatch<T>;
|
||||
if (pbatch != null)
|
||||
{
|
||||
if (CompareTo(pbatch) == 0 &&
|
||||
vertexCount + pbatch.vertexCount < Constants.maxVertsPerMesh)
|
||||
{
|
||||
rendererCount += pbatch.rendererCount;
|
||||
vertexCount += pbatch.vertexCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int CompareMaterialLists(Material[] a, Material[] b)
|
||||
{
|
||||
int l = Mathf.Min(a.Length, b.Length);
|
||||
for (int i = 0; i < l; ++i)
|
||||
{
|
||||
if (a[i] == null && b[i] == null)
|
||||
return 0;
|
||||
|
||||
if (a[i] == null) return -1;
|
||||
if (b[i] == null) return 1;
|
||||
|
||||
int compare = a[i].GetInstanceID().CompareTo(b[i].GetInstanceID());
|
||||
if (compare != 0)
|
||||
return compare;
|
||||
}
|
||||
return a.Length.CompareTo(b.Length);
|
||||
}
|
||||
|
||||
public int CompareTo(IRenderBatch other)
|
||||
{
|
||||
var pbatch = other as DynamicRenderBatch<T>;
|
||||
int result = CompareMaterialLists(materials, pbatch.materials);
|
||||
if (result == 0)
|
||||
return renderBatchParams.CompareTo(pbatch.renderBatchParams);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void BakeMesh(List<T> renderers,
|
||||
T renderer,
|
||||
ref Mesh bakedMesh, bool transformToActorLocalSpace = false)
|
||||
{
|
||||
// if the dynamic data is not available (such as when the batch is intended for GPU use), read it back:
|
||||
bool gpu = !dynamicVertexData.isCreated || dynamicVertexData == null;
|
||||
if (gpu)
|
||||
{
|
||||
dynamicVertexData = new ObiNativeList<DynamicBatchVertex>();
|
||||
dynamicVertexData.ResizeUninitialized(this.vertexCount);
|
||||
var nativeArray = dynamicVertexData.AsNativeArray<DynamicBatchVertex>();
|
||||
AsyncGPUReadback.RequestIntoNativeArray(ref nativeArray, gpuVertexBuffer, this.vertexCount * dynamicVertexData.stride, 0).WaitForCompletion();
|
||||
}
|
||||
|
||||
bakedMesh.Clear();
|
||||
|
||||
int vOffset = 0;
|
||||
int tOffset = 0;
|
||||
|
||||
for (int i = firstRenderer; i < firstRenderer + rendererCount; ++i)
|
||||
{
|
||||
// Count vertices of all instances:
|
||||
int vCount = 0;
|
||||
for (int k = 0; k < renderers[i].meshInstances; ++k)
|
||||
vCount += renderers[i].sourceMesh.vertexCount;
|
||||
|
||||
// Count triangles of all submeshes/instances:
|
||||
int tCount = 0;
|
||||
for (int m = 0; m < materials.Length; ++m)
|
||||
{
|
||||
int submeshIndex = Mathf.Min(m, renderers[i].sourceMesh.subMeshCount - 1);
|
||||
var submeshInfo = renderers[i].sourceMesh.GetSubMesh(submeshIndex);
|
||||
tCount += submeshInfo.indexCount * (int)renderers[i].meshInstances;
|
||||
}
|
||||
|
||||
// if this is the renderer we're interested in, populate the mesh:
|
||||
if (renderers[i].Equals(renderer))
|
||||
{
|
||||
bakedMesh.SetVertexBufferParams(vCount, vertexLayout);
|
||||
bakedMesh.SetVertexBufferData(dynamicVertexData.AsNativeArray<DynamicBatchVertex>(), vOffset, 0, vCount, 0, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
bakedMesh.SetVertexBufferData(staticVertexData.AsNativeArray<StaticBatchVertex>(), vOffset, 0, vCount, 1, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
// transform vertices from solver space to actor space:
|
||||
if (transformToActorLocalSpace)
|
||||
{
|
||||
var solver2Actor = renderer.actor.actorSolverToLocalMatrix;
|
||||
var verts = bakedMesh.vertices;
|
||||
for (int v = 0; v < verts.Length; ++v)
|
||||
verts[v] = solver2Actor.MultiplyPoint3x4(verts[v]);
|
||||
bakedMesh.vertices = verts;
|
||||
}
|
||||
|
||||
ObiNativeList<int> indices = new ObiNativeList<int>(tCount);
|
||||
|
||||
// calculate submeshes (one submesh per material):
|
||||
SubMeshDescriptor[] descriptors = new SubMeshDescriptor[materials.Length];
|
||||
for (int m = 0; m < materials.Length; ++m)
|
||||
{
|
||||
int vertexOffset = 0;
|
||||
var desc = new SubMeshDescriptor();
|
||||
desc.indexStart = indices.count;
|
||||
|
||||
int submeshIndex = Mathf.Min(m, renderer.sourceMesh.subMeshCount - 1);
|
||||
var submeshInfo = renderer.sourceMesh.GetSubMesh(submeshIndex);
|
||||
|
||||
for (int k = 0; k < renderer.meshInstances; ++k)
|
||||
{
|
||||
// append submesh triangles:
|
||||
var meshTriangles = renderer.sourceMesh.triangles;
|
||||
for (int t = submeshInfo.indexStart; t < submeshInfo.indexStart + submeshInfo.indexCount; ++t)
|
||||
indices.Add(vertexOffset + meshTriangles[t]);
|
||||
|
||||
vertexOffset += renderer.sourceMesh.vertexCount;
|
||||
}
|
||||
|
||||
desc.indexCount = indices.count - desc.indexStart;
|
||||
descriptors[m] = desc;
|
||||
}
|
||||
|
||||
bakedMesh.SetIndexBufferParams(tCount, IndexFormat.UInt32);
|
||||
bakedMesh.SetIndexBufferData(indices.AsNativeArray<int>(), 0, 0, tCount, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
bakedMesh.subMeshCount = materials.Length;
|
||||
for (int m = 0; m < materials.Length; ++m)
|
||||
bakedMesh.SetSubMesh(m, descriptors[m], MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
bakedMesh.RecalculateBounds();
|
||||
return;
|
||||
}
|
||||
|
||||
vOffset += vCount;
|
||||
tOffset += tCount;
|
||||
}
|
||||
|
||||
if (gpu)
|
||||
{
|
||||
dynamicVertexData.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bee4cda10f5944149b6f8c90a947c49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IRenderBatch : IComparable<IRenderBatch>
|
||||
{
|
||||
bool TryMergeWith(IRenderBatch other);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct RenderBatchParams
|
||||
{
|
||||
[HideInInspector] public int layer;
|
||||
public LightProbeUsage lightProbeUsage;
|
||||
public ReflectionProbeUsage reflectionProbeUsage;
|
||||
public ShadowCastingMode shadowCastingMode;
|
||||
public bool receiveShadows;
|
||||
public MotionVectorGenerationMode motionVectors;
|
||||
public uint renderingLayerMask;
|
||||
|
||||
public RenderBatchParams(bool receiveShadow)
|
||||
{
|
||||
layer = 0;
|
||||
lightProbeUsage = LightProbeUsage.BlendProbes;
|
||||
reflectionProbeUsage = ReflectionProbeUsage.BlendProbes;
|
||||
shadowCastingMode = ShadowCastingMode.On;
|
||||
receiveShadows = receiveShadow;
|
||||
motionVectors = MotionVectorGenerationMode.Camera;
|
||||
renderingLayerMask = 0xffffffff;
|
||||
}
|
||||
|
||||
public RenderBatchParams(Renderer renderer)
|
||||
{
|
||||
this.layer = renderer.gameObject.layer;
|
||||
this.lightProbeUsage = renderer.lightProbeUsage;
|
||||
this.reflectionProbeUsage = renderer.reflectionProbeUsage;
|
||||
this.shadowCastingMode = renderer.shadowCastingMode;
|
||||
this.receiveShadows = renderer.receiveShadows;
|
||||
this.motionVectors = renderer.motionVectorGenerationMode;
|
||||
this.renderingLayerMask = renderer.renderingLayerMask;
|
||||
}
|
||||
|
||||
public int CompareTo(RenderBatchParams param)
|
||||
{
|
||||
int cmp = layer.CompareTo(param.layer);
|
||||
if (cmp == 0) cmp = renderingLayerMask.CompareTo(param.renderingLayerMask);
|
||||
if (cmp == 0) cmp = lightProbeUsage.CompareTo(param.lightProbeUsage);
|
||||
if (cmp == 0) cmp = reflectionProbeUsage.CompareTo(param.reflectionProbeUsage);
|
||||
if (cmp == 0) cmp = shadowCastingMode.CompareTo(param.shadowCastingMode);
|
||||
if (cmp == 0) cmp = receiveShadows.CompareTo(param.receiveShadows);
|
||||
if (cmp == 0) cmp = motionVectors.CompareTo(param.motionVectors);
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
public RenderParams ToRenderParams()
|
||||
{
|
||||
var renderParams = new RenderParams();
|
||||
|
||||
// URP and HDRP don't work without this line.
|
||||
renderParams.renderingLayerMask = GraphicsSettings.defaultRenderingLayerMask;
|
||||
|
||||
renderParams.lightProbeUsage = lightProbeUsage;
|
||||
renderParams.reflectionProbeUsage = reflectionProbeUsage;
|
||||
renderParams.shadowCastingMode = shadowCastingMode;
|
||||
renderParams.receiveShadows = receiveShadows;
|
||||
renderParams.motionVectorMode = motionVectors;
|
||||
renderParams.renderingLayerMask = renderingLayerMask;
|
||||
renderParams.layer = layer;
|
||||
return renderParams;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a827293101844d32bed440c32d08c83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,141 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ChunkData
|
||||
{
|
||||
public int rendererIndex;
|
||||
public int offset; // index of the first element for each chunk.
|
||||
|
||||
public ChunkData(int rendererIndex, int offset)
|
||||
{
|
||||
this.rendererIndex = rendererIndex;
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
public class InstancedRenderBatch : IRenderBatch
|
||||
{
|
||||
private RenderBatchParams renderBatchParams;
|
||||
public RenderParams renderParams { get; private set; }
|
||||
|
||||
public Mesh mesh;
|
||||
public Material material;
|
||||
|
||||
public int firstRenderer;
|
||||
public int rendererCount;
|
||||
|
||||
public int firstInstance;
|
||||
public int instanceCount;
|
||||
|
||||
public GraphicsBuffer argsBuffer;
|
||||
|
||||
public InstancedRenderBatch(int rendererIndex, Mesh mesh, Material material, RenderBatchParams renderBatchParams)
|
||||
{
|
||||
this.renderBatchParams = renderBatchParams;
|
||||
this.firstRenderer = rendererIndex;
|
||||
this.rendererCount = 1;
|
||||
this.mesh = mesh;
|
||||
this.material = material;
|
||||
this.firstInstance = 0;
|
||||
this.instanceCount = 0;
|
||||
}
|
||||
|
||||
public void Initialize(bool gpu = false)
|
||||
{
|
||||
renderParams = renderBatchParams.ToRenderParams();
|
||||
|
||||
if (gpu)
|
||||
argsBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 1, 5 * sizeof(uint));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
argsBuffer?.Dispose();
|
||||
argsBuffer = null;
|
||||
}
|
||||
|
||||
public bool TryMergeWith(IRenderBatch other)
|
||||
{
|
||||
var ibatch = other as InstancedRenderBatch;
|
||||
if (ibatch != null)
|
||||
{
|
||||
if (CompareTo(ibatch) == 0 &&
|
||||
instanceCount + ibatch.instanceCount < Constants.maxInstancesPerBatch)
|
||||
{
|
||||
rendererCount += ibatch.rendererCount;
|
||||
instanceCount += ibatch.instanceCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int CompareTo(IRenderBatch other)
|
||||
{
|
||||
var ibatch = other as InstancedRenderBatch;
|
||||
|
||||
int idA = material != null ? material.GetInstanceID() : 0;
|
||||
int idB = (ibatch != null && ibatch.material != null) ? ibatch.material.GetInstanceID() : 0;
|
||||
|
||||
int compareMat = idA.CompareTo(idB);
|
||||
if (compareMat == 0)
|
||||
{
|
||||
idA = mesh != null ? mesh.GetInstanceID() : 0;
|
||||
idB = (ibatch != null && ibatch.mesh != null) ? ibatch.mesh.GetInstanceID() : 0;
|
||||
compareMat = idA.CompareTo(idB);
|
||||
|
||||
if (compareMat == 0)
|
||||
return renderBatchParams.CompareTo(ibatch.renderBatchParams);
|
||||
}
|
||||
|
||||
return compareMat;
|
||||
}
|
||||
|
||||
public void BakeMesh<T>(RendererSet<T> renderers, T renderer, ObiNativeList<ChunkData> chunkData,
|
||||
ObiNativeList<Matrix4x4> instanceTransforms,
|
||||
Matrix4x4 transform,
|
||||
ref Mesh bakedMesh, bool transformVertices = false) where T:ObiRenderer<T>
|
||||
{
|
||||
|
||||
// if the data is not available in the CPU (such as when the batch is intended for GPU use), read it back:
|
||||
bool gpu = argsBuffer != null && argsBuffer.IsValid();
|
||||
if (gpu)
|
||||
{
|
||||
instanceTransforms.Readback(false);
|
||||
}
|
||||
|
||||
List<CombineInstance> combineInstances = new List<CombineInstance>();
|
||||
|
||||
bakedMesh.Clear();
|
||||
|
||||
for (int i = 0; i < chunkData.count; ++i)
|
||||
{
|
||||
// if this chunk's renderer is the renderer we are interested in,
|
||||
// append its instances to the mesh.
|
||||
if (renderers[chunkData[i].rendererIndex].Equals(renderer))
|
||||
{
|
||||
int firstIndex = i > 0 ? chunkData[i - 1].offset : 0;
|
||||
int elementCount = chunkData[i].offset - firstIndex;
|
||||
|
||||
for (int m = 0; m < elementCount; ++m)
|
||||
{
|
||||
combineInstances.Add(new CombineInstance
|
||||
{
|
||||
mesh = mesh,
|
||||
transform = transformVertices ? transform * instanceTransforms[firstIndex + m] : instanceTransforms[firstIndex + m]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bakedMesh.CombineMeshes(combineInstances.ToArray(), true, true, false);
|
||||
bakedMesh.RecalculateBounds();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74d879a363c7040229e215fe6c48a581
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,186 +0,0 @@
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using Unity.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public class ProceduralRenderBatch<T> : IRenderBatch where T : struct
|
||||
{
|
||||
private RenderBatchParams renderBatchParams;
|
||||
public RenderParams renderParams { get; private set; }
|
||||
|
||||
public Material material;
|
||||
public Mesh mesh;
|
||||
|
||||
public int firstRenderer;
|
||||
public int rendererCount;
|
||||
|
||||
public int firstParticle;
|
||||
|
||||
public NativeArray<T> vertices;
|
||||
public NativeArray<int> triangles;
|
||||
|
||||
public GraphicsBuffer gpuVertexBuffer;
|
||||
public GraphicsBuffer gpuIndexBuffer;
|
||||
|
||||
public int vertexCount;
|
||||
public int triangleCount;
|
||||
|
||||
public ProceduralRenderBatch(int rendererIndex, Material material, RenderBatchParams param)
|
||||
{
|
||||
this.renderBatchParams = param;
|
||||
|
||||
this.material = material;
|
||||
this.firstRenderer = rendererIndex;
|
||||
this.firstParticle = 0;
|
||||
this.rendererCount = 1;
|
||||
this.vertexCount = 0;
|
||||
this.triangleCount = 0;
|
||||
}
|
||||
|
||||
public void Initialize(VertexAttributeDescriptor[] layout, bool gpu = false)
|
||||
{
|
||||
var rp = renderBatchParams.ToRenderParams();
|
||||
rp.material = material;
|
||||
renderParams = rp;
|
||||
|
||||
mesh = new Mesh();
|
||||
|
||||
mesh.SetVertexBufferParams(vertexCount, layout);
|
||||
mesh.SetIndexBufferParams(triangleCount * 3, IndexFormat.UInt32);
|
||||
|
||||
vertices = new NativeArray<T>(vertexCount, Allocator.Persistent);
|
||||
mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length, 0, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
triangles = new NativeArray<int>(triangleCount * 3, Allocator.Persistent);
|
||||
mesh.SetIndexBufferData(triangles, 0, 0, triangles.Length, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
mesh.subMeshCount = 1;
|
||||
SubMeshDescriptor subMeshDescriptor = new SubMeshDescriptor();
|
||||
subMeshDescriptor.indexCount = triangleCount * 3;
|
||||
mesh.SetSubMesh(0, subMeshDescriptor, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
if (gpu)
|
||||
{
|
||||
vertices.Dispose();
|
||||
triangles.Dispose();
|
||||
|
||||
mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
|
||||
mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
|
||||
|
||||
// particles with no vertices will have no vertex buffer, and Unity will throw an exception.
|
||||
if (mesh.vertexCount > 0)
|
||||
{
|
||||
gpuVertexBuffer ??= mesh.GetVertexBuffer(0);
|
||||
gpuIndexBuffer ??= mesh.GetIndexBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
gpuVertexBuffer?.Dispose();
|
||||
gpuIndexBuffer?.Dispose();
|
||||
|
||||
gpuVertexBuffer = null;
|
||||
gpuIndexBuffer = null;
|
||||
|
||||
if (vertices.IsCreated)
|
||||
vertices.Dispose();
|
||||
if (triangles.IsCreated)
|
||||
triangles.Dispose();
|
||||
|
||||
GameObject.DestroyImmediate(mesh);
|
||||
}
|
||||
|
||||
public bool TryMergeWith(IRenderBatch other)
|
||||
{
|
||||
var pbatch = other as ProceduralRenderBatch<T>;
|
||||
if (pbatch != null)
|
||||
{
|
||||
if (CompareTo(pbatch) == 0 &&
|
||||
vertexCount + pbatch.vertexCount < Constants.maxVertsPerMesh)
|
||||
{
|
||||
rendererCount += pbatch.rendererCount;
|
||||
triangleCount += pbatch.triangleCount;
|
||||
vertexCount += pbatch.vertexCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int CompareTo(IRenderBatch other)
|
||||
{
|
||||
var pbatch = other as ProceduralRenderBatch<T>;
|
||||
int idA = material != null ? material.GetInstanceID() : 0;
|
||||
int idB = (pbatch != null && pbatch.material != null) ? pbatch.material.GetInstanceID() : 0;
|
||||
|
||||
int result = idA.CompareTo(idB);
|
||||
if (result == 0)
|
||||
return renderBatchParams.CompareTo(pbatch.renderBatchParams);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void BakeMesh(int vertexOffset, int vertexCount, int triangleOffset, int triangleCount,
|
||||
Matrix4x4 transform,
|
||||
ref Mesh bakedMesh, bool transformVertices = false)
|
||||
{
|
||||
|
||||
// if the data is not available in the CPU (such as when the batch is intended for GPU use), read it back:
|
||||
bool gpu = !vertices.IsCreated;
|
||||
if (gpu)
|
||||
{
|
||||
vertices = new NativeArray<T>(this.vertexCount, Allocator.Persistent);
|
||||
triangles = new NativeArray<int>(this.triangleCount * 3, Allocator.Persistent);
|
||||
AsyncGPUReadback.RequestIntoNativeArray(ref vertices, gpuVertexBuffer, this.vertexCount * UnsafeUtility.SizeOf<T>(), 0).WaitForCompletion();
|
||||
AsyncGPUReadback.RequestIntoNativeArray(ref triangles, gpuIndexBuffer, this.triangleCount * 3 * 4, 0).WaitForCompletion();
|
||||
}
|
||||
|
||||
bakedMesh.Clear();
|
||||
|
||||
bakedMesh.SetVertexBufferParams(vertexCount, mesh.GetVertexAttributes());
|
||||
bakedMesh.SetVertexBufferData(vertices, vertexOffset, 0, vertexCount, 0, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
// transform vertices from solver space to actor space:
|
||||
if (transformVertices)
|
||||
{
|
||||
var solver2Actor = transform;
|
||||
var verts = bakedMesh.vertices;
|
||||
for (int v = 0; v < verts.Length; ++v)
|
||||
verts[v] = solver2Actor.MultiplyPoint3x4(verts[v]);
|
||||
bakedMesh.vertices = verts;
|
||||
}
|
||||
|
||||
ObiNativeList<int> indices = new ObiNativeList<int>(triangleCount * 3);
|
||||
|
||||
// offset indices:
|
||||
for (int i = 0; i < triangleCount * 3; ++i)
|
||||
{
|
||||
int index = triangles[triangleOffset * 3 + i] - vertexOffset;
|
||||
|
||||
// clamp indices to zero, since decimated ropes have unused triangles
|
||||
// that reference vertex 0. Subtracting the vertex offset from these results in a negative index.
|
||||
indices.Add(Mathf.Max(0,index));
|
||||
}
|
||||
|
||||
bakedMesh.SetIndexBufferParams(triangleCount * 3, IndexFormat.UInt32);
|
||||
bakedMesh.SetIndexBufferData(indices.AsNativeArray<int>(), 0, 0, triangleCount * 3, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
bakedMesh.subMeshCount = 1;
|
||||
SubMeshDescriptor subMeshDescriptor = new SubMeshDescriptor();
|
||||
subMeshDescriptor.indexCount = triangleCount * 3; // mesh triangle count.
|
||||
bakedMesh.SetSubMesh(0, subMeshDescriptor, MeshUpdateFlags.DontValidateIndices);
|
||||
|
||||
if (gpu)
|
||||
{
|
||||
if (vertices.IsCreated)
|
||||
vertices.Dispose();
|
||||
if (triangles.IsCreated)
|
||||
triangles.Dispose();
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ded06625ac9f94b1fa77fd845bb28ec9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user