mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
navmesh
cache tiles data if keep intermediate is on (we only need to cache the results of recast) fix tile generation (again) Add !m_geo check so that buildTile can regen the geometry needed to build the tile again.
This commit is contained in:
parent
1f21efc9e8
commit
30b9502e90
|
|
@ -40,6 +40,7 @@
|
|||
#include "math/mathIO.h"
|
||||
|
||||
#include "core/stream/fileStream.h"
|
||||
#include "T3D/assets/LevelAsset.h"
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
|
|
@ -365,7 +366,7 @@ bool NavMesh::onAdd()
|
|||
if(gEditingMission || mAlwaysRender)
|
||||
{
|
||||
mNetFlags.set(Ghostable);
|
||||
if(isClientObject())
|
||||
if (isClientObject())
|
||||
renderToDrawer();
|
||||
}
|
||||
|
||||
|
|
@ -740,6 +741,27 @@ void NavMesh::inspectPostApply()
|
|||
cancelBuild();
|
||||
}
|
||||
|
||||
void NavMesh::createNewFile()
|
||||
{
|
||||
// We need to construct a default file name
|
||||
String levelAssetId(Con::getVariable("$Client::LevelAsset"));
|
||||
|
||||
LevelAsset* levelAsset;
|
||||
if (!Sim::findObject(levelAssetId.c_str(), levelAsset))
|
||||
{
|
||||
Con::errorf("NavMesh::createNewFile() - Unable to find current level's LevelAsset. Unable to construct NavMesh filePath");
|
||||
return;
|
||||
}
|
||||
|
||||
Torque::Path basePath(levelAsset->getNavmeshPath());
|
||||
|
||||
if (basePath.isEmpty())
|
||||
basePath = (Torque::Path)(levelAsset->getLevelPath());
|
||||
|
||||
String fileName = Torque::FS::MakeUniquePath(basePath.getPath(), basePath.getFileName(), "nav");
|
||||
mFileName = StringTable->insert(fileName.c_str());
|
||||
}
|
||||
|
||||
void NavMesh::updateConfig()
|
||||
{
|
||||
//// Build rcConfig object from our console members.
|
||||
|
|
@ -792,36 +814,6 @@ void NavMesh::updateTiles(bool dirty)
|
|||
if(!isProperlyAdded())
|
||||
return;
|
||||
|
||||
// this is just here so that load regens the mesh, we should be saving it out.
|
||||
if (!m_geo)
|
||||
{
|
||||
Box3F worldBox = getWorldBox();
|
||||
SceneContainer::CallbackInfo info;
|
||||
info.context = PLC_Navigation;
|
||||
info.boundingBox = worldBox;
|
||||
m_geo = new RecastPolyList;
|
||||
info.polyList = m_geo;
|
||||
info.key = this;
|
||||
getContainer()->findObjects(worldBox, StaticObjectType | DynamicShapeObjectType, buildCallback, &info);
|
||||
|
||||
// Parse water objects into the same list, but remember how much geometry was /not/ water.
|
||||
U32 nonWaterVertCount = m_geo->getVertCount();
|
||||
U32 nonWaterTriCount = m_geo->getTriCount();
|
||||
if (mWaterMethod != Ignore)
|
||||
{
|
||||
getContainer()->findObjects(worldBox, WaterObjectType, buildCallback, &info);
|
||||
}
|
||||
|
||||
// Check for no geometry.
|
||||
if (!m_geo->getVertCount())
|
||||
{
|
||||
m_geo->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_geo->getChunkyMesh();
|
||||
}
|
||||
|
||||
mTiles.clear();
|
||||
mDirtyTiles.clear();
|
||||
|
||||
|
|
@ -834,7 +826,7 @@ void NavMesh::updateTiles(bool dirty)
|
|||
const F32* bmax = box.maxExtents;
|
||||
S32 gw = 0, gh = 0;
|
||||
rcCalcGridSize(bmin, bmax, mCellSize, &gw, &gh);
|
||||
const S32 ts = (S32)mTileSize;
|
||||
const S32 ts = (S32)(mTileSize / mCellSize);
|
||||
const S32 tw = (gw + ts - 1) / ts;
|
||||
const S32 th = (gh + ts - 1) / ts;
|
||||
const F32 tcs = mTileSize;
|
||||
|
|
@ -872,12 +864,43 @@ void NavMesh::processTick(const Move *move)
|
|||
void NavMesh::buildNextTile()
|
||||
{
|
||||
PROFILE_SCOPE(NavMesh_buildNextTile);
|
||||
|
||||
// this is just here so that load regens the mesh, also buildTile needs to regen incase geometry has changed.
|
||||
if (!m_geo)
|
||||
{
|
||||
Box3F worldBox = getWorldBox();
|
||||
SceneContainer::CallbackInfo info;
|
||||
info.context = PLC_Navigation;
|
||||
info.boundingBox = worldBox;
|
||||
m_geo = new RecastPolyList;
|
||||
info.polyList = m_geo;
|
||||
info.key = this;
|
||||
getContainer()->findObjects(worldBox, StaticObjectType | DynamicShapeObjectType, buildCallback, &info);
|
||||
|
||||
// Parse water objects into the same list, but remember how much geometry was /not/ water.
|
||||
U32 nonWaterVertCount = m_geo->getVertCount();
|
||||
U32 nonWaterTriCount = m_geo->getTriCount();
|
||||
if (mWaterMethod != Ignore)
|
||||
{
|
||||
getContainer()->findObjects(worldBox, WaterObjectType, buildCallback, &info);
|
||||
}
|
||||
|
||||
// Check for no geometry.
|
||||
if (!m_geo->getVertCount())
|
||||
{
|
||||
m_geo->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_geo->getChunkyMesh();
|
||||
}
|
||||
|
||||
if(!mDirtyTiles.empty())
|
||||
{
|
||||
// Pop a single dirty tile and process it.
|
||||
U32 i = mDirtyTiles.front();
|
||||
mDirtyTiles.pop_front();
|
||||
const Tile &tile = mTiles[i];
|
||||
Tile &tile = mTiles[i];
|
||||
|
||||
// Remove any previous data.
|
||||
nm->removeTile(nm->getTileRefAt(tile.x, tile.y, 0), 0, 0);
|
||||
|
|
@ -885,6 +908,33 @@ void NavMesh::buildNextTile()
|
|||
// Generate navmesh for this tile.
|
||||
U32 dataSize = 0;
|
||||
unsigned char* data = buildTileData(tile, dataSize);
|
||||
// cache our result (these only exist if keep intermediates is ticked)
|
||||
if (m_chf)
|
||||
{
|
||||
tile.chf = m_chf;
|
||||
m_chf = 0;
|
||||
}
|
||||
if (m_solid)
|
||||
{
|
||||
tile.solid = m_solid;
|
||||
m_solid = 0;
|
||||
}
|
||||
if (m_cset)
|
||||
{
|
||||
tile.cset = m_cset;
|
||||
m_cset = 0;
|
||||
}
|
||||
if (m_pmesh)
|
||||
{
|
||||
tile.pmesh = m_pmesh;
|
||||
m_pmesh = 0;
|
||||
}
|
||||
if (m_dmesh)
|
||||
{
|
||||
tile.dmesh = m_dmesh;
|
||||
m_dmesh = 0;
|
||||
}
|
||||
|
||||
if(data)
|
||||
{
|
||||
// Add new data (navmesh owns and deletes the data).
|
||||
|
|
@ -1275,6 +1325,7 @@ void NavMesh::buildTile(const U32 &tile)
|
|||
{
|
||||
mDirtyTiles.push_back_unique(tile);
|
||||
ctx->startTimer(RC_TIMER_TOTAL);
|
||||
m_geo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1757,8 +1808,13 @@ DefineEngineMethod(NavMesh, load, bool, (),,
|
|||
|
||||
bool NavMesh::save()
|
||||
{
|
||||
if(!dStrlen(mFileName) || !nm)
|
||||
if (!nm)
|
||||
return false;
|
||||
|
||||
if (!dStrlen(mFileName) || !nm)
|
||||
{
|
||||
createNewFile();
|
||||
}
|
||||
|
||||
FileStream stream;
|
||||
if(!stream.open(mFileName, Torque::FS::File::Write))
|
||||
|
|
|
|||
|
|
@ -250,6 +250,8 @@ public:
|
|||
|
||||
void inspectPostApply() override;
|
||||
|
||||
void createNewFile();
|
||||
|
||||
protected:
|
||||
|
||||
dtNavMesh const* getNavMesh() { return nm; }
|
||||
|
|
@ -272,17 +274,37 @@ private:
|
|||
/// Recast min and max points.
|
||||
F32 bmin[3], bmax[3];
|
||||
/// Default constructor.
|
||||
Tile() : box(Box3F::Invalid), x(0), y(0)
|
||||
Tile() : box(Box3F::Invalid), x(0), y(0), chf(0), solid(0), cset(0), pmesh(0), dmesh(0)
|
||||
{
|
||||
bmin[0] = bmin[1] = bmin[2] = bmax[0] = bmax[1] = bmax[2] = 0.0f;
|
||||
}
|
||||
/// Value constructor.
|
||||
Tile(const Box3F &b, U32 _x, U32 _y, const F32 *min, const F32 *max)
|
||||
: box(b), x(_x), y(_y)
|
||||
: box(b), x(_x), y(_y), chf(0), solid(0), cset(0), pmesh(0), dmesh(0)
|
||||
{
|
||||
rcVcopy(bmin, min);
|
||||
rcVcopy(bmax, max);
|
||||
}
|
||||
|
||||
~Tile()
|
||||
{
|
||||
if (chf)
|
||||
delete chf;
|
||||
if (cset)
|
||||
delete cset;
|
||||
if (solid)
|
||||
delete solid;
|
||||
if (pmesh)
|
||||
delete pmesh;
|
||||
if (dmesh)
|
||||
delete dmesh;
|
||||
}
|
||||
|
||||
rcCompactHeightfield* chf;
|
||||
rcHeightfield* solid;
|
||||
rcContourSet* cset;
|
||||
rcPolyMesh* pmesh;
|
||||
rcPolyMeshDetail* dmesh;
|
||||
};
|
||||
|
||||
/// List of tiles.
|
||||
|
|
|
|||
Loading…
Reference in a new issue