Files
Fishing2/Assets/Obi/Scripts/Common/Backends/Burst/Rendering/RopeAndRod/BurstChainRopeRenderSystem.cs
2025-11-10 00:08:26 +08:00

140 lines
5.7 KiB
C#

#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<ChainRendererData>(),
chunkData = chunkData.AsNativeArray<ChunkData>(),
modifiers = modifiers.AsNativeArray<ObiRopeChainRenderer.LinkModifier>(),
elements = elements.AsNativeArray<int2>(),
instanceTransforms = instanceTransforms.AsNativeArray<float4x4>(),
instanceColors = instanceColors.AsNativeArray<float4>(),
renderablePositions = m_Solver.renderablePositions.AsNativeArray<float4>(),
renderableOrientations = m_Solver.renderableOrientations.AsNativeArray<quaternion>(),
principalRadii = m_Solver.principalRadii.AsNativeArray<float4>(),
colors = m_Solver.colors.AsNativeArray<float4>(),
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<Matrix4x4>(), batch.instanceCount, batch.firstInstance);
}
}
}
[BurstCompile]
struct InstanceTransforms : IJobParallelFor
{
[ReadOnly] public NativeArray<ChainRendererData> rendererData;
[ReadOnly] public NativeArray<ChunkData> chunkData;
[ReadOnly] public NativeArray<ObiRopeChainRenderer.LinkModifier> modifiers;
[ReadOnly] public NativeArray<int2> elements;
[ReadOnly] public NativeArray<float4> renderablePositions;
[ReadOnly] public NativeArray<quaternion> renderableOrientations;
[ReadOnly] public NativeArray<float4> principalRadii;
[ReadOnly] public NativeArray<float4> colors;
[ReadOnly] public float4x4 solverToWorld;
[NativeDisableParallelForRestriction] public NativeArray<float4x4> instanceTransforms;
[NativeDisableParallelForRestriction] public NativeArray<float4> 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