mirror of
https://github.com/tribes2/engine.git
synced 2026-03-23 22:29:14 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
208
ai/graphBuildLOS.cc
Normal file
208
ai/graphBuildLOS.cc
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "ai/graph.h"
|
||||
|
||||
#define MuzzleHt 0.82f
|
||||
#define HeadHt 2.2f
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
// Want to see stuff on screen, so we scamble node order (bunch of random swaps)
|
||||
static void makeScrambler(Vector<S32>& vec, S32 size)
|
||||
{
|
||||
S32 i, i1, i2, count = size * 10;
|
||||
|
||||
for (i = 0, vec.setSize(size); i < size; i++)
|
||||
vec[i] = i;
|
||||
|
||||
while (--count >= 0)
|
||||
{
|
||||
S32 t = vec[i1 = (gRandGen.randI()&0xFFFFFF) % size];
|
||||
vec[i1] = vec[i2 = (gRandGen.randI()&0xFFFFFF) % size];
|
||||
vec[i2] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static RayInfo sColl;
|
||||
static bool haveLOS(Point3F src, Point3F dst, F32 above)
|
||||
{
|
||||
static const U32 sMask = InteriorObjectType|TerrainObjectType;
|
||||
src.z += above;
|
||||
dst.z += above;
|
||||
return !gServerContainer.castRay(src, dst, sMask, &sColl);
|
||||
}
|
||||
|
||||
class MakeLOSEntries : public GraphSearch
|
||||
{
|
||||
const GraphNodeList& mList;
|
||||
LOSXRefTable& mLOSTable;
|
||||
S32 mCurrent;
|
||||
GraphNode * mFromNode;
|
||||
Point3F mFromLoc;
|
||||
F32 mThreshDist;
|
||||
U32 mStartTime, mSaveMS;
|
||||
S32 mLowButNotHigh;
|
||||
S32 mFromIndex;
|
||||
Vector<S32> mScramble;
|
||||
S32 mLOSCalls;
|
||||
|
||||
public:
|
||||
Vector<LineSegment> mRenderSegs;
|
||||
Point3F mViewLoc;
|
||||
|
||||
protected:
|
||||
// virtuals-
|
||||
void onQExtraction();
|
||||
F32 getEdgeTime(const GraphEdge*);
|
||||
bool earlyOut();
|
||||
|
||||
public:
|
||||
MakeLOSEntries(const GraphNodeList& list, LOSXRefTable& xRef, Point3F view);
|
||||
|
||||
bool isDone() const {return mCurrent>=mList.size();}
|
||||
U32 elapsedTime() const {return Platform::getRealMilliseconds()-mSaveMS;}
|
||||
S32 lowNotHigh() const {return mLowButNotHigh;}
|
||||
S32 numLOSCalls() const {return mLOSCalls;}
|
||||
bool nextOneReady();
|
||||
void workAWhile();
|
||||
};
|
||||
|
||||
MakeLOSEntries::MakeLOSEntries(const GraphNodeList& list, LOSXRefTable& los, Point3F v)
|
||||
: mList(list), mLOSTable(los), mViewLoc(v)
|
||||
{
|
||||
S32 N = list.size();
|
||||
mLOSTable.setDims(N * (N + 1) >> 1, 2); // Alloc our 2-bit table
|
||||
mViewLoc.set(-44,-31,90);
|
||||
mThreshDist = 700.0f;
|
||||
mCurrent = -1;
|
||||
mSaveMS = Platform::getRealMilliseconds();
|
||||
mLOSCalls = mLowButNotHigh = 0;
|
||||
makeScrambler(mScramble, list.size());
|
||||
}
|
||||
|
||||
// Run LOS from base to this node. We truncate the search at a certain path distance,
|
||||
// which should make sense in all but a few cases that we should be aware of. It
|
||||
// will make the search quicker for most worlds though.
|
||||
void MakeLOSEntries::onQExtraction()
|
||||
{
|
||||
S32 toIndex = extractedNode()->getIndex();
|
||||
|
||||
if (mFromIndex < toIndex) {
|
||||
//==> Path distance really not right- just need a better local query.
|
||||
if (distSoFar() < mThreshDist) {
|
||||
Point3F toLoc = extractedNode()->location();
|
||||
bool losLow = haveLOS(mFromLoc, toLoc, MuzzleHt);
|
||||
bool losHigh = haveLOS(mFromLoc, toLoc, HeadHt);
|
||||
U32 tabEntry = LOSXRefTable::Hidden;
|
||||
|
||||
// Speed tracking
|
||||
mLOSCalls += 2;
|
||||
|
||||
// These are strange- add to list of warning log for graph maker
|
||||
mLowButNotHigh += (losLow && !losHigh);
|
||||
|
||||
// Crude calc of entry for now-
|
||||
if(losLow)
|
||||
tabEntry = LOSXRefTable::FullLOS;
|
||||
else if (losHigh)
|
||||
tabEntry = LOSXRefTable::MinorLOS;
|
||||
|
||||
// Enter into table-
|
||||
mLOSTable.setEntry(mFromIndex, toIndex, tabEntry);
|
||||
|
||||
// Stuff to render-
|
||||
if (mRenderSegs.size() < 600) {
|
||||
LineSegment segment(mFromLoc, tabEntry ? toLoc : sColl.point);
|
||||
if (segment.distance(mViewLoc) < 120.0f)
|
||||
mRenderSegs.push_back(segment);
|
||||
}
|
||||
}
|
||||
else // outside
|
||||
setDone();
|
||||
}
|
||||
}
|
||||
|
||||
// Virtual - this will cause graph time to equal distance.
|
||||
F32 MakeLOSEntries::getEdgeTime(const GraphEdge * edge)
|
||||
{
|
||||
return edge->mDist;
|
||||
}
|
||||
|
||||
// Prepare a new search. Note mCurrent constructs at -1 for proper entry.
|
||||
bool MakeLOSEntries::nextOneReady()
|
||||
{
|
||||
if (++mCurrent < mList.size()) {
|
||||
mFromNode = mList[mScramble[mCurrent]];
|
||||
mFromLoc = mFromNode->location();
|
||||
mFromIndex = mFromNode->getIndex();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define MillisecondWorkShift 90
|
||||
|
||||
// Virtual - runSearch() can be stopped in the middle.
|
||||
bool MakeLOSEntries::earlyOut()
|
||||
{
|
||||
U32 timeElapsed = (Platform::getRealMilliseconds() - mStartTime);
|
||||
return (timeElapsed > MillisecondWorkShift);
|
||||
}
|
||||
|
||||
void MakeLOSEntries::workAWhile()
|
||||
{
|
||||
mStartTime = Platform::getRealMilliseconds();
|
||||
|
||||
while (!isDone() && !earlyOut())
|
||||
if (inProgress())
|
||||
runSearch(mFromNode);
|
||||
else if (nextOneReady())
|
||||
runSearch(mFromNode);
|
||||
|
||||
NavigationGraph::sProcessPercent = F32(mCurrent) / F32(mList.size());
|
||||
}
|
||||
|
||||
bool NavigationGraph::prepLOSTableWork(Point3F viewLoc)
|
||||
{
|
||||
if (mTableBuilder) {
|
||||
delete mTableBuilder;
|
||||
mTableBuilder = NULL;
|
||||
}
|
||||
|
||||
mTableBuilder = new MakeLOSEntries(mNonTransient, mLOSXRef, viewLoc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This gets called repeatedly until the table is built. Idea here is to slice
|
||||
// the process so that some rendering can occur during this lengthy process.
|
||||
bool NavigationGraph::makeLOSTableEntries()
|
||||
{
|
||||
MakeLOSEntries * makeEntries = dynamic_cast<MakeLOSEntries*>(mTableBuilder);
|
||||
AssertFatal(makeEntries, "Graph preprocess: prepLOSTable() needed");
|
||||
|
||||
makeEntries->workAWhile();
|
||||
|
||||
mRenderThese = makeEntries->mRenderSegs;
|
||||
makeEntries->mRenderSegs.clear();
|
||||
|
||||
if (makeEntries->isDone()) {
|
||||
clearRenderSegs();
|
||||
Con::printf("Total table size = %d", mLOSXRef.numBytes());
|
||||
Con::printf("Performed %d LOS calls", makeEntries->numLOSCalls());
|
||||
Con::printf("Elapsed time = %d milliseconds", makeEntries->elapsedTime());
|
||||
if (makeEntries->lowNotHigh())
|
||||
Con::printf("%d Low-not-high entries found", makeEntries->lowNotHigh());
|
||||
delete mTableBuilder;
|
||||
mTableBuilder = NULL;
|
||||
// Convert data to better hasher-
|
||||
makeLOSHashTable();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue