Home Technical Talk

How do you accurately calculate eularAngles to avoid flipped orientation?

polycounter lvl 13
Offline / Send Message
shawnolson polycounter lvl 13
One of my tools exports scenes/objects into a game engine. One of the problems I have encountered lately is that sometimes the orientation is incorrect. The engine requires eulerAngles… but sometimes the angles are simply “flipped”.

In the attached image, the Max scene is the original. The right is the exported scene in another program called Hammer. Notice that all of the teapots along the yellow hilight are inverted on multiple axises in the game editor.

paint_object_rotation.png

I normally haven’t had a problem with this by just using something like:
local theRotation = theModel.rotation as eulerAngles

But when I started experimenting with painting models in the scene with the Object Paint tools, I’ve found that this method of calculating is incorrect. As you can see, those I simply copied, moved and rotated exported correctly--but all those part of an object paint stroke (yellow hilight) have inaccurate rotations.

The questions:

1) How do I detect this incorrect orientation?
2) How do I resolve it? (I’ve tried multiplying the angles by -1 or subtracting 180 in various attempts to get at the issue but I’m not getting the desired results).

Again, like always, all help is appreciated.

Replies

  • Eric Chadwick
    I'm not the right guy to answer this. But maybe some of Paul Neale's resources can help? http://paulneale.com/tutorials.htm
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Thanks for the input, Eric. Unfortunately, Pen's stuff was already on my list of things I found during my Google searches. I didn't find anything there to really answer my questions... but Paul has been a good resource for me :)
  • Eric Chadwick
    If no one else chimes in here, I would point you to the http://tech-artists.org forums, lots of good riggers there who probably know what to look for.
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    With static objects...
    1: probably impossible unless you make some fairly big assumptions
    2: see above


    With animation...
    1.look for big changes in curves over short spaces of time(<1frame)
    2. now it gets complicated....



    What are you actually trying to get out at the end?
    Could you just reset transforms on the painted objects?
  • gray
    its hard to give clear help because i don't have your setup. but if your only getting this problem in certain situations on one axis then maybe your rotations are fine and there is another factor that is causing it.

    i would try to isolate one simple object that has the problem and try to reproduce it. make sure that it is actually the sort of flipping you think it is then try to fix it.

    if there is a mis-match of axis or inverted rotation you should be able to find it by applying the (worldspase) transformation matrices to a axis-aligned object at the origin.

    edit:
    as poopipe noted this could take some work to track down. not so simple.
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    Gray has a point. who's to say its not a scale factor for example?
  • gray
    poopipe wrote: »
    who's to say its not a scale factor for example?

    it looks like it could be an inverse scale. i have no idea how these transforms are applied so its not really possible to comment past simple observation.

    edit:
    if you are trying to match an object from one coordinate system to another. ie from one software to another or file etc, apply the same transformations from one to the other system. take into account any differences ie y is up x is up etc. any other solution will probably be complicated as poopipe noted.

    i have not looked through this whole pdf but it seems to be at the right level of detail to solve your problem.

    http://gregslabaugh.name/publications/euler.pdf

    also you might want to look at a computer graphics book or opengl for transform matrices.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Thanks for the input guys.

    In the end I am simply trying to get a model to export at the same rotation it is in Max to the game engine. The methods I've successfully been using are getting just $object.rotation or $object.transform.rotation ... and that always works when I manually place/rotate the objects.

    The problem seems to only occur when I'm painting the objects into the scene with Object Paint ... and this creates rotations that "looK" the same as they would look if I manually placed/rotated... but the output rotation doesn't match.

    I had played with Reset Xform as I suspected that would fix it... but so far that didn't work... but that may be a result of the Paint Objects being Instances or References of the original object; I'll test later when I can open Max again.
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    find out what kind of controller setup is on the painted objects
  • gray
    shawnolson wrote: »
    I had played with Reset Xform as I suspected that would fix it... but so far that didn't work...

    i don't think that would work. reset xform aligns your object space axis to the world space axis. i'm not sure how that would help you unless of course you do not want to keep the object rotations and translations.

    but it look like your problem is not with the rotation in general but with some modifier that is changing the transform matrix in some way. so it should be much easier then dealing with eular angles. :thumbup: you simply have to figure out how to strip those modifications out to the point where you have an 'unmolested' object transform that can be read by whatever is exporting your geometry.

    note:
    i note here that i have for the first time found a use for the word unmolested in proper context. and aword myself 2 points.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    gray wrote: »
    but it look like your problem is not with the rotation in general but with some modifier that is changing the transform matrix in some way. so it should be much easier then dealing with eular angles. :thumbup: you simply have to figure out how to strip those modifications out to the point where you have an 'unmolested' object transform that can be read by whatever is exporting your geometry.
    These painted objects are meshes or primitives with no modifiers. But yes, unmolested transforms sounds about right... well, as right as that can sound... :)
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    poopipe wrote: »
    Gray has a point. who's to say its not a scale factor for example?

    You are right. It turns out that the scale on the painted objects is [-1,-1,-1] . Now I can get somewhere. Though honestly, I'm scratching my head trying to figure out the best way to negate the negative scale to get the correct rotation info based on this.

    Ideas? Hints?

    Again, thank you all.
  • Numerator
    If your source is in quaternions and you are converting to Euler angles, it is possible to get 360-angle as an answer vs. the angle that you want. This is because a quaternion can represent the same rotation from A to B in two ways. The shortest path, or the longest path.

    If you negate the quaternion that is rotating around the longest path, you obtain the shortest path and vice versa.
  • Denny
    Offline / Send Message
    Denny polycounter lvl 14
    Have you taken rotation order into account?
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Denny wrote: »
    Have you taken rotation order into account?
    For this engine, the model orientation is being mapped from Max as XYZ > YZX, if that is what you mean.

    Regarding the negative scale, I know it must be the culprit...

    I figure there must be some fomula to multiply the PRS matrix such that the orientation will output correctly, but I haven't figured it out. I noticed that when, in Max, I select an object and type $.scale = [1,1,1] it will suddenly orient the same as the erroneous models in the export.

    Sorry about my ignorance... I've been on a long process of learn as you go and have no formal education on anything--who didn't even graduate high school. (I'm a shoot-from-the-hip programmer that doesn't always have the luxury of training beyond docs and the kindness of the community :) ) ANd all things math are my worst skills... so it's always a slow process for me to figure out anything dealing with matrix math.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    poopipe wrote: »
    find out what kind of controller setup is on the painted objects
    Sorry I missed answering the question. The painted objects always have:

    Controller:Position_Rotation_Scale
  • Denny
    Offline / Send Message
    Denny polycounter lvl 14
    shawnolson wrote: »
    For this engine, the model orientation is being mapped from Max as XYZ > YZX, if that is what you mean.
    That's what I was thinking of yes.

    What's the world up axis of 3dsmax vs Hammer and are they left/right handed coordinates?
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    For some reason, model orientation is in what Max would have as YZX but otherwise for world geoemtry it is all XYZ with Z up .
  • gray
    shawnolson wrote: »
    I figure there must be some fomula to multiply the PRS matrix such that the orientation will output correctly, but I haven't figured it out. I noticed that when, in Max, I select an object and type $.scale = [1,1,1] it will suddenly orient the same as the erroneous models in the export.

    that would just be an elementary inverse scale matrix. 'math speak' which is essentially just a multiply of a channel by a negative number.

    edit:
    see below.
  • gray
    shawnolson wrote: »
    You are right. It turns out that the scale on the painted objects is [-1,-1,-1] . Now I can get somewhere. Though honestly, I'm scratching my head trying to figure out the best way to negate the negative scale to get the correct rotation info based on this.

    Ideas? Hints?

    Again, thank you all.

    hey i missed this post when i was skimming the thread. if the effected object has a scale of (-1,-1,-1) then thats really simple to fix. just multiply each scale transform buy -1 ie -1*(-1,-1,-1) and that should give you the correct result.

    the scale and rotation are independent. you don't need to mess with rotation.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Thanks Gray... I kept running into all kinds of problems with this... and it is probably a simple solution. But I just couldn't find a mathematical solution (using negative multiplcations or the inverse function). So instead I built a couple functions to help the artist find/fix the problems in the painted models.

    I'll probably return to this to create a workflow that solves it mathematically when I have more time to devote to it. For the moment, the helper functions are usable and almost always solve the problem.

    I guess I'd not even have to deal with this if the Object Paint tools would give positive scales to begin with... like you'd expect :)
  • gray
    i'm glad you found a workaround. its quite hard to get to a specific solution on something like this unless you start posting equations in latex or posting code. but i imagine it is quite simple and probably fixable with very little work.

    on a side note if you wanted to do the scale on paper you would first have to translate the pivot to the origin.
    then rotate to axis align the coordinate system
    then apply the scale by -1
    then do the inverse rotate and translate to put the object back into place.

    its a pain is the ass. i figured that maybe the objects would be smart enough to just do a -1*scale but i guess not. sorry mate. but i do think you should be able to get it with a scale done in the right way given your scale is -1,-1,-1. just makes sense. but who knows could be something else entirely.

    i would pick up a used intro to linear algebra book for cheap on amazon that has a matrix algebra chapter if you want to figure the correct math. that should be more then enough to get you out of any transform matrix math problems. Larson, Strang or Lay are good.

    i have heard this was a good one from a mathematics professor but have not personally read it. http://joshua.smcvt.edu/linearalgebra/
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Thanks again Gray and everyone else here).

    Unfortunately, I'm in and out of the hospital with a family illness ... and now away from Max tonight. So I cannot give the exact code I have where the problem lies. But here is a little clearer overview.

    A collection of objects in the scene (say 100 teapots that are references of one particular teapot). 50 of them were simply Referenced manually with Shift+Drag. But the other 49 were created with the Object Paint tool .

    Visually, all the teapots are oriented nicely (however that may be for the scene). But when you go to extract the XYZ orientation for another program, the values are all wrong for the 49 teapots that were made with the Paint tool. As it turns out, the only significant difference between these 49 teapots and the 51 (50 refs plus original) is that the originals have a scale of [1,1,1] and the painted ones have [-1,-1,-1].

    So in the end the best thing would be some function that looks like this applied to the objects :
    function getExpectedRotation obj = (
     
     if obj.rotation == [1,1,1] then (
     
      return obj.rotation
     
     ) else (
     
      local mathVoodoo = someMatrixMathFormulaOnTransform
     
     /*
    Do some math voodoo that basically returns a rotation
    value that would make this obj look the same as it currently
     does but with a scale of [1,1,1] 
    */
     
      return mathVodoo
     
     )
    )
    

    My guess is that this code already exists out there... but I am not quite the Google Master I used to be. Anymore, half the time I'm looking for the answer to something I keep finding my own posts presenting the problems!

    But yes I may need to start learning to integrate matrix math into my book of knowledge no matter how much it makes me moan... otherwise I will keep filling up the forums with questions :)
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    gray wrote: »
    i'm glad you found a workaround.
    As it turns out... my workaround failed if the brush stroke uses rotations and/or scattering. So a full math solution is in order. I've started reading the linear algebra book you linked to... but I'm not sure I'll have time to study a lot at the moment (my elderly father is moving in with us tonight... ) . But I'll try.

    In the meantime, any more feedback is appreciated.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    I wanted to share my solution that seems to work. I wanted to make some dynamic function that accounts for all scale problems (as that would be most diverse)... but since the problem seems unlikely in most circumstances, I'm stopping for now with the following code.

    I hope it helps someone.

    Essentially, if you need to have a scale of [1,1,1] on your objects that were painted with the Object Paint tool, you can select those objects and then do something like this:
    for obj in selection do (
     scale obj [-1,-1,-1]
     in coordsys local (
     rotate obj (eulerAngles (-1*obj.rotation.x_rotation) -180 (-1*obj.rotation.z_rotation))
     )
    )
    

    I'll be putting this into a function in Wall Worm in the next week.

    PS. If someone has a more robust formula, I'd be happy to see it... all the linear algebra stuff is making my beard get too gray too fast.
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    You can guarantee a positive scale by multiplying it by itself
  • Denny
    Offline / Send Message
    Denny polycounter lvl 14
    That only works if the scale is -1 or 1, not 0.5. (-0.5*-0.5 = 0.25) It is more stable to use an abs function, I don't know the syntax for it in Max Script but in Maya you do;

    $scale = `abs $scale`;

    Abs, absolute value, returns a non-negative value.
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    Fair point. I have no idea what the max equivalent is
  • gray
    sadly i don't know spit about max script (maya guy). so no working code solution from me.

    -1 is a special case which gives the inverse.

    @shawnolson

    so i took a look at that pdf and i'm going to have to say its crap for learning simple matrix algebra in order to understand 3d matrix transforms. its intended for math majors who need to learn rigorous proofs and will go on to abstract algebra etc. thats absolutely not what you need to read. :) those other books are much better. or any standard 'engineering' intro to linear algebra book. you only need the first few chapters on Gaussian elimination and matrix algebra you don't need to read the whole thing.

    that pdf will probably only annoy you with unimaginably abusive mathematical rigor. :poly142: matrix algebra is quite easy if you get the right book tho.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    gray wrote: »
    @shawnolson

    so i took a look at that pdf and i'm going to have to say its crap for learning simple matrix algebra ... that pdf will probably only annoy you with unimaginably abusive mathematical rigor. :poly142: matrix algebra is quite easy if you get the right book tho.

    Well you must know my type quite well :P I started reading it and lost all the zest for solving the problem after a few pages! I really wish I would have sucked it up and learned more math back in school... but honestly it's the one realm that my brain turns into a grinder when pondering. Logic, I'm great. Syntax, programming, writing, analyzing, yada yada yada... I excel with ease. But math... it likes my brain as much as I like Glenn Beck.

    What annoys me is that I can't just plug my brain into some machine and learn everything; and I know that this "problem" is probably a very novice mathematical problem. But now that I have a solution to my current scenario... I may never solve it.

    Incidentally, the code needs an addition because it seems that the UVW seems to flip too... so that needs to be accounted for if anyone else comes across this. I'll post that solution tomorrow if I get time.
  • Denny
    Offline / Send Message
    Denny polycounter lvl 14
    Seems the abs function is this simple if you need to use it. :)

    value = abs(value)
  • Xoliul
    Offline / Send Message
    Xoliul polycounter lvl 14
    Hey man, maybe you should just write your own Object Paint replacement ? I've done that as well, and I actually prefer it over the standard object paint...
    It's really not that difficult, I just got an example script off the net (Snap2Object.ms by P.G.Preeth). That way you have full control over the transforms of the placed objects.
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Xoliul wrote: »
    Hey man, maybe you should just write your own Object Paint replacement ? I've done that as well, and I actually prefer it over the standard object paint...
    It's really not that difficult, I just got an example script off the net (Snap2Object.ms by P.G.Preeth). That way you have full control over the transforms of the placed objects.
    It's certainly something to consider since I have some ideas in mind that could make it really cool. Of course, by planting that seed you've doomed me to avoid any design work even further... banished me back to more code blocks :)
  • poopipe
    Offline / Send Message
    poopipe grand marshal polycounter
    Why didn't reset xform fix it?
  • shawnolson
    Offline / Send Message
    shawnolson polycounter lvl 13
    Sorry I didn't mean to ignore a couple ideas here. So here is my feedback on those.
    Denny wrote: »
    Seems the abs function is this simple if you need to use it. :)

    value = abs(value)


    Using abs() wouldn't help because the scale and rotation are linked mathematically (in the transform). Just getting the positive scale values was never really the issue since it was the rotations that I needed.

    poopipe wrote: »
    Why didn't reset xform fix it?

    Reset XForm was my first step in figuring it out. But it failed. As Gray noted... Reset XForm aligns the object to the world... and that throws out the window the rotation values I am trying to get . (We all think of using that automatically here because we all know to use Reset Xform to solve random scaling issues... but in this case it isn't a good solution.)

    PEN answered this question over on the Area the best so far. I haven't had a chance to open Max and test this in my code... but my guess is that it will work.
Sign In or Register to comment.