www.pudn.com > RCApp-src.zip > Explosion.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 Explosion.cpp 
 *	\brief Game explosion. 
 * 
 *		This file contains the game explosion. 
 */ 
 
// RedEye includes 
#include "Explosion.h" 
 
float reExplosion::msTextureUnitCoord[4][2] = 
{	{0,  0}, 
	{1,  0}, 
	{0, 1}, 
	{1,  1} 
}; 
 
 
 
 
static void 
reSetExplosionScale(float size, ssgVertexArray *vertices) 
{ 
	int i, j; 
	static float unit_cutout[4][3] = 
	{	{-1, 0, -1}, 
		{1, 0, -1}, 
		{-1, 0, 1}, 
		{1, 0, 1} 
	}; 
 
	if (!vertices) return; 
 
	for(i = 0; i < 4; i++) 
	{ 
		float *v = vertices->get(i); 
 
		for (j = 0; j < 3; j++) 
			v[j] = unit_cutout[i][j]*size; 
	} 
} 
 
 
 
 
static int 
reExplosionPreDraw(ssgEntity *) 
{ 
  glDepthMask(false); 
  return 1; 
} 
 
 
 
 
static int 
reExplosionPostDraw(ssgEntity *) 
{ 
   glDepthMask(true); 
   return 1; 
} 
 
 
 
 
reExplosion::reExplosion(ssgBranch* pEntity) 
:	ssgTransform() 
{ 
	CreateStructure(); 
 
	mpEntity = pEntity; 
	mpEntity->ref(); 
} 
 
 
 
 
reExplosion::~reExplosion() 
{ 
	ssgDeRefDelete(mpColourArray); 
	ssgDeRefDelete(mpVertices); 
 
	ssgDeRefDelete(mpEntity); 
} 
 
 
 
 
void 
reExplosion::CreateStructure() 
{ 
 
	int i; 
 
	mpLeafGeometrySets = 0; 
	mpTextureCoordSets = 0; 
	mpState = 0; 
	mCount = 0; 
	mSqrtCount = 0; 
	mListSize = 0; 
    mSize = 0; 
 
	mpCutout = new ssgCutout(TRUE); 
 
	sgVec3 vertex; 
	sgVec4 colour; 
 
	// Set up vertex colour array - shared by all leafs 
 
	mpColourArray = new ssgColourArray(4); 
	mpColourArray->ref(); 
    sgSetVec4(colour, 1.0f, 1.0f, 1.0f, 1.0f); 
	for (i = 0; i < 4; i++) 
		mpColourArray->add(colour); 
 
	// Set up vertices - shared by all leafs 
 
	mpVertices = new ssgVertexArray(4); 
	mpVertices->ref(); 
	for (i = 0; i < 4; i++)	mpVertices->add(vertex); 
	reSetExplosionScale(1, mpVertices);  
 
	mpTimedSelector = new ssgTimedSelector(256); 
	mpTimedSelector->setMode(SSG_ANIM_ONESHOT); 
	//mpTimedSelector->setLimits(0,0); <---Implied 
 
	mpCutout->addKid(mpTimedSelector); 
	this->addKid(mpCutout); 
 
} 
 
 
 
 
void 
reExplosion::Initialise(ssgSimpleState* expl_state, int sqrt_count, float scale, float duration) 
{ 
	int i, j; 
 
    // If explosion size is unchanged dont need to do much other than replace the  
    // state, update the duration and scale 
    if (sqrt_count == mSqrtCount) 
    { 
        for (i = 0; i < mCount; i++) 
	    { 
			mpLeafGeometrySets[i]->setState(expl_state); 
        } 
        mpState = expl_state; 
 
        SetFrameDuration(duration); 
 
        if (scale != mSize) 
			SetScale(scale); 
 
        return; 
    }  
 
	mpTimedSelector->removeAllKids(); 
 
	mCount = sqrt_count*sqrt_count; 
	mSqrtCount = sqrt_count; 
	mpState = expl_state; 
 
	if (mCount > mListSize) 
	{ 
		if (mpLeafGeometrySets) delete[] mpLeafGeometrySets; 
		if (mpTextureCoordSets) delete[] mpTextureCoordSets; 
		mListSize = mCount; 
		 
		// Set up mCount texture and geometry arrays unique for each leaf 
 
		mpTextureCoordSets = new ssgTexCoordArray * [mCount]; 
		mpLeafGeometrySets = new ssgLeaf *[mCount];	 
	}	 
	 
	float text_tile_len = float(1.0/mSqrtCount); 
 
	for(i = 0; i < mCount; i++) 
	{ 
		sgVec2 text_coords; 
		float horiz = float((i % mSqrtCount) * text_tile_len); 
		float vert  = float((i / mSqrtCount) * text_tile_len); 
		mpTextureCoordSets[i] = new ssgTexCoordArray; 
		for (j = 0; j < 4;j++) 
		{ 
			sgSetVec2(text_coords, 
				horiz + msTextureUnitCoord[j][0] * text_tile_len, 
				vert + msTextureUnitCoord[j][1] * text_tile_len); 
			mpTextureCoordSets[i]->add(text_coords); 
		} 
	} 
 
	for (i = 0; i < mCount; i++) 
	{ 
		mpLeafGeometrySets[i] = new  ssgVtxTable (GL_TRIANGLE_STRIP, mpVertices, 0, mpTextureCoordSets[i], mpColourArray); 
		mpLeafGeometrySets[i]->setCallback(SSG_CALLBACK_PREDRAW, reExplosionPreDraw); 
		mpLeafGeometrySets[i]->setCallback(SSG_CALLBACK_POSTDRAW, reExplosionPostDraw); 
		mpLeafGeometrySets[i]->setState(mpState); 
		mpTimedSelector->addKid(mpLeafGeometrySets[i]); 
	} 
 
	mpTimedSelector->setLimits(0,mCount-1); 
	SetFrameDuration(duration); 
	SetScale(scale); 
 
} 
 
 
 
 
void 
reExplosion::SetScale(float scale) 
{ 
	int i; 
    mSize = scale; 
 
	reSetExplosionScale(scale, mpVertices); 
 
	for (i = 0; i < mCount; i++) 
		mpLeafGeometrySets[i]->dirtyBSphere(); 
} 
 
 
 
 
void 
reExplosion::SetFrameDuration(float ti) 
{ 
	mpTimedSelector->setDuration(ti); 
} 
 
 
 
 
void 
reExplosion::SetPosition(float x, float y, float z, float scale)  
{ 
	sgVec3 pos; 
	pos[0] = x; pos[1] = y; pos[2] = z; 
 
	setTransform(pos); 
 
	if (scale > 0) 
		SetScale(scale); 
} 
 
 
 
 
ssgSimpleState* 
reExplosion::MakeState(const char *explFname) 
{ 
	ssgSimpleState* pState = new ssgSimpleState(); 
 
    pState->setTexture("textures/explode1.rgba", TRUE, TRUE, FALSE); 
    pState->setShadeModel(GL_SMOOTH); 
    pState->disable(GL_LIGHTING); 
    pState->disable(GL_CULL_FACE); 
    pState->enable(GL_TEXTURE_2D); 
    pState->enable(GL_COLOR_MATERIAL); 
    pState->setColourMaterial(GL_AMBIENT_AND_DIFFUSE); 
    pState->setMaterial(GL_EMISSION, 0, 0, 0, 1); 
    pState->setMaterial(GL_SPECULAR, 0, 0, 0, 1); 
    pState->enable(GL_BLEND); 
    pState->enable(GL_ALPHA_TEST); 
    pState->setAlphaClamp(0.01f); 
	pState->setTranslucent(); 
 
    return pState; 
}