From: H. H. <hen...@gm...> - 2008-08-23 22:43:43
|
Okay, lets discuss on this matter. I have written the library with the implementation of using struct/union approach as I thought this was the implementation we decided on in the forums. We have multiple approaches: Proposal #1: the array approach typedef GLfloat GLMvec2f[2]; void glmVecSet2f (GLMvec2f out, GLfloat x, GLfloat y); void glmVecAdd2f (GLMvec2f out, const GLMvec2f v1, const GLMvec2f v2); This allows the user code to call like this: GLMvec2f a, b, c; glmVecSet2f (a, 1.0f, 1.0f); glmVecSet2f (b, 2.0f, 2.0f); glmVecAdd2f (c, a, b); However GCC will generate warnings on args 2 and 3 for glmVecAdd2f. We cannot define glmVecSet2f like this: GLMvec2f glmVecSet2f (GLMvec2f out, GLfloat x, GLfloat y); This is impossible because functions cannot return arrays. The bad side of this approach is that function calls cannot be nested like this: glmVecAdd2f (c, glmVecSet2f (a, 1.0f, 1.0f), glmVecSet2f (b, 2.0f, 2.0f)); Proposal #2: struct/union approach (the current implementation) typedef struct GLMvec2f_s { union { GLfloat v[2]; struct GLMvec2f_data_s { GLfloat x, y; }; }; } GLMvec2f; GLMvec2f *glmVecSet2f (GLMvec2f *out, GLfloat x, GLfloat y); GLMvec2f *glmVecAdd2f (GLMvec2f *out, const GLMvec2f *v1, const GLMvec2f *v2); This allows function calls to be nested: GLMvec2f a, b, c; glmVecAdd2f (&c, glmVecSet2f (&a, 1.0f, 1.0f), glmVecSet2f (&b, 2.0f, 2.0f)); Data can be also passed directly to OpenGL functions: GLMmat4f mat; glmMatIdentity4f (&mat); glLoadMatrixf (mat.m); (or some equivalent GL3 API call) Member can also be accessed by a moniker: mat.m11 = 1.0f; vec.x = 2.0f; col.r = 0.5f; As a sidenote, this is also how they do this in D3DX (the util library of D3D). The only con is the use of union, but I don't see this as a problem. They are not particularly complicated either IMO. Proposal #3: the struct-only approach struct GLMvec2f_s { GLfloat x, y; } GLMvec2f; GLMvec2f *glmVecSet2f (GLMvec2f *out, GLfloat x, GLfloat y); GLMvec2f *glmVecAdd2f (GLMvec2f *out, const GLMvec2f *v1, const GLMvec2f *v2); This is almost the same as #2 except that avoidance of unions. I would go with the struct/union. On Sun, Aug 24, 2008 at 1:22 AM, Jason McKesson <ko...@gm...> wrote: > Henri Häkkinen wrote: > > No no... We had this conversation already in the forums few days ago. > > The struct approach is superior over typedef GLfloat GLMmat2f[4]; for the > following reason: > > - it allows matrix data to be accessed as either using index or members. > You can see the memory layout of the matrix from the ordering of the mXX > members. > > - the following piece of code: > > typedef float FOO[2]; > > FOO *test (FOO *out, const FOO *f) > { > (*out)[0] = (*f)[0]; > (*out)[1] = (*f)[1]; > return out; > } > > The function "test" should not take pointers. Objects of type "FOO" already > are pointers, so it does not need to take FOO*'s. > > > int main () > { > FOO a, b; > test (&a, &b); > return 0; > } > > > Produces the following warning on GCC 4.2.3: > warning: passing argument 2 of 'test' from incompatible pointer type > > Which is why virtually every book on programming tells you *not* to define > multiple variables on the same line. > This has nothing to do how the variables are declared, but how the function test is called. > > Compare this: > > typedef struct { > union { > float f[2]; > struct { > float x, y; > }; > }; > } FOO; > > FOO *test (FOO *out, const FOO *f) > { > out->x = f->x; > out->y = f->y; > return out; > } > > I don't like the idea of these functions all taking pointers to the types > rather than the types themselves. I know C doesn't have an equivalent to the > & reference in C++, but the user code would be a lot cleaner if you only > passed pointers for parameters that are outputs (or large objects). That's > the general convention for most C libraries I've seen. > But it is also a lot more efficient to pass them as pointers. > > This code is a lot more clear and usable than the previous one. Also: > > vec[0] = -vec[0]; > > You cannot be sure if this vec is an array of vectors or are you accessing > the first element of a 2D vector. > > Implementing math datatypes as structure is a lot more cleaner approach > than the array approach. Perhaps we should think if the union there is > redundant but typedef GLfloat GLMvec2f[2]; is not a good idea. And I don't > think we should hinder our design by the assumed ignorance of the > afromentioned newbies. Besides, I have already implemented the library by > the struct approach design. See the OpenGL forums for the discussion we > underwent there fore more points. > > If you feel that the math types should be structs, then let them be struct. > But they should *not* be structs containing a union of an array and a > struct. That violates principle #2: simplicity. A principle you agreed on, > as you previously stated. Simplicity means you pick one side: struct or > array. > > ------------------------------------------------------------------------- > This SF.Net email is sponsored by the Moblin Your Move Developer's > challenge > Build the coolest Linux based applications with Moblin SDK & win great > prizes > Grand prize is a trip for two to an Open Source event anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Glsdk-devel mailing list > Gls...@li... > https://lists.sourceforge.net/lists/listinfo/glsdk-devel > > -- Henri 'henux' Häkkinen |