Sign in to follow this  
davidr

OpenGL GL_MODELVIEW matrix confusion

Recommended Posts

Hi, I have some experience with Direct3D, but I'm new to OpenGL. I'm having problems drawing a cube at an arbitrary location in the world. I managed to get things working using gluLookAt, but I'd prefer to create the view matrix myself then multiply it by the current objects world matrix e.g. glLoadMatrixd( camera.viewMatrix() * object.worldMatrix() ); So, the current setup is the object is located at the origin, with: right vector = <1, 0, 0> up vector = <0, 1, 0> look vector = <0, 0, -1> The camera is located at <0, 0, 10>. Its right, up, and look vectors are identical to the object (I'm not doing any rotations at the moment). The view matrix created by Camera::viewMatrix is:
"[         1,          0,          0,          0]
[         0,          1,          0,          0]
[         0,          0,         -1,        -10]
[         0,          0,          0,          1]" 

const GLdouble* Camera_Class::View_Matrix(void)
{
	if (m_View_Matrix_Dirty == false) 
	{
		return m_View_Matrix;
	}

	// Row 1
	m_View_Matrix[0] = m_Right_Vector[0];
	m_View_Matrix[1] = m_Right_Vector[1];
	m_View_Matrix[2] = m_Right_Vector[2];
	m_View_Matrix[3] = -1.0 * (m_Position_Vector * m_Right_Vector);
	// Row 2
	m_View_Matrix[4] = m_Up_Vector[0];
	m_View_Matrix[5] = m_Up_Vector[1];
	m_View_Matrix[6] = m_Up_Vector[2];
	m_View_Matrix[7] = -1.0 * (m_Position_Vector * m_Up_Vector);
	// Row 3
	m_View_Matrix[8] = m_Look_Vector[0];
	m_View_Matrix[9] = m_Look_Vector[1];
	m_View_Matrix[10] = m_Look_Vector[2];
	m_View_Matrix[11] = -1.0 * (m_Position_Vector * m_Look_Vector);
	// Row 4
	m_View_Matrix[12] = 0.0;
	m_View_Matrix[13] = 0.0;
	m_View_Matrix[14] = 0.0;
	m_View_Matrix[15] = 1.0;

	m_View_Matrix_Dirty = false;

	return m_View_Matrix;
}

Here is the paint function:
void OpenGL_Widget_Class::paintGL(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	
	glLoadMatrixd(m_Camera.View_Matrix());
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_INDEX_ARRAY);

	glVertexPointer(3, GL_DOUBLE, 0, m_Vertices);
	glColorPointer(4, GL_DOUBLE, 0, m_Colors);
	glIndexPointer(GL_INT, 0, m_Indices);

	// Row major
	// world_matrix = yaw * pitch * roll * world_matrix

	// Column major
	// world_matrix = ((world_matrix * roll) * pitch) * yaw

	for(QList<Object_Class*>::iterator iter = m_Cube_Objects.begin(); iter != m_Cube_Objects.end(); ++iter)
	{
		glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, m_Indices);
	}
	
	glFlush();
}

Other info: the near and far planes are set to 1 and 1000. Many thanks,

Share this post


Link to post
Share on other sites
Ok some notes/tips:

GL stores things in column order your matrix should be:


[1, 0, 0, 0,
0, 1, 0, 0,
0, 0, -1, 0,
0, 0, 10, 1 ]

then try:

glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(object); //object/camera may need to be switched, not sure cuz I
glMultMatrixd(camera); //never use LoadMatrix


You should let GL do things, because it's an API that does things uniformly and you don't have to worry about things like column order.

Make sure to use glMatrixMode(GL_MODELVIEW)

Share this post


Link to post
Share on other sites
Hi,

Thanks for the tips.

Re your comments about the view matrix, according to my math book, if you are using column vectors, e.g. v' = m*v, then the view matrix should look like:


/*
right_x, right_y, right_z, -(position dot right)
up_x, up_y, look_z, -(position dot up)
look_x, up_y, look_z, -(position dot look)
0, 0, 0, 1
*/




I also understand that i (row index), j (column index) refers to the jth row and ith column in an OpenGL matrix. Keeping both these things in mind, I rewrote my View_Matrix function:


const GLdouble* Camera_Class::View_Matrix(void)
{
/*
Regular matrix

0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15

OpenGL matrix

0, 4, 8, 12,
1, 5, 9, 13,
2, 6, 10, 14,
3, 7, 11, 15,

The first row of the matrix occupies elements 0, 4, 8, 12 - not 0, 1, 2, 3

*/


if (m_View_Matrix_Dirty == false)
{
return m_View_Matrix;
}

// First row of OpenGL matrix
m_View_Matrix[0] = m_Right_Vector[0];
m_View_Matrix[4] = m_Right_Vector[1];
m_View_Matrix[8] = m_Right_Vector[2];
m_View_Matrix[12] = -1 * (m_Position_Vector * m_Right_Vector);
// Second row of OpenGL matrix
m_View_Matrix[1] = m_Up_Vector[0];
m_View_Matrix[5] = m_Up_Vector[1];
m_View_Matrix[9] = m_Up_Vector[2];
m_View_Matrix[13] = -1 * (m_Position_Vector * m_Up_Vector);
// Third row of OpenGL matrix
m_View_Matrix[2] = m_Look_Vector[0];
m_View_Matrix[6] = m_Look_Vector[1];
m_View_Matrix[10] = m_Look_Vector[2];
m_View_Matrix[14] = -1 * (m_Position_Vector * m_Look_Vector);
// Fourth row of OpenGL matrix
m_View_Matrix[3] = 0.0;
m_View_Matrix[7] = 0.0;
m_View_Matrix[11] = 0.0;
m_View_Matrix[15] = 1.0;

m_View_Matrix_Dirty = false;

return m_View_Matrix;
}



If the camera is positioned at the origin, this produces a view matrix that is an identity matrix.


[ 1, 0, 0, 0]
[ 0, 1, 0, 0]
[ 0, 0, -1, 0]
[ 0, 0, 0, 1]



My object is positioned 4 units in front of the camera. Its world matrix is:


[ 1, 0, 0, 0]
[ 0, 1, 0, 0]
[ 0, 0, 1, -4]
[ 0, 0, 0, 1]



In the paint function, I multiply the view matrix by the world matrix, then paint the object (a 2x2 cube).

e.g. Result_Matrix = View_Matrix * World_Matrix

The result is a black screen.

Setting the objects position to 4 made the cube visible.

This is a bit confusing because I understood that in OpenGL the +z-axis extends "out of the screen", and the -z-axis into the screen. To move an object in the direction of the world z-axis I'd normally do something like (<0, 0, -1> * distance) + object_position, but that does not work in this case, or my view matrix is still wrong :(

Anyway,

Thanks again

Share this post


Link to post
Share on other sites
Your identity matrix has a -1 for the z-axis, so its not the identity..... In any system regardless of the z+ direction, the identity is still all 1's......

So there forefore, you had to switch your translation to this "new system" where you flipped the z-axis.

Share this post


Link to post
Share on other sites
Quote:
Original post by dpadam450
GL stores things in column order your matrix should be:
Thats actually not quite true...

Quote:

Column-major versus row-major is purely a notational convention. Note that post-multiplying with column-major matrices produces the same result as pre-multiplying with row-major matrices. The OpenGL Specification and the OpenGL Reference Manual both use column-major notation. You can use any notation, as long as it's clearly stated.

Sadly, the use of column-major format in the spec and blue book has resulted in endless confusion in the OpenGL programming community. Column-major notation suggests that matrices are not laid out in memory as a programmer would expect.

Share this post


Link to post
Share on other sites
Yea I've never heard of that, but that doesn't make sense because you cant have both unless there is an option to say "hey I want them row major now". I see what its saying but anytime you print a GL matrix, its always column major, even in GLSL. So can you tell GL how you want it?

Share this post


Link to post
Share on other sites
Quote:
Original post by dpadam450
Your identity matrix has a -1 for the z-axis, so its not the identity..... In any system regardless of the z+ direction, the identity is still all 1's......

So there forefore, you had to switch your translation to this "new system" where you flipped the z-axis.


Hi,

OK - I set my camera's look vector to <0, 0, 1>, the camera's position to <0, 0, 1>, and the cubes position to <0, 0, -2>.

If +z coordinates are behind the origin, and -z coordinates are in front of the origin, I can visualise this in my head, but the camera's look vector is pointing away from the cube - not at it.

In D3D, if the camera's look vector is <0, 0, 1>, then (a) <0, 0, 10> is a point in front of the origin, and (b) <0, 0, -10> is a point behind the origin.

<0, 0, 0> + (camera_look_vector * 10) = <0, 0, 10> (a).

I would expect things to work the same in OpenGL i.e.

Look vector = <0, 0, -1>
a = <0, 0, -10> // in front of the origin
b = <0, 0, 10> // behind the origin

<0, 0, 0> + (camera_look_vector * 10) = <0, 0, -10> (a)

Do you see what I'm getting at? I'm just trying to get this sorted in my head.

Thanks











Share this post


Link to post
Share on other sites
Ok your having coordinate problems un-related to openGL.

Image your origin is the middle of your screen. If your look vector is 0,0,1, then your looking down the positive z-axis, or outward from your pc screen. Your only going to see things that have a positive z-coordinate....


Again, you have this z- concept because your saying "OpenGL's z+ is DX's z-", which is true.......IFFFFF you want to describe GL in terms of DX.

So give this frame if your camera matrix is the identity matrix and remember the z- is the vector into the screen, then anything you see needs to be in the z- axis.

Got it? Again, in your case here, your camera is looking out towards your face, and your cube is behind your pc screen..... complete opposite directions.

[code]
OpenGL frame

y
|
|
|______ x
/
/z

Share this post


Link to post
Share on other sites
Quote:
Original post by dpadam450
Ok your having coordinate problems un-related to openGL.

Image your origin is the middle of your screen. If your look vector is 0,0,1, then your looking down the positive z-axis, or outward from your pc screen. Your only going to see things that have a positive z-coordinate....


Again, you have this z- concept because your saying "OpenGL's z+ is DX's z-", which is true.......IFFFFF you want to describe GL in terms of DX.

So give this frame if your camera matrix is the identity matrix and remember the z- is the vector into the screen, then anything you see needs to be in the z- axis.

Got it? Again, in your case here, your camera is looking out towards your face, and your cube is behind your pc screen..... complete opposite directions.

[code]
OpenGL frame

y
|
|
|______ x
/
/z


Thanks for the clarification.

In view space, the camera's vectors are aligned with <1, 0, 0>, <0, 1, 0>, and <0, 0, 1>, and objects need to have a position such as <x, y, -z> in order to be visible because OpenGL uses a right-handed coordinate system.

Anyway, things seem to be working now.

Share this post


Link to post
Share on other sites

/* transform matrix */
Vector3f n = view - eye; //look
Vector3f u = n.Cross(up); //right

//Vector3f v = n.Cross(u); //left-handed - ???
Vector3f v = u.Cross(n); //right-handed - currently I used this

u = u.Normalize();
v = v.Normalize();
n = n.Normalize();

/* make n as -z (negative z) in OpenGL (we look to the negative OpenGL) */
n = -n; //now become left-handed

//translation
Vector3f t = Vector3f(-eye.Dot(u), -eye.Dot(v), -eye.Dot(n));

/* interpreting as column-major like this in OpenGL
* ( u.x, u.y, u.z, t.x,
* v.x, v.y, v.z, t.y,
* n.x, n.y, n.z, t.z,
* 0 , 0, 0, 1 ) */


GLfloat m[] = { //so the matrix must be like this:
u.x, v.x, n.x, 0,
u.y, v.y, n.y, 0,
u.z, v.z, n.z, 0,
t.x, t.y, t.z, 1
};



I tested this transformation and gained the same result as gluLookAt method.
But now I'm having a problem deriving this for the billboard. The billboard code is like this:


Vector3f n = vecView; //vector from object of billboard to camera
Vector3f u = vecUp.Cross(n); /* !!! Point to the left??? */
Vector3f v = n.Cross(u);

u = u.Normalize();
v = v.Normalize();
n = n.Normalize();

//no translation yet
//Vector3f t = Vector3f(-posObj.Dot(u), -posObj.Dot(v), -posObj.Dot(n));

/* interpreting as column-major like this
* ( u.x, u.y, u.z, t.x,
* v.x, v.y, v.z, t.y,
* n.x, n.y, n.z, t.z,
* 0 , 0, 0, 1 ) */

/* THIS ONE NOT WORK!!!
GLfloat m[] = {
u.x, v.x, n.x, 0,
u.y, v.y, n.y, 0,
u.z, v.z, n.z, 0,
t.x, t.y, t.z, 1
};*/


/*BUT THIS ONE WORKS!!! -> This matrix's rotation part (u, v, n) is wrong of its position.*/

GLfloat billboardMat[] = {
u.x, u.y, u.z, 0,
v.x, v.y, v.z, 0,
n.x, n.y, n.z, 0,
t.x, t.y, t.z, 1
};


The billboard matrix is like this. I thought the billboardMat's elements is wrong but it does produce the right result of billboard.

In the opposite, if I used the camera transformation matrix without the line n = -n, I still get the billboard effect but the rotation of Y axis is wrong (the image is upside down).

It looks confusing. Anyone could give me some hints? :)

Thanks in advance.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Announcements

  • Forum Statistics

    • Total Topics
      628366
    • Total Posts
      2982274
  • Similar Content

    • By test opty
      Hi all,
       
      I'm starting OpenGL using a tut on the Web. But at this point I would like to know the primitives needed for creating a window using OpenGL. So on Windows and using MS VS 2017, what is the simplest code required to render a window with the title of "First Rectangle", please?
       
       
    • By DejayHextrix
      Hi, New here. 
      I need some help. My fiance and I like to play this mobile game online that goes by real time. Her and I are always working but when we have free time we like to play this game. We don't always got time throughout the day to Queue Buildings, troops, Upgrades....etc.... 
      I was told to look into DLL Injection and OpenGL/DirectX Hooking. Is this true? Is this what I need to learn? 
      How do I read the Android files, or modify the files, or get the in-game tags/variables for the game I want? 
      Any assistance on this would be most appreciated. I been everywhere and seems no one knows or is to lazy to help me out. It would be nice to have assistance for once. I don't know what I need to learn. 
      So links of topics I need to learn within the comment section would be SOOOOO.....Helpful. Anything to just get me started. 
      Thanks, 
      Dejay Hextrix 
    • By mellinoe
      Hi all,
      First time poster here, although I've been reading posts here for quite a while. This place has been invaluable for learning graphics programming -- thanks for a great resource!
      Right now, I'm working on a graphics abstraction layer for .NET which supports D3D11, Vulkan, and OpenGL at the moment. I have implemented most of my planned features already, and things are working well. Some remaining features that I am planning are Compute Shaders, and some flavor of read-write shader resources. At the moment, my shaders can just get simple read-only access to a uniform (or constant) buffer, a texture, or a sampler. Unfortunately, I'm having a tough time grasping the distinctions between all of the different kinds of read-write resources that are available. In D3D alone, there seem to be 5 or 6 different kinds of resources with similar but different characteristics. On top of that, I get the impression that some of them are more or less "obsoleted" by the newer kinds, and don't have much of a place in modern code. There seem to be a few pivots:
      The data source/destination (buffer or texture) Read-write or read-only Structured or unstructured (?) Ordered vs unordered (?) These are just my observations based on a lot of MSDN and OpenGL doc reading. For my library, I'm not interested in exposing every possibility to the user -- just trying to find a good "middle-ground" that can be represented cleanly across API's which is good enough for common scenarios.
      Can anyone give a sort of "overview" of the different options, and perhaps compare/contrast the concepts between Direct3D, OpenGL, and Vulkan? I'd also be very interested in hearing how other folks have abstracted these concepts in their libraries.
    • By aejt
      I recently started getting into graphics programming (2nd try, first try was many years ago) and I'm working on a 3d rendering engine which I hope to be able to make a 3D game with sooner or later. I have plenty of C++ experience, but not a lot when it comes to graphics, and while it's definitely going much better this time, I'm having trouble figuring out how assets are usually handled by engines.
      I'm not having trouble with handling the GPU resources, but more so with how the resources should be defined and used in the system (materials, models, etc).
      This is my plan now, I've implemented most of it except for the XML parts and factories and those are the ones I'm not sure of at all:
      I have these classes:
      For GPU resources:
      Geometry: holds and manages everything needed to render a geometry: VAO, VBO, EBO. Texture: holds and manages a texture which is loaded into the GPU. Shader: holds and manages a shader which is loaded into the GPU. For assets relying on GPU resources:
      Material: holds a shader resource, multiple texture resources, as well as uniform settings. Mesh: holds a geometry and a material. Model: holds multiple meshes, possibly in a tree structure to more easily support skinning later on? For handling GPU resources:
      ResourceCache<T>: T can be any resource loaded into the GPU. It owns these resources and only hands out handles to them on request (currently string identifiers are used when requesting handles, but all resources are stored in a vector and each handle only contains resource's index in that vector) Resource<T>: The handles given out from ResourceCache. The handles are reference counted and to get the underlying resource you simply deference like with pointers (*handle).  
      And my plan is to define everything into these XML documents to abstract away files:
      Resources.xml for ref-counted GPU resources (geometry, shaders, textures) Resources are assigned names/ids and resource files, and possibly some attributes (what vertex attributes does this geometry have? what vertex attributes does this shader expect? what uniforms does this shader use? and so on) Are reference counted using ResourceCache<T> Assets.xml for assets using the GPU resources (materials, meshes, models) Assets are not reference counted, but they hold handles to ref-counted resources. References the resources defined in Resources.xml by names/ids. The XMLs are loaded into some structure in memory which is then used for loading the resources/assets using factory classes:
      Factory classes for resources:
      For example, a texture factory could contain the texture definitions from the XML containing data about textures in the game, as well as a cache containing all loaded textures. This means it has mappings from each name/id to a file and when asked to load a texture with a name/id, it can look up its path and use a "BinaryLoader" to either load the file and create the resource directly, or asynchronously load the file's data into a queue which then can be read from later to create the resources synchronously in the GL context. These factories only return handles.
      Factory classes for assets:
      Much like for resources, these classes contain the definitions for the assets they can load. For example, with the definition the MaterialFactory will know which shader, textures and possibly uniform a certain material has, and with the help of TextureFactory and ShaderFactory, it can retrieve handles to the resources it needs (Shader + Textures), setup itself from XML data (uniform values), and return a created instance of requested material. These factories return actual instances, not handles (but the instances contain handles).
       
       
      Is this a good or commonly used approach? Is this going to bite me in the ass later on? Are there other more preferable approaches? Is this outside of the scope of a 3d renderer and should be on the engine side? I'd love to receive and kind of advice or suggestions!
      Thanks!
    • By nedondev
      I 'm learning how to create game by using opengl with c/c++ coding, so here is my fist game. In video description also have game contain in Dropbox. May be I will make it better in future.
      Thanks.
  • Popular Now