Created
April 3, 2022 06:49
-
-
Save shanecelis/e40050f7f08d70bb8fa1aeffcb44f61e to your computer and use it in GitHub Desktop.
Not intended for real distribution. Just enabling a twitter discussion.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Nito.Disposables; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
using static Unity.Mathematics.math; | |
namespace SeawispHunter.Buoyancy.DOTS { | |
#if ! DISABLE_BURST | |
[BurstCompile] | |
#endif | |
// https://gist.github.com/aras-p/4af04b9c9c1fe1180a0a645d499ad430 | |
public struct SurfaceMeshProcessor : IJobParallelFor, IDisposable { | |
[ReadOnly] public float3 planePosition; | |
[ReadOnly] public float3 planeNormal; | |
[ReadOnly] public NativeArray<Mesh.MeshData> meshDatas; | |
[ReadOnly] public NativeArray<int> vertexCount; | |
[ReadOnly] public NativeArray<uint> triCount; | |
[ReadOnly] public NativeArray<float4x4> xforms; | |
[NativeDisableParallelForRestriction] public NativeArrayOfArrays<float3> outputCentroids; | |
[NativeDisableParallelForRestriction] public NativeArrayOfArrays<float> outputAreas; | |
[NativeDisableParallelForRestriction] public NativeArrayOfArrays<float3> outputNormals; | |
public enum Calculate { | |
TriangleStatistics, | |
} | |
public Calculate calculate; | |
public SurfaceMeshProcessor(IList<MeshFilter> meshFilters, out IDisposable cleanUp, Allocator allocator) { | |
planeNormal = float3(0, 1, 0); | |
planePosition = 0; | |
int count = meshFilters.Count; | |
calculate = Calculate.TriangleStatistics; | |
var options = NativeArrayOptions.UninitializedMemory; | |
meshDatas = new NativeArray<Mesh.MeshData>(count, allocator, options); | |
vertexCount = new NativeArray<int>(count, allocator, options); | |
triCount = new NativeArray<uint>(count, allocator, options); | |
xforms = new NativeArray<float4x4>(count, allocator, options); | |
var meshArrays = new List<IDisposable>(count); | |
var counts = new List<int>(); | |
for (int i = 0; i < count; i++) { | |
var mesh = meshFilters[i].sharedMesh; | |
// using (var meshDataArray = Mesh.AcquireReadOnlyMeshData(mesh)) | |
var meshDataArray = Mesh.AcquireReadOnlyMeshData(mesh); | |
// We must dispose of the array but we can't keep a handle to it here. | |
meshArrays.Add(meshDataArray); | |
meshDatas[i] = meshDataArray[0]; | |
xforms[i] = meshFilters[i].transform.localToWorldMatrix; | |
vertexCount[i] = mesh.vertexCount; | |
triCount[i] = mesh.GetIndexCount(0); | |
counts.Add((int) triCount[i]); | |
} | |
outputCentroids = new NativeArrayOfArrays<float3>(counts, allocator, options); | |
outputAreas = new NativeArrayOfArrays<float>(counts, allocator, options); | |
outputNormals = new NativeArrayOfArrays<float3>(counts, allocator, options); | |
// Little problem here. We can't keep the meshDataArray directly. | |
// cleanUp = new Disposable(() => {foreach (var d in meshArrays) d.Dispose(); }); | |
cleanUp = new CollectionDisposable(meshArrays); | |
} | |
public void Execute(int index) { | |
var vCount = vertexCount[index]; | |
if (vCount == 0) | |
return; | |
var mat = xforms[index]; | |
var vdata = meshDatas[index]; | |
var verts = new NativeArray<float3>(vCount, | |
Allocator.Temp, | |
NativeArrayOptions.UninitializedMemory); | |
vdata.GetVertices(verts.Reinterpret<Vector3>()); | |
var normals = new NativeArray<float3>(vCount, | |
Allocator.Temp, | |
NativeArrayOptions.UninitializedMemory); | |
vdata.GetNormals(normals.Reinterpret<Vector3>()); | |
var tCount = triCount[index]; | |
float3 centroid = 0f; | |
float volume = 0f; | |
var _outputCentroids = outputCentroids[index]; | |
var _outputAreas = outputAreas[index]; | |
var _outputNormals = outputNormals[index]; | |
if (vdata.indexFormat == IndexFormat.UInt16) { | |
var tris = vdata.GetIndexData<ushort>(); | |
for (var i = 0; i < tCount; i += 3) { | |
float3 a = math.mul(mat, float4(verts[tris[i + 0]], 1)).xyz; | |
float3 b = math.mul(mat, float4(verts[tris[i + 1]], 1)).xyz; | |
float3 c = math.mul(mat, float4(verts[tris[i + 2]], 1)).xyz; | |
_outputCentroids[i] = (a + b + c) / 3f; | |
_outputAreas[i] = length(cross(b - a, c - a)) / 2f; | |
float3 n0 = math.mul(mat, float4(normals[tris[i + 0]], 0)).xyz; | |
float3 n1 = math.mul(mat, float4(normals[tris[i + 1]], 0)).xyz; | |
float3 n2 = math.mul(mat, float4(normals[tris[i + 2]], 0)).xyz; | |
float3 n = (n0 + n1 + n2) / 3f; | |
_outputNormals[i] = n; | |
} | |
} else { | |
var tris = vdata.GetIndexData<int>(); | |
for (var i = 0; i < tCount; i += 3) { | |
float3 a = math.mul(mat, float4(verts[tris[i + 0]], 1)).xyz; | |
float3 b = math.mul(mat, float4(verts[tris[i + 1]], 1)).xyz; | |
float3 c = math.mul(mat, float4(verts[tris[i + 2]], 1)).xyz; | |
_outputCentroids[i] = (a + b + c) / 3f; | |
_outputAreas[i] = length(cross(b - a, c - a)) / 2f; | |
float3 n0 = math.mul(mat, float4(normals[tris[i + 0]], 0)).xyz; | |
float3 n1 = math.mul(mat, float4(normals[tris[i + 1]], 0)).xyz; | |
float3 n2 = math.mul(mat, float4(normals[tris[i + 2]], 0)).xyz; | |
float3 n = (n0 + n1 + n2) / 3f; | |
_outputNormals[i] = n; | |
} | |
} | |
verts.Dispose(); | |
} | |
public void Dispose() { | |
if (meshDatas.IsCreated) | |
meshDatas.Dispose(); | |
if (vertexCount.IsCreated) | |
vertexCount.Dispose(); | |
if (xforms.IsCreated) | |
xforms.Dispose(); | |
if (triCount.IsCreated) | |
triCount.Dispose(); | |
if (outputCentroids.IsCreated) | |
outputCentroids.Dispose(); | |
if (outputAreas.IsCreated) | |
outputAreas.Dispose(); | |
if (outputNormals.IsCreated) | |
outputNormals.Dispose(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment