Reflective Factory Design

This is a discussion on Reflective Factory Design within the Game Programming forums, part of the General Programming Boards category; http://www.gamedev.net/reference/art...rticle1415.asp That looks like THE BEST way to manage all your Scene_Objects, it looks ultimately complex and Object Oriented to ...

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964

    Reflective Factory Design

    http://www.gamedev.net/reference/art...rticle1415.asp

    That looks like THE BEST way to manage all your Scene_Objects, it looks ultimately complex and Object Oriented to the 100% MAX the language can go....

    Is there anyone out there who can turn this article into a tutorial of some sort?

    The problem I have come across in my Game Engine is that I have to dynamically allocate objects into memory during runtime...

    For instance, if I click the build button on Worker A, to build, lets say a barracks, I have a Barracks object defined, but I need to create a new instance of that barracks object Right then and there on the fly.

    Thats where the Reflective Factory Design comes in... It is essentially a Class Factory.. (during runtime!)

    Is there anyone out there that can give a brief explanation of how the syntax of the whole thing works? I know the code has documentation, but it seems hard to follow. (Maybe I'm just a noob)

    Anyone willing to tackle this beast of a question?
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #2
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    I don't like the article and I don't like it's use of the pre-processor.

    There is a better way IMO.

  3. #3
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    What I do in my engine, is just load all the objects into a struct array.

    For example, you have a struct for your object:
    Code:
    struct
    {
    char *filename;
    vec3 pos;
    etc, etc
    } objectdata, *od;
    
    
    objectdata objectP[MAX_OBJECTS];
    and to create/load the object:
    Code:
    int objnum = 0;
    loadfunc(args)
    {
    loadMS3D(objectP[objnum].filename);
    etc, etc (set more varibles and other stuff)
    }
    If you want a better explination of what I mean, just ask.

    -psychopath

    [EDIT]I'll warn you, this method isn't very easy on memory usage.[/EDIT]
    Last edited by psychopath; 12-16-2005 at 09:05 AM.
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  4. #4
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    Phsyco it would be great if you would elaborate, I need all the outside references I can find dealing with this matter
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  5. #5
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    Ok, here's my code. I'll explain it as best as I can at the end.

    Object.h
    Code:
    #define MAX_OBJECTS		5000
    
    ...
    
    typedef struct 
    {
    	//file hander stuff:
    	int numframes;
    	int numpoints;
    	int numtris;
    	//int numtexcoords;
    	///int numglcmds;
    	//int framesize;
    	/*int texwidth, texheight;
    	int currentframe;
    	int nextframe;
    	float interpolate;
    	mesh *triindex;
    	texcoord *st;
    	vector3d *points;
    	//vector3d *normals;*/
    	MS3DHeader *pHeader;
    	MS3DVertex *pVertex;
    	MS3DTriangle *pTriangle;
    	MS3DMaterial *pMaterial;
    	MS3DJoint *pJoint;
    	MS3DKeyframe *pFrame;
    	int m_numMeshes;
    	Mesh *m_pMeshes;
    	int m_numMaterials;
    	Material *m_pMaterials;
    	int m_numTriangles;
    	Triangle *m_pTriangles;
    	int m_numVertices;
    	Vertex *m_pVertices;
    
    	//object properties:
    	char name;
    	char *filename;
    	int textype;
    	int type;
    	int repeatx;
    	int repeaty;
    	bool isenvironmentmapped;
    
    
    	//physical attributes:
    	float m; //mass
    	float t; //time
    	float speed; //meters per second
    	vector3d accel; //acceleration
    	vector3d disp; //displacment
    	vector3d pos; //position
    	vector3d dir; //direction
    	vector3d scale; //scale
    	vector3d v; //velocity
    	
    	matrix_4x4_type matrix; // Object matrix
    
    }objectdata, *obj;
    
    class object
    {
    public:
    	object();
    	virtual ~object();
    	
    	void position(obj objectP,float x,float y,float z);
    	void translate(obj objectP,float x,float y,float z);
    	void translateW(obj objectP,float x,float y,float z);
    	void rotate(obj objectP,int x,int y,int z);
    	void scale(obj objectP,int x,int y,int z);
    	void calculatenormal(float *p1, float *p2, float *p3);
    	void calculatenormals(obj &objectP);
    	char createobject(int type, char *fName, char *texfName1, char *texfName2, int textype, int repeatx, int repeaty,
    					  float px, float py, float pz, 
    					  float rx, float ry, float rz, 
    					  float sx, float sy, float sz);
    	void renderanimated(obj objectP, int startframe, int endframe, float percent);
    	void renderobjects();
    };
    
    extern objectdata objectP[MAX_OBJECTS];
    Object.cpp (excerpt)
    Code:
    int num_objects = 0;
    UINT bufferid = -1;
    int i, j;
    
    objectdata objectP[MAX_OBJECTS];
    
    ...
    
    char object::createobject(int type, char *fName, char *texfName1, char *texfName2, int textype, int repeatx, int repeaty, 
    						  float px, float py, float pz, 
    						  float rx, float ry, float rz, 
    						  float sx, float sy, float sz)
    {
    	objectP[num_objects].filename = fName;
    	objectP[num_objects].type = type;
    	objectP[num_objects].textype = textype;
    	objectP[num_objects].repeatx = repeatx;
    	objectP[num_objects].repeaty = repeaty;
    	
    	objectP[num_objects].pos.x = px;
    	objectP[num_objects].pos.y = py;
    	objectP[num_objects].pos.z = pz;
    	objectP[num_objects].scale.x = sx;
    	objectP[num_objects].scale.y = sy;
    	objectP[num_objects].scale.z = sz;
    	
    	/*if (objectP[num_objects].type!=0)
    	{
    		_ceCollision->createBbox(objectP[num_objects].pos.x, objectP[num_objects].pos.y, objectP[num_objects].pos.z,
    								 objectP[num_objects].min.x, objectP[num_objects].min.y, objectP[num_objects].min.z,
    								 objectP[num_objects].max.x, objectP[num_objects].max.y, objectP[num_objects].max.z);
    	}*/
    
    	if(type==0)
    	{
    		if(loadMS3D(&objectP[num_objects], fName)==NULL)
    		{
    			//TODO: Add Abort,Retry,Ignore dialouge box on error.
    			printf("ERROR! Unable to load MS3D object.\n");
    			return(1);//keep going anyway. tmp.
    		}
    		
    		if (textype == 0)
    		{
    			objectP[num_objects].m_pMaterials->m_texture = CreateModelTextureJPG(texfName1);
    			objectP[num_objects].m_pMaterials->m_texture1 = CreateModelTextureJPG(texfName2);
    		}
    		else if(textype == 1)
    		{
    			objectP[num_objects].m_pMaterials->m_texture = CreateModelTextureDDS(texfName1);
    			objectP[num_objects].m_pMaterials->m_texture1 = CreateModelTextureDDS(texfName2);
    		}
    		else if(textype == 2)
    			glDisable(GL_TEXTURE_2D);
    	}
    
    
    	MatrIdentity_4x4(objectP[num_objects].matrix);
    	position(&objectP[num_objects], px, py, pz);
    	rotate(&objectP[num_objects], rx, ry, rz);
    	scale(&objectP[num_objects], sx, sy, sz);
    
    	computeTangentsAndBinormals(&objectP[num_objects]);
    
    	num_objects++;
    	return (1);
    }
    Modified MS3D draw function (to support loading method):
    Code:
    int index[3];
    void drawMS3D(obj objectP, float scaleX, float scaleY) 
    {
    	glActiveTextureARB		= (PFNGLACTIVETEXTUREARBPROC)		wglGetProcAddress("glActiveTextureARB");
    	glMultiTexCoord2fARB	= (PFNGLMULTITEXCOORD2FARBPROC)		wglGetProcAddress("glMultiTexCoord2fARB");
    
    	GLboolean texEnabled = glIsEnabled( GL_TEXTURE_2D );
    	// Draw by group
    	for ( int i = 0; i < objectP->m_numMeshes; i++ )
    	{
    		int materialIndex = objectP->m_pMeshes[i].m_materialIndex;
    		if ( materialIndex >= 0 )
    		{
    			glMaterialfv( GL_FRONT, GL_AMBIENT, objectP->m_pMaterials[materialIndex].m_ambient );
    			glMaterialfv( GL_FRONT, GL_DIFFUSE, objectP->m_pMaterials[materialIndex].m_diffuse );
    			glMaterialfv( GL_FRONT, GL_SPECULAR, objectP->m_pMaterials[materialIndex].m_specular );
    			glMaterialfv( GL_FRONT, GL_EMISSION, objectP->m_pMaterials[materialIndex].m_emissive );
    			glMaterialf( GL_FRONT, GL_SHININESS, objectP->m_pMaterials[materialIndex].m_shininess );
    
    			if ( objectP->m_pMaterials[materialIndex].m_texture > 0 )
    			{
    				glActiveTextureARB(GL_TEXTURE0_ARB);
    				glEnable( GL_TEXTURE_2D );
    				glBindTexture( GL_TEXTURE_2D, objectP->m_pMaterials[materialIndex].m_texture );
    				//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    				glActiveTextureARB(GL_TEXTURE1_ARB);
    				glEnable( GL_TEXTURE_2D );
    				glBindTexture( GL_TEXTURE_2D, objectP->m_pMaterials[materialIndex].m_texture1 );
    			}
    			else
    				glDisable( GL_TEXTURE_2D );
    		}
    		else
    		{
    			// Material properties?
    			glDisable( GL_TEXTURE_2D );
    		}
    
    		glBegin( GL_TRIANGLES );
    		{
    			for ( int j = 0; j < objectP->m_pMeshes[i].m_numTriangles; j++ )
    			{
    				int triangleIndex = objectP->m_pMeshes[i].m_pTriangleIndices[j];
    				const Triangle *pTri = &objectP->m_pTriangles[triangleIndex];
    				
    				index[0] = pTri->m_vertexIndices[0];
    				
    				glNormal3fv( pTri->m_vertexNormals[0] );
    				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, pTri->m_s[0]*scaleX, pTri->m_t[0]*scaleY );
    				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, pTri->m_s[0]*scaleX, pTri->m_t[0]*scaleY );
    				glVertex3fv( objectP->m_pVertices[index[0]].m_location );
    				
    				index[1] = pTri->m_vertexIndices[1];
    				
    				glNormal3fv( pTri->m_vertexNormals[1] );
    				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, pTri->m_s[1]*scaleX, pTri->m_t[1]*scaleY );
    				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, pTri->m_s[1]*scaleX, pTri->m_t[1]*scaleY );
    				glVertex3fv( objectP->m_pVertices[index[1]].m_location );
    				
    				index[2] = pTri->m_vertexIndices[2];
    				
    				glNormal3fv( pTri->m_vertexNormals[2] );
    				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, pTri->m_s[2]*scaleX, pTri->m_t[2]*scaleY );
    				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, pTri->m_s[2]*scaleX, pTri->m_t[2]*scaleY );
    				glVertex3fv( objectP->m_pVertices[index[2]].m_location );
    			}
    		}
    		glEnd();
    	}
    
    	if ( texEnabled )
    		glEnable( GL_TEXTURE_2D );
    	else
    		glDisable( GL_TEXTURE_2D );
    
    	for(i=0; i<objectP->m_numVertices; i++)
    	{
    		_ceShader->attribute3fv(program[4], "rm_Tangent", objectP->m_pVertices[i].m_tangent);
    		_ceShader->attribute3fv(program[4], "rm_Binormal", objectP->m_pVertices[i].m_binormal);
    	}
    
    }
    Ok, first of all, the header struct contains pointers to MS3D data, loaded from the file, as well as engine variables. This struct is used as an array, declared by the line objectdata objectP[MAX_OBJECTS];. In the object create function, this array struct's variables are set by arguments taken from the function. The array index number starts at 0, and is increased at the end of the function. So every time this function is called, a new array index's struct values are set. For the drawing of the MS3D model, everything is the same as it would be with a single-model system, except the data (verticies, filenames, etc) are all called through the object class as pointers to the main MS3D struct's.

    Iv'e posted quite a bit of code here, and the best explination I can come up with.
    It shouldn't be too hard to get somthing like this working.

    -psychopath
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Implementing Inheritence into your design
    By bobthebullet990 in forum C++ Programming
    Replies: 6
    Last Post: 08-05-2006, 04:40 PM
  2. Abstract Factory pattern
    By Just in forum C++ Programming
    Replies: 3
    Last Post: 02-18-2005, 09:58 AM
  3. Opinions on new site design
    By jverkoey in forum A Brief History of Cprogramming.com
    Replies: 23
    Last Post: 01-21-2005, 12:34 PM
  4. Cprog tutorial: Design Patterns
    By maes in forum C++ Programming
    Replies: 7
    Last Post: 10-11-2004, 01:41 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21