📄 fxfoliagereplicator.cc
字号:
{
// Check Host.
AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!")
// Destroy Quad-tree.
mPotentialFoliageNodes = 0;
// Reset Billboards Acquired.
mBillboardsAcquired = 0;
// Finish if we didn't create any shapes.
if (mCurrentFoliageCount == 0) return;
// Remove shapes.
for (U32 idx = 0; idx < mCurrentFoliageCount; idx++)
{
fxFoliageItem* pFoliageItem;
// Fetch the Foliage Item.
pFoliageItem = mReplicatedFoliage[idx];
// Delete Shape.
if (pFoliageItem) delete pFoliageItem;
}
// Let's remove the Quad-Tree allocations.
for ( Vector<fxFoliageQuadrantNode*>::iterator QuadNodeItr = mFoliageQuadTree.begin();
QuadNodeItr != mFoliageQuadTree.end();
QuadNodeItr++ )
{
// Remove the node.
delete *QuadNodeItr;
}
// Clear the Foliage Quad-Tree Vector.
mFoliageQuadTree.clear();
// Clear the Replicated Foliage Vector.
mReplicatedFoliage.clear();
// Clear the Frustum Render Set Vector.
mFrustumRenderSet.mVisObjectSet.clear();
// Reset Foliage Count.
mCurrentFoliageCount = 0;
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::StartUp(void)
{
// Flag, Client Replication Started.
mClientReplicationStarted = true;
// Create foliage on Client.
if (isClientObject()) CreateFoliage();
}
//------------------------------------------------------------------------------
bool fxFoliageReplicator::onAdd()
{
if(!Parent::onAdd()) return(false);
// Add the Replicator to the Replicator Set.
dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"))->addObject(this);
// Set Default 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();
// Set the Render Transform.
setRenderTransform(mObjToWorld);
// Add to Scene.
addToScene();
mAddedToScene = true;
// Are we on the client?
if ( isClientObject() )
{
// Yes, so load foliage texture.
mFieldData.mFoliageTexture = TextureHandle( mFieldData.mFoliageFile, MeshTexture );
// If we are in the editor then we can manually startup replication.
if (gEditingMission) mClientReplicationStarted = true;
}
// Return OK.
return(true);
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::onRemove()
{
// Remove the Replicator from the Replicator Set.
dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"))->removeObject(this);
// Remove from Scene.
removeFromScene();
mAddedToScene = false;
// Are we on the Client?
if (isClientObject())
{
// Yes, so destroy Foliage.
DestroyFoliage();
// Remove Texture.
mFieldData.mFoliageTexture = NULL;
}
// Do Parent.
Parent::onRemove();
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::inspectPostApply()
{
// Set Parent.
Parent::inspectPostApply();
// Set Foliage Replication Mask (this object only).
setMaskBits(FoliageReplicationMask);
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::onEditorEnable()
{
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::onEditorDisable()
{
}
//------------------------------------------------------------------------------
ConsoleFunction(StartFoliageReplication, void, 1, 1, "StartFoliageReplication()")
{
// Find the Replicator Set.
SimSet *fxFoliageSet = dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"));
// Return if Error.
if (!fxFoliageSet)
{
// Console Warning.
Con::warnf("fxFoliageReplicator - Cannot locate the 'fxFoliageSet', this is bad!");
// Return here.
return;
}
// Parse Replication Object(s).
for (SimSetIterator itr(fxFoliageSet); *itr; ++itr)
{
// Fetch the Replicator Object.
fxFoliageReplicator* Replicator = static_cast<fxFoliageReplicator*>(*itr);
// Start Client Objects Only.
if (Replicator->isClientObject()) Replicator->StartUp();
}
// Info ...
Con::printf("fxFoliageReplicator - Client Foliage Replication Startup is complete.");
}
//------------------------------------------------------------------------------
bool fxFoliageReplicator::prepRenderImage(SceneState* state, const U32 stateKey, const U32 startZone,
const bool modifyBaseZoneState)
{
// 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->sortType = SceneRenderImage::Point;
image->isTranslucent = true;
image->poly[0] = getPosition();
// Insert it into the scene images.
state->insertRenderImage(image);
}
return false;
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::renderObject(SceneState* state, SceneRenderImage*)
{
// Check we are in Canonical State.
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
// Calculate Elapsed Time and take new Timestamp.
S32 Time = Platform::getVirtualMilliseconds();
F32 ElapsedTime = (Time - mLastRenderTime) * 0.001f;
mLastRenderTime = Time;
// Setup out the Projection Matrix/Viewport.
RectI viewport;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
dglGetViewport(&viewport);
state->setupBaseProjection();
// Draw Placement Area (if needed and Editing Mission).
if (gEditingMission && mFieldData.mShowPlacementArea)
{
// Setup our rendering state.
glPushMatrix();
dglMultMatrix(&getTransform());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// Do we need to draw the Inner Radius?
if (mFieldData.mInnerRadiusX || mFieldData.mInnerRadiusY)
{
// Yes, so draw Inner Radius.
glBegin(GL_TRIANGLE_STRIP);
for (U32 Angle = mCreationAreaAngle; Angle < (mCreationAreaAngle+360); Angle++)
{
F32 XPos, YPos;
// Calculate Position.
XPos = mFieldData.mInnerRadiusX * mCos(mDegToRad(-(F32)Angle));
YPos = mFieldData.mInnerRadiusY * mSin(mDegToRad(-(F32)Angle));
// Set Colour.
glColor4f( mFieldData.mPlaceAreaColour.red,
mFieldData.mPlaceAreaColour.green,
mFieldData.mPlaceAreaColour.blue,
AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
// Draw Arc Line.
glVertex3f( XPos, YPos, -(F32)mFieldData.mPlacementBandHeight/2.0f);
glVertex3f( XPos, YPos, +(F32)mFieldData.mPlacementBandHeight/2.0f);
}
glEnd();
}
// Do we need to draw the Outer Radius?
if (mFieldData.mOuterRadiusX || mFieldData.mOuterRadiusY)
{
// Yes, so draw Outer Radius.
glBegin(GL_TRIANGLE_STRIP);
for (U32 Angle = mCreationAreaAngle; Angle < (mCreationAreaAngle+360); Angle++)
{
F32 XPos, YPos;
// Calculate Position.
XPos = mFieldData.mOuterRadiusX * mCos(mDegToRad(-(F32)Angle));
YPos = mFieldData.mOuterRadiusY * mSin(mDegToRad(-(F32)Angle));
// Set Colour.
glColor4f( mFieldData.mPlaceAreaColour.red,
mFieldData.mPlaceAreaColour.green,
mFieldData.mPlaceAreaColour.blue,
AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
// Draw Arc Line.
glVertex3f( XPos, YPos, -(F32)mFieldData.mPlacementBandHeight/2.0f);
glVertex3f( XPos, YPos, +(F32)mFieldData.mPlacementBandHeight/2.0f);
}
glEnd();
}
// Restore rendering state.
glDisable(GL_BLEND);
glPopMatrix();
// Animate Area Selection.
mCreationAreaAngle = (U32)(mCreationAreaAngle + (1000 * ElapsedTime));
mCreationAreaAngle = mCreationAreaAngle % 360;
}
// Draw Foliage.
if (!mFieldData.mHideFoliage && mCurrentFoliageCount)
{
// Calculate some constants.
const F32 ClippedViewDistance = mFieldData.mViewDistance;
const F32 MinimumViewDistance = mFieldData.mViewClosest - mFieldData.mFadeOutRegion;
const F32 MaximumViewDistance = ClippedViewDistance + mFieldData.mFadeInRegion;
const F32 LuminanceMidPoint = (mFieldData.mMinLuminance + mFieldData.mMaxLuminance) / 2.0f;
const F32 LuminanceMagnitude = mFieldData.mMaxLuminance - LuminanceMidPoint;
// Billboard Details.
MatrixF ModelView;
Point4F Position;
const Point4F XRotation(1,0,0,0);
const Point4F YRotation(0,1,0,0);
Point4F ZRotation;
F32 LeftTexPos;
F32 RightTexPos;
// Sway Luminance.
F32 Luminance = 1.0f;
// Reset Sway Offsets.
F32 SwayOffsetX = 0.0f;
F32 SwayOffsetY = 0.0f;
// Is Swaying On and *in* Sync?
if (mFieldData.mSwayOn && mFieldData.mSwaySync)
{
// Yes, so calculate Global Sway Offset.
SwayOffsetX = mFieldData.mSwayMagnitudeSide * mCosTable[(U32)mGlobalSwayPhase];
SwayOffsetY = mFieldData.mSwayMagnitudeFront * mSinTable[(U32)mGlobalSwayPhase];
// Animate Global Sway Phase (Modulus).
mGlobalSwayPhase = mGlobalSwayPhase + (mGlobalSwayTimeRatio * ElapsedTime);
if (mGlobalSwayPhase >= 720.0f) mGlobalSwayPhase -= 720.0f;
}
// Is Light On and *in* Sync?
if (mFieldData.mLightOn && mFieldData.mLightSync)
{
// Yes, so calculate Global Light Luminance.
Luminance = LuminanceMidPoint + LuminanceMagnitude * mCosTable[(U32)mGlobalLightPhase];
// Animate Global Light Phase (Modulus).
mGlobalLightPhase = mGlobalLightPhase + (mGlobalLightTimeRatio * ElapsedTime);
if (mGlobalLightPhase >= 720.0f) mGlobalLightPhase -= 720.0f;
}
// Are we using culling?
if (mFieldData.mUseCulling)
{
// Yes, so clear the Render Object Set.
mFrustumRenderSet.mVisObjectSet.clear();
// Calculate nearest Clipping Far-Plane.
//
// NOTE:- Here we want the nearest plane to which we want to clip.
// This will be either the 'mViewDistance'/'mFadeInRegion' or the
// frustum FarPlane.
F32 FarClipPlane = getMin((F32)state->getFarPlane(), mFieldData.mViewDistance + mFieldData.mFadeInRegion);
// Setup the Clip-Planes.
mFrustumRenderSet.SetupClipPlanes(state, FarClipPlane);
if ( mFieldData.mUseDebugInfo)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
// Compile the Visible Set.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -