Open3D
Open3D copied to clipboard
What coordinate system does Open3D use?
Checklist
- [X] I have searched for similar issues.
- [X] For Python issues, I have tested with the latest development wheel.
- [X] I have checked the release documentation and the latest documentation (for
master
branch).
My Question
I can't find any reference to the coordinate system used in Open3D.
For instance, OpenGL uses RH y-up (z backward), Blender uses RH z-up, DirectX uses LH y UP, and Unreal uses RH with x to the right and y up).
# OpenGL RH y UP
# y
# |
# +---x
# /
# z
# Blender RH z UP
# z
# | y
# |/
# +---x
# Direct X (not used here), LH y UP
# y
# | z
# |/
# +---x
# Unreal Engine, RH, x RIGHT y UP
# y
# |
# +---x
# /
# z
This is pretty fundamental, so I probably just missed it in the docs. If it's not in the docs, this would be really helpful to add up front in the docs.
I'm passing my data (point cloud, meshes) through several applications with potentially different coordinate systems, and want to make sure I have all my transformations correct. I'm quite familiar with this domain, so I only a reference to which coordinate system is in use. Thanks!
Using code adapted from Draw Line Set, it looks like the coordinate system is RH y UP, which matches OpenGL, etc.
def generate_axes(scale: float) -> List[o3d.geometry.LineSet]:
points = [
[0, 0, 0],
[scale, 0, 0],
[0, scale, 0],
[0, 0, scale],
]
lines = [
[0, 1],
[0, 2],
[0, 3]
]
colors = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]
line_set = o3d.geometry.LineSet(
points=o3d.utility.Vector3dVector(points),
lines=o3d.utility.Vector2iVector(lines),
)
line_set.colors = o3d.utility.Vector3dVector(colors)
return [line_set, ]
The part that confuses me, maybe, is the front
argument to draw_geometries
. When I set it to [0, 0, 1]
the camera points down the negative z axis, and when I set it to [0, 0, -1]
it points down the positive z axis. This seems backwards. Am I misinterpreting this front
vector? I'm thinking of this as the initial forward vector of the camera. But look-at calculations are usually:
- set camera position and look-at
- fwd = (look_at - camera_pos).normalized
- right = fwd x up, normalize if paranoid
- true up = right x fwd
So this front
argument seems like maybe it's not the forward vector of the camera, but the vector from the origin to the camera position. Setting this to [0, 0, 10] doesn't seem to move the camera any farther away.
o3d.visualization.draw_geometries(
to_view,
zoom=0.3412,
front=[0, 0, 1],
lookat=[0, 0, 0],
up=[0, 1, 0],
point_show_normal=True
)
Camera position (slightly adjusted for visibility) when front=[0, 0, -1]
Camera position when front=[0, 0, 1]
I'm also confused because the normals in this "F" synthetic point cloud are all 0, 1, 0
, which should point along the positive Y (green axis).
-1.624193 0.000000 -1.892043 0.000000 1.000000 0.000000
EDIT scratch this comment. I was flipping the normals myself.
Okay, I think this is right, and maybe helpful to someone else:
- Coordinate system is right handed (RH), x RIGHT, y UP, (thus z BACKWARDS), which matches OpenGL
- The
lookat
argument ofdraw_geometries
is as expected from any "look at" calculation. - The
front
argument is not the forward vector of the camera, It's a vector FROM the look-at target TO the camera. This argument will be normalized, so if you want to get a 45 degree downward view, this can be[0, 1, 1]
. - To get the full position of the camera, multiply the
zoom
argument and thefront
vector.
Here's an annotated version of the arguments.
o3d.visualization.draw_geometries(
to_view,
# Camera position is calculated as `lookat + (zoom * front)`
front=[0, 1, 1], # vector FROM origin TO camera (will be normalized)
zoom=1, # multiplies normalized `front` vector to determine position of camera
lookat=[-2, 0, -2], # look at position, determines true forward vector of camera
up=[0, 1, 0], # starting up vector, determines true right vector of camera
point_show_normal=True
)
Verified the output .obj
file is consistent with OpenGL coordinate system. Importing into blender with
- -Z forward
- Y up
gives the correct orientation of the test F mesh.
@cod3monk3y thank you very much! This is the first consistent explanation of hoe the open3d coordinate system works that I have found.