In this example I am confused about the use of rotate and translate, more specifically,
// The earth rotates around the sun
pushMatrix();
rotate(theta);
translate(50,0);
fill(50,200,255);
ellipse(0,0,10,10);
What does rotate(theta); rotate? What is the relation of rotate and translate?
rotate and translate are acting on the current coordinate system.
i.e. draw actions (rect(), ellipse(), etc...) will apply within a the current coordinate system. where rotate & translate will move the coordinate system.
prior to the block of code you supplied, the current point was translated to the center of the window in order to draw the sun.
pushMatrix() saves that position and then relative to the suns center, "everything" (the coordinate system) is rotated by theta, and "everything" is translated by (50,0) effectively moving the "current point" to the correct position to then draw the earth using ellipse(0,0,10,10).
Note you could probably omit the translate step and use ellipse(50,0,10,10) to get the same visual result, if it were not for the fact that the next code block is dependent on that translate to get the moon position correctly.
Here is an interesting link which explains this in terms of "moving the graph paper";
Related
for a personal project, I've created a simple 3D engine in python using as little libraries as possible. I did what I wanted - I am able to render simple polygons, and have a movable camera. However, there is a problem:
I implemented a simple flat shader, but in order for it to work, I need to know the camera location (the camera is my light source). However, the problem is that I have no way of knowing the camera's location in the world space. At any point, I am able to display my view matrix, but I am unsure about how to extract the camera's location from it, especially after I rotate the camera. Here is a screenshot of my engine with the view matrix. The camera has not been rotated yet and it is very simple to extract its location (0, 1, 4).
However, upon moving the camera to a point between the X and Z axes and pointing it upwards (and staying at the same height), the view matrix changes to this:
It is obvious now that the last column cannot be taken directly to determine the camera location (it should be something like (4,1,4) on the last picture).
I have tried a lot of math, but I can't figure out the way to determine the camera x,y,z location from the view matrix. I will appreciate any and all help in solving this, as it seems to be a simple problem, yet whose solution eludes me. Thank you.
EDIT:
I was advised to transform a vertex (0,0,0,1) by my view matrix. This, however, does not work. See the example (the vertex obviously is not located at the printed coordinates):
Just take the transform of the vector (0,0,0,1) with the modelview matrix: Which is simply the rightmost column of the modelview matrix.
EDIT: #ampersander: I wonder why you're trying to work with the camera location in the first place, if you assume the source of illumination to be located at the camera's position. In that case, just be aware, that in OpenGL there is no such thing as a camera, and in fact, what the "view" transform does, is move everything in the world around so that where you assume your camera to be ends up at the coordinate origin (0,0,0).
Or in other words: After the modelview transform, the transformed vertex position is in fact the vector from the camera to the vertex, in view space. Which means that for your assumed illumination calculation the direction toward the light source, is the negative vertex position. Take that, normalize it to unit length and stick it into the illumination term.
I'm working on my raytracer and it seems I can't manage to handle the case where the direction vector of my camera is parallel to the vector (0,1,0).
I think it is linked to my way to compute the vector up and right for camera but I can't manage to find a work around.
Here is how I do it:
cam_up = vector_cross(cam_dir, {0, 1, 0});
camp_right = vector_cross(cam_right, cam_dir);
Can somebody enlighten me?
You have the correct formula for calculation of an orthogonal axis from a single cameraOut vector. However, as has been stated this formula will not account for the camera roll, which could be any direction in the plane perpendicular to the camera direction. This will be apparent when moving a camera across the pole (y-axis) as there will be undesireable behavior (yes it will be correctly aimed, but no doubt the roll won't be desired).
For more information, look into gimbal lock.
The roll itself is not really incorrect, however in reality for this camera transition to be smooth and appear correct (rather than suddenly flip or spin as it's direction becomes 0,1,0), you need to correct any roll incurred. This is a rotation about the cameraOut axis and ideally should be relative to the previous cameraAlong. This means in order to maintain the correct roll (or perceived correct roll) you need to consider the camera POSE (position and orientation) from the previous frame and ensure the roll is mitigated. Of course, if the camera doesn't move (i.e. your rendering a frame with a static camera position) you do not have a previous camera state so the position cannot be calculated and instead must be explicitly defined as part of the scene definition.
Personally I store an entire orthogonal axis for a camera so the orientation and roll is always clearly defined. This is only for completeness, to be honest you don't need to store the entire axis, 2 vectors cameraOut and cameraAlong (the third one being cameraUp) are enough. cameraAlong is dependant on the handed-ness of your coordinate system (e.g. for initial camera position say position (0,0,0) in left hand coordinate system, the cameraAlong direction will be in the right direction in relation to the viewer, for right hand system the cameraAlong would be the other way around. The cameraUp and cameraOut would are the same in both coordinate systems).
Hope this helps.
P.S This isn't ray tracing specific and the same principles apply for OpenGL/DirectX or any 3D representation.
Here is the deal, I'm programming a 2D framework/game engine with opengl ES. I am using VBOs and an ortho projection to draw an arrangement of sprites throughout the screen (as part of the testing), and everything was going nice and smooth until I had to play with translations and rotations. The specific problem I am having is that when I apply a translation with glTranslatef() prior to the rotation, the function does not only move the sprite, but also my origin, messing up my whole transformation. I am 100% sure it is working this way, because I used glTranslatef() to move to the right and bottom the sprite half of the size of the screen (yes, my origin is in the top left) and then apply a constant rotation and the thing just keeps mooving in a circular path around the center of the screen (actually rotating, but not as I expect.
If you want some code, here we go:
gl.glTranslatef(-(x+width/2), -(y+height/2), -layer);
gl.glRotatef(angle, 0.0f, 0.0f, -1.0f);
gl.glTranslatef(x+width/2, y+height/2, layer);
In this fragment of code, x and y are the position of the sprite, height and width are the size of the sprite, angle the angle of rotation, and layer just a form of organizing the sprites into several layers, pretty straight forward, right?
Again, my problem is that glTranslatef(); is moving both, the sprite and the origin, am I doing something wrong or misunderstanding something about the translation?
Thanks in advance.
you might need to use glPushMatrix and glPopMatrix since anything you do after those translations and rotations will be affected by them
but what you are describing is actually how it works, if you use a translate, that sort of becomes your new origin because once you do a translate, everything after that is affected by that translate, thats why you need to push and pop, so that you can go, push -> translate object and/or rotate -> pop, and then you can go about with whatever other translations you need to do without having that previous translation affecting everything else
its a bit confusing at first but google around and you'll see how to use them properly
http://www.khronos.org/opengles/sdk/1.1/docs/man/glPushMatrix.xml
I think you misunderstood how matrices work in openGL. When you do a matrix operation such as glRotatef and glTranslatef the matrices are being multiplied, resulting in affecting the base vectors.. For instance, let's say we are only drawing a point that starts at (0,0,0). If you call translate(1,0,0) the point will be in (1,0,0), after that you call rotate(90, 0, 0, 1) and your point will be on the same place as before but rotated. Now the last call is translate(-1,0,0) and your point is at (1,-1,0) (and not where you started)!
And that is what you did in your "fragment of code". The thing is you did not specify what you really want to do and how do you define your verices is relative as well.. If you want something like a view with some image that you want to control in sense of changing the position and rotation, you might want to create a square vertex buffer with values from -1 to 1 in both dimensions (or (-width/2, -height/2) to (width/2, height/2)). In this case the base center of your object is in (0,0,0) and that is probably the point you want to rotate it around (or am I wrong here?). So when you want to define the position of the object with origin point, you will need to write translatef(x+width/2,y+height/2,..).
As for the whole process of drawing in this case: If you want the origin to be at (x,y,z), with a (width, height) and rotated by (angle) here is the sequence
glTranslatef(x,y,z)
glTranslatef(width/2,height/2,0)
glScalef(width/2,height/2, 1) //only if verices defined at (-1,1)
glRotatef(angle, 0, 0, 1)
Do note in this case that since you rotate the object around its center its origin will not be at (x,y,z) anymore.
In general I would suggest to stay away from glRotate, glTranslate and glScale if possible. They tend to make things very nasty. So another way is to construct a matrix directly from base vectors: With little math you can compute all 4 points of your "square view" based on parameters such as origin, width, height and rotation.. The 4 points being (A-origin), (B-lower left point), (C-lower right point), (D-upper right point) your base vectors are (B-A), (D-A) and normalized(dotProduct((B-A), (D-A))) this 3 vectors can be inserted int top left 3x3 matrix of the GL matrix (witch is 4x4 or float[16]) and they represent both, rotation and scale so all you need to add is the translation part (just google around a bit for this approach).
Given the 3D vector of the direction that the camera is facing and the orientation/direction vector of a 3D object in the 3D space, how can I calculate the 2-dimensional slope that the mouse pointer must follow on the screen in order to visually be moving along the direction of said object?
Basically I'd like to be able to click on an arrow and make it move back and forth by dragging it, but only if the mouse pointer drags (roughly) along the length of the arrow, i.e. in the direction that it's pointing to.
thank you
I'm not sure I 100% understand your question. Would you mind posting a diagram?
You might find these of interest. I answered previous questions to calculate a local X Y Z axis given a camera direction (look at) vector, and also a question to translate an object in a plane parallel to the camera.
Both of these examples use Vector dot product, Vector cross product to compute the required vectors. In your example the vector dot product can be also used to output the angle between two vectors once you have found them.
It depends to an extent on the transformation that you are using to convert your 3d real world coordinates to 2d screen coordinates, e.g. perspective, isometric, etc... You will typically have a forward (3d -> 2d) and backward (2d -> 3d) transformation in play, where the backward transformation loses information. (i.e. going forward each 3d point will map to a unique 2d point, but going back from the point may not yield the same 3d point). You can often project the mouse point onto the object to get the missing dimension.
For mouse dragging, you typically get the user to specify an operation (translation on the plane of projection, zooming in or out, or rotating about an anchor point). Your input is the mouse coordinate at the start and end of the drag, which you transform into your 3d coordinate system to get two 3d coordinates, which will give you dx, dy, dz for dragging / translation etc...
I'm a fresh in cocos3d, now I have a problem.
In cocos3d, I want to rotate a node. I got the angles in x axis, y axis, z axis, then I used the property:rotation to rotate, like this:
theNodeToBeRotated.rotation = cc3v(x,y,z);
But I found out it didn't rotate as I expected, because the document said the rotate order is y-x-z.
I want to change the order to x-y-z. Can anyone let me know how?
You might need to clarify further regarding the following: "it didn't rotate as I expected"
OpenGL ES (and ergo, cocos3D) uses the y-axis as up so the rotation order is still x-y-z. If you are importing a model, you then need to take into account the 3D editor's co-ordinate system and adapt accordingly.
If you are not used to working with three-dimensional representations, the leap from 2D to 3D can be a significant hurdle. Within Cocos3D:
the x-axis is positive on the right and negative on the left
the y-axis is positive upwards and negative downwards
the z-axis is positive moving towards you and negative moving away from you
Envisage those three lines of axis, or even better, a piece of string.
If you are rotating around the x-axis, hold the string horizontally from left to right: the object would rotating towards you or away from you.
If you are rotating around the y-axis, hold the string vertically from feet to head: the object would rotate as if like a revolving door.
If you are rotating around the z-axis, hold one end close to your chest and the other end as far away as possible: the object would rotate similar to a clock face.
-- Update
I heavily wouldn't recommend changing the rotation order as it is the OpenGL standard to use Y-X-Z. If you wish to modify it, take a look at CC3GLMatrixMath and look for kmMat4RotationYXZ - there is also kmMat4RotationZYX. If you want to have X-Y-Z, you would need to construct your own rotation matrix and update accordingly in CC3GLMatrix and CC3GLMatrixMath.
As a reference, you also have the OpenGL Red book - it should have some suggestions for you.