142 lines
5.0 KiB
C#
142 lines
5.0 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Obi
|
|
{
|
|
/**
|
|
* ObiConstraintBatch are groups of constraints of the same type that are added/removed together from the solver.
|
|
* Batches can be of two main types:
|
|
*
|
|
* - Cooked: cooked batches reorder their constraints for better data locality and to enable the vectorized code path.
|
|
* Once the cooking proccess has finished constraints can't be added or removed, only activated/deactivated,
|
|
* but they yield very good performance.
|
|
*
|
|
* - Raw: raw batches allow for efficient addition/removal of constraints on the fly, and very efficient activation/deactivation.
|
|
* They do not require cooking but perform worse than cooked batches, as they don't do anyhting special regarding
|
|
* vectorization or improving cache data locality.
|
|
*
|
|
* ObiBatchedConstraints hold parameters for a group of batches of the same type.
|
|
*/
|
|
[Serializable]
|
|
public abstract class ObiConstraintBatch
|
|
{
|
|
protected IntPtr batch; /**< pointer to constraint batch in the solver.*/
|
|
|
|
public float maxYoungModulus = 0.02f; /**< default value of max stiffness (N/m2)*/
|
|
public float minYoungModulus = 0.0001f; /**< default value of min stiffness (N/m2)*/
|
|
|
|
[SerializeField][HideInInspector] protected int constraintCount = 0; /**< amount of constraints in this batch*/
|
|
[SerializeField][HideInInspector] protected bool cooked = false; /**< returns whether this batch supports cooking or not.*/
|
|
[SerializeField][HideInInspector] protected bool sharesParticles = false; /**< returns whether this batch must be done serially or can benefit from multithreading.*/
|
|
|
|
[SerializeField][HideInInspector] protected List<int> activeConstraints = new List<int>(); /**< list of active constraint indices.*/
|
|
[SerializeField][HideInInspector] protected List<int> phaseSizes = new List<int>(); /**< phase sizes for cooked batches.*/
|
|
|
|
public IntPtr OniBatch{
|
|
get{return batch;}
|
|
}
|
|
|
|
public int ConstraintCount{
|
|
get{return constraintCount;}
|
|
}
|
|
public bool IsCooked{
|
|
get{return cooked;}
|
|
}
|
|
public bool SharesParticles{
|
|
get{return sharesParticles;}
|
|
}
|
|
public IEnumerable<int> ActiveConstraints
|
|
{
|
|
get{return activeConstraints.AsReadOnly();}
|
|
}
|
|
|
|
// Implement this method to provide info about the batch type:
|
|
public abstract Oni.ConstraintType GetConstraintType();
|
|
|
|
// Implement these method to provide a custom clearing/cooking/swapping implementation.
|
|
public abstract void Clear();
|
|
public virtual void Cook(){}
|
|
|
|
// Implement these methods to perform custom actions when adding/removing the batch from the solver.
|
|
protected abstract void OnAddToSolver(ObiBatchedConstraints constraints);
|
|
protected abstract void OnRemoveFromSolver(ObiBatchedConstraints constraints);
|
|
|
|
// Implement these methods to push/pull constraint data to/from the solver.
|
|
public abstract void PushDataToSolver(ObiBatchedConstraints constraints);
|
|
public abstract void PullDataFromSolver(ObiBatchedConstraints constraints);
|
|
|
|
public abstract List<int> GetConstraintsInvolvingParticle(int particleIndex);
|
|
|
|
protected float StiffnessToCompliance(float stiffness){
|
|
float minCompliance = 1.0f/Mathf.Max(minYoungModulus,0.00001f);
|
|
float maxCompliance = 1.0f/Mathf.Max(maxYoungModulus,minYoungModulus);
|
|
return Mathf.Lerp(minCompliance,maxCompliance,stiffness);
|
|
}
|
|
|
|
public void ActivateConstraint(int index){
|
|
if (!activeConstraints.Contains(index))
|
|
activeConstraints.Add(index);
|
|
}
|
|
|
|
public void DeactivateConstraint(int index){
|
|
activeConstraints.Remove(index);
|
|
}
|
|
|
|
public ObiConstraintBatch(bool cooked, bool sharesParticles){
|
|
this.cooked = cooked;
|
|
this.sharesParticles = sharesParticles;
|
|
}
|
|
|
|
/**
|
|
* This constructor allows to override min/max young modulus, used to map a stiffness range of (0,1) to physical compliance values.
|
|
*/
|
|
public ObiConstraintBatch(bool cooked, bool sharesParticles, float minYoungModulus, float maxYoungModulus){
|
|
this.cooked = cooked;
|
|
this.sharesParticles = sharesParticles;
|
|
this.maxYoungModulus = maxYoungModulus;
|
|
this.minYoungModulus = minYoungModulus;
|
|
}
|
|
|
|
public void AddToSolver(ObiBatchedConstraints constraints){
|
|
|
|
// create a constraint batch:
|
|
batch = Oni.CreateBatch((int)GetConstraintType(),cooked);
|
|
Oni.AddBatch(constraints.Actor.Solver.OniSolver,batch,sharesParticles);
|
|
|
|
// custom stuff:
|
|
OnAddToSolver(constraints);
|
|
}
|
|
|
|
public void RemoveFromSolver(ObiBatchedConstraints constraints){
|
|
|
|
// custom stuff:
|
|
OnRemoveFromSolver(constraints);
|
|
|
|
// remove the constraint batch from the solver
|
|
// (no need to destroy it as its destruction is managed by the solver)
|
|
Oni.RemoveBatch(constraints.Actor.Solver.OniSolver,batch);
|
|
|
|
// important: set the batch pointer to null, as it could be destroyed by the solver.
|
|
batch = IntPtr.Zero;
|
|
|
|
}
|
|
|
|
public void SetActiveConstraints(){
|
|
Oni.SetActiveConstraints(batch,activeConstraints.ToArray(),activeConstraints.Count);
|
|
}
|
|
|
|
public void Enable(){
|
|
Oni.EnableBatch(batch,true);
|
|
}
|
|
|
|
public void Disable(){
|
|
Oni.EnableBatch(batch,false);
|
|
}
|
|
|
|
}
|
|
}
|
|
|