📄 fxfoliagereplicator.cc
字号:
// Reset Frame Serial.
pFoliageItem->LastFrameSerialID = 0;
// Reset Transform.
pFoliageItem->Transform.identity();
// Set Position.
pFoliageItem->Transform.setColumn(3, FoliagePosition);
// Are we fixing size @ max?
if (mFieldData.mFixSizeToMax)
{
// Yes, so set height maximum height.
pFoliageItem->Height = mFieldData.mMaxHeight;
// Is the Aspect Ratio Fixed?
if (mFieldData.mFixAspectRatio)
// Yes, so lock to height.
pFoliageItem->Width = pFoliageItem->Height;
else
// No, so set width to maximum width.
pFoliageItem->Width = mFieldData.mMaxWidth;
}
else
{
// No, so choose a new Scale.
pFoliageItem->Height = RandomGen.randF(mFieldData.mMinHeight, mFieldData.mMaxHeight);
// Is the Aspect Ratio Fixed?
if (mFieldData.mFixAspectRatio)
// Yes, so lock to height.
pFoliageItem->Width = pFoliageItem->Height;
else
// No, so choose a random width.
pFoliageItem->Width = RandomGen.randF(mFieldData.mMinWidth, mFieldData.mMaxWidth);
}
// Are we randomly flipping horizontally?
if (mFieldData.mRandomFlip)
// Yes, so choose a random flip for this object.
pFoliageItem->Flipped = (RandomGen.randF(0, 1000) < 500.0f) ? false : true;
else
// No, so turn-off flipping.
pFoliageItem->Flipped = false;
// Calculate Foliage Item World Box.
// NOTE:- We generate a psuedo-volume here. It's basically the volume to which the
// plane can move and this includes swaying!
//
// Is Sway On?
if (mFieldData.mSwayOn)
{
// Yes, so take swaying into account...
pFoliageItem->FoliageBox.min = FoliagePosition +
Point3F(-pFoliageItem->Width / 2.0f - mFieldData.mSwayMagnitudeSide,
-0.5f - mFieldData.mSwayMagnitudeFront,
pFoliageItem->Height );
pFoliageItem->FoliageBox.max = FoliagePosition +
Point3F(+pFoliageItem->Width / 2.0f + mFieldData.mSwayMagnitudeSide,
+0.5f + mFieldData.mSwayMagnitudeFront,
pFoliageItem->Height );
}
else
{
// No, so give it a minimum volume...
pFoliageItem->FoliageBox.min = FoliagePosition +
Point3F(-pFoliageItem->Width / 2.0f,
-0.5f,
pFoliageItem->Height );
pFoliageItem->FoliageBox.max = FoliagePosition +
Point3F(+pFoliageItem->Width / 2.0f,
+0.5f,
pFoliageItem->Height );
}
// Monitor the total volume.
MinPoint.setMin( pFoliageItem->FoliageBox.min - getRenderPosition() );
MaxPoint.setMax( pFoliageItem->FoliageBox.max - getRenderPosition() );
// Store Shape in Replicated Shapes Vector.
mReplicatedFoliage.push_back(pFoliageItem);
// Increase Foliage Count.
mCurrentFoliageCount++;
}
// Is Lighting On?
if (mFieldData.mLightOn)
{
// Yes, so step through Foliage.
for (U32 idx = 0; idx < mCurrentFoliageCount; idx++)
{
fxFoliageItem* pFoliageItem;
// Fetch the Foliage Item.
pFoliageItem = mReplicatedFoliage[idx];
// Do we have an item?
if (pFoliageItem)
{
// Yes, so are lights syncronised?
if (mFieldData.mLightSync)
{
// Yes, so reset Global Light phase.
mGlobalLightPhase = 0.0f;
// Set Global Light Time Ratio.
mGlobalLightTimeRatio = 719.0f / mFieldData.mLightTime;
}
else
{
// No, so choose a random Light phase.
pFoliageItem->LightPhase = RandomGen.randF(0, 719.0f);
// Set Light Time Ratio.
pFoliageItem->LightTimeRatio = 719.0f / mFieldData.mLightTime;
}
}
}
}
// Is Swaying Enabled?
if (mFieldData.mSwayOn)
{
// Yes, so step through Foliage.
for (U32 idx = 0; idx < mCurrentFoliageCount; idx++)
{
fxFoliageItem* pFoliageItem;
// Fetch the Foliage Item.
pFoliageItem = mReplicatedFoliage[idx];
// Do we have an item?
if (pFoliageItem)
{
// Are we using Sway Sync?
if (mFieldData.mSwaySync)
{
// Yes, so reset Global Sway phase.
mGlobalSwayPhase = 0.0f;
// Set Global Sway Time Ratio.
mGlobalSwayTimeRatio = 719.0f / RandomGen.randF(mFieldData.mMinSwayTime, mFieldData.mMaxSwayTime);
}
else
{
// No, so choose a random Sway phase.
pFoliageItem->SwayPhase = RandomGen.randF(0, 719.0f);
// Set to random Sway Time.
pFoliageItem->SwayTimeRatio = 719.0f / RandomGen.randF(mFieldData.mMinSwayTime, mFieldData.mMaxSwayTime);
}
}
}
}
// Update our Object Volume.
mObjBox.min.set(MinPoint);
mObjBox.max.set(MaxPoint);
setTransform(mObjToWorld);
// ----------------------------------------------------------------------------------------------------------------------
// Step 3.
// ----------------------------------------------------------------------------------------------------------------------
// Reset Next Allocated Node to Stack base.
mNextAllocatedNodeIdx = 0;
// Allocate a new Node.
fxFoliageQuadrantNode* pNewNode = new fxFoliageQuadrantNode;
// Store it in the Quad-tree.
mFoliageQuadTree.push_back(pNewNode);
// Populate Initial Node.
//
// Set Start Level.
pNewNode->Level = mQuadTreeLevels;
// Calculate Total Foliage Area.
pNewNode->QuadrantBox = getWorldBox();
// Reset Quadrant child nodes.
pNewNode->QuadrantChildNode[0] =
pNewNode->QuadrantChildNode[1] =
pNewNode->QuadrantChildNode[2] =
pNewNode->QuadrantChildNode[3] = NULL;
// Create our initial cull list with *all* billboards into.
fxFoliageCulledList CullList;
CullList.mCulledObjectSet = mReplicatedFoliage;
// Move to next node Index.
mNextAllocatedNodeIdx++;
// Let's start this thing going by recursing it's children.
ProcessNodeChildren(pNewNode, &CullList);
// Calculate Elapsed Time and take new Timestamp.
F32 ElapsedTime = (Platform::getRealMilliseconds() - mStartCreationTime) * 0.001f;
// Console Output.
Con::printf("fxFoliageReplicator - Lev: %d PotNodes: %d Used: %d Objs: %d Time: %0.4fs.",
mQuadTreeLevels,
mPotentialFoliageNodes,
mNextAllocatedNodeIdx-1,
mBillboardsAcquired,
ElapsedTime);
// Dump (*very*) approximate allocated memory.
F32 MemoryAllocated = (mNextAllocatedNodeIdx-1) * sizeof(fxFoliageQuadrantNode);
MemoryAllocated += mCurrentFoliageCount * sizeof(fxFoliageItem);
MemoryAllocated += mCurrentFoliageCount * sizeof(fxFoliageItem*);
Con::printf("fxFoliageReplicator - Approx. %0.2fMb allocated.", MemoryAllocated / 1048576.0f);
// ----------------------------------------------------------------------------------------------------------------------
// Take first Timestamp.
mLastRenderTime = Platform::getVirtualMilliseconds();
}
//------------------------------------------------------------------------------
Box3F fxFoliageReplicator::FetchQuadrant(Box3F Box, U32 Quadrant)
{
Box3F QuadrantBox;
// Select Quadrant.
switch(Quadrant)
{
// UL.
case 0:
QuadrantBox.min = Box.min + Point3F(0, Box.len_y()/2, 0);
QuadrantBox.max = QuadrantBox.min + Point3F(Box.len_x()/2, Box.len_y()/2, Box.len_z());
break;
// UR.
case 1:
QuadrantBox.min = Box.min + Point3F(Box.len_x()/2, Box.len_y()/2, 0);
QuadrantBox.max = QuadrantBox.min + Point3F(Box.len_x()/2, Box.len_y()/2, Box.len_z());
break;
// LL.
case 2:
QuadrantBox.min = Box.min;
QuadrantBox.max = QuadrantBox.min + Point3F(Box.len_x()/2, Box.len_y()/2, Box.len_z());
break;
// LR.
case 3:
QuadrantBox.min = Box.min + Point3F(Box.len_x()/2, 0, 0);
QuadrantBox.max = QuadrantBox.min + Point3F(Box.len_x()/2, Box.len_y()/2, Box.len_z());
break;
default:
return Box;
}
return QuadrantBox;
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::ProcessNodeChildren(fxFoliageQuadrantNode* pParentNode, fxFoliageCulledList* pCullList)
{
// ---------------------------------------------------------------
// Split Node into Quadrants and Process each.
// ---------------------------------------------------------------
// Process All Quadrants (UL/UR/LL/LR).
for (U32 q = 0; q < 4; q++)
ProcessQuadrant(pParentNode, pCullList, q);
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::ProcessQuadrant(fxFoliageQuadrantNode* pParentNode, fxFoliageCulledList* pCullList, U32 Quadrant)
{
// Fetch Quadrant Box.
const Box3F QuadrantBox = FetchQuadrant(pParentNode->QuadrantBox, Quadrant);
// Create our new Cull List.
fxFoliageCulledList CullList(QuadrantBox, pCullList);
// Did we get any objects?
if (CullList.GetListCount() > 0)
{
// Yes, so allocate a new Node.
fxFoliageQuadrantNode* pNewNode = new fxFoliageQuadrantNode;
// Store it in the Quad-tree.
mFoliageQuadTree.push_back(pNewNode);
// Move to next node Index.
mNextAllocatedNodeIdx++;
// Populate Quadrant Node.
//
// Next Sub-level.
pNewNode->Level = pParentNode->Level - 1;
// Calculate Quadrant Box.
pNewNode->QuadrantBox = QuadrantBox;
// Reset Child Nodes.
pNewNode->QuadrantChildNode[0] =
pNewNode->QuadrantChildNode[1] =
pNewNode->QuadrantChildNode[2] =
pNewNode->QuadrantChildNode[3] = NULL;
// Put a reference in parent.
pParentNode->QuadrantChildNode[Quadrant] = pNewNode;
// If we're not at sub-level 0 then process this nodes children.
if (pNewNode->Level != 0) ProcessNodeChildren(pNewNode, &CullList);
// If we've reached sub-level 0 then store Cull List (for rendering).
if (pNewNode->Level == 0)
{
// Store the render list from our culled object set.
pNewNode->RenderList = CullList.mCulledObjectSet;
// Keep track of the total billboard acquired.
mBillboardsAcquired += CullList.GetListCount();
}
}
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::SyncFoliageReplicators(void)
{
// Check Host.
AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!")
// 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);
// Set Foliage Replication Mask.
if (Replicator->isServerObject())
{
Con::printf("fxFoliageReplicator - Restarting fxFoliageReplicator Object...");
Replicator->setMaskBits(FoliageReplicationMask);
}
}
// Info ...
Con::printf("fxFoliageReplicator - Client Foliage Sync has completed.");
}
//------------------------------------------------------------------------------
void fxFoliageReplicator::DestroyFoliage(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -