📄 fxlight.cc
字号:
// Reset Last Render Time.
mLastRenderTime = Platform::getRealMilliseconds();
// Screen Viewport.
RectI viewport;
// Setup out the Projection Matrix/Viewport.
glMatrixMode(GL_PROJECTION);
glPushMatrix();
dglGetViewport(&viewport);
state->setupBaseProjection();
// Setup Billboard View.
//
// NOTE:- We need to adjust for any animated offset.
glPushMatrix();
// Get Object Transform.
RXF = getRenderTransform();
RXF.getColumn(3, &Position);
// Translate transform to absolute position.
Position.x = mAnimationPosition.x;
Position.y = mAnimationPosition.y;
Position.z = mAnimationPosition.z;
// Set new Position.
RXF.setColumn(3, Position);
dglMultMatrix(&RXF);
// Finish-up billboard.
dglGetModelview(&ModelView);
ModelView.getColumn(3, &Position);
ModelView.identity();
ModelView.setColumn(3, Position);
dglLoadMatrix(&ModelView);
// Setup our rendering state.
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
// Select User Blend Mode.
switch(mDataBlock->mBlendMode)
{
case 0:
glBlendFunc(GL_SRC_ALPHA, GL_ONE); break;
case 1:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); break;
case 2:
glBlendFunc(GL_ONE,GL_ONE); break;
default:
// Duh, User error.
Con::printf("fxLight: Invalid Blend Mode Selected!");
glBlendFunc(GL_SRC_ALPHA, GL_ONE); break;
}
// Is the Flare On?
if (mDataBlock->mFlareOn && mEnable)
{
// Flare On ...
// Modulate Texture.
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
Point3F ScreenPoint;
Point3F ObjectPoint;
// Get Animation Position.
ObjectPoint = mAnimationPosition;
//
// Calculate screen point, on screen?
if (dglPointToScreen(ObjectPoint, ScreenPoint))
{
// Fetch Eye Position.
Point3F eyePos = state->getCameraPosition();
// Calculate Distance from Light.
F32 Distance = (ObjectPoint - eyePos).len();
// Reset Billboard Radius.
BBRadius = 1.0f;
// Are we using Constant Size?
if (mDataBlock->mConstantSizeOn)
{
// Yes, so simply size to Constant Size.
BBRadius *= mDataBlock->mConstantSize;
}
else
{
// No, so calculate current size (in world units) according to distance.
// Are we below the near size distance?
if (Distance <= mDataBlock->mNearDistance)
{
// Yes, so clamp at near size.
BBRadius *= mDataBlock->mNearSize;
}
// Are we above the far size distance?
else if (Distance >= mDataBlock->mFarDistance)
{
// Yes, so clamp at far size.
BBRadius *= mDataBlock->mFarSize;
}
else
{
// In the ramp so calculate current size according to distance.
BBRadius = mDataBlock->mNearSize + ((Distance - mDataBlock->mNearDistance) * ((mDataBlock->mFarSize - mDataBlock->mNearSize) / ( mDataBlock->mFarDistance - mDataBlock->mNearDistance )));
}
}
}
else
{
// Console Warning.
//Con::warnf("Flare point off screen! How did this happen huh?");
// Calculate Billboard Radius.
BBRadius = 0;
}
// Do we have Line-of-sight?
if (TestLOS(mAnimationPosition, mAttached?mpAttachedObject:NULL))
{
// Yes, so are we fully showing?
if (mFlareScale < 1.0f)
{
// No, so calculate new scale.
mFlareScale += mElapsedTime / mDataBlock->mFadeTime;
// Check new scale.
if (mFlareScale > 1.0f) mFlareScale = 1.0f;
}
}
else
{
// No, so are we fully hidden?
if (mFlareScale > 0.0f)
{
// No, so calculate new scale.
mFlareScale -= mElapsedTime / mDataBlock->mFadeTime;
// Check new scale.
if (mFlareScale < 0.0f) mFlareScale = 0.0f;
}
}
// Scale BB Size.
BBRadius *= mFlareScale;
// Are we linking flare size?
if (mDataBlock->mLinkFlareSize)
{
// Yes, so Scale by LUMINANCE (better for modern colour monitors).
BBRadius *= (mAnimationColour.red * 0.212671f) +
(mAnimationColour.green * 0.715160f) +
(mAnimationColour.blue * 0.072169f);
}
// Select Icon Texture.
glBindTexture(GL_TEXTURE_2D, mFlareTextureHandle.getGLName());
// Are we linking the flare?
if (mDataBlock->mLinkFlare)
{
// Yes, so set Flare Colour to animation.
glColor3f(mAnimationColour.red, mAnimationColour.green, mAnimationColour.blue);
}
else
{
// No, so set it to constant flare colour.
glColor3f(mDataBlock->mFlareColour.red, mDataBlock->mFlareColour.green, mDataBlock->mFlareColour.blue);
}
}
else
{
// Icon On ...
// Icon Blend Function.
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// Replace Texture.
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// Calculate Billboard Radius.
BBRadius = mIconSize / 2;
// Select Icon Texture.
glBindTexture(GL_TEXTURE_2D, mIconTextureHandle.getGLName());
}
// Only draw if needed.
if (BBRadius > 0)
{
// Rotate, if we have a rotation.
if (mAnimationRotation != 0.0f) glRotatef(mAnimationRotation, 0, 1, 0);
// Draw Billboard.
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(-BBRadius, 0, BBRadius);
glTexCoord2f(1, 0);
glVertex3f(BBRadius, 0, BBRadius);
glTexCoord2f(1, 1);
glVertex3f(BBRadius, 0, -BBRadius);
glTexCoord2f(0, 1);
glVertex3f(-BBRadius, 0, -BBRadius);
glEnd();
}
// Restore rendering state.
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
// Restore our nice, friendly and dull canonical state.
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
dglSetViewport(viewport);
// Check we have restored Canonical State.
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}
//------------------------------------------------------------------------------
bool fxLight::TestLOS(const Point3F& ObjectPosition, SceneObject* AttachedObj)
{
// Valid Control Object types (for now).
const U32 ObjectMask = PlayerObjectType | VehicleObjectType | CameraObjectType;
// Get Server Connection.
GameConnection* con = GameConnection::getConnectionToServer();
// Problem?
if (!con) return false;
// Get the Control Object.
ShapeBase* ControlObj = con->getControlObject();
// Valid Control Objects?
if (!ControlObj || !(ControlObj->getType() & ObjectMask)) return false;
// Kill flare if Third-person not available.
if (!ControlObj->isFirstPerson() && !mDataBlock->mFlareTP) return false;
// Fetch Eye Position.
Point3F eyePos;
MatrixF eye;
con->getControlCameraTransform(0, &eye);
eye.getColumn(3, &eyePos);
// Get our object center.
Point3F endPos = ObjectPosition;
// LOS Mask.
static U32 losMask = STATIC_COLLISION_MASK |
ShapeBaseObjectType |
StaticTSObjectType |
PlayerObjectType;
// Stop Collisions with our Control Object (in first person).
if (ControlObj->isFirstPerson()) ControlObj->disableCollision();
// If we are attached to an object then disable it's collision.
if (AttachedObj) AttachedObj->disableCollision();
// Store old Object Box.
Box3F OldObjBox = mObjBox;
// Set LOS Test Object Box.
mObjBox.min.set( -0.5, -0.5, -0.5 );
mObjBox.max.set( 0.5, 0.5, 0.5 );
// Reset the World Box.
resetWorldBox();
// Perform a ray cast on the client container database.
RayInfo info;
bool los = !gClientContainer.castRay(eyePos, endPos, losMask, &info);
// Restore old Object Box.
mObjBox = OldObjBox;
// Reset the World Box.
resetWorldBox();
// If we are attached to an object then enable it's collision.
if (AttachedObj) AttachedObj->enableCollision();
// Continue Collisions with our Control Object (in first person).
if (ControlObj->isFirstPerson()) ControlObj->enableCollision();
// Return LOS result.
return los;
};
//------------------------------------------------------------------------------
U32 fxLight::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
{
// Pack Parent.
U32 retMask = Parent::packUpdate(con, mask, stream);
// Write Attach Flag.
if (stream->writeFlag((mask & fxLightAttachChange) && mAttachValid))
{
// Get Attached Object.
GameBase* Obj = getProcessAfter();
// Write Object Attach/Detach Flag.
if (stream->writeFlag(Obj != NULL))
{
/*
// Get Server Connection.
GameConnection* conn = GameConnection::getLocalClientConnection();
// Problem?
if (!conn)
{
// Invalidate Attachment.
mAttachValid = false;
// Return here.
return(retMask);
}
*/
// Get the GhostID of the object.
S32 GhostID = con->getGhostIndex(Obj);
// Send it to the client.
stream->writeRangedU32(U32(GhostID), 0, GhostConnection::MaxGhostCount);
}
// Invalidate Attachment.
mAttachValid = false;
}
// Write Config Change Flag.
if (stream->writeFlag(mask & fxLightConfigChangeMask))
{
// Position.
stream->writeAffineTransform(mObjToWorld);
// Enable.
stream->write(mEnable);
// Basis Light.
stream->write(mIconSize);
}
// Were done ...
return(retMask);
}
//------------------------------------------------------------------------------
void fxLight::unpackUpdate(NetConnection * con, BitStream * stream)
{
// Unpack Parent.
Parent::unpackUpdate(con, stream);
// Read Attach Position.
if (stream->readFlag())
{
// Read Attach/Detach Flag.
mAttached = stream->readFlag();
// Read Position.
if (mAttached)
{
// Get the ObjectID.
S32 ObjectID = stream->readRangedU32(0, GhostConnection::MaxGhostCount);
// Resolve it.
NetObject* pObject = con->resolveGhost(ObjectID);
if (pObject != NULL)
{
// Get the object.
mpAttachedObject = dynamic_cast<GameBase*>(pObject);
// Make sure we know if it's deleted.
deleteNotify(mpAttachedObject);
//Con::warnf(ConsoleLogEntry::General, "fxLight::unpack: attached to object.");
}
else
{
//Con::warnf(ConsoleLogEntry::General, "fxLight::unpack: could not resolve attachment targetID!");
//Con::warnf(ConsoleLogEntry::General, "fxLight::unpack: recovering by detaching object.");
mAttached = false;
}
}
else
{
// Reset Any Attachment.
mAttached = false;
}
}
// Read Config Change Details?
if(stream->readFlag())
{
MatrixF ObjectMatrix;
// Position.
stream->readAffineTransform(&ObjectMatrix);
// Enable.
stream->read(&mEnable);
// Basis Light.
stream->read(&mIconSize);
// Set Transform.
setTransform(ObjectMatrix);
// Reset Animation.
ResetAnimation();
}
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -