Jump to content

RotationFromAxis causing mesh blink


altreality
 Share

Recommended Posts

Hi,

I am building this simple train game where i make a locomotive(or a box that represents one) follow a curving track.

 

Preview here: http://synth2014.github.io/Age-of-Steam/babylon/rk4.html

 

I have only straight and circular segments. Somewhat realistic train movement is achieved by having a front point and a back point for the locomotive. The loco is positioned and oriented using these points. Its parallel to the line joining these points and positioned in the midpoint of the line. These points are marked by the red sphere(front) & grey sphere(back) respectively in the link above

 

The front point is moved along the current curve(straight or circular), then the back point is calculated. The algorithm for that uses sphere intersection with straight lines or circular segments.

 

I use BABYLON.Vector3.RotationFromAxis(xAxis, yAxis, zAxis) to rotate the box representing the locomotive. The code for it is:

// forwardVecWS is the line joining the front point and the back point,// and pointing towards the front point.    var xAxis = forwardVecWS.clone();  // the new x-axis of the loco                                        // relative to World Space is simply the forward axis    var yAxis = new BABYLON.Vector3(0, 0, 0);    var zAxis = new BABYLON.Vector3(0, 0, 0);    zAxis = BABYLON.Vector3.Cross(xAxis, frontSegment.upAxis).normalize();    yAxis = BABYLON.Vector3.Cross(zAxis, xAxis).normalize();    xAxis = BABYLON.Vector3.Cross(yAxis, zAxis).normalize();    console.debug("x(" + xAxis.x + "," + xAxis.y + "," + xAxis.z +                "), y(" + yAxis.x + "," + yAxis.y + "," + yAxis.z +               "), z(" + zAxis.x + "," + zAxis.y + "," + zAxis.z + ")");

I seem to be calculating the local-axes of the box in world space correctly as can be seen from the developer tools view:

GET http://synth2014.github.io/Age-of-Steam/babylon/js/utils.js babylon.2.1.debug.js:4703BJS - [19:29:02]: Babylon.js engine (v2.1.0) launchedbabylon.2.1.debug.js:3072 GET http://synth2014.github.io/Age-of-Steam/babylon/scenes/dummy.babylon.manifest?1440770342473 404 (Not Found)Database.checkManifestFile @ babylon.2.1.debug.js:3072Database @ babylon.2.1.debug.js:3032SceneLoader.Append @ babylon.2.1.debug.js:18734SceneLoader.Load @ babylon.2.1.debug.js:18684startGame @ mainRK4.js:34Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:466 x(0.9994770317996606,0,0.03233671141195854), y(0,1,0), z(-0.03233671141195854,0,0.9994770317996606)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:466 x(0.9994350227871951,0,0.033610046509320576), y(0,1,0), z(-0.03361004650932058,0,0.9994350227871953)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:466 x(0.9993905467884464,0,0.03490752053483967), y(0,1,0), z(-0.03490752053483967,0,0.9993905467884464)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1

Yet somehow, the box keeps disappearing for some the values. I had faced this earlier if the Vector3 for the axes were not normalized or the frame supplied wasn't orthogonal. From what I can see, thats not the case here.

 

Anyone has any idea what may be going on? The code in question is here: https://github.com/synth2014/Age-of-Steam/blob/gh-pages/babylon/js/FastLoco.js#L451

 

There are some steps for the calculation that should be irrelevant if the final x,y & z axis values are normalized and the frame is orthogonal.

Link to comment
Share on other sites

Well, I added some code to check the orthogonality and normalization and they seem to be correct:

 

Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9994770317996606,0,0.03233671141195854), y(0,1,0), z(-0.03233671141195854,0,0.9994770317996606)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9994350227871951,0,0.033610046509320576), y(0,1,0), z(-0.03361004650932058,0,0.9994350227871953)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=0.9999999999999999, y=1, z=1.0000000000000002Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9993905467884464,0,0.03490752053483967), y(0,1,0), z(-0.03490752053483967,0,0.9993905467884464)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9993435115829765,0,0.03622907474674426), y(0,1,0), z(-0.036229074746744264,0,0.9993435115829767)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=0.9999999999999999, y=1, z=1.0000000000000002Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9992938168341208,0,0.037574827173187275), y(0,1,0), z(-0.037574827173187275,0,0.9992938168341208)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1

The dot products of the axes with each other are 0. The lengths of each axis is 1(within floating point precision)

 

 var xDotz = BABYLON.Vector3.Dot(xAxis, zAxis);    var xDoty = BABYLON.Vector3.Dot(xAxis, yAxis);    var yDotz = BABYLON.Vector3.Dot(yAxis, zAxis);    console.debug("x(" + xAxis.x + "," + xAxis.y + "," + xAxis.z +                "), y(" + yAxis.x + "," + yAxis.y + "," + yAxis.z +               "), z(" + zAxis.x + "," + zAxis.y + "," + zAxis.z + ")");    console.debug("x.z=" + xDotz + ", x.y=" + xDoty + ", y.z=" + yDotz);    console.debug("Length x=" + xAxis.length() + ", y=" + yAxis.length() + ", z=" + zAxis.length());
Link to comment
Share on other sites

Thanks Jerome. Seems you were spot on. The rotation angles sometimes have a NaN in one of the angles. 

 

Updated http://synth2014.github.io/Age-of-Steam/babylon/rk4.html to print out the rotation and position too:

 

Failed to load resource: the server responded with a status of 404 (Not Found)babylon.2.1.debug.js:4703BJS - [23:17:20]: Babylon.js engine (v2.1.0) launchedhttp://synth2014.github.io/Age-of-Steam/babylon/scenes/dummy.babylon.manifest?1440784040518 Failed to load resource: the server responded with a status of 404 (Not Found)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9994770317996606,0,0.03233671141195854), y(0,1,0), z(-0.03233671141195854,0,0.9994770317996606)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=0, y=-0.032342349615338765, z=NaNFastLoco.js:483 Position(15.050137463756561, 0, 0.3233671188354492)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9994350227871951,0,0.033610046509320576), y(0,1,0), z(-0.03361004650932058,0,0.9994350227871953)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=0.9999999999999999, y=1, z=1.0000000000000002FastLoco.js:482 Rotation x=-1.4901161193847656e-8, y=-0.03361637757690891, z=NaNFastLoco.js:483 Position(15.147261049621582, 0, 0.3361004590988159)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9993905467884464,0,0.03490752053483967), y(0,1,0), z(-0.03490752053483967,0,0.9993905467884464)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=0, y=-0.0349146137642364, z=-1.4901161193847656e-8FastLoco.js:483 Position(15.244280262470246, 0, 0.34907519817352295)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9993435115829765,0,0.03622907474674426), y(0,1,0), z(-0.036229074746744264,0,0.9993435115829767)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=0.9999999999999999, y=1, z=1.0000000000000002FastLoco.js:482 Rotation x=0, y=-0.036237004818494976, z=NaNFastLoco.js:483 Position(15.341193910209656, 0, 0.36229074001312256)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9992938168341208,0,0.037574827173187275), y(0,1,0), z(-0.037574827173187275,0,0.9992938168341208)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=NaN, y=-0.03758367457586275, z=NaNFastLoco.js:483 Position(15.438000300746918, 0, 0.37574827671051025)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9992413735216208,0,0.03894454316877913), y(0,1,0), z(-0.03894454316877913,0,0.9992413735216208)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=0, y=-0.03895439427871502, z=0FastLoco.js:483 Position(15.534699540012358, 0, 0.389445424079895)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9991860780093766,0,0.04033833799551142), y(0,1,0), z(-0.04033833799551142,0,0.9991860780093766)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=NaN, y=-0.04034928564659717, z=0FastLoco.js:483 Position(15.631288637889863, 0, 0.40338337421417236)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9991278314631757,0,0.041756153985874), y(0,1,0), z(-0.041756153985874,0,0.9991278314631757)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=0, y=-0.04176829769043192, z=0FastLoco.js:483 Position(15.727766104263305, 0, 0.41756153106689453)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9990665362840676,0,0.04319787121324316), y(0,1,0), z(-0.04319787121324316,0,0.9990665362840676)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=NaN, y=-0.04321131744913273, z=NaNFastLoco.js:483 Position(15.824132141109466, 0, 0.431978702545166)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9990020884231274,0,0.044663489857264344), y(0,1,0), z(-0.044663489857264344,0,0.9990020884231274)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=0, y=-0.044678352527951666, z=-1.4901161193847656e-8FastLoco.js:483 Position(15.920383662265778, 0, 0.4466348886489868)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9989343793541373,0,0.046153068634325126), y(0,1,0), z(-0.046153068634325126,0,0.9989343793541373)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=NaN, y=-0.04616946951298599, z=NaNFastLoco.js:483 Position(16.016519773662566, 0, 0.4615306854248047)Integrator.js:37 Verlet: Position: 0.1, velocity:0.1FastLoco.js:470 x(0.9988633097128881,0,0.047666429585350605), y(0,1,0), z(-0.047666429585350605,0,0.9988633097128881)FastLoco.js:474 x.z=0, x.y=0, y.z=0FastLoco.js:475 Length x=1, y=1, z=1FastLoco.js:482 Rotation x=0, y=-0.04768449845694656, z=0FastLoco.js:483 Position(16.112539283206942, 0, 0.47666430473327637)

I wonder why there should be a NaN returned for a valid(as far as I can see),  set of axes.

Maybe these are some sort of floating point issue. Sometimes z=1.0000000000000002 for example.

I don't think that such a small difference should throw off the calculation leading to a NaN though!

 

Setting up a Play Ground here: http://www.babylonjs-playground.com/#1HH4OJ#11

Anyone knows how to print debug values in PG?

 

Link to comment
Share on other sites

Thanks Jerome.

 

I will try a temporary fix in that function till its in the mainline.

 

One thing I have noticed with the Cross product function,

var cross =  Vector3.Cross(u, v);

Even if u & v are unit vectors, the cross vector isn't necessarily a unit vector and should be normalized anyway to be safe.

 

----------------

 

Hmm, normalizing in that function does not fix the issue. I will check what else is going on there.

u1 = new Vector3(x, y, z);u1.normalize();v1 = Vector3.Cross(w, u1); // v1 image of v through rotation around wv1.normalize();cross = Vector3.Cross(u, u1); // returns same direction as w (=local z) if positive angle : cross(source, image)cross.normalize();
Link to comment
Share on other sites

Actually I guess the problem is in the dot product. 

If the dot product isn't in the range [-1, 1],  Math.acos(dot) will return NaN, what is happening in your PG.

 

So as u is already normalized, if we normalize u1, then dot(u, u1) should be between -1 and 1 in all cases.

 

The other solution would be to compare parameter axis coordinate values not to zero (limit case, as currently) but to epsilonToZero (almost zero) to avoid near limit cases going bad due to floating computation approximations. 

 

I'll check it as monday.

Link to comment
Share on other sites

Ok, thank you for the fix :-)

I will PR it in the mainstream ... unless you want to do it to get credit of course

 

I was wrong when I said initially that axis1, axis2, axis3 parameters should be normalized when passed to RotationFromAxis()

Axis1, axis2 and axis3 are vectors that belong to the user, they aren't modified by the function but just copied and these copies only are then normalized.

So they don't need to be normalized, but they have to be orthogonal and left-handed oriented.

Link to comment
Share on other sites

Ok

I'm on it

 

There's a weird approximation problem in the Dot product function ... unless it is in the BJS normalize() method or a genuine js approximation problem

With your set of values, if u and u1 are explicitly normalized Vector3.Dot(u, u1) returns here 1.0000000002 what shouldn't be possible ... It shoud be 0.0000009 or 1.0, but not greater than 1.0

 

that's why you had then to clamp the dot product although it shoudn't be necessary with normalized vectors

 

Well, I guess that I will PR a fix with the clamping stuff before we investigate where the approximation is wrong (dot, normalize, js math)

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...