#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS) using UnityEngine; using Unity.Jobs; using Unity.Collections; using Unity.Mathematics; using Unity.Burst; using Unity.Collections.LowLevel.Unsafe; namespace Obi { public class BurstChainRopeRenderSystem : ObiChainRopeRenderSystem { protected Matrix4x4[] transformsArray = new Matrix4x4[1023]; public BurstChainRopeRenderSystem(ObiSolver solver) : base(solver) { } public override void Setup() { base.Setup(); } public override void Render() { using (m_RenderMarker.Auto()) { // generate raw frames using parallel transport var instanceTransformsJob = new InstanceTransforms() { rendererData = rendererData.AsNativeArray(), chunkData = chunkData.AsNativeArray(), modifiers = modifiers.AsNativeArray(), elements = elements.AsNativeArray(), instanceTransforms = instanceTransforms.AsNativeArray(), instanceColors = instanceColors.AsNativeArray(), renderablePositions = m_Solver.renderablePositions.AsNativeArray(), renderableOrientations = m_Solver.renderableOrientations.AsNativeArray(), principalRadii = m_Solver.principalRadii.AsNativeArray(), colors = m_Solver.colors.AsNativeArray(), solverToWorld = m_Solver.transform.localToWorldMatrix, }; instanceTransformsJob.Schedule(chunkData.count, 8).Complete(); //Draw instances: for (int i = 0; i < batchList.Count; i++) { var batch = batchList[i]; var rp = batch.renderParams; rp.material = batch.material; rp.worldBounds = m_Solver.bounds; Graphics.RenderMeshInstanced(rp, batch.mesh, 0, instanceTransforms.AsNativeArray(), batch.instanceCount, batch.firstInstance); } } } [BurstCompile] struct InstanceTransforms : IJobParallelFor { [ReadOnly] public NativeArray rendererData; [ReadOnly] public NativeArray chunkData; [ReadOnly] public NativeArray modifiers; [ReadOnly] public NativeArray elements; [ReadOnly] public NativeArray renderablePositions; [ReadOnly] public NativeArray renderableOrientations; [ReadOnly] public NativeArray principalRadii; [ReadOnly] public NativeArray colors; [ReadOnly] public float4x4 solverToWorld; [NativeDisableParallelForRestriction] public NativeArray instanceTransforms; [NativeDisableParallelForRestriction] public NativeArray instanceColors; public void Execute(int i) { int firstIndex = i > 0 ? chunkData[i - 1].offset : 0; int elementCount = chunkData[i].offset - firstIndex; var rendererIndex = chunkData[i].rendererIndex; var renderer = rendererData[rendererIndex]; float3 rendScale = ((float4)renderer.scale).xyz; int firstModifier = rendererIndex > 0 ? rendererData[rendererIndex - 1].modifierOffset : 0; int modifierCount = renderer.modifierOffset - firstModifier; var modifier = new ObiRopeChainRenderer.LinkModifier(); modifier.Clear(); BurstPathFrame frame = new BurstPathFrame(); frame.Reset(); float twist = -renderer.twist * elementCount * renderer.twistAnchor; frame.SetTwist(twist); // parallel transport: for (int m = 0; m < elementCount; ++m) { if (modifierCount > 0) modifier = modifiers[firstModifier + m % modifierCount]; int index = firstIndex + m; float4 pos = renderablePositions[elements[index].x]; float4 nextPos = renderablePositions[elements[index].y]; float4 vector = nextPos - pos; float3 tangent = math.normalizesafe(vector.xyz); if (renderer.usesOrientedParticles == 1) { frame.Transport(nextPos.xyz, tangent, math.rotate(renderableOrientations[elements[index].x], new float3(0, 1, 0)), twist); twist += renderer.twist; } else frame.Transport(nextPos.xyz, tangent, renderer.twist); var rotation = quaternion.LookRotationSafe(frame.tangent, frame.normal); var position = (pos + vector * 0.5f).xyz + math.mul(rotation, modifier.translation); var scale = principalRadii[elements[index].x].x * 2 * rendScale * modifier.scale; rotation = math.mul(rotation, quaternion.Euler(math.radians(modifier.rotation))); instanceTransforms[index] = math.mul(solverToWorld,float4x4.TRS(position,rotation,scale)); instanceColors[index] = (colors[elements[index].x] + colors[elements[index].y]) * 0.5f; } } } } } #endif