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;
}