VS 2005 problems...?

Started by
15 comments, last by Will Vale 16 years, 10 months ago
Hello! Well after installing VS 2005 and eventually getting my code to compile without all the depricated warnings with fopen(), strupr() and annoying scoped out int i = 0; i < whatever etc etc inside a alot of functions im getting memory leaks being picked up using _CrtDumpMemoryLeaks() where as before hand using .NET 2003 I wasn't... I've narrowed it down to this bit of code: void Model3DS::DeleteModel( t3DModel* pModel ) { int i = 0; for( i = 0; i < pModel->numOfObjects; i++ ) { if( pModel->pObject.pFaces != NULL ) { delete [] (pModel->pObject.pFaces); pModel->pObject.pFaces = NULL; } if( pModel->pObject.pNormals != NULL ) { delete [] (pModel->pObject.pNormals); pModel->pObject.pNormals = NULL; } if( pModel->pObject.pVerts != NULL ) { delete [] (pModel->pObject.pVerts); pModel->pObject.pVerts = NULL; } if( pModel->pObject.pTexVerts != NULL ) { delete [] pModel->pObject.pTexVerts; pModel->pObject.pTexVerts = NULL; } } pModel->pObject.clear(); pModel->pMaterials.clear(); pModel = NULL; } Can anyone think of a reason why VS 2005 would report the .3DS model as not free'd and .NET 2003 says everything is fine? Cheers!
Show A Man A Program, Frustrate Him For A Day...Teach A Man To Program, Frustrate Him For The Rest Of His Life...
Advertisement
Answer to question:

It looks like you might be forgetting to delete the model itself (i.e. delete pModel) at the bottom of the function.

Well-intentioned advice which you are free to ignore:

It's OK to pass NULL to delete, so you don't need to do all the "if ( x != NULL )" checks unless you really like them :) This only applies to delete though!

You might also want to encapsulate the ownership of the model internals in the model itself, so that deleting the model does all the other stuff, rather than having external code do it. To do this, put all the "delete pModel->something" code into the model destructor as just "delete something".

You might then also want to use STL containers to store all those internals so you don't have to remember to delete them. Makes looking after memory much easier, but there are pros and cons to STL so this isn't something you should feel you *have* to do.

Hope this helps!

Cheers,

Will
Hey! Cheers for the help mate!

Well I'm actually passing by reference to the Model3DS::DeleteModel( t3DModel* pModel ) code DeleteModel( &model )...so model isn't a pointer...so I don't actually need to call delete pModel inside of DeleteModel() etc

So I can't really see what else it can be? :S

Cheers

- DB
Show A Man A Program, Frustrate Him For A Day...Teach A Man To Program, Frustrate Him For The Rest Of His Life...
Quote:Original post by Will Vale
You might also want to encapsulate the ownership of the model internals in the model itself, so that deleting the model does all the other stuff, rather than having external code do it. To do this, put all the "delete pModel->something" code into the model destructor as just "delete something".


QFE.

The object should encapsulate its internals. If I, as a third-party developer, allocate a model, then delete it (either because it had automatic scope and was deleted as the flow of execution left that block or because I've called delete on a pointer to it) then I, quite reasonably, expect exactly that -- that it was deleted. Use the destructor.

It will also help to avoid problems like you're having at the moment because rather than having to delete a whole bunch of stuff and then the model, you need only delete the model.
[TheUnbeliever]
If your program is deterministic in how it allocates memory, you can use the allocation id reported by the CRT - this should be in your leak report. Add a call to _CrtSetBreakAlloc(long) at the start of your program and pass in this number. You should then break into the debugger on the allocation which is leaking.

If your program isn't deterministic (the order of allocations changes each time you run it, as may happen with leaks during gameplay) you can't do this. If this happens to me I usually use the allocation sizes to give me a clue as to what it is that might be leaking.

If none of this works you might need to post your Model class header so we can see what it allocates and make sure it matches with what's freed. Your code snippet is a bit isolated.

Oh, and if you're also considering making any of the suggested changes to improve your code, I'd make sure to find + fix the memory leak first rather than hoping that the changes will deal with it. Otherwise you might just be covering up a different problem...

Cheers,

Will
Reading comprehension, anyone?

It's unlikely we can help you without more information.

First, use source tags.
Second, share the declaration of t3DModel.

You could be doing something obviously wrong, but we can't tell because we don't know anything about the types involved.
Cheers guys! :) Here the code...just a few notes:

I originally got this source from the net and wrapped up the original functions into a class. Oh, and yes I should move all the deletion into the destructor I know, I was just keeping Destroy() outside the class for testing purposes to start off with. Usually I would use pointers for t3DModel struct inside this class BUT i'm getting a NULL ptr in there somewhere with t3DObject::strName, I'll sort that out later tho...


/////////////////////////////////////////////////////////////// HEADER//--------------------------------------------------------------------------------------------------/**@file			3ds.h@brief			Loads in a .3DS file**///--------------------------------------------------------------------------------------------------#ifndef _3DS_H_#define _3DS_H_//--------------------------------------------------------------------------------------------------/**@includes**///--------------------------------------------------------------------------------------------------#include "TextureManager.h"#include "Math.h"#include &lt;vector&gt;#include &lt;fstream&gt;#pragma warning(disable:4267) //--------------------------------------------------------------------------------------------------/**@defines**///--------------------------------------------------------------------------------------------------#define PRIMARY				0x4D4D#define OBJECTINFO			0x3D3D			// This gives the version of the mesh and is found right before the material and object information#define VERSION				0x0002			// This gives the version of the .3ds file#define EDITKEYFRAME		0xB000			// This is the header for all of the key frame info#define MATERIAL			0xAFFF			// This stored the texture info#define OBJECT				0x4000			// This stores the faces, vertices, etc...#define MATNAME				0xA000			// This holds the material name#define MATDIFFUSE			0xA020			// This holds the color of the object/material#define MATMAP				0xA200			// This is a header for a new material#define MATMAPFILE			0xA300			// This holds the file name of the texture#define OBJECT_MESH			0x4100			// This lets us know that we are reading a new object#define OBJECT_VERTICES     0x4110			// The objects vertices#define OBJECT_FACES		0x4120			// The objects faces#define OBJECT_MATERIAL		0x4130			// This is found if the object has a material, either texture map or color#define OBJECT_UV			0x4140			// The UV texture coordinates//--------------------------------------------------------------------------------------------------/**@forward declarations**///--------------------------------------------------------------------------------------------------class ModelManager;//--------------------------------------------------------------------------------------------------/**@struct			tFace@brief			Face info for the model**///--------------------------------------------------------------------------------------------------struct tFace{	int vertIndex[3];			// Indicies for the verts that make up this triangle	int coordIndex[3];			// Indicies for the tex coords to texture this face};//--------------------------------------------------------------------------------------------------/**@struct			tMaterialInfo@brief			Material info for the model**///--------------------------------------------------------------------------------------------------struct tMaterialInfo{	char strName[255];		// The texture name	char strFile[255];		// The texture file name (If this is set it's a texture map)	u8   color[3];			// The color of the object (R, G, B)	int  texureId;			// the texture ID	f32  uTile;				// u tiling of texture  (Currently not used)	f32  vTile;				// v tiling of texture	(Currently not used)	f32  uOffset;			// u offset of texture	(Currently not used)	f32  vOffset;			// v offset of texture	(Currently not used)};//--------------------------------------------------------------------------------------------------/**@struct			t3DObjectBounds@brief			This holds all the information for our model/scene. 				You should eventually turn into a robust class that 				has loading/drawing/querying functions like:				LoadModel(...); DrawObject(...); DrawModel(...); DestroyModel(...);**///--------------------------------------------------------------------------------------------------struct t3DObject {	int	           numOfVerts;			// The number of verts in the model	int	           numOfFaces;			// The number of faces in the model	int	           numTexVertex;		// The number of texture coordinates	int	           materialID;			// The texture ID to use, which is the index into our texture array	bool           bHasTexture;			// This is TRUE if there is a texture map for this object	char           strName[255];		// The name of the object	Vector3        *pVerts;				// The object's vertices	Vector3        *pNormals;			// The object's normals	Vector2		   *pTexVerts;			// The texture's UV coordinates	tFace          *pFaces;				// The faces information of the object};//--------------------------------------------------------------------------------------------------/**@enum			ELEMENT@brief			**///--------------------------------------------------------------------------------------------------enum ELEMENT{	kX = 1,	kY = 2,	kZ = 3};//--------------------------------------------------------------------------------------------------/**@struct			t3DModel@brief			This holds our model information.  This should also turn into a robust class.				We use STL's (Standard Template Library) vector class to ease our link list burdens. :)**///--------------------------------------------------------------------------------------------------struct t3DModel {	int					  numOfObjects;	  // The number of objects in the model	int					  numOfMaterials; // The number of materials for the model	vector&lt;tMaterialInfo&gt; pMaterials;	  // The list of material information (Textures and colors)	vector&lt;t3DObject&gt;	  pObject;		  // The object list for our model};//--------------------------------------------------------------------------------------------------/**@struct			tIndices@brief			Here is our structure for our 3DS indicies (since .3DS stores 4 unsigned shorts)**///--------------------------------------------------------------------------------------------------struct tIndices{								unsigned short a, b, c, bVisible;		// This will hold point1, 2, and 3 index's into the											// vertex array plus a visible flag};//--------------------------------------------------------------------------------------------------/**@struct			tChunk@brief			This holds the chunk info**///--------------------------------------------------------------------------------------------------struct tChunk{	unsigned short int ID;					// The chunk's ID			unsigned int       length;				// The length of the chunk	unsigned int       bytesRead;			// The amount of bytes read within that chunk};//--------------------------------------------------------------------------------------------------/**@class			Model3DS@brief			This class handles all of the loading code**///--------------------------------------------------------------------------------------------------class Model3DS{	friend class ModelManager;public:	Model3DS();	//~Model3DS()	//{	//	Destroy();	//}	bool				Load( char* strFileName,							  char* filter,							  char* wrap,							  char* texEnv,							  u8	alphaR = 255,							  u8	alphaG = 0,							  u8	alphaB = 255 );	void				 Destroy();	bool				 ComputeObjectData();	bool				 WriteData( const char* fileName ) const;		void				 Render();	inline t3DObject     GetObject( uint index ) const;	inline t3DModel		 GetModel() const;	inline tMaterialInfo GetModelMaterial( uint index ) const;private:	// Will hold collision data and such for each	// object in the model	struct ObjectData	{			Vector3 largestVertices;		f32		largestVertex;		Vector3 largestPositives;		Vector3 largestNegatives;		f32		width;		f32		height;		f32		depth;		f32		centerX;		f32		centerY;		f32		centerZ;	};		bool   Import3DS( t3DModel* pModel, char* strFileName );	void   CreateModelTextures( t3DModel* pModel, 								uint**	  textureArray, 								char*	  filter,								char*	  wrap,								char*     texEnv,								u8	      r = 255, 								u8		  g = 0,								u8		  b = 255 );	void	RenderModel( t3DModel* pModel, uint* textureArray );	void	DeleteModel( t3DModel* pModel );	int     GetString( char* str );	void    ReadChunk( tChunk* pChunk );	void    ProcessNextChunk( t3DModel *pModel, tChunk* pChunk );	void    ProcessNextObjectChunk( t3DModel *pModel, t3DObject* pObject, tChunk* pChunk );	void    ProcessNextMaterialChunk( t3DModel* pModel, tChunk* pChunk );	void    ReadColorChunk( tMaterialInfo* pMaterial, tChunk* pChunk );	void    ReadVertices( t3DObject* pObject, tChunk* pChunk );	void    ReadVertexIndices( t3DObject* pObject, tChunk* pChunk );	void    ReadUVCoordinates( t3DObject* pObject, tChunk* pChunk );	void    ReadObjectMaterial( t3DModel* pModel, t3DObject* pObject, tChunk* pPreviousChunk );	void    ComputeNormals( t3DModel* pModel );	f32	    FindLargestVertex( t3DObject* pObject );	Vector3 FindLargestVertexXYZ( t3DObject* pObject );	f32	    FindLargestPoint( t3DObject* pObject, ELEMENT which );	f32		FindLargestPointNoAbs( t3DObject* pObject, ELEMENT which );	f32	    FindLowestPoint( t3DObject* pObject, ELEMENT which );	f32		FindDimensions( t3DObject* pObject, ELEMENT which );	f32		FindCenter( t3DObject* pObject, ELEMENT which );	FILE*				  m_pFilePointer;	t3DModel			  m_Model;	uint*				  m_pTextureArray;		bool				  m_ModelLoaded;	bool				  m_ObjectDataComputed;	vector &lt; ObjectData &gt; m_ObjectData;	int					  m_Buffer[50000]; // Used to read past unwanted data};//--------------------------------------------------------------------------------------------------/**@function		GetModel@brief			Returns the model struct**///--------------------------------------------------------------------------------------------------inline t3DModel Model3DS::GetModel() const{	assert( m_ModelLoaded && "Model not loaded!" );	return m_Model;}#endif // _3DS_H_ /////////////////////////////////////////// CPP#include "3ds.h"//--------------------------------------------------------------------------------------------------/**@function		Ctor	@brief			Initialise file ptr	**///--------------------------------------------------------------------------------------------------Model3DS::Model3DS(){	m_pFilePointer       = NULL;	m_pTextureArray      = NULL;	m_ModelLoaded        = false;	m_ObjectDataComputed = false;}//--------------------------------------------------------------------------------------------------/**@function		Import3DS	@brief			Loads in the 3D model	**///--------------------------------------------------------------------------------------------------bool Model3DS::Import3DS(t3DModel *pModel, char *strFileName){	char strMessage[255] = {0};	tChunk currentChunk = {0};	// Open the 3DS file	m_pFilePointer = fopen( strFileName, "rb" );	// Make sure we have a valid file pointer (we found the file)	if( !m_pFilePointer ) 	{		sprintf(strMessage, "Unable to find the file: %s!", strFileName);		MessageBox(NULL, strMessage, "Error", MB_OK);		return false;	}	// Once we have the file open, we need to read the very first data chunk	// to see if it's a 3DS file.  That way we don't read an invalid file.	// If it is a 3DS file, then the first chunk ID will be equal to PRIMARY (some hex num)	// Read the first chuck of the file to see if it's a 3DS file	ReadChunk(¤tChunk);	// Make sure this is a 3DS file	if (currentChunk.ID != PRIMARY)	{		sprintf(strMessage, "Unable to load PRIMARY chuck from file: %s!", strFileName);		MessageBox(NULL, strMessage, "Error", MB_OK);		return false;	}	// Now we actually start reading in the data.  ProcessNextChunk() is recursive	// Begin loading objects, by calling this recursive function	ProcessNextChunk(pModel, ¤tChunk);	// After we have read the whole 3DS file, we want to calculate our own vertex normals.	ComputeNormals(pModel);	return true;}//--------------------------------------------------------------------------------------------------/**@function		ProcessNextChunk	@brief			This function reads the main sections of the .3DS file, then dives deeper with recursion	**///--------------------------------------------------------------------------------------------------void Model3DS::ProcessNextChunk(t3DModel *pModel, tChunk *pPreviousChunk){	t3DObject newObject = {0};					// This is used to add to our object list	tMaterialInfo newTexture = {0};				// This is used to add to our material list	tChunk currentChunk = {0};					// The current chunk to load	tChunk tempChunk = {0};						// A temp chunk for holding data			// Below we check our chunk ID each time we read a new chunk.  Then, if	// we want to extract the information from that chunk, we do so.	// If we don't want a chunk, we just read past it.  	// Continue to read the sub chunks until we have reached the length.	// After we read ANYTHING we add the bytes read to the chunk and then check	// check against the length.	while (pPreviousChunk-&gt;bytesRead &lt; pPreviousChunk-&gt;length)	{		// Read next Chunk		ReadChunk(¤tChunk);		// Check the chunk ID		switch (currentChunk.ID)		{		case VERSION:							// This holds the version of the file			// If the file was made in 3D Studio Max, this chunk has an int that 			// holds the file version.  Since there might be new additions to the 3DS file			// format in 4.0, we give a warning to that problem.			// However, if the file wasn't made by 3D Studio Max, we don't 100% what the			// version length will be so we'll simply ignore the value			// Read the file version and add the bytes read to our bytesRead variable			currentChunk.bytesRead += fread(m_Buffer, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			// If the file version is over 3, give a warning that there could be a problem			if ((currentChunk.length - currentChunk.bytesRead == 4) && (m_Buffer[0] &gt; 0x03)) {				MessageBox(NULL, "This 3DS file is over version 3 so it may load incorrectly", "Warning", MB_OK);			}			break;		case OBJECTINFO:						// This holds the version of the mesh			{					// This chunk holds the version of the mesh.  It is also the head of the MATERIAL				// and OBJECT chunks.  From here on we start reading in the material and object info.				// Read the next chunk				ReadChunk(&tempChunk);				// Get the version of the mesh				tempChunk.bytesRead += fread(m_Buffer, 1, tempChunk.length - tempChunk.bytesRead, m_pFilePointer);				// Increase the bytesRead by the bytes read from the last chunk				currentChunk.bytesRead += tempChunk.bytesRead;				// Go to the next chunk, which is the object has a texture, it should be MATERIAL, then OBJECT.				ProcessNextChunk(pModel, ¤tChunk);				break;			}		case MATERIAL:							// This holds the material information			// This chunk is the header for the material info chunks			// Increase the number of materials			pModel-&gt;numOfMaterials++;			// Add a empty texture structure to our texture list.			// If you are unfamiliar with STL's "vector" class, all push_back()			// does is add a new node onto the list.  I used the vector class			// so I didn't need to write my own link list functions.  			pModel-&gt;pMaterials.push_back(newTexture);			// Proceed to the material loading function			ProcessNextMaterialChunk(pModel, ¤tChunk);			break;		case OBJECT:							// This holds the name of the object being read			// This chunk is the header for the object info chunks.  It also			// holds the name of the object.			// Increase the object count			pModel-&gt;numOfObjects++;			// Add a new tObject node to our list of objects (like a link list)			pModel-&gt;pObject.push_back(newObject);			// Initialize the object and all it's data members			memset(&(pModel-&gt;pObject[pModel-&gt;numOfObjects - 1]), 0, sizeof(t3DObject));			// Get the name of the object and store it, then add the read bytes to our byte counter.			currentChunk.bytesRead += GetString(pModel-&gt;pObject[pModel-&gt;numOfObjects - 1].strName);			// Now proceed to read in the rest of the object information			ProcessNextObjectChunk(pModel, &(pModel-&gt;pObject[pModel-&gt;numOfObjects - 1]), ¤tChunk);			break;		case EDITKEYFRAME:			// Because I wanted to make this a SIMPLE tutorial as possible, I did not include			// the key frame information.  This chunk is the header for all the animation info.			// In a later tutorial this will be the subject and explained thoroughly.			//ProcessNextKeyFrameChunk(pModel, currentChunk);			// Read past this chunk and add the bytes read to the byte counter			currentChunk.bytesRead += fread(m_Buffer, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			break;		default: 			// If we didn't care about a chunk, then we get here.  We still need			// to read past the unknown or ignored chunk and add the bytes read to the byte counter.			currentChunk.bytesRead += fread(m_Buffer, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			break;		}		// Add the bytes read from the last chunk to the previous chunk passed in.		pPreviousChunk-&gt;bytesRead += currentChunk.bytesRead;	}}//--------------------------------------------------------------------------------------------------/**@function		ProcessNextObjectChunk	@brief			This function handles all the information about the objects in the file	**///--------------------------------------------------------------------------------------------------void Model3DS::ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk){	// The current chunk to work with	tChunk currentChunk = {0};	// Continue to read these chunks until we read the end of this sub chunk	while (pPreviousChunk-&gt;bytesRead &lt; pPreviousChunk-&gt;length)	{		// Read the next chunk		ReadChunk(¤tChunk);		// Check which chunk we just read		switch (currentChunk.ID)		{		case OBJECT_MESH:					// This lets us know that we are reading a new object			// We found a new object, so let's read in it's info using recursion			ProcessNextObjectChunk(pModel, pObject, ¤tChunk);			break;		case OBJECT_VERTICES:				// This is the objects vertices			ReadVertices(pObject, ¤tChunk);			break;		case OBJECT_FACES:					// This is the objects face information			ReadVertexIndices(pObject, ¤tChunk);			break;		case OBJECT_MATERIAL:				// This holds the material name that the object has			// This chunk holds the name of the material that the object has assigned to it.			// This could either be just a color or a texture map.  This chunk also holds			// the faces that the texture is assigned to (In the case that there is multiple			// textures assigned to one object, or it just has a texture on a part of the object.			// Since most of my game objects just have the texture around the whole object, and 			// they aren't multitextured, I just want the material name.			// We now will read the name of the material assigned to this object			ReadObjectMaterial(pModel, pObject, ¤tChunk);						break;		case OBJECT_UV:						// This holds the UV texture coordinates for the object			// This chunk holds all of the UV coordinates for our object.  Let's read them in.			ReadUVCoordinates(pObject, ¤tChunk);			break;		default:  			// Read past the ignored or unknown chunks			currentChunk.bytesRead += fread(m_Buffer, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			break;		}		// Add the bytes read from the last chunk to the previous chunk passed in.		pPreviousChunk-&gt;bytesRead += currentChunk.bytesRead;	}}//--------------------------------------------------------------------------------------------------/**@function		ProcessNextMaterialChunk	@brief			This function handles all the information about the material (Texture)**///--------------------------------------------------------------------------------------------------void Model3DS::ProcessNextMaterialChunk(t3DModel *pModel, tChunk *pPreviousChunk){	// The current chunk to work with	tChunk currentChunk = {0};	// Continue to read these chunks until we read the end of this sub chunk	while (pPreviousChunk-&gt;bytesRead &lt; pPreviousChunk-&gt;length)	{		// Read the next chunk		ReadChunk(¤tChunk);		// Check which chunk we just read in		switch (currentChunk.ID)		{		case MATNAME:							// This chunk holds the name of the material			// Here we read in the material name			currentChunk.bytesRead += fread(pModel-&gt;pMaterials[pModel-&gt;numOfMaterials - 1].strName, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			break;		case MATDIFFUSE:						// This holds the R G B color of our object			ReadColorChunk(&(pModel-&gt;pMaterials[pModel-&gt;numOfMaterials - 1]), ¤tChunk);			break;		case MATMAP:							// This is the header for the texture info			// Proceed to read in the material information			ProcessNextMaterialChunk(pModel, ¤tChunk);			break;		case MATMAPFILE:						// This stores the file name of the material			// Here we read in the material's file name			currentChunk.bytesRead += fread(pModel-&gt;pMaterials[pModel-&gt;numOfMaterials - 1].strFile, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			break;		default:  			// Read past the ignored or unknown chunks			currentChunk.bytesRead += fread(m_Buffer, 1, currentChunk.length - currentChunk.bytesRead, m_pFilePointer);			break;		}		// Add the bytes read from the last chunk to the previous chunk passed in.		pPreviousChunk-&gt;bytesRead += currentChunk.bytesRead;	}}//--------------------------------------------------------------------------------------------------/**@function		ReadChunk@brief			This function reads in a chunk ID and it's length in bytes**///--------------------------------------------------------------------------------------------------void Model3DS::ReadChunk(tChunk *pChunk){	// This reads the chunk ID which is 2 bytes.	// The chunk ID is like OBJECT or MATERIAL.  It tells what data is	// able to be read in within the chunks section.  	pChunk-&gt;bytesRead = fread(&pChunk-&gt;ID, 1, 2, m_pFilePointer);	// Then, we read the length of the chunk which is 4 bytes.	// This is how we know how much to read in, or read past.	pChunk-&gt;bytesRead += fread(&pChunk-&gt;length, 1, 4, m_pFilePointer);}//--------------------------------------------------------------------------------------------------/**@function		GetString@brief			This function reads in a string of characters**///--------------------------------------------------------------------------------------------------int Model3DS::GetString(char *pBuffer){	int index = 0;	// Read 1 byte of data which is the first letter of the string	fread(pBuffer, 1, 1, m_pFilePointer);	// Loop until we get NULL	while (*(pBuffer + index++) != 0)	{		// Read in a character at a time until we hit NULL.		fread(pBuffer + index, 1, 1, m_pFilePointer);	}	// Return the string length, which is how many bytes we read in (including the NULL)	return strlen(pBuffer) + 1;}//--------------------------------------------------------------------------------------------------/**@function		ReadColorChunk@brief			This function reads in the RGB color data**///--------------------------------------------------------------------------------------------------void Model3DS::ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk){	tChunk tempChunk = {0};	// Read the color chunk info	ReadChunk(&tempChunk);	// Read in the R G B color (3 bytes - 0 through 255)	tempChunk.bytesRead += fread(pMaterial-&gt;color, 1, tempChunk.length - tempChunk.bytesRead, m_pFilePointer);	// Add the bytes read to our chunk	pChunk-&gt;bytesRead += tempChunk.bytesRead;}//--------------------------------------------------------------------------------------------------/**@function		ReadVertexIndices@brief			This function reads in the indices for the vertex array**///--------------------------------------------------------------------------------------------------void Model3DS::ReadVertexIndices(t3DObject *pObject, tChunk *pPreviousChunk){	unsigned short index = 0;					// This is used to read in the current face index	// In order to read in the vertex indices for the object, we need to first	// read in the number of them, then read them in.  Remember,	// we only want 3 of the 4 values read in for each face.  The fourth is	// a visibility flag for 3D Studio Max that doesn't mean anything to us.	// Read in the number of faces that are in this object (int)	pPreviousChunk-&gt;bytesRead += fread(&pObject-&gt;numOfFaces, 1, 2, m_pFilePointer);	// Alloc enough memory for the faces and initialize the structure	pObject-&gt;pFaces = new tFace [pObject-&gt;numOfFaces];	memset(pObject-&gt;pFaces, 0, sizeof(tFace) * pObject-&gt;numOfFaces);	// Go through all of the faces in this object	for(int i = 0; i &lt; pObject-&gt;numOfFaces; i++)	{		// Next, we read in the A then B then C index for the face, but ignore the 4th value.		// The fourth value is a visibility flag for 3D Studio Max, we don't care about this.		for(int j = 0; j &lt; 4; j++)		{			// Read the first vertice index for the current face 			pPreviousChunk-&gt;bytesRead += fread(&index, 1, sizeof(index), m_pFilePointer);			if(j &lt; 3)			{				// Store the index in our face structure.				pObject-&gt;pFaces.vertIndex[j] = index;			}		}	}}//--------------------------------------------------------------------------------------------------/**@function		ReadUVCoordinates@brief			This function reads in the UV coordinates for the object**///--------------------------------------------------------------------------------------------------void Model3DS::ReadUVCoordinates(t3DObject *pObject, tChunk *pPreviousChunk){	// In order to read in the UV indices for the object, we need to first	// read in the amount there are, then read them in.	// Read in the number of UV coordinates there are (int)	pPreviousChunk-&gt;bytesRead += fread(&pObject-&gt;numTexVertex, 1, 2, m_pFilePointer);	// Allocate memory to hold the UV coordinates	pObject-&gt;pTexVerts = new Vector2 [pObject-&gt;numTexVertex];	// Read in the texture coodinates (an array 2 f32)	pPreviousChunk-&gt;bytesRead += fread(pObject-&gt;pTexVerts, 1, pPreviousChunk-&gt;length - pPreviousChunk-&gt;bytesRead, m_pFilePointer);}//--------------------------------------------------------------------------------------------------/**@function		ReadVertices@brief			This function reads in the vertices for the object**///--------------------------------------------------------------------------------------------------void Model3DS::ReadVertices( t3DObject *pObject, tChunk *pPreviousChunk ){	// Like most chunks, before we read in the actual vertices, we need	// to find out how many there are to read in.  Once we have that number	// we then fread() them into our vertice array.	// Read in the number of vertices (int)	pPreviousChunk-&gt;bytesRead += fread(&(pObject-&gt;numOfVerts), 1, 2, m_pFilePointer);	// Allocate the memory for the verts and initialize the structure	pObject-&gt;pVerts = new Vector3 [pObject-&gt;numOfVerts];	memset(pObject-&gt;pVerts, 0, sizeof(Vector3) * pObject-&gt;numOfVerts);	// Read in the array of vertices (an array of 3 f32s)	pPreviousChunk-&gt;bytesRead += fread(pObject-&gt;pVerts, 1, pPreviousChunk-&gt;length - pPreviousChunk-&gt;bytesRead, m_pFilePointer);	// Now we should have all of the vertices read in.  Because 3D Studio Max	// Models with the Z-Axis pointing up (strange and ugly I know!), we need	// to flip the m_Y values with the m_Z values in our vertices.  That way it	// will be normal, with Y pointing up.  If you prefer to work with Z pointing	// up, then just delete this next loop.  Also, because we swap the Y and Z	// we need to negate the Z to make it come out correctly.	// Go through all of the vertices that we just read and swap the Y and Z values	for(int i = 0; i &lt; pObject-&gt;numOfVerts; i++)	{		// Store off the Y value		f32 fTempY = pObject-&gt;pVerts.GetY();		// Set the Y value to the Z value		pObject-&gt;pVerts.SetY( pObject-&gt;pVerts.GetZ() );		// Set the Z value to the Y value, 		// but negative Z because 3D Studio max does the opposite.		pObject-&gt;pVerts.SetZ( -fTempY );	}}//--------------------------------------------------------------------------------------------------/**@function		ReadObjectMaterial@brief		This function reads in the material name assigned to the object and sets the materialID**///--------------------------------------------------------------------------------------------------void Model3DS::ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk){	char strMaterial[255] = {0};			// This is used to hold the objects material name	// *What is a material?*  - A material is either the color or the texture map of the object.	// It can also hold other information like the brightness, shine, etc... Stuff we don't	// really care about.  We just want the color, or the texture map file name really.	// Here we read the material name that is assigned to the current object.	// strMaterial should now have a string of the material name, like "Material #2" etc..	pPreviousChunk-&gt;bytesRead += GetString(strMaterial);	// Now that we have a material name, we need to go through all of the materials	// and check the name against each material.  When we find a material in our material	// list that matches this name we just read in, then we assign the materialID	// of the object to that material index.  You will notice that we passed in the	// model to this function.  This is because we need the number of textures.	// Yes though, we could have just passed in the model and not the object too.	// Go through all of the textures	for(int i = 0; i &lt; pModel-&gt;numOfMaterials; i++)	{		// If the material we just read in matches the current texture name		if(strcmp(strMaterial, pModel-&gt;pMaterials.strName) == 0)		{			// Now that we found the material, check if it's a texture map.			// If the strFile has a string length of 1 and over it's a texture			if(strlen(pModel-&gt;pMaterials.strFile) &gt; 0) 			{								// Set the material ID to the current index 'i' and stop checking				pObject-&gt;materialID = i;				// Set the object's flag to say it has a texture map to bind.				pObject-&gt;bHasTexture = true;			}				break;		}		else		{			// Here we check first to see if there is a texture already assigned to this object			if(pObject-&gt;bHasTexture != true)			{				// Set the ID to -1 to show there is no material for this object				pObject-&gt;materialID = -1;			}		}	}	// Read past the rest of the chunk since we don't care about shared vertices	// You will notice we subtract the bytes already read in this chunk from the total length.	pPreviousChunk-&gt;bytesRead += fread(m_Buffer, 1, pPreviousChunk-&gt;length - pPreviousChunk-&gt;bytesRead, m_pFilePointer);}			//--------------------------------------------------------------------------------------------------/**@function		ComputeNormals@brief		This function computes the normals and vertex normals of the objects**///--------------------------------------------------------------------------------------------------void Model3DS::ComputeNormals(t3DModel *pModel){	Vector3 vVector1, vVector2, vNormal, vPoly[3];	// If there are no objects, we can skip this part	if( pModel-&gt;numOfObjects &lt;= 0 )		return;	// What are vertex normals?  And how are they different from other normals?	// Well, if you find the normal to a triangle, you are finding a "Face Normal".	// If you give OpenGL a face normal for lighting, it will make your object look	// really flat and not very round.  If we find the normal for each vertex, it makes	// the smooth lighting look.  This also covers up blocky looking objects and they appear	// to have more polygons than they do.    Basically, what you do is first	// calculate the face normals, then you take the average of all the normals around each	// vertex.  It's just averaging.  That way you get a better approximation for that vertex.	// Go through each of the objects to calculate their normals	for(int index = 0; index &lt; pModel-&gt;numOfObjects; index++)	{		// Get the current object		t3DObject *pObject = &(pModel-&gt;pObject[index]);		// Here we allocate all the memory we need to calculate the normals		Vector3 *pNormals		= new Vector3 [pObject-&gt;numOfFaces];		Vector3 *pTempNormals	= new Vector3 [pObject-&gt;numOfFaces];		pObject-&gt;pNormals		= new Vector3 [pObject-&gt;numOfVerts];		// Go though all of the faces of this object		for(int i=0; i &lt; pObject-&gt;numOfFaces; i++)		{															// To cut down LARGE code, we extract the 3 points of this face			vPoly[0] = pObject-&gt;pVerts[pObject-&gt;pFaces.vertIndex[0]];			vPoly[1] = pObject-&gt;pVerts[pObject-&gt;pFaces.vertIndex[1]];			vPoly[2] = pObject-&gt;pVerts[pObject-&gt;pFaces.vertIndex[2]];			// Now let's calculate the face normals (Get 2 vectors and find the cross product of those 2)			vVector1 = SubVector(vPoly[0], vPoly[2]);		// Get the vector of the polygon (we just need 2 sides for the normal)			vVector2 = SubVector(vPoly[2], vPoly[1]);		// Get a second vector of the polygon			vNormal  = Cross(vVector1, vVector2);		// Return the cross product of the 2 vectors (normalize vector, but not a unit vector)			pTempNormals = vNormal;					// Save the un-normalized normal for the vertex normals			vNormal  = Normalize(vNormal);				// Normalize the cross product to give us the polygons normal			pNormals = vNormal;						// Assign the normal to the list of normals		}		//////////////// Now Get The Vertex Normals /////////////////		Vector3 vSum(0.0f, 0.0f, 0.0f);		Vector3 vZero = vSum;		int shared=0;		for (i = 0; i &lt; pObject-&gt;numOfVerts; i++)			// Go through all of the vertices		{			for (int j = 0; j &lt; pObject-&gt;numOfFaces; j++)	// Go through all of the triangles			{												// Check if the vertex is shared by another face				if (pObject-&gt;pFaces[j].vertIndex[0] == i || 					pObject-&gt;pFaces[j].vertIndex[1] == i || 					pObject-&gt;pFaces[j].vertIndex[2] == i)				{					vSum = AddVector(vSum, pTempNormals[j]);// Add the un-normalized normal of the shared face					shared++;								// Increase the number of shared triangles				}			}      			// Get the normal by dividing the sum by the shared.  We negate the shared so it has the normals pointing out.			pObject-&gt;pNormals = DivideVectorByScaler(vSum, f32(-shared));			// Normalize the normal for the final vertex normal			pObject-&gt;pNormals = Normalize(pObject-&gt;pNormals);				vSum = vZero;									// Reset the sum			shared = 0;										// Reset the shared		}		// Free our memory and start over on the next object		delete [] pTempNormals;		delete [] pNormals;	}}//--------------------------------------------------------------------------------------------------/**@function		FindLargestVertex@brief			Finds the largest vertex in the model**///--------------------------------------------------------------------------------------------------f32 Model3DS::FindLargestVertex( t3DObject *pObject ){	Vector3 temp = FindLargestVertexXYZ( pObject );	f32 largest[] = { temp.GetX(), temp.GetY(), temp.GetZ() };	for( int k = 0; k &lt; 2; ++k)		for( int j = k + 1; j &gt; 0; --j )			if(largest[j] &gt; largest[j-1])			{				f32 temp = largest[j];				largest[j] = largest[j - 1];				largest[j - 1] = temp;			}	return largest[0];}//--------------------------------------------------------------------------------------------------/**@function		FindLargestPoint@brief			Finds the largest point in m_X, m_Y and m_Z axis of the model (depending on ELEMENT)**///--------------------------------------------------------------------------------------------------f32 Model3DS::FindLargestPoint( t3DObject* pObject, ELEMENT which ){	int numVerts = pObject-&gt;numOfVerts;	f32 finalLargest = -99999999.9f;	f32* largest = new f32[ numVerts ];	switch( which )	{	case kX:		for( int i = 0; i &lt; numVerts; i++ )		{			largest = abs( pObject-&gt;pVerts.GetX() );			if( largest &gt; finalLargest )				finalLargest = largest;		}		break;	case kY:		for( int i = 0; i &lt; numVerts; i++ )		{			largest = abs( pObject-&gt;pVerts.GetY() );			if( largest &gt; finalLargest )				finalLargest = largest;		}		break;	case kZ:		for( int i = 0; i &lt; numVerts; i++ )		{			largest = abs( pObject-&gt;pVerts.GetZ() );			if( largest &gt; finalLargest )				finalLargest = largest;		}		break;	default:		break;	}	SafeDeleteArray( largest );	return finalLargest;}//--------------------------------------------------------------------------------------------------/**@function		FindLargestPointNoAbs@brief			Finds the largest point in m_X, m_Y and m_Z axis of the model, excludes ABS on all 				vertices.**///--------------------------------------------------------------------------------------------------f32 Model3DS::FindLargestPointNoAbs( t3DObject* pObject, ELEMENT which ){	int numVerts = pObject-&gt;numOfVerts;	f32 finalLargest = -99999999.9f;	f32* largest = new f32[ numVerts ];	switch( which )	{	case kX:		for( int i = 0; i &lt; numVerts; i++ )		{			largest = pObject-&gt;pVerts.GetX();			if( largest &gt; finalLargest )				finalLargest = largest;		}		break;	case kY:		for( int i = 0; i &lt; numVerts; i++ )		{			largest = pObject-&gt;pVerts.GetY();			if( largest &gt; finalLargest )				finalLargest = largest;		}		break;	case kZ:		for( int i = 0; i &lt; numVerts; i++ )		{			largest = pObject-&gt;pVerts.GetZ();			if( largest &gt; finalLargest )				finalLargest = largest;		}		break;	default:		break;	}	SafeDeleteArray( largest );	return finalLargest;}//--------------------------------------------------------------------------------------------------/**@function		FindLowestPoint@brief			Finds the lowest point in m_X, m_Y and m_Z axis of the model (depending on ELEMENT)**///--------------------------------------------------------------------------------------------------f32 Model3DS::FindLowestPoint( t3DObject* pObject, ELEMENT which ){	int numVerts = pObject-&gt;numOfVerts;	f32 finalLowest = 99999999.9f;	f32* lowest = new f32[ numVerts ];	switch( which )	{	case kX:		for( int i = 0; i &lt; numVerts; i++ )		{			lowest = pObject-&gt;pVerts.GetX();			if( lowest &lt; finalLowest )				finalLowest = lowest;		}		break;	case kY:		for( int i = 0; i &lt; numVerts; i++ )		{			lowest = pObject-&gt;pVerts.GetY();			if( lowest &lt; finalLowest )				finalLowest = lowest;		}		break;	case kZ:		for( int i = 0; i &lt; numVerts; i++ )		{			lowest = pObject-&gt;pVerts.GetZ();			if( lowest &lt; finalLowest )				finalLowest = lowest;		}		break;	default:		break;	}	SafeDeleteArray( lowest );	return finalLowest;}//--------------------------------------------------------------------------------------------------/**@function		FindCenter@brief			**///--------------------------------------------------------------------------------------------------f32 Model3DS::FindCenter( t3DObject* pObject, ELEMENT which ){	f32 lowest = FindLowestPoint( pObject, which );	f32 highest = FindLargestPointNoAbs( pObject, which );	return (lowest + highest) / 2.0f;}//--------------------------------------------------------------------------------------------------/**@function		FindLargestPoint@brief			Finds the largest point in m_X, m_Y and m_Z axis of the model (depending on ELEMENT)**///--------------------------------------------------------------------------------------------------Vector3 Model3DS::FindLargestVertexXYZ( t3DObject* pObject ){	f32 lX = FindLargestPoint( pObject, kX );	f32 lY = FindLargestPoint( pObject, kY );	f32 lZ = FindLargestPoint( pObject, kZ );    return Vector3( lX, lY, lZ );}//--------------------------------------------------------------------------------------------------/**@function		FindDimensions@brief			**///--------------------------------------------------------------------------------------------------f32 Model3DS::FindDimensions( t3DObject* pObject, ELEMENT which ){	f32 lowest = abs( FindLowestPoint( pObject, which ) );	f32 highest = FindLargestPointNoAbs( pObject, which );	return lowest + highest;}//--------------------------------------------------------------------------------------------------/**@function		DeleteModel@brief			Deletes the model data**///--------------------------------------------------------------------------------------------------void Model3DS::DeleteModel( t3DModel* pModel ){	for( int i = 0; i &lt; pModel-&gt;numOfObjects; i++ )	{		// Free the faces, normals, vertices's, and texture coordinates.		if( pModel-&gt;pObject.pFaces != NULL )		{			delete [] (pModel-&gt;pObject.pFaces);			pModel-&gt;pObject.pFaces = NULL;		}				if( pModel-&gt;pObject.pNormals != NULL )			{			delete [] (pModel-&gt;pObject.pNormals);			pModel-&gt;pObject.pNormals = NULL;		}				if( pModel-&gt;pObject.pVerts != NULL )			{			delete [] (pModel-&gt;pObject.pVerts);			pModel-&gt;pObject.pVerts = NULL;		}		if( pModel-&gt;pObject.pTexVerts != NULL )			{			delete [] pModel-&gt;pObject.pTexVerts;			pModel-&gt;pObject.pTexVerts = NULL;		}	}	pModel-&gt;pObject.clear();	pModel-&gt;pMaterials.clear();	pModel = NULL;}//--------------------------------------------------------------------------------------------------/**@function		CreateModelTextures@brief			Takes a ptr to a uint ptr. Finds the amount of textures in the model and creates the				uint array inside the function. The number of textures is assigned to arraySize.**///--------------------------------------------------------------------------------------------------void Model3DS::CreateModelTextures( t3DModel* pModel, 									uint** textureArray, 									char* filter,									char* wrap,									char* texEnv,									u8 r,									u8 g,									u8 b ){	uint size = pModel-&gt;numOfMaterials;	if( size &gt; 0 )		*textureArray = new uint[ size ];	// Go through all the materials	for(int i = 0; i &lt; pModel-&gt;numOfMaterials; i++)	{		// Check to see if there is a file name to load in this material		if( strlen( pModel-&gt;pMaterials.strFile ) &gt; 0 )			GenerateTextures( *textureArray,								i,								pModel-&gt;pMaterials.strFile, 								filter,								wrap,								texEnv,								r,								g,								b );		// Set the texture ID for this material		pModel-&gt;pMaterials.texureId = i;	}}//--------------------------------------------------------------------------------------------------/**@function		Destroy@brief		**///--------------------------------------------------------------------------------------------------void Model3DS::Destroy(){	if( m_Model.numOfMaterials &gt; 0 )			glDeleteTextures( m_Model.numOfMaterials, m_pTextureArray );	DeleteModel( &m_Model );	SafeDeleteArray( m_pTextureArray );	if( !m_ObjectData.empty() )		m_ObjectData.clear();}//--------------------------------------------------------------------------------------------------/**@function		RenderModel@brief			Renders the 3D model. Takes a texture array created in CreateModelTextures**///--------------------------------------------------------------------------------------------------void Model3DS::RenderModel( t3DModel* pModel, uint* textureArray ){	for(int i = 0; i &lt; pModel-&gt;numOfObjects; i++)	{		// Make sure we have valid objects just in case. (size() is in the vector class)		if(pModel-&gt;pObject.size() &lt;= 0) break;		// Get the current object that we are displaying		t3DObject *pObject = &pModel-&gt;pObject;		// Check to see if this object has a texture map, if so bind the texture to it.		if(pObject-&gt;bHasTexture)		{			// Turn on texture mapping and turn off color			glEnable(GL_TEXTURE_2D);			// Reset the color to normal again			glColor3ub(255, 255, 255);			// Bind the texture map to the object by it's materialID			glBindTexture(GL_TEXTURE_2D, textureArray[pObject-&gt;materialID]);		} else {			// Turn off texture mapping and turn on color			glDisable(GL_TEXTURE_2D);			// Reset the color to normal again			glColor3ub(255, 255, 255);		}		// This determines if we are in wireframe or normal mode		glBegin(GL_TRIANGLES);					// Begin drawing with our selected mode (triangles or lines)		// Go through all of the faces (polygons) of the object and draw them		for(int j = 0; j &lt; pObject-&gt;numOfFaces; j++)		{			// Go through each corner of the triangle and draw it.			for(int whichVertex = 0; whichVertex &lt; 3; whichVertex++)			{				// Get the index for each point of the face				int index = pObject-&gt;pFaces[j].vertIndex[whichVertex];				// Give OpenGL the normal for this vertex.				glNormal3f(pObject-&gt;pNormals[ index ].GetX(), pObject-&gt;pNormals[ index ].GetY(), pObject-&gt;pNormals[ index ].GetZ() );				// If the object has a texture associated with it, give it a texture coordinate.				if(pObject-&gt;bHasTexture)				{					// Make sure there was a UVW map applied to the object or else it won't have tex coords.					if(pObject-&gt;pTexVerts) 					{						glTexCoord2f(pObject-&gt;pTexVerts[ index ].GetX(), pObject-&gt;pTexVerts[ index ].GetY());					}				} else {					// Make sure there is a valid material/color assigned to this object.					// You should always at least assign a material color to an object, 					// but just in case we want to check the size of the material list.					// if the size is at least one, and the material ID != -1,					// then we have a valid material.					if(pModel-&gt;pMaterials.size() && pObject-&gt;materialID &gt;= 0) 					{						// Get and set the color that the object is, since it must not have a texture						u8 *pColor = pModel-&gt;pMaterials[pObject-&gt;materialID].color;						// Assign the current color to this model						glColor3ub(pColor[0], pColor[1], pColor[2]);					}				}				// Pass in the current vertex of the object (Corner of current face)				glVertex3f( pObject-&gt;pVerts[ index ].GetX(),							pObject-&gt;pVerts[ index ].GetY(), 							pObject-&gt;pVerts[ index ].GetZ() );			}		}		glEnd();								// End the drawing	}}//--------------------------------------------------------------------------------------------------/**@function		Load@brief			Loads the 3DS file and computes each objects bounds (collision) data**///--------------------------------------------------------------------------------------------------bool Model3DS::Load( char* strFileName, 				     char* filter, 					 char* wrap, 					 char* texEnv, 					 u8	alphaR, 					 u8	alphaG, 					 u8	alphaB ){	if( m_ModelLoaded )	{		MessageBox( NULL, "Model already loaded!", "Error", MB_OK );		return false;	}	// Load the model	m_ModelLoaded = Import3DS( &m_Model, strFileName );	if( m_pFilePointer )		fclose( m_pFilePointer );	if( !m_ModelLoaded ) 	{		MessageBox( NULL, "Model not loaded!", "Error", MB_OK );		return false;	}	// If the model was loaded, create the models textures	// and the find the objects collision data	CreateModelTextures( &m_Model, 						 &m_pTextureArray, 						 filter, 						 wrap, 						 texEnv, 						 alphaR, 						 alphaG, 						 alphaB );	// Compute the collision data	// ComputeObjectData();		return m_ModelLoaded;}//--------------------------------------------------------------------------------------------------/**@function		ComputeObjectData@brief			Computes all the collision data for all objects in the model.**///--------------------------------------------------------------------------------------------------bool Model3DS::ComputeObjectData(){	if( !m_ModelLoaded ) 	{		MessageBox( NULL, "Model not loaded!", "Error", MB_OK );		return false;	}	if( m_ModelLoaded )	{		for( int i = 0; i &lt; m_Model.numOfObjects; i++ )		{			ObjectData temp;			temp.largestVertices  = FindLargestVertexXYZ( &m_Model.pObject );			temp.largestVertex	  = FindLargestVertex( &m_Model.pObject );			f32 largestX		  = FindLargestPointNoAbs( &m_Model.pObject, kX );			f32 largestY		  = FindLargestPointNoAbs( &m_Model.pObject, kY );			f32 largestZ		  = FindLargestPointNoAbs( &m_Model.pObject, kZ );			temp.largestPositives = Vector3( largestX, largestY, largestZ );			f32 lowestX		      = FindLowestPoint( &m_Model.pObject, kX );			f32 lowestY		      = FindLowestPoint( &m_Model.pObject, kY );			f32 lowestZ		      = FindLowestPoint( &m_Model.pObject, kZ );			temp.largestNegatives = Vector3( lowestX, lowestY, lowestZ );			temp.width			  = FindDimensions( &m_Model.pObject, kX );			temp.height			  = FindDimensions( &m_Model.pObject, kY );			temp.depth			  = FindDimensions( &m_Model.pObject, kZ );			temp.centerX		  = FindCenter( &m_Model.pObject, kX );			temp.centerY		  = FindCenter( &m_Model.pObject, kY );			temp.centerZ		  = FindCenter( &m_Model.pObject, kZ );			m_ObjectData.push_back( temp );		}		m_ObjectDataComputed = true;	}	return m_ObjectDataComputed;}//--------------------------------------------------------------------------------------------------/**@function		WriteData@brief			Writes each objects collision data to the specified file name**///--------------------------------------------------------------------------------------------------bool Model3DS::WriteData( const char* fileName ) const{	if( !m_ModelLoaded ) 	{		MessageBox( NULL, "Model not loaded!", "Error", MB_OK );		return false;	}		if( !m_ObjectDataComputed ) 	{		MessageBox( NULL, "Model data not computed!", "Error", MB_OK );		return false;	}	ofstream data;	data.open( fileName );	if( !data )	{		MessageBox( NULL, "Can't open stream!", "Error", MB_OK );		return false;	}		if( data )	{		for( uint i = 0; i &lt; m_ObjectData.size(); i++ )		{			f32 largestVX = m_ObjectData.largestVertices.GetX();			f32 largestVY = m_ObjectData.largestVertices.GetY();			f32 largestVZ = m_ObjectData.largestVertices.GetZ();						data &lt;&lt; "ObjectName="              &lt;&lt; m_Model.pObject.strName    &lt;&lt; endl;			data &lt;&lt; "LargestVertex="           &lt;&lt; m_ObjectData.largestVertex &lt;&lt; endl;            			data &lt;&lt; "LargestVertices="         &lt;&lt; largestVX 											   &lt;&lt; "," 											   &lt;&lt; largestVY 											   &lt;&lt; "," 											   &lt;&lt; largestVZ &lt;&lt; endl;			data &lt;&lt; "Dimensions="			   &lt;&lt; m_ObjectData.width   &lt;&lt; ","											   &lt;&lt; m_ObjectData.height  &lt;&lt; ","											   &lt;&lt; m_ObjectData.depth   &lt;&lt; endl;			data &lt;&lt; "Center="				   &lt;&lt; m_ObjectData.centerX &lt;&lt; ","											   &lt;&lt; m_ObjectData.centerY &lt;&lt; ","											   &lt;&lt; m_ObjectData.centerZ &lt;&lt; endl;		}		data.close();	}	return true;}//--------------------------------------------------------------------------------------------------/**@function		Render@brief			Renders each object in the model**///--------------------------------------------------------------------------------------------------void Model3DS::Render(){	if( !m_ModelLoaded ) 	{		MessageBox( NULL, "Model not loaded!", "Error", MB_OK );		exit(0);	}	glEnable( GL_BLEND );														glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );	RenderModel( &m_Model, m_pTextureArray );	glDisable( GL_BLEND );}


Cheers guys, appreciate it!

- DB

[Edited by - DrunkenBrit on June 5, 2007 9:11:26 AM]
Show A Man A Program, Frustrate Him For A Day...Teach A Man To Program, Frustrate Him For The Rest Of His Life...
Sorry I tried to do code tags and all I saw on the RHS of page was quote tags...

- DB
Show A Man A Program, Frustrate Him For A Day...Teach A Man To Program, Frustrate Him For The Rest Of His Life...
Quote:Original post by DrunkenBrit
Sorry I tried to do code tags and all I saw on the RHS of page was quote tags...

- DB


[source]your code here[/source]

/\ What you're looking for with that length of code listing.
[TheUnbeliever]
Thanks, all done now, any chance with some help with the memory leak please? ;)
Show A Man A Program, Frustrate Him For A Day...Teach A Man To Program, Frustrate Him For The Rest Of His Life...

This topic is closed to new replies.

Advertisement