- added finalizeSlicedFindPathPartial()
- added handleStep()/handleToggle() to samples - changed how crowds are rendered - added path topology optimization step
This commit is contained in:
parent
e5d603ac92
commit
ccf401d3da
@ -140,6 +140,9 @@ void duDebugDrawCross(struct duDebugDraw* dd, const float x, const float y, cons
|
||||
void duDebugDrawBox(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz, const unsigned int* fcol);
|
||||
|
||||
void duDebugDrawCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz, unsigned int col);
|
||||
|
||||
void duDebugDrawGridXZ(struct duDebugDraw* dd, const float ox, const float oy, const float oz,
|
||||
const int w, const int h, const float size,
|
||||
const unsigned int col, const float lineWidth);
|
||||
@ -172,6 +175,9 @@ void duAppendCross(struct duDebugDraw* dd, const float x, const float y, const f
|
||||
void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz, const unsigned int* fcol);
|
||||
|
||||
void duAppendCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz, unsigned int col);
|
||||
|
||||
|
||||
class duDisplayList : public duDebugDraw
|
||||
{
|
||||
|
@ -135,6 +135,16 @@ void duDebugDrawBox(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
dd->end();
|
||||
}
|
||||
|
||||
void duDebugDrawCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz, unsigned int col)
|
||||
{
|
||||
if (!dd) return;
|
||||
|
||||
dd->begin(DU_DRAW_TRIS);
|
||||
duAppendCylinder(dd, minx,miny,minz, maxx,maxy,maxz, col);
|
||||
dd->end();
|
||||
}
|
||||
|
||||
void duDebugDrawGridXZ(struct duDebugDraw* dd, const float ox, const float oy, const float oz,
|
||||
const int w, const int h, const float size,
|
||||
const unsigned int col, const float lineWidth)
|
||||
@ -289,6 +299,58 @@ void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
}
|
||||
}
|
||||
|
||||
void duAppendCylinder(struct duDebugDraw* dd, float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz, unsigned int col)
|
||||
{
|
||||
if (!dd) return;
|
||||
|
||||
static const int NUM_SEG = 16;
|
||||
static float dir[NUM_SEG*2];
|
||||
static bool init = false;
|
||||
if (!init)
|
||||
{
|
||||
init = true;
|
||||
for (int i = 0; i < NUM_SEG; ++i)
|
||||
{
|
||||
const float a = (float)i/(float)NUM_SEG*DU_PI*2;
|
||||
dir[i*2] = cosf(a);
|
||||
dir[i*2+1] = sinf(a);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int col2 = duMultCol(col, 160);
|
||||
|
||||
const float cx = (maxx + minx)/2;
|
||||
const float cz = (maxz + minz)/2;
|
||||
const float rx = (maxx - minx)/2;
|
||||
const float rz = (maxz - minz)/2;
|
||||
|
||||
for (int i = 2; i < NUM_SEG; ++i)
|
||||
{
|
||||
const int a = 0, b = i-1, c = i;
|
||||
dd->vertex(cx+dir[a*2+0]*rx, miny, cz+dir[a*2+1]*rz, col2);
|
||||
dd->vertex(cx+dir[b*2+0]*rx, miny, cz+dir[b*2+1]*rz, col2);
|
||||
dd->vertex(cx+dir[c*2+0]*rx, miny, cz+dir[c*2+1]*rz, col2);
|
||||
}
|
||||
for (int i = 2; i < NUM_SEG; ++i)
|
||||
{
|
||||
const int a = 0, b = i, c = i-1;
|
||||
dd->vertex(cx+dir[a*2+0]*rx, maxy, cz+dir[a*2+1]*rz, col);
|
||||
dd->vertex(cx+dir[b*2+0]*rx, maxy, cz+dir[b*2+1]*rz, col);
|
||||
dd->vertex(cx+dir[c*2+0]*rx, maxy, cz+dir[c*2+1]*rz, col);
|
||||
}
|
||||
for (int i = 0, j = NUM_SEG-1; i < NUM_SEG; j = i++)
|
||||
{
|
||||
dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col2);
|
||||
dd->vertex(cx+dir[j*2+0]*rx, miny, cz+dir[j*2+1]*rz, col2);
|
||||
dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col);
|
||||
|
||||
dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, col2);
|
||||
dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, col);
|
||||
dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, col);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void evalArc(const float x0, const float y0, const float z0,
|
||||
const float dx, const float dy, const float dz,
|
||||
|
@ -72,9 +72,9 @@ static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile,
|
||||
}
|
||||
}
|
||||
if (con)
|
||||
c = duRGBA(255,255,255,64);
|
||||
c = duRGBA(255,255,255,24);
|
||||
else
|
||||
c = duRGBA(0,0,0,128);
|
||||
c = duRGBA(0,0,0,48);
|
||||
}
|
||||
else
|
||||
c = duRGBA(0,48,64,32);
|
||||
|
@ -173,12 +173,22 @@ public:
|
||||
// Returns: Path query state.
|
||||
dtStatus updateSlicedFindPath(const int maxIter);
|
||||
|
||||
// Finalizes sliced path find query.
|
||||
// Finalizes sliced path find query and returns found path.
|
||||
// path - (out) array holding the search result.
|
||||
// pathCount - (out) Number of polygons in search result array.
|
||||
// maxPath - (in) The max number of polygons the path array can hold.
|
||||
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
|
||||
|
||||
// Finalizes partial sliced path find query and returns path to the furthest
|
||||
// polygon on the existing path that was visited during the search.
|
||||
// existing - (out) Array of polygons in the existing path.
|
||||
// existingSize - (out) Number of polygons in existing path array.
|
||||
// path - (out) array holding the search result.
|
||||
// pathCount - (out) Number of polygons in search result array.
|
||||
// maxPath - (in) The max number of polygons the path array can hold.
|
||||
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
|
||||
dtPolyRef* path, int* pathCount, const int maxPath);
|
||||
|
||||
// Finds a straight path from start to end locations within the corridor
|
||||
// described by the path polygons.
|
||||
// Start and end locations will be clamped on the corridor.
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
inline void operator=(const dtNodePool&) {}
|
||||
void clear();
|
||||
dtNode* getNode(dtPolyRef id);
|
||||
const dtNode* findNode(dtPolyRef id) const;
|
||||
dtNode* findNode(dtPolyRef id);
|
||||
|
||||
inline unsigned int getNodeIdx(const dtNode* node) const
|
||||
{
|
||||
|
@ -1015,6 +1015,75 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount,
|
||||
return DT_SUCCESS;
|
||||
}
|
||||
|
||||
dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
|
||||
dtPolyRef* path, int* pathCount, const int maxPath)
|
||||
{
|
||||
*pathCount = 0;
|
||||
|
||||
if (existingSize == 0)
|
||||
{
|
||||
return DT_FAILURE;
|
||||
}
|
||||
|
||||
if (m_query.status != DT_SUCCESS && m_query.status != DT_IN_PROGRESS)
|
||||
{
|
||||
// Reset query.
|
||||
memset(&m_query, 0, sizeof(dtQueryData));
|
||||
return DT_FAILURE;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
|
||||
if (m_query.startRef == m_query.endRef)
|
||||
{
|
||||
// Special case: the search starts and ends at same poly.
|
||||
path[n++] = m_query.startRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find furthest existing node that was visited.
|
||||
dtNode* prev = 0;
|
||||
dtNode* node = 0;
|
||||
for (int i = existingSize-1; i >= 0; --i)
|
||||
{
|
||||
node = m_nodePool->findNode(existing[i]);
|
||||
if (node)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!node)
|
||||
{
|
||||
return DT_FAILURE;
|
||||
}
|
||||
|
||||
// Reverse the path.
|
||||
do
|
||||
{
|
||||
dtNode* next = m_nodePool->getNodeAtIdx(node->pidx);
|
||||
node->pidx = m_nodePool->getNodeIdx(prev);
|
||||
prev = node;
|
||||
node = next;
|
||||
}
|
||||
while (node);
|
||||
|
||||
// Store path
|
||||
node = prev;
|
||||
do
|
||||
{
|
||||
path[n++] = node->id;
|
||||
node = m_nodePool->getNodeAtIdx(node->pidx);
|
||||
}
|
||||
while (node && n < maxPath);
|
||||
}
|
||||
|
||||
// Reset query.
|
||||
memset(&m_query, 0, sizeof(dtQueryData));
|
||||
|
||||
*pathCount = n;
|
||||
|
||||
return DT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos,
|
||||
const dtPolyRef* path, const int pathSize,
|
||||
|
@ -70,7 +70,7 @@ void dtNodePool::clear()
|
||||
m_nodeCount = 0;
|
||||
}
|
||||
|
||||
const dtNode* dtNodePool::findNode(dtPolyRef id) const
|
||||
dtNode* dtNodePool::findNode(dtPolyRef id)
|
||||
{
|
||||
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||||
unsigned short i = m_first[bucket];
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -284,14 +284,14 @@
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
|
||||
<array>
|
||||
<array>
|
||||
<integer>59</integer>
|
||||
<integer>52</integer>
|
||||
<integer>51</integer>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</array>
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
|
||||
<string>{{0, 590}, {264, 660}}</string>
|
||||
<string>{{0, 577}, {264, 622}}</string>
|
||||
</dict>
|
||||
<key>PBXTopSmartGroupGIDs</key>
|
||||
<array/>
|
||||
@ -301,14 +301,14 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {281, 678}}</string>
|
||||
<string>{{0, 0}, {281, 640}}</string>
|
||||
<key>GroupTreeTableConfiguration</key>
|
||||
<array>
|
||||
<string>MainColumn</string>
|
||||
<real>264</real>
|
||||
</array>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1278 719 0 0 1280 778 </string>
|
||||
<string>47 97 1200 681 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXSmartGroupTreeModule</string>
|
||||
@ -326,7 +326,7 @@
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>6B8632A30F78115100E2684A</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>NavMeshTesterTool.cpp</string>
|
||||
<string>CrowdTool.cpp</string>
|
||||
<key>PBXSplitModuleInNavigatorKey</key>
|
||||
<dict>
|
||||
<key>Split0</key>
|
||||
@ -334,29 +334,46 @@
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>6B8632A40F78115100E2684A</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>NavMeshTesterTool.cpp</string>
|
||||
<string>CrowdTool.cpp</string>
|
||||
<key>_historyCapacity</key>
|
||||
<integer>0</integer>
|
||||
<key>bookmark</key>
|
||||
<string>6B8D56DA127AEC580077C699</string>
|
||||
<string>6B74B7631286BB6900262888</string>
|
||||
<key>history</key>
|
||||
<array>
|
||||
<string>6B8D565F127ADB0D0077C699</string>
|
||||
<string>6B8D566D127ADB7D0077C699</string>
|
||||
<string>6B8D566F127ADB7D0077C699</string>
|
||||
<string>6B8D56C7127AEC100077C699</string>
|
||||
<string>6B8D56C8127AEC100077C699</string>
|
||||
<string>6B8D56C9127AEC100077C699</string>
|
||||
<string>6B8D56CA127AEC100077C699</string>
|
||||
<string>6B8D56CB127AEC100077C699</string>
|
||||
<string>6B8D56CC127AEC100077C699</string>
|
||||
<string>6B8D56CD127AEC100077C699</string>
|
||||
<string>6B8D56CE127AEC100077C699</string>
|
||||
<string>6B8D56CF127AEC100077C699</string>
|
||||
<string>6B8D56D0127AEC100077C699</string>
|
||||
<string>6B8D56D2127AEC100077C699</string>
|
||||
<string>6B8D56D8127AEC580077C699</string>
|
||||
<string>6B8D56D9127AEC580077C699</string>
|
||||
<string>6B4DE62F12807542001CFDF4</string>
|
||||
<string>6B4DE647128079E0001CFDF4</string>
|
||||
<string>6B4DE649128079E0001CFDF4</string>
|
||||
<string>6B4DE64A128079E0001CFDF4</string>
|
||||
<string>6B74B5F3128312AC00262888</string>
|
||||
<string>6B74B5F4128312AC00262888</string>
|
||||
<string>6B74B60F128312E900262888</string>
|
||||
<string>6B74B623128314A500262888</string>
|
||||
<string>6B74B624128314A500262888</string>
|
||||
<string>6B74B626128314A500262888</string>
|
||||
<string>6B74B627128314A500262888</string>
|
||||
<string>6B74B628128314A500262888</string>
|
||||
<string>6B74B629128314A500262888</string>
|
||||
<string>6B74B62A128314A500262888</string>
|
||||
<string>6B74B62B128314A500262888</string>
|
||||
<string>6B74B62C128314A500262888</string>
|
||||
<string>6B74B66412869CE100262888</string>
|
||||
<string>6B74B66712869CE100262888</string>
|
||||
<string>6B74B66F12869E3000262888</string>
|
||||
<string>6B74B6BF1286AA0C00262888</string>
|
||||
<string>6B74B6D81286ABC000262888</string>
|
||||
<string>6B74B6FC1286AE0B00262888</string>
|
||||
<string>6B74B7061286AEBD00262888</string>
|
||||
<string>6B74B7071286AEBD00262888</string>
|
||||
<string>6B74B7401286B7C400262888</string>
|
||||
<string>6B74B75F1286BB6900262888</string>
|
||||
<string>6B74B7601286BB6900262888</string>
|
||||
<string>6B74B7611286BB6900262888</string>
|
||||
<string>6B74B7621286BB6900262888</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>SplitCount</key>
|
||||
@ -370,18 +387,18 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {992, 434}}</string>
|
||||
<string>{{0, 0}, {914, 472}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1278 719 0 0 1280 778 </string>
|
||||
<string>47 97 1200 681 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXNavigatorGroup</string>
|
||||
<key>Proportion</key>
|
||||
<string>434pt</string>
|
||||
<string>472pt</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Proportion</key>
|
||||
<string>239pt</string>
|
||||
<string>164pt</string>
|
||||
<key>Tabs</key>
|
||||
<array>
|
||||
<dict>
|
||||
@ -395,7 +412,7 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {992, -27}}</string>
|
||||
<string>{{10, 27}, {992, 49}}</string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>XCDetailModule</string>
|
||||
@ -411,7 +428,7 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {992, 212}}</string>
|
||||
<string>{{10, 27}, {992, 169}}</string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXProjectFindModule</string>
|
||||
@ -449,9 +466,9 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {992, 212}}</string>
|
||||
<string>{{10, 27}, {914, 137}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1278 719 0 0 1280 778 </string>
|
||||
<string>47 97 1200 681 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXBuildResultsModule</string>
|
||||
@ -460,7 +477,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>Proportion</key>
|
||||
<string>992pt</string>
|
||||
<string>914pt</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>Name</key>
|
||||
@ -479,11 +496,11 @@
|
||||
</array>
|
||||
<key>TableOfContents</key>
|
||||
<array>
|
||||
<string>6B8D5625127AD44A0077C699</string>
|
||||
<string>6B74B5DD1283104100262888</string>
|
||||
<string>1CA23ED40692098700951B8B</string>
|
||||
<string>6B8D5626127AD44A0077C699</string>
|
||||
<string>6B74B5DE1283104100262888</string>
|
||||
<string>6B8632A30F78115100E2684A</string>
|
||||
<string>6B8D5627127AD44A0077C699</string>
|
||||
<string>6B74B5DF1283104100262888</string>
|
||||
<string>1CA23EDF0692099D00951B8B</string>
|
||||
<string>1CA23EE00692099D00951B8B</string>
|
||||
<string>1CA23EE10692099D00951B8B</string>
|
||||
@ -631,14 +648,14 @@
|
||||
</array>
|
||||
<key>TableOfContents</key>
|
||||
<array>
|
||||
<string>6B8D563A127AD6CA0077C699</string>
|
||||
<string>6B74B5FD128312AC00262888</string>
|
||||
<string>1CCC7628064C1048000F2A68</string>
|
||||
<string>1CCC7629064C1048000F2A68</string>
|
||||
<string>6B8D563B127AD6CA0077C699</string>
|
||||
<string>6B8D563C127AD6CA0077C699</string>
|
||||
<string>6B8D563D127AD6CA0077C699</string>
|
||||
<string>6B8D563E127AD6CA0077C699</string>
|
||||
<string>6B8D563F127AD6CA0077C699</string>
|
||||
<string>6B74B5FE128312AC00262888</string>
|
||||
<string>6B74B5FF128312AC00262888</string>
|
||||
<string>6B74B600128312AC00262888</string>
|
||||
<string>6B74B601128312AC00262888</string>
|
||||
<string>6B74B602128312AC00262888</string>
|
||||
</array>
|
||||
<key>ToolbarConfigUserDefaultsMinorVersion</key>
|
||||
<string>2</string>
|
||||
@ -670,13 +687,12 @@
|
||||
<integer>5</integer>
|
||||
<key>WindowOrderList</key>
|
||||
<array>
|
||||
<string>6B8D56D5127AEC100077C699</string>
|
||||
<string>6B8D56D6127AEC100077C699</string>
|
||||
<string>6B8D56D7127AEC100077C699</string>
|
||||
<string>6B74B604128312AC00262888</string>
|
||||
<string>6B74B605128312AC00262888</string>
|
||||
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
|
||||
</array>
|
||||
<key>WindowString</key>
|
||||
<string>0 59 1278 719 0 0 1280 778 </string>
|
||||
<string>47 97 1200 681 0 0 1280 778 </string>
|
||||
<key>WindowToolsV3</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
virtual void reset();
|
||||
virtual void handleMenu();
|
||||
virtual void handleClick(const float* s, const float* p, bool shift);
|
||||
virtual void handleToggle();
|
||||
virtual void handleStep();
|
||||
virtual void handleUpdate(const float dt);
|
||||
virtual void handleRender();
|
||||
|
@ -138,8 +138,10 @@ public:
|
||||
dtPolyRef* cornerPolys, const int maxCorners,
|
||||
dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
|
||||
void optimizePath(const float* next, const float pathOptimizationRange,
|
||||
dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
void optimizePathVisibility(const float* next, const float pathOptimizationRange,
|
||||
dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
|
||||
bool optimizePathTopology(dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
|
||||
void movePosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
void moveTargetPosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
@ -216,6 +218,8 @@ struct Agent
|
||||
float collisionQueryRange;
|
||||
float pathOptimizationRange;
|
||||
|
||||
float topologyOptTime;
|
||||
|
||||
Neighbour neis[AGENT_MAX_NEIGHBOURS];
|
||||
int nneis;
|
||||
|
||||
@ -243,6 +247,8 @@ enum UpdateFlags
|
||||
CROWDMAN_ANTICIPATE_TURNS = 1,
|
||||
CROWDMAN_USE_VO = 2,
|
||||
CROWDMAN_DRUNK = 4,
|
||||
CROWDMAN_OPTIMIZE_VIS = 8,
|
||||
CROWDMAN_OPTIMIZE_TOPO = 16,
|
||||
};
|
||||
|
||||
|
||||
@ -295,6 +301,9 @@ class CrowdManager
|
||||
int getNeighbours(const float* pos, const float height, const float range,
|
||||
const Agent* skip, Neighbour* result, const int maxResult);
|
||||
|
||||
void updateTopologyOptimization(const float dt, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
void updateMoveRequest(const float dt, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
|
||||
public:
|
||||
CrowdManager();
|
||||
~CrowdManager();
|
||||
@ -307,9 +316,8 @@ public:
|
||||
|
||||
bool requestMoveTarget(const int idx, dtPolyRef ref, const float* pos);
|
||||
bool adjustMoveTarget(const int idx, dtPolyRef ref, const float* pos);
|
||||
|
||||
|
||||
int getActiveAgents(Agent** agents, const int maxAgents);
|
||||
void updateMoveRequest(const float dt, dtNavMeshQuery* navquery, const dtQueryFilter* filter);
|
||||
void update(const float dt, unsigned int flags, dtNavMeshQuery* navquery);
|
||||
|
||||
const dtQueryFilter* getFilter() const { return &m_filter; }
|
||||
|
@ -44,9 +44,13 @@ class CrowdTool : public SampleTool
|
||||
bool m_showVO;
|
||||
bool m_showOpt;
|
||||
bool m_showGrid;
|
||||
bool m_showNodes;
|
||||
bool m_showPerfGraph;
|
||||
|
||||
bool m_expandOptions;
|
||||
bool m_anticipateTurns;
|
||||
bool m_optimizeVis;
|
||||
bool m_optimizeTopo;
|
||||
bool m_useVO;
|
||||
bool m_drunkMove;
|
||||
|
||||
@ -74,6 +78,7 @@ public:
|
||||
virtual void reset();
|
||||
virtual void handleMenu();
|
||||
virtual void handleClick(const float* s, const float* p, bool shift);
|
||||
virtual void handleToggle();
|
||||
virtual void handleStep();
|
||||
virtual void handleUpdate(const float dt);
|
||||
virtual void handleRender();
|
||||
|
@ -93,6 +93,7 @@ public:
|
||||
virtual void reset();
|
||||
virtual void handleMenu();
|
||||
virtual void handleClick(const float* s, const float* p, bool shift);
|
||||
virtual void handleToggle();
|
||||
virtual void handleStep();
|
||||
virtual void handleUpdate(const float dt);
|
||||
virtual void handleRender();
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
virtual void reset();
|
||||
virtual void handleMenu();
|
||||
virtual void handleClick(const float* s, const float* p, bool shift);
|
||||
virtual void handleToggle();
|
||||
virtual void handleStep();
|
||||
virtual void handleUpdate(const float dt);
|
||||
virtual void handleRender();
|
||||
|
@ -65,6 +65,7 @@ struct SampleTool
|
||||
virtual void handleClick(const float* s, const float* p, bool shift) = 0;
|
||||
virtual void handleRender() = 0;
|
||||
virtual void handleRenderOverlay(double* proj, double* model, int* view) = 0;
|
||||
virtual void handleToggle() = 0;
|
||||
virtual void handleStep() = 0;
|
||||
virtual void handleUpdate(const float dt) = 0;
|
||||
};
|
||||
@ -108,6 +109,7 @@ public:
|
||||
virtual void handleTools();
|
||||
virtual void handleDebugMode();
|
||||
virtual void handleClick(const float* s, const float* p, bool shift);
|
||||
virtual void handleToggle();
|
||||
virtual void handleStep();
|
||||
virtual void handleRender();
|
||||
virtual void handleRenderOverlay(double* proj, double* model, int* view);
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
virtual void handleTools();
|
||||
virtual void handleDebugMode();
|
||||
virtual void handleClick(const float* s, const float* p, bool shift);
|
||||
virtual void handleStep();
|
||||
virtual void handleToggle();
|
||||
virtual void handleRender();
|
||||
virtual void handleRenderOverlay(double* proj, double* model, int* view);
|
||||
virtual void handleMeshChanged(class InputGeom* geom);
|
||||
|
@ -230,6 +230,10 @@ void ConvexVolumeTool::handleClick(const float* /*s*/, const float* p, bool shif
|
||||
|
||||
}
|
||||
|
||||
void ConvexVolumeTool::handleToggle()
|
||||
{
|
||||
}
|
||||
|
||||
void ConvexVolumeTool::handleStep()
|
||||
{
|
||||
}
|
||||
|
@ -506,8 +506,8 @@ int PathCorridor::findCorners(float* cornerVerts, unsigned char* cornerFlags,
|
||||
return ncorners;
|
||||
}
|
||||
|
||||
void PathCorridor::optimizePath(const float* next, const float pathOptimizationRange,
|
||||
dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
void PathCorridor::optimizePathVisibility(const float* next, const float pathOptimizationRange,
|
||||
dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
{
|
||||
dtAssert(m_path);
|
||||
|
||||
@ -539,6 +539,31 @@ void PathCorridor::optimizePath(const float* next, const float pathOptimizationR
|
||||
}
|
||||
}
|
||||
|
||||
bool PathCorridor::optimizePathTopology(dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
{
|
||||
dtAssert(m_path);
|
||||
|
||||
if (m_npath < 3)
|
||||
return false;
|
||||
|
||||
static const int MAX_ITER = 32;
|
||||
static const int MAX_RES = 32;
|
||||
|
||||
dtPolyRef res[MAX_RES];
|
||||
int nres = 0;
|
||||
navquery->initSlicedFindPath(m_path[0], m_path[m_npath-1], m_pos, m_target, filter);
|
||||
navquery->updateSlicedFindPath(MAX_ITER);
|
||||
dtStatus status = navquery->finalizeSlicedFindPathPartial(m_path, m_npath, res, &nres, MAX_RES);
|
||||
|
||||
if (status == DT_SUCCESS && nres > 0)
|
||||
{
|
||||
m_npath = mergeCorridor(m_path, m_npath, m_maxPath, res, nres);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PathCorridor::movePosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
{
|
||||
dtAssert(m_path);
|
||||
@ -876,6 +901,7 @@ int CrowdManager::addAgent(const float* pos, const float radius, const float hei
|
||||
ag->height = height;
|
||||
ag->collisionQueryRange = radius * 8;
|
||||
ag->pathOptimizationRange = radius * 30;
|
||||
ag->topologyOptTime = 0;
|
||||
ag->nneis = 0;
|
||||
|
||||
dtVset(ag->dvel, 0,0,0);
|
||||
@ -901,7 +927,9 @@ int CrowdManager::addAgent(const float* pos, const float radius, const float hei
|
||||
void CrowdManager::removeAgent(const int idx)
|
||||
{
|
||||
if (idx >= 0 && idx < MAX_AGENTS)
|
||||
memset(&m_agents[idx], 0, sizeof(Agent));
|
||||
{
|
||||
m_agents[idx].active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CrowdManager::requestMoveTarget(const int idx, dtPolyRef ref, const float* pos)
|
||||
@ -1231,6 +1259,76 @@ void CrowdManager::updateMoveRequest(const float dt, dtNavMeshQuery* navquery, c
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int addToOptQueue(Agent* newag, Agent** agents, const int nagents, const int maxAgents)
|
||||
{
|
||||
// Insert neighbour based on greatest time.
|
||||
int slot = 0;
|
||||
if (!nagents)
|
||||
{
|
||||
slot = nagents;
|
||||
}
|
||||
else if (newag->topologyOptTime <= agents[nagents-1]->topologyOptTime)
|
||||
{
|
||||
if (nagents >= maxAgents)
|
||||
return nagents;
|
||||
slot = nagents;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nagents; ++i)
|
||||
if (newag->topologyOptTime >= agents[i]->topologyOptTime)
|
||||
break;
|
||||
|
||||
const int tgt = i+1;
|
||||
const int n = dtMin(nagents-i, maxAgents-tgt);
|
||||
|
||||
dtAssert(tgt+n <= maxAgents);
|
||||
|
||||
if (n > 0)
|
||||
memmove(&agents[tgt], &agents[i], sizeof(Agent*)*n);
|
||||
slot = i;
|
||||
}
|
||||
|
||||
agents[slot] = newag;
|
||||
|
||||
return dtMin(nagents+1, maxAgents);
|
||||
}
|
||||
|
||||
void CrowdManager::updateTopologyOptimization(const float dt, dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
{
|
||||
Agent* agents[MAX_AGENTS];
|
||||
int nagents = getActiveAgents(agents, MAX_AGENTS);
|
||||
if (!nagents)
|
||||
return;
|
||||
|
||||
const float OPT_TIME_THR = 0.5f; // seconds
|
||||
const int OPT_MAX_AGENTS = 1;
|
||||
|
||||
Agent* queue[OPT_MAX_AGENTS];
|
||||
int nqueue = 0;
|
||||
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
ag->topologyOptTime += dt;
|
||||
if (ag->topologyOptTime >= OPT_TIME_THR)
|
||||
{
|
||||
nqueue = addToOptQueue(ag, queue, nqueue, OPT_MAX_AGENTS);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nqueue; ++i)
|
||||
{
|
||||
Agent* ag = queue[i];
|
||||
ag->corridor.optimizePathTopology(navquery, filter);
|
||||
ag->topologyOptTime = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery)
|
||||
{
|
||||
m_sampleCount = 0;
|
||||
@ -1251,6 +1349,10 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
// Update async move request and path finder.
|
||||
updateMoveRequest(dt, navquery, &m_filter);
|
||||
|
||||
// Optimize path topology.
|
||||
if (flags & CROWDMAN_OPTIMIZE_TOPO)
|
||||
updateTopologyOptimization(dt, navquery, &m_filter);
|
||||
|
||||
// Register agents to proximity grid.
|
||||
m_grid.clear();
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
@ -1283,12 +1385,12 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
|
||||
// Check to see if the corner after the next corner is directly visible,
|
||||
// and short cut to there.
|
||||
if (ag->ncorners > 0)
|
||||
if ((flags & CROWDMAN_OPTIMIZE_VIS) && ag->ncorners > 0)
|
||||
{
|
||||
const float* target = &ag->cornerVerts[dtMin(1,ag->ncorners-1)*3];
|
||||
dtVcopy(ag->opts, ag->corridor.getPos());
|
||||
dtVcopy(ag->opte, target);
|
||||
ag->corridor.optimizePath(target, ag->pathOptimizationRange, navquery, &m_filter);
|
||||
ag->corridor.optimizePathVisibility(target, ag->pathOptimizationRange, navquery, &m_filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ CrowdTool::CrowdTool() :
|
||||
m_oldFlags(0),
|
||||
m_targetRef(0),
|
||||
m_expandDebugDraw(false),
|
||||
m_showLabels(true),
|
||||
m_showLabels(false),
|
||||
m_showCorners(false),
|
||||
m_showTargets(false),
|
||||
m_showCollisionSegments(false),
|
||||
@ -103,8 +103,12 @@ CrowdTool::CrowdTool() :
|
||||
m_showVO(false),
|
||||
m_showOpt(false),
|
||||
m_showGrid(false),
|
||||
m_showNodes(false),
|
||||
m_showPerfGraph(false),
|
||||
m_expandOptions(true),
|
||||
m_anticipateTurns(true),
|
||||
m_optimizeVis(true),
|
||||
m_optimizeTopo(true),
|
||||
m_useVO(true),
|
||||
m_drunkMove(false),
|
||||
m_run(true),
|
||||
@ -168,6 +172,10 @@ void CrowdTool::handleMenu()
|
||||
if (m_expandOptions)
|
||||
{
|
||||
imguiIndent();
|
||||
if (imguiCheck("Optimize Visibility", m_optimizeVis))
|
||||
m_optimizeVis = !m_optimizeVis;
|
||||
if (imguiCheck("Optimize Topology", m_optimizeTopo))
|
||||
m_optimizeTopo = !m_optimizeTopo;
|
||||
if (imguiCheck("Anticipate Turns", m_anticipateTurns))
|
||||
m_anticipateTurns = !m_anticipateTurns;
|
||||
if (imguiCheck("Use VO", m_useVO))
|
||||
@ -199,6 +207,10 @@ void CrowdTool::handleMenu()
|
||||
m_showOpt = !m_showOpt;
|
||||
if (imguiCheck("Show Prox Grid", m_showGrid))
|
||||
m_showGrid = !m_showGrid;
|
||||
if (imguiCheck("Show Nodes", m_showNodes))
|
||||
m_showNodes = !m_showNodes;
|
||||
if (imguiCheck("Show Perf Graph", m_showPerfGraph))
|
||||
m_showPerfGraph = !m_showPerfGraph;
|
||||
imguiUnindent();
|
||||
}
|
||||
}
|
||||
@ -280,6 +292,10 @@ void CrowdTool::handleClick(const float* s, const float* p, bool shift)
|
||||
}
|
||||
|
||||
void CrowdTool::handleStep()
|
||||
{
|
||||
}
|
||||
|
||||
void CrowdTool::handleToggle()
|
||||
{
|
||||
m_run = !m_run;
|
||||
}
|
||||
@ -298,6 +314,10 @@ void CrowdTool::handleUpdate(const float dt)
|
||||
flags |= CROWDMAN_USE_VO;
|
||||
if (m_drunkMove)
|
||||
flags |= CROWDMAN_DRUNK;
|
||||
if (m_optimizeVis)
|
||||
flags |= CROWDMAN_OPTIMIZE_VIS;
|
||||
if (m_optimizeTopo)
|
||||
flags |= CROWDMAN_OPTIMIZE_TOPO;
|
||||
|
||||
m_crowd.update(dt, flags, m_sample->getNavMeshQuery());
|
||||
|
||||
@ -315,33 +335,76 @@ void CrowdTool::handleRender()
|
||||
dtNavMesh* nmesh = m_sample->getNavMesh();
|
||||
if (!nmesh)
|
||||
return;
|
||||
|
||||
dtNavMeshQuery* navquery = m_sample->getNavMeshQuery();
|
||||
|
||||
if (m_showNodes)
|
||||
{
|
||||
if (navquery)
|
||||
duDebugDrawNavMeshNodes(&dd, *navquery);
|
||||
}
|
||||
|
||||
dd.depthMask(false);
|
||||
|
||||
// Draw paths
|
||||
if (m_showPath)
|
||||
{
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
const dtPolyRef* path = ag->corridor.getPath();
|
||||
const int npath = ag->corridor.getPathCount();
|
||||
for (int i = 0; i < npath; ++i)
|
||||
duDebugDrawNavMeshPoly(&dd, *nmesh, path[i], duRGBA(0,0,0,32));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_targetRef)
|
||||
duDebugDrawCross(&dd, m_targetPos[0],m_targetPos[1]+0.1f,m_targetPos[2], s, duRGBA(0,0,0,128), 2.0f);
|
||||
|
||||
|
||||
duDebugDrawCross(&dd, m_targetPos[0],m_targetPos[1]+0.1f,m_targetPos[2], s, duRGBA(255,255,255,192), 2.0f);
|
||||
|
||||
// Occupancy grid.
|
||||
if (m_showGrid)
|
||||
{
|
||||
float gridy = -FLT_MAX;
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
const float* pos = ag->corridor.getPos();
|
||||
gridy = dtMax(gridy, pos[1]);
|
||||
}
|
||||
gridy += 1.0f;
|
||||
|
||||
dd.begin(DU_DRAW_QUADS);
|
||||
const ProximityGrid* grid = m_crowd.getGrid();
|
||||
const int* bounds = grid->getBounds();
|
||||
const float cs = grid->getCellSize();
|
||||
for (int y = bounds[1]; y <= bounds[3]; ++y)
|
||||
{
|
||||
for (int x = bounds[0]; x <= bounds[2]; ++x)
|
||||
{
|
||||
const int count = grid->getItemCountAt(x,y);
|
||||
if (!count) continue;
|
||||
unsigned int col = duRGBA(128,0,0,dtMin(count*40,255));
|
||||
dd.vertex(x*cs, gridy, y*cs, col);
|
||||
dd.vertex(x*cs, gridy, y*cs+cs, col);
|
||||
dd.vertex(x*cs+cs, gridy, y*cs+cs, col);
|
||||
dd.vertex(x*cs+cs, gridy, y*cs, col);
|
||||
}
|
||||
}
|
||||
dd.end();
|
||||
}
|
||||
|
||||
// Trail
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
const float height = ag->height;
|
||||
const float radius = ag->radius;
|
||||
const float* pos = ag->npos;
|
||||
const float* target = ag->corridor.getTarget();
|
||||
const float* vel = ag->vel;
|
||||
const float* dvel = ag->dvel;
|
||||
|
||||
dd.depthMask(false);
|
||||
|
||||
if (m_showPath)
|
||||
{
|
||||
const dtPolyRef* path = ag->corridor.getPath();
|
||||
const int npath = ag->corridor.getPathCount();
|
||||
for (int i = 0; i < npath; ++i)
|
||||
duDebugDrawNavMeshPoly(&dd, *nmesh, path[i], duRGBA(0,0,0,64));
|
||||
}
|
||||
|
||||
|
||||
dd.begin(DU_DRAW_LINES,3.0f);
|
||||
float prev[3], preva = 1;
|
||||
dtVcopy(prev, pos);
|
||||
@ -356,13 +419,18 @@ void CrowdTool::handleRender()
|
||||
dtVcopy(prev, v);
|
||||
}
|
||||
dd.end();
|
||||
|
||||
if (m_showTargets)
|
||||
{
|
||||
duDebugDrawArc(&dd, pos[0], pos[1], pos[2], target[0], target[1], target[2],
|
||||
0.25f, 0, 0.4f, duRGBA(0,0,0,128), 1.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Corners & co
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
const float radius = ag->radius;
|
||||
const float* pos = ag->npos;
|
||||
|
||||
if (m_showCorners)
|
||||
{
|
||||
if (ag->ncorners)
|
||||
@ -372,32 +440,32 @@ void CrowdTool::handleRender()
|
||||
{
|
||||
const float* va = j == 0 ? pos : &ag->cornerVerts[(j-1)*3];
|
||||
const float* vb = &ag->cornerVerts[j*3];
|
||||
dd.vertex(va[0],va[1]+radius,va[2], duRGBA(128,0,0,64));
|
||||
dd.vertex(vb[0],vb[1]+radius,vb[2], duRGBA(128,0,0,64));
|
||||
dd.vertex(va[0],va[1]+radius,va[2], duRGBA(128,0,0,192));
|
||||
dd.vertex(vb[0],vb[1]+radius,vb[2], duRGBA(128,0,0,192));
|
||||
}
|
||||
dd.end();
|
||||
|
||||
|
||||
if (m_anticipateTurns)
|
||||
{
|
||||
/* float dvel[3], pos[3];
|
||||
calcSmoothSteerDirection(ag->pos, ag->cornerVerts, ag->ncorners, dvel);
|
||||
pos[0] = ag->pos[0] + dvel[0];
|
||||
pos[1] = ag->pos[1] + dvel[1];
|
||||
pos[2] = ag->pos[2] + dvel[2];
|
||||
|
||||
const float off = ag->radius+0.1f;
|
||||
const float* tgt = &ag->cornerVerts[0];
|
||||
const float y = ag->pos[1]+off;
|
||||
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
|
||||
dd.vertex(ag->pos[0],y,ag->pos[2], duRGBA(255,0,0,192));
|
||||
dd.vertex(pos[0],y,pos[2], duRGBA(255,0,0,192));
|
||||
|
||||
dd.vertex(pos[0],y,pos[2], duRGBA(255,0,0,192));
|
||||
dd.vertex(tgt[0],y,tgt[2], duRGBA(255,0,0,192));
|
||||
|
||||
dd.end();*/
|
||||
/* float dvel[3], pos[3];
|
||||
calcSmoothSteerDirection(ag->pos, ag->cornerVerts, ag->ncorners, dvel);
|
||||
pos[0] = ag->pos[0] + dvel[0];
|
||||
pos[1] = ag->pos[1] + dvel[1];
|
||||
pos[2] = ag->pos[2] + dvel[2];
|
||||
|
||||
const float off = ag->radius+0.1f;
|
||||
const float* tgt = &ag->cornerVerts[0];
|
||||
const float y = ag->pos[1]+off;
|
||||
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
|
||||
dd.vertex(ag->pos[0],y,ag->pos[2], duRGBA(255,0,0,192));
|
||||
dd.vertex(pos[0],y,pos[2], duRGBA(255,0,0,192));
|
||||
|
||||
dd.vertex(pos[0],y,pos[2], duRGBA(255,0,0,192));
|
||||
dd.vertex(tgt[0],y,tgt[2], duRGBA(255,0,0,192));
|
||||
|
||||
dd.end();*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -408,7 +476,7 @@ void CrowdTool::handleRender()
|
||||
duDebugDrawCross(&dd, center[0],center[1]+radius,center[2], 0.2f, duRGBA(192,0,128,255), 2.0f);
|
||||
duDebugDrawCircle(&dd, center[0],center[1]+radius,center[2], ag->collisionQueryRange,
|
||||
duRGBA(192,0,128,128), 2.0f);
|
||||
|
||||
|
||||
dd.begin(DU_DRAW_LINES, 3.0f);
|
||||
for (int j = 0; j < ag->boundary.getSegmentCount(); ++j)
|
||||
{
|
||||
@ -421,7 +489,7 @@ void CrowdTool::handleRender()
|
||||
}
|
||||
dd.end();
|
||||
}
|
||||
|
||||
|
||||
if (m_showOpt)
|
||||
{
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
@ -429,6 +497,48 @@ void CrowdTool::handleRender()
|
||||
dd.vertex(ag->opte[0],ag->opte[1]+0.3f,ag->opte[2], duRGBA(0,128,0,192));
|
||||
dd.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Agent cylinders.
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
const float radius = ag->radius;
|
||||
const float* pos = ag->npos;
|
||||
|
||||
duDebugDrawCircle(&dd, pos[0], pos[1], pos[2], radius, duRGBA(0,0,0,32), 2.0f);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
const float height = ag->height;
|
||||
const float radius = ag->radius;
|
||||
const float* pos = ag->npos;
|
||||
|
||||
duDebugDrawCylinder(&dd, pos[0]-radius, pos[1]+radius*0.1f, pos[2]-radius,
|
||||
pos[0]+radius, pos[1]+height, pos[2]+radius,
|
||||
duRGBA(220,220,220,128));
|
||||
}
|
||||
|
||||
|
||||
// Velocity stuff.
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
const float radius = ag->radius;
|
||||
const float height = ag->height;
|
||||
const float* pos = ag->npos;
|
||||
const float* vel = ag->vel;
|
||||
const float* dvel = ag->dvel;
|
||||
|
||||
duDebugDrawCircle(&dd, pos[0], pos[1]+height, pos[2], radius, duRGBA(220,220,220,192), 2.0f);
|
||||
|
||||
if (m_showVO)
|
||||
{
|
||||
@ -458,138 +568,31 @@ void CrowdTool::handleRender()
|
||||
}
|
||||
|
||||
duDebugDrawArrow(&dd, pos[0],pos[1]+height,pos[2],
|
||||
pos[0]+vel[0],pos[1]+height+vel[1],pos[2]+vel[2],
|
||||
0.0f, 0.4f, duRGBA(0,0,0,192), 2.0f);
|
||||
|
||||
duDebugDrawArrow(&dd, pos[0],pos[1]+height-0.1f,pos[2],
|
||||
pos[0]+dvel[0],pos[1]+height-0.1f+dvel[1],pos[2]+dvel[2],
|
||||
pos[0]+dvel[0],pos[1]+height+dvel[1],pos[2]+dvel[2],
|
||||
0.0f, 0.4f, duRGBA(0,192,255,192), 1.0f);
|
||||
|
||||
duDebugDrawCylinderWire(&dd, pos[0]-radius, pos[1]+radius*0.1f, pos[2]-radius,
|
||||
pos[0]+radius, pos[1]+height, pos[2]+radius,
|
||||
duRGBA(0,192,255,255), 3.0f);
|
||||
duDebugDrawArrow(&dd, pos[0],pos[1]+height,pos[2],
|
||||
pos[0]+vel[0],pos[1]+height+vel[1],pos[2]+vel[2],
|
||||
0.0f, 0.4f, duRGBA(0,0,0,192), 2.0f);
|
||||
}
|
||||
|
||||
// Targets
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
|
||||
dd.depthMask(true);
|
||||
}
|
||||
|
||||
if (m_showGrid)
|
||||
{
|
||||
float gridy = -FLT_MAX;
|
||||
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
|
||||
const float* pos = ag->npos;
|
||||
const float* target = ag->corridor.getTarget();
|
||||
|
||||
if (m_showTargets)
|
||||
{
|
||||
const Agent* ag = m_crowd.getAgent(i);
|
||||
if (!ag->active) continue;
|
||||
const float* pos = ag->corridor.getPos();
|
||||
gridy = dtMax(gridy, pos[1]);
|
||||
duDebugDrawArc(&dd, pos[0], pos[1], pos[2], target[0], target[1], target[2],
|
||||
0.25f, 0, 0.4f, duRGBA(0,0,0,128), 1.0f);
|
||||
}
|
||||
gridy += 1.0f;
|
||||
|
||||
dd.depthMask(false);
|
||||
dd.begin(DU_DRAW_QUADS);
|
||||
const ProximityGrid* grid = m_crowd.getGrid();
|
||||
const int* bounds = grid->getBounds();
|
||||
const float cs = grid->getCellSize();
|
||||
for (int y = bounds[1]; y <= bounds[3]; ++y)
|
||||
{
|
||||
for (int x = bounds[0]; x <= bounds[2]; ++x)
|
||||
{
|
||||
const int count = grid->getItemCountAt(x,y);
|
||||
if (!count) continue;
|
||||
unsigned int col = duRGBA(128,0,0,dtMin(count*40,255));
|
||||
dd.vertex(x*cs, gridy, y*cs, col);
|
||||
dd.vertex(x*cs, gridy, y*cs+cs, col);
|
||||
dd.vertex(x*cs+cs, gridy, y*cs+cs, col);
|
||||
dd.vertex(x*cs+cs, gridy, y*cs, col);
|
||||
}
|
||||
}
|
||||
dd.end();
|
||||
dd.depthMask(true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
for (int i = 0; i < m_form.npolys; ++i)
|
||||
{
|
||||
duDebugDrawNavMeshPoly(&dd, *nmesh, m_form.polys[i], duRGBA(255,255,255,32));
|
||||
}
|
||||
|
||||
dd.depthMask(false);
|
||||
|
||||
dd.begin(DU_DRAW_POINTS, 4.0f);
|
||||
for (int i = 0; i < m_form.nsegs; ++i)
|
||||
{
|
||||
const FormationSeg* seg = &m_form.segs[i];
|
||||
for (int j = 0; j < seg->nints-1; ++j)
|
||||
{
|
||||
if (seg->ints[j].inside == 0) continue;
|
||||
const float u0 = seg->ints[j].u;
|
||||
const float u1 = seg->ints[j+1].u;
|
||||
float ia[3], ib[3];
|
||||
dtVlerp(ia, seg->p,seg->q, u0);
|
||||
dtVlerp(ib, seg->p,seg->q, u1);
|
||||
dd.vertex(ia,duRGBA(128,0,0,192));
|
||||
dd.vertex(ib,duRGBA(128,0,0,192));
|
||||
}
|
||||
}
|
||||
dd.end();
|
||||
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
for (int i = 0; i < m_form.nsegs; ++i)
|
||||
{
|
||||
const FormationSeg* seg = &m_form.segs[i];
|
||||
dd.vertex(seg->p,duRGBA(255,255,255,128));
|
||||
dd.vertex(seg->q,duRGBA(255,255,255,128));
|
||||
for (int j = 0; j < seg->nints-1; ++j)
|
||||
{
|
||||
if (seg->ints[j].inside == 0) continue;
|
||||
const float u0 = seg->ints[j].u;
|
||||
const float u1 = seg->ints[j+1].u;
|
||||
float ia[3], ib[3];
|
||||
dtVlerp(ia, seg->p,seg->q, u0);
|
||||
dtVlerp(ib, seg->p,seg->q, u1);
|
||||
dd.vertex(ia,duRGBA(128,0,0,192));
|
||||
dd.vertex(ib,duRGBA(128,0,0,192));
|
||||
}
|
||||
}
|
||||
dd.end();
|
||||
|
||||
{
|
||||
const float r = m_sample->getAgentRadius();
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
for (int i = 0; i < m_form.nsegs; ++i)
|
||||
{
|
||||
const FormationSeg* seg = &m_form.segs[i];
|
||||
dd.vertex(seg->p,duRGBA(255,255,255,128));
|
||||
dd.vertex(seg->q,duRGBA(255,255,255,128));
|
||||
for (int j = 0; j < seg->nints-1; ++j)
|
||||
{
|
||||
if (seg->ints[j].inside == 0) continue;
|
||||
const float u0 = seg->ints[j].u;
|
||||
const float u1 = seg->ints[j+1].u;
|
||||
float ia[3], ib[3];
|
||||
dtVlerp(ia, seg->p,seg->q, u0);
|
||||
dtVlerp(ib, seg->p,seg->q, u1);
|
||||
|
||||
const float spacing = r*2.5f;
|
||||
float delta[3];
|
||||
dtVsub(delta, ib,ia);
|
||||
float d = dtVlen(delta);
|
||||
int np = (int)floorf(d/spacing);
|
||||
for (int k = 0; k < np; ++k)
|
||||
{
|
||||
float pos[3];
|
||||
dtVmad(pos, ia, delta, (float)(k+0.5f)/(float)np);
|
||||
dd.vertex(pos[0],pos[1]-1,pos[2],duRGBA(128,0,0,192));
|
||||
dd.vertex(pos[0],pos[1]+2,pos[2],duRGBA(128,0,0,192));
|
||||
}
|
||||
}
|
||||
}
|
||||
dd.end();
|
||||
}
|
||||
|
||||
dd.depthMask(true);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
|
||||
@ -622,15 +625,18 @@ void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
|
||||
}
|
||||
}
|
||||
|
||||
GraphParams gp;
|
||||
gp.setRect(300, 10, 500, 200, 8);
|
||||
gp.setValueRange(0.0f, 2.0f, 4, "ms");
|
||||
if (m_showPerfGraph)
|
||||
{
|
||||
GraphParams gp;
|
||||
gp.setRect(300, 10, 500, 200, 8);
|
||||
gp.setValueRange(0.0f, 2.0f, 4, "ms");
|
||||
|
||||
drawGraphBackground(&gp);
|
||||
drawGraph(&gp, &m_crowdRvoTime, 0, "RVO Sampling", duRGBA(255,0,128,255));
|
||||
drawGraph(&gp, &m_crowdTotalTime, 1, "Total", duRGBA(128,255,0,255));
|
||||
|
||||
gp.setRect(300, 10, 500, 50, 8);
|
||||
gp.setValueRange(0.0f, 2000.0f, 1, "0");
|
||||
drawGraph(&gp, &m_crowdSampleCount, 0, "Sample Count", duRGBA(255,255,255,255));
|
||||
drawGraphBackground(&gp);
|
||||
drawGraph(&gp, &m_crowdRvoTime, 0, "RVO Sampling", duRGBA(255,0,128,255));
|
||||
drawGraph(&gp, &m_crowdTotalTime, 1, "Total", duRGBA(128,255,0,255));
|
||||
|
||||
gp.setRect(300, 10, 500, 50, 8);
|
||||
gp.setValueRange(0.0f, 2000.0f, 1, "0");
|
||||
drawGraph(&gp, &m_crowdSampleCount, 0, "Sample Count", duRGBA(255,255,255,255));
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +321,10 @@ void NavMeshTesterTool::handleClick(const float* /*s*/, const float* p, bool shi
|
||||
}
|
||||
|
||||
void NavMeshTesterTool::handleStep()
|
||||
{
|
||||
}
|
||||
|
||||
void NavMeshTesterTool::handleToggle()
|
||||
{
|
||||
// TODO: merge separate to a path iterator. Use same code in recalc() too.
|
||||
if (m_toolMode != TOOLMODE_PATHFIND_FOLLOW)
|
||||
|
@ -132,6 +132,10 @@ void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, bool
|
||||
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::handleToggle()
|
||||
{
|
||||
}
|
||||
|
||||
void OffMeshConnectionTool::handleStep()
|
||||
{
|
||||
}
|
||||
|
@ -176,6 +176,12 @@ void Sample::handleClick(const float* s, const float* p, bool shift)
|
||||
m_tool->handleClick(s, p, shift);
|
||||
}
|
||||
|
||||
void Sample::handleToggle()
|
||||
{
|
||||
if (m_tool)
|
||||
m_tool->handleToggle();
|
||||
}
|
||||
|
||||
void Sample::handleStep()
|
||||
{
|
||||
if (m_tool)
|
||||
|
@ -357,10 +357,10 @@ void Sample_Debug::handleClick(const float* s, const float* p, bool shift)
|
||||
m_tool->handleClick(s, p, shift);
|
||||
}
|
||||
|
||||
void Sample_Debug::handleStep()
|
||||
void Sample_Debug::handleToggle()
|
||||
{
|
||||
if (m_tool)
|
||||
m_tool->handleStep();
|
||||
m_tool->handleToggle();
|
||||
}
|
||||
|
||||
bool Sample_Debug::handleBuild()
|
||||
|
@ -86,8 +86,10 @@ public:
|
||||
m_sample->setHighlightedTile(m_hitPos);
|
||||
}
|
||||
|
||||
virtual void handleToggle() {}
|
||||
|
||||
virtual void handleStep() {}
|
||||
|
||||
|
||||
virtual void handleUpdate(const float /*dt*/) {}
|
||||
|
||||
virtual void handleRender()
|
||||
|
@ -125,6 +125,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void handleToggle() {}
|
||||
|
||||
virtual void handleStep() {}
|
||||
|
||||
virtual void handleUpdate(const float /*dt*/) {}
|
||||
|
@ -204,14 +204,19 @@ int main(int /*argc*/, char** /*argv*/)
|
||||
else if (event.key.keysym.sym == SDLK_SPACE)
|
||||
{
|
||||
if (sample)
|
||||
sample->handleStep();
|
||||
sample->handleToggle();
|
||||
}
|
||||
else if (event.key.keysym.sym == SDLK_1)
|
||||
{
|
||||
if (sample)
|
||||
sample->handleStep();
|
||||
}
|
||||
else if (event.key.keysym.sym == SDLK_9)
|
||||
{
|
||||
if (geom)
|
||||
geom->save("geomset.txt");
|
||||
}
|
||||
else if (event.key.keysym.sym == SDLK_2)
|
||||
else if (event.key.keysym.sym == SDLK_0)
|
||||
{
|
||||
delete geom;
|
||||
geom = new InputGeom;
|
||||
|
Loading…
x
Reference in New Issue
Block a user