Object, world, camera and projection spaces in OpenGL - opengl

I'm trying to understand creating spaces in OpenGL:
Object space
World space
Camera space
Projection space
Is my understanding of these stages correct?
The "cube" is being created in the center of the cartesian coordinate system, directly inside the program by typing the vertices coordinates.
The coordinates are transformed into coordinates inside of the "world", which means moving it to any place on the screen.
Well, actually I'd like you to check my understanding of those two terms.
Now, I'm creating a triangle on the black screen. How does openGL code fits to these spaces?
It works on GL_MODELVIEW flag by default, but that's the second stage - world space. Does that mean that calling glVertex3f() creates a triangle in the object space?
Where is the world space part?
Also, I've read that the last two spaces are not part of the openGL pipeline (or whatever it's called).
However, OpenGL contains flags such as the GL_PROJECTION, for example:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h); // w - width, h - height
gluPerspective(45, ratio, 1, 100); // radio = w/h
glMatrixMode(GL_MODELVIEW);
What does this code do? It sets the perspective. Does it create the z axis? But isn't it already the object space part?

1) Object space is the object's vertices relative to the object's origin. In the case of a 1x1x1 cube, your vertices would be:
( 0.5, 0.5, 0.5)
(-0.5, 0.5, 0.5)
( 0.5, -0.5, 0.5)
(-0.5, -0.5, 0.5)
etc.
2) World space is where the object is in your world. If you want this cube to be at (15, 10), you'd create a translation matrix that, when multiplied with each vertex, would center your vertices around (15, 10). For example, the first vertex would become (15.5, 10.5, 0.5). The matrix to go from object to world space is called the "model" matrix.
3) Eye Space (sometimes called Camera space) is the world relative to the location of the viewer. Since this has to be a matrix that each vertex is multiplied by, it's technically the inverse of the camera's orientation. That is, if you want a camera at (0, 0, -10), your "view" matrix has to be a translation of (0, 0, 10). That way all the objects in the world are forward 10 units, making it look like you are backwards 10 units.
4) Projection space is how we apply a correct perspective to a scene (assuming you're not using an orthographic projection). This is almost always represented by a frustum, and this article can explain that better than I can. Essentially you are mapping 3d space onto another skewed space.
OpenGL then handles clip space and screen space.
It works on GL_MODELVIEW flag by default, but that's the second stage - world space. Does that mean that calling glVertex3f() creates a triangle in the object space?
You set vertices with glVertex3f() in object space always. (this is actually a very old and slow way to do it, but that's not really the point of this question)
When you set GL_MODELVIEW, it's only changing the model matrix (which can be manipulated with glLoadMatrix, glTranslate, glRotate, glScale, etc.).
Line by line, your piece of code is doing the following:
All transformations will now be affecting the projection matrix.
Clear out the old projection matrix and replace it with the identity matrix.
Use the entire screen as the viewport.
Set the projection matrix to a perspective with a 45 degree vertical field of view with an aspect ratio of w/h, the near-clip plane 1 unit away, and the far-clip plane 100 units away.
All transformations are now affecting the modelview matrix again.
The Z axis already exists, this just sets the projection matrix that gives you perspective, tells OpenGL to use the entire window to render. This isn't the object space, it's the way you transform object space to projection space.
Also a side note, you're using really, really old OpenGL (1992 old). glTranslate, etc. were deprecated a long time ago and are now just removed from the API. The only reason you can still use them is because drivers keep them there for compatibility's sake. I'd recommend you look into using modern (3.0+) OpenGL. Modern graphics pipelines are several orders of magnitude faster than immediate mode (glBegin, glVertex, glEnd).

Related

How models are resized when resizing glViewport() and glFrustum()?

static void resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
We know when we resize window, this resize() is called and viewport is resized. But how models are resized when we change the window size?
What appreas on the screen of course changes when you change the projection matrix or viewport, since that is the whole point of the exercise. If you look at the end result in screen space, the models will of course appear bigger or smaller if the projection or viewport parameters are changed. And mathematically, there is a scale component involved. Since the projection matrix and viewport transform is applied to every vertex in every draw call, you could view this as the models beeing "resized". But one typically doesn't look at things that way.
That's more of a matter of how you look at things. The object space vertices of the models are not changed, neither is the world space position and size (if you like to think in such terms).
We use three different "coordinates" to make sense of a 3D world:
Models, with the positions of their vertices and whatnot, are defined in Model Space. This is the coordinate system that was originally used (for example in Blender) to create the model and define where the vertex positions are.
There can be lots of models, all with different positions, in a world. To make sense of this all, we define World Space. You have to set up a matrix that transforms every model from its Model Space to our global World Space.
Next, there's Eye Space (or Camera Space, or View Space). A matrix that transforms from World Space to Eye Space gives us the ability to easily move our camera around. Eventually, Eye Space is what we will actually "see".
But wait! There's more! Eye Space is only still a bunch of vertices, there's no concept of perspective. In the end, all OpenGL does is render all triangles that are inside a unit cube. This is known as Normalized Device Coordinate Space. To go from Eye Space to Normalized Device Coordinate Space, we apply yet again a matrix, which we usually call the projection matrix at this stage.
Old OpenGL used to have all functionality built in: you are using it yourself when you call
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
This basically says: We want to adjust the projection matrix. Then we set it equal to the identity matrix. Then we use a convenience function called glFrustum to set up the correct projection matrix. The call to glFrustum sets up a perspective projection matrix, i.e. one where "things that are further away become smaller".

Rotation and translation of the Earth opengl c++

I am trying to get a sphere to rotate around another simulating the orbit of the Earth.
I am able to get the Earth to orbit around the sun; however, I can't get it to rotate around itself.
This is the code I have so far:
//sun
glMaterialAmbientAndDiffuse(GLMaterialEnums::FRONT,GLColor<GLfloat,4>(1.5f,1.0f,0.0f));
glTranslate(0.0f, 0.0f, 0.0f);
glRotate(15.0, 1.0, 0.0, 0.0);
drawEllipsoid(10.0, 1.0, 4, 4);
glPushMatrix();
//Earth
glMaterialAmbientAndDiffuse(GLMaterialEnums::FRONT,GLColor<GLfloat,4>(0.5f,10.5f,10.5f));
glRotate(orbit,Vrui::Vector(0,0,1));
glTranslate(105.0, 0.0, 0.0);
drawPlanetGrid(5, 1, 4, 4, 1);
glPopMatrix();
orbit += .1;
if (orbit > 360)
{
orbit = 0;
}
Could anyone help me move in the right direction? I also needed to know how I can get the Earth to orbit around the sun in a tilted angle.
Basically, you need to manage some model matrices. The sun's model matrix (if centered in (0,0,0) has just a rotational part). The earth rotating around the sun, needs a model matrix which is first rotated and then translated to be placed in the orbit of the sun. So when calculating a new frame you increase your rotation parameter, create the rotation and then apply the translation. If you want to add a moon, you need another model matrix, which is accumulated. That is, the moon needs a separate rotation and translation (like the sun) but you have to account also for the transformation of the earth. Make sure that you understand what a transformation matrix does. In that case the transformation matrix is just a coordinate transformation. So, you have your sun, earth and moon in a local frame. The model matrices achieve the transformation from local coordinate system to the world coordinate system. The view matrix transforms world coordinates to eye coordinates. And then there is only projection left for you.
To solve this, you need to understand the idea of co-ordinate systems and how to use them within OpenGL.
A co-ordinate system is just a set of points that share the same XYZ axes. In each system, the XYZ axes do not necessarily point in the same direction, so in one system moving in positive X could move in negative Y in other system. To convert points from one system to another you use a transformation matrix.
A scene is made up of several co-ordinate systems:-
World space
Camera space (or view space)
Object space
Model space
So, your model (the Earth, say) has a transformation from its model space to object space - this is the rotation of the earth around the vertical axis. Then it has a transformation from object space to world space - this is the translation about the sun and tilting. The final transformation is from world space to camera space.
So, you need three matrices to put your Earth model into the right place on screen. this may seem like a lot of processing, but the thing about these matrices is that they can be multiplied together to form a single object->camera space matrix.
Once you've set up the scene using the various co-ordinate systems and transformations, it should work.
You may want to work with cubes rather than spheres to start with as it's easier to follow what is happening to the vertices as they're being transformed.

OpenGL define vertex position in pixels

I've been writing a 2D basic game engine in OpenGL/C++ and learning everything as I go along. I'm still rather confused about defining vertices and their "position". That is, I'm still trying to understand the vertex-to-pixels conversion mechanism of OpenGL. Can it be explained briefly or can someone point to an article or something that'll explain this. Thanks!
This is rather basic knowledge that your favourite OpenGL learning resource should teach you as one of the first things. But anyway the standard OpenGL pipeline is as follows:
The vertex position is transformed from object-space (local to some object) into world-space (in respect to some global coordinate system). This transformation specifies where your object (to which the vertices belong) is located in the world
Now the world-space position is transformed into camera/view-space. This transformation is determined by the position and orientation of the virtual camera by which you see the scene. In OpenGL these two transformations are actually combined into one, the modelview matrix, which directly transforms your vertices from object-space to view-space.
Next the projection transformation is applied. Whereas the modelview transformation should consist only of affine transformations (rotation, translation, scaling), the projection transformation can be a perspective one, which basically distorts the objects to realize a real perspective view (with farther away objects being smaller). But in your case of a 2D view it will probably be an orthographic projection, that does nothing more than a translation and scaling. This transformation is represented in OpenGL by the projection matrix.
After these 3 (or 2) transformations (and then following perspective division by the w component, which actually realizes the perspective distortion, if any) what you have are normalized device coordinates. This means after these transformations the coordinates of the visible objects should be in the range [-1,1]. Everything outside this range is clipped away.
In a final step the viewport transformation is applied and the coordinates are transformed from the [-1,1] range into the [0,w]x[0,h]x[0,1] cube (assuming a glViewport(0, w, 0, h) call), which are the vertex' final positions in the framebuffer and therefore its pixel coordinates.
When using a vertex shader, steps 1 to 3 are actually done in the shader and can therefore be done in any way you like, but usually one conforms to this standard modelview -> projection pipeline, too.
The main thing to keep in mind is, that after the modelview and projection transforms every vertex with coordinates outside the [-1,1] range will be clipped away. So the [-1,1]-box determines your visible scene after these two transformations.
So from your question I assume you want to use a 2D coordinate system with units of pixels for your vertex coordinates and transformations? In this case this is best done by using glOrtho(0.0, w, 0.0, h, -1.0, 1.0) with w and h being the dimensions of your viewport. This basically counters the viewport transformation and therefore transforms your vertices from the [0,w]x[0,h]x[-1,1]-box into the [-1,1]-box, which the viewport transformation then transforms back to the [0,w]x[0,h]x[0,1]-box.
These have been quite general explanations without mentioning that the actual transformations are done by matrix-vector-multiplications and without talking about homogenous coordinates, but they should have explained the essentials. This documentation of gluProject might also give you some insight, as it actually models the transformation pipeline for a single vertex. But in this documentation they actually forgot to mention the division by the w component (v" = v' / v'(3)) after the v' = P x M x v step.
EDIT: Don't forget to look at the first link in epatel's answer, which explains the transformation pipeline a bit more practical and detailed.
It is called transformation.
Vertices are set in 3D coordinates which is transformed into a viewport coordinates (into your window view). This transformation can be set in various ways. Orthogonal transformation can be easiest to understand as a starter.
http://www.songho.ca/opengl/gl_transform.html
http://www.opengl.org/wiki/Vertex_Transformation
http://www.falloutsoftware.com/tutorials/gl/gl5.htm
Firstly be aware that OpenGL not uses standard pixel coordinates. I mean by that for particular resolution, ie. 800x600 you dont have horizontal coordinates in range 0-799 or 1-800 stepped by one. You rather have coordinates ranged from -1 to 1 later send to graphic card rasterizing unit and after that matched to particular resolution.
I ommited one step here - before all that you have an ModelViewProjection matrix (or viewProjection matrix in some simple cases) which before all that will cast coordinates you use to an projection plane. Default use of that is to implement a camera which converts 3D space of world (View for placing an camera into right position and Projection for casting 3d coordinates into screen plane. In ModelViewProjection it's also step of placing a model into right place in world).
Another case (and you can use Projection matrix this way to achieve what you want) is to use these matrixes to convert one range of resolutions to another.
And there's a trick you will need. You should read about modelViewProjection matrix and camera in openGL if you want to go serious. But for now I will tell you that with proper matrix you can just cast your own coordinate system (and ie. use ranges 0-799 horizontaly and 0-599 verticaly) to standarized -1:1 range. That way you will not see that underlying openGL api uses his own -1 to 1 system.
The easiest way to achieve this is glOrtho function. Here's the link to documentation:
http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml
This is example of proper usage:
glMatrixMode (GL_PROJECTION)
glLoadIdentity ();
glOrtho (0, 800, 600, 0, 0, 1)
glMatrixMode (GL_MODELVIEW)
Now you can use own modelView matrix ie. for translation (moving) objects but don't touch your projection example. This code should be executed before any drawing commands. (Can be after initializing opengl in fact if you wont use 3d graphics).
And here's working example: http://nehe.gamedev.net/tutorial/2d_texture_font/18002/
Just draw your figures instead of drawing text. And there is another thing - glPushMatrix and glPopMatrix for choosen matrix (in this example projection matrix) - you wont use that until you combining 3d with 2d rendering.
And you can still use model matrix (ie. for placing tiles somewhere in world) and view matrix (in example for zooming view, or scrolling through world - in this case your world can be larger than resolution and you could crop view by simple translations)
After looking at my answer I see it's a little chaotic but If you confused - just read about Model, View, and Projection matixes and try example with glOrtho. If you're still confused feel free to ask.
MSDN has a great explanation. It may be in terms of DirectX but OpenGL is more-or-less the same.
Google for "opengl rendering pipeline". The first five articles all provide good expositions.
The key transition from vertices to pixels (actually, fragments, but you won't be too far off if you think "pixels") is in the rasterization stage, which occurs after all vertices have been transformed from world-coordinates to screen coordinates and clipped.

Creating a tiled world with OpenGL

I'm planning to create a tiled world with OpenGL, with slightly rotated tiles and houses and building in the world will be made of models.
Can anybody suggest me what projection(Orthogonal, Perspective) should I use, and how to setup the View matrix(using OpenGL)?
If you can't figure what style of world I'm planning to create, look at this game:
http://www.youtube.com/watch?v=i6eYtLjFu-Y&feature=PlayList&p=00E63EDCF757EADF&index=2
Using Orhtogonal vs Perspective projection is entirely an art style choice. The Pokemon serious you're talking about is orthogonal -- in fact, it's entirely layered 2D sprites (no 3D involved).
OpenGL has no VIEW matrix. It has a MODELVIEW matrix and a PROJECTION matrix. For Pokemon-style levels, I suggest using simple glOrtho for the projection.
Let's assume your world is in XY space (coordinates for tiles, cameras, and other objects are of the form [x, y, 0]). If a single tile is sized 1,1, then something like glOrtho(12, 9, -10, 10) would be a good projection matrix (12 wide, 9 tall, and Z=0 is the ground plane).
For MODELVIEW, you can start by loading identity, glTranslate() by the tile position, and then glTranslate() by the negative of the camera position, before you draw your geometry. If you want to be able to rotate the camera, you glRotate() by the negative (inverse) of the camera rotation between the two Translate()s. In the end, you end up with the following matrix chain:
output = Projection × (CameraTranslation-1 × CameraRotation-1 × ModelLocation × ModelRotation) × input
The parts in parens are MODELVIEW, and the "-1" means "inverse" which really is negative for translation and transpose for rotation.
If you want to rotate your models, too, you generally do that first of all (before the first glTranslate().
Finally, I suggest the OpenGL forums (www.opengl.org) or the OpenGL subforums of www.gamedev.net might be a better place to ask this question :-)
The projection used by that video game looks Oblique to me. There are many different projections, not just perspective and orthographic. See here for a list of the most common ones: http://en.wikipedia.org/wiki/File:Graphical_projection_comparison.png
You definitely want perspective, with a fixed rotation around the X-axis only. Around 45-60 degrees or thereof. If you don't care about setting up the projection code yourself, the gluPerspective function from the GLU library is handy.
Assuming OpenGL 2.1:
glMatrixMode(GL_PROJECTION); //clip matrix
glLoadIdentity();
gluPerspective(90.0, width/height, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW); //world/object matrix
glLoadIdentity();
glRotatef(45.0f, 1.0f, 0.0f, 0.0f);
/* render */
The last two parameters to gluPerspective is the distance to the near and far clipping planes. Their values depend on the scale you use for the environment.

OpenGL Rotation

I'm trying to do a simple rotation in OpenGL but must be missing the point.
I'm not looking for a specific fix so much as a quick explanation or link that explains OpenGL rotation more generally.
At the moment I have code like this:
glPushMatrix();
glRotatef(90.0, 0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 3.0, 2.0, 0.0 );
glVertex3f( 3.0, 1.0, 0.0 );
glEnd();
glPopMatrix();
But the result is not a triangle rotated 90 degrees.
Edit
Hmm thanks to Mike Haboustak - it appeared my code was calling a SetCamera function that use glOrtho. I'm too new to OpenGL to have any idea of what this meant but disabling this and rotating in the Z-axis produced the desired result.
Ensure that you're modifying the modelview matrix by putting the following before the glRotatef call:
glMatrixMode(GL_MODELVIEW);
Otherwise, you may be modifying either the projection or a texture matrix instead.
Do you get a 1 unit straight line? It seems that 90deg rot. around Y is going to have you looking at the side of a triangle with no depth.
You should try rotating around the Z axis instead and see if you get something that makes more sense.
OpenGL has two matrices related to the display of geometry, the ModelView and the Projection. Both are applied to coordinates before the data becomes visible on the screen. First the ModelView matrix is applied, transforming the data from model space into view space. Then the Projection matrix is applied with transforms the data from view space for "projection" on your 2D monitor.
ModelView is used to position multiple objects to their locations in the "world", Projection is used to position the objects onto the screen.
Your code seems fine, so I assume from reading the documentation you know what the nature of functions like glPushMatrix() is. If rotating around Z still doesn't make sense, verify that you're editing the ModelView matrix by calling glMatrixMode.
The "accepted answer" is not fully correct - rotating around the Z will not help you see this triangle unless you've done some strange things prior to this code. Removing a glOrtho(...) call might have corrected the problem in this case, but you still have a couple of other issues.
Two major problems with the code as written:
Have you positioned the camera previously? In OpenGL, the camera is located at the origin, looking down the Z axis, with positive Y as up. In this case, the triangle is being drawn in the same plane as your eye, but up and to the right. Unless you have a very strange projection matrix, you won't see it. gluLookat() is the easiest command to do this, but any command that moves the current matrix (which should be MODELVIEW) can be made to work.
You are drawing the triangle in a left handed, or clockwise method, whereas the default for OpenGL is a right handed, or counterclockwise coordinate system. This means that, if you are culling backfaces (which you are probably not, but will likely move onto as you get more advanced), you would not see the triangle as expected. To see the problem, put your right hand in front of your face and, imagining it is in the X-Y plane, move your fingers in the order you draw the vertices (1,1) to (3,2) to (3,1). When you do this, your thumb is facing away from your face, meaning you are looking at the back side of the triangle. You need to get into the habit of drawing faces in a right handed method, since that is the common way it is done in OpenGL.
The best thing I can recommend is to use the NeHe tutorials - http://nehe.gamedev.net/. They begin by showing you how to set up OpenGL in several systems, move onto drawing triangles, and continue slowly and surely to more advanced topics. They are very easy to follow.
Regarding Projection matrix, you can find a good source to start with here:
http://msdn.microsoft.com/en-us/library/bb147302(VS.85).aspx
It explains a bit about how to construct one type of projection matrix. Orthographic projection is the very basic/primitive form of such a matrix and basically what is does is taking 2 of the 3 axes coordinates and project them to the screen (you can still flip axes and scale them but there is no warp or perspective effect).
transformation of matrices is most likely one of the most important things when rendering in 3D and basically involves 3 matrix stages:
Transform1 = Object coordinates system to World (for example - object rotation and scale)
Transform2 = World coordinates system to Camera (placing the object in the right place)
Transform3 = Camera coordinates system to Screen space (projecting to screen)
Usually the 3 matrix multiplication result is referred to as the WorldViewProjection matrix (if you ever bump into this term), since it transforms the coordinates from Model space through World, then to Camera and finally to the screen representation.
Have fun