I’ve had a hard time figuring out why I always had to switch roll and pitch rotations (+rotation order) for all of my models. Then I realized that in panda3d the x-axis points right and the y-axis points forward, whereas I need the models to face forward along the x-axis and rotate respectively. So, if I use the setHpr-method, it does not rotate as I wish.
So far, I’ve added some dummy-nodes to my models and manually applied the rotations in the order yaw-roll-pitch.
The models are placed forward-facing in x-direction in blender. So, if I want to rotate my object around the y-axis (e.g. facing front upwards), I would expect to set the variable pitch but I actually have to change the roll-value of the panda3d-node. Same with roll.
What would be the most reasonable approach if I neither want to change all models nor always switch out roll and pitch and apply a manual rotation order? Even if I rotated all models by 90° in blender to face forward in y-direction, I would still have to rotate them back again in panda3d. Is there a way to change the configuration of pandas coordinate system or any other non-confusing solution?
Best regards and thanks in advance for any help,
Thomas.
This seems like it would be an annoying issue indeed. While maybe not the solution you’re looking for, you could just write a little generic class for doing transformations on your Blender models which are facing a certain direction, so you wouldn’t have to do as much manual work.
Perhaps the simplest way would be to create your models facing the positive Y-direction in Blender and parenting the loaded models to a “root” NodePath – itself parented to base.render in Panda – for which you set a yaw of -90. Then your models will have a default local orientation corresponding to the Panda coordinate system, while they face the global positive X-direction.
You then have the choice of setting the model orientation relative to their parent (a simple call to model.set_hpr(h, p, r)) or relative to “the world” (base.render), by passing in the latter to that call as its first parameter (model.set_hpr(base.render, h, p, r)).
Hmm… Presuming that it’s infeasible to change the models or to adjust for the issue via nodes, I fear that doing this might call for some hacking of the engine’s source-code.
Specifically, I believe that Panda has a config-setting that allows one to specify the default coordinate system, simply called “coordinate-system”. However, a quick search seems to suggest that there isn’t likely an x-forward coordinate system supported. Thus it might be that modifying the source to add such support would be called for.
@Simulan: Well, the manual work is not that much of a problem, but I’d rather have a comprehensible solution instead of just reversing, rotating or swapping some stuff.
@serega-kkz: Unfortunately, I did not really get what you wanted to tell me. I’m aware of the blender coordinate system and I also did not understand the approach with the flatten-methods
@Epihaius: I think, if there is no better alternative, I’m going to go with that solution. Though, I just tested this approach and found out, that the pitch (rotation around the actual y-axis) is reversed now, so I would always have to setP(-pitch). I didn’t figure out yet how to do that in a better way. I’ve had enough of coordinate-transformations already
@Thaumaturge: I can change the models, but still I find it quite restrictive to have to comply with the y-axis facing forward… I thought, there could possibly be a better way. Changing the panda3d source-code is no option either.
That does make sense. It’s important to know how to interprete a “positive angle”. The coordinate system Panda and Blender use is called a “right-handed” coordinate system. In such a system, you can figure out the positive direction of an angle by curling the fingers on your right hand while the thumb points in the positive direction of the corresponding axis. As you try this out, you should notice that a positive pitch angle probably has the opposite direction of what you expected, compared to the positive roll angle that you previously used.
So I think it’s best to get used to how this works and consider those previous roll angles to be “wrong” instead of the pitch angles.
Yeah they can be quite confusing .
Flattening “bakes” the current transform into the vertices of the model, so if you clear the transform after flattening, the model will still appear to have that transform applied.
Well, I do not have problems with the blender coordinate system but I have data that I want to visualize where all the objects are positioned facing forward in x-direction and their roll and pitch are set respectively. In panda the objects face forward in y-direction and whatever I do in blender, my given data (object positions and orientations) does not fit to panda without fiddling. I’m sorry if I did not explain it well enough!
I’m not aware how the flatten-methods work. I’m going to look into that later
A quick thought, possibly not useful: Could you write an intermediary rotation-method that converts Panda-standard rotations into your intended rotations? Something that you could call in place of the standard “NodePath.setHpr”, etc.?
Rather than use hpr, you could construct a quaternion for each axis rotation and multiply them in the order you want to get the desired order of rotation operations. The same approach works with a matrix as well.
I suppose that is because when rotating 90 degrees around z-axis, the y-axis rotates with it and then faces into the opposite direction as it would if I had a right-handed coordinate system that faces forward in x-direction. So it would not replicate the following (also right-handed) coordinate system:
What do you mean by considering the previous roll angles to be wrong instead of the pitch angles?
So I would flatten the model-node after each rotation in order to apply them in the “correct” or rather desired order? I’m still not sure if I understood this right.
I do not fully understand quaternions yet but the hint that this also works with a rotation matrix might be a good solution. I could create the corresponding rotation matrix for my initial Hpr-values, multiply it by (0,1,0) = (x,y,z) to indicate that the direction faces in positive y-direction and get the transformed Hpr-values with that I could simply use setHpr in the correct order, right?
With a quaternion, you can trivially construct a rotation around a given axis and by multiplying you can combine them in the desired order, for example:
from panda3d.core import LRotation
# Rotate 90 degrees around X axis, and 45 degrees around Y axis
quat = LRotation((1, 0, 0), 90) * LRotation((0, 1, 0), 45)
npath.setQuat(quat)
print(npath.getHpr())
I don’t think, that my problem has something to do with gimbal lock.
I want to visualize some external data in panda, where all objects have predefined positions (x, y, z) and orientations (yaw, pitch roll). Whatever the position/orientation is, I want to visualize it as it is. But the orientations refer to a right-handed coordinate system that faces forward in x-direction, meaning objects face towards positive x and respectively pitch is the rotation around y and roll is the rotation around x as in the following picture (rotation order is zyx). But panda apparently uses pitch as rotation around x and roll as rotation around y since it places objects facing towards positive y (with rotation order zxy). (I hope I didn’t confuse something)
As I said, the workaround was to swap roll and pitch and manually change their rotation order by appending some dummy nodes and rotating every one of them at a time. If I do that, everything works fine but it is kind of messy (and confusing) to do that for everything.
I’m not really sure how to show that in blender, I’m sorry.
I think, I’m going to try out some new ideas tomorrow and report if it was successful
Edit: Thank you for the quick explanation @rdb!! I will try that tomorrow
Well I just meant using the negated value of the roll angle for the pitch, as you already mentioned you had to do. So if you have a roll of 24 in Blender, multiply it with -1 in Panda to get a pitch of -24. Not all that intuitive, I agree, but it seemed like an easy enough workaround.
For instance, if you export a model from Blender with a pitch of 31 and a roll of 24, in Panda you could then call flatten_light on the loaded model node:
model = base.loader.load_model(model_filename)
print("hpr:", model.get_hpr())
model.flatten_light()
print("hpr:", model.get_hpr())
The first print call should output LVecBase3f(0, 31, 24), while the second print call should output LVecBase3f(0, 0, 0); the internal transformation matrix has been reset to identity, but the model will still look as if it’s rotated as before flattening (because the vertex positions themselves have been altered). Whether this is useful to you, I don’t know.
Since simply switching the order of pitch and roll works for you, I wonder whether the cause of this issue is the default order of rotation angles in Blender. In version 2.8 of Blender, I see that the default order is XYZ Euler. This corresponds to pitch-roll-yaw, while the default order in Panda is roll-pitch-yaw (and not yaw-pitch-roll, as hpr may seem to suggest).
So, out of curiosity, if you change that order to YXZ Euler in Blender (not sure how to do this in another version of Blender, but in e.g. 2.8 you can select this from a dropdown-menu at the right of the interface), does it then work in Panda as expected (without any kind of adjustments)?
Theoretically, this does not affect the panda in any way. So this is the inner workings of the blender, and there is no way to export . However, I found a mention in panda in the form of a custom coordinate system, how this is implemented is unclear.
That relates to the ability to change the coordinate system from the default Z-up right-handed to a left-handed or Y-up coordinate system (via the coordinate-system config variable). However, I do not think it affects the order of rotation operations.
Normally, converters are writing the rotations as a matrix or as a quaternion, where the order is irrelevant.