The Nav Generation Functions example demonstrates how to add new functions to generate nav edges in your nav data.
Nav generation functions are specified in appData/settings/vrfSim/navigationProfiles.mtl. That file specifies a list of plugins that should be loaded. By default the plugin generated by this example will automatically be loaded. Each profile in that file then specifies a list of functions for generating nav edges and nav points.
A nav edge is a line through the nav data that can connect to separate points that might not otherwise be connected. It can be useful for indicating that entities may path plan through areas of the terrain that do not look to be traversable by the Nav Generator, such as closed doors, ladders, elevators, etc.
A nav point is a point of interest within the nav data. These can be queried and used by entities at run time.
New nav generation functions can be called based on dynamic terrain data, feature data queries, or as general functions that implement a custom algorithm based on some other data.
This example adds two functions that create nav edges. The first generates edges that allow lifeforms to navigate through closed doors that are implemented using dynamic terrain features. The second can generate nav edges based on terrain path feature data.
#include <matrix/topoCoord.h>
std::list<DtNavDataGenerator::NavEdgePoints>* edges, void* usr)
{
DtDcm localToTopoDcm;
DtDcm topoToLocalDcm;
DtDcmVecMul(localToTopoDcm, dynTerrInfo.
location(), topoOrig);
std::vector<DtVector> normals;
const unsigned numTests = 7;
for (unsigned i = 0; i < numTests; ++i)
{
DtVector topoPt1(sin(nextAngle) + topoOrig.x(), cos(nextAngle) + topoOrig.y(), topoOrig.z());
DtVector topoPt2 = topoOrig + (topoOrig - topoPt1);
DtDcmVecMul(topoToLocalDcm, topoPt1, locPt1);
DtDcmVecMul(topoToLocalDcm, topoPt2, locPt2);
bool dataAvail = false;
while (!dataAvail)
{
}
if (intersects && dataAvail)
{
normals.push_back(record.
normal());
}
nextAngle += M_2PI / numTests;
if (nextAngle > M_2PI)
{
nextAngle -= M_2PI;
}
}
std::map<DtVector, unsigned> normalCounts;
for (unsigned i = 0; i < normals.size(); ++i)
{
bool foundMatch = false;
double closestMagSq = 9999999;
bool closestIsFlipped = false;
std::map<DtVector, unsigned>::iterator ctItr = normalCounts.begin();
for (; ctItr != normalCounts.end() && !foundMatch; ++ctItr)
{
if (currNormal.approxEq(ctItr->first, 0.01) ||
flippedCurrNormal.approxEq(ctItr->first, 0.01))
{
++ctItr->second;
foundMatch = true;
}
else
{
double magSq = (ctItr->first - currNormal).magnitudeSquared();
double flippedMagSq = (ctItr->first - flippedCurrNormal).magnitudeSquared();
if (magSq < closestMagSq)
{
closestMagSq = magSq;
closestIsFlipped = false;
}
if (flippedMagSq < closestMagSq)
{
closestMagSq = flippedMagSq;
closestIsFlipped = true;
}
}
}
if (!foundMatch)
{
if (closestIsFlipped)
{
normalCounts.insert(std::make_pair(flippedCurrNormal, (unsigned)1));
}
else
{
normalCounts.insert(std::make_pair(currNormal, (unsigned)1));
}
}
}
double avgCount =
double(normals.size()) / normalCounts.size();
unsigned normalCountUsed = 0;
std::map<DtVector, unsigned>::iterator ctItr = normalCounts.begin();
for (; ctItr != normalCounts.end(); ++ctItr)
{
if (ctItr->second >= avgCount)
{
normalCountUsed += ctItr->second;
normalSum += tempSum;
}
}
if (!normalSum.magnitudeIsZero())
{
DtVecScale(normalSum, 1.0 / normalCountUsed, edgeVec);
}
if (!edgeVec.magnitudeIsZero())
{
edgeVec.normalize();
DtVector topoEdgePoint1, topoEdgePoint2;
DtDcmVecMul(localToTopoDcm, edgePoint1, topoEdgePoint1);
DtVector topoEdgeVec = topoEdgePoint1 - topoOrig;
topoEdgeVec.setZ(0);
topoEdgeVec.normalize();
topoEdgePoint1 = topoOrig + topoEdgeVec;
topoEdgePoint2 = topoOrig - topoEdgeVec;
DtDcmVecMul(topoToLocalDcm, topoEdgePoint1, edgePoint1);
DtDcmVecMul(topoToLocalDcm, topoEdgePoint2, edgePoint2);
return true;
}
return false;
}
int sectorX, int sectorY, unsigned edgeTag, std::list<DtNavDataGenerator::NavEdgePoints>* edges, void* usr)
{
bool edgeAdded = false;
{
std::auto_ptr<MAKVRinTerra::DtFeatureGeometry::PointVector> points =
std::vector<DtVector> clampedPoints(points->size(),
DtVector());
for (unsigned ptIdx = 0; ptIdx < points->size(); ++ptIdx)
{
DtVector pt((*points)[ptIdx].x(), (*points)[ptIdx].y(), (*points)[ptIdx].z());
bool dataAvailable = false;
bool intersectionFound = false;
while (!dataAvailable)
{
intersectionPoint, &dataAvailable);
}
if (intersectionFound)
{
clampedPoints[ptIdx] =
DtVector(intersectionPoint.
x(), intersectionPoint.
y(), intersectionPoint.
z());
}
else
{
clampedPoints[ptIdx] = pt;
}
}
unsigned idx1 = 0;
unsigned idx2 = 1;
while (idx2 < clampedPoints.size())
{
clampedPoints[idx1], clampedPoints[idx2], edgeTag));
++idx1;
++idx2;
edgeAdded = true;
}
}
return edgeAdded;
}