Obi Official Forum

Full Version: softBody velocity
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi, I am trying to get access to the velocity of my softbody because i can switch between multiple character with different controls. some use rigidbody and one use the softbody, when i switch from the rigidbody to the softbody, i can apply a force to the softbody that is the same as the last velocity of my rigidbody before switching, but when i try to switch from the softbody to a rigidbody, i would like to get the last velocity of my softbody and apply it to the rigidbody's velocity,  but unfortunately,I am unsure where to access the softbody's velocity, i was able to find the solver's velocities but it return an unusable vector4 that is only usable with obi element.
(14-05-2021, 02:17 AM)ReaperQc Wrote: [ -> ]I am unsure where to access the softbody's velocity.

You can't, because a softbody (like any deformable body) doesn't have a single velocity. Different parts of it can move in different directions and with different velocities.

This is also true of rotating rigidbodies, however in a rigidbody you can estimate the velocity at any point using the center of mass' angular velocity (Unity's GetPointVelocity() method). However this doesn't work in a softbody, because it doesn't have a single angular velocity either.

Quote:i was able to find the solver's velocities but it return an unusable vector4 that is only usable with obi element.

That's the only way to get velocities out of a deformable body: query the velocity of its individual particles. However that's far from unusable, you can a lot of things with this. I think you're interested in finding the linear velocity of the softbody's center of mass. This is done by calculating a mass-weighted average of all particles' velocities.

There's code for this in the manual that you can copypaste (http://obi.virtualmethodstudio.com/tutor...icles.html) you just have to swap positions with velocities.

Let me know if you need help with it.

cheers!
I get what you are saying, basically, since every particles in the softbody will not move at the same speed, i can't get a single velocity straight out the box, but i can calculate an average? for all these velocity?, and that information would be store in the solver's velocities or maybe i am a llitle too new to this.

but you meant something like 


and by doing a for loop of the velocities
vector3 finalVelocity = new Vector3( 0, 0 ,0);

for( int actorIndex = 0; actorIndex < solver.velocitiies.size() ; actorIndex++)
{
finalVelocity +=  solver.velocitiies[actorIndex];
}

finalVelocity /= solver.velocities.size();

i didn't test yet, but was this what you meant, am i going in wrong direction with this?

thnak you for your quick answer by the way.
(14-05-2021, 01:39 PM)ReaperQc Wrote: [ -> ]I get what you are saying, basically, since every particles in the softbody will not move at the same speed, i can't get a single velocity straight out the box, but i can calculate an average? for all these velocity?

Yes, that's basically it Sonrisa. The average of all particle velocities in the softbody would be the velocity of the "whole" softbody.


In the real world when we talk about some object's velocity, what are we really talking about? For instance: a person running certainly has some velocity, but where do you measure it? is it the velocity of his right foot? the velocity of his left shoulder? maybe the velocity of his head, or his chest?

What makes sense in most cases is to measure the velocity of the object's center of mass (often abbreviated as CoM). This is the point at which if you hit the object, it would move in a straight line without rotating. Or, the point at which you would be able to balance the object on a stick. In case of a person, this point is likely near the pelvis.

Eg: if you kick a soccer ball right in its center of mass, it will go straight, no effect. If you hit it off-center, it will rotate as it moves, and as a result it will trace a curve mid-air (due to something called Magnus effect, if you want to look it up)

If you discretize an object (that is, divide it up into small chunks, like particles), you can calculate the position of its center of mass by averaging the position of all individual particles, weighted by their mass. If you average their velocities instead, weighting them by their mass, you get the velocity of the center of mass.


(14-05-2021, 01:39 PM)ReaperQc Wrote: [ -> ]but you meant something like 
[color=#1256f1][size=small]and by doing a for loop of the velocities

for( int actorIndex = 0; actorIndex < solver.velocitiies.size() ; actorIndex++)
{
vector3 finalVelocity +=  [color=#1256f1][size=small][font=Tahoma, Verdana, Arial, sans-serif]solver.velocitiies[actorIndex];
}

finalVelocity /= solver.velocities.size();

i didn't test yet, but was this what you meant, am i going in wrong direction with this?

This is fine if all your particles have the same mass, which is often the case. Note that your code iterates trough all particles in the solver, if you have more than one actor in your solver you will want to iterate over the particles in that actor only.

Some code to calculate the velocity of the CoM. Accounts for different particle masses, and multiple actors in the solver:

Code:
using UnityEngine;
using Obi;

[RequireComponent(typeof(ObiActor))]
public class ActorCOM : MonoBehaviour {

    ObiActor actor;
        public Vector4 vel;

    void Awake(){
        actor = GetComponent<ObiActor>();
    }

    void FixedUpdate(){

        if (actor == null || !actor.isLoaded)
            return;

            vel = Vector4.zero;
        float massAccumulator = 0;

        // Iterate over all particles in an actor:
        for (int i = 0; i < actor.solverIndices.Length; ++i){

            // retrieve the particle index in the solver:
            int solverIndex = actor.solverIndices[i];

            // look up the inverse mass of this particle:
            float invMass = actor.solver.invMasses[solverIndex];

            // accumulate it:
            if (invMass > 0)
            {
                massAccumulator += 1.0f / invMass; // TODO: watch out for division by zero here!
                vel += actor.solver.velocities[solverIndex] / invMass;
            }

        }

        vel /= massAccumulator;

    }
}
Thank you for your clear explanation, i read it, understood it, and implemented it, and it works like i want it to. so thank you and have a nice day.
You're welcome, have a nice day too Sonrisa. Let me know if you need help at any point.