Sign in to follow this  
enotirab

OpenGL OpenGl Matrix Problem

Recommended Posts

Hi all. I am fairly new to game programming and recently decided to try to include 3d models in a game engine that I'm working on. I bought a good book on the subject by Evan Pipho. I had good success with the md2 model format and now I am trying to work with the Ms3D format so I can use skeletal animation. I am able to load the model and draw it in it's original pose but have had very little success animating the model(it turns into mush). Evan's demo works perfectly so I've been using it as a basis for comparison and I've track down the difference between his code and mind...but that has given me greater confusion. I'm programming the engine in OpenGL and designed a Vector class and Matrix class to allow for manipulation of verts as did he..and there is where the differences have come up. He seems to store the translational data for the matrix in the bottom row, but the translation matrix in the back of the Red Book show the translation matrix as storing the translational data in the last column instead. Using those specs I am able to multiply a rotational and transitional matrix together(much in the was DirectX seems too) and then transform a vector in exactly the way I'd expect. However the resulting matrices I am getting do not match his. This is obviously due to the location of the translational data. I'm really stumped and although I have narrowed the problem down I cannot seem to understand why he placed his transitional data here and I believe that understanding this is key to fixing the problem. I'd be happy to post source code, but there is so much that its impractical for me to post it all. This is my first post here on Gamedev so if anyone has suggestions I'd really appreciate it!

Share this post


Link to post
Share on other sites
Sound slike your problem is about how matrix and vectors works. OpenGL uses a notation with column vectors and column major matrices. This means a vectors are represented as 4x1 matrices (4 tall, 1 wide). Matrices being column major means that, when stored in linear memory, the 2D array is flattened column by column.

Now, if the book instead uses a notation of row vectors and row major matrices, everything will look different on paper; vectors are now 1x4 (1 tall, 4 wide) instead, and the matrices will look transposed compared to what OpenGL uses. The transpose will effectively put translation in the bottom row instead of the right column (as in OpenGL).

However, once you start working out how matrix multiplication works, and how the matrices are flattened to linear memory, you will see that everything actually end up exactly the same. If you get different result, you are most likely reading something wrong or the book is explaining something wrong.

Share this post


Link to post
Share on other sites
Well his code doesn't seem to quite line up with the book ideas. The custom matrix class that he creates seems to use row-major matrices for the rotational portion but column-major for transitional data. More specifically here is my code for setting transitional and rotational information:


void Matrix4X4::SetTranslate(float x, float y, float z)
{
m[3] = x;
m[7] = y;
m[11] = z;

}

void Matrix4X4::SetRotation(float x,float y,float z)
{

float cosX = cosf(x);
float cosY = cosf(y);
float sinX = sinf(x);
float sinY = sinf(y);
float cosZ = cosf(z);
float sinZ = sinf(z);

float cosXsinY = cosX * sinY;
float sinXsinY = sinX * sinY;

m[0] = cosY * cosZ;
m[1] = -cosZ * sinZ;
m[2] = -sinY;
m[4] = -sinXsinY * cosZ + cosX * sinZ;
m[5] = sinXsinY * sinZ + cosX * cosZ;
m[6] = -sinX * cosY;
m[8] = cosXsinY * cosZ + sinX * sinZ;
m[9] = -cosXsinY * sinZ + sinX * cosZ;
m[10] = cosX * cosY;
m[15] = 1.0f;
}

and his code:

inline void CMatrix4X4::SetRotation(float fX, float fY, float fZ)
{
double cx = cos(fX);
double sx = sin(fX);
double cy = cos(fY);
double sy = sin(fY);
double cz = cos(fZ);
double sz = sin(fZ);

m_fMat[0] = (float)(cy * cz);
m_fMat[1] = (float)(cy * sz);
m_fMat[2] = (float)(-sy);

m_fMat[4] = (float)(sx * sy * cz - cx * sz);
m_fMat[5] = (float)(sx * sy * sz + cx * cz);
m_fMat[6] = (float)(sx * cy);

m_fMat[8] = (float)(cx * sy * cz + sx * sz);
m_fMat[9] = (float)(cx * sy * sz - sx * cz);
m_fMat[10] = (float)(cx * cy);

m_fMat[15] = 1.0f;
}

inline void CMatrix4X4::SetTranslation(float fX, float fY, float fZ)
{
m_fMat[12] = fX;
m_fMat[13] = fY;
m_fMat[14] = fZ;
}




also, for his matrix multiplication he multiplies them backwards. I thought for awhile that these matrices were simply transposed from each other, but that isn't quite true from what I can tell. Its important to note that I'm not using these matrices directly in OpenGl. I'm not feeding them to the matrix stack at all, but just using them to edit vertex data directly.

[Edited by - enotirab on January 20, 2009 7:41:59 PM]

Share this post


Link to post
Share on other sites
Having the translation in elements 3, 7 and 11 is unusual. Not that it's wrong, but it implies that you have different vector ordering (row or column vectors) and matrix majorness (row or column major matrix).

As long as you are consistent, everything will be correct. You just have to be very careful that you define all operations correct, and since you're getting wrong result, I believe that you're not defining your operations (multiplication specifically) correct with respect to vector ordering and sides you multiply from.

Share this post


Link to post
Share on other sites
That must be the case. The reason I placed them there is because much of the literature that I've read seems to place them there. The back of the Red Book, and also this site

When I transform hard-coded verts by multiplying them I SEEM to get the correct result, but my matrices do not match his and the model verts are definitely not coming out correctly. I'm unsure of why this is inconsistent. Its likely that you are correct and I am misunderstanding the way the vector transformations should occur.

Here is my code for it:

Matrix4X4 Matrix4X4::operator*(const Matrix4X4 rhs)
{
Matrix4X4 temp(
//first row
m[0]*rhs.m[0] + m[1]*rhs.m[4] + m[2]*rhs.m[8] + m[3]*rhs.m[12], m[0]*rhs.m[1] + m[1]*rhs.m[5] + m[2]*rhs.m[9] + m[3]*rhs.m[13],
m[0]*rhs.m[2] + m[1]*rhs.m[6] + m[2]*rhs.m[10]+m[3]*rhs.m[14], m[0]*rhs.m[3] + m[1]*rhs.m[7] + m[2]*rhs.m[11] + m[3]*rhs.m[15],
//second row
m[4]*rhs.m[0] + m[5]*rhs.m[4] + m[6]*rhs.m[8] + m[7]*rhs.m[12], m[4]*rhs.m[1] + m[5]*rhs.m[5] + m[6]*rhs.m[9] + m[7]*rhs.m[13],
m[4]*rhs.m[2] + m[5]*rhs.m[6] + m[6]*rhs.m[10]+m[7]*rhs.m[14], m[4]*rhs.m[3] + m[5]*rhs.m[7] + m[6]*rhs.m[11] + m[7]*rhs.m[15],

//third row
m[8]*rhs.m[0] + m[9]*rhs.m[4] + m[10]*rhs.m[8] + m[11]*rhs.m[12], m[8]*rhs.m[1] + m[9]*rhs.m[5] + m[10]*rhs.m[9] + m[11]*rhs.m[13],
m[8]*rhs.m[2] + m[9]*rhs.m[6] + m[10]*rhs.m[10]+m[11]*rhs.m[14], m[8]*rhs.m[3] + m[9]*rhs.m[7] + m[10]*rhs.m[11] + m[11]*rhs.m[15],
//fourth row
m[12]*rhs.m[0] + m[13]*rhs.m[4] + m[14]*rhs.m[8] + m[15]*rhs.m[12], m[12]*rhs.m[1] + m[13]*rhs.m[5] + m[14]*rhs.m[9] + m[15]*rhs.m[13],
m[12]*rhs.m[2] + m[13]*rhs.m[6] + m[14]*rhs.m[10]+m[15]*rhs.m[14], m[12]*rhs.m[3] + m[13]*rhs.m[7] + m[14]*rhs.m[11] + m[15]*rhs.m[15]);




return temp;
}


void Vector::Transform(const Matrix4X4& mat)
{
float nx,ny,nz;

nx = mat.Get(0,0) * v[vX] + mat.Get(1,0) *v[vY] + mat.Get(2,0) *v[vZ] + mat.Get(3,0);
ny = mat.Get(0,1) *v[vX]+ mat.Get(1,1) *v[vY] + mat.Get(2,1) *v[vZ] + mat.Get(3,1);
nz = mat.Get(0,2) *v[vX]+ mat.Get(1,2) *v[vY] + mat.Get(2,2) *v[vZ] + mat.Get(3,2);

v[vX] = nx;
v[vY] = ny;
v[vZ] = nz;
}




Basically I'm just confused as to why the Red Book has a translation matrix
like this;

1 0 0 dx
0 1 0 dy (which is how mine is meant to be set up.
0 0 1 dz
0 0 0 1

and other matrix classes I have read about seem to be using a translation matrix like this:

1 0 0 0
0 1 0 0
0 0 1 0
dx dy dyz 1

I do understand that you have two options of transforming vectors. As a row from one side of multiplication, or as a column on the other. I'm using(I belive) a column style, so it should look like this:

1 0 0 dx * vx
0 1 0 dy * vy
0 0 1 dz * vz
0 0 0 1 * 1


Please forgive me if I seem like I'm being obtuse....I must be missing something and since this is a key graphical programming issue I really want to fix the error in my logic.

[Edited by - enotirab on January 20, 2009 3:33:22 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by enotirab
Basically I'm just confused as to why the Red Book has a translation matrix
like this;

1 0 0 dx
0 1 0 dy (which is how mine is meant to be set up.
0 0 1 dz
0 0 0 1

It is the correct notation in OpenGL.

However, keep in mind how OpenGL stores these 16 elements of the matrix into an 1-dimensional array. That is, the vertical elements (columns) are stored first, then move on the next column.

The problem may be that your matrix class stores 16 elements in row-major order; storing the first row elements, then moving to the next line, which is common for math and C++.

I do not know the original intention for OpenGL's way in first place, however, as a result, you can find very interesting fact; 3 consecutive elements in an array represent a meaningful set.

For example, the first column, (m0, m1, m2) is the left(X) axis,
the second column, (m4, m5, m6) is the up(Y) axis,
the third column, (m8, m9, 10) is the forward(Z) axis,
and the right most column, (m12, m13, m14) is for the translation.

Here is an image for better understanding;


For more info, check this link;
OpenGL Matrix

You can keep the own structure in your class, but you need to transpose the matrix data when you pass them to OpenGL. OpenGL also provides functions for this; glLoadTransposeMatrix{fd}() and glMultTransposeMatrix{fd}().

Share this post


Link to post
Share on other sites
Thanks very much everyone for your help. I finally got it to work as a result. Now my skeletal animation is working like a charm. I basically had columns as rows, and rows as columns (base on the visual diagram). I don't know how long I'd have struggled with this alone. Thanks so much!

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
      628401
    • Total Posts
      2982467
  • 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