bbbaaarrr Posted January 10, 2020 Share Posted January 10, 2020 Hi, 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... Cheers, B. Quote Link to comment Share on other sites More sharing options...
Drughi Posted January 10, 2020 Share Posted January 10, 2020 (edited) Hey! 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; return; } } 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 January 10, 2020 by Drughi Quote Link to comment Share on other sites More sharing options...
bbbaaarrr Posted January 11, 2020 Author Share Posted January 11, 2020 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... Thanks!!! B. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.