Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: MVP functions

  1. #1

    MVP functions

    Hi,
    I'm very new to OpenGL and for various reasons I'm rolling my own functions to calculate the various parts of my MVP matrix (described here). Anyway the code based off of them doesn't work (naturally...) and i would greatly appreciate if someone with a few minutes could take a look at them and check whether they're at fault, since I can't find a good way to isolate them from the rest of the code, so can't tell where the error is.
    Thanks in advance
    Angus
    Code :
    void perspective(float fovy, float aspect, float zNear, float zFar, float result[4][4])
    {
    	float f=1/tanf(fovy/2);
     
    	result[0][0]=f/aspect;
    	result[0][1]=0;
    	result[0][2]=0;
    	result[0][3]=0;
    	result[1][0]=0;
    	result[1][1]=f;
    	result[1][2]=0;
    	result[1][3]=0;
    	result[2][0]=0;
    	result[2][1]=0;
    	result[2][2]=(zFar+zNear)/(zNear-zFar);
    	result[2][3]=(2*zNear*zFar)/(zNear-zFar);
    	result[3][0]=0;
    	result[3][1]=0;
    	result[3][2]=-1;
    	result[3][3]=0;
    }
     
    void crossproduct(float a[4], float b[4], float result[4]);
     
    void lookat(float eyeX, float eyeY, float eyeZ, float centreX, float centreY, float centreZ, float upX, float upY, float upZ, float result[4][4])
    {
    	float f[4] = {centreX-eyeX, centreY-eyeY, centreZ-eyeZ, 1};
    	float u[4] = {upX, upY, upZ, 1};
    	float s[4];
    	float temp[4][4];
    	float temp2[4][4];
    	normalise(f);
    	normalise(u);
     
    	crossproduct(f, u, s);
    	crossproduct(s, f, u);
     
    	temp[0][0]=s[0];
    	temp[0][1]=s[1];
    	temp[0][2]=s[2];
    	temp[0][3]=0;
    	temp[1][0]=u[0];
    	temp[1][1]=u[1];
    	temp[1][2]=u[2];
    	temp[1][3]=0;
    	temp[2][0]=-f[0];
    	temp[2][1]=-f[1];
    	temp[2][2]=-f[2];
    	temp[2][3]=0;
    	temp[3][0]=0;
    	temp[3][1]=0;
    	temp[3][2]=0;
    	temp[3][3]=1;
     
    	translate(temp2, -eyeX, -eyeY, -eyeZ);
    	multmatrix(temp, temp2, result);
    }
     
    void crossproduct(float a[4], float b[4], float result[4])
    {
    	result[0] = (a[1]*b[2]) - (a[2] * b[1]);
    	result[1] = (a[2]*b[0]) - (a[0] * b[2]);
    	result[2] = (a[0]*b[1]) - (a[1] * b[0]);
    	result[3] = 1;
    }
     
    void multmatrix(float a[4][4], float b[4][4], float result[4][4])
    {
    	int i;
    	int j;
    	int k;
    	float total;
     
    	for(i=0;i<4;i++)
    		for(j=0;j<4;j++)
    		{
    			total=0;
    			for(k=0;k<4;k++)
    				total+=a[i][k]*b[k][j];
    			result[i][j]=total;
    		}
     
    }
     
    void translate(float result[4][4], float x, float y, float z)
    {
    	result[0][0]=1;
    	result[0][1]=0;
    	result[0][2]=0;
    	result[0][3]=x;
    	result[1][0]=0;
    	result[1][1]=1;
    	result[1][2]=0;
    	result[1][3]=y;
    	result[2][0]=0;
    	result[2][1]=0;
    	result[2][2]=1;
    	result[2][3]=z;
    	result[3][0]=0;
    	result[3][1]=0;
    	result[3][2]=0;
    	result[3][3]=1;
    }

  2. #2
    Member Regular Contributor
    Join Date
    Apr 2010
    Posts
    493

    Re: MVP functions

    I've only looked at your translate.
    OpenGL expects matrices stored in float arrays to be column major, i.e. the first index is the column and the second is the row - your translate matrix are transposed.

  3. #3

    Re: MVP functions

    Thanks, don't know why I didn't think to check which way matrices should be. Will change that and see if it at all improves things.
    Angus

  4. #4
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    2,882

    Re: MVP functions

    Yeah, an easy way to deal with this given that C/C++ is row-major order and OpenGL is column-major is: Just do row-major like C/C++ wants, and flip the transform order.

    That is, instead of doing "P*V*M * v_obj = v_clip" like OpenGL wants, do this "v_obj * M*V*P = v_clip". In practice this means you use the transposes of the matrices, and you composite them in the opposite order. Then you can blissfully care less that OpenGL uses column major order.

  5. #5
    Advanced Member Frequent Contributor
    Join Date
    Jan 2007
    Posts
    965

    Re: MVP functions

    There's also glLoadTransposeMatrix and glMultTransposeMatrix.

  6. #6

    Re: MVP functions

    Tried flipping round the order of the transformations just now which didn't help. I'll do a full proper check of the entire piece of code tomorrow/over the next week, mainly worried about these bits of code as I've no real way to check they're working.
    Just as a matter of interest, is there any good reason to keep the C code using row major matrices? I just did it because it seems intuitive and I hadn't checked properly but you seem to imply there's a good reason one might want to do that.

  7. #7
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,723

    Re: MVP functions

    is there any good reason to keep the C code using row major matrices?
    No, not really. It's all purely conventional; just put the columns where you put the rows now. Your matrix multiplication functions will all work exactly the same.

  8. #8
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    2,882

    Re: MVP functions

    Quote Originally Posted by Mjiig
    is there any good reason to keep the C code using row major matrices?
    Yes. Then you never have to do transposes to pass matrices to OpenGL. Further, you end up with matrix translate and basis vectors being in rows of the matrix rather than column which is more efficient to access. And you can just forget the whole column major issue on the C/C++ side.

  9. #9
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,723

    Re: MVP functions

    Further, you end up with matrix translate and basis vectors being in rows of the matrix rather than column which is more efficient to access.
    I think you're conflating certain terms, which is why we give conflicting advice that is in fact the same. The major storage order of a matrix does not change how the basis vectors are stored. It simply changes the order of storage of the data.

    What you're talking about is combing row-major storage with row vectors. That is, you're transposing the matrix into a row-based matrix, and then storing that row-based matrix in a row-major array.

    This results in identical data to storing a column-based matrix in a column-major array. That's why transposing isn't necessary; because you've transposed the data at storage time.

    A more detailed discussion of the issue can be found on this Stack Exchange answer.

  10. #10
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    2,882

    Re: MVP functions

    Quote Originally Posted by Alfonse Reinheart
    What you're talking about is combing row-major storage with row vectors....This results in identical data to storing a column-based matrix in a column-major array. That's why transposing isn't necessary; because you've transposed the data at storage time.
    Exactly. You're right. We're talking about the same thing. Thanks for clarifying that.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •