C++, ' ** ' and Graphics Engines...

Started by
20 comments, last by hplus0603 18 years, 3 months ago
I know this is a bit cheeky of me, putting this all into one thread, but I need help with a couple of broad subjects. Firstly, having come from a (shakey) C programming background, I'm still not too sure about classes, and was wondering how programs and APIs such as DirectX can use a single class to create what seems to be a billion unrelated objects, along with the methods to handle them all( I've yet to find a use for the constructor\destructor methods...) secondly, I've been looking around, but I can't seem to find out what the ** operator is for(the place its most often seen is in the definition of main() in C and Cpp) Finally, I'm trying to create my own graphics engine. I not expecting much from it, and I've found an interesting article about it on www.flipcode.com and I'm following their advice, but it feels like my header/source is missing some things. here is the listing for my header;
Quote: #ifndef __VERTEX_H #define __VERTEX_H #include <math.h> #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /******************************************************************************** *List of functions and variables * ********************************************************************************* *SQR(name) * maths macro to define the square of variable 'name' * ********************************************************************************* *sine[],cosine[], * maths tables to increase speed * *tangent[] * * ********************************************************************************* *POINT,PPOINT * 3d point structures. PPOINT is the pointer version * * * * *LINE,PLINE * 3d line structure. consists of 2 POINT structures * * * * *VECTOR,PVECTOR * mathematical definition of a vector * * * * *VERTEX,PVERTEX * vertex data structure. includes position,colour and * * * texture coordinates * * * * *TRIANGLE,PTRIANGLE * defines a triangle as an array of 3 VERTEX structures * * * * *QUAD,PQUAD * defines a quad as an array of 4 VERTEX structures * * * * *POLYGON,PPOLYGON * defines a polygon with 'num_points' points, starting * * * at address 'point' * ********************************************************************************* #define SQR(name) name*name //Not too sure this'll work... enum plane_pos{BEHIND,ON,IN_FRONT} typedef enum plane_pos PLANE_POS ; typedef float[4][4] MATRIX_4x4;//4x4 matrix MATRIX_4x4 identity_matrix; MATRIX_4x4 inv_identity_matrix; MATRIX_4x4 test_matrix_1;// used during InitMathset to check for correct working of functions MATRIX_4x4 test_matrix_2;// (as above) MATRIX_4x4 add_result_matrix;// (ditto) MATRIX_4x4 concat_result_matrix;// (get the picture yet?) MATRIX_4x4 inv_result_matrix;//(no comment :) int sine[360]; int cosine[360]; int tangent[360]; typedef struct{ int x,y,z;//position int r,g,b,a;//colour and alpha }POINT,*PPOINT;//Use for particles( if poss) typedef struct{ POINT point[2];//two points make a line }LINE,*PLINE;//Use for ... ... ... something ... typedef struct{ int x,y,z;//magnitude int dirx,diry,dirz;//direction }VECTOR,*PVECTOR;// used in conjunction with one of the others, to move them in a set direction typedef struct{ int x,y,z;//position int r,g,b,a;//colour and alpha int u,v;//texture coordinates }VERTEX,*PVERTEX; typedef struct{ PVERTEX vertices[3];//the 3 vertices that make up a triangle }TRIANGLE,*PTRIANGLE; typedef struct{ PVERTEX vertices[4];//the 4 vertices that make up a quad }QUAD,*PQUAD; typedef struct{ int num_vertices;//number of vertices in quad PVERTEX vertices;//pointer to vertex list }POLYGON,*PPOLYGON; bool InitMathset(void); //call this before anything else. This can be ignored, but it will check that all of the functions work properly, //and sets up the sine,cosine and tangent tables PLANE_POS CheckPlane(POINT point,TRIANGLE triangle); //checks to see where point "point" is in comparison to plane "plane" LINE ScaleLine(PLINE line,float scale_factor); //scales a line "line" by "scale_factor" TRIANGLE ScaleTriangle(PTRIANGLE triangle,float scale_factor); //scales "triangle" by "scale_factor" QUAD ScaleQuad(PQUAD quad,float scale_factor); //scales "quad" by "scale_factor" POLYGON ScalePolygon(PPOLYGON polygon,float scale_factor); //scales "polygon" by "scale_factor" VECTOR Normalise(VECTOR vector); //Normalises the magnitude of a vector to 1.0 float GetMagnitude(VECTOR vector); // Gets the magnitude of a vector |U|=sqrt(Ux^2+Uy^2+Uz^2) float FindDotProduct(VECTOR u,VECTOR v); //uses dot product to find the angle between2 vectors theta=COS^-1*((u.x*v.x+u.y*v.y+u.z*v.z)/(GetMagnitude(u)*GetMagnitude(v))) VECTOR FindCrossProduct(VECTOR u, VECTOR v); //finds and returns the normal vector of vectors u and v <(u.y*v.z)-(u.z*v.y),(u.x*v.z)-(u.z*v.x),(u.x*v.y)-(u.y*v.x)>=<Nx,Ny,Nz> MATRIX_4x4 ConcatenateMatrix(MATRIX_4x4 mat_1,MATRIX_4x4 mat_2); //performs mat_1*mat_2 and returns the result MATRIX_4x4 AddMatrix(MATRIX_4x4 mat_1,MATRIX_4x4 mat_2); //adds mat1 to mat2 MATRIX_4x4 MultIdent(MATRIX_4x4 matrix); //multiplies the given matrix by the identity matrix. This just returns the original matrix MATRIX_4x4 AddVectorToMatrix(VECTOR vector, MATRIX_4x4 matrix); //transforms a vector into a matrix and multiplies it into the supplied matrix MATRIX_4x4 InvertMatrix(MATRIX_4x4 matrix); //multiples the given matrix by the inverse of the identity matrix #endif//__VERTEX_H
Is there anything else that I need to add mathematically, bearing in mind that I'll implement the drawing\rendering through OpenGL? Also, why can't I get the two flipping pluses to show when I'm trying to write 'C plus plus'?
Advertisement
Quote:Original post by webwraith
secondly, I've been looking around, but I can't seem to find out what the ** operator is for(the place its most often seen is in the definition of main() in C and Cpp)
As you already know, using a * in a declaration makes the type a pointer. ** is simply a pointer-to-a-pointer; in fact, you could if you wanted to, go crazy and have a pointer-to-a-pointer-to-a-pointer-to-a-pointer-to-a-pointer.

I imagine you've seen it in main as: char** argv
this is equivalent to char* argv[], or char argv[][].
Quote:Original post by webwraith
I know this is a bit cheeky of me, putting this all into one thread, but I need help with a couple of broad subjects. Firstly, having come from a (shakey) C programming background, I'm still not too sure about classes, and was wondering how programs and APIs such as DirectX can use a single class to create what seems to be a billion unrelated objects, along with the methods to handle them all( I've yet to find a use for the constructor\destructor methods...)


If you're talking about what I think you are, it's rather simple:

struct Manager {public:    ObjectA * CreateObjectA( void ) {        return new ObjectA;    }    void DestroyObjectA( ObjectA * object ) {        delete object;    }    ObjectB * CreateObjectB( void ) {        return new ObjectB;    }    void DestroyObjectB( ObjectB * object ) {        delete object;    }};


Quote:secondly, I've been looking around, but I can't seem to find out what the ** operator is for(the place its most often seen is in the definition of main() in C and Cpp)


That's not an operator, that's a pointer to a pointer. It's often used as the second parameter of main (argv) like so:

int main( int argc , char ** argv );

argv is layed out in a specific manner:

It is a pointer to the beginning of an array.
This array is an array of pointers to the beginnings of arrays of characters (strings).

Thus, if we were to use STL containers and objects (presuming it were legal in this context), it's quite similar to:

std::vector< std::string > argv;

The main difference being they use C style arrays:

std::string * argv; or std::string argv[];

And C style strings:

(char *) * argv; or (char *) argv[];

Quote:Finally, I'm trying to create my own graphics engine. I not expecting much from it, and I've found an interesting article about it on www.flipcode.com
and I'm following their advice, but it feels like my header/source is missing some things.

here is the listing for my header;

*snip*

Is there anything else that I need to add mathematically, bearing in mind that I'll implement the drawing\rendering through OpenGL?


If there is, you'll find out when you run accross it. And then you can add it. See YAGNI.

Quote:Also, why can't I get the two flipping pluses to show when I'm trying to write 'C plus plus'?


The forum PMSes like that. I don't know why either.
When it came to the APIs, I was speaking generally, I know when to use the constructor\destructor methods, I've just never needed them before(the fact that I've never managed to program a functional class before, may have something to do with that...).And I tried to implement a class once, but it was basically a mess, as I tend to need someone going through these things with me step-by-step with actual uses for the classes( in particular, my DirectX book is sitting on the shelf, gathering dust until I can find some simpler examples of good classes)

Thanks to the both of you for the 'pointer to a pointer' part, but I've got another question for you about it now;

what's the point? (pun not intended)

why not use a single pointer to whatever data you want to retrieve?

In the meantime, I'll keep an eye out for those elusive math functions... ;)
Quote:Original post by webwraith
Thanks to the both of you for the 'pointer to a pointer' part, but I've got another question for you about it now;

what's the point? (pun not intended)

why not use a single pointer to whatever data you want to retrieve?


Because argv (which is a list of arguments given to the program) is an array of C-strings (which are char arrays). Remember, arrays are basically pointers. If it was a pointer to a char, it would be more difficult to know where one argument ended and another began.
If the data you want to retrieve is a pointer (say, a pointer to an interface of some sort), then you need a pointer to a pointer to actually retrieve it. (Or, alternately, a reference to a pointer)

Note that when you say CreateVertexBuffer() in DirectX, that will (at least conceptually) create a CVertexBuffer object internally; initialize it as necessary; and then return a pointer to the actual object (through the pointer-to-pointer interface).

When you call Release() on the interface, it will decrement the refcount, and if it reaches 0, call delete on itself, which will call the destructor, which will clean up any data referenced by the object.
enum Bool { True, False, FileNotFound };
Quote:
#define SQR(name) name*name //Not too sure this'll work...


SQR(x+1) will expand to: x+1*x+1, which equals x+x+1. Definitely not what you wanted.

Quote:
#define SQR(name) (name)*(name)

But even better would be:

template <class T>inline T sqr(const T& x){   return x*x;}


In case you're unfamiliar with templates...the above code will create a function sqr(x) for any type that has a defined * operator. The performance will be the same as a #define, but it's typesafe.

-Alex
Quote:template <class T>
inline T sqr(const T& x)
{
return x*x;
}

I've never actually used templates, although I've got a tutorial on a simple one, so how does this actually work?

also, how would I use it? My understanding of templates was that you create a class (or whatever) with one before you can use it, meaning I'd still need a different one for each numerical type I intend to use.
Quote:Original post by webwraith
Quote:template <class T>
inline T sqr(const T& x)
{
return x*x;
}

I've never actually used templates, although I've got a tutorial on a simple one, so how does this actually work?

Basically, the compiler creates an instance of the function sqr for every data type you use it with. If you pass a float value to sqr, the compiler will create an instance of sqr where the unknown type T is replaced with float. Templates are very powerful code generation tools, which save you, the coder, from having to create n different versions of sqr to deal with n different data types.

Quote:Original post by webwraith
also, how would I use it? My understanding of templates was that you create a class with one before you can use it, meaning I'd still need a different one for each numerical type I intend to use.

That is true with templatized classes, but not with templatized functions. Take the sqr function above. In your code, you'd call sqr like so:
sqr<double>(1.0);
This explicitly tells the compiler that 1.0 is to be treated as a value of type double. However, you can omit the part in the < > brackets if you are passing a variable to the function; the compiler can determine the type being passed from the type of the variable.

[Edited by - iNsAn1tY on December 31, 2005 9:49:41 AM]
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
I'd have thought that 1.0 would have been treated as a float?
I take it, you only need to add the <..> when casting as a new/different type?

Thanks for the help, so far. I'm all ears for any other suggestions

This topic is closed to new replies.

Advertisement