Hasty before flight check in. Some adjustments to VO code (renaming, optimize segment sampling). Crowd sim performance graph.
This commit is contained in:
parent
0e4aa30e85
commit
07ec6dfa08
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -283,14 +283,13 @@
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
|
||||
<array>
|
||||
<array>
|
||||
<integer>17</integer>
|
||||
<integer>11</integer>
|
||||
<integer>59</integer>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</array>
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
|
||||
<string>{{0, 0}, {264, 660}}</string>
|
||||
<string>{{0, 646}, {264, 660}}</string>
|
||||
</dict>
|
||||
<key>PBXTopSmartGroupGIDs</key>
|
||||
<array/>
|
||||
@ -325,7 +324,7 @@
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>6B8632A30F78115100E2684A</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>DetourNavMeshQuery.cpp</string>
|
||||
<string>CrowdTool.cpp</string>
|
||||
<key>PBXSplitModuleInNavigatorKey</key>
|
||||
<dict>
|
||||
<key>Split0</key>
|
||||
@ -333,11 +332,11 @@
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>6B8632A40F78115100E2684A</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>DetourNavMeshQuery.cpp</string>
|
||||
<string>CrowdTool.cpp</string>
|
||||
<key>_historyCapacity</key>
|
||||
<integer>0</integer>
|
||||
<key>bookmark</key>
|
||||
<string>6B1C8DAF121E821F0048697F</string>
|
||||
<string>6B1C8E6F1221BC910048697F</string>
|
||||
<key>history</key>
|
||||
<array>
|
||||
<string>6BBB4AA5115B4F3400CF791D</string>
|
||||
@ -356,7 +355,6 @@
|
||||
<string>6BAF3CB012116AD9008CFCDF</string>
|
||||
<string>6BAF3CB112116AD9008CFCDF</string>
|
||||
<string>6BAF3CB412116AD9008CFCDF</string>
|
||||
<string>6BAF3DFC1211AEB2008CFCDF</string>
|
||||
<string>6BAF3E781212869F008CFCDF</string>
|
||||
<string>6BAF404F12140B4E008CFCDF</string>
|
||||
<string>6BAF405112140B4E008CFCDF</string>
|
||||
@ -376,7 +374,6 @@
|
||||
<string>6BAF4524121D1723008CFCDF</string>
|
||||
<string>6BAF4525121D1723008CFCDF</string>
|
||||
<string>6BAF4562121D1849008CFCDF</string>
|
||||
<string>6BAF457C121D19CB008CFCDF</string>
|
||||
<string>6BAF457D121D19CB008CFCDF</string>
|
||||
<string>6BAF457E121D19CB008CFCDF</string>
|
||||
<string>6BAF457F121D19CB008CFCDF</string>
|
||||
@ -384,18 +381,13 @@
|
||||
<string>6BAF4581121D19CB008CFCDF</string>
|
||||
<string>6BAF4582121D19CB008CFCDF</string>
|
||||
<string>6BAF4593121D1B18008CFCDF</string>
|
||||
<string>6BAF45AC121D2C03008CFCDF</string>
|
||||
<string>6BAF45B8121D2F37008CFCDF</string>
|
||||
<string>6BAF45E4121D7277008CFCDF</string>
|
||||
<string>6BAF4604121D7388008CFCDF</string>
|
||||
<string>6BAF4605121D7388008CFCDF</string>
|
||||
<string>6BAF4607121D7388008CFCDF</string>
|
||||
<string>6BAF461E121D746C008CFCDF</string>
|
||||
<string>6BAF4637121D74D3008CFCDF</string>
|
||||
<string>6BAF46A0121D8B41008CFCDF</string>
|
||||
<string>6BAF46A1121D8B41008CFCDF</string>
|
||||
<string>6BAF46A2121D8B41008CFCDF</string>
|
||||
<string>6BAF46A3121D8B41008CFCDF</string>
|
||||
<string>6BAF46D3121D8FF1008CFCDF</string>
|
||||
<string>6BAF4739121D9FBE008CFCDF</string>
|
||||
<string>6BAF473A121D9FBE008CFCDF</string>
|
||||
@ -403,17 +395,25 @@
|
||||
<string>6BAF475A121DA31D008CFCDF</string>
|
||||
<string>6BAF475B121DA31D008CFCDF</string>
|
||||
<string>6BAF475C121DA31D008CFCDF</string>
|
||||
<string>6BAF475D121DA31D008CFCDF</string>
|
||||
<string>6BAF475E121DA31D008CFCDF</string>
|
||||
<string>6BAF475F121DA31D008CFCDF</string>
|
||||
<string>6BAF4760121DA31D008CFCDF</string>
|
||||
<string>6BAF4778121DCAF9008CFCDF</string>
|
||||
<string>6BAF478E121DD150008CFCDF</string>
|
||||
<string>6B1C8D82121E80950048697F</string>
|
||||
<string>6B1C8DA2121E813D0048697F</string>
|
||||
<string>6B1C8DA3121E813D0048697F</string>
|
||||
<string>6B1C8DAD121E821F0048697F</string>
|
||||
<string>6B1C8DA8121E81C40048697F</string>
|
||||
<string>6B1C8DB3121E8D970048697F</string>
|
||||
<string>6B1C8DBF121E8F610048697F</string>
|
||||
<string>6B1C8DC0121E8F610048697F</string>
|
||||
<string>6B1C8DC5121E902F0048697F</string>
|
||||
<string>6B1C8DD8121EA3470048697F</string>
|
||||
<string>6B1C8E08121EB4FF0048697F</string>
|
||||
<string>6B1C8E09121EB4FF0048697F</string>
|
||||
<string>6B1C8E0A121EB4FF0048697F</string>
|
||||
<string>6B1C8E0C121EB4FF0048697F</string>
|
||||
<string>6B1C8E24121EB6D30048697F</string>
|
||||
<string>6B1C8E27121EB6D30048697F</string>
|
||||
<string>6B1C8E30121EB9310048697F</string>
|
||||
<string>6B1C8E691221BC910048697F</string>
|
||||
<string>6B1C8E6A1221BC910048697F</string>
|
||||
<string>6B1C8E6B1221BC910048697F</string>
|
||||
</array>
|
||||
<key>prevStack</key>
|
||||
<array>
|
||||
@ -458,11 +458,7 @@
|
||||
<string>6BAF3B1512112F65008CFCDF</string>
|
||||
<string>6BAF3DAA1211882E008CFCDF</string>
|
||||
<string>6BAF3E631211B713008CFCDF</string>
|
||||
<string>6BAF3F5F1213E45B008CFCDF</string>
|
||||
<string>6BBB4AE2115B4F3400CF791D</string>
|
||||
<string>6BBB4AF7115B4F3400CF791D</string>
|
||||
<string>6BAF405912140B4E008CFCDF</string>
|
||||
<string>6BAF40A612142254008CFCDF</string>
|
||||
<string>6BAF411712197F3D008CFCDF</string>
|
||||
<string>6BAF41801219811E008CFCDF</string>
|
||||
<string>6BAF41DA121A5D13008CFCDF</string>
|
||||
@ -481,37 +477,43 @@
|
||||
<string>6BAF410212197F3D008CFCDF</string>
|
||||
<string>6BAF44FA121C5713008CFCDF</string>
|
||||
<string>6BAF45E9121D7277008CFCDF</string>
|
||||
<string>6BAF4455121C40AC008CFCDF</string>
|
||||
<string>6BAF447E121C4895008CFCDF</string>
|
||||
<string>6BAF473D121D9FBE008CFCDF</string>
|
||||
<string>6BAF4749121D9FED008CFCDF</string>
|
||||
<string>6BAF4762121DA31D008CFCDF</string>
|
||||
<string>6BAF4767121DA31D008CFCDF</string>
|
||||
<string>6BAF4768121DA31D008CFCDF</string>
|
||||
<string>6BAF4797121DD34D008CFCDF</string>
|
||||
<string>6B1C8D84121E80950048697F</string>
|
||||
<string>6B1C8D85121E80950048697F</string>
|
||||
<string>6B1C8D86121E80950048697F</string>
|
||||
<string>6B1C8D87121E80950048697F</string>
|
||||
<string>6B1C8D88121E80950048697F</string>
|
||||
<string>6B1C8D89121E80950048697F</string>
|
||||
<string>6B1C8D8A121E80950048697F</string>
|
||||
<string>6B1C8D8B121E80950048697F</string>
|
||||
<string>6B1C8D8C121E80950048697F</string>
|
||||
<string>6B1C8D8D121E80950048697F</string>
|
||||
<string>6B1C8D8E121E80950048697F</string>
|
||||
<string>6B1C8D8F121E80950048697F</string>
|
||||
<string>6B1C8D90121E80950048697F</string>
|
||||
<string>6B1C8D91121E80950048697F</string>
|
||||
<string>6B1C8D92121E80950048697F</string>
|
||||
<string>6B1C8D93121E80950048697F</string>
|
||||
<string>6B1C8D94121E80950048697F</string>
|
||||
<string>6B1C8D95121E80950048697F</string>
|
||||
<string>6B1C8D96121E80950048697F</string>
|
||||
<string>6B1C8DA5121E813D0048697F</string>
|
||||
<string>6B1C8DA6121E813D0048697F</string>
|
||||
<string>6B1C8DAA121E81C40048697F</string>
|
||||
<string>6B1C8DAE121E821F0048697F</string>
|
||||
<string>6B1C8DB6121E8D970048697F</string>
|
||||
<string>6B1C8DB7121E8D970048697F</string>
|
||||
<string>6B1C8DDB121EA3470048697F</string>
|
||||
<string>6B1C8E11121EB4FF0048697F</string>
|
||||
<string>6B1C8E12121EB4FF0048697F</string>
|
||||
<string>6B1C8E13121EB4FF0048697F</string>
|
||||
<string>6B1C8E14121EB4FF0048697F</string>
|
||||
<string>6B1C8E1B121EB4FF0048697F</string>
|
||||
<string>6B1C8E2A121EB6D30048697F</string>
|
||||
<string>6B1C8E2B121EB6D30048697F</string>
|
||||
<string>6B1C8E2D121EB6D30048697F</string>
|
||||
<string>6B1C8E2E121EB6D30048697F</string>
|
||||
<string>6B1C8E58121EBEBF0048697F</string>
|
||||
<string>6B1C8E59121EBEBF0048697F</string>
|
||||
<string>6B1C8E661221BC080048697F</string>
|
||||
<string>6B1C8E6C1221BC910048697F</string>
|
||||
<string>6B1C8E6D1221BC910048697F</string>
|
||||
<string>6B1C8E6E1221BC910048697F</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>SplitCount</key>
|
||||
@ -525,18 +527,18 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {994, 606}}</string>
|
||||
<string>{{0, 0}, {994, 505}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXNavigatorGroup</string>
|
||||
<key>Proportion</key>
|
||||
<string>606pt</string>
|
||||
<string>505pt</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Proportion</key>
|
||||
<string>67pt</string>
|
||||
<string>168pt</string>
|
||||
<key>Tabs</key>
|
||||
<array>
|
||||
<dict>
|
||||
@ -604,7 +606,7 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {994, 40}}</string>
|
||||
<string>{{10, 27}, {994, 141}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
</dict>
|
||||
|
@ -24,19 +24,20 @@
|
||||
|
||||
// Tool to create crowds.
|
||||
|
||||
|
||||
enum BodyType
|
||||
{
|
||||
BODY_CIRCLE = 0,
|
||||
BODY_CAPSULE = 1,
|
||||
BODY_SEGMENT = 1,
|
||||
};
|
||||
|
||||
struct Body
|
||||
struct ObstacleBody
|
||||
{
|
||||
float p[3], q[3]; // Position of the obstacle
|
||||
float vel[3]; // Velocity of the obstacle
|
||||
float dvel[3]; // Velocity of the obstacle
|
||||
float rad; // Radius of the obstacle
|
||||
float dp[3], np[3]; // Use for side selection during sampling.
|
||||
bool touch;
|
||||
int type; // Type of the obstacle (see ObstacleType)
|
||||
};
|
||||
|
||||
@ -44,9 +45,9 @@ struct Body
|
||||
static const int RVO_SAMPLE_RAD = 15;
|
||||
static const int MAX_RVO_SAMPLES = (RVO_SAMPLE_RAD*2+1)*(RVO_SAMPLE_RAD*2+1) + 100;
|
||||
|
||||
struct RVO
|
||||
struct RVODebugData
|
||||
{
|
||||
inline RVO() : ns(0) {}
|
||||
inline RVODebugData() : ns(0) {}
|
||||
float spos[MAX_RVO_SAMPLES*3];
|
||||
float scs[MAX_RVO_SAMPLES];
|
||||
float spen[MAX_RVO_SAMPLES];
|
||||
@ -90,11 +91,13 @@ struct Agent
|
||||
float npos[3];
|
||||
float disp[3];
|
||||
|
||||
float opts[3], opte[3];
|
||||
|
||||
float maxspeed;
|
||||
float t;
|
||||
float var;
|
||||
|
||||
RVO rvo;
|
||||
RVODebugData rvo;
|
||||
|
||||
float colradius;
|
||||
float colcenter[3];
|
||||
@ -116,6 +119,59 @@ struct Agent
|
||||
unsigned char active;
|
||||
};
|
||||
|
||||
|
||||
class SampleGraph
|
||||
{
|
||||
static const int MAX_SAMPLES = 512;
|
||||
float m_samples[MAX_SAMPLES];
|
||||
int m_hsamples;
|
||||
public:
|
||||
SampleGraph() :
|
||||
m_hsamples(0)
|
||||
{
|
||||
for (int i = 0; i < MAX_SAMPLES; ++i)
|
||||
m_samples[i] = 0;
|
||||
}
|
||||
|
||||
~SampleGraph()
|
||||
{
|
||||
}
|
||||
|
||||
inline void addSample(const float val)
|
||||
{
|
||||
m_hsamples = (m_hsamples+MAX_SAMPLES-1) % MAX_SAMPLES;
|
||||
m_samples[m_hsamples] = val;
|
||||
}
|
||||
|
||||
inline int getSampleCount() const
|
||||
{
|
||||
return MAX_SAMPLES;
|
||||
}
|
||||
|
||||
inline float getSample(const int i) const
|
||||
{
|
||||
return m_samples[(m_hsamples+i) % MAX_SAMPLES];
|
||||
}
|
||||
|
||||
inline float getSampleMin() const
|
||||
{
|
||||
float val = m_samples[0];
|
||||
for (int i = 1; i < MAX_SAMPLES; ++i)
|
||||
if (m_samples[i] < val)
|
||||
val = m_samples[i];
|
||||
return val;
|
||||
}
|
||||
|
||||
inline float getSampleMax() const
|
||||
{
|
||||
float val = m_samples[0];
|
||||
for (int i = 1; i < MAX_SAMPLES; ++i)
|
||||
if (m_samples[i] > val)
|
||||
val = m_samples[i];
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
enum UpdateFlags
|
||||
{
|
||||
CROWDMAN_ANTICIPATE_TURNS = 1,
|
||||
@ -128,6 +184,10 @@ class CrowdManager
|
||||
static const int MAX_AGENTS = 32;
|
||||
Agent m_agents[MAX_AGENTS];
|
||||
int m_shortcutIter;
|
||||
|
||||
SampleGraph m_totalTime;
|
||||
SampleGraph m_rvoTime;
|
||||
|
||||
public:
|
||||
CrowdManager();
|
||||
~CrowdManager();
|
||||
@ -140,6 +200,9 @@ public:
|
||||
void setMoveTarget(const int idx, const float* pos);
|
||||
|
||||
void update(const float dt, unsigned int flags, dtNavMeshQuery* navquery);
|
||||
|
||||
const SampleGraph* getTotalTimeGraph() const { return &m_totalTime; }
|
||||
const SampleGraph* getRVOTimeGraph() const { return &m_rvoTime; }
|
||||
};
|
||||
|
||||
class CrowdTool : public SampleTool
|
||||
@ -155,6 +218,7 @@ class CrowdTool : public SampleTool
|
||||
bool m_showCollisionSegments;
|
||||
bool m_showPath;
|
||||
bool m_showVO;
|
||||
bool m_showOpt;
|
||||
|
||||
bool m_expandOptions;
|
||||
bool m_anticipateTurns;
|
||||
@ -164,7 +228,7 @@ class CrowdTool : public SampleTool
|
||||
bool m_run;
|
||||
|
||||
CrowdManager m_crowd;
|
||||
|
||||
|
||||
enum ToolMode
|
||||
{
|
||||
TOOLMODE_CREATE,
|
||||
|
@ -16,6 +16,9 @@
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef SAMPLEINTERFACES_H
|
||||
#define SAMPLEINTERFACES_H
|
||||
|
||||
#include "DebugDraw.h"
|
||||
#include "Recast.h"
|
||||
#include "RecastDump.h"
|
||||
@ -62,6 +65,12 @@ public:
|
||||
virtual int getBuildTime(const rcBuilTimeLabel label);
|
||||
};
|
||||
|
||||
|
||||
// TODO: Find better solution. This is useful for timing in some cases when the full build interface would be overkill.
|
||||
rcTimeVal getPerfTime();
|
||||
int getPerfDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end);
|
||||
|
||||
|
||||
// OpenGL debug draw implementation.
|
||||
class DebugDrawGL : public duDebugDraw
|
||||
{
|
||||
@ -88,3 +97,6 @@ public:
|
||||
virtual bool write(const void* ptr, const size_t size);
|
||||
virtual bool read(void* ptr, const size_t size);
|
||||
};
|
||||
|
||||
#endif // SAMPLEINTERFACES_H
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "Sample.h"
|
||||
#include "DetourDebugDraw.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "SampleInterfaces.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# define snprintf _snprintf
|
||||
@ -197,7 +198,7 @@ static void normalizeArray(float* arr, const int n)
|
||||
arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void normalizeSamples(RVO* rvo)
|
||||
void normalizeSamples(RVODebugData* rvo)
|
||||
{
|
||||
normalizeArray(rvo->spen, rvo->ns);
|
||||
normalizeArray(rvo->svpen, rvo->ns);
|
||||
@ -207,7 +208,7 @@ void normalizeSamples(RVO* rvo)
|
||||
}
|
||||
|
||||
|
||||
void setDynCircleBody(Body* b, const float* pos, const float rad, const float* vel, const float* dvel)
|
||||
void setDynCircleBody(ObstacleBody* b, const float* pos, const float rad, const float* vel, const float* dvel)
|
||||
{
|
||||
b->type = BODY_CIRCLE;
|
||||
dtVcopy(b->p, pos);
|
||||
@ -216,7 +217,7 @@ void setDynCircleBody(Body* b, const float* pos, const float rad, const float* v
|
||||
b->rad = rad;
|
||||
}
|
||||
|
||||
void setStatCircleBody(Body* b, const float* pos, const float rad)
|
||||
void setStatCircleBody(ObstacleBody* b, const float* pos, const float rad)
|
||||
{
|
||||
b->type = BODY_CIRCLE;
|
||||
dtVcopy(b->p, pos);
|
||||
@ -225,14 +226,14 @@ void setStatCircleBody(Body* b, const float* pos, const float rad)
|
||||
b->rad = rad;
|
||||
}
|
||||
|
||||
void setStatCapsuleBody(Body* b, const float* p, const float* q, const float rad)
|
||||
void setStatSegmentBody(ObstacleBody* b, const float* p, const float* q)
|
||||
{
|
||||
b->type = BODY_CAPSULE;
|
||||
b->type = BODY_SEGMENT;
|
||||
dtVcopy(b->p, p);
|
||||
dtVcopy(b->q, q);
|
||||
dtVset(b->vel, 0,0,0);
|
||||
dtVset(b->dvel, 0,0,0);
|
||||
b->rad = rad;
|
||||
b->rad = 0;
|
||||
}
|
||||
|
||||
static const float VEL_WEIGHT = 2.0f;
|
||||
@ -261,84 +262,66 @@ static int sweepCircleCircle(const float* c0, const float r0, const float* v,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sweepCircleSegment(const float* c0, const float r0, const float* v,
|
||||
const float* sa, const float* sb, const float sr,
|
||||
float& tmin, float &tmax)
|
||||
static void prepareBodies(const ObstacleBody* agent, ObstacleBody* obs, const int nobs)
|
||||
{
|
||||
// equation parameters
|
||||
float L[3], H[3];
|
||||
dtVsub(L, sb, sa);
|
||||
dtVsub(H, c0, sa);
|
||||
const float radius = r0+sr;
|
||||
const float l2 = dtVdot2D(L, L);
|
||||
const float r2 = radius * radius;
|
||||
const float dl = dtVperp2D(v, L);
|
||||
const float hl = dtVperp2D(H, L);
|
||||
const float a = dl * dl;
|
||||
const float b = 2.0f * hl * dl;
|
||||
const float c = hl * hl - (r2 * l2);
|
||||
float d = (b*b) - (4.0f * a * c);
|
||||
|
||||
// infinite line missed by infinite ray.
|
||||
if (d < 0.0f)
|
||||
return 0;
|
||||
|
||||
const float i2a = 1.0f/(2*a);
|
||||
d = dtSqrt(d);
|
||||
tmin = (-b - d) * i2a;
|
||||
tmax = (-b + d) * i2a;
|
||||
|
||||
// line missed by ray range.
|
||||
/* if (tmax < 0.0f || tmin > 1.0f)
|
||||
return 0;*/
|
||||
|
||||
// find what part of the ray was collided.
|
||||
const float il2 = 1.0f / l2;
|
||||
float Pedge[3];
|
||||
dtVmad(Pedge, c0, v, tmin);
|
||||
dtVsub(H, Pedge, sa);
|
||||
const float e0 = dtVdot2D(H, L) * il2;
|
||||
dtVmad(Pedge, c0, v, tmax);
|
||||
dtVsub(H, Pedge, sa);
|
||||
const float e1 = dtVdot2D(H, L) * il2;
|
||||
|
||||
if (e0 < 0.0f || e1 < 0.0f)
|
||||
for (int i = 0; i < nobs; ++i)
|
||||
{
|
||||
float ctmin, ctmax;
|
||||
if (sweepCircleCircle(c0, r0, v, sa, sr, ctmin, ctmax))
|
||||
ObstacleBody* ob = &obs[i];
|
||||
|
||||
if (ob->type == BODY_CIRCLE)
|
||||
{
|
||||
if (e0 < 0.0f && ctmin > tmin)
|
||||
tmin = ctmin;
|
||||
if (e1 < 0.0f && ctmax < tmax)
|
||||
tmax = ctmax;
|
||||
// Side
|
||||
const float* pa = agent->p;
|
||||
const float* pb = ob->p;
|
||||
|
||||
const float orig[3] = {0,0};
|
||||
float dv[3];
|
||||
dtVsub(ob->dp,pb,pa);
|
||||
dtVnormalize(ob->dp);
|
||||
dtVsub(dv, ob->dvel, agent->dvel);
|
||||
|
||||
const float a = dtTriArea2D(orig, ob->dp,dv);
|
||||
if (a < 0.01f)
|
||||
{
|
||||
ob->np[0] = -ob->dp[2];
|
||||
ob->np[2] = ob->dp[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
ob->np[0] = ob->dp[2];
|
||||
ob->np[2] = -ob->dp[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (ob->type == BODY_SEGMENT)
|
||||
{
|
||||
return 0;
|
||||
// Precalc if the agent is really close to the segment.
|
||||
const float r = 0.01f;
|
||||
float t;
|
||||
ob->touch = dtDistancePtSegSqr2D(agent->p, ob->p, ob->q, t) < dtSqr(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (e0 > 1.0f || e1 > 1.0f)
|
||||
{
|
||||
float ctmin, ctmax;
|
||||
if (sweepCircleCircle(c0, r0, v, sb, sr, ctmin, ctmax))
|
||||
{
|
||||
if (e0 > 1.0f && ctmin > tmin)
|
||||
tmin = ctmin;
|
||||
if (e1 > 1.0f && ctmax < tmax)
|
||||
tmax = ctmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int isectRaySeg(const float* ap, const float* u,
|
||||
const float* bp, const float* bq,
|
||||
float& t)
|
||||
{
|
||||
float /*u[3]*/ v[3], w[3];
|
||||
// dtVsub(u,aq,ap);
|
||||
dtVsub(v,bq,bp);
|
||||
dtVsub(w,ap,bp);
|
||||
float d = dtVperp2D(u,v);
|
||||
if (fabsf(d) < 1e-6f) return 0;
|
||||
d = 1.0f/d;
|
||||
t = dtVperp2D(v,w) * d;
|
||||
if (t < 0 || t > 1) return 0;
|
||||
float s = dtVperp2D(u,w) * d;
|
||||
if (s < 0 || s > 1) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void processSamples(Body* agent, const float vmax,
|
||||
const Body* obs, const int nobs, RVO* rvo,
|
||||
static void processSamples(ObstacleBody* agent, const float vmax,
|
||||
const ObstacleBody* obs, const int nobs, RVODebugData* rvo,
|
||||
const float* spos, const float cs, const int nspos,
|
||||
float* res)
|
||||
{
|
||||
@ -365,7 +348,7 @@ static void processSamples(Body* agent, const float vmax,
|
||||
|
||||
for (int i = 0; i < nobs; ++i)
|
||||
{
|
||||
const Body* ob = &obs[i];
|
||||
const ObstacleBody* ob = &obs[i];
|
||||
float htmin = 0, htmax = 0;
|
||||
|
||||
if (ob->type == BODY_CIRCLE)
|
||||
@ -378,30 +361,7 @@ static void processSamples(Body* agent, const float vmax,
|
||||
dtVsub(vab, vab, ob->vel);
|
||||
|
||||
// Side
|
||||
// NOTE: dp, and dv are constant over the whole calculation,
|
||||
// they can be precomputed per object.
|
||||
const float* pa = agent->p;
|
||||
const float* pb = ob->p;
|
||||
|
||||
const float orig[3] = {0,0};
|
||||
float dp[3],dv[3],np[3];
|
||||
dtVsub(dp,pb,pa);
|
||||
dtVnormalize(dp);
|
||||
dtVsub(dv, ob->dvel, agent->dvel);
|
||||
|
||||
const float a = dtTriArea2D(orig, dp,dv);
|
||||
if (a < 0.01f)
|
||||
{
|
||||
np[0] = -dp[2];
|
||||
np[2] = dp[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
np[0] = dp[2];
|
||||
np[2] = -dp[0];
|
||||
}
|
||||
|
||||
side += dtClamp(dtMin(dtVdot2D(dp,vab)*2,dtVdot2D(np,vab)*2), 0.0f, 1.0f);
|
||||
side += dtClamp(dtMin(dtVdot2D(ob->dp,vab)*2, dtVdot2D(ob->np,vab)*2), 0.0f, 1.0f);
|
||||
nside++;
|
||||
|
||||
if (!sweepCircleCircle(agent->p,agent->rad, vab, ob->p,ob->rad, htmin, htmax))
|
||||
@ -414,17 +374,11 @@ static void processSamples(Body* agent, const float vmax,
|
||||
htmin = -htmin * 0.5f;
|
||||
}
|
||||
}
|
||||
else if (ob->type == BODY_CAPSULE)
|
||||
else if (ob->type == BODY_SEGMENT)
|
||||
{
|
||||
// NOTE: the segments are assumed to come from a navmesh which is shrunken by
|
||||
// the agent radius, hence the use of really small radius.
|
||||
// This can be handle more efficiently by using seg-seg test instead.
|
||||
// If the whole segment is to be treated as obstacle, use agent->rad instead of 0.01f!
|
||||
const float r = 0.01f; // agent->rad
|
||||
|
||||
float t;
|
||||
if (dtDistancePtSegSqr2D(agent->p, ob->p, ob->q, t) < dtSqr(r+ob->rad))
|
||||
if (ob->touch)
|
||||
{
|
||||
// Special case when the agent is very close to the segment.
|
||||
float sdir[3], snorm[3];
|
||||
dtVsub(sdir, ob->q, ob->p);
|
||||
snorm[0] = -sdir[2];
|
||||
@ -438,8 +392,9 @@ static void processSamples(Body* agent, const float vmax,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sweepCircleSegment(agent->p, r, vcand, ob->p, ob->q, ob->rad, htmin, htmax))
|
||||
if (!isectRaySeg(agent->p, vcand, ob->p, ob->q, htmin))
|
||||
continue;
|
||||
htmax = maxToi;
|
||||
}
|
||||
|
||||
// Avoid less when facing walls.
|
||||
@ -483,7 +438,8 @@ static void processSamples(Body* agent, const float vmax,
|
||||
}
|
||||
|
||||
|
||||
void sampleRVO(Body* agent, const float vmax, const Body* obs, const int nobs, RVO* rvo, const float bias, float* nvel)
|
||||
void sampleRVO(ObstacleBody* agent, const float vmax, const ObstacleBody* obs,
|
||||
const int nobs, RVODebugData* rvo, const float bias, float* nvel)
|
||||
{
|
||||
dtVset(nvel, 0,0,0);
|
||||
|
||||
@ -620,6 +576,8 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
if (!navquery)
|
||||
return;
|
||||
|
||||
rcTimeVal startTime = getPerfTime();
|
||||
|
||||
const float ext[3] = {2,4,2};
|
||||
dtQueryFilter filter;
|
||||
|
||||
@ -802,8 +760,9 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
}
|
||||
|
||||
// Velocity planning.
|
||||
rcTimeVal rvoStartTime = getPerfTime();
|
||||
static const int MAX_BODIES = 32;
|
||||
Body bodies[MAX_BODIES];
|
||||
ObstacleBody bodies[MAX_BODIES];
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
@ -847,14 +806,14 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
|
||||
if (nbodies < MAX_BODIES)
|
||||
{
|
||||
setStatCapsuleBody(&bodies[nbodies], s,s+3,0);
|
||||
setStatSegmentBody(&bodies[nbodies], s,s+3);
|
||||
nbodies++;
|
||||
}
|
||||
}
|
||||
|
||||
Body agent;
|
||||
ObstacleBody agent;
|
||||
setDynCircleBody(&agent, ag->pos, ag->radius, ag->vel, ag->dvel);
|
||||
|
||||
prepareBodies(&agent, bodies, nbodies);
|
||||
sampleRVO(&agent, ag->maxspeed, bodies, nbodies, &ag->rvo, 0.4f, ag->nvel);
|
||||
|
||||
// Normalize samples for debug draw
|
||||
@ -865,7 +824,9 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
dtVcopy(ag->nvel, ag->dvel);
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal rvoEndTime = getPerfTime();
|
||||
m_rvoTime.addSample(getPerfDeltaTimeUsec(rvoStartTime, rvoEndTime) / 1000.0f);
|
||||
|
||||
// Integrate and update perceived velocity.
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
@ -967,13 +928,30 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
dtVset(ag->opts, 0,0,0);
|
||||
dtVset(ag->opte, 0,0,0);
|
||||
|
||||
if (ag->npath && ag->ncorners > 1)
|
||||
{
|
||||
// The target is the corner after the next corner to steer to.
|
||||
const float* tgt = &ag->corners[3];
|
||||
float tgt[3];
|
||||
dtVcopy(tgt, &ag->corners[3]);
|
||||
const float distSqr = dtVdist2DSqr(ag->pos, tgt);
|
||||
if (distSqr > dtSqr(0.01f)) // && distSqr < dtSqr(20.0f))
|
||||
if (distSqr > dtSqr(0.01f))
|
||||
{
|
||||
// Clamp teh ray to max distance.
|
||||
const float maxDist = ag->colradius*3;
|
||||
if (distSqr > dtSqr(maxDist))
|
||||
{
|
||||
float delta[3];
|
||||
dtVsub(delta, tgt, ag->pos);
|
||||
dtVmad(tgt, ag->pos, delta, dtSqr(maxDist)/distSqr);
|
||||
}
|
||||
|
||||
dtVcopy(ag->opts, ag->pos);
|
||||
dtVcopy(ag->opte, tgt);
|
||||
|
||||
static const int MAX_RES = 32;
|
||||
dtPolyRef res[MAX_RES];
|
||||
float t, norm[3];
|
||||
@ -986,6 +964,9 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal endTime = getPerfTime();
|
||||
|
||||
m_totalTime.addSample(getPerfDeltaTimeUsec(startTime, endTime) / 1000.0f);
|
||||
}
|
||||
|
||||
|
||||
@ -1000,6 +981,7 @@ CrowdTool::CrowdTool() :
|
||||
m_showCollisionSegments(false),
|
||||
m_showPath(false),
|
||||
m_showVO(false),
|
||||
m_showOpt(false),
|
||||
m_expandOptions(true),
|
||||
m_anticipateTurns(true),
|
||||
m_useVO(true),
|
||||
@ -1079,6 +1061,8 @@ void CrowdTool::handleMenu()
|
||||
m_showPath = !m_showPath;
|
||||
if (imguiCheck("Show VO", m_showVO))
|
||||
m_showVO = !m_showVO;
|
||||
if (imguiCheck("Show Opt", m_showOpt))
|
||||
m_showOpt = !m_showOpt;
|
||||
imguiUnindent();
|
||||
}
|
||||
}
|
||||
@ -1276,10 +1260,18 @@ void CrowdTool::handleRender()
|
||||
dd.end();
|
||||
}
|
||||
|
||||
if (m_showOpt)
|
||||
{
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
dd.vertex(ag->opts[0],ag->opts[1]+0.3f,ag->opts[2], duRGBA(0,128,0,192));
|
||||
dd.vertex(ag->opte[0],ag->opte[1]+0.3f,ag->opte[2], duRGBA(0,128,0,192));
|
||||
dd.end();
|
||||
}
|
||||
|
||||
if (m_showVO)
|
||||
{
|
||||
// Draw detail about agent sela
|
||||
const RVO* rvo = &ag->rvo;
|
||||
const RVODebugData* rvo = &ag->rvo;
|
||||
|
||||
const float dx = ag->pos[0];
|
||||
const float dy = ag->pos[1]+ag->height;
|
||||
@ -1316,6 +1308,69 @@ void CrowdTool::handleRender()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drawGraphBackground(const int x, const int y, const int w, const int h,
|
||||
const float vmin, const float vmax, const int ndiv,
|
||||
const char* units)
|
||||
{
|
||||
// BG
|
||||
DebugDrawGL dd;
|
||||
dd.begin(DU_DRAW_QUADS);
|
||||
dd.vertex(x,y,0, duRGBA(0,0,0,64));
|
||||
dd.vertex(x+w,y,0, duRGBA(0,0,0,96));
|
||||
dd.vertex(x+w,y+h,0, duRGBA(128,128,128,64));
|
||||
dd.vertex(x,y+h,0, duRGBA(128,128,128,64));
|
||||
dd.end();
|
||||
|
||||
const int pad = 10;
|
||||
|
||||
const float sy = (h-pad*2) / (vmax-vmin);
|
||||
const float oy = y+pad-vmin*sy;
|
||||
|
||||
char text[64];
|
||||
|
||||
// Divider Lines
|
||||
for (int i = 0; i < ndiv; ++i)
|
||||
{
|
||||
const float u = (float)i/(float)ndiv;
|
||||
const float v = vmin + (vmax-vmin)*u;
|
||||
snprintf(text, 64, "%.2f %s", v, units);
|
||||
const float fy = oy + v*sy;
|
||||
imguiDrawText(x+w-pad, (int)fy-4, IMGUI_ALIGN_RIGHT, text, imguiRGBA(0,0,0,255));
|
||||
dd.begin(DU_DRAW_LINES, 1.0f);
|
||||
dd.vertex(x,fy,0,duRGBA(0,0,0,64));
|
||||
dd.vertex(x+w-pad-60,fy,0,duRGBA(0,0,0,64));
|
||||
dd.end();
|
||||
}
|
||||
}
|
||||
|
||||
static void drawGraph(const SampleGraph* graph,
|
||||
const int x, const int y, const int w, const int h,
|
||||
const float vmin, const float vmax, const unsigned int col)
|
||||
{
|
||||
DebugDrawGL dd;
|
||||
|
||||
const int pad = 10;
|
||||
|
||||
const float sx = (w-pad*2) / (float)graph->getSampleCount();
|
||||
const float sy = (h-pad*2) / (vmax-vmin);
|
||||
const float ox = x+pad;
|
||||
const float oy = y+pad-vmin*sy;
|
||||
|
||||
// Values
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
for (int i = 0; i < graph->getSampleCount()-1; ++i)
|
||||
{
|
||||
const float fx0 = ox + i*sx;
|
||||
const float fy0 = oy + graph->getSample(i)*sy;
|
||||
const float fx1 = ox + (i+1)*sx;
|
||||
const float fy1 = oy + graph->getSample(i+1)*sy;
|
||||
dd.vertex(fx0,fy0,0,col);
|
||||
dd.vertex(fx1,fy1,0,col);
|
||||
}
|
||||
dd.end();
|
||||
}
|
||||
|
||||
void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
|
||||
{
|
||||
GLdouble x, y, z;
|
||||
@ -1344,4 +1399,11 @@ void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const int gx = 300, gy = 10, gw = 500, gh = 200;
|
||||
const float vmin = 0.0f, vmax = 10.0f;
|
||||
|
||||
drawGraphBackground(gx,gy,gw,gh, vmin,vmax, 4, "ms");
|
||||
drawGraph(m_crowd.getRVOTimeGraph(), gx,gy,gw,gh, vmin,vmax, duRGBA(255,0,0,128));
|
||||
drawGraph(m_crowd.getTotalTimeGraph(), gx,gy,gw,gh, vmin,vmax, duRGBA(192,255,0,192));
|
||||
}
|
||||
|
@ -174,6 +174,49 @@ int BuildContext::getBuildTime(const rcBuilTimeLabel label)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
// Win32
|
||||
#include <windows.h>
|
||||
|
||||
rcTimeVal getPerfTime()
|
||||
{
|
||||
__int64 count;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&count);
|
||||
return count;
|
||||
}
|
||||
|
||||
int getPerfDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end)
|
||||
{
|
||||
static __int64 freq = 0;
|
||||
if (freq == 0)
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
|
||||
__int64 elapsed = end - start;
|
||||
return (int)(elapsed*1000000 / freq);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Linux, BSD, OSX
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
rcTimeVal getPerfTime()
|
||||
{
|
||||
timeval now;
|
||||
gettimeofday(&now, 0);
|
||||
return (rcTimeVal)now.tv_sec*1000000L + (rcTimeVal)now.tv_usec;
|
||||
}
|
||||
|
||||
int getPerfDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end)
|
||||
{
|
||||
return (int)(end - start);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DebugDrawGL::depthMask(bool state)
|
||||
{
|
||||
glDepthMask(state ? GL_TRUE : GL_FALSE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user