📄 splash.cc
字号:
const U32 /*startZone*/, const bool /*modifyBaseState*/)
{
if (isLastState(state, stateKey))
return false;
setLastState(state, stateKey);
// This should be sufficient for most objects that don't manage zones, and
// don't need to return a specialized RenderImage...
if (state->isObjectRendered(this))
{
mFog = 0.0;
SceneRenderImage* image = new SceneRenderImage;
image->obj = this;
image->isTranslucent = true;
image->sortType = SceneRenderImage::Point;
image->textureSortKey = (U32)(dsize_t)mDataBlock;
state->setImageRefPoint(this, image);
state->insertRenderImage(image);
}
return false;
}
//--------------------------------------------------------------------------
// Render
//--------------------------------------------------------------------------
void Splash::renderObject(SceneState* state, SceneRenderImage*)
{
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
RectI viewport;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
dglGetViewport(&viewport);
state->setupObjectProjection(this);
render();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
dglSetViewport(viewport);
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}
//--------------------------------------------------------------------------
// Process tick
//--------------------------------------------------------------------------
void Splash::processTick(const Move*)
{
mCurrMS += TickMs;
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
if( isServerObject() )
{
if( mCurrMS >= mEndingMS )
{
mDead = true;
if( mCurrMS >= (mEndingMS + mDataBlock->ringLifetime * 1000) )
{
deleteObject();
}
}
}
else
#endif
{
if( mCurrMS >= mEndingMS )
{
mDead = true;
}
}
}
//--------------------------------------------------------------------------
// Advance time
//--------------------------------------------------------------------------
void Splash::advanceTime(F32 dt)
{
if (dt == 0.0)
return;
mElapsedTime += dt;
updateColor();
updateWave( dt );
updateEmitters( dt );
updateRings( dt );
if( !mDead )
{
emitRings( dt );
}
}
//----------------------------------------------------------------------------
// Update emitters
//----------------------------------------------------------------------------
void Splash::updateEmitters( F32 dt )
{
Point3F pos = getPosition();
for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ )
{
if( mEmitterList[i] )
{
mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0, 0.0, 0.0 ), (S32) (dt * 1000) );
}
}
}
//----------------------------------------------------------------------------
// Update wave
//----------------------------------------------------------------------------
void Splash::updateWave( F32 dt )
{
mVelocity += mDataBlock->acceleration * dt;
mRadius += mVelocity * dt;
}
//----------------------------------------------------------------------------
// Render splash
//----------------------------------------------------------------------------
void Splash::render()
{
glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
SplashRing *ring = NULL;
U32 i=0;
while( bool( ring = ringList.next( ring ) ) )
{
SplashRing *next = ringList.next( ring );
if( !next )
break;
renderSegment( *ring, *next );
i++;
}
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
//----------------------------------------------------------------------------
// Render horizontal segment created from 2 sets of points that are the
// top and bottom rings of the segment.
//----------------------------------------------------------------------------
void Splash::renderSegment( SplashRing &top, SplashRing &bottom )
{
F32 texFactor = mDataBlock->texWrap;
glBindTexture( GL_TEXTURE_2D, mDataBlock->textureHandle[0].getGLName() );
F32 topAlpha = top.elapsedTime / top.lifetime;
F32 bottomAlpha = bottom.elapsedTime / bottom.lifetime;
if( topAlpha < 0.5 )
topAlpha *= 2.0;
else
topAlpha = 1.0 - topAlpha;
if( bottomAlpha < 0.5 )
bottomAlpha *= 2.0;
else
bottomAlpha = 1.0 - bottomAlpha;
top.color.alpha = topAlpha;
bottom.color.alpha = bottomAlpha;
glBegin( GL_QUAD_STRIP );
{
for( U32 i=0; i<top.points.size(); i++ )
{
F32 t = F32(i) / F32(top.points.size());
glTexCoord2f( t * texFactor, top.v );
glColor4fv( top.color );
glVertex3fv( top.points[i].position );
glTexCoord2f( t * texFactor, bottom.v );
glColor4fv( bottom.color );
glVertex3fv( bottom.points[i].position );
}
glTexCoord2f( 1.0 * texFactor, top.v );
glColor4fv( top.color );
glVertex3fv( top.points[0].position );
glTexCoord2f( 1.0 * texFactor, bottom.v );
glColor4fv( bottom.color );
glVertex3fv( bottom.points[0].position );
}
glEnd();
}
//----------------------------------------------------------------------------
// Update color
//----------------------------------------------------------------------------
void Splash::updateColor()
{
SplashRing *ring = NULL;
while( bool( ring = ringList.next( ring ) ) )
{
F32 t = F32(ring->elapsedTime) / F32(ring->lifetime);
for( U32 i = 1; i < SplashData::NUM_TIME_KEYS; i++ )
{
if( mDataBlock->times[i] >= t )
{
F32 firstPart = t - mDataBlock->times[i-1];
F32 total = (mDataBlock->times[i] -
mDataBlock->times[i-1]);
firstPart /= total;
ring->color.interpolate( mDataBlock->colors[i-1],
mDataBlock->colors[i],
firstPart);
break;
}
}
}
}
//----------------------------------------------------------------------------
// Create ring
//----------------------------------------------------------------------------
SplashRing Splash::createRing()
{
SplashRing ring;
U32 numPoints = mDataBlock->numSegments + 1;
Point3F ejectionAxis( 0.0, 0.0, 1.0 );
Point3F axisx;
if (mFabs(ejectionAxis.z) < 0.999f)
mCross(ejectionAxis, Point3F(0, 0, 1), &axisx);
else
mCross(ejectionAxis, Point3F(0, 1, 0), &axisx);
axisx.normalize();
for( U32 i=0; i<numPoints; i++ )
{
F32 t = F32(i) / F32(numPoints);
AngAxisF thetaRot( axisx, mDataBlock->ejectionAngle * (M_PI / 180.0));
AngAxisF phiRot( ejectionAxis, t * (M_PI * 2.0));
Point3F pointAxis = ejectionAxis;
MatrixF temp;
thetaRot.setMatrix(&temp);
temp.mulP(pointAxis);
phiRot.setMatrix(&temp);
temp.mulP(pointAxis);
Point3F startOffset = axisx;
temp.mulV( startOffset );
startOffset *= mDataBlock->startRadius;
SplashRingPoint point;
point.position = getPosition() + startOffset;
point.velocity = pointAxis * mDataBlock->velocity;
ring.points.push_back( point );
}
ring.color = mDataBlock->colors[0];
ring.lifetime = mDataBlock->ringLifetime;
ring.elapsedTime = 0.0;
ring.v = mDataBlock->texFactor * mFmod( mElapsedTime, 1.0 );
return ring;
}
//----------------------------------------------------------------------------
// Emit rings
//----------------------------------------------------------------------------
void Splash::emitRings( F32 dt )
{
mTimeSinceLastRing += dt;
S32 numNewRings = (S32) (mTimeSinceLastRing * F32(mDataBlock->ejectionFreq));
mTimeSinceLastRing -= numNewRings / mDataBlock->ejectionFreq;
for( S32 i=numNewRings-1; i>=0; i-- )
{
F32 t = F32(i) / F32(numNewRings);
t *= dt;
t += mTimeSinceLastRing;
SplashRing ring = createRing();
updateRing( &ring, t );
ringList.link( ring );
}
}
//----------------------------------------------------------------------------
// Update rings
//----------------------------------------------------------------------------
void Splash::updateRings( F32 dt )
{
SplashRing *ring = NULL;
while( bool( ring = ringList.next( ring ) ) )
{
ring->elapsedTime += dt;
if( !ring->isActive() )
{
SplashRing *inactiveRing = ring;
ring = ringList.prev( ring );
ringList.free( inactiveRing );
}
else
{
updateRing( ring, dt );
}
}
}
//----------------------------------------------------------------------------
// Update ring
//----------------------------------------------------------------------------
void Splash::updateRing( SplashRing *ring, F32 dt )
{
for( U32 i=0; i<ring->points.size(); i++ )
{
if( mDead )
{
Point3F vel = ring->points[i].velocity;
vel.normalize();
vel *= mDataBlock->acceleration;
ring->points[i].velocity += vel * dt;
}
ring->points[i].velocity += Point3F( 0.0, 0.0, -9.8 ) * dt;
ring->points[i].position += ring->points[i].velocity * dt;
}
}
//----------------------------------------------------------------------------
// Explode
//----------------------------------------------------------------------------
void Splash::spawnExplosion()
{
if( !mDataBlock->explosion ) return;
Explosion* pExplosion = new Explosion;
pExplosion->onNewDataBlock(mDataBlock->explosion);
MatrixF trans = getTransform();
trans.setPosition( getPosition() );
pExplosion->setTransform( trans );
pExplosion->setInitialState( trans.getPosition(), VectorF(0,0,1), 1);
if (!pExplosion->registerObject())
delete pExplosion;
}
//--------------------------------------------------------------------------
// packUpdate
//--------------------------------------------------------------------------
U32 Splash::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
{
U32 retMask = Parent::packUpdate(con, mask, stream);
if( stream->writeFlag(mask & GameBase::InitialUpdateMask) )
{
mathWrite(*stream, mInitialPosition);
}
return retMask;
}
//--------------------------------------------------------------------------
// unpackUpdate
//--------------------------------------------------------------------------
void Splash::unpackUpdate(NetConnection* con, BitStream* stream)
{
Parent::unpackUpdate(con, stream);
if( stream->readFlag() )
{
mathRead(*stream, &mInitialPosition);
setPosition( mInitialPosition );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -