bases, pronounced basees, or baseeeees if you’re French.
It’s left or right handed for the entire coordinate system, not per axis, so that cuts down the number of permutations a lot. I think there’s just twelve in total? Y-UP, Y-DOWN, X-UP, X-DOWN, Z-UP, Z-DOWN, and left or right handed versions of each.
True, but we’re talking about 3D Cartesian coordinate systems here, which have orthogonal axes.
I made a chopsticks toy to help me visualizing coordinate systems since I seem to be doing a lot of it recently:
The handedness of a system should be dictated by its axes and the right hand rule. You can’t have a left handed coordinate system where Y is up, X is right, and Z is forward (coming out the screen) like in three.js, for example. So when making a frame you can choose 1 of 6 for the first axis (X, Y, Z, and + / - for each), 4 for the next, and 2 for the last which should be 48 options.
I’ll try to write a small function later tonight that produces the matrix needed to get from one from the other – something like this that returns a Matrix4:
// from three.js frame to unity frame
getBasisTransform( '+X+Y+Z', '+Y+X-Z' )
Some of those are practically the same, but offset only by one rotation.
However we’d want to make this as easy to describe as possible with as zero math needed by the end user. There should be no transformations of any sort needed, only a description of the original basis and the target basis (relative to the display, because that’s what matters most here as we’re talking about graphical space).
3D Cartesian coordinate systems here, which have orthogonal axes.
And with the same units along each axis.
But I don’t think that rotation needs to be limited to all-right or all-left for every axis, there can be a mix. It isn’t our choice to make, and it’ll just lead to someone who encounters such a basis asking the same questions because the API doesn’t handle the case.
That’s what you and I may desire, but strictly true. We need to account for cases that don’t follow this desirable rule, because inevitably there are cases that do not conform to this rule.
Then we’ll have people coming back and asking the same question because the API doesn’t support it.
I prefer the more robust design decision for this one, because any basis we are converting from is speculative. We aren’t designing for a specific set of basii here (basii because “bases” is confusing).
Why not? Anyone can arbitrarily choose the handedness of each axis of any basis they create. At least, as far as Eulers, I believe this is completely fine. I’m not sure about Quaternions.
Let’s consider why other cases are not legitimate to include in any solution.
How does that work? Which of each axii () are forward, left, and up? Or do we assume a certain order, like forward-left-up? In the first basis forward is +X, left is +Y, and up is +Z?
This matters because people want to know how to orient things relative to a display (camera).
Oh yeah, what about handedness? This matters. As I linked above, not all coordinate systems are right handed.
rotation in relation to what? the basis is the top of the chain, there is no super-basis it is rotated in.
p.s. the whole concept from handedness implies there are only two kinds of basises (basii?) just like there are only two kinds of hands. no matter how you rotate your left hand around, it still remains a left hand, right?
There are super basii: the display, and the gl space.
Think about it from an end-user perspective, where that user does not know any math, and just wants to get things working easily. Think about this scenario:
They make an object, perhaps from importing a car model.
They place it into the scene and “drive” it forward along -Z (the axis that the camera looks down by default, easy).
Now, they receive some data from somewhere, a sub-scene that some designer wants to put in the scene, but it is in another basis.
The end user, knowing absolute no math, wants to convert that other basis (whatever it is) so that everything is pointing down -Z as expected, just like the user’s initial scene.
Ideally, there should not be any math thinking involved to achieve this, just a simple basis conversion based on easy-to-describe charateristics.
Oh! And that leads me to realize something! There are infinite basii: besides the 384 basii made of differing orientations and rotation directions, there may be an overall different unit of measurement used for each axis. One basii might be in inches, and another in feet, and another in Meters.
So, the ultimately solution would consider all of those things and make it super easy for the end use.
Let’s prevent them from doing math! Let’s lower the barrier of entry. Let’s make things so easy that people know Three.js is the best solution that exists
(or, at least, lets make the new version of Three so much better than the previous version, even if those versions were all already better than all other alternatives. )
There’s lots of progress to be made. I 100% believe 3D isn’t as easy as it can be yet.
what about the basis rotated by 13.1 degrees in the screen space? should we consider it to be different type of basis, too? or just multiples of 90 degrees count?
FWIW, I have converted a subtree in my scene from one basis to the Three basis, and now no matter what I do, the camera “up” axis is always sideways relative to the car I want to follow, and I’m having a hard time figuring how to fix it. No matter what I set the value of camera.up to, OrbitControls doesn’t seem to care.
It’s like my head is turned sideways.
You see, it’s not just about converting axii and rotation, it’s also about converting all tools to operate in the new basis. This isn’t an easy problem to solve.
Idk, some tools may be harder to learn and work with, and yet they are vital for the job. if you do not use them, you will do poor job. the docs maybe could help with this by linking to khan academy videos or something?
It is arbitrarily chosable by whoever designs their coordinate system, right? If we can account for that just as easily, then why not.
Yes by how the axes are selected.
Let’s consider why other cases are not legitimate to include in any solution.
The code I have provided handles left handed coordinate systems – I didn’t say otherwise.
Why not? Anyone can arbitrarily choose the handedness of each axis of any basis they create.
Again this is dictated by the axes.
That’s what you and I may desire, but strictly true. We need to account for cases that don’t follow this desirable rule, because inevitably there are cases that do not conform to this rule.
Oh yeah, what about handedness? This matters. As I linked above, not all coordinate systems are right handed.
It is strictly true. Please research left handed coordinate systems before stating this so confidently. You don’t need anyone to tell you a coordinate system is left handed you can tell by looking at the axes. The math between a left handed coordinate is the same, too, it’s just a matter of how you display. Computing the cross product in a left and right handed system is the same, for example, but the visual result is different because of how you’ve organized the axes.
At least, as far as Eulers, I believe this is completely fine. I’m not sure about Quaternions.
Dealing with rotations explodes the complexity of this problem quite a bit. If you want this addressed I’d just deal with positions first.
How does that work? Which of each axii () are forward, left, and up? Or do we assume a certain order, like forward-left-up? In the first basis forward is +X, left is +Y, and up is +Z?
You see, it’s not just about converting axii and rotation, it’s also about converting all tools to operate in the new basis. This isn’t an easy problem to solve.
The fact that you haven’t gotten it working doesn’t mean it can’t work… I’m doing the same thing in my application using OrbitControls and everything works just fine. I’m not just making up solutions I’m trying to help you based on the experience I’ve had dealing with these coordinate frame transformations for years for robotics applications. If you want to make a fiddle to demonstrate how you’re trying to achieve it I can try to adjust it so it gets the results you’re interested in.
Oh ok, that’s good. I didn’t see in your example how to specify handedness, and the README has no result for the search term “hand”.
I don’t see the result I expect. Maybe I’m not expecting the right thing, but in the following screenshot, -Z is forward (the default Three.js camera view) and for reference I oriented the axii on the left to show this. As you see I chose +X to be forward, but it looks like -X is actually forward.
Based on your assumption that all people follow the conventions that you’ve linked to (f.e. on Wolfram, and elsewhere), then yeah, each axis dictates handed ness.
But people don’t all follow every convention. I can make any set of axii, and I can arbitrarily choose to point either my left or my right thumb down any given axis, and rotate towards the tips of my fingers.
There’s no way you can force me not to do that. And there’s no way you can force everyone not to do that.
The links you posted are desirable conventions, but they are not strictly reality.
It is similar to saying that all class names are always PascalCase just because that is the convention in JavaScript, yet anyone can arbitrarily choose to write class my_class {} or class myClass {} just because they can.
Class names being PascalCase is not strictly reality. This same concept applies to handedness; not everyone is going to follow the desired conventions.
Yes indeed. It is part of the problem space.
Totally! I’m only describing that ideally the whole solution would cover all the tooling, not just a matrix transform of a sub tree while the tooling still expects and operates in the Three basis.
That’s an opinion. If I am using Three.js, but not actually touching low-level WebGL APIs, I’m doing a bad job? If my experience designer doesn’t think about graphics math, is he doing a bad job?
These thoughts are not helpful in improving the existing solutions. I’d like to keep the conversation on how to improve some existing (or non-existent) APIs, without assuming everyone wants to do math. In fact, I’m assuming that more people should have access to these tools with lower level of entry. That’s my goal.
I found my problem: camera.up must be specified before creating OrbitControls. Some parts of the code read it dynamically, while other parts do not.
So there’s more things to consider here: how do we make the overall APIs easy to use with respect to basii changes? I have a “low level” mapping library (on top of Three), and by default the camera and orbit controls are already created. Now telling the scene to “follow another object” where that object is from another basis, doesn’t work.
oh shit ) I cant tell you how many times I cursed designers who made assets without thinking about its use in realtime context. 50% of the time they create unuseable garbage, no matter how pretty.
And robust basis conversion, not just with matrix transforms but around all tooling, would help reduce that percentage value (or I should say, make the designer’s output format less relevant)
I also don’t see the result I expect. Maybe I’m not expecting the right thing, but in the following screenshot, -Z is forward (the default Three.js camera view) and for reference I oriented the axii on the left to show this. As you see I chose +X to be forward, but it looks like -X is actually forward.
If you want to think about it that way then that’s fine. The way I’ve modeled the example above is the three.js frame is displayed as +X, +Y, +Z because I choose to think about forward as +Z and that rendering occurs with -Z into the screen because that’s how the WebGL coordinate system works. The “LookAt” function, for example, orients an object to point +Z as the target point but this is explicitly reversed if the object is a camera. Ultimately as long as you define forward to be notionally the same between both frames the conversion will work. Consistency is what’s important. You should be able to pass “+X+Y-Z” as the three.js coordinate system and have it work but I’d have to think about what I’d expect it to look like before saying it all works correctly. I can verify later tonight if you’re interested.
Based on your assumption that all people follow the conventions that you’ve linked to (f.e. on Wolfram, and elsewhere), then yeah, each axis dictates handed ness.
But people don’t all follow every convention. I can make any set of axii, and I can arbitrarily choose to point either my left or my right thumb down any given axis, and rotate towards the tips of my fingers.
There’s no way you can force me not to do that. And there’s no way you can force everyone not to do that.
This is not how the rule works. Again, please read up on what it means I have given you resources and if you don’t understand why it’s the case then please ask. Linked in the above reference I gave is information on the right hand rule which discusses the cross product and the role it plays. Your index finger should be the first vector being crossed and your middle finger should be second (order matters with the cross product!). Your thumb represents the direction the resulting vector is pointing from the cross product. The behavior is because of underlying mathematics and the direction axes are pointing not because people are arbitrarily choosing that rotations are negated sometimes and not others.
The links you posted are desirable conventions, but they are not strictly reality.
This is not true. The behavior is underpinned by mathematical principals.
So there’s more things to consider here: how do we make the overall APIs easy to use with respect to basii changes? I have a “low level” mapping library (on top of Three), and by default the camera and orbit controls are already created. Now telling the scene to “follow another object” where that object is from another basis, doesn’t work.
It’s a losing battle and not every library you’re interested in using is going to operate in the same. In the case of OrbitControls maybe it would be nice if it respected the current camera up rather than the one at instantiation but there will always be code that isn’t as flexible that you don’t have control over. It’s easiest to just use a given tool or object in the properly oriented coordinate frame if you can. My hierarchy looks like so:
Scene
- Camera
- World with +Z up
- Stuff in the World
I have no issues with the camera pointing. If you need the camera to be parented to something you can either update the position before rendering or add it as a child to an inverted transform:
Scene
- World Transform Group
- World with +Z up
- World Transform to Three.js Frame
- Camera