Sign in to follow this  
mike74

returning a multidimensional array

Recommended Posts

Ok, I'm writing a function that I want to return a rotation matrix. It looks like this: float[3][3] multmat(float x, float y, float z, double theta) { float rm[3][3]; float c = cos(theta); float s = sin(theta); float t = 1 - cos(theta); rm[0][0] = t*x*x + c; rm[1][0] = t*x*y - s*z; rm[2][0] = t*x*z + s*y; rm[0][1] = t*x*y + s*z; rm[1][1] = t*y*y + c; rm[2][1] = t*y*z - s*x; rm[0][2] = t*x*z - s*y; rm[1][2] = t*y*z + s*x; rm[2][2] = t*z*z + c; return rm; } However, C++ doesn't seem to like the float[3][3] return declaration. It says: 38 C:\Dev-Cpp\linedraw.cpp expected unqualified-id before '[' token Any ideas how to get this working? Thanks. Mike C. http://www.coolgroups.com/zoomer/

Share this post


Link to post
Share on other sites
Two mistakes:
1. That memory will be deleted once the function is done, so you might get garbage.
2. You have to always return a pointer when you want to return an array (regardless of how many dimensions it has).

Share this post


Link to post
Share on other sites
There's two ways to do it...

By returning a pointer to a point, which is what a multi-array is.
float ** foo()
{
float array2[3][3];
initalize_array2;
return array2;
}
...

float array[3][3];
array = foo;


and by passing by reference, which would automaitically update your array

void foo(float** array)
{
assign_array(array);
}
...
float array[3][3];
foo(array);



Share this post


Link to post
Share on other sites
I would do it like this:


float rm[3][3];

float[3][3] multmat(float x, float y, float z, double theta)
{
float c = cos(theta);
float s = sin(theta);
float t = 1 - cos(theta);
rm[0][0] = t*x*x + c;
rm[1][0] = t*x*y - s*z;
rm[2][0] = t*x*z + s*y;

rm[0][1] = t*x*y + s*z;
rm[1][1] = t*y*y + c;
rm[2][1] = t*y*z - s*x;

rm[0][2] = t*x*z - s*y;
rm[1][2] = t*y*z + s*x;
rm[2][2] = t*z*z + c;
}

void some_other_function()
{
//just use rm normally
}

Share this post


Link to post
Share on other sites
What? Isn't that what I had?

Mike C.
http://www.coolgroups.com/zoomer/

Quote:
Original post by Raduprv
I would do it like this:


float rm[3][3];

float[3][3] multmat(float x, float y, float z, double theta)
{
float c = cos(theta);
float s = sin(theta);
float t = 1 - cos(theta);
rm[0][0] = t*x*x + c;
rm[1][0] = t*x*y - s*z;
rm[2][0] = t*x*z + s*y;

rm[0][1] = t*x*y + s*z;
rm[1][1] = t*y*y + c;
rm[2][1] = t*y*z - s*x;

rm[0][2] = t*x*z - s*y;
rm[1][2] = t*y*z + s*x;
rm[2][2] = t*z*z + c;
}

void some_other_function()
{
//just use rm normally
}


Share this post


Link to post
Share on other sites
A few things here.
If you're doing 3d rotation, you need a 4x4 array, not a 3x3 array.

If the following prototype doesn't work:


float[3][3] multmat(float x, float y, float z, double theta) {

// stuff //

}








You should make it like this.


float **BuildRotateMatrix(float axis_x, float axis_y, float axis_z, float theta) {

float **rm;
int i;

// the following chunk will allocate ram in a way that will NOT be //
// de-allocated when the function returns; //
// Of course, it would be MUCH faster and cause less memory fragmentation //
// if you allocate all the matrices when the program begins, and do NO //
// allocation in these functions at all. //
// Just pass in the arrays instead (ie, float **matfunc(float **matrix, other params..) //

// need a 4x4 array for 3d matrix math, or 3x3 array for 2d matrix math //
rm = (float **)malloc(sizeof(float*) * 4);

if(NULL == rm) return NULL; // out of memory //

for(i = 0; i < 4; i++) {
rm[i] = (float *)malloc(sizeof(float) * 4);
if(NULL == rm[i]) return NULL; // you probably want to free up the //
// memory allocated in previous calls first //
}
// end memory allocation chunk //

// now, the following code I took almost entirely from your initial post //
// is ROTATION code (like you said), not a matrix multiply. //
// It would be a good idea to name the function accordingly, otherwise //
// it will be VERY confusing to use. //

float c = fcos(theta); // if you use plain-old cos() or sin() //
float s = fsin(theta); // you are casting from double to float //
float t = 1 - fcos(theta); // which can also be slow //

rm[0][0] = t*x*x + c;
rm[1][0] = t*x*y - s*z;
rm[2][0] = t*x*z + s*y;
rm[3][0] = 0.0f; // new //

rm[0][1] = t*x*y + s*z;
rm[1][1] = t*y*y + c;
rm[2][1] = t*y*z - s*x;
rm[3][1] = 0.0f; // new //

rm[0][2] = t*x*z - s*y;
rm[1][2] = t*y*z + s*x;
rm[2][2] = t*z*z + c;
rm[3][2] = 0.0f; // new //

// new addition //
rm[0][3] = 0.0f;
rm[1][3] = 0.0f;
rm[2][3] = 0.0f;
rm[3][3] = 1.0f;

return rm;
}









If you allocate memory in your functions, make sure you deallocate it after
you're done using it, or you'll run out of memory in no time considering
that these functions will be done many times per second.
Again, don't allocate memory in a 3d math function, since you'll have a
metric butt-load of memory fragmentation in no time, and it'll be amazingly
slow (memory allocation is a slow process).

If you use a 3x3 array for 3d math, you should rewrite all your functions
to use 4x4 arrays. Otherwise, nothing will work.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cryoknight
A few things here.
If you're doing 3d rotation, you need a 4x4 array, not a 3x3 array.

If you use a 3x3 array for 3d math, you should rewrite all your functions
to use 4x4 arrays. Otherwise, nothing will work.

That's a bunch of balogna. You can do 3D rotations perfectly fine with a 3x3 matrix.

In response to the original post, either pass the array by reference or return the array encapsulated inside a struct:


void multmat( float (&your_matrix)[3][3], float x, float y, float z, double theta)


-or-

struct blah { float matrix[3][3]; };
blah multmat( float x, float y, float z, double theta);

Share this post


Link to post
Share on other sites
If all you are doing is rotation, sure. But not if you want to be able
to do the full 3d pipeline of matrix multiplications.
If you didn't need the 4x4 matrices, they wouldn't bother using them
in EVERY SINGLE 3d programming book.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cryoknight
If all you are doing is rotation, sure. But not if you want to be able
to do the full 3d pipeline of matrix multiplications.
If you didn't need the 4x4 matrices, they wouldn't bother using them
in EVERY SINGLE 3d programming book.

All he is talking about is rotations without respect to a 3d pipeline. For all you know this isn't even related to graphics in any way.

Share this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP

void multmat( float (&your_matrix)[3][3], float x, float y, float z, double theta)



if your going to pass bare arrays i would recommend this version as the typical way using pointers just leads to arrays decaying to pointers (pointer decay). You know specifically the dimensions are always the same then you are just losing information using pointers. Statically allocated arrays are rich in information compared to pointers.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
void multmat( float (&your_matrix)[3][3], float x, float y, float z, double theta)

is not a good way to do this, instead use this

void multmat( float your_matrix[3][3], float x, float y, float z, double theta)

it will preserve all the dimensional information, and it is passed as a pointer anyways, so don't worry about it being copied every time, 'cause it won't.

Share this post


Link to post
Share on other sites
Quote:
Original post by Raduprv
I would do it like this:


float rm[3][3];

float[3][3] multmat(float x, float y, float z, double theta)
{
float c = cos(theta);
float s = sin(theta);
float t = 1 - cos(theta);
rm[0][0] = t*x*x + c;
rm[1][0] = t*x*y - s*z;
rm[2][0] = t*x*z + s*y;

rm[0][1] = t*x*y + s*z;
rm[1][1] = t*y*y + c;
rm[2][1] = t*y*z - s*x;

rm[0][2] = t*x*z - s*y;
rm[1][2] = t*y*z + s*x;
rm[2][2] = t*z*z + c;
}

void some_other_function()
{
//just use rm normally
}


And if you need to use multmat from within another file. Or you need to get two different matrices?

Just pass by reference, I see that as the best solution.

Share this post


Link to post
Share on other sites
Quote:
Original post by A Guy from CRO
And if you need to use multmat from within another file. Or you need to get two different matrices?

Just pass by reference, I see that as the best solution.


Then you declare it as extern in some other fle.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cryoknight
If all you are doing is rotation, sure. But not if you want to be able
to do the full 3d pipeline of matrix multiplications.
If you didn't need the 4x4 matrices, they wouldn't bother using them
in EVERY SINGLE 3d programming book.


I've seen professional renderers that utilize 4x3 matrices, a 3x3 rotation and then the offset vector. There are plenty of different ways to work with matrices. People find shortcuts, optimizations, etc. Never convince yourself that there is only one right answer to a programming question.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
void multmat( float (&your_matrix)[3][3], float x, float y, float z, double theta)

is not a good way to do this, instead use this

void multmat( float your_matrix[3][3], float x, float y, float z, double theta)

it will preserve all the dimensional information, and it is passed as a pointer anyways, so don't worry about it being copied every time, 'cause it won't.

Actually, my version is the one that preserves dimension information, yours does not. Yours only preserves the number of columns and not the number of rows, whereas mine preserves both.

Share this post


Link to post
Share on other sites
Im curious as to why you think

void multmat( float (&your_matrix)[3][3], float x, float y, float z, double theta)

is not a good way to do this.

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