1

I have three vectors representing the forward direction (d), upward direction (up), and right direction (right) in an OpenGL camera system. I need to update these vectors when the camera is rotated, so they continue to face the correct directions. My coordinate system follows the convention of +x to the right, +y upward, and +z out of the screen.

Vector Representation Coordinate System

Here's my current approach:

// Create the three vectors (Vector4f used for OpenGL compatibility)
d = new Vector4f(0, 0, -1, 0);
right = new Vector4f(1, 0, 0, 0);

// Create a transformation matrix
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
Matrix4f.rotate((float) Math.toRadians(cam.getPitch()), new Vector3f(1, 0, 0), matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(cam.getYaw()), new Vector3f(0, 1, 0), matrix, matrix);
Matrix4f.rotate((float) Math.toRadians(cam.getRoll()), new Vector3f(0, 0, 1), matrix, matrix);

// Transform the 3 vectors with the matrix
Matrix4f.transform(matrix, d, d);
Matrix4f.transform(matrix, right, right);

up = Vector3f.cross(right.xyz, d.xyz, null);

// Normalize the vectors
d.normalise(); up.normalise(); right.normalise();

Problem

However, when the camera is pointing in certain directions, the resulting vectors do not match the expected values. Here are a few examples:

When the camera points in the direction of the x-axis:

Camera Position: (-63, 15, 100)
Camera Rotation: (0, 90, 15)
Current Vectors: d(-1, 0, 0); up(0, 1, 0); right(0, 0, -1)
Desired Vectors: d(1, 0, 0); up(0, 1, 0); right(0, 0, 1)

When the camera points in the direction of the z-axis:

Camera Position: (-15, -15, 51)
Camera Rotation: (0, 0, 15)
Current Vectors: d(0, 0, 1); up(0, 1, 0); right(-1, 0, 0)
Desired Vectors: d(0, 0, 1); up(0, 1, 0); right(-1, 0, 0)

When the camera looks upward along the y-axis:

Camera Position: (-11, -48, 104)
Camera Rotation: (0, 90, -90)
Current Vectors: d(-1, 0, 0); up(0, 0, -1); right(0, -1, 0)
Desired Vectors: d(0, 1, 0); up(-1, 0, 0); right(0, 0, 1)

None of the calculated vectors match the desired vectors, and I'm unsure what went wrong during the rotation. If you require additional information, please let me know, and I will update the post accordingly.

EDIT: I have made some progress by modifying the source code and examples. The resulting vectors are now closer to the desired values, but they still fall short. It seems like there might be a small mistake or oversight that is causing the discrepancy. Additionally, I am curious if there are any specific conditions or limitations for the rotation angles, such as a restricted range (e.g., -180° to +180°), that I should be aware of? (for example only -180° to +180° or something like that?)

Here is a visual representation of my transformation matrix:

Transformation Matrix

Gykonik
  • 638
  • 1
  • 7
  • 24
  • 1
    Not sure that is the issue but the way you put it should `right` not be `(0,0,-1)`? I believe the following needs to be true: `cross(up, d) == right`. Anyway for your "wrong" example please provide testable scenario. So please provide `cam` values that you used in your example that produced wrong results. – Matic Oblak Apr 23 '18 at 14:01
  • Then the rotation might be off from what you expect. I am not sure what values are in your `cam` but if for instance `cam.x` represents a value that from user perspective turns left or right then the rotation must be done around "up", not around "right"... – Matic Oblak Apr 23 '18 at 14:08
  • Also be clear about creating the 3 camera vectors. Are these called every time (are they reset to original before new values are processed) because now it looks like they are part of some method but since you normalize them at the end we might expect they are initialized once and then the matrix multiplication is being called many times. If so then it is most likely the construction of your rotation matrix is wrong because you need to rotate around current base vectors. But this again depends on what you expect to have as a result. – Matic Oblak Apr 23 '18 at 14:14
  • Ok, I edited it. Now you also have Cam Pos and Cam Rotation. (cam.x is the x value of camera rotation ofc). To the first aspect: This would make sense but if you imagine that you stand at the origin (0,0,0). In my coordinate system d would go forward (in the screen) (1,0,0), up would go up (0,1,0) and then right has to go to the right (0,0,1). What am I missing? And has `cross(up,d)==right` to be true or `cross(d, up)==right`? – Gykonik Apr 23 '18 at 15:23
  • Answer to your 3rd post: The 3 vectors are then used to calculate a view frustum (maybe you know it, for frustum culling). But they don't get changed I just use them for a few vector additions and scalar products and then call the method again next frame – Gykonik Apr 23 '18 at 15:26
  • you can obtain your vectors directly from camera matrix see [Understanding 4x4 homogenous transform matrices](https://stackoverflow.com/a/28084380/2521214). You can even apply transform matrix on your vectors you just need to temporarily set the matrix origin to `(0,0,0)` so you do not offset the vectors. – Spektre Apr 24 '18 at 07:03
  • What do you mean by camera matrix? My only 2 matrices are projectionMatrix, viewMatrix (and transformationMatrix). Is this the same as a viewMatrix, or how do I get the camera matrix? And could you maybe explain your idea more in depth? :) – Gykonik Apr 24 '18 at 09:07
  • I edited the post to be up to date. Seems like we got closer to the solution – Gykonik Apr 24 '18 at 11:58
  • well I am talking about [`ModelView` matrix which is the multiplication of Model matrix (placing of rendered object in space) and View matrix (inverse of camera matrix)](https://stackoverflow.com/a/49841796/2521214). If you got just one matrix on CPU side (on GPU you can have just one) than you do not have direct access to your camera nor object placing other than in the right place in between the incremental transformation calls. Projection matrix hold just the projection (usually perspective) and does not have any relation to camera placing (otherwise you got projection matrix abuse) – Spektre Apr 24 '18 at 18:49
  • the last 3 links in the **Understanding 4x4 homogenous transform** I linked before deals with camera and player control which is most likely what you want to see ... – Spektre Apr 24 '18 at 18:51
  • Ahh I forgot, I also have a ModelView matrix. I have a modelMatrix with the cameras rotation, a viewMatrix and a modelViewMatrix. Im no sure, how I can extract the 3 vectors out of the modelViewMatrix. Could you explain it? – Gykonik Apr 24 '18 at 21:06
  • you are using some `matrix4f` class I do not know (I do not code in JAVA) but if you can access individual cells of it see in which places the vectors and origin are located. The image in the link of mine is for OpenGL convention. The DirectX has it transponated. In pure OpenGL you can use `float m[16]; glGetFloatv(GL_MODELVIEW_MATRIX,m);` btw. to notify user `nick` present in the thread you should add `@nick` to your comment and site will notify the user automatically (not needed for author of the tread which is you here but for all others you should so we see you commented us) – Spektre Apr 25 '18 at 06:45
  • so the `x,y,z` axises and `o` origin are either first 4 columns in matrix (OpenGL) or rows (DirectX) ignoring the last element which holds `w` and projection. – Spektre Apr 25 '18 at 06:48
  • @Spektre my matrix is [this](https://ibb.co/fP8nwx). I guess, that the columns are `x,y,z` and `o`, aren't they? And this are my desired straight, up and right vectors? Because it seems that they are the negativ. Can this be because I didnt invert the viewMatrix? – Gykonik Apr 25 '18 at 08:18
  • @Niklas render them and you will see. They can be both it depends on the multiplication order (`matrix*vector` or `vector*matrix`) is used and the order of matrix storage (row-major,column major) . So easier is to try one render and see if not OK than it is the other. to render the matrix just extract `X,Y,Z,O` and render lines `O,O+X*a` , `O,O+Y*a` and `O,O+Z*a` where `a` is size of the axises to render. The numbers suggest you are using rows (**DirectX** style) so origin is `O(47.5,-47.42,90.82)` I moved the image to this site into your question. It is better to have it here – Spektre Apr 25 '18 at 08:23
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/169760/discussion-between-niklas-and-spektre). – Gykonik Apr 25 '18 at 12:35
  • @Niklas IIRC chat does not notify so you need to check it periodically on your own. I added some stuff there – Spektre Apr 25 '18 at 13:00

0 Answers0