touslecoq Posted October 19, 2016 Share Posted October 19, 2016 Folks I am not sure whether this is a mathematical limitation or a babylon/javscript limitation (or a touslecoq limitation!). As part of the app I am developing I am comparing the normals of faces on 2 meshes in order to calculate the angle and axis of rotation required those faces. This works fine in most cases - however I found in certain cases that the rotation was seemingly random. Some investigation using the console and I determined that this occurs when the faces being compared are exactly 180 degrees apart. I have created a playground to recreate/illustrate the issue. This basically creates a mesh and rotates randomly in 3 dimensions; creates a second mesh with exactly the same rotation. calls a function to calculate the normals of a given face (0-12) for each mesh and calculate the angle between those normals and the axis of rotation (ie a vector that is 90 degrees to those normals). I call the function twice: comparing Mesh 1, Face 0 with Mesh 2, Face 2 - these faces are on opposite sides of the meshes. The angle (180 degrees) is correctly determined but the axis is calculated as (0,0,0). This I believe is the cause of the strange behaviour I have seen in my app. comparing Mesh 1, Face 0 with Mesh 2, Face 4 - these faces are on 2 perpendicular sides of the meshes and the angle (90 degrees) and axis are correctly determined See the console log for the outputs which include the vertices, normals of each selected face and the calculated angle and axis. Look out for axis = (0,0,0) for the second test. Re-run several times and it gets it wrong consistently. So ... million dollar (since pound is worthless now) question ... is there a workaround to calculate the normal to 2 vectors that are 180 degrees apart? http://www.babylonjs-playground.com/#VFKAZ#12 Cheers Rich Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 20, 2016 Share Posted October 20, 2016 Hey Rich, this is expected as there can be an infinity of vectors perpendicular to 2 vectors tat are 180 degrees apart. Look at the code of the cross function: Tmp.Vector3[0].x = left.y * right.z - left.z * right.y; Tmp.Vector3[0].y = left.z * right.x - left.x * right.z; Tmp.Vector3[0].z = left.x * right.y - left.y * right.x; Pryme8 1 Quote Link to comment Share on other sites More sharing options...
touslecoq Posted October 20, 2016 Author Share Posted October 20, 2016 Hi Deltakosh, thanks. What you say (with a clear head and a night's sleep) makes perfect sense. So there are 360 degrees worth (infinite as you said) of potential axis and actually any of them would do as what I want to do is to flip the mesh 180 degrees around an axis that is perpendicular to the normal of the selected face. In which case I can choose either of the vectors that were already used to calculate the normal of that face as the axis. I have updated the playground: - swapped the tests around so it does the 90 degree test function call first and then the 180 degree test - added a condition that if the returned rotation axis was 0,0,0 then use the m1Vector1 that was one of the vectors used to calculate normal to selected face of mesh 1 - added a condition so that for the second test it now performs the rotation - should see the red and blue faces parallel if successful - added additional log trace to show where the alternative rotation axis has been used and to show the vectors used to calculate the face normals. Now for the weird bit. If I comment out line 33 (the random rotation of the meshes) then it works fine. Mesh 1 is rotated 180 degrees so that it faces opposite but parallel direction to mesh2. The log trace shows that in the second test the faces were 180 degrees apart, that a rotation axis of 0,0,0 was returned and that the alternative was used succesfully. However if I uncomment that line so that the mesh1 is randomnly rotated and mesh 2 starts off with same rotation as mesh 1, the rotation does not work and and the boxes do not end up parallel but opposite. Quite perplexing - if anyone has time can you find my error please - it could be a BABYLON.Space.LOCAL vs .WORLD issue although I have tried both and it didn't work. I also tried normalizing the vector without luck. http://www.babylonjs-playground.com/#VFKAZ#29 Thanks Rich Quote Link to comment Share on other sites More sharing options...
touslecoq Posted October 20, 2016 Author Share Posted October 20, 2016 Ok .. so I just realised I had made a schoolboy error in previous version in the test for whether the returned axis was 0,0,0 - I used the assignment (=) rather than equality (==) operator. I fixed that and it was no longer matching axis 0,0,0 so for ease i have changed it to check for rotation angle = Math.PI. I was trying to avoid this because a> requires exact comparison of floating point numbers to many decimal places; and b> in my own app the error occurs even at 179.999999... degrees. However for purposes of this it is fine.T Rather than the random initial rotation I have rotated both meshes only 90 degrees round x axis to make debugging easier. Results are weird. Although the trace identifies correctly that the angle is 180 degrees and chooses the alternative axis and states it is rotating Mesh 1 around that axis 180 degrees. It only actually seems to rotate it 90 degrees. Confused! http://www.babylonjs-playground.com/#VFKAZ#39 GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
touslecoq Posted October 22, 2016 Author Share Posted October 22, 2016 Nudge. Still cannot fathom this ... :/. Quote Link to comment Share on other sites More sharing options...
adam Posted October 22, 2016 Share Posted October 22, 2016 Yesterday I was thinking about how to do this with the Mesh.lookAt function. You could figure out the rotation to the face and then the rotation to the point (using Mesh.lookAt) and then get the difference of those to get the final rotation. touslecoq 1 Quote Link to comment Share on other sites More sharing options...
touslecoq Posted October 23, 2016 Author Share Posted October 23, 2016 Hi Adam thanks for your reply - not 100% sure i understood your suggestion though. I could use Mesh.lookAt to get the face to look at the other mesh but they wouldn't necessary be pointing in the same/opposite (i.e. parallel) direction afterwards. So for example if you had one cube at the world origin and another at 100,100,100 with both cubes in their default orientation. I *think* using mesh.lookat on the second mesh would result in that mesh rotating to roughly PI/4, PI/4, PI/4 (i.e. diagonally back towards mesh 1) as opposed to 0,0,PI (i.e. i.e. 180 degree rotation around the z axis so it faces back along the x-axis). Possibly creating submeshes (i.e. for each face) and using align mesh on those submeshes may work (not sure how mesh.lookAt works in relation to submeshes)? I could have misunderstood how mesh.lookAt works so the above may not be true. The reason for this desired behaviour is that I want to rotate the second mesh so that its specified face faces the specified face of the other mesh so that I can then translate the position and align or "mate" the 2 faces. The strange thing is - my existing solution seems to work for all other angles its just the exact 180 degree edge case that is the problem. Thanks, Rich. Quote Link to comment Share on other sites More sharing options...
touslecoq Posted October 24, 2016 Author Share Posted October 24, 2016 UPDATE ... So I found what to me looks like weird behaviour. I created a really simple, cut down, version of the playground to demonstrate it. Not sure if this is the cause of all of my woes but it does explain some of the odd behaviour seen in posts above... So this playground 1) creates 2 boxes, 2) sets them both to the same initial rotation (PI/3, PI/3, 0); and 3) rotates the first box 180 degrees around its x axis. I try 2 options for setting initial rotation. To my eye these are simply 2 ways to write the same code (someone more proficient may disagree): OPTION1 (lines 38-41): mesh1.rotation = new BABYLON.Vector3(Math.PI / 3, Math.PI / 3, 0); mesh2.rotation = new BABYLON.Vector3(Math.PI / 3, Math.PI / 3, 0); scene.render(); OPTION2 (lines 44-46): var initialRotation = new BABYLON.Vector3(Math.PI / 3, Math.PI / 3, 0); mesh1.rotation = initialRotation; mesh2.rotation = initialRotation; scene.render(); With line 51 (step 3, the 180 degree rotation) commented out, both OPTION1 and OPTION2 work fine and set the initial rotation as expected:http://www.babylonjs-playground.com/#VFKAZ#97http://www.babylonjs-playground.com/#VFKAZ#98 However with line 51 uncommented in order to perform the 180 degree rotation, OPTION1 works fine (http://www.babylonjs-playground.com/#VFKAZ#100) but OPTION2 seems to cause mesh1 to lose its initial rotation (http://www.babylonjs-playground.com/#VFKAZ#99). This issue is why my previous playgrounds above appeared to be only rotating by 90 degrees and not 180 as expected. Because mesh 1 was actually losing its initial rotation of 90 degrees and then flipping 180 degrees it was still only 90 degree different to mesh2!! What am I missing. Why would the way the initial rotation is set impact the way subsequent rotates are handled? I don't even know how I would go about debugging this to be honest!? Quote Link to comment Share on other sites More sharing options...
adam Posted October 24, 2016 Share Posted October 24, 2016 36 minutes ago, touslecoq said: To my eye these are simply 2 ways to write the same code (someone more proficient may disagree): It's not the same. You are sharing rotation vector between 2 meshes. When the rotate function is used, the mesh switches to using rotationQuaternion and zeros out the rotation vector. Quote Link to comment Share on other sites More sharing options...
touslecoq Posted October 25, 2016 Author Share Posted October 25, 2016 Interesting, thanks Adam. So when the Rotation attribute is used it doesn't actually apply a rotation (ie doesn't re-calculate and update the vertexData)? Thanks Rich 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.