www.pudn.com > RCApp-src.zip > MaterialManager.cpp


/* 
	RedEye Project (http://members.ozemail.com.au/~ndmcevoy/) 
	Copyright (C) 2003  Nick McEvoy 
 
	This library is free software; you can redistribute it and/or 
	modify it under the terms of the GNU Library General Public 
	License as published by the Free Software Foundation; either 
	version 2 of the License, or (at your option) any later version. 
 
	This library is distributed in the hope that it will be useful, 
	but WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
	Library General Public License for more details. 
 
	You should have received a copy of the GNU Library General Public 
	License along with this library; if not, write to the Free 
	Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 
	----------------------------------------------------------------- 
 
		Commented for use with Doxygen (http://www.doxygen.org) 
 
	----------------------------------------------------------------- 
*/ 
 
/*! \file MaterialManager.cpp 
 *	\brief Material manager. 
 * 
 *		This file contains the material manager. 
 */ 
 
// GLUT includes 
#include  
 
// RedEye includes 
#include "MaterialManager.h" 
#include "SoundManager.h" 
#include "Engine.h" 
 
//! The one and only instance 
reMaterialManager* reMaterialManager::mpInstance = NULL; 
 
#define DEFAULT_TEXTURE "textures/CandyStripe.rgb" 
 
#define NOCLAMP 0 
#define UCLAMP  1 
#define VCLAMP  2 
#define UVCLAMP 3 
 
// todo: to be replaced by reading material data from file 
struct Material 
{ 
public: 
	char* msFilename; 
 
	int   miClamp; 
	bool  mbTransparency; 
	float mfAlphaRef; 
	bool  mbLighting; 
 
	sgVec4 mfEmission; 
	sgVec4 mfSpecular; 
	float mfShininess; 
 
	// ODE surface parameters 
	dSurfaceParameters mSurface; 
}; 
 
// todo: to be replaced by reading material data from file 
Material materials[] = 
{ 
	{ 
		DEFAULT_TEXTURE,	// DEFAULT ... DO NOT REMOVE !!! 
		NOCLAMP, false, 0.0, true, 
		0, 0, 0, 1, 
		0, 0, 0, 1, 
		0, 
		dContactBounce | dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM, 
		dInfinity, 0,	// mu, mu2 
		0.0, 0.0,		// bounce, bounce_vel 
		0.8, 0.2,		// soft_erp, soft_cfm 
		0.0, 0.0,		// motion1, motion2 
		0.5, 0.5		// slip1, slip2 
	}, 
	{ 
		"textures/Grass.bmp", 
		NOCLAMP, false, 0.0, true, 
		0, 0, 0, 1, 
		0, 0, 0, 1, 
		0, 
		dContactBounce | dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM, 
		dInfinity, 0,	// mu, mu2 
		0.0, 0.1,		// bounce, bounce_vel 
		0.8, 0.2,		// soft_erp, soft_cfm 
		0.0, 0.0,		// motion1, motion2 
		0.5, 0.5		// slip1, slip2 
	}, 
	{ 
		"textures/Ocean.rgb", 
		NOCLAMP, true, 0.0, true, 
		0, 0, 0, 1, 
		1, 1, 1, 1, 
		5, 
		dContactBounce | dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM, 
		0.1, 0,			// mu, mu2 
		0.0, 0.0,		// bounce, bounce_vel 
		0.4, 0.2,		// soft_erp, soft_cfm 
		0.0, 0.0,		// motion1, motion2 
		0.5, 0.5		// slip1, slip2 
	}, 
	{ 
		"textures/Rock.bmp", 
		NOCLAMP, false, 0.0, true, 
		0, 0, 0, 1, 
		0, 0, 0, 1, 
		0, 
		dContactBounce | dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM, 
		dInfinity, 0,	// mu, mu2 
		0.0, 0.1,		// bounce, bounce_vel 
		0.8, 0.2,		// soft_erp, soft_cfm 
		0.0, 0.0,		// motion1, motion2 
		0.8, 0.8		// slip1, slip2 
	}, 
	{ 
		"textures/Sand.rgb", 
		NOCLAMP, false, 0.0, true, 
		0, 0, 0, 1, 
		0, 0, 0, 1, 
		0, 
		dContactBounce | dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM, 
		dInfinity, 0,	// mu, mu2 
		0.0, 0.1,		// bounce, bounce_vel 
		0.8, 0.2,		// soft_erp, soft_cfm 
		0.0, 0.0,		// motion1, motion2 
		0.8, 0.8		// slip1, slip2 
	}, 
	{ 
		"textures/TestTextureGrass.bmp", 
		NOCLAMP, false, 0.0, true, 
		0, 0, 0, 1, 
		0, 0, 0, 1, 
		0, 
		dContactBounce | dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM, 
		0.1, 0,			// mu, mu2 
		0.0, 0.0,		// bounce, bounce_vel 
		0.5, 0.2,		// soft_erp, soft_cfm 
		0.0, 0.0,		// motion1, motion2 
		0.5, 0.5		// slip1, slip2 
	}, 
	{ 
		"textures/fuzzy.inta", 
		UVCLAMP, true, 0.2, false, 
		0, 0, 0, 1, 
		1, 1, 1, 1, 
		0, 
		0,			// ode flags 
		0, 0,		// mu, mu2 
		0, 0,		// bounce, bounce_vel 
		0, 0,		// soft_erp, soft_cfm 
		0, 0,		// motion1, motion2 
		0, 0		// slip1, slip2 
	}, 
}; 
static int miNumMaterials = sizeof(materials)/sizeof(Material); 
 
 
 
 
bool 
reCompareBaseFilename(const char* fname, const char* fname2) 
{ 
	int i; 
	int iLen = strlen(fname); 
	int iLen2 = strlen(fname2); 
	const char* fnbase = NULL; 
	const char* fnbase2 = NULL; 
 
	for (i = iLen; i >= 0; i--) 
	{ 
		if (fname[i] == '/') 
		{ 
			fnbase = &fname[i+1]; 
			break; 
		} 
		fnbase = &fname[i]; 
	} 
 
	for (i = iLen2; i >= 0; i--) 
	{ 
		if (fname2[i] == '/') 
		{ 
			fnbase2 = &fname2[i+1]; 
			break; 
		} 
		fnbase2 = &fname2[i]; 
	} 
 
	if (strcmp(fnbase, fnbase2) == 0) 
		return true; 
	else 
		return false; 
} 
 
 
 
 
ssgState* 
reGetAppState(char* fname) 
{ 
	return reGetMaterialManager()->GetAppState(fname); 
} 
 
 
 
 
reMaterial::reMaterial(int iIndex) 
{ 
	miIndex = iIndex; 
 
	setExternalPropertyIndex(iIndex); 
 
	if (materials[iIndex].msFilename[0] != '\0') 
	{ 
		setTexture( 
			materials[iIndex].msFilename, 
			!(materials[iIndex].miClamp & UCLAMP), 
			!(materials[iIndex].miClamp & VCLAMP)); 
		enable(GL_TEXTURE_2D); 
	} 
	else 
		disable(GL_TEXTURE_2D); 
 
	if (materials[iIndex].mbLighting) 
		enable(GL_LIGHTING); 
	else 
		disable(GL_LIGHTING); 
 
	setShadeModel(GL_SMOOTH); 
	enable(GL_COLOR_MATERIAL); 
	enable(GL_CULL_FACE); 
	setColourMaterial(GL_AMBIENT_AND_DIFFUSE); 
	setMaterial(GL_EMISSION, 0, 0, 0, 1); 
	setMaterial(GL_SPECULAR, 0, 0, 0, 1); 
	setShininess(0); 
 
	if (materials[iIndex].mbTransparency) 
	{ 
		setTranslucent(); 
		enable(GL_ALPHA_TEST); 
		setAlphaClamp(materials[iIndex].mfAlphaRef); 
		enable(GL_BLEND); 
	} 
	else 
	{ 
		setOpaque(); 
		disable(GL_BLEND); 
	} 
} 
 
 
 
 
const char* 
reMaterial::GetFilename() 
{ 
	return materials[miIndex].msFilename; 
} 
 
 
 
 
void 
reMaterial::GetSurfaceParams(dSurfaceParameters& Surface) 
{ 
	Surface = materials[miIndex].mSurface; 
} 
 
 
 
 
reMaterialManager::reMaterialManager() 
: mMaterialList(false) 
{ 
} 
 
 
 
 
reMaterialManager::~reMaterialManager() 
{ 
	DestroyDatabase(); 
	mpInstance = NULL; 
} 
 
 
 
 
reMaterialManager* 
reMaterialManager::GetInstance() 
{ 
	if (mpInstance == NULL) 
	{ 
		mpInstance = new reMaterialManager; 
	} 
	return mpInstance; 
} 
 
 
 
 
void 
reMaterialManager::CreateDatabase() 
{ 
	printf("reMaterialManager::CreateDatabase() - creating materials...\n"); 
 
	// Set the state callback 
	ssgSetAppStateCallback(reGetAppState); 
 
	// todo: move materials to an xml file 
	for (int i = 0; i < miNumMaterials; i++) 
	{ 
		// Keep sound going 
		reGetSoundManager()->Update(); 
 
		// Create material 
		reMaterial* pMaterial = new reMaterial(i); 
		pMaterial->ref(); 
		mMaterialList.AddTail(pMaterial); 
	} 
 
	// todo: read xml 
 
	printf("reMaterialManager::CreateDatabase() - done\n"); 
} 
 
 
 
 
void 
reMaterialManager::DestroyDatabase() 
{ 
	printf("reMaterialManager::DestroyDatabase() - destroying materials...\n"); 
 
	// Destroy materials 
	LISTPOSITION pos = mMaterialList.GetHeadPosition(); 
	while (pos) 
	{ 
		reMaterial* pMaterial = mMaterialList.GetNext(pos); 
		ssgDeRefDelete(pMaterial); 
	} 
	mMaterialList.RemoveAll(); 
 
	printf("reMaterialManager::DestroyDatabase() - done\n"); 
} 
 
 
 
 
ssgSimpleState* 
reMaterialManager::GetSimpleState(char* fname) 
{ 
	ssgSimpleState* pState = (ssgSimpleState*)GetAppState(fname); 
	if (!pState) 
	{ 
		ulSetError(UL_WARNING,  
		     "reMaterialManager::GetSimpleState() Could not find texture %s.", fname); 
		pState = (ssgSimpleState*)GetAppState(DEFAULT_TEXTURE); 
	} 
	return pState; 
} 
 
 
 
 
ssgState* 
reMaterialManager::GetAppState(char* fname) 
{ 
	LISTPOSITION pos = mMaterialList.GetHeadPosition(); 
	while (pos) 
	{ 
		reMaterial* pMaterial = mMaterialList.GetNext(pos); 
		if (reCompareBaseFilename(pMaterial->GetFilename(), fname)) 
			return pMaterial; // Found 
	} 
 
	return NULL; // Not found 
} 
 
 
 
 
bool 
reMaterialManager::GetSurfaceParams(int iIndex, dSurfaceParameters& Surface) 
{ 
	LISTPOSITION pos = mMaterialList.GetHeadPosition(); 
	while (pos) 
	{ 
		reMaterial* pMaterial = mMaterialList.GetNext(pos); 
		if (pMaterial->GetIndex() == iIndex) 
		{ 
			pMaterial->GetSurfaceParams(Surface); 
			return true; // Found 
		} 
	} 
 
	return false; // Not found 
}