Jump to content

rbds to follow point positions *and* orientations *SOLVED*

Recommended Posts


I need to animate a group of packed RBD prims scattered on animated set of points. The points are scattered on animated deforming geometry. They derive of course @P as well as @orient based on surface normal and tangent vectors.

Now I want to simulate RBDs that would try to follow those positions and orientations closely, but retain their dynamic properties as well (so they collide properly).

So far I managed to achieve reliable position following based on http://www.tokeru.com/cgwiki/index.php?title=HoudiniDops#RBD_follow_targets but now I'd like to set the torque accordingly.

My way of thinking is that I should somehow calculate the torque based  rbd @orient with original input point @orient (analogously to how I calculated the position delta), but anything I do produces just rotational chaos...

Anyone with C4D background should see here that MoGraph's dynamic rotation following is what I'm after...


Share this post

Link to post
Share on other sites

this is something I'm interested in as well. I think if you check the GuidedRBDBulletSolver example files the answer should be burried in this setup, but I haven't had the time to dig deeper.

I think this is the relevant wrangle (/obj/guidedrbdbulletsolver_example1/animated_guide_simulation/rbdbulletsolver4/dopnet/guide_geometry):

int dotQuat(vector4 q1; vector4 q2){
    int dotQ = (q1.w*q2.w+q1.x*q2.x+q1.y*q2.y+q1.z*q2.z) < 0;
    return dotQ;

// Unguide pieces with no guided neighbours
int useneighbours = point(0, "__guide_useneighbours", @ptnum);
int guide_count = point(0, "__guide_neighbourcount", @ptnum);
if (chi("useneighbours") && guide_count && useneighbours)
    int ns[] = point(0, "__guide_neighbours", @ptnum);
    int newns[];
    foreach(int n; ns)
        int guided = inpointgroup(0, "__guided", n);
        if (guided) append(newns, n);
    setpointattrib(0, "__guide_neighbours", @ptnum, newns);
    int num = len(newns);
    if (num < min(guide_count, chi("minneighbours")))
        i@group___guided = 0;

int pt = findattribval(1, "point", "name", s@__guide_name, 0);
if(pt >= 0)
    vector restpos = primintrinsic(0, "pivot", @primnum) + v@__guide_pivot_offset;
    int pr1 = pointprims(1, pt)[0];
    vector restpos1 = primintrinsic(1, "pivot", pr1);
    vector pos1 = point(1, "P", pt); 
    vector offset = restpos - restpos1; 
    matrix3 xform1 = primintrinsic(1, "transform", pr1);
    vector pos = pos1 + offset * xform1;

    float timeMult = 1.0/@TimeInc; 
    timeMult *= 1.0/chf("timescale");
    matrix3 xform = primintrinsic(0, "transform", @primnum);
    rotate(xform, v@__guide_rot_offset, 0);
    vector4 quat = quaternion(xform);
    vector4 quat1 = quaternion(xform1);
    int reverse = dotQuat(quat1, quat) ? -1 : 1;
    quat *= reverse;
    if(i@active && s@__guide_name!="")
        float bias = ch("bias");
        if (haspointattrib(0, "__guide_blend"))
            bias *= clamp(float(point(0, "__guide_blend", @ptnum)), 0, 1);
        v@w = lerp(v@w, qconvert(qmultiply(quat1, qinvert(quat))) * timeMult, bias);
        v@v = lerp(v@v, (pos - @P) * timeMult,  bias);
        int hasAdiff = haspointattrib(0, "__guide_angleDiff");
        int hasLdiff = haspointattrib(0, "__guide_linearDiff");
        if(hasAdiff && hasLdiff)
            setpointattrib(0, "__guide_prP", @ptnum, pos, "set");
            setpointattrib(0, "__guide_prQ", @ptnum, quat1, "set");
} else {
    i@group___guided = 0;


Edited by Drughi

Share this post

Link to post
Share on other sites

Hey Johannes,

There you go...

First thing to remember is to set proper piece transform attributes before the sim. It messes them up otherwise...

Per http://www.tokeru.com/cgwiki/index.php?title=HoudiniDops#RBD_extract_correct_transform_attributes

matrix m4 = primintrinsic(0,'packedfulltransform',@ptnum);
matrix3 m3 = matrix3(m4);
@orient = quaternion(m3);
@scale = cracktransform(0,0,2,0,m4);
v@pivot = primintrinsic(0,'pivot',@ptnum);

Put the above to a wrangle before the dop.

Then inside the DOPnet put the following to a geometry wrangle:

int dotQuat( vector4 q1; vector4 q2 ) {
    int dotQ = (q1.w*q2.w+q1.x*q2.x+q1.y*q2.y+q1.z*q2.z) < 0;
    return dotQ;

vector4 q = @orient;
vector4 q1 = point( 1, "orient", @ptnum );

int reverse = dotQuat(q1, q) ? -1 : 1;
q *= reverse;

v@w = qconvert(qmultiply(q1, qinvert(q)));

As you can see the above is directly pasted from the example code.

That's only for the rotation part. The @P part is trivial as setting @P or @v directly...



  • Like 1

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now