#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS) using Unity.Jobs; using Unity.Collections; using Unity.Mathematics; using Unity.Burst; using UnityEngine; namespace Obi { [BurstCompile] struct ResetNormals : IJobParallelFor { [ReadOnly] public NativeArray phases; public NativeArray normals; [WriteOnly] public NativeArray tangents; public void Execute(int i) { // leave fluid and softbody normals intact. if ((phases[i] & (int)ObiUtils.ParticleFlags.Fluid) == 0 && normals[i].w >= 0) { normals[i] = float4.zero; tangents[i] = float4.zero; } } } [BurstCompile] unsafe struct UpdateTriangleNormalsJob : IJobParallelFor { [ReadOnly] public NativeArray deformableTriangles; [ReadOnly] public NativeArray deformableTriangleUVs; [ReadOnly] public NativeArray renderPositions; [NativeDisableParallelForRestriction] public NativeArray normals; [NativeDisableParallelForRestriction] public NativeArray tangents; public void Execute(int i) { int p1 = deformableTriangles[i*3]; int p2 = deformableTriangles[i*3 + 1]; int p3 = deformableTriangles[i*3 + 2]; float3 m1 = (renderPositions[p2] - renderPositions[p1]).xyz; float3 m2 = (renderPositions[p3] - renderPositions[p1]).xyz; float2 s = deformableTriangleUVs[i * 3 + 1] - deformableTriangleUVs[i * 3]; float2 t = deformableTriangleUVs[i * 3 + 2] - deformableTriangleUVs[i * 3]; float4 normal = new float4(math.cross(m1, m2), 0); float4 tangent = float4.zero; float area = s.x * t.y - t.x * s.y; if (math.abs(area) > BurstMath.epsilon) { tangent = new float4(t.y * m1.x - s.y * m2.x, t.y * m1.y - s.y * m2.y, t.y * m1.z - s.y * m2.z, 0) / area; } BurstMath.AtomicAdd(normals, p1, normal); BurstMath.AtomicAdd(normals, p2, normal); BurstMath.AtomicAdd(normals, p3, normal); BurstMath.AtomicAdd(tangents, p1, tangent); BurstMath.AtomicAdd(tangents, p2, tangent); BurstMath.AtomicAdd(tangents, p3, tangent); } } [BurstCompile] unsafe struct UpdateEdgeNormalsJob : IJobParallelFor { [ReadOnly] public NativeArray deformableEdges; [ReadOnly] public NativeArray velocities; [ReadOnly] public NativeArray wind; [ReadOnly] public NativeArray renderPositions; [NativeDisableParallelForRestriction] public NativeArray normals; public void Execute(int i) { int p1 = deformableEdges[i * 2]; int p2 = deformableEdges[i * 2 + 1]; float4 edge = renderPositions[p2] - renderPositions[p1]; float4 avgWind = (velocities[p1] + velocities[p2]) * 0.5f - (wind[p1] + wind[p2]) * 0.5f; float4 normal = avgWind - math.projectsafe(avgWind, edge); BurstMath.AtomicAdd(normals, p1, normal); BurstMath.AtomicAdd(normals, p2, normal); } } [BurstCompile] struct RenderableOrientationFromNormals : IJobParallelFor { [ReadOnly] public NativeArray phases; public NativeArray normals; public NativeArray tangents; [WriteOnly] public NativeArray renderableOrientations; public void Execute(int i) { if (((phases[i] & (int)ObiUtils.ParticleFlags.Fluid) == 0 && normals[i].w >= 0) && // not fluid or softbody (no SDF stored) math.lengthsq(normals[i]) > BurstMath.epsilon && math.lengthsq(tangents[i]) > BurstMath.epsilon) { normals[i] = math.normalizesafe(normals[i]); tangents[i] = math.normalizesafe(tangents[i]); // particle orientation from normal/tangent: renderableOrientations[i] = quaternion.LookRotation(normals[i].xyz, tangents[i].xyz); } } } } #endif