📄 weatherlightning.cpp
字号:
// setup alpha value
F32 strikeAlpha;
if(currentAge < (strikeTime / 3.0))
{
strikeAlpha = currentAge / (strikeTime / 3.0);
strikeAlpha = mPow(strikeAlpha, F32(1.0 / 3.0));
}
else if(currentAge < (2.0 * strikeTime / 3.0))
strikeAlpha = 1.0;
else
strikeAlpha = 1.0 - ((currentAge - (2.0 * strikeTime / 3.0)) / (strikeTime / 3.0));
glColor4f(1.0f, 1.0f, 1.0f, strikeAlpha);
// generate texture coords
Point3F points[4];
F32 width = ((startPoint.z - endPoint.z) * 0.125f);
points[0] = startPoint - perpVec * width;
points[1] = startPoint + perpVec * width;
points[2] = endPoint + perpVec * width;
points[3] = endPoint - perpVec * width;
// bind and draw texture
glBindTexture(GL_TEXTURE_2D, strikeTexture->getGLName());
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0); glVertex3fv(points[0]);
glTexCoord2f(0, 1); glVertex3fv(points[1]);
glTexCoord2f(1, 1); glVertex3fv(points[2]);
glTexCoord2f(1, 0); glVertex3fv(points[3]);
//glTexCoord2f(0, 0); glVertex3fv(points[0]);
//glTexCoord2f(1, 0); glVertex3fv(points[1]);
//glTexCoord2f(1, 1); glVertex3fv(points[2]);
//glTexCoord2f(0, 1); glVertex3fv(points[3]);
glEnd();
//
// fuzzy texture
//
// setup alpha value
F32 constAlpha;
if(currentAge < strikeTime / 2.0)
constAlpha = currentAge / (strikeTime / 2.0);
else if(currentAge < (2.0 * strikeTime / 3.0))
constAlpha = 1.0 - ((currentAge - (strikeTime / 2.0)) / (strikeTime / 6.0));
else
constAlpha = 0.0;
glColor4f(1.0, 1.0, 1.0, constAlpha);
// generate texture coords
width *= 4;
points[0] = startPoint - perpVec * width;
points[1] = startPoint + perpVec * width;
points[2] = endPoint + perpVec * width;
points[3] = endPoint - perpVec * width;
if(constAlpha != 0.0)
{
// bind and draw texture
glBindTexture(GL_TEXTURE_2D, fuzzyTexture->getGLName());
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0); glVertex3fv(points[0]);
glTexCoord2f(0, 1); glVertex3fv(points[1]);
glTexCoord2f(1, 1); glVertex3fv(points[2]);
glTexCoord2f(1, 0); glVertex3fv(points[3]);
//glTexCoord2f(0, 0); glVertex3fv(points[0]);
//glTexCoord2f(1, 0); glVertex3fv(points[1]);
//glTexCoord2f(1, 1); glVertex3fv(points[2]);
//glTexCoord2f(0, 1); glVertex3fv(points[3]);
glEnd();
glDepthMask(GL_TRUE);
}
//
// flash texture
//
// setup alpha value
glColor4f(1.0f, 1.0f, 1.0f, strikeAlpha);
// generate texture coords
points[0] = startPoint - perpVec * width + frontVec * width;
points[1] = startPoint - perpVec * width - frontVec * width;
points[2] = startPoint + perpVec * width - frontVec * width;
points[3] = startPoint + perpVec * width + frontVec * width;
// bind and draw texture
glBindTexture(GL_TEXTURE_2D, flashTexture->getGLName());
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0); glVertex3fv(points[0]);
glTexCoord2f(0, 1); glVertex3fv(points[1]);
glTexCoord2f(1, 1); glVertex3fv(points[2]);
glTexCoord2f(1, 0); glVertex3fv(points[3]);
//glTexCoord2f(0, 0); glVertex3fv(points[0]);
//glTexCoord2f(1, 0); glVertex3fv(points[1]);
//glTexCoord2f(1, 1); glVertex3fv(points[2]);
//glTexCoord2f(0, 1); glVertex3fv(points[3]);
glEnd();
//
// finished
//
glDepthMask(GL_TRUE);
}
void WeatherLightning::renderObject(SceneState* state, SceneRenderImage*)
{
if(mActiveBolts.size())
{
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
RectI viewport;
F64 farPlane;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
dglGetViewport(&viewport);
farPlane = state->getFarPlane();
const Point3F &camPos = state->getCameraPosition();
// adjust far clip plane
F64 distance = (getPosition() - camPos).lenSquared();
state->setFarPlane(getMax(farPlane, distance));
state->setupObjectProjection(this);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
for(U32 i = 0; i < mActiveBolts.size(); i++)
mActiveBolts[i]->render(camPos);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
state->setFarPlane(farPlane);
dglSetViewport(viewport);
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}
}
void WeatherLightning::processTick(const Move *move)
{
Parent::processTick(move);
if (isServerObject())
{
S32 msBetweenStrikes = (S32)(60.0 / strikesPerMinute * 1000.0);
lastThink += TickMs;
if( lastThink > msBetweenStrikes )
{
strikeRandomPoint();
lastThink -= msBetweenStrikes;
}
}
}
void WeatherLightning::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
U32 i;
// loop through and erase any dead bolts
for(i = 0; i < mActiveBolts.size();)
{
WeatherLightningBolt* bolt = mActiveBolts[i];
bolt->currentAge += dt;
if(bolt->currentAge > bolt->deathAge)
{
delete bolt;
mActiveBolts.erase_fast(i);
continue;
}
i++;
}
// loop through and find any pending sound events
for(i = 0; i < mSoundEvents.size();)
{
SoundEvent *sEvent = &mSoundEvents[i];
sEvent->time -= dt;
if(sEvent->time <= 0.0)
{
// fire off the sound
if(sEvent->soundBlockId != -1)
alxPlay(mDataBlock->thunderSounds[sEvent->soundBlockId], &sEvent->position);
mSoundEvents.erase_fast(i);
continue;
}
i++;
}
}
void WeatherLightning::strikeRandomPoint()
{
// choose random strike point within object bounds
Point2F strikePoint;
strikePoint.x = sgRandomGen.randF( 0.0, 1.0 );
strikePoint.y = sgRandomGen.randF( 0.0, 1.0 );
SimGroup* pClientGroup = Sim::getClientGroup();
for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++)
{
NetConnection* nc = static_cast<NetConnection*>(*itr);
WeatherLightningStrikeEvent* wlEvent = new WeatherLightningStrikeEvent;
wlEvent->mLightning = this;
wlEvent->mStart = strikePoint;
nc->postNetEvent(wlEvent);
}
}
TextureHandle* WeatherLightning::getRandomStrike()
{
U32 strike = (U32)(mCeil(mDataBlock->numStrikes * sgRandomGen.randF()) - 1.0f);
return &mDataBlock->strikeTextures[strike];
}
TextureHandle* WeatherLightning::getRandomFlash()
{
U32 flash = (U32)(mCeil(mDataBlock->numFlashes * sgRandomGen.randF()) - 1.0f);
return &mDataBlock->flashTextures[flash];
}
TextureHandle* WeatherLightning::getRandomFuzzy()
{
U32 fuzzy = (U32)(mCeil(mDataBlock->numFuzzes * sgRandomGen.randF()) - 1.0f);
return &mDataBlock->fuzzyTextures[fuzzy];
}
S32 WeatherLightning::getRandomSound()
{
U32 sound = (U32)(mCeil(mDataBlock->numSounds * sgRandomGen.randF()) - 1.0f);
if(mDataBlock->thunderSounds[sound] != NULL_AUDIOHANDLE)
return sound;
return -1;
}
void WeatherLightning::processEvent(WeatherLightningStrikeEvent* wlEvent)
{
AssertFatal(wlEvent->mStart.x >= 0 && wlEvent->mStart.x <= 1.0, "Out of bounds coord!");
mActiveBolts.push_back(new WeatherLightningBolt);
WeatherLightningBolt* bolt = mActiveBolts.last();
Point3F strikePoint(0.0, 0.0, 0.0);
strikePoint.x = wlEvent->mStart.x;
strikePoint.y = wlEvent->mStart.y;
strikePoint *= mObjScale;
strikePoint += getPosition();
strikePoint += Point3F( -mObjScale.x * 0.5, -mObjScale.y * 0.5, 0.0 );
RayInfo rayInfo;
Point3F start = strikePoint;
start.z = mObjScale.z * 0.5 + getPosition().z;
strikePoint.z += -mObjScale.z * 0.5;
bool rayHit = gClientContainer.castRay(start, strikePoint, (STATIC_COLLISION_MASK | WaterObjectType), &rayInfo);
if(rayHit)
strikePoint.z = rayInfo.point.z;
F32 height = mObjScale.z * 0.5 + getPosition().z;
bolt->startPoint = Point3F(strikePoint.x, strikePoint.y, height);
bolt->endPoint = strikePoint;
bolt->currentAge = 0.0f;
bolt->deathAge = boltDeathAge;
bolt->strikeTime = 0.35;
bolt->strikeTexture = getRandomStrike();
bolt->flashTexture = getRandomFlash();
bolt->fuzzyTexture = getRandomFuzzy();
// setup a thunder sound event
Point3F listener;
alxGetListenerPoint3F(AL_POSITION, &listener);
mSoundEvents.increment();
SoundEvent& sEvent = mSoundEvents.last();
// find the length to the closest point on the bolt
Point3F dHat = bolt->startPoint - bolt->endPoint;
F32 boltLength = dHat.len();
dHat /= boltLength;
F32 distAlong = mDot((listener - bolt->endPoint), dHat);
Point3F contactPoint;
if(distAlong >= boltLength)
contactPoint = bolt->startPoint;
else if(distAlong <= 0.0)
contactPoint = bolt->endPoint;
else
contactPoint = bolt->endPoint + dHat * distAlong;
F32 delayDist = (listener - contactPoint).len();
U32 delayTime = U32((delayDist / 330.0f) * 100.0f);
MatrixF trans(true);
trans.setPosition(contactPoint);
sEvent.soundBlockId = getRandomSound();
sEvent.position = trans;
sEvent.time = delayTime;
// play strike sound
trans.setPosition(strikePoint);
if(mDataBlock->strikeSound)
alxPlay(mDataBlock->strikeSound, &trans);
}
U32 WeatherLightning::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
{
U32 retMask = Parent::packUpdate(conn, mask, stream);
// Only write data if this is the initial packet or we've been inspected.
if (stream->writeFlag(mask & (InitialUpdateMask | ExtendedInfoMask)))
{
// Initial update
mathWrite(*stream, getPosition());
mathWrite(*stream, mObjScale);
}
return retMask;
}
void WeatherLightning::unpackUpdate(NetConnection *conn, BitStream *stream)
{
Parent::unpackUpdate(conn, stream);
if (stream->readFlag())
{
// Initial update
Point3F pos;
mathRead(*stream, &pos);
setPosition( pos );
mathRead(*stream, &mObjScale);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -