1660 lines
46 KiB
C++
Executable File
1660 lines
46 KiB
C++
Executable File
//-----------------------------------------------------------------------------
|
|
// Torque Game Engine
|
|
//
|
|
// Written by Melvyn May, Started on 4th May 2002.
|
|
//
|
|
// "My code is written for the Torque community, so do your worst with it,
|
|
// just don't rip-it-off and call it your own without even thanking me".
|
|
//
|
|
// - Melv.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "console/consoleTypes.h"
|
|
#include "dgl/dgl.h"
|
|
#include "core/bitStream.h"
|
|
#include "game/gameConnection.h"
|
|
#include "game/gameBase.h"
|
|
#include "sceneGraph/sceneState.h"
|
|
#include "sceneGraph/sceneGraph.h"
|
|
#include "fxLight.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Put this in /example/common/editor/EditorGui.cs in [function Creator::init( %this )]
|
|
//
|
|
// %Environment_Item[<next item-index in list>] = "fxLight"; <-- ADD THIS.
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Put the function in /example/common/editor/ObjectBuilderGui.gui [around line 458] ...
|
|
//
|
|
// function ObjectBuilderGui::buildfxLight(%this)
|
|
// {
|
|
// %this.className = "fxLight";
|
|
// %this.addField("dataBlock", "TypeDataBlock", "fxLight Data", "fxLightData");
|
|
// %this.process();
|
|
// }
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Put 'fxLightIcon.jpg' in /example/common/editor/ directory.
|
|
// Put the example 'corona.png' in the "/example/common/lighting/" directory.
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
extern bool gEditingMission;
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
//IMPLEMENT_CONSOLETYPE(fxLightData)
|
|
//IMPLEMENT_GETDATATYPE(fxLightData)
|
|
//IMPLEMENT_SETDATATYPE(fxLightData)
|
|
IMPLEMENT_CO_DATABLOCK_V1(fxLightData);
|
|
IMPLEMENT_CO_NETOBJECT_V1(fxLight);
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
fxLightData::fxLightData()
|
|
{
|
|
// Datablock Light.
|
|
mLightOn = true;
|
|
mRadius = 10.0f;
|
|
mBrightness = 1.0f;
|
|
mColour .set(1,1,1);
|
|
|
|
// Datablock Sun-Light.
|
|
// Datablock Flare.
|
|
mFlareOn = false;
|
|
mFlareTP = true;
|
|
mFlareTextureName = StringTable->insert("");
|
|
mConstantSizeOn = false;
|
|
mConstantSize = 1.0f;
|
|
mNearSize = 3.0f;
|
|
mFarSize = 0.5f;
|
|
mNearDistance = 10.0f;
|
|
mFarDistance = 30.0f;
|
|
mFadeTime = 0.1f;
|
|
mFlareColour .set(1,1,1);
|
|
mBlendMode = 0;
|
|
|
|
// Datablock Animation.
|
|
mMinColour .set(0,0,0);
|
|
mMaxColour .set(1,1,1);
|
|
mMinBrightness = 0.0f;
|
|
mMaxBrightness = 1.0f;
|
|
mMinRadius = 0.1f;
|
|
mMaxRadius = 20.0f;
|
|
mStartOffset .set(-5,0,0);
|
|
mEndOffset .set(+5,0,0);
|
|
mMinRotation = 0;
|
|
mMaxRotation = 359;
|
|
mSingleColourKeys = true;
|
|
mRedKeys = StringTable->insert("AZA");
|
|
mGreenKeys = StringTable->insert("AZA");
|
|
mBlueKeys = StringTable->insert("AZA");
|
|
mBrightnessKeys = StringTable->insert("AZA");
|
|
mRadiusKeys = StringTable->insert("AZA");
|
|
mOffsetKeys = StringTable->insert("AZA");
|
|
mRotationKeys = StringTable->insert("AZA");
|
|
mColourTime = 5.0f;
|
|
mBrightnessTime = 5.0f;
|
|
mRadiusTime = 5.0f;
|
|
mOffsetTime = 5.0f;
|
|
mRotationTime = 5.0f;
|
|
mLerpColour = true;
|
|
mLerpBrightness = true;
|
|
mLerpRadius = true;
|
|
mLerpOffset = true;
|
|
mLerpRotation = true;
|
|
mUseColour = false;
|
|
mUseBrightness = false;
|
|
mUseRadius = false;
|
|
mUseOffsets = false;
|
|
mUseRotation = false;
|
|
mLinkFlare = true;
|
|
mLinkFlareSize = false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLightData::initPersistFields()
|
|
{
|
|
Parent::initPersistFields();
|
|
|
|
|
|
// Datablock Light.
|
|
addField( "LightOn", TypeBool, Offset( mLightOn, fxLightData ) );
|
|
addField( "Radius", TypeF32, Offset( mRadius, fxLightData ) );
|
|
addField( "Brightness", TypeF32, Offset( mBrightness, fxLightData ) );
|
|
addField( "Colour", TypeColorF, Offset( mColour, fxLightData ) );
|
|
|
|
// Flare.
|
|
addField( "FlareOn", TypeBool, Offset( mFlareOn, fxLightData ) );
|
|
addField( "FlareTP", TypeBool, Offset( mFlareTP, fxLightData ) );
|
|
addField( "FlareBitmap", TypeFilename, Offset( mFlareTextureName, fxLightData ) );
|
|
addField( "FlareColour", TypeColorF, Offset( mFlareColour, fxLightData ) );
|
|
addField( "ConstantSizeOn", TypeBool, Offset( mConstantSizeOn, fxLightData ) );
|
|
addField( "ConstantSize", TypeF32, Offset( mConstantSize, fxLightData ) );
|
|
addField( "NearSize", TypeF32, Offset( mNearSize, fxLightData ) );
|
|
addField( "FarSize", TypeF32, Offset( mFarSize, fxLightData ) );
|
|
addField( "NearDistance", TypeF32, Offset( mNearDistance, fxLightData ) );
|
|
addField( "FarDistance", TypeF32, Offset( mFarDistance, fxLightData ) );
|
|
addField( "FadeTime", TypeF32, Offset( mFadeTime, fxLightData ) );
|
|
addField( "BlendMode", TypeS32, Offset( mBlendMode, fxLightData ) );
|
|
|
|
// Datablock Animation.
|
|
addField( "AnimColour", TypeBool, Offset( mUseColour, fxLightData ) );
|
|
addField( "AnimBrightness", TypeBool, Offset( mUseBrightness, fxLightData ) );
|
|
addField( "AnimRadius", TypeBool, Offset( mUseRadius, fxLightData ) );
|
|
addField( "AnimOffsets", TypeBool, Offset( mUseOffsets, fxLightData ) );
|
|
addField( "AnimRotation", TypeBool, Offset( mUseRotation, fxLightData ) );
|
|
addField( "LinkFlare", TypeBool, Offset( mLinkFlare, fxLightData ) );
|
|
addField( "LinkFlareSize", TypeBool, Offset( mLinkFlareSize, fxLightData ) );
|
|
addField( "MinColour", TypeColorF, Offset( mMinColour, fxLightData ) );
|
|
addField( "MaxColour", TypeColorF, Offset( mMaxColour, fxLightData ) );
|
|
addField( "MinBrightness", TypeF32, Offset( mMinBrightness, fxLightData ) );
|
|
addField( "MaxBrightness", TypeF32, Offset( mMaxBrightness, fxLightData ) );
|
|
addField( "MinRadius", TypeF32, Offset( mMinRadius, fxLightData ) );
|
|
addField( "MaxRadius", TypeF32, Offset( mMaxRadius, fxLightData ) );
|
|
addField( "StartOffset", TypePoint3F, Offset( mStartOffset, fxLightData ) );
|
|
addField( "EndOffset", TypePoint3F, Offset( mEndOffset, fxLightData ) );
|
|
addField( "MinRotation", TypeF32, Offset( mMinRotation, fxLightData ) );
|
|
addField( "MaxRotation", TypeF32, Offset( mMaxRotation, fxLightData ) );
|
|
addField( "SingleColourKeys", TypeBool, Offset( mSingleColourKeys, fxLightData ) );
|
|
addField( "RedKeys", TypeString, Offset( mRedKeys, fxLightData ) );
|
|
addField( "GreenKeys", TypeString, Offset( mGreenKeys, fxLightData ) );
|
|
addField( "BlueKeys", TypeString, Offset( mBlueKeys, fxLightData ) );
|
|
addField( "BrightnessKeys", TypeString, Offset( mBrightnessKeys, fxLightData ) );
|
|
addField( "RadiusKeys", TypeString, Offset( mRadiusKeys, fxLightData ) );
|
|
addField( "OffsetKeys", TypeString, Offset( mOffsetKeys, fxLightData ) );
|
|
addField( "RotationKeys", TypeString, Offset( mRotationKeys, fxLightData ) );
|
|
addField( "ColourTime", TypeF32, Offset( mColourTime, fxLightData ) );
|
|
addField( "BrightnessTime", TypeF32, Offset( mBrightnessTime, fxLightData ) );
|
|
addField( "RadiusTime", TypeF32, Offset( mRadiusTime, fxLightData ) );
|
|
addField( "OffsetTime", TypeF32, Offset( mOffsetTime, fxLightData ) );
|
|
addField( "RotationTime", TypeF32, Offset( mRotationTime, fxLightData ) );
|
|
addField( "LerpColour", TypeBool, Offset( mLerpColour, fxLightData ) );
|
|
addField( "LerpBrightness", TypeBool, Offset( mLerpBrightness, fxLightData ) );
|
|
addField( "LerpRadius", TypeBool, Offset( mLerpRadius, fxLightData ) );
|
|
addField( "LerpOffset", TypeBool, Offset( mLerpOffset, fxLightData ) );
|
|
addField( "LerpRotation", TypeBool, Offset( mLerpRotation, fxLightData ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool fxLightData::onAdd()
|
|
{
|
|
if (Parent::onAdd() == false)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLightData::packData(BitStream* stream)
|
|
{
|
|
// Parent packing.
|
|
Parent::packData(stream);
|
|
|
|
// Datablock Light.
|
|
stream->write(mLightOn);
|
|
stream->write(mRadius);
|
|
stream->write(mBrightness);
|
|
stream->write(mColour);
|
|
|
|
// Datablock Flare.
|
|
stream->writeString(mFlareTextureName);
|
|
stream->write(mFlareColour);
|
|
stream->write(mFlareOn);
|
|
stream->write(mFlareTP);
|
|
stream->write(mConstantSizeOn);
|
|
stream->write(mConstantSize);
|
|
stream->write(mNearSize);
|
|
stream->write(mFarSize);
|
|
stream->write(mNearDistance);
|
|
stream->write(mFarDistance);
|
|
stream->write(mFadeTime);
|
|
stream->write(mBlendMode);
|
|
|
|
// Datablock Animation.
|
|
stream->writeFlag(mUseColour);
|
|
stream->writeFlag(mUseBrightness);
|
|
stream->writeFlag(mUseRadius);
|
|
stream->writeFlag(mUseOffsets);
|
|
stream->writeFlag(mUseRotation);
|
|
stream->writeFlag(mLinkFlare);
|
|
stream->writeFlag(mLinkFlareSize);
|
|
stream->write(mMinColour);
|
|
stream->write(mMaxColour);
|
|
stream->write(mMinBrightness);
|
|
stream->write(mMaxBrightness);
|
|
stream->write(mMinRadius);
|
|
stream->write(mMaxRadius);
|
|
stream->write(mStartOffset.x);
|
|
stream->write(mStartOffset.y);
|
|
stream->write(mStartOffset.z);
|
|
stream->write(mEndOffset.x);
|
|
stream->write(mEndOffset.y);
|
|
stream->write(mEndOffset.z);
|
|
stream->write(mMinRotation);
|
|
stream->write(mMaxRotation);
|
|
stream->writeFlag(mSingleColourKeys);
|
|
stream->writeString(mRedKeys);
|
|
stream->writeString(mGreenKeys);
|
|
stream->writeString(mBlueKeys);
|
|
stream->writeString(mBrightnessKeys);
|
|
stream->writeString(mRadiusKeys);
|
|
stream->writeString(mOffsetKeys);
|
|
stream->writeString(mRotationKeys);
|
|
stream->write(mColourTime);
|
|
stream->write(mBrightnessTime);
|
|
stream->write(mRadiusTime);
|
|
stream->write(mOffsetTime);
|
|
stream->write(mRotationTime);
|
|
stream->writeFlag(mLerpColour);
|
|
stream->writeFlag(mLerpBrightness);
|
|
stream->writeFlag(mLerpRadius);
|
|
stream->writeFlag(mLerpOffset);
|
|
stream->writeFlag(mLerpRotation);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLightData::unpackData(BitStream* stream)
|
|
{
|
|
// Parent unpacking.
|
|
Parent::unpackData(stream);
|
|
|
|
// Datablock Light.
|
|
stream->read(&mLightOn);
|
|
stream->read(&mRadius);
|
|
stream->read(&mBrightness);
|
|
stream->read(&mColour);
|
|
|
|
// Flare.
|
|
mFlareTextureName = StringTable->insert(stream->readSTString());
|
|
stream->read(&mFlareColour);
|
|
stream->read(&mFlareOn);
|
|
stream->read(&mFlareTP);
|
|
stream->read(&mConstantSizeOn);
|
|
stream->read(&mConstantSize);
|
|
stream->read(&mNearSize);
|
|
stream->read(&mFarSize);
|
|
stream->read(&mNearDistance);
|
|
stream->read(&mFarDistance);
|
|
stream->read(&mFadeTime);
|
|
stream->read(&mBlendMode);
|
|
|
|
// Datablock Animation.
|
|
mUseColour = stream->readFlag();
|
|
mUseBrightness = stream->readFlag();
|
|
mUseRadius = stream->readFlag();
|
|
mUseOffsets = stream->readFlag();
|
|
mUseRotation = stream->readFlag();
|
|
mLinkFlare = stream->readFlag();
|
|
mLinkFlareSize = stream->readFlag();
|
|
stream->read(&mMinColour);
|
|
stream->read(&mMaxColour);
|
|
stream->read(&mMinBrightness);
|
|
stream->read(&mMaxBrightness);
|
|
stream->read(&mMinRadius);
|
|
stream->read(&mMaxRadius);
|
|
stream->read(&mStartOffset.x);
|
|
stream->read(&mStartOffset.y);
|
|
stream->read(&mStartOffset.z);
|
|
stream->read(&mEndOffset.x);
|
|
stream->read(&mEndOffset.y);
|
|
stream->read(&mEndOffset.z);
|
|
stream->read(&mMinRotation);
|
|
stream->read(&mMaxRotation);
|
|
mSingleColourKeys = stream->readFlag();
|
|
mRedKeys = stream->readSTString();
|
|
mGreenKeys = stream->readSTString();
|
|
mBlueKeys = stream->readSTString();
|
|
mBrightnessKeys = stream->readSTString();
|
|
mRadiusKeys = stream->readSTString();
|
|
mOffsetKeys = stream->readSTString();
|
|
mRotationKeys = stream->readSTString();
|
|
stream->read(&mColourTime);
|
|
stream->read(&mBrightnessTime);
|
|
stream->read(&mRadiusTime);
|
|
stream->read(&mOffsetTime);
|
|
stream->read(&mRotationTime);
|
|
mLerpColour = stream->readFlag();
|
|
mLerpBrightness = stream->readFlag();
|
|
mLerpRadius = stream->readFlag();
|
|
mLerpOffset = stream->readFlag();
|
|
mLerpRotation = stream->readFlag();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Class: fxLight
|
|
//------------------------------------------------------------------------------
|
|
|
|
fxLight::fxLight()
|
|
{
|
|
// Setup NetObject.
|
|
mTypeMask |= StaticObjectType | StaticTSObjectType | StaticRenderedObjectType;
|
|
mNetFlags.set(Ghostable | ScopeAlways);
|
|
mAddedToScene = false;
|
|
|
|
// Reset DataBlock.
|
|
mDataBlock = NULL;
|
|
|
|
// Reset Attachment stuff.
|
|
mAttached = false;//mAttachWait = mAttachValid = false;
|
|
|
|
// Initialise Animation.
|
|
InitialiseAnimation();
|
|
|
|
// Set Light Type.
|
|
mLight.mType = LightInfo::Point;
|
|
|
|
mountPoint = 0;
|
|
mountTransform.identity();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
fxLight::~fxLight()
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::initPersistFields()
|
|
{
|
|
// Initialise parents' persistent fields.
|
|
Parent::initPersistFields();
|
|
|
|
// Add our own persistent fields.
|
|
addField( "Enable", TypeBool, Offset( mEnable, fxLight ) );
|
|
addField( "IconSize", TypeF32, Offset( mIconSize, fxLight ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::processTick(const Move* m)
|
|
{
|
|
// Process Parent.
|
|
Parent::processTick(m);
|
|
|
|
// Are we attached?
|
|
/*if (isServerObject() && mAttachWait)
|
|
{
|
|
//Con::printf("fxLight: Checking Object...");
|
|
// Get Attached Object.
|
|
GameBase* Obj = getProcessAfter();
|
|
|
|
// Write Object Attach/Detach Flag.
|
|
if (Obj != NULL)
|
|
{
|
|
// Get Server Connection.
|
|
GameConnection* con = GameConnection::getLocalClientConnection();
|
|
// Problem?
|
|
if (!con)
|
|
{
|
|
Con::printf("fxLight: Could not get Game Connection!!!");
|
|
return;
|
|
}
|
|
S32 ghostIndex = con->getGhostIndex(Obj);
|
|
if (ghostIndex == -1)
|
|
{
|
|
return;
|
|
//Con::printf("fxLight: Attached but no GHOST available yet...");
|
|
}
|
|
else
|
|
{
|
|
Con::printf("fxLight: Attached and found GHOST!!! YIPEE YEAY!!!!");
|
|
|
|
// Finished waiting for attachment.
|
|
mAttachWait = false;
|
|
// Attachment is now valid to send.
|
|
mAttachValid = true;
|
|
// Send to the client.
|
|
setMaskBits(fxLightAttachChange);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Con::printf("fxLight: Attached but no object available, stopping search.");
|
|
|
|
// Finished waiting for attachment.
|
|
mAttachWait = false;
|
|
}
|
|
}*/
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::setEnable(bool Status)
|
|
{
|
|
// Set Attribute.
|
|
mEnable = Status;
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(fxLightConfigChangeMask);
|
|
}
|
|
|
|
void fxLight::setFlareBitmap(const char* Name)
|
|
{
|
|
// Set Flare Texture Name.
|
|
mDataBlock->mFlareTextureName = StringTable->insert(Name);
|
|
|
|
// Only let the client load an actual texture.
|
|
if (isClientObject())
|
|
{
|
|
// Reset existing flare texture.
|
|
mFlareTextureHandle = NULL;
|
|
|
|
// Got a nice flare texture?
|
|
if (*mDataBlock->mFlareTextureName)
|
|
{
|
|
// Yes, so load it.
|
|
mFlareTextureHandle = TextureHandle(mDataBlock->mFlareTextureName, BitmapTexture, true);
|
|
}
|
|
}
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(fxLightConfigChangeMask);
|
|
}
|
|
|
|
void fxLight::reset(void)
|
|
{
|
|
// Reset Animation.
|
|
ResetAnimation();
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(fxLightConfigChangeMask);
|
|
}
|
|
|
|
/*void fxLight::attachToObject(const char* ObjectName)
|
|
{
|
|
// Find the Selected Object.
|
|
GameBase *Obj = dynamic_cast<GameBase*>(Sim::findObject(ObjectName));
|
|
|
|
// Check we found it.
|
|
if (!Obj)
|
|
{
|
|
Con::warnf("Couldn't find %s object to attach to!", ObjectName);
|
|
return;
|
|
}
|
|
|
|
// If the object has a name then output attachment.
|
|
//if (getName()) Con::printf("%s attached to object %s.", getName(), ObjectName);
|
|
|
|
// set-up dependency.
|
|
processAfter(Obj);
|
|
|
|
// Make sure we know if it's deleted.
|
|
deleteNotify(Obj);
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) mAttachWait = true;
|
|
}
|
|
|
|
void fxLight::detachFromObject(void)
|
|
{
|
|
// Return if nothing to do!
|
|
if (!getProcessAfter()) return;
|
|
|
|
// If the object has a name then output detachment.
|
|
//if (getName()) Con::printf("%s detached from object %s.", getName(), getProcessAfter()->getName());
|
|
|
|
// Don't need delete notification now.
|
|
clearNotify(getProcessAfter());
|
|
|
|
// Clear dependency.
|
|
clearProcessAfter();
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject())
|
|
{
|
|
// Signal Attach is no invalid.
|
|
mAttachValid = false;
|
|
// Tell the client it's all over.
|
|
setMaskBits(fxLightAttachChange);
|
|
}
|
|
}*/
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
ConsoleMethod( fxLight, setEnable, void, 3, 3, "(bool enabled)")
|
|
{
|
|
object->setEnable(dAtob(argv[2]));
|
|
}
|
|
|
|
ConsoleMethod( fxLight, reset, void, 2, 2, "() Reset the light.")
|
|
{
|
|
object->reset();
|
|
}
|
|
|
|
/*ConsoleMethod( fxLight, attachToObject, void, 3, 3, "(SimObject obj) Attach to the SimObject obj.")
|
|
{
|
|
object->attachToObject(argv[2]);
|
|
}
|
|
|
|
ConsoleMethod( fxLight, detachFromObject, void, 2, 2, "() Detach from the object previously set by attachToObject.")
|
|
{
|
|
object->detachFromObject();
|
|
}*/
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::registerLights(LightManager * lightManager, bool lightingScene)
|
|
{
|
|
// Exit if disabled.
|
|
if (!mEnable) return;
|
|
|
|
// Animate Light.
|
|
AnimateLight();
|
|
|
|
// Return if lighting scene or light off.
|
|
if (lightingScene || !mDataBlock->mLightOn) return;
|
|
|
|
// Setup light frame.
|
|
mLight.mPos = mAnimationPosition;
|
|
mLight.mRadius = mAnimationRadius;
|
|
mLight.mColor = mAnimationColour;
|
|
|
|
// Add light to light manager.
|
|
lightManager->sgRegisterGlobalLight(&mLight);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::AnimateLight(void)
|
|
{
|
|
// Calculate Elapsed Time.
|
|
F32 mElapsedTime = (F32)((Platform::getRealMilliseconds() - mLastAnimateTime) / 1000.0f);
|
|
|
|
// Reset Last Animation Time.
|
|
mLastAnimateTime = Platform::getRealMilliseconds();
|
|
|
|
|
|
mDataBlock->mColourTime = getMax(mDataBlock->mColourTime, 0.1f);
|
|
mDataBlock->mBrightnessTime = getMax(mDataBlock->mBrightnessTime, 0.1f);
|
|
mDataBlock->mRadiusTime = getMax(mDataBlock->mRadiusTime, 0.1f);
|
|
mDataBlock->mOffsetTime = getMax(mDataBlock->mOffsetTime, 0.1f);
|
|
mDataBlock->mRotationTime = getMax(mDataBlock->mRotationTime, 0.1f);
|
|
|
|
|
|
// ********************************************
|
|
// Calculate Colour.
|
|
// ********************************************
|
|
|
|
// Animating Colour?
|
|
if (mDataBlock->mUseColour)
|
|
{
|
|
U32 PosFrom;
|
|
U32 PosTo;
|
|
F32 LerpFactor;
|
|
|
|
// Yes, so adjust time-base.
|
|
mColourElapsedTime += mElapsedTime;
|
|
|
|
// Adjust to Bounds.
|
|
while (mColourElapsedTime > mDataBlock->mColourTime) { mColourElapsedTime -= mDataBlock->mColourTime; };
|
|
|
|
// Scale Time.
|
|
F32 ScaledTime = mColourElapsedTime * mColourTimeScale;
|
|
|
|
// Calculate Position From.
|
|
PosFrom = mFloor(ScaledTime);
|
|
|
|
// Are we Lerping?
|
|
if (mDataBlock->mLerpColour)
|
|
{
|
|
// Yes, so calculate Position To.
|
|
PosTo = mCeil(ScaledTime);
|
|
|
|
// Calculate Lerp Factor.
|
|
LerpFactor = ScaledTime - PosFrom;
|
|
}
|
|
else
|
|
{
|
|
// No, so clamp Position.
|
|
PosTo = PosFrom;
|
|
|
|
// Clamp lerp factor.
|
|
LerpFactor = 0.0f;
|
|
}
|
|
|
|
// Reset RGB Set Flag.
|
|
bool RedSet = false;
|
|
bool GreenSet = false;
|
|
bool BlueSet = false;
|
|
|
|
// ********************************************
|
|
// Red<GREEN,BLUE> Keys.
|
|
// ********************************************
|
|
if (mRedKeysLength)
|
|
{
|
|
// Are we using single-channel colour keys?
|
|
if (mDataBlock->mSingleColourKeys)
|
|
{
|
|
// Yes, so calculate rgb from red keys.
|
|
mAnimationColour.red = GetLerpKey(mDataBlock->mRedKeys, PosFrom, PosTo, mDataBlock->mMinColour.red, mDataBlock->mMaxColour.red, LerpFactor);
|
|
mAnimationColour.green = GetLerpKey(mDataBlock->mRedKeys, PosFrom, PosTo, mDataBlock->mMinColour.green, mDataBlock->mMaxColour.green, LerpFactor);
|
|
mAnimationColour.blue = GetLerpKey(mDataBlock->mRedKeys, PosFrom, PosTo, mDataBlock->mMinColour.blue, mDataBlock->mMaxColour.blue, LerpFactor);
|
|
|
|
// Flag RGB Set.
|
|
RedSet = GreenSet = BlueSet = true;
|
|
}
|
|
else
|
|
{
|
|
// No, so calculate Red only.
|
|
mAnimationColour.red = GetLerpKey(mDataBlock->mRedKeys, PosFrom, PosTo, mDataBlock->mMinColour.red, mDataBlock->mMaxColour.red, LerpFactor);
|
|
|
|
// Flag Red Set.
|
|
RedSet = true;
|
|
}
|
|
}
|
|
|
|
// ********************************************
|
|
// Green Keys.
|
|
// ********************************************
|
|
if (!mDataBlock->mSingleColourKeys && mGreenKeysLength)
|
|
{
|
|
// Calculate Green.
|
|
mAnimationColour.green = GetLerpKey(mDataBlock->mGreenKeys, PosFrom, PosTo, mDataBlock->mMinColour.green, mDataBlock->mMaxColour.green, LerpFactor);
|
|
|
|
// Flag Green Set.
|
|
GreenSet = true;
|
|
}
|
|
|
|
// ********************************************
|
|
// Blue Keys.
|
|
// ********************************************
|
|
if (!mDataBlock->mSingleColourKeys && mBlueKeysLength)
|
|
{
|
|
// Calculate Blue.
|
|
mAnimationColour.blue = GetLerpKey(mDataBlock->mGreenKeys, PosFrom, PosTo, mDataBlock->mMinColour.blue, mDataBlock->mMaxColour.blue, LerpFactor);
|
|
|
|
// Flag Blue Set.
|
|
BlueSet = true;
|
|
}
|
|
|
|
// Set to static colour if we failed to set RGB correctly.
|
|
if (!RedSet || !GreenSet || !BlueSet) mAnimationColour = mDataBlock->mColour;
|
|
}
|
|
else
|
|
{
|
|
// No, so set to static Colour.
|
|
mAnimationColour = mDataBlock->mColour;
|
|
}
|
|
|
|
|
|
// ********************************************
|
|
// Calculate Brightness.
|
|
// ********************************************
|
|
|
|
// Animating Brightness?
|
|
if (mDataBlock->mUseBrightness)
|
|
{
|
|
U32 PosFrom;
|
|
U32 PosTo;
|
|
F32 LerpFactor;
|
|
|
|
// Yes, so adjust time-base.
|
|
mBrightnessElapsedTime += mElapsedTime;
|
|
|
|
// Adjust to Bounds.
|
|
while (mBrightnessElapsedTime > mDataBlock->mBrightnessTime) { mBrightnessElapsedTime -= mDataBlock->mBrightnessTime; };
|
|
|
|
// Scale Time.
|
|
F32 ScaledTime = mBrightnessElapsedTime * mBrightnessTimeScale;
|
|
|
|
// Calculate Position From.
|
|
PosFrom = mFloor(ScaledTime);
|
|
|
|
// Are we Lerping?
|
|
if (mDataBlock->mLerpBrightness)
|
|
{
|
|
// Yes, so calculate Position To.
|
|
PosTo = mCeil(ScaledTime);
|
|
|
|
// Calculate Lerp Factor.
|
|
LerpFactor = ScaledTime - PosFrom;
|
|
}
|
|
else
|
|
{
|
|
// No, so clamp Position.
|
|
PosTo = PosFrom;
|
|
|
|
// Clamp lerp factor.
|
|
LerpFactor = 0.0f;
|
|
}
|
|
|
|
// ********************************************
|
|
// Brightness Keys.
|
|
// ********************************************
|
|
if (mBrightnessKeysLength)
|
|
{
|
|
// No, so calculate Brightness.
|
|
mAnimationBrightness = GetLerpKey(mDataBlock->mBrightnessKeys, PosFrom, PosTo, mDataBlock->mMinBrightness, mDataBlock->mMaxBrightness, LerpFactor);
|
|
}
|
|
else
|
|
{
|
|
// Set to static brightness if we failed to set Brightness correctly.
|
|
mAnimationBrightness = mDataBlock->mBrightness;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No, so set to static Brightness.
|
|
mAnimationBrightness = mDataBlock->mBrightness;
|
|
}
|
|
|
|
// Adjust Colour by Brightness.
|
|
mAnimationColour *= ColorF( mAnimationBrightness, mAnimationBrightness, mAnimationBrightness );
|
|
|
|
|
|
// ********************************************
|
|
// Calculate Radius.
|
|
// ********************************************
|
|
|
|
// Animating Radius?
|
|
if (mDataBlock->mUseRadius)
|
|
{
|
|
U32 PosFrom;
|
|
U32 PosTo;
|
|
F32 LerpFactor;
|
|
|
|
// Yes, so adjust time-base.
|
|
mRadiusElapsedTime += mElapsedTime;
|
|
|
|
// Adjust to Bounds.
|
|
while (mRadiusElapsedTime > mDataBlock->mRadiusTime) { mRadiusElapsedTime -= mDataBlock->mRadiusTime; };
|
|
|
|
// Scale Time.
|
|
F32 ScaledTime = mRadiusElapsedTime * mRadiusTimeScale;
|
|
|
|
// Calculate Position From.
|
|
PosFrom = mFloor(ScaledTime);
|
|
|
|
// Are we Lerping?
|
|
if (mDataBlock->mLerpRadius)
|
|
{
|
|
// Yes, so calculate Position To.
|
|
PosTo = mCeil(ScaledTime);
|
|
|
|
// Calculate Lerp Factor.
|
|
LerpFactor = ScaledTime - PosFrom;
|
|
}
|
|
else
|
|
{
|
|
// No, so clamp Position.
|
|
PosTo = PosFrom;
|
|
|
|
// Clamp lerp factor.
|
|
LerpFactor = 0.0f;
|
|
}
|
|
|
|
// ********************************************
|
|
// Radius Keys.
|
|
// ********************************************
|
|
if (mRadiusKeysLength)
|
|
{
|
|
// No, so calculate Radius.
|
|
mAnimationRadius = GetLerpKey(mDataBlock->mRadiusKeys, PosFrom, PosTo, mDataBlock->mMinRadius, mDataBlock->mMaxRadius, LerpFactor);
|
|
}
|
|
else
|
|
{
|
|
// Set to static Radius if we failed to set Radius correctly.
|
|
mAnimationRadius = mDataBlock->mRadius;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No, so set to static Radius.
|
|
mAnimationRadius = mDataBlock->mRadius;
|
|
}
|
|
|
|
|
|
// ********************************************
|
|
// Calculate Rotation.
|
|
// ********************************************
|
|
|
|
// Animating Rotation?
|
|
if (mDataBlock->mUseRotation)
|
|
{
|
|
U32 PosFrom;
|
|
U32 PosTo;
|
|
F32 LerpFactor;
|
|
|
|
// Yes, so adjust time-base.
|
|
mRotationElapsedTime += mElapsedTime;
|
|
|
|
// Adjust to Bounds.
|
|
while (mRotationElapsedTime > mDataBlock->mRotationTime) { mRotationElapsedTime -= mDataBlock->mRotationTime; };
|
|
|
|
// Scale Time.
|
|
F32 ScaledTime = mRotationElapsedTime * mRotationTimeScale;
|
|
|
|
// Calculate Position From.
|
|
PosFrom = mFloor(ScaledTime);
|
|
|
|
// Are we Lerping?
|
|
if (mDataBlock->mLerpRotation)
|
|
{
|
|
// Yes, so calculate Position To.
|
|
PosTo = mCeil(ScaledTime);
|
|
|
|
// Calculate Lerp Factor.
|
|
LerpFactor = ScaledTime - PosFrom;
|
|
}
|
|
else
|
|
{
|
|
// No, so clamp Position.
|
|
PosTo = PosFrom;
|
|
|
|
// Clamp lerp factor.
|
|
LerpFactor = 0.0f;
|
|
}
|
|
|
|
// ********************************************
|
|
// Rotation Keys.
|
|
// ********************************************
|
|
if (mRotationKeysLength)
|
|
{
|
|
// No, so calculate Rotation.
|
|
mAnimationRotation = GetLerpKey(mDataBlock->mRotationKeys, PosFrom, PosTo, mDataBlock->mMinRotation, mDataBlock->mMaxRotation, LerpFactor);
|
|
}
|
|
else
|
|
{
|
|
// Set to static Rotation if we failed to set Rotation correctly.
|
|
mAnimationRotation = mDataBlock->mMinRotation;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No, so set to static Rotation.
|
|
mAnimationRotation = 0;
|
|
}
|
|
|
|
|
|
|
|
// ********************************************
|
|
// Calculate Offsets.
|
|
// ********************************************
|
|
|
|
// Are we attached?
|
|
if(mAttached)
|
|
calculateLightPosition();
|
|
|
|
// Reset Animation Offset.
|
|
mAnimationOffset.set(0, 0, 0);
|
|
|
|
// Are we animating Offsets?
|
|
if (mDataBlock->mUseOffsets)
|
|
{
|
|
U32 PosFrom;
|
|
U32 PosTo;
|
|
F32 LerpFactor;
|
|
|
|
// Yes, so adjust time-base.
|
|
mOffsetElapsedTime += mElapsedTime;
|
|
|
|
// Adjust to Bounds.
|
|
while (mOffsetElapsedTime > mDataBlock->mOffsetTime) { mOffsetElapsedTime -= mDataBlock->mOffsetTime; };
|
|
|
|
// Scale Time.
|
|
F32 ScaledTime = mOffsetElapsedTime * mOffsetTimeScale;
|
|
|
|
// Calculate Position From.
|
|
PosFrom = mFloor(ScaledTime);
|
|
|
|
// Are we Lerping?
|
|
if (mDataBlock->mLerpRadius)
|
|
{
|
|
// Yes, so calculate Position To.
|
|
PosTo = mCeil(ScaledTime);
|
|
|
|
// Calculate Lerp Factor.
|
|
LerpFactor = ScaledTime - PosFrom;
|
|
}
|
|
else
|
|
{
|
|
// No, so clamp Position.
|
|
PosTo = PosFrom;
|
|
|
|
// Clamp lerp factor.
|
|
LerpFactor = 0.0f;
|
|
}
|
|
|
|
// ********************************************
|
|
// Offset Keys.
|
|
// ********************************************
|
|
if (mOffsetKeysLength)
|
|
{
|
|
// No, so get static Position.
|
|
if (!mAttached) getRenderTransform().getColumn(3, &mAnimationPosition);
|
|
|
|
// Calculte Current Offset.
|
|
//
|
|
// NOTE:- We store this here in-case we need it for the flare position.
|
|
mAnimationOffset.x = GetLerpKey(mDataBlock->mOffsetKeys, PosFrom, PosTo, mDataBlock->mStartOffset.x, mDataBlock->mEndOffset.x, LerpFactor);
|
|
mAnimationOffset.y = GetLerpKey(mDataBlock->mOffsetKeys, PosFrom, PosTo, mDataBlock->mStartOffset.y, mDataBlock->mEndOffset.y, LerpFactor);
|
|
mAnimationOffset.z = GetLerpKey(mDataBlock->mOffsetKeys, PosFrom, PosTo, mDataBlock->mStartOffset.z, mDataBlock->mEndOffset.z, LerpFactor);
|
|
|
|
// Lerp to Offset Position.
|
|
mAnimationPosition += mAnimationOffset;
|
|
}
|
|
else
|
|
{
|
|
// Set to static Position if we failed to set Position correctly.
|
|
if (!mAttached) getRenderTransform().getColumn(3, &mAnimationPosition);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No, so set to static Position.
|
|
if (!mAttached) getRenderTransform().getColumn(3, &mAnimationPosition);
|
|
}
|
|
|
|
// Construct a world box to include light animation.
|
|
//
|
|
// NOTE:- We do this so that we always scope the object if we have it's
|
|
// potential volume in the view.
|
|
|
|
buildObjectBox();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::InitialiseAnimation(void)
|
|
{
|
|
// Enable Light.
|
|
mEnable = true;
|
|
|
|
// Basis Light.
|
|
mIconSize = 1.0f;
|
|
|
|
// Texture Handles.
|
|
mIconTextureHandle =
|
|
mFlareTextureHandle = NULL;
|
|
|
|
// Reset Flare Scale.
|
|
mFlareScale = 0.0f;
|
|
|
|
// Reset Animation.
|
|
ResetAnimation();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::ResetAnimation(void)
|
|
{
|
|
mAnimationOffset = Point3F(0.0, 0.0, 0.0);
|
|
|
|
|
|
// Check Animation Keys.
|
|
CheckAnimationKeys();
|
|
|
|
// Reset Times.
|
|
mColourElapsedTime =
|
|
mBrightnessElapsedTime =
|
|
mRadiusElapsedTime =
|
|
mOffsetElapsedTime =
|
|
mRotationElapsedTime = 0.0f;
|
|
|
|
// Reset Last Animation Time.
|
|
mLastAnimateTime = mLastRenderTime = F32(Platform::getVirtualMilliseconds());
|
|
|
|
// Exit if no datablock is ready.
|
|
if (!mDataBlock) return;
|
|
|
|
// Check Flare Details.
|
|
if (mDataBlock->mFarDistance < 0) mDataBlock->mFarDistance = 0.001f;
|
|
if (mDataBlock->mNearDistance >= mDataBlock->mFarDistance) mDataBlock->mNearDistance = mDataBlock->mFarDistance - 0.001f; // Stop Division by 0!
|
|
if (mDataBlock->mBlendMode > 2) mDataBlock->mBlendMode = 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
F32 fxLight::GetLerpKey(StringTableEntry Key, U32 PosFrom, U32 PosTo, F32 ValueFrom, F32 ValueTo, F32 Lerp)
|
|
{
|
|
// Get Key at Selected Positions.
|
|
char KeyFrameFrom = dToupper(*(Key + PosFrom)) - 65;
|
|
char KeyFrameTo = dToupper(*(Key + PosTo)) - 65;
|
|
|
|
// Calculate Range.
|
|
F32 ValueRange = (ValueTo-ValueFrom)/25.0f;
|
|
// Calculate Key Lerp.
|
|
F32 KeyFrameLerp = (KeyFrameTo - KeyFrameFrom) * Lerp;
|
|
|
|
// Return Lerped Value.
|
|
return ValueFrom + ((KeyFrameFrom + KeyFrameLerp) * ValueRange);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
U32 fxLight::CheckKeySyntax(StringTableEntry Key)
|
|
{
|
|
// Return problem.
|
|
if (!Key) return 0;
|
|
|
|
// Copy KeyCheck.
|
|
StringTableEntry KeyCheck = Key;
|
|
|
|
// Give benifit of doubt!
|
|
bool KeyValid = true;
|
|
|
|
// Check Key-frame validity.
|
|
do
|
|
{
|
|
if (dToupper(*KeyCheck) < 'A' && dToupper(*KeyCheck) > 'Z') KeyValid = false;
|
|
|
|
} while (*(KeyCheck++));
|
|
|
|
// Return result.
|
|
if (KeyValid)
|
|
return dStrlen(Key);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::CheckAnimationKeys(void)
|
|
{
|
|
if (!mDataBlock) return;
|
|
|
|
// Check Key Validities.
|
|
mRedKeysLength = CheckKeySyntax(mDataBlock->mRedKeys);
|
|
mGreenKeysLength = CheckKeySyntax(mDataBlock->mGreenKeys);
|
|
mBlueKeysLength = CheckKeySyntax(mDataBlock->mBlueKeys);
|
|
mBrightnessKeysLength = CheckKeySyntax(mDataBlock->mBrightnessKeys);
|
|
mRadiusKeysLength = CheckKeySyntax(mDataBlock->mRadiusKeys);
|
|
mOffsetKeysLength = CheckKeySyntax(mDataBlock->mOffsetKeys);
|
|
mRotationKeysLength = CheckKeySyntax(mDataBlock->mRotationKeys);
|
|
|
|
// Calculate Time Scales.
|
|
if (mDataBlock->mColourTime) mColourTimeScale = (mRedKeysLength-1) / mDataBlock->mColourTime;
|
|
if (mDataBlock->mBrightnessTime) mBrightnessTimeScale = (mBrightnessKeysLength-1) / mDataBlock->mBrightnessTime;
|
|
if (mDataBlock->mRadiusTime) mRadiusTimeScale = (mRadiusKeysLength-1) / mDataBlock->mRadiusTime;
|
|
if (mDataBlock->mOffsetTime) mOffsetTimeScale = (mOffsetKeysLength-1) / mDataBlock->mOffsetTime;
|
|
if (mDataBlock->mRotationTime) mRotationTimeScale = (mRotationKeysLength-1) / mDataBlock->mRotationTime;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool fxLight::onNewDataBlock(GameBaseData* dptr)
|
|
{
|
|
// Cast new Datablock.
|
|
mDataBlock = dynamic_cast<fxLightData*>(dptr);
|
|
// Check for problems.
|
|
if (!mDataBlock || !Parent::onNewDataBlock(dptr))return false;
|
|
|
|
// Reset Animation.
|
|
ResetAnimation();
|
|
|
|
// Set Flare Bitmap.
|
|
setFlareBitmap(mDataBlock->mFlareTextureName);
|
|
|
|
// Script-it.
|
|
scriptOnNewDataBlock();
|
|
|
|
// Return OK.
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool fxLight::onAdd()
|
|
{
|
|
// Add Parent.
|
|
if(!Parent::onAdd()) return(false);
|
|
|
|
buildObjectBox();
|
|
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
// Add to Scene.
|
|
addToScene();
|
|
mAddedToScene = true;
|
|
|
|
// Only on client.
|
|
if (isClientObject())
|
|
{
|
|
// Fetch Textures.
|
|
mIconTextureHandle = TextureHandle(FXLIGHTDBICONTEXTURE, BitmapTexture, true);
|
|
setFlareBitmap(mDataBlock->mFlareTextureName);
|
|
|
|
// Add object to Light Set.
|
|
Sim::getLightSet()->addObject(this);
|
|
}
|
|
|
|
// Return OK.
|
|
return(true);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::onRemove()
|
|
{
|
|
// Detach from Object.
|
|
//detachFromObject();
|
|
|
|
// Remove from Scene.
|
|
removeFromScene();
|
|
mAddedToScene = false;
|
|
|
|
// Only on client.
|
|
if (isClientObject())
|
|
{
|
|
// Remove Texture References.
|
|
mIconTextureHandle = mFlareTextureHandle = NULL;
|
|
|
|
// Remove object from Light Set.
|
|
Sim::getLightSet()->removeObject(this);
|
|
}
|
|
|
|
// Do Parent.
|
|
Parent::onRemove();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*void fxLight::onDeleteNotify(SimObject* Obj)
|
|
{
|
|
// Server?
|
|
if (isServerObject())
|
|
{
|
|
// Yes, so detach the server way!
|
|
detachFromObject();
|
|
}
|
|
else
|
|
{
|
|
// No, so do it manually (if needed).
|
|
if (mAttached) clearNotify(mpAttachedObject);
|
|
|
|
// Store it happening.
|
|
mAttached = false;
|
|
}
|
|
|
|
// Do Parent.
|
|
Parent::onDeleteNotify(Obj);
|
|
}*/
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::inspectPostApply()
|
|
{
|
|
// Reset Animation.
|
|
ResetAnimation();
|
|
|
|
// Set Parent.
|
|
Parent::inspectPostApply();
|
|
|
|
// Fetch Icon Texture.
|
|
if (isServerObject()) mIconTextureHandle = TextureHandle(FXLIGHTDBICONTEXTURE, BitmapTexture, true);
|
|
|
|
// Set Config Change Mask.
|
|
setMaskBits(fxLightConfigChangeMask);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool fxLight::prepRenderImage(SceneState* state, const U32 stateKey, const U32 startZone,
|
|
const bool modifyBaseZoneState)
|
|
{
|
|
// No need to render without a flare when not editing mission!
|
|
if (!mDataBlock->mFlareOn && !gEditingMission) return false;
|
|
|
|
// Return if last state.
|
|
if (isLastState(state, stateKey)) return false;
|
|
// Set Last State.
|
|
setLastState(state, stateKey);
|
|
|
|
// Is Object Rendered?
|
|
if (state->isObjectRendered(this))
|
|
{
|
|
// Yes, so get a SceneRenderImage.
|
|
SceneRenderImage* image = new SceneRenderImage;
|
|
// Populate it.
|
|
image->obj = this;
|
|
image->isTranslucent = true;
|
|
image->sortType = SceneRenderImage::EndSort;
|
|
// Insert it into the scene images.
|
|
state->insertRenderImage(image);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void fxLight::renderObject(SceneState* state, SceneRenderImage*)
|
|
{
|
|
if ( !mEnable || !mDataBlock->mLightOn ) return;
|
|
|
|
// Check we are in Canonical State.
|
|
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
|
|
|
// Cannot render without appropriate texture!
|
|
if (!mDataBlock->mFlareOn && !mIconTextureHandle) return;
|
|
if (mDataBlock->mFlareOn && !mFlareTextureHandle) return;
|
|
|
|
MatrixF ModelView;
|
|
MatrixF RXF;
|
|
Point4F Position;
|
|
F32 BBRadius;
|
|
|
|
// Calculate Elapsed Time.
|
|
F32 mElapsedTime = (F32)((Platform::getRealMilliseconds() - mLastRenderTime) / 1000.0f);
|
|
|
|
// 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, getAttachedObject()))
|
|
{
|
|
// 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 the GhostID of the object.
|
|
S32 GhostID = con->getGhostIndex(Obj);
|
|
// Send it to the client.
|
|
stream->writeRangedU32(U32(GhostID), 0, NetConnection::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, NetConnection::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();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|