Jump to content
  • Advertisement
Sign in to follow this  
Doggan

Matrix Mult parameter craziness

This topic is 4099 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Why does the following code not work? Something cryptic is happening, or I am overlooking something very easy...
typedef float Matrix[4][4];

void makeIdent(Matrix &mtx)
{
	mtx[0][0] = 1.0f;	mtx[0][1] = 0.0f;	mtx[0][2] = 0.0f;	mtx[0][3] = 0.0f;
	mtx[1][0] = 0.0f;	mtx[1][1] = 1.0f;	mtx[1][2] = 0.0f;	mtx[1][3] = 0.0f;
	mtx[2][0] = 0.0f;	mtx[2][1] = 0.0f;	mtx[2][2] = 1.0f;	mtx[2][3] = 0.0f;
	mtx[3][0] = 0.0f;	mtx[3][1] = 0.0f;	mtx[3][2] = 0.0f;	mtx[3][3] = 1.0f;
}

void mtxMult(Matrix &res, const Matrix mtx1, const Matrix mtx2)
{
	res[0][0] = mtx1[0][0] * mtx2[0][0] + mtx1[0][1] * mtx2[1][0] + mtx1[0][2] * mtx2[2][0] + mtx1[0][3] * mtx2[3][0];
	res[0][1] = mtx1[0][0] * mtx2[0][1] + mtx1[0][1] * mtx2[1][1] + mtx1[0][2] * mtx2[2][1] + mtx1[0][3] * mtx2[3][1];
	res[0][2] = mtx1[0][0] * mtx2[0][2] + mtx1[0][1] * mtx2[1][2] + mtx1[0][2] * mtx2[2][2] + mtx1[0][3] * mtx2[3][2];
	res[0][3] = mtx1[0][0] * mtx2[0][3] + mtx1[0][1] * mtx2[1][3] + mtx1[0][2] * mtx2[2][3] + mtx1[0][3] * mtx2[3][3];

	res[1][0] = mtx1[1][0] * mtx2[0][0] + mtx1[1][1] * mtx2[1][0] + mtx1[1][2] * mtx2[2][0] + mtx1[1][3] * mtx2[3][0];
	res[1][1] = mtx1[1][0] * mtx2[0][1] + mtx1[1][1] * mtx2[1][1] + mtx1[1][2] * mtx2[2][1] + mtx1[1][3] * mtx2[3][1];
	res[1][2] = mtx1[1][0] * mtx2[0][2] + mtx1[1][1] * mtx2[1][2] + mtx1[1][2] * mtx2[2][2] + mtx1[1][3] * mtx2[3][2];
	res[1][3] = mtx1[1][0] * mtx2[0][3] + mtx1[1][1] * mtx2[1][3] + mtx1[1][2] * mtx2[2][3] + mtx1[1][3] * mtx2[3][3];

	res[2][0] = mtx1[2][0] * mtx2[0][0] + mtx1[2][1] * mtx2[1][0] + mtx1[2][2] * mtx2[2][0] + mtx1[2][3] * mtx2[3][0];
	res[2][1] = mtx1[2][0] * mtx2[0][1] + mtx1[2][1] * mtx2[1][1] + mtx1[2][2] * mtx2[2][1] + mtx1[2][3] * mtx2[3][1];
	res[2][2] = mtx1[2][0] * mtx2[0][2] + mtx1[2][1] * mtx2[1][2] + mtx1[2][2] * mtx2[2][2] + mtx1[2][3] * mtx2[3][2];
	res[2][3] = mtx1[2][0] * mtx2[0][3] + mtx1[2][1] * mtx2[1][3] + mtx1[2][2] * mtx2[2][3] + mtx1[2][3] * mtx2[3][3];

	res[3][0] = mtx1[3][0] * mtx2[0][0] + mtx1[3][1] * mtx2[1][0] + mtx1[3][2] * mtx2[2][0] + mtx1[3][3] * mtx2[3][0];
	res[3][1] = mtx1[3][0] * mtx2[0][1] + mtx1[3][1] * mtx2[1][1] + mtx1[3][2] * mtx2[2][1] + mtx1[3][3] * mtx2[3][1];
	res[3][2] = mtx1[3][0] * mtx2[0][2] + mtx1[3][1] * mtx2[1][2] + mtx1[3][2] * mtx2[2][2] + mtx1[3][3] * mtx2[3][2];
	res[3][3] = mtx1[3][0] * mtx2[0][3] + mtx1[3][1] * mtx2[1][3] + mtx1[3][2] * mtx2[2][3] + mtx1[3][3] * mtx2[3][3];
}

int _tmain(int argc, _TCHAR* argv[])
{
	// This works, no problem.
	Matrix a, result;

	makeIdent(a);
	makeIdent(result);

	Matrix b = 
	{ 
		1.0,	0.0,	0.0,	0.0, 
		0.0,	.7071,	.7071,	0.0, 
		0.0,	-.7071,	.7071,	0.0, 
		0.0,	0.0,	0.0,	1.0 
	};

	mtxMult(result, a, b);

	// Now, let's store the result in a.
	makeIdent(a);

	mtxMult(a, a, b);

	float res1 = result[1][2];
	float res2 = a[1][2];

	return 0;

If you run this code, and compare res1 and res2, they are different, yet SHOULD be the same. Here is the problem. When using mtxMult, and the result matrix is one of either mtx1 or mtx2, the values calculated are incorrect. It is as if a value is being overwritten during the execution of the body of the mtxMult function. This makes no sense to me, since mtx1 and mtx2 are passed by const value. A complete copy of the original matrices are made, and these are declared const, which means they will not change value in the function. The res is passed by reference, so it's values will change. It is not being used in any of the calculations - it is only being used for storage. Any ideas?.... [Edited by - Doggan on September 25, 2007 1:34:57 AM]

Share this post


Link to post
Share on other sites
Advertisement
You are passing in a const pointer as mtx1. The data being pointed to may change, and does through res. The const only limits your use of mtx1.

For example, you can do:
char a[1024];
const char* b = a;
strcpy(a,"something");


This will "change" the value pointed to by b, even though b is const. You can (although usually shouldn't) even discard const qualifiers by casting to a non-const.

Side note: your Matrix b assignent uses doubles for a float array. You took care to specify the values were float in makeIdent(), so I figured you might actually care about the implicit cast.

Share this post


Link to post
Share on other sites
Wow... I see now.

I did not write the framework for this application. I guess I wasn't realizing that the Matrix "type" was simply an array of floats. Normally, I would be dealing with a Matrix class. In that case, the code posted would work, as it is a standard pass-by-value.

This Matrix "float array typedef" masks the problem. So in actuality, when it appears that I am passing by value, I am really passing by reference. Ugh.

Thanks for your post. I am aware of the casting issue, but this code was just copied and pasted together real quick for posting purposes.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!