_xiaofang/xiaofang/Assets/Obi/Scripts/Common/Utils/ObiParticleDragger.cs

85 lines
3.0 KiB
C#
Raw Normal View History

2024-12-18 02:18:45 +08:00
using System;
using UnityEngine;
namespace Obi
{
[RequireComponent(typeof(LineRenderer))]
[RequireComponent(typeof(ObiParticlePicker))]
public class ObiParticleDragger : MonoBehaviour
{
public float springStiffness = 500;
public float springDamping = 50;
public bool drawSpring = true;
private LineRenderer lineRenderer;
private ObiParticlePicker picker;
private ObiParticlePicker.ParticlePickEventArgs pickArgs;
void OnEnable()
{
lineRenderer = GetComponent<LineRenderer>();
picker = GetComponent<ObiParticlePicker>();
picker.OnParticlePicked.AddListener(Picker_OnParticleDragged);
picker.OnParticleDragged.AddListener(Picker_OnParticleDragged);
picker.OnParticleReleased.AddListener(Picker_OnParticleReleased);
picker.solver.OnSimulationStart += Solver_OnEndSimulation;
}
void OnDisable()
{
picker.solver.OnSimulationStart -= Solver_OnEndSimulation;
picker.OnParticlePicked.RemoveListener(Picker_OnParticleDragged);
picker.OnParticleDragged.RemoveListener(Picker_OnParticleDragged);
picker.OnParticleReleased.RemoveListener(Picker_OnParticleReleased);
lineRenderer.positionCount = 0;
}
private void Solver_OnEndSimulation(ObiSolver solver, float timeToSimulate, float substepTime)
{
if (solver != null && pickArgs != null)
{
// Calculate picking position in solver space:
Vector4 targetPosition = solver.transform.InverseTransformPoint(pickArgs.worldPosition);
// Calculate effective inverse mass:
float invMass = solver.invMasses[pickArgs.particleIndex];
if (invMass > 0)
{
// Calculate and apply spring force:
Vector4 position = solver.positions[pickArgs.particleIndex];
Vector4 velocity = solver.velocities[pickArgs.particleIndex];
solver.externalForces[pickArgs.particleIndex] = ((targetPosition - position) * springStiffness - velocity * springDamping) / invMass;
if (drawSpring)
{
lineRenderer.positionCount = 2;
lineRenderer.SetPosition(0, pickArgs.worldPosition);
lineRenderer.SetPosition(1, solver.transform.TransformPoint(position));
}
else
{
lineRenderer.positionCount = 0;
}
}
}
}
void Picker_OnParticleDragged(ObiParticlePicker.ParticlePickEventArgs e)
{
pickArgs = e;
}
void Picker_OnParticleReleased(ObiParticlePicker.ParticlePickEventArgs e)
{
pickArgs = null;
lineRenderer.positionCount = 0;
}
}
}