Thread: Mmk, I give up, lets try your way. (Resource Management)

  1. #16
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Code:
    class VertexContainer
    {
    public:
    	std::vector<VertexData *> Vertices;
    private:
    	/*
    	void GetVertexInfo(DWORD dwID)
    	{
    		for ( vertices begin, to vertices end) itor++
    		{
    			check to see if element.dwID = the passed dwID
    			{
    				if so return pointer to that element
    			}
    		}
    	}
    	*/
    };
    Now that getvertexinfo function is psuedocoded. Is this the most efficient way of doing this? Is there a way I could do this mathematically? Instead of brute force checking if ID's match?

    EDIT:

    Sorry just answered my question, all we do is pass an ObjectInfo struct to that function, one that looks like this
    Code:
    struct ObjectInfo
    {
    	DWORD dwStartIndex;
    	DWORD dwEndIndex;
    	DWORD dwID;
    	DWORD *dwTextureIDs;
    };
    And then read the information from the passed structure and return a pointer to the beginning and end of the ID set ...

    Maybe, anyone willing to correct me on this one?
    Last edited by Shamino; 01-12-2006 at 10:41 AM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #17
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Just an update of my progress, if any...

    Code:
    #include "windows.h"
    #include <vector>
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    class MaterialData
    {
    	friend class MaterialContainer;
    
    	DWORD MaterialID;
    	bool  Active;
    	float Ambient[4], Diffuse[4], Specular[4], Emissive[4];
    	float Shininess;
    	int Texture;
    	char *TextureFilename;
    
    public:
    
    };
    
    
    class MaterialContainer
    {
    	std::vector<MaterialData *> Materials;
    
    	bool Active;
    
    public:
    
    	MaterialContainer(void) {}
    
    	virtual ~MaterialContainer(void)
    	{
        //Terminate threads
    		if (Materials.size()>0)
    		{
    			for (DWORD i=0;i<Materials.size();i++)
    			{
    				Materials[i]->Active=false;
    				if (Materials[i]) delete Materials[i];
    			}
    			Materials.clear();
    		}
    	}
    
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    class PhysicsData
    {
    	friend class PhysicsContainer;
    
    	DWORD PhysicsID;
    	bool  Active;
    	double mass;
    	double velocity[3];
    
    public:
    
    };
    
    class PhysicsContainer
    {
    	std::vector<PhysicsData *> Physics;
    
    	bool  Active;
    
    public:
    
    	PhysicsContainer(void) {}
    
    	virtual ~PhysicsContainer(void)
    	{
        //Terminate threads
    		if (Physics.size()>0)
    		{
    			for (DWORD i=0;i<Physics.size();i++)
    			{
    				Physics[i]->Active=false;
    				if (Physics[i]) delete Physics[i];
    			}
    			Physics.clear();
    		}
    	}
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    class VertexData
    {
    	friend class VertexContainer;
    
    	DWORD VertexID;
    	bool  Active;
    	float vertex[3];
    	char boneID;
    
    public:
    
    };
    
    class VertexContainer
    {
    	std::vector<VertexData *> Vertices;
    
    	bool  Active;
    
    public:
    
    	VertexContainer(void) {}
    
    	virtual ~VertexContainer(void)
    	{
        //Terminate threads
    		if (Vertices.size()>0)
    		{
    			for (DWORD i=0;i<Vertices.size();i++)
    			{
    				Vertices[i]->Active=false;
    				if (Vertices[i]) delete Vertices[i];
    			}
    			Vertices.clear();
    		}
    	}
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    class PositionData
    {
    	friend class PositionContainer;
    
    	DWORD PositionID;
    	bool  Active;
    	float pos[3];
    
    public:
    
    };
    
    class PositionContainer
    {
    	std::vector<PositionData *> Positions;
    
    	bool  Active;
    
    public:
    
    	PositionContainer(void) {}
    
    	virtual ~PositionContainer(void)
    	{
        //Terminate threads
    		if (Positions.size()>0)
    		{
    			for (DWORD i=0;i<Positions.size();i++)
    			{
    				Positions[i]->Active=false;
    				if (Positions[i]) delete Positions[i];
    			}
    			Positions.clear();
    		}
    	}
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    class ObjectInfo
    {
    	DWORD dwStartIndex;
    	DWORD dwEndIndex;
    	DWORD dwID;
    	DWORD *dwTextureIDs;
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    class ResourceCache
    {
    	PhysicsContainer   Physics;
    	VertexContainer    Vertices;
    	PositionContainer  Positions;
    	MaterialContainer  Materials;
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    class RenderList
    {
    	ResourceCache *RenderData;
    	std::vector<DWORD> ObjectIDs;
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    I'm thinking instead of having a VertexData class that contains vertex data AND handles it, I should have a Vertex object that is handled by VertexData, therefore VertexData only needs to know the offset of the VertexObject to give it an ID... Same goes with all those class combo's up there..


    Please Correct anything I am doing wrong!!
    Last edited by Shamino; 01-16-2006 at 01:48 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  3. #18
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Why the comment terminate threads? I see no threads being fired off in your code.

  4. #19
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    I thought those just cleared out the containers... and deleted everything in em.. Oh well, removed them if that isn't what they do..

    Anyways, I just noticed something major.... I kept forgetting that it is a 3 tiered hierarchy...


    On the bottom, we have our data structures, then these are tied together with the resourceCache class, which is tied together by the Renderlist Class!!!

    I finally can see the structure on paper...

    Renderlist contains methods to access the resource cache and manipulate it (draw methods and such). ResourceCache contains methods to access the resource containers..



    Those thread remover thingies were in your animation code, I thought every container class needed it, but apparently not ..

    I'll repost some code...
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  5. #20
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The thread termination code was for animations inside of the MFC editor I'm coding. Each animation is it's own thread and so when the application terminates, I had to terminate each thread. I've change the code to WaitForSingleObject() which will wait for the thread to terminate and then proceed. It's a safe way to end all threads.

    I'll use threads in the engine for this as well as input and the music/sfx system.

  6. #21
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    So about my post above bubba, where I re-explained the system to myself.

    Is this correct? The stuff in bold I mean?

    What would some of the classes methods look like?

    Also, how exactly is the ObjectInfo struct used, Bubba? I'm real close to solving this puzzle, just need a bit more info..

    I realize that ObjectInfo is a "visitor" of sorts, but where exactly does it come into play, what object fills out this information?

    Here is my most updated code with a bunch of documentation...

    Fill in the blanks maybe? Am I asking too much?

    Code:
    #include "windows.h"
    #include <vector>
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // this is the Material data structure, and the class
    // that contains the data.
    struct MaterialData
    {
    	DWORD MaterialID;
    	float Ambient[4], Diffuse[4], Specular[4], Emissive[4];
    	float Shininess;
    	int Texture;
    	char *TextureFilename;
    };
    
    
    class MaterialContainer
    {
    	friend class ResourceCache;
    	std::vector<MaterialData *> Materials;
    
    public:
    
    	MaterialContainer(void) {}
    
    	virtual ~MaterialContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This is the Physics data container, and the class that
    // contains the info.
    struct PhysicsData
    {
    	DWORD PhysicsID;
    	double mass;
    	double velocity[3];
    };
    
    class PhysicsContainer
    {
    	friend class ResourceCache;
    	std::vector<PhysicsData *> Physics;
    
    public:
    
    	PhysicsContainer(void) {}
    
    	virtual ~PhysicsContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This is the Vertex Data structure and the class
    // that holds the data
    struct VertexData
    {
    	DWORD VertexID;
    	float vertex[3];
    	char boneID;
    };
    
    class VertexContainer
    {
    	friend class ResourceCache;
    	std::vector<VertexData *> Vertices;
    
    public:
    
    	VertexContainer(void) {}
    
    	virtual ~VertexContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This is the PositionData structure and the class that contains
    // the data.
    struct PositionData
    {
    	DWORD PositionID;
    	float pos[3];
    
    };
    
    class PositionContainer
    {
    	friend class ResourceCache;
    	std::vector<PositionData *> Positions;
    
    public:
    
    	PositionContainer(void) {}
    
    	virtual ~PositionContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This structure is still a mystery to me, although I do know
    // that it acts as a visitor to the ResourceCache class..
    // Or is it a visitor to the RenderList?  How does this baby
    // get filled out?  And where is it used?
    struct ObjectInfo
    {
    	DWORD dwStartIndex;
    	DWORD dwEndIndex;
    	DWORD dwID;
    	DWORD *dwTextureIDs;
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This class simply put, is a container of containers, a wrapper class...
    // Methods to access the containers are here...
    class ResourceCache
    {
    	friend class Renderlist;
    	PhysicsContainer   Physics;
    	VertexContainer    Vertices;
    	PositionContainer  Positions;
    	MaterialContainer  Materials;
    
    	// Add methods to... ?  Return data from the containers?
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This class is a handle to resource Cache, and it is the only class
    // that any part of the engine ever has to deal with... I hope...
    class RenderList
    {
    	ResourceCache *RenderData;
    	std::vector<DWORD> ObjectIDs;
    
    	// Add methods here to Manage the list of ID's...
    	// What else do I need?
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    Last edited by Shamino; 01-16-2006 at 10:04 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  7. #22
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    I'm giving this project like 4 more days to move somewhere, otherwise I'm scrapping it and will work with a 2d rpg...

    Its this freakin resource manager... I dont know what methods go where, how class A interacts with class B, how struct A plays with class B...

    Who knows....

    I'm just fed up with the fact that I've been working on this thing for a month and I can't figure it out... And it seems like no one can tell me how it works.. I don't want metaphors, I don't want comparisons, I want to know how the fudge to make this work!!

    Code:
    #include <vector>
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // this is the Material data structure, and the class
    // that contains the data.
    struct MaterialData
    {
    	DWORD MaterialID;
    	float Ambient[4], Diffuse[4], Specular[4], Emissive[4];
    	float Shininess;
    	int Texture;
    	char *TextureFilename;
    };
    
    
    class MaterialContainer
    {
    	friend class ResourceCache;
    	std::vector<MaterialData *> Materials;
    
    public:
    
    	MaterialContainer(void) {}
    
    	virtual ~MaterialContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This is the Physics data container, and the class that
    // contains the info.
    struct PhysicsData
    {
    	DWORD PhysicsID;
    	double mass;
    	double velocity[3];
    };
    
    class PhysicsContainer
    {
    	friend class ResourceCache;
    	std::vector<PhysicsData *> Physics;
    
    public:
    
    	PhysicsContainer(void) {}
    
    	virtual ~PhysicsContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This is the Vertex Data structure and the class
    // that holds the data
    struct VertexData
    {
    	DWORD VertexID;
    	float vertex[3];
    	char boneID;
    };
    
    class VertexContainer
    {
    	friend class ResourceCache;
    	std::vector<VertexData *> Vertices;
    
    public:
    
    	VertexContainer(void) {}
    
    	virtual ~VertexContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This is the PositionData structure and the class that contains
    // the data.
    struct PositionData
    {
    	DWORD PositionID;
    	float pos[3];
    
    };
    
    class PositionContainer
    {
    	friend class ResourceCache;
    	std::vector<PositionData *> Positions;
    
    public:
    
    	PositionContainer(void) {}
    
    	virtual ~PositionContainer(void)
    	{
    	}
    
    	// Add methods to add stuff to container, and remove stuff...
    
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This structure is still a mystery to me, although I do know
    // that it acts as a visitor to the ResourceCache class..
    // Or is it a visitor to the RenderList?  How does this baby
    // get filled out?  And where is it used?
    struct ObjectInfo
    {
    	DWORD dwStartIndex;
    	DWORD dwEndIndex;
    	DWORD dwID;
    	DWORD *dwTextureIDs;
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This class simply put, is a container of containers, a wrapper class...
    // Methods to access the containers are here...
    class ResourceCache
    {
    	friend class Renderlist;
    	PhysicsContainer   Physics;
    	VertexContainer    Vertices;
    	PositionContainer  Positions;
    	MaterialContainer  Materials;
    
    	// Add methods to... ?  Return data from the containers?
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    // This class is a handle to resource Cache, and it is the only class
    // that any part of the engine ever has to deal with... I hope...
    class RenderList
    {
    	ResourceCache *RenderData;
    	std::vector<DWORD> ObjectIDs;
    
    	// Add methods here to Manage the list of ID's...
    	// What else do I need?
    };
    /////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  8. #23
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Then create one for yourself. Stop trying to mimic what I've done and code your own.

    I'm not going to wade through lines and lines of your source to tell you how to get my system working in your implementation. Think about what needs to be done, write it down, and code a class structure to get the job done efficiently and effectively.

  9. #24
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    I like how you ignore questions.

    I'm not asking you to write code.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  10. #25
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    OMG, Bubba, you are forgiven...

    Forcing people to think for themselves usually ends up well...

    Okay...

    [metaphor]

    So we have our Object, lets call him a.. hmm, a carrot top.. yes..

    So, carrot top has like, this bit of information, that people need to draw him... (we'll deal with textures first)...

    So carrot goes over to Resource Cache, and resource cache asks wtf do you look like carrot top...

    Carrot top is all like, "carrot.jpeg".... and resource cache is like, noob, and he creates a pointer to a resource struct sizeof whatever carrot top rambles about... which we all know could be a lot..

    So resource cache is like, okay, sweet, now we have your data structure, I'll throw this in resource container blah, in resource slot ***37*** <--- OBJECT ID!!!...

    Carrot top is like, sweet, now I know what object ID I am... and so he heads over to the render list... renderlist is like, dude, carrot top, WTF are you?

    And carrot replies, I'm a number 37 bizaaaatch... and renderlist checks out container 37, hmm, carrot.jpeg...

    Then renderlist heads over to render engine, hes all like, we need a number 37 please, a "carrot.jpeg".... renderengine is all like, ANOTHER CARROT TOP?!

    He draws it reluctantly...

    End story

    [/metaphor]

    I hope you found that entertaining and informative...
    Last edited by Shamino; 01-17-2006 at 10:10 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  11. #26
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Entertaining, anyway
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #27
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    I'm pretty sure I understand how the whole thing fits together now..
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  13. #28

    Join Date
    May 2005
    Posts
    1,042
    Bubba is not trying to be a penis head as you suspect. This idea that there's some universal way to handle all resources is invalid.

    When I started, I started in a manner similar to what you are doing: I started using fileformats to which there was a tutorial posted online. I flat out copied the header files which contained all of the definitions for the important data structures. I didn't even try to make my own file format. So, I used the header files that you've found from that nehe tutorial for doing ms3d models, and I did the same for quake3 bsp files for that tutorial posted on gamedev. Excellent way to start. Note that I ultimately learned how to load stuff and re-wrote all of the actual code, but even that doesn't really matter.

    So, you know how to load and store a ms3d model itself. Lets look at some of my code that I use for the renderer to hold a ms3d model. I don't do anything special with this, this is just the most basic way you can render a ms3d model: no lighting, no fancy graphical effects, just the regular fixed-function OpenGL pipeline with single textureing going on here. This is the structure, defined in my GLRenderer.h header file

    Code:
    /*
    	Single texture
    	Lighting information allowed
    */
    struct	MS3DModelRenderData
    {
    	Vector3	Position;
    	Vector3	Orientation;
    	CMS3D_MODEL	*pModel;
    };
    MS3DModelRenderData, the Position is the displacement of the model, I use this to call glTranslate.

    Orientation is the angles (in degrees) about the X, Y and Z axis. This result can be derived from various sources, including doing various physics calculations, integrating quaternions over time, etc. Also, there are many ways to store the Orientation: angles about each axis, three vectors that represent the coordinate system (which is the same as a matrix: each of these vectors that represent the coordinate system are put into the columns of the OpenGL modelview matrix). But, because this is just a simple way to render a ms3d model, I choose to use the simplest way to store orientation: degrees about the xyz.


    Then somewhere I have a function to add the ms3d model to the renderer. In my GLRenderer, I have a vector of MS3DModelRenderData* as well as a vector that contains every other renderable type of data. It isn't pretty, but it is very straightforward, it works, and I like it even though it inflates the code substantially. This may be a good case to use inheritance, so that 'everything' that you can put in the renderer derives from a single class, but I chose not to. Critique as you will.

    ...

    Code:
    	/*
    		Data containers
    	*/
    	std::vector<unsigned	int>	mvQuake3MultiTexturedFaces;
    	std::vector<unsigned	int>	mvQuake3SingleTexturedFaces;
    
    
    	std::vector<DebugSphereData*>				mDebugSpheres;
    	std::vector<DebugBox*>						mDebugBoxes; //
    	std::vector<DebugLineData*>					mDebugLines;
    	std::vector<DebugPoint*>					mDebugPoints;
    	std::vector<MS3DModelRenderData*>			mMS3DRenderData;//
    	std::vector<AlphaBlendedQuadRenderData*>	mAlphaBlendedQuads;//
    	std::vector<BasicQuad*>						mBasicQuads;//
    	std::vector<skybox*>						mSkyBoxes;	//FIXME: should only really ever be one
    	std::vector<skysphere*>						mSkySpheres;//

    Those data definitions are private member data of my GLRenderer class.

    Then, as member functions of my class, I have code to add data to my renderer. For example, here is the code to add the ms3dmodel render data to the renderer:

    Code:
    	//Angles are in degrees
    	void	AddMS3DModelToRenderer(float	PosX,float	PosY,float PosZ,
    									 float	AngleX,float AngleY,float AngleZ,
    									 CMS3D_MODEL	*pModel)	
    	{
    		MS3DModelRenderData	*pData = new	MS3DModelRenderData;
    		
    		pData->Position.x	=	PosX;
    		pData->Position.y	=	PosY;
    		pData->Position.z	=	PosZ;
    
    		pData->Orientation.x	=	AngleX;
    		pData->Orientation.y	=	AngleY;
    		pData->Orientation.z	=	AngleZ;
    
    		pData->pModel		=	pModel;
    		
    		this->mMS3DRenderData.push_back(pData);
    	}

    Then, I have code in the GLRenderer for being able to render the actual model based on the type it is. Note that for every type of renderable 'thing' I have, I have a corresponding rendering function. Very straightforward, but I also didn't make this with any particularly high level functionality in mind (I don't really care about writing vertex/fragment shader programs...I've written code for doing stencil shadow volumes for my ms3d model, but I don't support it in my actual useful render class).



    Code:
    /*
    	December	27, 2004
    */
    void	GLRenderer::RenderMS3DModels()
    {	
    	if(!mMS3DRenderData.size())
    	{
    		return;
    	}
    
    	gpNTGLAPI->glActiveTextureARB(GL_TEXTURE0_ARB);
    	
    	NT_GL(glEnable(GL_TEXTURE_2D))	//this enables the first texture unit
    
    	gpNTGLAPI->glActiveTextureARB(GL_TEXTURE1_ARB);
    	
    	NT_GL(glDisable(GL_TEXTURE_2D))	//this disables the second texture unit
    
    
    	NT_GL(glDisable(GL_LIGHTING))	//to make sure we can always see the model
    
    	R_NormalCullMode();	//counter clockwise culling
    
    	gpNTGLAPI->glActiveTextureARB(GL_TEXTURE0_ARB);	//make sure the first texture unit is the one we bind to 
    
    	std::vector<MS3DModelRenderData*>::iterator	ptr;	//to iterate through the vector
    	
    	MS3DModelRenderData	*pTempData=0;	//ptr to the actual 
    	
    	CMS3D_MODEL	*pTempModel=0;
    	
    	//Enable states for indexed drawing 
    	//FIXME: I don't actually used indexed drawing right now, do that
    	NT_GL(glEnableClientState(GL_VERTEX_ARRAY))
    	NT_GL(glEnableClientState(GL_TEXTURE_COORD_ARRAY))
    		
    	gpNTGLAPI->glClientActiveTextureARB(GL_TEXTURE0_ARB);
    	NT_GL(glEnableClientState(GL_TEXTURE_COORD_ARRAY))
    
    	for(ptr = mMS3DRenderData.begin(); ptr != mMS3DRenderData.end(); ptr++)
    	{
    		pTempData	=	*ptr;
    
    		pTempModel	=	pTempData->pModel;
    		
    		//	pTempModel->Draw(&pTempData->Position,pTempData->Orientation.x,pTempData->Orientation.y,pTempData->Orientation.z);
    		CMS3D_MODEL::mesh	*pMesh = NULL;
    		CMS3D_MODEL::material *pMaterial = NULL;
    		CMS3D_MODEL::vertex	*pVert = NULL;
    		CMS3D_MODEL::triangle	*pTri = NULL;
    		
    
    		NT_GL(glPushMatrix())
    
    		NT_GL(glTranslatef(pTempData->Position.x,pTempData->Position.y,pTempData->Position.z))
    		NT_GL(glRotatef(pTempData->Orientation.x,1,0,0))
    		NT_GL(glRotatef(pTempData->Orientation.y,0,1,0))
    		NT_GL(glRotatef(pTempData->Orientation.z,0,0,1))
    		
    		//Each mesh shares the same material index
    		Vector3	tosend;	//the final vert you send to OpenGL
    		Vector3	lightnormal;	//preferably the goraud shaded normal
    
    
    		for(int i = 0; i < pTempModel->mNumMeshes; i++)
    		{
    			pMesh	=	&pTempModel->mpMeshes[i];
    			pMaterial	=	&pTempModel->mpMaterials[pMesh->materialindex];
    
    			gpTextureManager->BindTexture(GL_TEXTURE_2D,pMaterial->mTexture);
    
    			for(int j = 0; j < pMesh->mNumTriangles; j++)
    			{
    				pTri	=	&pTempModel->mpTriangles[pMesh->TriangleIndices[j]];
    			
    				gpNTGLAPI->ntglBegin(GL_TRIANGLES);
    				for(int k = 0; k < 3; k++)
    				{
    					pVert = &pTempModel->mpVertices[pTri->mVertexIndices[k]];
    					tosend.x = pVert->mCoord[0];
    					tosend.y = pVert->mCoord[1];
    					tosend.z = pVert->mCoord[2];
    					
    
    					gpNTGLAPI->ntglTexCoord2f(pTri->m_s[k],pTri->m_t[k]);
    					gpNTGLAPI->ntglVertex3f(tosend.x,tosend.y,tosend.z);
    				}
    				gpNTGLAPI->ntglEnd();
    			}
    		}
    		NT_GL(glPopMatrix())
    	}
    	R_QuakeCullMode();	//FIXME: don't really need to do this here dumbass
    }


    Now, you may be wondering, where exactly do I call this render function? I have a function in my GLRenderer called RenderScene. There is a grace period for each frame where the engine updates all objects. Anything that wants to have itself drawn adds its pertinent data to the renderer.

    At the end of this grace period, the engine finally calls the renderer's RenderScene function. This is what the renderscene function looks like:

    Code:
    void	GLRenderer::GLRenderScene()
    {
    	NT_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))
    	NT_GL(glMatrixMode(GL_MODELVIEW))
    	NT_GL(glLoadIdentity())
    
    
    	Vector3	Pos(0,0,0);
    	Vector3	View(0,0,0);
    	Vector3	Up(0,0,0);
    	
    	/*
    		-Generate the matrix to represent the current view direction and position
    	*/
    
    	NT_GL(glMatrixMode(GL_MODELVIEW))
    	NT_GL(glPushMatrix())
    	NT_GL(glLoadIdentity())
    
    	Pos		= (Export.mpPlayer.mpCam->mPosition);
    
    	R_GenerateViewMatrix(RAD2DEG(Export.mpPlayer.mpCam->xRadians),RAD2DEG(Export.mpPlayer.mpCam->yRadians),0,Pos);
    
    	/*
    		-Render everything that has been sent to the renderer
    	*/
    	RenderQuake3SingleTexturedFaces();
    	RenderQuake3MultiTexturedFaces();
    
    	RenderMS3DModels();
    	RenderAllDebugSpheres();
    	RenderAllDebugLines();
    	RenderAllDebugBoxes();
    	RenderAllDebugPoints();
    
    	RenderBasicQuads();
    	RenderSkyBox();
    	RenderSkySphere();
    	RenderAlphaBlendedQuads();	//NEEDS TO COME LAST!!!
    	NT_GL(glPopMatrix())
    
    	/*
    		-This needs to come last because Text is drawn ontop of everything else (otherwise it can be depth-tested away)
    	*/
    	gpTextManager->DrawText();
    	
    	SwapBuffers(gpNTGLAPI->NT_DEVICE_CONTEXT);
    	
    	/*
    		-This clears the containers so they can be re-filled for the next scene
    	*/
    	ResetScene();
    	NT_GL(glMatrixMode(GL_MODELVIEW))
    	NT_GL(glLoadIdentity())
    }
    There are about 10 million valid criticisms against my design. But, this works, I like it, it's easy to maintain, and once I've implemented something it's easy to reuse it.

    EDIT:
    So we have our Object, lets call him a.. hmm, a carrot top.. yes..

    So, carrot top has like, this bit of information, that people need to draw him... (we'll deal with textures first)...

    So carrot goes over to Resource Cache, and resource cache asks wtf do you look like carrot top...

    Carrot top is all like, "carrot.jpeg".... and resource cache is like, noob, and he creates a pointer to a resource struct sizeof whatever carrot top rambles about... which we all know could be a lot..

    So resource cache is like, okay, sweet, now we have your data structure, I'll throw this in resource container blah, in resource slot ***37*** <--- OBJECT ID!!!...

    Carrot top is like, sweet, now I know what object ID I am... and so he heads over to the render list... renderlist is like, dude, carrot top, WTF are you?

    And carrot replies, I'm a number 37 bizaaaatch... and renderlist checks out container 37, hmm, carrot.jpeg...

    Then renderlist heads over to render engine, hes all like, we need a number 37 please, a "carrot.jpeg".... renderengine is all like, ANOTHER CARROT TOP?!

    He draws it reluctantly...

    End story
    You know, in the picture you sent me you appear to be about 18 years old. None of this is particularly easy, and although bubba and I have clashed before he doesn't really deserve the sarcasm. I have just given you everything I do for adding a milkshape3d model to the renderer. You implied that giving you code would help you, so I've given you the swamp of code that I use to perform one very mundane, very specific task in an engine of ~30,000 lines of code. If you still are having trouble, we are going to go back to metaphors, but ultimately you will learn by trying stuff, being frustrated (which is a good sign, shows you are trying) and finding what works on your own.

    And, it's not like your on a particularly slow learning curve. It's not like bubba or I were just born knowing how to do this ...........well, perhaps bubba, but it sure as hell took me forever and a day, and it's not like I'm writing professional quality code.
    Last edited by BobMcGee123; 01-18-2006 at 06:23 AM.
    I'm not immature, I'm refined in the opposite direction.

  14. #29
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Oh, don't get me wrong, that metaphor right there was in all seriousness..

    I really ment that , no sarcasm .

    I like metaphors, no one was giving me a good one .. You should know that by now... I work in metaphors ..
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  15. #30

    Join Date
    May 2005
    Posts
    1,042
    Okay, well you can forget me helping you from now on.

    Figure it out on your own.

    I enjoy talking about programming but I don't ultimately care if you get anything working.

    The only appropriate answer to my reply would have been a constructive question to figure out what I was saying. You didn't want metaphors, so I posted code. I posted code, and you post more of that little cocky bastard ......... Subsequently, I can only conclude that you aren't motivated enough to do this.

    If you have a change of heart and want to ask me a question I may reconsider.

    EDIT:
    another thing I would like to point out...everything you are struggling with is stuff myself and bubba have struggled with before. We know how to struggle, and be frustrated. Being a successful programmer means living in a constant state of heightened frustration. Learn to deal with that frustration more effectively (don't ........ off people that may otherwise help you).
    Last edited by BobMcGee123; 01-18-2006 at 08:52 AM.
    I'm not immature, I'm refined in the opposite direction.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. VC++ 6 Menu resource question
    By Mecnels in forum Windows Programming
    Replies: 1
    Last Post: 04-22-2003, 12:04 PM
  2. JPEG Resource
    By dragunsflame in forum Windows Programming
    Replies: 2
    Last Post: 04-08-2003, 10:07 PM
  3. resource problem/question
    By stallion in forum Windows Programming
    Replies: 4
    Last Post: 01-29-2003, 02:08 PM
  4. menu resource file
    By satriani in forum Windows Programming
    Replies: 5
    Last Post: 06-08-2002, 10:52 PM
  5. Radiohead rule
    By Brian in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 01-18-2002, 07:37 PM