Footroll – or just rolling an object…
April 10th, 2006 by Helge Mathee - Viewed 8056 times - Popularity: 19% [?]In this post I would like to demonstrate a technique using a scripted operator to roll something along its edges / boundary. The post includes the full code as well as images / movies for further explanation.
I created an object, and extracted a curve from the boundary edges. Of course, you can always go the other route and create the curve first, and then afterwards create the mesh off the curve.
What I now want to do is roll the object along this curve, like a footroll. Here’s a picture and a movie for further explanation:

The code is fairly simple, and I tried to comment / document as much as possible.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | // get the transform of the control object var inXf = Inlocal1.value.transform; // get the control object's rotation var inRot = XSIMath.CreateRotation(); inXf.GetRotation(inRot); // get the value of the operator's roll parameter var roll = In_UpdateContext.parameters("roll").value; // get the value of the operator's distance parameter var distance = In_UpdateContext.parameters("distance").value; // set a vector which is going to start out as the y axis var yAxis = XSIMath.CreateVector3(); yAxis.Set(0,1,0); // multiply y by the rotation, so it points along the // control object's y axis yAxis.MulByRotationInPlace(inRot); // create the output transform of the curve var xf = XSIMath.CreateTransform(); // if there is any rotation (if y doesn't point straight up) if(yAxis.x!=0||yAxis.z!=0) { // store the height of y temporarily var yAxisHeight = yAxis.y; // remove the y part of yAxis yAxis.y = 0; // normalize it (puts its length to 1) yAxis.NormalizeInPlace(); // multiply the length of y by the distance param yAxis.ScaleInPlace(distance ); // get the curve's geometry var geo = Incrvlist.value.Geometry; // get the closest curve position to the resulting // position of the yAxis (on the ground plane) var vbArgs = new VBArray(geo.GetClosestCurvePosition2(yAxis)); var args = vbArgs.toArray(); // change the length of y relatively to the distance // of the closest point on the curve // this removes the unwanted jittery behaviour yAxis.NormalizeInPlace(); yAxis.ScaleInPlace(args[3].length()); // now get the closest position again var vbArgs = new VBArray(geo.GetClosestCurvePosition2(yAxis)); var args = vbArgs.toArray(); // get the U value of the curve for the closest point var curveU = args[2]; // now evaluate the curve for the given U // note: this is using the hard coded subcurve index // 0, so it never works for multi-curve-curvelists var vbArgs = new VBArray(geo.curves(0).EvaluatePosition(curveU)); var args = vbArgs.toArray(); // get the position and tangent var curvePos = args[0]; var curveTan = args[1]; // calculate the angle between the former Y axis and // the ground plane var angle = Math.acos(yAxisHeight)/2; // negate (turn around) the yAxis // as we want to move the object position // relatively to the position on the curve curvePos.NegateInPlace(); // define a quaternion for the rotation var quat = XSIMath.CreateQuaternion(); // the rotation for the tilt is a rotation around // the tangent of the curve on the given position // with an angle defined by the overall rotation // of the control object quat.Set( Math.cos(angle), Math.sin(angle) * curveTan.x, Math.sin(angle) * curveTan.y, Math.sin(angle) * curveTan.z ); // create a rotation for the tilt var rotTilt = XSIMath.CreateRotation(); rotTilt .SetFromQuaternion(quat); // now we rotation the position of the curveobject // around the tangent of the curve, by using // our rotTilt rotation var centerPos = XSIMath.CreateVector3(); centerPos.MulByRotation(curvePos,rotTilt); // define an additional rotation for the roll var rotRoll = XSIMath.CreateRotation(); // define an eulerangles vector for the rotation var rotAngles = XSIMath.CreateVector3(); // set the y rotation by the given roll param rotAngles.y = XSIMath.DegreesToRadians(roll); // set the rotations euler angles by the vector rotRoll .SetFromXYZAngles(rotAngles); // rotate the position of the curveobject again // by the rotRoll rotation centerPos.MulByRotationInPlace(rotRoll); // for the output transform, create a new rotation // and multiply both rotations together var rot = XSIMath.CreateRotation(); rot.Mul(rotTilt,rotRoll); // now substract the curvePosition off the center // position, to put it back in its own space centerPos.SubInPlace(curvePos); // for the output transform, set the // translation and rotation xf.SetTranslation(centerPos); xf.SetRotation(rot); } // output the transform Out.value.transform = xf; |
If you want to checkout the scene, here it is (XSI 5.1).
You can find the scripted operator below the local kinematics of the curve. Enjoy!
Popularity: 19% [?]




Very nice and utile Helge! Thanks for the tutorial and script explanations!
This will makes my life easier! thanks a lot Helge
Wow, this is great ! Very nice and elegant solution ! Thanks for posting this blog :)
thanks!
Thanks for share!
Plz, explain a little bit how to use this magic code?
Dang… What kind of a wild mind are you man? Wonderful effort and very generous share Helge, as always…
Cheers
AJ