Files
Fishing2/Assets/Obi/Scripts/Common/Backends/Compute/Constraints/ShapeMatching/ComputeShapeMatchingConstraintsBatch.cs
2025-11-10 00:08:26 +08:00

204 lines
11 KiB
C#

using UnityEngine;
namespace Obi
{
public class ComputeShapeMatchingConstraintsBatch : ComputeConstraintsBatchImpl, IShapeMatchingConstraintsBatchImpl
{
private GraphicsBuffer firstIndexBuffer;
private GraphicsBuffer numIndicesBuffer;
private GraphicsBuffer explicitGroupBuffer;
private GraphicsBuffer shapeMaterialParametersBuffer;
private GraphicsBuffer restComsBuffer;
private GraphicsBuffer comsBuffer;
private GraphicsBuffer constraintOrientationsBuffer;
private GraphicsBuffer AqqBuffer;
private GraphicsBuffer linearTransformsBuffer;
private GraphicsBuffer plasticDeformationsBuffer;
private ObiNativeVector4List m_RestComs;
private ObiNativeVector4List m_Coms;
private ObiNativeQuaternionList m_ConstraintOrientations;
private bool m_RecalculateRestShape = false;
public ComputeShapeMatchingConstraintsBatch(ComputeShapeMatchingConstraints constraints)
{
m_Constraints = constraints;
m_ConstraintType = Oni.ConstraintType.ShapeMatching;
}
public void SetShapeMatchingConstraints(ObiNativeIntList particleIndices,
ObiNativeIntList firstIndex,
ObiNativeIntList numIndices,
ObiNativeIntList explicitGroup,
ObiNativeFloatList shapeMaterialParameters,
ObiNativeVector4List restComs,
ObiNativeVector4List coms,
ObiNativeQuaternionList constraintOrientations,
ObiNativeMatrix4x4List linearTransforms,
ObiNativeMatrix4x4List plasticDeformations,
ObiNativeFloatList lambdas,
int count)
{
this.particleIndices = particleIndices.AsComputeBuffer<int>();
this.firstIndexBuffer = firstIndex.AsComputeBuffer<int>();
this.numIndicesBuffer = numIndices.AsComputeBuffer<int>();
this.explicitGroupBuffer = explicitGroup.AsComputeBuffer<int>();
this.shapeMaterialParametersBuffer = shapeMaterialParameters.AsComputeBuffer<float>();
this.restComsBuffer = restComs.AsComputeBuffer<Vector4>();
this.comsBuffer = coms.AsComputeBuffer<Vector4>();
this.constraintOrientationsBuffer = constraintOrientations.AsComputeBuffer<Quaternion>();
this.linearTransformsBuffer = linearTransforms.AsComputeBuffer<Matrix4x4>();
this.plasticDeformationsBuffer = plasticDeformations.AsComputeBuffer<Matrix4x4>();
if (AqqBuffer != null)
AqqBuffer.Dispose();
AqqBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, count, 64); // float4x4
m_RestComs = restComs;
m_Coms = coms;
m_ConstraintOrientations = constraintOrientations;
m_ConstraintCount = count;
}
public override void Destroy()
{
if (AqqBuffer != null)
AqqBuffer.Dispose();
}
public override void Evaluate(float stepTime, float substepTime, int steps, float timeLeft)
{
if (m_ConstraintCount > 0)
{
var shader = ((ComputeShapeMatchingConstraints)m_Constraints).constraintsShader;
int threadGroups = ComputeMath.ThreadGroupCount(m_ConstraintCount, 128);
shader.SetInt("activeConstraintCount", m_ConstraintCount);
shader.SetFloat("deltaTime", substepTime);
if (m_RecalculateRestShape)
{
m_RecalculateRestShape = false;
int restKernel = ((ComputeShapeMatchingConstraints)m_Constraints).restStateKernel;
shader.SetBuffer(restKernel, "particleIndices", particleIndices);
shader.SetBuffer(restKernel, "firstIndex", firstIndexBuffer);
shader.SetBuffer(restKernel, "numIndices", numIndicesBuffer);
shader.SetBuffer(restKernel, "RW_restComs", restComsBuffer);
shader.SetBuffer(restKernel, "RW_Aqq", AqqBuffer);
shader.SetBuffer(restKernel, "RW_deformation", plasticDeformationsBuffer);
shader.SetBuffer(restKernel, "restPositions", solverImplementation.restPositionsBuffer);
shader.SetBuffer(restKernel, "restOrientations", solverImplementation.restOrientationsBuffer);
shader.SetBuffer(restKernel, "invMasses", solverImplementation.invMassesBuffer);
shader.SetBuffer(restKernel, "invRotationalMasses", solverImplementation.invRotationalMassesBuffer);
shader.SetBuffer(restKernel, "principalRadii", solverImplementation.principalRadiiBuffer);
shader.Dispatch(restKernel, threadGroups, 1, 1);
m_RestComs.Readback();
m_RestComs.WaitForReadback();
}
//var shader = ((ComputeShapeMatchingConstraints)m_Constraints).constraintsShader;
int projectKernel = ((ComputeShapeMatchingConstraints)m_Constraints).projectKernel;
int plasticityKernel = ((ComputeShapeMatchingConstraints)m_Constraints).plasticityKernel;
shader.SetBuffer(projectKernel, "particleIndices", particleIndices);
shader.SetBuffer(projectKernel, "firstIndex", firstIndexBuffer);
shader.SetBuffer(projectKernel, "numIndices", numIndicesBuffer);
shader.SetBuffer(projectKernel, "explicitGroup", explicitGroupBuffer);
shader.SetBuffer(projectKernel, "shapeMaterialParameters", shapeMaterialParametersBuffer);
shader.SetBuffer(projectKernel, "restComs", restComsBuffer);
shader.SetBuffer(projectKernel, "coms", comsBuffer);
shader.SetBuffer(projectKernel, "constraintOrientations", constraintOrientationsBuffer);
shader.SetBuffer(projectKernel, "Aqq", AqqBuffer);
shader.SetBuffer(projectKernel, "RW_linearTransforms", linearTransformsBuffer);
shader.SetBuffer(projectKernel, "deformation", plasticDeformationsBuffer);
shader.SetBuffer(projectKernel, "positions", solverImplementation.positionsBuffer);
shader.SetBuffer(projectKernel, "restPositions", solverImplementation.restPositionsBuffer);
shader.SetBuffer(projectKernel, "orientations", solverImplementation.orientationsBuffer);
shader.SetBuffer(projectKernel, "restOrientations", solverImplementation.restOrientationsBuffer);
shader.SetBuffer(projectKernel, "invMasses", solverImplementation.invMassesBuffer);
shader.SetBuffer(projectKernel, "invRotationalMasses", solverImplementation.invRotationalMassesBuffer);
shader.SetBuffer(projectKernel, "principalRadii", solverImplementation.principalRadiiBuffer);
shader.SetBuffer(projectKernel, "deltasAsInt", solverImplementation.positionDeltasIntBuffer);
shader.SetBuffer(projectKernel, "positionConstraintCounts", solverImplementation.positionConstraintCountBuffer);
shader.Dispatch(projectKernel, threadGroups, 1, 1);
shader.SetBuffer(plasticityKernel, "particleIndices", particleIndices);
shader.SetBuffer(plasticityKernel, "firstIndex", firstIndexBuffer);
shader.SetBuffer(plasticityKernel, "numIndices", numIndicesBuffer);
shader.SetBuffer(plasticityKernel, "shapeMaterialParameters", shapeMaterialParametersBuffer);
shader.SetBuffer(plasticityKernel, "RW_restComs", restComsBuffer);
shader.SetBuffer(plasticityKernel, "constraintOrientations", constraintOrientationsBuffer);
shader.SetBuffer(plasticityKernel, "RW_Aqq", AqqBuffer);
shader.SetBuffer(plasticityKernel, "linearTransforms", linearTransformsBuffer);
shader.SetBuffer(plasticityKernel, "RW_deformation", plasticDeformationsBuffer);
shader.SetBuffer(plasticityKernel, "restPositions", solverImplementation.restPositionsBuffer);
shader.SetBuffer(plasticityKernel, "restOrientations", solverImplementation.restOrientationsBuffer);
shader.SetBuffer(plasticityKernel, "invMasses", solverImplementation.invMassesBuffer);
shader.SetBuffer(plasticityKernel, "invRotationalMasses", solverImplementation.invRotationalMassesBuffer);
shader.SetBuffer(plasticityKernel, "principalRadii", solverImplementation.principalRadiiBuffer);
shader.Dispatch(plasticityKernel, threadGroups, 1, 1);
}
}
public override void Apply(float substepTime)
{
if (m_ConstraintCount > 0)
{
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
var shader = ((ComputeShapeMatchingConstraints)m_Constraints).constraintsShader;
int applyKernel = ((ComputeShapeMatchingConstraints)m_Constraints).applyKernel;
shader.SetBuffer(applyKernel, "particleIndices", particleIndices);
shader.SetBuffer(applyKernel, "firstIndex", firstIndexBuffer);
shader.SetBuffer(applyKernel, "numIndices", numIndicesBuffer);
shader.SetBuffer(applyKernel, "RW_positions", solverImplementation.positionsBuffer);
shader.SetBuffer(applyKernel, "positionConstraintCounts", solverImplementation.positionConstraintCountBuffer);
shader.SetBuffer(applyKernel, "deltasAsInt", solverImplementation.positionDeltasIntBuffer);
shader.SetInt("activeConstraintCount", m_ConstraintCount);
shader.SetFloat("sorFactor", parameters.SORFactor);
int threadGroups = ComputeMath.ThreadGroupCount(m_ConstraintCount, 128);
shader.Dispatch(applyKernel, threadGroups, 1, 1);
}
}
public void CalculateRestShapeMatching()
{
// just set a flag and do the actual calculation at the start of Evaluate().
// This ensures GPu data of both particles and constraints is up to date when calculating the rest shape.
m_RecalculateRestShape = true;
}
public void RequestDataReadback()
{
m_Coms.Readback();
m_ConstraintOrientations.Readback();
}
public void WaitForReadback()
{
m_Coms.WaitForReadback();
m_ConstraintOrientations.WaitForReadback();
}
}
}