Cleaning up crowd source code.
This commit is contained in:
parent
7ee6e96e5a
commit
a92660c62f
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -213,10 +213,11 @@
|
||||
<string>active-combo-popup</string>
|
||||
<string>action</string>
|
||||
<string>NSToolbarFlexibleSpaceItem</string>
|
||||
<string>debugger-enable-breakpoints</string>
|
||||
<string>build-and-go</string>
|
||||
<string>com.apple.ide.PBXToolbarStopButton</string>
|
||||
<string>NSToolbarFlexibleSpaceItem</string>
|
||||
<string>get-info</string>
|
||||
<string>NSToolbarFlexibleSpaceItem</string>
|
||||
<string>com.apple.pbx.toolbar.searchfield</string>
|
||||
</array>
|
||||
<key>ControllerClassBaseName</key>
|
||||
@ -290,7 +291,7 @@
|
||||
</array>
|
||||
</array>
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
|
||||
<string>{{0, 872}, {264, 660}}</string>
|
||||
<string>{{0, 820}, {264, 607}}</string>
|
||||
</dict>
|
||||
<key>PBXTopSmartGroupGIDs</key>
|
||||
<array/>
|
||||
@ -300,14 +301,14 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {281, 678}}</string>
|
||||
<string>{{0, 0}, {281, 625}}</string>
|
||||
<key>GroupTreeTableConfiguration</key>
|
||||
<array>
|
||||
<string>MainColumn</string>
|
||||
<real>264</real>
|
||||
</array>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
<string>0 112 1280 666 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXSmartGroupTreeModule</string>
|
||||
@ -337,7 +338,7 @@
|
||||
<key>_historyCapacity</key>
|
||||
<integer>0</integer>
|
||||
<key>bookmark</key>
|
||||
<string>6B847811122D2EB200ADF63D</string>
|
||||
<string>6BD6680B123D30DB0021A7A4</string>
|
||||
<key>history</key>
|
||||
<array>
|
||||
<string>6BBB4AA5115B4F3400CF791D</string>
|
||||
@ -359,7 +360,6 @@
|
||||
<string>6BAF4525121D1723008CFCDF</string>
|
||||
<string>6BAF46D3121D8FF1008CFCDF</string>
|
||||
<string>6BAF475B121DA31D008CFCDF</string>
|
||||
<string>6B1C8DC5121E902F0048697F</string>
|
||||
<string>6B1C8E08121EB4FF0048697F</string>
|
||||
<string>6B1C8E0A121EB4FF0048697F</string>
|
||||
<string>6B1C8E27121EB6D30048697F</string>
|
||||
@ -368,7 +368,6 @@
|
||||
<string>6BA687831222F42100730711</string>
|
||||
<string>6BA687881222F4DB00730711</string>
|
||||
<string>6BA687CA1222FA9300730711</string>
|
||||
<string>6BA687D81222FC4700730711</string>
|
||||
<string>6BD4020E1224336600995864</string>
|
||||
<string>6BD402111224336600995864</string>
|
||||
<string>6BD402121224336600995864</string>
|
||||
@ -379,8 +378,6 @@
|
||||
<string>6BD4028C1224399300995864</string>
|
||||
<string>6BD4029B12243A8000995864</string>
|
||||
<string>6BD402B4122441CB00995864</string>
|
||||
<string>6BD403B51224F8C400995864</string>
|
||||
<string>6BD403BA1224F8C400995864</string>
|
||||
<string>6B9209A412259E5B00D5B5AD</string>
|
||||
<string>6B920A521225C0AC00D5B5AD</string>
|
||||
<string>6B920A541225C0AC00D5B5AD</string>
|
||||
@ -388,7 +385,6 @@
|
||||
<string>6B920A6E1225C5DD00D5B5AD</string>
|
||||
<string>6B920A811225D2EC00D5B5AD</string>
|
||||
<string>6B920A8C1225D3C900D5B5AD</string>
|
||||
<string>6B920A8E1225D3C900D5B5AD</string>
|
||||
<string>6B920A8F1225D3C900D5B5AD</string>
|
||||
<string>6B920AA71225DBCB00D5B5AD</string>
|
||||
<string>6B920AA81225DBCB00D5B5AD</string>
|
||||
@ -408,7 +404,6 @@
|
||||
<string>6B847513122B9F4900ADF63D</string>
|
||||
<string>6B847515122B9F4900ADF63D</string>
|
||||
<string>6B847516122B9F4900ADF63D</string>
|
||||
<string>6B847517122B9F4900ADF63D</string>
|
||||
<string>6B847518122B9F4900ADF63D</string>
|
||||
<string>6B847634122CE32800ADF63D</string>
|
||||
<string>6B847635122CE32800ADF63D</string>
|
||||
@ -418,193 +413,19 @@
|
||||
<string>6B84778B122D279700ADF63D</string>
|
||||
<string>6B8477BB122D297200ADF63D</string>
|
||||
<string>6B8477E1122D2B9100ADF63D</string>
|
||||
<string>6B8477EC122D2CC900ADF63D</string>
|
||||
<string>6B8477ED122D2CC900ADF63D</string>
|
||||
<string>6B8477EE122D2CC900ADF63D</string>
|
||||
<string>6B8477FB122D2E2A00ADF63D</string>
|
||||
<string>6B8477FC122D2E2A00ADF63D</string>
|
||||
<string>6B8477FD122D2E2A00ADF63D</string>
|
||||
<string>6B8477FE122D2E2A00ADF63D</string>
|
||||
<string>6B8477FF122D2E2A00ADF63D</string>
|
||||
<string>6B847810122D2EB000ADF63D</string>
|
||||
</array>
|
||||
<key>nextStack</key>
|
||||
<array>
|
||||
<string>6B847808122D2E2A00ADF63D</string>
|
||||
<string>6B8476A3122CF2C800ADF63D</string>
|
||||
<string>6B8476BC122CF69E00ADF63D</string>
|
||||
</array>
|
||||
<key>prevStack</key>
|
||||
<array>
|
||||
<string>6BBB4AE0115B4F3400CF791D</string>
|
||||
<string>6BBB4AE6115B4F3400CF791D</string>
|
||||
<string>6BBB4AE7115B4F3400CF791D</string>
|
||||
<string>6BBB4AE8115B4F3400CF791D</string>
|
||||
<string>6BBB4AE9115B4F3400CF791D</string>
|
||||
<string>6BBB4AEA115B4F3400CF791D</string>
|
||||
<string>6BBB4AEB115B4F3400CF791D</string>
|
||||
<string>6BBB4AEC115B4F3400CF791D</string>
|
||||
<string>6BBB4AED115B4F3400CF791D</string>
|
||||
<string>6BBB4AEE115B4F3400CF791D</string>
|
||||
<string>6BBB4AEF115B4F3400CF791D</string>
|
||||
<string>6BBB4AF0115B4F3400CF791D</string>
|
||||
<string>6BBB4AF1115B4F3400CF791D</string>
|
||||
<string>6BBB4AF8115B4F3400CF791D</string>
|
||||
<string>6BBB4AF9115B4F3400CF791D</string>
|
||||
<string>6BBB4AFA115B4F3400CF791D</string>
|
||||
<string>6BBB4AFD115B4F3400CF791D</string>
|
||||
<string>6BBB4C3B115B7A3D00CF791D</string>
|
||||
<string>6BF5F27811747CFA000502A6</string>
|
||||
<string>6BF5F28011747CFA000502A6</string>
|
||||
<string>6BF5F28D11747CFA000502A6</string>
|
||||
<string>6BF5F2ED11748884000502A6</string>
|
||||
<string>6BF5F2EE11748884000502A6</string>
|
||||
<string>6BF5F33911759C3C000502A6</string>
|
||||
<string>6B98466011E6F9B400FA177B</string>
|
||||
<string>6B98471011E734A100FA177B</string>
|
||||
<string>6B98471211E734A100FA177B</string>
|
||||
<string>6B98471411E734A100FA177B</string>
|
||||
<string>6B98477911E7433F00FA177B</string>
|
||||
<string>6B9847C511E752CC00FA177B</string>
|
||||
<string>6BF9B15511EB8CF20043574C</string>
|
||||
<string>6BF9B14911EB8CF20043574C</string>
|
||||
<string>6BAF3860120A8A8E008CFCDF</string>
|
||||
<string>6BAF3A3B1210235F008CFCDF</string>
|
||||
<string>6BAF3ABC121038F9008CFCDF</string>
|
||||
<string>6BAF3B0612112E63008CFCDF</string>
|
||||
<string>6BAF3DAA1211882E008CFCDF</string>
|
||||
<string>6BAF3E631211B713008CFCDF</string>
|
||||
<string>6BBB4AE2115B4F3400CF791D</string>
|
||||
<string>6BAF411712197F3D008CFCDF</string>
|
||||
<string>6BAF41801219811E008CFCDF</string>
|
||||
<string>6BAF41DA121A5D13008CFCDF</string>
|
||||
<string>6BAF4289121ADD46008CFCDF</string>
|
||||
<string>6BAF4396121C1F3D008CFCDF</string>
|
||||
<string>6BAF43BE121C1F3D008CFCDF</string>
|
||||
<string>6BAF43D1121C2164008CFCDF</string>
|
||||
<string>6BAF43D2121C2164008CFCDF</string>
|
||||
<string>6B98477411E7406900FA177B</string>
|
||||
<string>6BAF3861120A8A8E008CFCDF</string>
|
||||
<string>6BAF45E9121D7277008CFCDF</string>
|
||||
<string>6BAF473D121D9FBE008CFCDF</string>
|
||||
<string>6BAF4762121DA31D008CFCDF</string>
|
||||
<string>6BAF4767121DA31D008CFCDF</string>
|
||||
<string>6BAF4768121DA31D008CFCDF</string>
|
||||
<string>6B1C8E2D121EB6D30048697F</string>
|
||||
<string>6BA6874F1222EADA00730711</string>
|
||||
<string>6BA687531222EADA00730711</string>
|
||||
<string>6BA687731222F02E00730711</string>
|
||||
<string>6BA687BD1222F82500730711</string>
|
||||
<string>6BA6881D1223060400730711</string>
|
||||
<string>6BD402201224336600995864</string>
|
||||
<string>6BD402221224336600995864</string>
|
||||
<string>6BD4022B1224336600995864</string>
|
||||
<string>6BD4022D1224336600995864</string>
|
||||
<string>6BD402731224387200995864</string>
|
||||
<string>6BD403251224632E00995864</string>
|
||||
<string>6BD403C01224F8C400995864</string>
|
||||
<string>6BD403C11224F8C400995864</string>
|
||||
<string>6BD403C91224F8C400995864</string>
|
||||
<string>6BAF4456121C40AC008CFCDF</string>
|
||||
<string>6B1C8E2A121EB6D30048697F</string>
|
||||
<string>6B920A911225D3C900D5B5AD</string>
|
||||
<string>6B920A921225D3C900D5B5AD</string>
|
||||
<string>6BA7F89D1226ED5200C8C47A</string>
|
||||
<string>6B847523122B9F4900ADF63D</string>
|
||||
<string>6B847524122B9F4900ADF63D</string>
|
||||
<string>6B847525122B9F4900ADF63D</string>
|
||||
<string>6B84752D122B9F4900ADF63D</string>
|
||||
<string>6B84752E122B9F4900ADF63D</string>
|
||||
<string>6B84752F122B9F4900ADF63D</string>
|
||||
<string>6B847530122B9F4900ADF63D</string>
|
||||
<string>6B847531122B9F4900ADF63D</string>
|
||||
<string>6B847533122B9F4900ADF63D</string>
|
||||
<string>6B847561122BA46300ADF63D</string>
|
||||
<string>6B847562122BA46300ADF63D</string>
|
||||
<string>6B847563122BA46300ADF63D</string>
|
||||
<string>6B847564122BA46300ADF63D</string>
|
||||
<string>6B847582122BA90400ADF63D</string>
|
||||
<string>6B8475E8122BAF3500ADF63D</string>
|
||||
<string>6B8475EA122BAF3500ADF63D</string>
|
||||
<string>6B8475EC122BAF3500ADF63D</string>
|
||||
<string>6B8475EE122BAF3500ADF63D</string>
|
||||
<string>6B84763A122CE32800ADF63D</string>
|
||||
<string>6B84763B122CE32800ADF63D</string>
|
||||
<string>6B8476D3122CF7AA00ADF63D</string>
|
||||
<string>6B8476E4122CFDA900ADF63D</string>
|
||||
<string>6B8476E7122CFDA900ADF63D</string>
|
||||
<string>6B8476E8122CFDA900ADF63D</string>
|
||||
<string>6B8476F6122CFDA900ADF63D</string>
|
||||
<string>6B847700122D000800ADF63D</string>
|
||||
<string>6B847701122D000800ADF63D</string>
|
||||
<string>6B84771E122D116E00ADF63D</string>
|
||||
<string>6B847720122D116E00ADF63D</string>
|
||||
<string>6B84772C122D11F500ADF63D</string>
|
||||
<string>6B847731122D11FC00ADF63D</string>
|
||||
<string>6B847738122D125B00ADF63D</string>
|
||||
<string>6B84774A122D148B00ADF63D</string>
|
||||
<string>6B84774B122D148B00ADF63D</string>
|
||||
<string>6B84774C122D148B00ADF63D</string>
|
||||
<string>6B84774D122D148B00ADF63D</string>
|
||||
<string>6B84775B122D156100ADF63D</string>
|
||||
<string>6B847766122D15FF00ADF63D</string>
|
||||
<string>6B84777E122D223D00ADF63D</string>
|
||||
<string>6B84777F122D223D00ADF63D</string>
|
||||
<string>6B847780122D223D00ADF63D</string>
|
||||
<string>6B847781122D223D00ADF63D</string>
|
||||
<string>6B847783122D223D00ADF63D</string>
|
||||
<string>6B847791122D279700ADF63D</string>
|
||||
<string>6B847793122D279700ADF63D</string>
|
||||
<string>6B847795122D279700ADF63D</string>
|
||||
<string>6B847796122D279700ADF63D</string>
|
||||
<string>6B847799122D279700ADF63D</string>
|
||||
<string>6B84779A122D279700ADF63D</string>
|
||||
<string>6B84779B122D279700ADF63D</string>
|
||||
<string>6B84779C122D279700ADF63D</string>
|
||||
<string>6B84779D122D279700ADF63D</string>
|
||||
<string>6B84779E122D279700ADF63D</string>
|
||||
<string>6B84779F122D279700ADF63D</string>
|
||||
<string>6B8477A0122D279700ADF63D</string>
|
||||
<string>6B8477A1122D279700ADF63D</string>
|
||||
<string>6B8477A2122D279700ADF63D</string>
|
||||
<string>6B8477A3122D279700ADF63D</string>
|
||||
<string>6B8477A4122D279700ADF63D</string>
|
||||
<string>6B8477A5122D279700ADF63D</string>
|
||||
<string>6B8477A6122D279700ADF63D</string>
|
||||
<string>6B8477A7122D279700ADF63D</string>
|
||||
<string>6B8477A8122D279700ADF63D</string>
|
||||
<string>6B8477AA122D279700ADF63D</string>
|
||||
<string>6B8477AC122D279700ADF63D</string>
|
||||
<string>6B8477AD122D279700ADF63D</string>
|
||||
<string>6B8477BE122D297200ADF63D</string>
|
||||
<string>6B8477BF122D297200ADF63D</string>
|
||||
<string>6B8477C0122D297200ADF63D</string>
|
||||
<string>6B8477C1122D297200ADF63D</string>
|
||||
<string>6B8477C2122D297200ADF63D</string>
|
||||
<string>6B8477CA122D2A4200ADF63D</string>
|
||||
<string>6B8477CB122D2A4200ADF63D</string>
|
||||
<string>6B8477CD122D2A4200ADF63D</string>
|
||||
<string>6B8477CE122D2A4200ADF63D</string>
|
||||
<string>6B8477CF122D2A4200ADF63D</string>
|
||||
<string>6B8477D0122D2A4200ADF63D</string>
|
||||
<string>6B8477D4122D2ACE00ADF63D</string>
|
||||
<string>6B8477D9122D2AFF00ADF63D</string>
|
||||
<string>6B8477DA122D2AFF00ADF63D</string>
|
||||
<string>6B8477DF122D2B2000ADF63D</string>
|
||||
<string>6B8477E5122D2B9100ADF63D</string>
|
||||
<string>6B8477E6122D2B9100ADF63D</string>
|
||||
<string>6B8477F0122D2CC900ADF63D</string>
|
||||
<string>6B8477F1122D2CC900ADF63D</string>
|
||||
<string>6B8477F2122D2CC900ADF63D</string>
|
||||
<string>6B8477F7122D2CEA00ADF63D</string>
|
||||
<string>6B847801122D2E2A00ADF63D</string>
|
||||
<string>6B847802122D2E2A00ADF63D</string>
|
||||
<string>6B847803122D2E2A00ADF63D</string>
|
||||
<string>6B847804122D2E2A00ADF63D</string>
|
||||
<string>6B847805122D2E2A00ADF63D</string>
|
||||
<string>6B847806122D2E2A00ADF63D</string>
|
||||
<string>6B847807122D2E2A00ADF63D</string>
|
||||
<string>6B847571122BA90400ADF63D</string>
|
||||
<string>6B73B22F123A7ECC00671B94</string>
|
||||
<string>6BD667D3123D27030021A7A4</string>
|
||||
<string>6BD667E3123D2BD60021A7A4</string>
|
||||
<string>6BD667FF123D2D230021A7A4</string>
|
||||
<string>6BD66800123D2D230021A7A4</string>
|
||||
<string>6BD66806123D2F4E0021A7A4</string>
|
||||
<string>6BD66807123D2F4E0021A7A4</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>SplitCount</key>
|
||||
@ -618,18 +439,18 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {994, 569}}</string>
|
||||
<string>{{0, 0}, {994, 490}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
<string>0 112 1280 666 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXNavigatorGroup</string>
|
||||
<key>Proportion</key>
|
||||
<string>569pt</string>
|
||||
<string>490pt</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Proportion</key>
|
||||
<string>104pt</string>
|
||||
<string>130pt</string>
|
||||
<key>Tabs</key>
|
||||
<array>
|
||||
<dict>
|
||||
@ -643,7 +464,7 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {994, 57}}</string>
|
||||
<string>{{10, 27}, {994, 31}}</string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>XCDetailModule</string>
|
||||
@ -688,7 +509,7 @@
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>XCMainBuildResultsModuleGUID</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>Build</string>
|
||||
<string>Build Results</string>
|
||||
<key>XCBuildResultsTrigger_Collapse</key>
|
||||
<integer>1021</integer>
|
||||
<key>XCBuildResultsTrigger_Open</key>
|
||||
@ -697,9 +518,9 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {994, 77}}</string>
|
||||
<string>{{10, 27}, {994, 103}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
<string>0 112 1280 666 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXBuildResultsModule</string>
|
||||
@ -727,11 +548,11 @@
|
||||
</array>
|
||||
<key>TableOfContents</key>
|
||||
<array>
|
||||
<string>6B847502122B87E000ADF63D</string>
|
||||
<string>6BD66794123D10F20021A7A4</string>
|
||||
<string>1CA23ED40692098700951B8B</string>
|
||||
<string>6B847503122B87E000ADF63D</string>
|
||||
<string>6BD66795123D10F20021A7A4</string>
|
||||
<string>6B8632A30F78115100E2684A</string>
|
||||
<string>6B847504122B87E000ADF63D</string>
|
||||
<string>6BD66796123D10F20021A7A4</string>
|
||||
<string>1CA23EDF0692099D00951B8B</string>
|
||||
<string>1CA23EE00692099D00951B8B</string>
|
||||
<string>1CA23EE10692099D00951B8B</string>
|
||||
@ -880,14 +701,14 @@
|
||||
</array>
|
||||
<key>TableOfContents</key>
|
||||
<array>
|
||||
<string>6B847537122B9F4900ADF63D</string>
|
||||
<string>6BD667A0123D13100021A7A4</string>
|
||||
<string>1CCC7628064C1048000F2A68</string>
|
||||
<string>1CCC7629064C1048000F2A68</string>
|
||||
<string>6B847538122B9F4900ADF63D</string>
|
||||
<string>6B847539122B9F4900ADF63D</string>
|
||||
<string>6B84753A122B9F4900ADF63D</string>
|
||||
<string>6B84753B122B9F4900ADF63D</string>
|
||||
<string>6B84753C122B9F4900ADF63D</string>
|
||||
<string>6BD667A1123D13100021A7A4</string>
|
||||
<string>6BD667A2123D13100021A7A4</string>
|
||||
<string>6BD667A3123D13100021A7A4</string>
|
||||
<string>6BD667A4123D13100021A7A4</string>
|
||||
<string>6BD667A5123D13100021A7A4</string>
|
||||
</array>
|
||||
<key>ToolbarConfigUserDefaultsMinorVersion</key>
|
||||
<string>2</string>
|
||||
@ -919,12 +740,12 @@
|
||||
<integer>5</integer>
|
||||
<key>WindowOrderList</key>
|
||||
<array>
|
||||
<string>6B8475D2122BAE1800ADF63D</string>
|
||||
<string>6B8475D3122BAE1800ADF63D</string>
|
||||
<string>6BD667A7123D13100021A7A4</string>
|
||||
<string>6BD667A8123D13100021A7A4</string>
|
||||
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
|
||||
</array>
|
||||
<key>WindowString</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
<string>0 112 1280 666 0 0 1280 778 </string>
|
||||
<key>WindowToolsV3</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
@ -49,6 +49,7 @@
|
||||
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; };
|
||||
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; };
|
||||
6BD402011224279400995864 /* PerfTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BD402001224279400995864 /* PerfTimer.cpp */; };
|
||||
6BD667DA123D28100021A7A4 /* CrowdManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BD667D9123D28100021A7A4 /* CrowdManager.cpp */; };
|
||||
6BF5F23A11747606000502A6 /* Filelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23911747606000502A6 /* Filelist.cpp */; };
|
||||
6BF5F2401174763B000502A6 /* SlideShow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; };
|
||||
6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C13F1111953A002B3F46 /* TestCase.cpp */; };
|
||||
@ -140,6 +141,8 @@
|
||||
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6BD401FF1224278800995864 /* PerfTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PerfTimer.h; path = ../../Include/PerfTimer.h; sourceTree = SOURCE_ROOT; };
|
||||
6BD402001224279400995864 /* PerfTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PerfTimer.cpp; path = ../../Source/PerfTimer.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6BD667D8123D27EC0021A7A4 /* CrowdManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CrowdManager.h; path = ../../Include/CrowdManager.h; sourceTree = SOURCE_ROOT; };
|
||||
6BD667D9123D28100021A7A4 /* CrowdManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CrowdManager.cpp; path = ../../Source/CrowdManager.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6BF5F23911747606000502A6 /* Filelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Filelist.cpp; path = ../../Source/Filelist.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6BF5F23C11747614000502A6 /* Filelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Filelist.h; path = ../../Include/Filelist.h; sourceTree = SOURCE_ROOT; };
|
||||
6BF5F23E1174763B000502A6 /* SlideShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SlideShow.h; path = ../../Include/SlideShow.h; sourceTree = SOURCE_ROOT; };
|
||||
@ -201,6 +204,8 @@
|
||||
6BD402001224279400995864 /* PerfTimer.cpp */,
|
||||
6B847774122D220D00ADF63D /* ValueHistory.h */,
|
||||
6B847776122D221C00ADF63D /* ValueHistory.cpp */,
|
||||
6BD667D8123D27EC0021A7A4 /* CrowdManager.h */,
|
||||
6BD667D9123D28100021A7A4 /* CrowdManager.cpp */,
|
||||
);
|
||||
name = Classes;
|
||||
sourceTree = "<group>";
|
||||
@ -459,6 +464,7 @@
|
||||
6BD402011224279400995864 /* PerfTimer.cpp in Sources */,
|
||||
6B9EFF0912281C3E00535FF1 /* DetourObstacleAvoidance.cpp in Sources */,
|
||||
6B847777122D221D00ADF63D /* ValueHistory.cpp in Sources */,
|
||||
6BD667DA123D28100021A7A4 /* CrowdManager.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
123
RecastDemo/Include/CrowdManager.h
Normal file
123
RecastDemo/Include/CrowdManager.h
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef CROWDMANAGER_H
|
||||
#define CROWDMANAGER_H
|
||||
|
||||
#include "DetourNavMeshQuery.h"
|
||||
#include "DetourObstacleAvoidance.h"
|
||||
#include "ValueHistory.h"
|
||||
|
||||
|
||||
enum AgentTargetState
|
||||
{
|
||||
AGENT_TARGET_NONE = 0,
|
||||
AGENT_TARGET_SET = 1,
|
||||
AGENT_TARGET_ACQUIRED = 2,
|
||||
AGENT_TARGET_PATH = 3,
|
||||
AGENT_TARGET_FAILED = 4,
|
||||
};
|
||||
|
||||
static const int AGENT_MAX_PATH = 256;
|
||||
static const int AGENT_MAX_CORNERS = 4;
|
||||
static const int AGENT_MAX_TRAIL = 64;
|
||||
static const int AGENT_MAX_COLSEGS = 32;
|
||||
static const int AGENT_MAX_NEIS = 8;
|
||||
|
||||
struct Agent
|
||||
{
|
||||
float pos[3];
|
||||
float radius, height;
|
||||
|
||||
float dvel[3];
|
||||
float nvel[3];
|
||||
float vel[3];
|
||||
float npos[3];
|
||||
float disp[3];
|
||||
|
||||
float opts[3], opte[3];
|
||||
|
||||
float maxspeed;
|
||||
float t;
|
||||
float var;
|
||||
|
||||
float colradius;
|
||||
float colcenter[3];
|
||||
float colsegs[AGENT_MAX_COLSEGS*6];
|
||||
int ncolsegs;
|
||||
|
||||
float trail[AGENT_MAX_TRAIL*3];
|
||||
int htrail;
|
||||
|
||||
unsigned char targetState;
|
||||
float target[3];
|
||||
dtPolyRef targetRef;
|
||||
|
||||
dtPolyRef path[AGENT_MAX_PATH];
|
||||
int npath;
|
||||
|
||||
float cornerVerts[AGENT_MAX_CORNERS*3];
|
||||
unsigned char cornerFlags[AGENT_MAX_CORNERS];
|
||||
dtPolyRef cornerPolys[AGENT_MAX_CORNERS];
|
||||
int ncorners;
|
||||
|
||||
unsigned char active;
|
||||
};
|
||||
|
||||
|
||||
enum UpdateFlags
|
||||
{
|
||||
CROWDMAN_ANTICIPATE_TURNS = 1,
|
||||
CROWDMAN_USE_VO = 2,
|
||||
CROWDMAN_DRUNK = 4,
|
||||
};
|
||||
|
||||
class CrowdManager
|
||||
{
|
||||
static const int MAX_AGENTS = 32;
|
||||
Agent m_agents[MAX_AGENTS];
|
||||
dtObstacleAvoidanceDebugData* m_vodebug[MAX_AGENTS];
|
||||
dtObstacleAvoidanceQuery* m_obstacleQuery;
|
||||
|
||||
int m_totalTime;
|
||||
int m_rvoTime;
|
||||
int m_sampleCount;
|
||||
|
||||
public:
|
||||
CrowdManager();
|
||||
~CrowdManager();
|
||||
|
||||
void reset();
|
||||
const Agent* getAgent(const int idx);
|
||||
const int getAgentCount() const;
|
||||
int addAgent(const float* pos, const float radius, const float height);
|
||||
void removeAgent(const int idx);
|
||||
void setMoveTarget(const int idx, const float* pos);
|
||||
|
||||
int getActiveAgents(Agent** agents, const int maxAgents);
|
||||
|
||||
void update(const float dt, unsigned int flags, dtNavMeshQuery* navquery);
|
||||
|
||||
const dtObstacleAvoidanceDebugData* getVODebugData(const int idx) const { return m_vodebug[idx]; }
|
||||
inline int getTotalTime() const { return m_totalTime; }
|
||||
inline int getRVOTime() const { return m_rvoTime; }
|
||||
inline int getSampleCount() const { return m_sampleCount; }
|
||||
};
|
||||
|
||||
|
||||
#endif // CROWDMANAGER_H
|
@ -23,70 +23,10 @@
|
||||
#include "DetourNavMesh.h"
|
||||
#include "DetourObstacleAvoidance.h"
|
||||
#include "ValueHistory.h"
|
||||
#include "CrowdManager.h"
|
||||
|
||||
// Tool to create crowds.
|
||||
|
||||
enum AgentTargetState
|
||||
{
|
||||
AGENT_TARGET_NONE = 0,
|
||||
AGENT_TARGET_SET = 1,
|
||||
AGENT_TARGET_ACQUIRED = 2,
|
||||
AGENT_TARGET_PATH = 3,
|
||||
AGENT_TARGET_FAILED = 4,
|
||||
};
|
||||
|
||||
static const int AGENT_MAX_PATH = 256;
|
||||
static const int AGENT_MAX_CORNERS = 4;
|
||||
static const int AGENT_MAX_TRAIL = 64;
|
||||
static const int AGENT_MAX_COLSEGS = 32;
|
||||
static const int AGENT_MAX_NEIS = 8;
|
||||
|
||||
enum AgentApproach
|
||||
{
|
||||
AGENT_APPROACH_CORNER = 0,
|
||||
AGENT_APPROACH_OFFMESH_CON = 0,
|
||||
AGENT_APPROACH_END = 0,
|
||||
};
|
||||
|
||||
struct Agent
|
||||
{
|
||||
float pos[3];
|
||||
float radius, height;
|
||||
|
||||
float dvel[3];
|
||||
float nvel[3];
|
||||
float vel[3];
|
||||
float npos[3];
|
||||
float disp[3];
|
||||
|
||||
float opts[3], opte[3];
|
||||
|
||||
float maxspeed;
|
||||
float t;
|
||||
float var;
|
||||
|
||||
float colradius;
|
||||
float colcenter[3];
|
||||
float colsegs[AGENT_MAX_COLSEGS*6];
|
||||
int ncolsegs;
|
||||
|
||||
float trail[AGENT_MAX_TRAIL*3];
|
||||
int htrail;
|
||||
|
||||
unsigned char targetState;
|
||||
float target[3];
|
||||
dtPolyRef targetRef;
|
||||
|
||||
dtPolyRef path[AGENT_MAX_PATH];
|
||||
int npath;
|
||||
float corners[AGENT_MAX_CORNERS*3];
|
||||
int ncorners;
|
||||
|
||||
unsigned char active;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct Isect
|
||||
{
|
||||
float u;
|
||||
@ -112,46 +52,6 @@ struct Formation
|
||||
int npolys;
|
||||
};
|
||||
|
||||
|
||||
enum UpdateFlags
|
||||
{
|
||||
CROWDMAN_ANTICIPATE_TURNS = 1,
|
||||
CROWDMAN_USE_VO = 2,
|
||||
CROWDMAN_DRUNK = 4,
|
||||
};
|
||||
|
||||
class CrowdManager
|
||||
{
|
||||
static const int MAX_AGENTS = 32;
|
||||
Agent m_agents[MAX_AGENTS];
|
||||
dtObstacleAvoidanceDebugData* m_vodebug[MAX_AGENTS];
|
||||
|
||||
ValueHistory m_totalTime;
|
||||
ValueHistory m_rvoTime;
|
||||
ValueHistory m_sampleCount;
|
||||
|
||||
dtObstacleAvoidanceQuery* m_obstacleQuery;
|
||||
|
||||
public:
|
||||
CrowdManager();
|
||||
~CrowdManager();
|
||||
|
||||
void reset();
|
||||
const Agent* getAgent(const int idx);
|
||||
const int getAgentCount() const;
|
||||
int addAgent(const float* pos, const float radius, const float height);
|
||||
void removeAgent(const int idx);
|
||||
void setMoveTarget(const int idx, const float* pos);
|
||||
|
||||
void update(const float dt, unsigned int flags, dtNavMeshQuery* navquery);
|
||||
|
||||
const dtObstacleAvoidanceDebugData* getVODebugData(const int idx) const { return m_vodebug[idx]; }
|
||||
|
||||
const ValueHistory* getTotalTimeGraph() const { return &m_totalTime; }
|
||||
const ValueHistory* getRVOTimeGraph() const { return &m_rvoTime; }
|
||||
const ValueHistory* getSampleCountGraph() const { return &m_sampleCount; }
|
||||
};
|
||||
|
||||
class CrowdTool : public SampleTool
|
||||
{
|
||||
Sample* m_sample;
|
||||
@ -178,6 +78,10 @@ class CrowdTool : public SampleTool
|
||||
|
||||
CrowdManager m_crowd;
|
||||
|
||||
ValueHistory m_crowdTotalTime;
|
||||
ValueHistory m_crowdRvoTime;
|
||||
ValueHistory m_crowdSampleCount;
|
||||
|
||||
enum ToolMode
|
||||
{
|
||||
TOOLMODE_CREATE,
|
||||
|
743
RecastDemo/Source/CrowdManager.cpp
Normal file
743
RecastDemo/Source/CrowdManager.cpp
Normal file
@ -0,0 +1,743 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
#include "DetourNavMesh.h"
|
||||
#include "DetourNavMeshQuery.h"
|
||||
#include "DetourObstacleAvoidance.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "CrowdManager.h"
|
||||
#include "SampleInterfaces.h" // For timer
|
||||
|
||||
|
||||
static const int VO_ADAPTIVE_GRID_SIZE = 4;
|
||||
static const int VO_ADAPTIVE_GRID_DEPTH = 5;
|
||||
static const int VO_GRID_SIZE = 33;
|
||||
|
||||
|
||||
static int fixupCorridor(dtPolyRef* path, const int npath, const int maxPath,
|
||||
const dtPolyRef* visited, const int nvisited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
||||
// Find furthest common polygon.
|
||||
for (int i = npath-1; i >= 0; --i)
|
||||
{
|
||||
bool found = false;
|
||||
for (int j = nvisited-1; j >= 0; --j)
|
||||
{
|
||||
if (path[i] == visited[j])
|
||||
{
|
||||
furthestPath = i;
|
||||
furthestVisited = j;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
// If no intersection found just return current path.
|
||||
if (furthestPath == -1 || furthestVisited == -1)
|
||||
return npath;
|
||||
|
||||
// Concatenate paths.
|
||||
|
||||
// Adjust beginning of the buffer to include the visited.
|
||||
const int req = nvisited - furthestVisited;
|
||||
const int orig = dtMin(furthestPath+1, npath);
|
||||
int size = dtMax(0, npath-orig);
|
||||
if (req+size > maxPath)
|
||||
size = maxPath-req;
|
||||
if (size)
|
||||
memmove(path+req, path+orig, size*sizeof(dtPolyRef));
|
||||
|
||||
// Store visited
|
||||
for (int i = 0; i < req; ++i)
|
||||
path[i] = visited[(nvisited-1)-i];
|
||||
|
||||
return req+size;
|
||||
}
|
||||
|
||||
static int mergeCorridor(dtPolyRef* path, const int npath, const int maxPath,
|
||||
const dtPolyRef* visited, const int nvisited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
||||
// Find furthest common polygon.
|
||||
for (int i = npath-1; i >= 0; --i)
|
||||
{
|
||||
bool found = false;
|
||||
for (int j = nvisited-1; j >= 0; --j)
|
||||
{
|
||||
if (path[i] == visited[j])
|
||||
{
|
||||
furthestPath = i;
|
||||
furthestVisited = j;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
// If no intersection found just return current path.
|
||||
if (furthestPath == -1 || furthestVisited == -1)
|
||||
return npath;
|
||||
|
||||
// Concatenate paths.
|
||||
|
||||
// Adjust beginning of the buffer to include the visited.
|
||||
const int req = furthestVisited;
|
||||
if (req <= 0)
|
||||
return npath;
|
||||
|
||||
const int orig = furthestPath;
|
||||
int size = dtMax(0, npath-orig);
|
||||
if (req+size > maxPath)
|
||||
size = maxPath-req;
|
||||
if (size)
|
||||
memmove(path+req, path+orig, size*sizeof(dtPolyRef));
|
||||
|
||||
// Store visited
|
||||
for (int i = 0; i < req; ++i)
|
||||
path[i] = visited[i];
|
||||
|
||||
return req+size;
|
||||
}
|
||||
|
||||
// Finds straight path towards the goal and prunes it to contain only relevant vertices.
|
||||
static int findCorners(const float* pos, const float* target,
|
||||
const dtPolyRef* path, const int npath,
|
||||
float* cornerVerts, unsigned char* cornerFlags,
|
||||
dtPolyRef* cornerPolys, const int maxCorners,
|
||||
const dtNavMeshQuery* navquery)
|
||||
{
|
||||
static const float MIN_TARGET_DIST = 0.01f;
|
||||
|
||||
int ncorners = navquery->findStraightPath(pos, target, path, npath,
|
||||
cornerVerts, cornerFlags, cornerPolys,
|
||||
maxCorners);
|
||||
|
||||
// Prune points in the beginning of the path which are too close.
|
||||
while (ncorners)
|
||||
{
|
||||
if ((cornerFlags[0] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
|
||||
dtVdist2DSqr(&cornerVerts[0], pos) > dtSqr(MIN_TARGET_DIST))
|
||||
break;
|
||||
ncorners--;
|
||||
if (ncorners)
|
||||
{
|
||||
memmove(cornerFlags, cornerFlags+1, sizeof(unsigned char)*ncorners);
|
||||
memmove(cornerPolys, cornerPolys+1, sizeof(dtPolyRef)*ncorners);
|
||||
memmove(cornerVerts, cornerVerts+3, sizeof(float)*3*ncorners);
|
||||
}
|
||||
}
|
||||
|
||||
// Prune points after an off-mesh connection.
|
||||
for (int i = 0; i < ncorners; ++i)
|
||||
{
|
||||
if (cornerFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION)
|
||||
{
|
||||
ncorners = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ncorners;
|
||||
}
|
||||
|
||||
static int optimizePath(const float* pos, const float* next, const float maxLookAhead,
|
||||
dtPolyRef* path, const int npath,
|
||||
const dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
{
|
||||
// Clamp the ray to max distance.
|
||||
float goal[3];
|
||||
dtVcopy(goal, next);
|
||||
const float distSqr = dtVdist2DSqr(pos, goal);
|
||||
|
||||
// If too close to the goal, do not try to optimize.
|
||||
if (distSqr < dtSqr(0.01f))
|
||||
return npath;
|
||||
|
||||
// If too far truncate ray length.
|
||||
if (distSqr > dtSqr(maxLookAhead))
|
||||
{
|
||||
float delta[3];
|
||||
dtVsub(delta, goal, pos);
|
||||
dtVmad(goal, pos, delta, dtSqr(maxLookAhead)/distSqr);
|
||||
}
|
||||
|
||||
static const int MAX_RES = 32;
|
||||
dtPolyRef res[MAX_RES];
|
||||
float t, norm[3];
|
||||
const int nres = navquery->raycast(path[0], pos, goal, filter, t, norm, res, MAX_RES);
|
||||
if (nres > 1 && t > 0.99f)
|
||||
{
|
||||
return mergeCorridor(path, npath, AGENT_MAX_PATH, res, nres);
|
||||
}
|
||||
|
||||
return npath;
|
||||
}
|
||||
|
||||
static void updateLocalNeighbourhood(Agent* ag, dtNavMeshQuery* navquery, const dtQueryFilter* filter)
|
||||
{
|
||||
if (!ag->npath)
|
||||
return;
|
||||
|
||||
// Only update the neigbourhood after certain distance has been passed.
|
||||
if (dtVdist2DSqr(ag->pos, ag->colcenter) < dtSqr(ag->colradius*0.25f))
|
||||
return;
|
||||
|
||||
dtVcopy(ag->colcenter, ag->pos);
|
||||
static const int MAX_LOCALS = 32;
|
||||
dtPolyRef locals[MAX_LOCALS];
|
||||
|
||||
const int nlocals = navquery->findLocalNeighbourhood(ag->path[0], ag->pos, ag->colradius, filter, locals, 0, MAX_LOCALS);
|
||||
|
||||
ag->ncolsegs = 0;
|
||||
for (int j = 0; j < nlocals; ++j)
|
||||
{
|
||||
float segs[DT_VERTS_PER_POLYGON*3*2];
|
||||
const int nsegs = navquery->getPolyWallSegments(locals[j], filter, segs);
|
||||
for (int k = 0; k < nsegs; ++k)
|
||||
{
|
||||
const float* s = &segs[k*6];
|
||||
// Skip too distant segments.
|
||||
float tseg;
|
||||
const float distSqr = dtDistancePtSegSqr2D(ag->pos, s, s+3, tseg);
|
||||
if (distSqr > dtSqr(ag->colradius))
|
||||
continue;
|
||||
if (ag->ncolsegs < AGENT_MAX_COLSEGS)
|
||||
{
|
||||
memcpy(&ag->colsegs[ag->ncolsegs*6], s, sizeof(float)*6);
|
||||
ag->ncolsegs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void collectObstacles(Agent* ag, Agent** agents, const int nagents,
|
||||
dtObstacleAvoidanceQuery* obstacleQuery)
|
||||
{
|
||||
obstacleQuery->reset();
|
||||
|
||||
// Add dynamic obstacles.
|
||||
for (int j = 0; j < nagents; ++j)
|
||||
{
|
||||
const Agent* nei = agents[j];
|
||||
if (nei == ag) continue;
|
||||
|
||||
float diff[3];
|
||||
dtVsub(diff, ag->npos, nei->npos);
|
||||
if (fabsf(diff[1]) >= (ag->height+nei->height)/2.0f)
|
||||
continue;
|
||||
diff[1] = 0;
|
||||
|
||||
const float distSqr = dtVlenSqr(diff);
|
||||
if (distSqr > dtSqr(ag->colradius))
|
||||
continue;
|
||||
|
||||
obstacleQuery->addCircle(nei->pos, nei->radius, nei->vel, nei->dvel, distSqr);
|
||||
}
|
||||
|
||||
// Add static segment obstacles.
|
||||
for (int j = 0; j < ag->ncolsegs; ++j)
|
||||
{
|
||||
const float* s = &ag->colsegs[j*6];
|
||||
if (dtTriArea2D(ag->pos, s, s+3) < 0.0f)
|
||||
continue;
|
||||
|
||||
float tseg;
|
||||
const float distSqr = dtDistancePtSegSqr2D(ag->pos, s, s+3, tseg);
|
||||
|
||||
obstacleQuery->addSegment(s, s+3, distSqr);
|
||||
}
|
||||
}
|
||||
|
||||
static void calcSmoothSteerDirection(const float* pos, const float* corners, const int ncorners, float* dvel)
|
||||
{
|
||||
const int ip0 = 0;
|
||||
const int ip1 = dtMin(1, ncorners-1);
|
||||
const float* p0 = &corners[ip0*3];
|
||||
const float* p1 = &corners[ip1*3];
|
||||
|
||||
float dir0[3], dir1[3];
|
||||
dtVsub(dir0, p0, pos);
|
||||
dtVsub(dir1, p1, pos);
|
||||
dir0[1] = 0;
|
||||
dir1[1] = 0;
|
||||
|
||||
float len0 = dtVlen(dir0);
|
||||
float len1 = dtVlen(dir1);
|
||||
if (len1 > 0.001f)
|
||||
dtVscale(dir1,dir1,1.0f/len1);
|
||||
|
||||
const float strength = 0.5f;
|
||||
|
||||
dvel[0] = dir0[0] - dir1[0]*len0*strength;
|
||||
dvel[1] = 0;
|
||||
dvel[2] = dir0[2] - dir1[2]*len0*strength;
|
||||
|
||||
dtVnormalize(dvel);
|
||||
}
|
||||
|
||||
static void calcStraightSteerDirection(const float* pos, const float* corners, const int ncorners, float* dvel)
|
||||
{
|
||||
dtVsub(dvel, &corners[0], pos);
|
||||
dvel[1] = 0;
|
||||
|
||||
dtVnormalize(dvel);
|
||||
}
|
||||
|
||||
CrowdManager::CrowdManager() :
|
||||
m_obstacleQuery(0),
|
||||
m_totalTime(0),
|
||||
m_rvoTime(0),
|
||||
m_sampleCount(0)
|
||||
{
|
||||
|
||||
m_obstacleQuery = dtAllocObstacleAvoidanceQuery();
|
||||
m_obstacleQuery->init(6, 10);
|
||||
|
||||
m_obstacleQuery->setDesiredVelocityWeight(2.0f);
|
||||
m_obstacleQuery->setCurrentVelocityWeight(0.75f);
|
||||
m_obstacleQuery->setPreferredSideWeight(0.75f);
|
||||
m_obstacleQuery->setCollisionTimeWeight(2.5f);
|
||||
m_obstacleQuery->setTimeHorizon(2.5f);
|
||||
m_obstacleQuery->setVelocitySelectionBias(0.4f);
|
||||
|
||||
memset(m_vodebug, 0, sizeof(m_vodebug));
|
||||
const int sampleCount = dtMax(VO_GRID_SIZE*VO_GRID_SIZE, (VO_ADAPTIVE_GRID_SIZE*VO_ADAPTIVE_GRID_SIZE)*VO_ADAPTIVE_GRID_DEPTH);
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
m_vodebug[i] = dtAllocObstacleAvoidanceDebugData();
|
||||
m_vodebug[i]->init(sampleCount);
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
CrowdManager::~CrowdManager()
|
||||
{
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
dtFreeObstacleAvoidanceDebugData(m_vodebug[i]);
|
||||
dtFreeObstacleAvoidanceQuery(m_obstacleQuery);
|
||||
}
|
||||
|
||||
void CrowdManager::reset()
|
||||
{
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
memset(&m_agents[i], 0, sizeof(Agent));
|
||||
}
|
||||
|
||||
const int CrowdManager::getAgentCount() const
|
||||
{
|
||||
return MAX_AGENTS;
|
||||
}
|
||||
|
||||
const Agent* CrowdManager::getAgent(const int idx)
|
||||
{
|
||||
return &m_agents[idx];
|
||||
}
|
||||
|
||||
int CrowdManager::addAgent(const float* pos, const float radius, const float height)
|
||||
{
|
||||
// Find empty slot.
|
||||
int idx = -1;
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
return -1;
|
||||
|
||||
Agent* ag = &m_agents[idx];
|
||||
memset(ag, 0, sizeof(Agent));
|
||||
dtVcopy(ag->pos, pos);
|
||||
ag->radius = radius;
|
||||
ag->colradius = radius * 7.5f;
|
||||
ag->height = height;
|
||||
ag->active = 1;
|
||||
ag->var = (rand() % 10) / 9.0f;
|
||||
|
||||
// Init trail
|
||||
for (int i = 0; i < AGENT_MAX_TRAIL; ++i)
|
||||
dtVcopy(&ag->trail[i*3], ag->pos);
|
||||
ag->htrail = 0;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void CrowdManager::removeAgent(const int idx)
|
||||
{
|
||||
if (idx >= 0 && idx < MAX_AGENTS)
|
||||
memset(&m_agents[idx], 0, sizeof(Agent));
|
||||
}
|
||||
|
||||
void CrowdManager::setMoveTarget(const int idx, const float* pos)
|
||||
{
|
||||
Agent* ag = &m_agents[idx];
|
||||
dtVcopy(ag->target, pos);
|
||||
ag->targetState = AGENT_TARGET_SET;
|
||||
}
|
||||
|
||||
int CrowdManager::getActiveAgents(Agent** agents, const int maxAgents)
|
||||
{
|
||||
int n = 0;
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
if (n < maxAgents)
|
||||
agents[n++] = &m_agents[i];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery)
|
||||
{
|
||||
m_sampleCount = 0;
|
||||
m_totalTime = 0;
|
||||
m_rvoTime = 0;
|
||||
|
||||
if (!navquery)
|
||||
return;
|
||||
|
||||
TimeVal startTime = getPerfTime();
|
||||
|
||||
const float ext[3] = {2,4,2};
|
||||
dtQueryFilter filter;
|
||||
|
||||
Agent* agents[MAX_AGENTS];
|
||||
int nagents = getActiveAgents(agents, MAX_AGENTS);
|
||||
|
||||
|
||||
// Update target and agent navigation state.
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
// Make sure that the first path polygon corresponds to the current agent location.
|
||||
if (!ag->npath)
|
||||
{
|
||||
float nearest[3];
|
||||
ag->path[0] = navquery->findNearestPoly(ag->pos, ext, &filter, nearest);
|
||||
if (ag->path[0])
|
||||
{
|
||||
ag->npath = 1;
|
||||
dtVcopy(ag->pos, nearest);
|
||||
}
|
||||
}
|
||||
|
||||
if (ag->targetState == AGENT_TARGET_SET)
|
||||
{
|
||||
float nearest[3];
|
||||
ag->targetRef = navquery->findNearestPoly(ag->target, ext, &filter, nearest);
|
||||
if (ag->targetRef)
|
||||
dtVcopy(ag->target, nearest);
|
||||
ag->targetState = AGENT_TARGET_ACQUIRED;
|
||||
}
|
||||
|
||||
if (ag->targetState == AGENT_TARGET_ACQUIRED)
|
||||
{
|
||||
ag->npath = navquery->findPath(ag->path[0], ag->targetRef, ag->pos, ag->target,
|
||||
&filter, ag->path, AGENT_MAX_PATH);
|
||||
if (ag->npath)
|
||||
{
|
||||
ag->targetState = AGENT_TARGET_PATH;
|
||||
// Check for partial path.
|
||||
if (ag->path[ag->npath-1] != ag->targetRef)
|
||||
{
|
||||
// Partial path, constrain target position inside the last polygon.
|
||||
ag->targetRef = ag->path[ag->npath-1];
|
||||
float nearest[3];
|
||||
if (navquery->closestPointOnPoly(ag->targetRef, ag->target, nearest))
|
||||
dtVcopy(ag->target, nearest);
|
||||
else
|
||||
ag->targetState = AGENT_TARGET_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
ag->targetState = AGENT_TARGET_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
// Get nearby navmesh segments to collide with.
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
updateLocalNeighbourhood(ag, navquery, &filter);
|
||||
}
|
||||
|
||||
static const float MAX_ACC = 8.0f;
|
||||
static const float MAX_SPEED = 3.5f;
|
||||
|
||||
// Find next corner to steer to.
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
ag->ncorners = 0;
|
||||
dtVset(ag->opts, 0,0,0);
|
||||
dtVset(ag->opte, 0,0,0);
|
||||
|
||||
if (ag->targetState == AGENT_TARGET_PATH)
|
||||
{
|
||||
// Find nest couple of corners for steering.
|
||||
ag->ncorners = findCorners(ag->pos, ag->target, ag->path, ag->npath,
|
||||
ag->cornerVerts, ag->cornerFlags, ag->cornerPolys,
|
||||
AGENT_MAX_CORNERS, navquery);
|
||||
|
||||
// Check to see if the corner after the next corner is directly visible,
|
||||
// and short cut to there.
|
||||
if (ag->ncorners > 1)
|
||||
{
|
||||
const float maxLookAhead = ag->colradius*4;
|
||||
|
||||
dtVcopy(ag->opts, ag->pos);
|
||||
dtVcopy(ag->opte, ag->cornerVerts+3);
|
||||
|
||||
ag->npath = optimizePath(ag->pos, ag->cornerVerts+3, maxLookAhead,
|
||||
ag->path, ag->npath, navquery, &filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate steering.
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
if (!ag->ncorners)
|
||||
{
|
||||
// No corner to steer to, stop.
|
||||
dtVset(ag->dvel, 0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate steering direction.
|
||||
if (flags & CROWDMAN_ANTICIPATE_TURNS)
|
||||
{
|
||||
calcSmoothSteerDirection(ag->pos, ag->cornerVerts, ag->ncorners, ag->dvel);
|
||||
}
|
||||
else
|
||||
{
|
||||
calcStraightSteerDirection(ag->pos, ag->cornerVerts, ag->ncorners, ag->dvel);
|
||||
}
|
||||
|
||||
// Calculate steering speed.
|
||||
|
||||
// Calculate speed scale, which tells the agent to slowdown at the end of the path.
|
||||
float speedScale = 1.0f;
|
||||
const bool endOfPath = (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_END) ? true : false;
|
||||
const bool offMeshConnection = (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ? true : false;
|
||||
const float slowDownRadius = ag->radius*2;
|
||||
if (endOfPath || offMeshConnection)
|
||||
{
|
||||
const float distToGoal = dtVdist2D(ag->pos, &ag->cornerVerts[(ag->ncorners-1)*3]);
|
||||
speedScale = dtMin(1.0f, distToGoal / slowDownRadius);
|
||||
}
|
||||
|
||||
// Apply style.
|
||||
if (flags & CROWDMAN_DRUNK)
|
||||
{
|
||||
// Drunken steering
|
||||
|
||||
// Pulsating speed.
|
||||
ag->t += dt * (1.0f - ag->var*0.25f);
|
||||
ag->maxspeed = MAX_SPEED*(1 + dtSqr(cosf(ag->t*2.0f))*0.3f);
|
||||
|
||||
dtVscale(ag->dvel, ag->dvel, ag->maxspeed * speedScale);
|
||||
|
||||
// Slightly wandering steering.
|
||||
const float amp = cosf(ag->var*13.69f+ag->t*3.123f) * 0.2f;
|
||||
const float nx = -ag->dvel[2];
|
||||
const float nz = ag->dvel[0];
|
||||
ag->dvel[0] += nx*amp;
|
||||
ag->dvel[2] += nz*amp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal steering.
|
||||
ag->maxspeed = MAX_SPEED;
|
||||
dtVscale(ag->dvel, ag->dvel, ag->maxspeed * speedScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Velocity planning.
|
||||
TimeVal rvoStartTime = getPerfTime();
|
||||
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
if (flags & CROWDMAN_USE_VO)
|
||||
{
|
||||
collectObstacles(ag, agents, nagents, m_obstacleQuery);
|
||||
|
||||
bool adaptive = true;
|
||||
|
||||
if (adaptive)
|
||||
{
|
||||
m_obstacleQuery->setSamplingGridSize(VO_ADAPTIVE_GRID_SIZE);
|
||||
m_obstacleQuery->setSamplingGridDepth(VO_ADAPTIVE_GRID_DEPTH);
|
||||
m_obstacleQuery->sampleVelocityAdaptive(ag->pos, ag->radius, ag->maxspeed,
|
||||
ag->vel, ag->dvel, ag->nvel, m_vodebug[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_obstacleQuery->setSamplingGridSize(VO_GRID_SIZE);
|
||||
m_obstacleQuery->sampleVelocity(ag->pos, ag->radius, ag->maxspeed, ag->vel, ag->dvel,
|
||||
ag->nvel, m_vodebug[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dtVcopy(ag->nvel, ag->dvel);
|
||||
}
|
||||
}
|
||||
TimeVal rvoEndTime = getPerfTime();
|
||||
|
||||
// Integrate.
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
// Fake dynamic constraint.
|
||||
const float maxDelta = MAX_ACC * dt;
|
||||
float dv[3];
|
||||
dtVsub(dv, ag->nvel, ag->vel);
|
||||
float ds = dtVlen(dv);
|
||||
if (ds > maxDelta)
|
||||
dtVscale(dv, dv, maxDelta/ds);
|
||||
dtVadd(ag->vel, ag->vel, dv);
|
||||
|
||||
// Integrate
|
||||
if (dtVlen(ag->vel) > 0.0001f)
|
||||
dtVmad(ag->npos, ag->pos, ag->vel, dt);
|
||||
else
|
||||
dtVcopy(ag->npos, ag->pos);
|
||||
}
|
||||
|
||||
// Handle collisions.
|
||||
for (int iter = 0; iter < 4; ++iter)
|
||||
{
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
dtVset(ag->disp, 0,0,0);
|
||||
|
||||
float w = 0;
|
||||
|
||||
for (int j = 0; j < nagents; ++j)
|
||||
{
|
||||
if (i == j) continue;
|
||||
Agent* nei = agents[j];
|
||||
|
||||
float diff[3];
|
||||
dtVsub(diff, ag->npos, nei->npos);
|
||||
|
||||
if (fabsf(diff[1]) >= (ag->height+nei->height)/2.0f)
|
||||
continue;
|
||||
|
||||
diff[1] = 0;
|
||||
|
||||
float dist = dtVlenSqr(diff);
|
||||
if (dist > dtSqr(ag->radius+nei->radius))
|
||||
continue;
|
||||
dist = sqrtf(dist);
|
||||
float pen = (ag->radius+nei->radius) - dist;
|
||||
if (dist > 0.0001f)
|
||||
pen = (1.0f/dist) * (pen*0.5f) * 0.7f;
|
||||
|
||||
dtVmad(ag->disp, ag->disp, diff, pen);
|
||||
|
||||
w += 1.0f;
|
||||
}
|
||||
|
||||
if (w > 0.0001f)
|
||||
{
|
||||
const float iw = 1.0f / w;
|
||||
dtVscale(ag->disp, ag->disp, iw);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
dtVadd(ag->npos, ag->npos, ag->disp);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
// Move along navmesh and update new position.
|
||||
float result[3];
|
||||
dtPolyRef visited[16];
|
||||
int nvisited = navquery->moveAlongSurface(ag->path[0], ag->pos, ag->npos, &filter,
|
||||
result, visited, 16);
|
||||
ag->npath = fixupCorridor(ag->path, ag->npath, AGENT_MAX_PATH, visited, nvisited);
|
||||
|
||||
// Adjust agent height to stay on top of the navmesh.
|
||||
float h = 0;
|
||||
navquery->getPolyHeight(ag->path[0], result, &h);
|
||||
result[1] = h;
|
||||
dtVcopy(ag->pos, result);
|
||||
}
|
||||
|
||||
|
||||
TimeVal endTime = getPerfTime();
|
||||
|
||||
int ns = 0;
|
||||
for (int i = 0; i < nagents; ++i)
|
||||
{
|
||||
Agent* ag = agents[i];
|
||||
|
||||
if (flags & CROWDMAN_USE_VO)
|
||||
{
|
||||
// Normalize samples for debug draw
|
||||
m_vodebug[i]->normalizeSamples();
|
||||
ns += m_vodebug[i]->getSampleCount();
|
||||
}
|
||||
|
||||
// Update agent movement trail.
|
||||
ag->htrail = (ag->htrail + 1) % AGENT_MAX_TRAIL;
|
||||
dtVcopy(&ag->trail[ag->htrail*3], ag->pos);
|
||||
}
|
||||
|
||||
m_sampleCount = ns;
|
||||
m_rvoTime = getPerfDeltaTimeUsec(rvoStartTime, rvoEndTime);
|
||||
m_totalTime = getPerfDeltaTimeUsec(startTime, endTime);
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,12 @@
|
||||
#include "DetourObstacleAvoidance.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "SampleInterfaces.h"
|
||||
#include "CrowdManager.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
static const int VO_ADAPTIVE_GRID_SIZE = 4;
|
||||
static const int VO_ADAPTIVE_GRID_DEPTH = 5;
|
||||
static const int VO_GRID_SIZE = 33;
|
||||
|
||||
|
||||
static bool isectSegAABB(const float* sp, const float* sq,
|
||||
const float* amin, const float* amax,
|
||||
@ -80,101 +77,6 @@ static bool isectSegAABB(const float* sp, const float* sq,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int fixupCorridor(dtPolyRef* path, const int npath, const int maxPath,
|
||||
const dtPolyRef* visited, const int nvisited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
||||
// Find furthest common polygon.
|
||||
for (int i = npath-1; i >= 0; --i)
|
||||
{
|
||||
bool found = false;
|
||||
for (int j = nvisited-1; j >= 0; --j)
|
||||
{
|
||||
if (path[i] == visited[j])
|
||||
{
|
||||
furthestPath = i;
|
||||
furthestVisited = j;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
// If no intersection found just return current path.
|
||||
if (furthestPath == -1 || furthestVisited == -1)
|
||||
return npath;
|
||||
|
||||
// Concatenate paths.
|
||||
|
||||
// Adjust beginning of the buffer to include the visited.
|
||||
const int req = nvisited - furthestVisited;
|
||||
const int orig = dtMin(furthestPath+1, npath);
|
||||
int size = dtMax(0, npath-orig);
|
||||
if (req+size > maxPath)
|
||||
size = maxPath-req;
|
||||
if (size)
|
||||
memmove(path+req, path+orig, size*sizeof(dtPolyRef));
|
||||
|
||||
// Store visited
|
||||
for (int i = 0; i < req; ++i)
|
||||
path[i] = visited[(nvisited-1)-i];
|
||||
|
||||
return req+size;
|
||||
}
|
||||
|
||||
static int mergeCorridor(dtPolyRef* path, const int npath, const int maxPath,
|
||||
const dtPolyRef* visited, const int nvisited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
||||
// Find furthest common polygon.
|
||||
for (int i = npath-1; i >= 0; --i)
|
||||
{
|
||||
bool found = false;
|
||||
for (int j = nvisited-1; j >= 0; --j)
|
||||
{
|
||||
if (path[i] == visited[j])
|
||||
{
|
||||
furthestPath = i;
|
||||
furthestVisited = j;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
// If no intersection found just return current path.
|
||||
if (furthestPath == -1 || furthestVisited == -1)
|
||||
return npath;
|
||||
|
||||
// Concatenate paths.
|
||||
|
||||
// Adjust beginning of the buffer to include the visited.
|
||||
const int req = furthestVisited;
|
||||
if (req <= 0)
|
||||
return npath;
|
||||
|
||||
const int orig = furthestPath;
|
||||
int size = dtMax(0, npath-orig);
|
||||
if (req+size > maxPath)
|
||||
size = maxPath-req;
|
||||
if (size)
|
||||
memmove(path+req, path+orig, size*sizeof(dtPolyRef));
|
||||
|
||||
// Store visited
|
||||
for (int i = 0; i < req; ++i)
|
||||
path[i] = visited[i];
|
||||
|
||||
return req+size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void getAgentBounds(const Agent* ag, float* bmin, float* bmax)
|
||||
{
|
||||
bmin[0] = ag->pos[0] - ag->radius;
|
||||
@ -185,543 +87,6 @@ static void getAgentBounds(const Agent* ag, float* bmin, float* bmax)
|
||||
bmax[2] = ag->pos[2] + ag->radius;
|
||||
}
|
||||
|
||||
|
||||
CrowdManager::CrowdManager() :
|
||||
m_obstacleQuery(0)
|
||||
{
|
||||
|
||||
m_obstacleQuery = dtAllocObstacleAvoidanceQuery();
|
||||
m_obstacleQuery->init(6, 10);
|
||||
|
||||
m_obstacleQuery->setDesiredVelocityWeight(2.0f);
|
||||
m_obstacleQuery->setCurrentVelocityWeight(0.75f);
|
||||
m_obstacleQuery->setPreferredSideWeight(0.75f);
|
||||
m_obstacleQuery->setCollisionTimeWeight(2.5f);
|
||||
m_obstacleQuery->setTimeHorizon(2.5f);
|
||||
m_obstacleQuery->setVelocitySelectionBias(0.4f);
|
||||
|
||||
memset(m_vodebug, 0, sizeof(m_vodebug));
|
||||
const int sampleCount = dtMax(VO_GRID_SIZE*VO_GRID_SIZE, (VO_ADAPTIVE_GRID_SIZE*VO_ADAPTIVE_GRID_SIZE)*VO_ADAPTIVE_GRID_DEPTH);
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
m_vodebug[i] = dtAllocObstacleAvoidanceDebugData();
|
||||
m_vodebug[i]->init(sampleCount);
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
CrowdManager::~CrowdManager()
|
||||
{
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
dtFreeObstacleAvoidanceDebugData(m_vodebug[i]);
|
||||
dtFreeObstacleAvoidanceQuery(m_obstacleQuery);
|
||||
}
|
||||
|
||||
void CrowdManager::reset()
|
||||
{
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
memset(&m_agents[i], 0, sizeof(Agent));
|
||||
}
|
||||
|
||||
const int CrowdManager::getAgentCount() const
|
||||
{
|
||||
return MAX_AGENTS;
|
||||
}
|
||||
|
||||
const Agent* CrowdManager::getAgent(const int idx)
|
||||
{
|
||||
return &m_agents[idx];
|
||||
}
|
||||
|
||||
int CrowdManager::addAgent(const float* pos, const float radius, const float height)
|
||||
{
|
||||
// Find empty slot.
|
||||
int idx = -1;
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
return -1;
|
||||
|
||||
Agent* ag = &m_agents[idx];
|
||||
memset(ag, 0, sizeof(Agent));
|
||||
dtVcopy(ag->pos, pos);
|
||||
ag->radius = radius;
|
||||
ag->colradius = radius * 7.5f;
|
||||
ag->height = height;
|
||||
ag->active = 1;
|
||||
ag->var = (rand() % 10) / 9.0f;
|
||||
|
||||
// Init trail
|
||||
for (int i = 0; i < AGENT_MAX_TRAIL; ++i)
|
||||
dtVcopy(&ag->trail[i*3], ag->pos);
|
||||
ag->htrail = 0;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void CrowdManager::removeAgent(const int idx)
|
||||
{
|
||||
if (idx >= 0 && idx < MAX_AGENTS)
|
||||
memset(&m_agents[idx], 0, sizeof(Agent));
|
||||
}
|
||||
|
||||
void CrowdManager::setMoveTarget(const int idx, const float* pos)
|
||||
{
|
||||
Agent* ag = &m_agents[idx];
|
||||
dtVcopy(ag->target, pos);
|
||||
ag->targetState = AGENT_TARGET_SET;
|
||||
}
|
||||
|
||||
static void calcSmoothSteerDirection(const float* pos, const float* corners, const int ncorners, float* dvel)
|
||||
{
|
||||
const int ip0 = 0;
|
||||
const int ip1 = dtMin(1, ncorners-1);
|
||||
const float* p0 = &corners[ip0*3];
|
||||
const float* p1 = &corners[ip1*3];
|
||||
|
||||
float dir0[3], dir1[3];
|
||||
dtVsub(dir0, p0, pos);
|
||||
dtVsub(dir1, p1, pos);
|
||||
dir0[1] = 0;
|
||||
dir1[1] = 0;
|
||||
|
||||
float len0 = dtVlen(dir0);
|
||||
float len1 = dtVlen(dir1);
|
||||
if (len1 > 0.001f)
|
||||
dtVscale(dir1,dir1,1.0f/len1);
|
||||
|
||||
const float strength = 0.5f;
|
||||
|
||||
dvel[0] = dir0[0] - dir1[0]*len0*strength;
|
||||
dvel[1] = 0;
|
||||
dvel[2] = dir0[2] - dir1[2]*len0*strength;
|
||||
}
|
||||
|
||||
void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery)
|
||||
{
|
||||
if (!navquery)
|
||||
return;
|
||||
|
||||
TimeVal startTime = getPerfTime();
|
||||
|
||||
const float ext[3] = {2,4,2};
|
||||
dtQueryFilter filter;
|
||||
|
||||
// Update target and agent navigation state.
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
if (!ag->npath)
|
||||
{
|
||||
float nearest[3];
|
||||
ag->path[0] = navquery->findNearestPoly(ag->pos, ext, &filter, nearest);
|
||||
if (ag->path[0])
|
||||
{
|
||||
ag->npath = 1;
|
||||
dtVcopy(ag->pos, nearest);
|
||||
}
|
||||
}
|
||||
|
||||
if (ag->targetState == AGENT_TARGET_SET)
|
||||
{
|
||||
float nearest[3];
|
||||
ag->targetRef = navquery->findNearestPoly(ag->target, ext, &filter, nearest);
|
||||
if (ag->targetRef)
|
||||
dtVcopy(ag->target, nearest);
|
||||
ag->targetState = AGENT_TARGET_ACQUIRED;
|
||||
}
|
||||
|
||||
if (ag->targetState == AGENT_TARGET_ACQUIRED)
|
||||
{
|
||||
ag->npath = navquery->findPath(ag->path[0], ag->targetRef, ag->pos, ag->target,
|
||||
&filter, ag->path, AGENT_MAX_PATH);
|
||||
if (ag->npath)
|
||||
{
|
||||
ag->targetState = AGENT_TARGET_PATH;
|
||||
// Check for partial path.
|
||||
if (ag->path[ag->npath-1] != ag->targetRef)
|
||||
{
|
||||
// Partial path, constrain target position inside the last polygon.
|
||||
ag->targetRef = ag->path[ag->npath-1];
|
||||
float nearest[3];
|
||||
if (navquery->closestPointOnPoly(ag->targetRef, ag->target, nearest))
|
||||
dtVcopy(ag->target, nearest);
|
||||
else
|
||||
ag->targetState = AGENT_TARGET_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
ag->targetState = AGENT_TARGET_FAILED;
|
||||
}
|
||||
|
||||
if (ag->npath && dtVdist2DSqr(ag->pos, ag->colcenter) > dtSqr(ag->colradius*0.25f))
|
||||
{
|
||||
dtVcopy(ag->colcenter, ag->pos);
|
||||
static const int MAX_LOCALS = 32;
|
||||
dtPolyRef locals[MAX_LOCALS];
|
||||
|
||||
const int nlocals = navquery->findLocalNeighbourhood(ag->path[0], ag->pos, ag->colradius, &filter, locals, 0, MAX_LOCALS);
|
||||
|
||||
ag->ncolsegs = 0;
|
||||
for (int j = 0; j < nlocals; ++j)
|
||||
{
|
||||
float segs[DT_VERTS_PER_POLYGON*3*2];
|
||||
const int nsegs = navquery->getPolyWallSegments(locals[j], &filter, segs);
|
||||
for (int k = 0; k < nsegs; ++k)
|
||||
{
|
||||
const float* s = &segs[k*6];
|
||||
// Skip too distant segments.
|
||||
float tseg;
|
||||
const float distSqr = dtDistancePtSegSqr2D(ag->pos, s, s+3, tseg);
|
||||
if (distSqr > dtSqr(ag->colradius))
|
||||
continue;
|
||||
if (ag->ncolsegs < AGENT_MAX_COLSEGS)
|
||||
{
|
||||
memcpy(&ag->colsegs[ag->ncolsegs*6], s, sizeof(float)*6);
|
||||
ag->ncolsegs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const float MAX_ACC = 8.0f;
|
||||
static const float MAX_SPEED = 3.5f;
|
||||
|
||||
static const float MIN_TARGET_DIST = 0.01f;
|
||||
|
||||
// Calculate steering.
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
if (m_agents[i].targetState != AGENT_TARGET_PATH) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
if (flags & CROWDMAN_DRUNK)
|
||||
{
|
||||
ag->t += dt * (1.0f - ag->var*0.25f);
|
||||
ag->maxspeed = MAX_SPEED*(1 + dtSqr(cosf(ag->t*2.0f))*0.3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
ag->maxspeed = MAX_SPEED;
|
||||
}
|
||||
|
||||
unsigned char cornerFlags[AGENT_MAX_CORNERS];
|
||||
dtPolyRef cornerPolys[AGENT_MAX_CORNERS];
|
||||
ag->ncorners = navquery->findStraightPath(ag->pos, ag->target, ag->path, ag->npath,
|
||||
ag->corners, cornerFlags, cornerPolys, AGENT_MAX_CORNERS);
|
||||
|
||||
// Prune points in the beginning of the path which are too close.
|
||||
while (ag->ncorners)
|
||||
{
|
||||
if ((cornerFlags[0] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
|
||||
dtVdist2DSqr(&ag->corners[0], ag->pos) > dtSqr(MIN_TARGET_DIST))
|
||||
break;
|
||||
ag->ncorners--;
|
||||
if (ag->ncorners)
|
||||
{
|
||||
memmove(cornerFlags, cornerFlags+1, sizeof(unsigned char)*ag->ncorners);
|
||||
memmove(cornerPolys, cornerPolys+1, sizeof(dtPolyRef)*ag->ncorners);
|
||||
memmove(ag->corners, ag->corners+3, sizeof(float)*3*ag->ncorners);
|
||||
}
|
||||
}
|
||||
|
||||
// Prune points after an off-mesh connection.
|
||||
for (int i = 0; i < ag->ncorners; ++i)
|
||||
{
|
||||
if (cornerFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION)
|
||||
{
|
||||
ag->ncorners = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ag->ncorners)
|
||||
{
|
||||
// No corner to steer to, stop.
|
||||
dtVset(ag->dvel, 0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate delta movement.
|
||||
|
||||
if (flags & CROWDMAN_ANTICIPATE_TURNS)
|
||||
{
|
||||
calcSmoothSteerDirection(ag->pos, ag->corners, ag->ncorners, ag->dvel);
|
||||
}
|
||||
else
|
||||
{
|
||||
dtVsub(ag->dvel, &ag->corners[0], ag->pos);
|
||||
ag->dvel[1] = 0;
|
||||
}
|
||||
|
||||
bool endOfPath = (cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_END) ? true : false;
|
||||
bool offMeshConnection = (cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ? true : false;
|
||||
|
||||
// Limit desired velocity to max speed.
|
||||
const float slowDownRadius = ag->radius*2;
|
||||
float distToGoal = slowDownRadius;
|
||||
if (endOfPath || offMeshConnection)
|
||||
distToGoal = dtVdist2D(ag->pos, &ag->corners[(ag->ncorners-1)*3]);
|
||||
|
||||
float clampedSpeed = ag->maxspeed * dtMin(1.0f, distToGoal / slowDownRadius);
|
||||
float speed = dtVlen(ag->dvel);
|
||||
if (speed > 0.0001f)
|
||||
clampedSpeed /= speed;
|
||||
dtVscale(ag->dvel, ag->dvel, clampedSpeed);
|
||||
|
||||
if (flags & CROWDMAN_DRUNK)
|
||||
{
|
||||
const float amp = cosf(ag->var*13.69f+ag->t*3.123f) * 0.2f;
|
||||
const float nx = -ag->dvel[2];
|
||||
const float nz = ag->dvel[0];
|
||||
ag->dvel[0] += nx*amp;
|
||||
ag->dvel[2] += nz*amp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Velocity planning.
|
||||
TimeVal rvoStartTime = getPerfTime();
|
||||
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
if (m_agents[i].targetState != AGENT_TARGET_PATH) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
if (flags & CROWDMAN_USE_VO)
|
||||
{
|
||||
m_obstacleQuery->reset();
|
||||
|
||||
// Add dynamic obstacles.
|
||||
for (int j = 0; j < MAX_AGENTS; ++j)
|
||||
{
|
||||
if (i == j) continue;
|
||||
const int idx = j;
|
||||
|
||||
if (!m_agents[idx].active) continue;
|
||||
Agent* nei = &m_agents[idx];
|
||||
|
||||
float diff[3];
|
||||
dtVsub(diff, ag->npos, nei->npos);
|
||||
if (fabsf(diff[1]) >= (ag->height+nei->height)/2.0f)
|
||||
continue;
|
||||
diff[1] = 0;
|
||||
|
||||
const float distSqr = dtVlenSqr(diff);
|
||||
if (distSqr > dtSqr(ag->colradius))
|
||||
continue;
|
||||
|
||||
m_obstacleQuery->addCircle(nei->pos, nei->radius, nei->vel, nei->dvel, distSqr);
|
||||
}
|
||||
|
||||
// Add static obstacles.
|
||||
for (int j = 0; j < ag->ncolsegs; ++j)
|
||||
{
|
||||
const float* s = &ag->colsegs[j*6];
|
||||
if (dtTriArea2D(ag->pos, s, s+3) < 0.0f)
|
||||
continue;
|
||||
|
||||
float tseg;
|
||||
const float distSqr = dtDistancePtSegSqr2D(ag->pos, s, s+3, tseg);
|
||||
|
||||
m_obstacleQuery->addSegment(s, s+3, distSqr);
|
||||
}
|
||||
|
||||
bool adaptive = true;
|
||||
|
||||
if (adaptive)
|
||||
{
|
||||
m_obstacleQuery->setSamplingGridSize(VO_ADAPTIVE_GRID_SIZE);
|
||||
m_obstacleQuery->setSamplingGridDepth(VO_ADAPTIVE_GRID_DEPTH);
|
||||
m_obstacleQuery->sampleVelocityAdaptive(ag->pos, ag->radius, ag->maxspeed,
|
||||
ag->vel, ag->dvel, ag->nvel, m_vodebug[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_obstacleQuery->setSamplingGridSize(VO_GRID_SIZE);
|
||||
m_obstacleQuery->sampleVelocity(ag->pos, ag->radius, ag->maxspeed, ag->vel, ag->dvel,
|
||||
ag->nvel, m_vodebug[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dtVcopy(ag->nvel, ag->dvel);
|
||||
}
|
||||
}
|
||||
TimeVal rvoEndTime = getPerfTime();
|
||||
|
||||
// Integrate and update perceived velocity.
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
// Fake dynamic constraint.
|
||||
const float maxDelta = MAX_ACC * dt;
|
||||
float dv[3];
|
||||
dtVsub(dv, ag->nvel, ag->vel);
|
||||
float ds = dtVlen(dv);
|
||||
if (ds > maxDelta)
|
||||
dtVscale(dv, dv, maxDelta/ds);
|
||||
dtVadd(ag->vel, ag->vel, dv);
|
||||
|
||||
// Integrate
|
||||
if (dtVlen(ag->vel) > 0.0001f)
|
||||
dtVmad(ag->npos, ag->pos, ag->vel, dt);
|
||||
else
|
||||
dtVcopy(ag->npos, ag->pos);
|
||||
}
|
||||
|
||||
// Handle collisions.
|
||||
for (int iter = 0; iter < 4; ++iter)
|
||||
{
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
dtVset(ag->disp, 0,0,0);
|
||||
|
||||
float w = 0;
|
||||
|
||||
for (int j = 0; j < MAX_AGENTS; ++j)
|
||||
{
|
||||
if (i == j) continue;
|
||||
if (!m_agents[j].active) continue;
|
||||
Agent* nei = &m_agents[j];
|
||||
|
||||
float diff[3];
|
||||
dtVsub(diff, ag->npos, nei->npos);
|
||||
|
||||
if (fabsf(diff[1]) >= (ag->height+nei->height)/2.0f)
|
||||
continue;
|
||||
|
||||
diff[1] = 0;
|
||||
|
||||
float dist = dtVlenSqr(diff);
|
||||
if (dist > dtSqr(ag->radius+nei->radius))
|
||||
continue;
|
||||
dist = sqrtf(dist);
|
||||
float pen = (ag->radius+nei->radius) - dist;
|
||||
if (dist > 0.0001f)
|
||||
pen = (1.0f/dist) * (pen*0.5f) * 0.7f;
|
||||
|
||||
dtVmad(ag->disp, ag->disp, diff, pen);
|
||||
|
||||
w += 1.0f;
|
||||
}
|
||||
|
||||
if (w > 0.0001f)
|
||||
{
|
||||
const float iw = 1.0f / w;
|
||||
dtVscale(ag->disp, ag->disp, iw);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
dtVadd(ag->npos, ag->npos, ag->disp);
|
||||
}
|
||||
}
|
||||
|
||||
// Move along navmesh and update new position.
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
Agent* ag = &m_agents[i];
|
||||
|
||||
float result[3];
|
||||
dtPolyRef visited[16];
|
||||
int nvisited = navquery->moveAlongSurface(ag->path[0], ag->pos, ag->npos, &filter,
|
||||
result, visited, 16);
|
||||
ag->npath = fixupCorridor(ag->path, ag->npath, AGENT_MAX_PATH, visited, nvisited);
|
||||
|
||||
float h = 0;
|
||||
navquery->getPolyHeight(ag->path[0], result, &h);
|
||||
result[1] = h;
|
||||
dtVcopy(ag->pos, result);
|
||||
|
||||
ag->htrail = (ag->htrail + 1) % AGENT_MAX_TRAIL;
|
||||
dtVcopy(&ag->trail[ag->htrail*3], ag->pos);
|
||||
}
|
||||
|
||||
// Optimize path
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
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.
|
||||
float tgt[3];
|
||||
dtVcopy(tgt, &ag->corners[3]);
|
||||
const float distSqr = dtVdist2DSqr(ag->pos, tgt);
|
||||
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];
|
||||
const int nres = navquery->raycast(ag->path[0], ag->pos, tgt, &filter, t, norm, res, MAX_RES);
|
||||
if (nres > 1 && t > 0.99f)
|
||||
{
|
||||
ag->npath = mergeCorridor(ag->path, ag->npath, AGENT_MAX_PATH, res, nres);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TimeVal endTime = getPerfTime();
|
||||
|
||||
int ns = 0;
|
||||
for (int i = 0; i < MAX_AGENTS; ++i)
|
||||
{
|
||||
if (!m_agents[i].active) continue;
|
||||
if (m_agents[i].targetState != AGENT_TARGET_PATH) continue;
|
||||
if (flags & CROWDMAN_USE_VO)
|
||||
{
|
||||
// Normalize samples for debug draw
|
||||
m_vodebug[i]->normalizeSamples();
|
||||
ns += m_vodebug[i]->getSampleCount();
|
||||
}
|
||||
}
|
||||
|
||||
m_sampleCount.addSample((float)ns);
|
||||
m_totalTime.addSample(getPerfDeltaTimeUsec(startTime, endTime) / 1000.0f);
|
||||
m_rvoTime.addSample(getPerfDeltaTimeUsec(rvoStartTime, rvoEndTime) / 1000.0f);
|
||||
}
|
||||
|
||||
static int insertIsect(float u, int inside, Isect* ints, int nints)
|
||||
{
|
||||
int i;
|
||||
@ -950,7 +315,7 @@ void CrowdTool::handleClick(const float* s, const float* p, bool shift)
|
||||
}
|
||||
else
|
||||
{
|
||||
bool single = false;
|
||||
bool single = true;
|
||||
|
||||
if (single)
|
||||
{
|
||||
@ -1066,6 +431,10 @@ void CrowdTool::handleUpdate(const float dt)
|
||||
flags |= CROWDMAN_DRUNK;
|
||||
|
||||
m_crowd.update(dt, flags, m_sample->getNavMeshQuery());
|
||||
|
||||
m_crowdSampleCount.addSample((float)m_crowd.getSampleCount());
|
||||
m_crowdTotalTime.addSample(m_crowd.getTotalTime() / 1000.0f);
|
||||
m_crowdRvoTime.addSample(m_crowd.getRVOTime() / 1000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1127,8 +496,8 @@ void CrowdTool::handleRender()
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
for (int j = 0; j < ag->ncorners; ++j)
|
||||
{
|
||||
const float* va = j == 0 ? ag->pos : &ag->corners[(j-1)*3];
|
||||
const float* vb = &ag->corners[j*3];
|
||||
const float* va = j == 0 ? ag->pos : &ag->cornerVerts[(j-1)*3];
|
||||
const float* vb = &ag->cornerVerts[j*3];
|
||||
dd.vertex(va[0],va[1]+ag->radius,va[2], duRGBA(128,0,0,64));
|
||||
dd.vertex(vb[0],vb[1]+ag->radius,vb[2], duRGBA(128,0,0,64));
|
||||
}
|
||||
@ -1136,14 +505,14 @@ void CrowdTool::handleRender()
|
||||
|
||||
if (m_anticipateTurns)
|
||||
{
|
||||
float dvel[3], pos[3];
|
||||
calcSmoothSteerDirection(ag->pos, ag->corners, ag->ncorners, dvel);
|
||||
/* 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->corners[0];
|
||||
const float* tgt = &ag->cornerVerts[0];
|
||||
const float y = ag->pos[1]+off;
|
||||
|
||||
dd.begin(DU_DRAW_LINES, 2.0f);
|
||||
@ -1154,7 +523,7 @@ void CrowdTool::handleRender()
|
||||
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();
|
||||
dd.end();*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1351,10 +720,10 @@ void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
|
||||
gp.setValueRange(0.0f, 2.0f, 4, "ms");
|
||||
|
||||
drawGraphBackground(&gp);
|
||||
drawGraph(&gp, m_crowd.getRVOTimeGraph(), 0, "RVO Sampling", duRGBA(255,0,128,255));
|
||||
drawGraph(&gp, m_crowd.getTotalTimeGraph(), 1, "Total", duRGBA(128,255,0,255));
|
||||
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_crowd.getSampleCountGraph(), 0, "Sample Count", duRGBA(255,255,255,255));
|
||||
drawGraph(&gp, &m_crowdSampleCount, 0, "Sample Count", duRGBA(255,255,255,255));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user