Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to tune/set constraints of a particle group from an obiActor during runtime
#4
Awesome!
Thanks for the detailed answer Sonrisa 

Got it to work by looping over the constraints and particle indices as you described and a minimal working example is implemented below.

Performance decrease did not seem too bad (so far).
Since it is crucial for my application, I also looked into initializing at startup only.
Here I noticed that the solverBatchOffsets returned an empty list when called in the void start()?

Code:
    void Start()
    {
        obiSoftbody = obiActor.GetComponent<ObiSoftbody>();
        particlesInGroup = obiParticleGroup.particleIndices;
        List<int> offsets = obiSoftbody.solverBatchOffsets[(int)Oni.ConstraintType.ShapeMatching];
        Debug.Log(offsets.Count); // returns 0
    }
I circumvent this problem by setting the constraints only in the first update of the updateloop.


Minimal working example is given below:


Code:
using Obi;
using System.Collections.Generic;
using UnityEngine;

public class ParticleGroupTest : MonoBehaviour
{
    [SerializeField] private ObiActor obiActor = null;
    [SerializeField] private ObiParticleGroup obiParticleGroup = null;

    [SerializeField] private bool setConstraintsEveryUpdate = false;

    [SerializeField] private float deformationResistance = 0.1f;
    [SerializeField] private float plasticYield = 0.0f;
    [SerializeField] private float plasticCreep = 0.0f;
    [SerializeField] private float plasticRecovery = 0.0f;
    [SerializeField] private float maxDeformation = 0.0f;


    private ObiSoftbody obiSoftbody = null;
    private List<int> particlesInGroup;

    private bool updatedOnce = false;


    void Start()
    {
        obiSoftbody = obiActor.GetComponent<ObiSoftbody>();
        particlesInGroup = obiParticleGroup.particleIndices;
    }


    void Update()
    {
        if (setConstraintsEveryUpdate == true) SetConstraints(); //constantly update the constraint of the given particle group;
        else if (setConstraintsEveryUpdate == false && updatedOnce == false)
        {
            // set constraints only in the first loop, need to do this in the update since the line:
            // List<int> offsets = obiSoftbody.solverBatchOffsets[(int)Oni.ConstraintType.ShapeMatching];
            // returns an empty list when being called in: void Start()
            SetConstraints();
            updatedOnce = true;
        }
    }


    void SetConstraints()
    {
        // Sets the all the constraints that are tied to the particles in the particle group

        // get constraints stored in the actor:
        var actorConstraints = obiSoftbody.GetConstraintsByType(Oni.ConstraintType.ShapeMatching)
                    as ObiConstraints<ObiShapeMatchingConstraintsBatch>;
        // get runtime constraints in the solver:
        var solverConstraints = obiSoftbody.solver.GetConstraintsByType(Oni.ConstraintType.ShapeMatching)
                    as ObiConstraints<ObiShapeMatchingConstraintsBatch>;

        // get batches and offsets
        List<ObiShapeMatchingConstraintsBatch> actorSoftBodyBatches = actorConstraints.batches;
        List<ObiShapeMatchingConstraintsBatch> solverSoftBodyBatches = solverConstraints.batches;
        List<int> offsets = obiSoftbody.solverBatchOffsets[(int)Oni.ConstraintType.ShapeMatching];

        for (int i_batch = 0; i_batch < actorSoftBodyBatches.Count; ++i_batch) // loop over batches   
            for (int i_constraint = 0; i_constraint < actorConstraints.batches[i_batch].activeConstraintCount; ++i_constraint) // constraints
                if (ConstraintIsReferencedInParticleGroup(actorConstraints.batches[i_batch], i_constraint, particlesInGroup))
                {
                    int index = i_constraint + offsets[i_batch];

                    solverSoftBodyBatches[i_batch].materialParameters[index * 5] = deformationResistance;
                    solverSoftBodyBatches[i_batch].materialParameters[index * 5 + 1] = plasticYield;
                    solverSoftBodyBatches[i_batch].materialParameters[index * 5 + 2] = plasticCreep;
                    solverSoftBodyBatches[i_batch].materialParameters[index * 5 + 3] = plasticRecovery;
                    solverSoftBodyBatches[i_batch].materialParameters[index * 5 + 4] = maxDeformation;
                }
    }

    bool ConstraintIsReferencedInParticleGroup(ObiShapeMatchingConstraintsBatch actorSoftBodyBatch,
                                                                        int constraint_i, List<int> particlesInGroup)
    {
        // If constraint_i is reference by any (maybe even single) particle in the particle group, return true, else false
        int firstIndex = actorSoftBodyBatch.firstIndex[constraint_i]; // first index of particle affected by constraint i
        int numIndices = actorSoftBodyBatch.numIndices[constraint_i]; // amount of particles affected by constraint i

        for (int i = firstIndex; i < firstIndex + numIndices; ++i) // loop over particles affected by constraint i
        {
            int particle_index = actorSoftBodyBatch.particleIndices[i]; // get particle index
            if (particlesInGroup.Contains(particle_index)) return true;
        }
        return false;
    }
}
Reply


Messages In This Thread
RE: How to tune/set constraints of a particle group from an obiActor during runtime - by Jschol - 19-10-2021, 03:29 PM