Changed the sample stuff to support extra link tool. Added simple tool to create eextra links (no detour support yet).

This commit is contained in:
Mikko Mononen
2010-01-05 14:26:40 +00:00
parent 57c70704d8
commit eb6b215d23
19 changed files with 3692 additions and 740 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -280,14 +280,14 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
<integer>42</integer>
<integer>37</integer>
<integer>34</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 460}, {282, 660}}</string>
<string>{{0, 464}, {282, 660}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@@ -322,7 +322,7 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A30F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>Sample_TileMesh.cpp</string>
<string>ExtraLinkTool.cpp</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@@ -330,11 +330,11 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A40F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>Sample_TileMesh.cpp</string>
<string>ExtraLinkTool.cpp</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>6BBB89A710EAC398008FEA1F</string>
<string>6BB7FE8710F3830D006DA0A6</string>
<key>history</key>
<array>
<string>6B57D358108C66B200DDD053</string>
@@ -359,27 +359,33 @@
<string>6BB93D0A10CFFC1300F74F2B</string>
<string>6BB93D1510CFFC6D00F74F2B</string>
<string>6BB93D1B10CFFD7600F74F2B</string>
<string>6B98693110DF8929007D8D84</string>
<string>6B98693310DF8929007D8D84</string>
<string>6B9869F710DFFA98007D8D84</string>
<string>6B9869F810DFFA98007D8D84</string>
<string>6BBB87D710EA97CC008FEA1F</string>
<string>6BBB87D910EA97CC008FEA1F</string>
<string>6BBB87DA10EA97CC008FEA1F</string>
<string>6BBB883C10EA9B6F008FEA1F</string>
<string>6BBB884E10EA9ECC008FEA1F</string>
<string>6BBB889B10EAA094008FEA1F</string>
<string>6BBB894510EAAB73008FEA1F</string>
<string>6BBB898310EAB1AA008FEA1F</string>
<string>6BBB898810EAB225008FEA1F</string>
<string>6BBB898E10EABB10008FEA1F</string>
<string>6BBB898F10EABB10008FEA1F</string>
<string>6BBB899110EABB10008FEA1F</string>
<string>6BBB899210EABB10008FEA1F</string>
<string>6BBB899D10EABD34008FEA1F</string>
<string>6BBB899E10EABD34008FEA1F</string>
<string>6BBB899F10EABD34008FEA1F</string>
<string>6BBB89A010EABD34008FEA1F</string>
<string>6BB7FD7F10F36BD5006DA0A6</string>
<string>6BB7FDB210F37703006DA0A6</string>
<string>6BB7FDB310F37703006DA0A6</string>
<string>6BB7FDB410F37703006DA0A6</string>
<string>6BB7FDC010F37703006DA0A6</string>
<string>6BB7FDC110F37703006DA0A6</string>
<string>6BB7FDEE10F377DD006DA0A6</string>
<string>6BB7FE0F10F37CF7006DA0A6</string>
<string>6BB7FE1010F37CF7006DA0A6</string>
<string>6BB7FE3A10F3817A006DA0A6</string>
<string>6BB7FE3B10F3817A006DA0A6</string>
<string>6BB7FE3C10F3817A006DA0A6</string>
<string>6BB7FE3E10F3817A006DA0A6</string>
<string>6BB7FE6010F381DC006DA0A6</string>
<string>6BB7FE7410F38224006DA0A6</string>
<string>6BB7FE7510F38224006DA0A6</string>
<string>6BB7FE7610F38224006DA0A6</string>
<string>6BB7FE8210F3830D006DA0A6</string>
<string>6BB7FE8310F3830D006DA0A6</string>
<string>6BB7FE8410F3830D006DA0A6</string>
</array>
<key>prevStack</key>
<array>
@@ -387,189 +393,98 @@
<string>6B98693810DF8929007D8D84</string>
<string>6B98693910DF8929007D8D84</string>
<string>6B9869FC10DFFA98007D8D84</string>
<string>6BBB87E310EA97CC008FEA1F</string>
<string>6BBB87E410EA97CC008FEA1F</string>
<string>6BBB87E510EA97CC008FEA1F</string>
<string>6BBB87E610EA97CC008FEA1F</string>
<string>6BBB87E710EA97CC008FEA1F</string>
<string>6BBB87E810EA97CC008FEA1F</string>
<string>6BBB87E910EA97CC008FEA1F</string>
<string>6BBB87EB10EA97CC008FEA1F</string>
<string>6BBB87EC10EA97CC008FEA1F</string>
<string>6BBB87EF10EA97CC008FEA1F</string>
<string>6BBB87F010EA97CC008FEA1F</string>
<string>6BBB87F110EA97CC008FEA1F</string>
<string>6BBB87F410EA97CC008FEA1F</string>
<string>6BBB87F510EA97CC008FEA1F</string>
<string>6BBB87F610EA97CC008FEA1F</string>
<string>6BBB87F710EA97CC008FEA1F</string>
<string>6BBB87F810EA97CC008FEA1F</string>
<string>6BBB87FA10EA97CC008FEA1F</string>
<string>6BBB87FB10EA97CC008FEA1F</string>
<string>6BBB87FC10EA97CC008FEA1F</string>
<string>6BBB87FD10EA97CC008FEA1F</string>
<string>6BBB87FE10EA97CC008FEA1F</string>
<string>6BBB87FF10EA97CC008FEA1F</string>
<string>6BBB880010EA97CC008FEA1F</string>
<string>6BBB880110EA97CC008FEA1F</string>
<string>6BBB880210EA97CC008FEA1F</string>
<string>6BBB880310EA97CC008FEA1F</string>
<string>6BBB880510EA97CC008FEA1F</string>
<string>6BBB880610EA97CC008FEA1F</string>
<string>6BBB880710EA97CC008FEA1F</string>
<string>6BBB880810EA97CC008FEA1F</string>
<string>6BBB880910EA97CC008FEA1F</string>
<string>6BBB880A10EA97CC008FEA1F</string>
<string>6BBB880B10EA97CC008FEA1F</string>
<string>6BBB880C10EA97CC008FEA1F</string>
<string>6BBB880D10EA97CC008FEA1F</string>
<string>6BBB880E10EA97CC008FEA1F</string>
<string>6BBB880F10EA97CC008FEA1F</string>
<string>6BBB881010EA97CC008FEA1F</string>
<string>6BBB881110EA97CC008FEA1F</string>
<string>6BBB881210EA97CC008FEA1F</string>
<string>6BBB881310EA97CC008FEA1F</string>
<string>6BBB881410EA97CC008FEA1F</string>
<string>6BBB881510EA97CC008FEA1F</string>
<string>6BBB881610EA97CC008FEA1F</string>
<string>6BBB881710EA97CC008FEA1F</string>
<string>6BBB881810EA97CC008FEA1F</string>
<string>6BBB882710EA99CA008FEA1F</string>
<string>6BBB882810EA99CA008FEA1F</string>
<string>6BBB882910EA99CA008FEA1F</string>
<string>6BBB882A10EA99CA008FEA1F</string>
<string>6BBB883610EA9B3D008FEA1F</string>
<string>6BBB883710EA9B3D008FEA1F</string>
<string>6BBB883E10EA9B6F008FEA1F</string>
<string>6BBB883F10EA9B6F008FEA1F</string>
<string>6BBB885510EA9ECC008FEA1F</string>
<string>6BBB885610EA9ECC008FEA1F</string>
<string>6BBB885710EA9ECC008FEA1F</string>
<string>6BBB885810EA9ECC008FEA1F</string>
<string>6BBB885910EA9ECC008FEA1F</string>
<string>6BBB885A10EA9ECC008FEA1F</string>
<string>6BBB885B10EA9ECC008FEA1F</string>
<string>6BBB885C10EA9ECC008FEA1F</string>
<string>6BBB885D10EA9ECC008FEA1F</string>
<string>6BBB885E10EA9ECC008FEA1F</string>
<string>6BBB885F10EA9ECC008FEA1F</string>
<string>6BBB886010EA9ECC008FEA1F</string>
<string>6BBB886110EA9ECC008FEA1F</string>
<string>6BBB886210EA9ECC008FEA1F</string>
<string>6BBB886310EA9ECC008FEA1F</string>
<string>6BBB886410EA9ECC008FEA1F</string>
<string>6BBB886510EA9ECC008FEA1F</string>
<string>6BBB886610EA9ECC008FEA1F</string>
<string>6BBB886710EA9ECC008FEA1F</string>
<string>6BBB886810EA9ECC008FEA1F</string>
<string>6BBB886910EA9ECC008FEA1F</string>
<string>6BBB886A10EA9ECC008FEA1F</string>
<string>6BBB886B10EA9ECC008FEA1F</string>
<string>6BBB886C10EA9ECC008FEA1F</string>
<string>6BBB886D10EA9ECC008FEA1F</string>
<string>6BBB886E10EA9ECC008FEA1F</string>
<string>6BBB886F10EA9ECC008FEA1F</string>
<string>6BBB887010EA9ECC008FEA1F</string>
<string>6BBB887110EA9ECC008FEA1F</string>
<string>6BBB887210EA9ECC008FEA1F</string>
<string>6BBB887310EA9ECC008FEA1F</string>
<string>6BBB887410EA9ECC008FEA1F</string>
<string>6BBB887E10EA9FE6008FEA1F</string>
<string>6BBB887F10EA9FE6008FEA1F</string>
<string>6BBB888010EA9FE6008FEA1F</string>
<string>6BBB888110EA9FE6008FEA1F</string>
<string>6BBB888210EA9FE6008FEA1F</string>
<string>6BBB888310EA9FE6008FEA1F</string>
<string>6BBB888410EA9FE6008FEA1F</string>
<string>6BBB889610EAA050008FEA1F</string>
<string>6BBB889D10EAA094008FEA1F</string>
<string>6BBB88B410EAA316008FEA1F</string>
<string>6BBB88B510EAA316008FEA1F</string>
<string>6BBB88B610EAA316008FEA1F</string>
<string>6BBB88B710EAA316008FEA1F</string>
<string>6BBB88B810EAA316008FEA1F</string>
<string>6BBB88B910EAA316008FEA1F</string>
<string>6BBB88BA10EAA316008FEA1F</string>
<string>6BBB88BB10EAA316008FEA1F</string>
<string>6BBB88BC10EAA316008FEA1F</string>
<string>6BBB88BD10EAA316008FEA1F</string>
<string>6BBB88C110EAA316008FEA1F</string>
<string>6BBB88C210EAA316008FEA1F</string>
<string>6BBB88C310EAA316008FEA1F</string>
<string>6BBB88C510EAA316008FEA1F</string>
<string>6BBB88C610EAA316008FEA1F</string>
<string>6BBB88C710EAA316008FEA1F</string>
<string>6BBB88C810EAA316008FEA1F</string>
<string>6BBB88D310EAA384008FEA1F</string>
<string>6BBB88D410EAA384008FEA1F</string>
<string>6BBB88D510EAA384008FEA1F</string>
<string>6BBB88DA10EAA39C008FEA1F</string>
<string>6BBB88E410EAA3D9008FEA1F</string>
<string>6BBB88E510EAA3D9008FEA1F</string>
<string>6BBB88E610EAA3D9008FEA1F</string>
<string>6BBB88E710EAA3D9008FEA1F</string>
<string>6BBB88E810EAA3D9008FEA1F</string>
<string>6BBB88E910EAA3D9008FEA1F</string>
<string>6BBB88F010EAA44E008FEA1F</string>
<string>6BBB88F410EAA4E6008FEA1F</string>
<string>6BBB88FC10EAA614008FEA1F</string>
<string>6BBB88FD10EAA614008FEA1F</string>
<string>6BBB88FE10EAA614008FEA1F</string>
<string>6BBB88FF10EAA614008FEA1F</string>
<string>6BBB890010EAA614008FEA1F</string>
<string>6BBB890110EAA614008FEA1F</string>
<string>6BBB890210EAA614008FEA1F</string>
<string>6BBB890310EAA614008FEA1F</string>
<string>6BBB890A10EAA6C2008FEA1F</string>
<string>6BBB890D10EAA6C2008FEA1F</string>
<string>6BBB890E10EAA6C2008FEA1F</string>
<string>6BBB891B10EAA87B008FEA1F</string>
<string>6BBB891C10EAA87B008FEA1F</string>
<string>6BBB891D10EAA87B008FEA1F</string>
<string>6BBB891F10EAA87B008FEA1F</string>
<string>6BBB892310EAA87B008FEA1F</string>
<string>6BBB892510EAA87B008FEA1F</string>
<string>6BBB892710EAA87B008FEA1F</string>
<string>6BBB892810EAA87B008FEA1F</string>
<string>6BBB892910EAA87B008FEA1F</string>
<string>6BBB892A10EAA87B008FEA1F</string>
<string>6BBB892B10EAA87B008FEA1F</string>
<string>6BBB892F10EAA899008FEA1F</string>
<string>6BBB893A10EAAADC008FEA1F</string>
<string>6BBB893C10EAAADC008FEA1F</string>
<string>6BBB893D10EAAADC008FEA1F</string>
<string>6BBB893E10EAAADC008FEA1F</string>
<string>6BBB894A10EAAB73008FEA1F</string>
<string>6BBB894C10EAAB73008FEA1F</string>
<string>6BBB894E10EAAB73008FEA1F</string>
<string>6BBB895010EAAB73008FEA1F</string>
<string>6BBB895210EAAB73008FEA1F</string>
<string>6BBB895310EAAB73008FEA1F</string>
<string>6BBB895510EAAB73008FEA1F</string>
<string>6BBB896010EAAE6C008FEA1F</string>
<string>6BBB896110EAAE6C008FEA1F</string>
<string>6BBB896310EAAE6C008FEA1F</string>
<string>6BBB896C10EAB179008FEA1F</string>
<string>6BBB896E10EAB179008FEA1F</string>
<string>6BBB897010EAB179008FEA1F</string>
<string>6BBB897210EAB179008FEA1F</string>
<string>6BBB897410EAB179008FEA1F</string>
<string>6BBB897610EAB179008FEA1F</string>
<string>6BBB897810EAB179008FEA1F</string>
<string>6BBB897A10EAB179008FEA1F</string>
<string>6BBB897C10EAB179008FEA1F</string>
<string>6BBB898510EAB1AA008FEA1F</string>
<string>6BBB898610EAB1AA008FEA1F</string>
<string>6BBB898A10EAB225008FEA1F</string>
<string>6BBB899410EABB10008FEA1F</string>
<string>6BBB899510EABB10008FEA1F</string>
<string>6BBB899610EABB10008FEA1F</string>
<string>6BBB899710EABB10008FEA1F</string>
<string>6BBB899810EABB10008FEA1F</string>
<string>6BBB899910EABB10008FEA1F</string>
<string>6BBB89A110EABD34008FEA1F</string>
<string>6BBB89A210EABD34008FEA1F</string>
<string>6BBB89A310EABD34008FEA1F</string>
<string>6BB7FD6110F3564B006DA0A6</string>
<string>6BB7FD6310F3564B006DA0A6</string>
<string>6BB7FD6410F3564B006DA0A6</string>
<string>6BB7FD6510F3564B006DA0A6</string>
<string>6BB7FD6610F3564B006DA0A6</string>
<string>6BB7FD6910F3564B006DA0A6</string>
<string>6BB7FD8310F36BD5006DA0A6</string>
<string>6BB7FD8410F36BD5006DA0A6</string>
<string>6BB7FD8510F36BD5006DA0A6</string>
<string>6BB7FD8610F36BD5006DA0A6</string>
<string>6BB7FD8710F36BD5006DA0A6</string>
<string>6BB7FD8810F36BD5006DA0A6</string>
<string>6BB7FD8910F36BD5006DA0A6</string>
<string>6BB7FD8B10F36BD5006DA0A6</string>
<string>6BB7FD9F10F36D7A006DA0A6</string>
<string>6BB7FDC510F37703006DA0A6</string>
<string>6BB7FDC610F37703006DA0A6</string>
<string>6BB7FDC710F37703006DA0A6</string>
<string>6BB7FDC810F37703006DA0A6</string>
<string>6BB7FDCB10F37703006DA0A6</string>
<string>6BB7FDCC10F37703006DA0A6</string>
<string>6BB7FDCD10F37703006DA0A6</string>
<string>6BB7FDCE10F37703006DA0A6</string>
<string>6BB7FDCF10F37703006DA0A6</string>
<string>6BB7FDD010F37703006DA0A6</string>
<string>6BB7FDD810F37703006DA0A6</string>
<string>6BB7FDD910F37703006DA0A6</string>
<string>6BB7FDDA10F37703006DA0A6</string>
<string>6BB7FDDB10F37703006DA0A6</string>
<string>6BB7FDDC10F37703006DA0A6</string>
<string>6BB7FDDD10F37703006DA0A6</string>
<string>6BB7FDDE10F37703006DA0A6</string>
<string>6BB7FDDF10F37703006DA0A6</string>
<string>6BB7FDE010F37703006DA0A6</string>
<string>6BB7FDE110F37703006DA0A6</string>
<string>6BB7FDE210F37703006DA0A6</string>
<string>6BB7FDE310F37703006DA0A6</string>
<string>6BB7FDF210F377DD006DA0A6</string>
<string>6BB7FDF310F377DD006DA0A6</string>
<string>6BB7FDF410F377DD006DA0A6</string>
<string>6BB7FDF510F377DD006DA0A6</string>
<string>6BB7FDF610F377DD006DA0A6</string>
<string>6BB7FDF810F377DD006DA0A6</string>
<string>6BB7FDFA10F377DD006DA0A6</string>
<string>6BB7FE1710F37CF7006DA0A6</string>
<string>6BB7FE1810F37CF7006DA0A6</string>
<string>6BB7FE1910F37CF7006DA0A6</string>
<string>6BB7FE1A10F37CF7006DA0A6</string>
<string>6BB7FE1B10F37CF7006DA0A6</string>
<string>6BB7FE1C10F37CF7006DA0A6</string>
<string>6BB7FE1D10F37CF7006DA0A6</string>
<string>6BB7FE1E10F37CF7006DA0A6</string>
<string>6BB7FE1F10F37CF7006DA0A6</string>
<string>6BB7FE2110F37CF7006DA0A6</string>
<string>6BB7FE2210F37CF7006DA0A6</string>
<string>6BB7FE2310F37CF7006DA0A6</string>
<string>6BB7FE4310F3817A006DA0A6</string>
<string>6BB7FE4410F3817A006DA0A6</string>
<string>6BB7FE4510F3817A006DA0A6</string>
<string>6BB7FE4610F3817A006DA0A6</string>
<string>6BB7FE4710F3817A006DA0A6</string>
<string>6BB7FE4810F3817A006DA0A6</string>
<string>6BB7FE4910F3817A006DA0A6</string>
<string>6BB7FE4A10F3817A006DA0A6</string>
<string>6BB7FE4B10F3817A006DA0A6</string>
<string>6BB7FE4C10F3817A006DA0A6</string>
<string>6BB7FE4D10F3817A006DA0A6</string>
<string>6BB7FE4E10F3817A006DA0A6</string>
<string>6BB7FE4F10F3817A006DA0A6</string>
<string>6BB7FE5010F3817A006DA0A6</string>
<string>6BB7FE5110F3817A006DA0A6</string>
<string>6BB7FE5210F3817A006DA0A6</string>
<string>6BB7FE5310F3817A006DA0A6</string>
<string>6BB7FE5410F3817A006DA0A6</string>
<string>6BB7FE5510F3817A006DA0A6</string>
<string>6BB7FE5610F3817A006DA0A6</string>
<string>6BB7FE5710F3817A006DA0A6</string>
<string>6BB7FE5810F3817A006DA0A6</string>
<string>6BB7FE5910F3817A006DA0A6</string>
<string>6BB7FE6310F381DC006DA0A6</string>
<string>6BB7FE6410F381DC006DA0A6</string>
<string>6BB7FE7810F38224006DA0A6</string>
<string>6BB7FE7910F38224006DA0A6</string>
<string>6BB7FE7A10F38224006DA0A6</string>
<string>6BB7FE8510F3830D006DA0A6</string>
<string>6BB7FE8610F3830D006DA0A6</string>
</array>
</dict>
<key>SplitCount</key>
@@ -583,18 +498,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {976, 515}}</string>
<string>{{0, 0}, {976, 527}}</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>515pt</string>
<string>527pt</string>
</dict>
<dict>
<key>Proportion</key>
<string>158pt</string>
<string>146pt</string>
<key>Tabs</key>
<array>
<dict>
@@ -608,7 +523,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {976, 194}}</string>
<string>{{10, 27}, {976, 119}}</string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@@ -662,7 +577,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {976, 131}}</string>
<string>{{10, 27}, {976, 119}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1280 719 0 0 1280 778 </string>
</dict>
@@ -692,11 +607,11 @@
</array>
<key>TableOfContents</key>
<array>
<string>6BBB881A10EA97CC008FEA1F</string>
<string>6BB7FD6B10F3564B006DA0A6</string>
<string>1CA23ED40692098700951B8B</string>
<string>6BBB881B10EA97CC008FEA1F</string>
<string>6BB7FD6C10F3564B006DA0A6</string>
<string>6B8632A30F78115100E2684A</string>
<string>6BBB881C10EA97CC008FEA1F</string>
<string>6BB7FD6D10F3564B006DA0A6</string>
<string>1CA23EDF0692099D00951B8B</string>
<string>1CA23EE00692099D00951B8B</string>
<string>1CA23EE10692099D00951B8B</string>
@@ -845,14 +760,14 @@
</array>
<key>TableOfContents</key>
<array>
<string>6BBB882C10EA99CA008FEA1F</string>
<string>6BB7FD6E10F3564B006DA0A6</string>
<string>1CCC7628064C1048000F2A68</string>
<string>1CCC7629064C1048000F2A68</string>
<string>6BBB882D10EA99CA008FEA1F</string>
<string>6BBB882E10EA99CA008FEA1F</string>
<string>6BBB882F10EA99CA008FEA1F</string>
<string>6BBB883010EA99CA008FEA1F</string>
<string>6BBB883110EA99CA008FEA1F</string>
<string>6BB7FD6F10F3564B006DA0A6</string>
<string>6BB7FD7010F3564B006DA0A6</string>
<string>6BB7FD7110F3564B006DA0A6</string>
<string>6BB7FD7210F3564B006DA0A6</string>
<string>6BB7FD7310F3564B006DA0A6</string>
</array>
<key>ToolbarConfigUserDefaultsMinorVersion</key>
<string>2</string>
@@ -884,8 +799,8 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
<string>6BBB888F10EAA01C008FEA1F</string>
<string>6BBB889010EAA01C008FEA1F</string>
<string>6BB7FDE610F37703006DA0A6</string>
<string>6BB7FDE710F37703006DA0A6</string>
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
</array>
<key>WindowString</key>

View File

@@ -35,6 +35,8 @@
6BA1E88C10C7BFC9008007F6 /* Sample_SoloMeshTiled.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BA1E88910C7BFC9008007F6 /* Sample_SoloMeshTiled.cpp */; };
6BB788170FC0472B003C24DB /* ChunkyTriMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB788160FC0472B003C24DB /* ChunkyTriMesh.cpp */; };
6BB7FC0B10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; };
6BB7FD4A10F3559D006DA0A6 /* ExtraLinkTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7FD4910F3559D006DA0A6 /* ExtraLinkTool.cpp */; };
6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */; };
6BB93C7D10CFE1D500F74F2B /* DebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7A10CFE1D500F74F2B /* DebugDraw.cpp */; };
6BB93C7E10CFE1D500F74F2B /* DetourDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7B10CFE1D500F74F2B /* DetourDebugDraw.cpp */; };
6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */; };
@@ -96,6 +98,10 @@
6BB788180FC04753003C24DB /* ChunkyTriMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChunkyTriMesh.h; path = ../../Include/ChunkyTriMesh.h; sourceTree = SOURCE_ROOT; };
6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NavMeshTesterTool.h; path = ../../Include/NavMeshTesterTool.h; sourceTree = SOURCE_ROOT; };
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NavMeshTesterTool.cpp; path = ../../Source/NavMeshTesterTool.cpp; sourceTree = SOURCE_ROOT; };
6BB7FD4810F3558D006DA0A6 /* ExtraLinkTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtraLinkTool.h; path = ../../Include/ExtraLinkTool.h; sourceTree = SOURCE_ROOT; };
6BB7FD4910F3559D006DA0A6 /* ExtraLinkTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExtraLinkTool.cpp; path = ../../Source/ExtraLinkTool.cpp; sourceTree = SOURCE_ROOT; };
6BB7FDA310F36EFC006DA0A6 /* InputGeom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InputGeom.h; path = ../../Include/InputGeom.h; sourceTree = SOURCE_ROOT; };
6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputGeom.cpp; path = ../../Source/InputGeom.cpp; sourceTree = SOURCE_ROOT; };
6BB93C7710CFE1D500F74F2B /* DebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DebugDraw.h; path = ../../../DebugUtils/Include/DebugDraw.h; sourceTree = SOURCE_ROOT; };
6BB93C7810CFE1D500F74F2B /* DetourDebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetourDebugDraw.h; path = ../../../DebugUtils/Include/DetourDebugDraw.h; sourceTree = SOURCE_ROOT; };
6BB93C7910CFE1D500F74F2B /* RecastDebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecastDebugDraw.h; path = ../../../DebugUtils/Include/RecastDebugDraw.h; sourceTree = SOURCE_ROOT; };
@@ -141,6 +147,8 @@
6BB788160FC0472B003C24DB /* ChunkyTriMesh.cpp */,
6B137C7C0F7FCBE400459200 /* SDLMain.h */,
6B137C6E0F7FCBBB00459200 /* SDLMain.m */,
6BB7FDA310F36EFC006DA0A6 /* InputGeom.h */,
6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */,
);
name = Classes;
sourceTree = "<group>";
@@ -237,6 +245,8 @@
children = (
6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */,
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */,
6BB7FD4810F3558D006DA0A6 /* ExtraLinkTool.h */,
6BB7FD4910F3559D006DA0A6 /* ExtraLinkTool.cpp */,
6B25B6100FFA62AD004F1BC4 /* Sample.h */,
6B25B6140FFA62BE004F1BC4 /* Sample.cpp */,
6BA1E88E10C7BFD3008007F6 /* Sample_SoloMeshSimple.h */,
@@ -363,6 +373,8 @@
6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */,
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */,
6BB7FC0B10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp in Sources */,
6BB7FD4A10F3559D006DA0A6 /* ExtraLinkTool.cpp in Sources */,
6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -0,0 +1,45 @@
//
// Copyright (c) 2009 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 EXTRALINKTOOL_H
#define EXTRALINKTOOL_H
#include "Sample.h"
// Tool to create extra links for InputGeom
class ExtraLinkTool : public SampleTool
{
Sample* m_sample;
float m_hitPos[3];
bool m_hitPosSet;
public:
ExtraLinkTool();
~ExtraLinkTool();
virtual int type() { return TOOL_EXTRA_LINK; }
virtual void init(Sample* sample);
virtual void reset();
virtual void handleMenu();
virtual void handleClick(const float* p, bool shift);
virtual void handleRender();
virtual void handleRenderOverlay(double* proj, double* model, int* view);
};
#endif // EXTRALINKTOOL_H

View File

@@ -0,0 +1,62 @@
//
// Copyright (c) 2009 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 INPUTGEOM_H
#define INPUTGEOM_H
#include "ChunkyTriMesh.h"
#include "MeshLoaderObj.h"
struct ExtraLink
{
float spos[3]; // Start position of the link.
float epos[3]; // End position of the link.
};
class InputGeom
{
rcChunkyTriMesh* m_chunkyMesh;
rcMeshLoaderObj* m_mesh;
float m_meshBMin[3], m_meshBMax[3];
static const int MAX_LINKS = 256;
ExtraLink m_links[MAX_LINKS];
int m_nlinks;
public:
InputGeom();
~InputGeom();
bool loadMesh(const char* filepath);
// Method to return static mesh data.
inline const rcMeshLoaderObj* getMesh() const { return m_mesh; }
inline const float* getMeshBoundsMin() const { return m_meshBMin; }
inline const float* getMeshBoundsMax() const { return m_meshBMax; }
inline const rcChunkyTriMesh* getChunkyMesh() const { return m_chunkyMesh; }
bool raycastMesh(float* src, float* dst, float& tmin);
// Extra links
int getExtraLinkCount() const { return m_nlinks; }
ExtraLink* getExtraLink(int i) { return &m_links[i]; }
void addExtraLink(const float* spos, const float* epos);
void deleteExtraLink(int i);
};
#endif // INPUTGEOM_H

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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 NAVMESHTESTERTOOL_H
#define NAVMESHTESTERTOOL_H

View File

@@ -1,7 +1,26 @@
//
// Copyright (c) 2009 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 RECASTSAMPLE_H
#define RECASTSAMPLE_H
#include "DebugDraw.h"
#include "DetourNavMesh.h"
struct DebugDrawGL : public duDebugDraw
{
@@ -16,6 +35,7 @@ enum SampleToolType
TOOL_NONE = 0,
TOOL_TILE_EDIT,
TOOL_NAVMESH_TESTER,
TOOL_EXTRA_LINK,
};
struct SampleTool
@@ -34,12 +54,8 @@ struct SampleTool
class Sample
{
protected:
const float* m_verts;
int m_nverts;
const int* m_tris;
const float* m_trinorms;
int m_ntris;
float m_bmin[3], m_bmax[3];
class InputGeom* m_geom;
dtNavMesh* m_navMesh;
float m_cellSize;
float m_cellHeight;
@@ -69,12 +85,11 @@ public:
virtual void handleClick(const float* p, bool shift);
virtual void handleRender();
virtual void handleRenderOverlay(double* proj, double* model, int* view);
virtual void handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax);
virtual void handleMeshChanged(class InputGeom* geom);
virtual bool handleBuild();
virtual class dtNavMesh* getNavMesh() { return 0; }
virtual class InputGeom* getInputGeom() { return m_geom; }
virtual class dtNavMesh* getNavMesh() { return m_navMesh; }
virtual float getAgentRadius() { return m_agentRadius; }
virtual float getAgentHeight() { return m_agentHeight; }

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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 RECASTSAMPLESOLOMESHSIMPLE_H
#define RECASTSAMPLESOLOMESHSIMPLE_H
@@ -9,8 +27,6 @@
class Sample_SoloMeshSimple : public Sample //Sample_SoloMesh
{
protected:
dtNavMesh* m_navMesh;
bool m_keepInterResults;
rcBuildTimes m_buildTimes;
@@ -57,12 +73,8 @@ public:
virtual void handleRender();
virtual void handleRenderOverlay(double* proj, double* model, int* view);
virtual void handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax);
virtual void handleMeshChanged(class InputGeom* geom);
virtual bool handleBuild();
virtual class dtNavMesh* getNavMesh() { return m_navMesh; }
};

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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 RECASTSAMPLESOLOMESHTILED_H
#define RECASTSAMPLESOLOMESHTILED_H
@@ -10,8 +28,6 @@
class Sample_SoloMeshTiled : public Sample
{
protected:
dtNavMesh* m_navMesh;
struct Tile
{
inline Tile() : chf(0), solid(0), cset(0), pmesh(0), dmesh(0), buildTime(0) {}
@@ -39,7 +55,6 @@ protected:
float m_tileSize;
rcBuildTimes m_buildTimes;
rcChunkyTriMesh* m_chunkyMesh;
rcPolyMesh* m_pmesh;
rcPolyMeshDetail* m_dmesh;
rcConfig m_cfg;
@@ -87,12 +102,8 @@ public:
virtual void handleRender();
virtual void handleRenderOverlay(double* proj, double* model, int* view);
virtual void handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax);
virtual void handleMeshChanged(class InputGeom* geom);
virtual bool handleBuild();
virtual class dtNavMesh* getNavMesh() { return m_navMesh; }
};

View File

@@ -24,18 +24,14 @@
#include "Recast.h"
#include "RecastLog.h"
#include "ChunkyTriMesh.h"
#include "NavMeshTesterTool.h"
class Sample_TileMesh : public Sample
{
protected:
bool m_keepInterResults;
bool m_buildAll;
rcBuildTimes m_buildTimes;
dtNavMesh* m_navMesh;
rcChunkyTriMesh* m_chunkyMesh;
unsigned char* m_triflags;
rcHeightfield* m_solid;
rcCompactHeightfield* m_chf;
@@ -68,12 +64,8 @@ public:
virtual void handleDebugMode();
virtual void handleRender();
virtual void handleRenderOverlay(double* proj, double* model, int* view);
virtual void handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax);
virtual void handleMeshChanged(class InputGeom* geom);
virtual bool handleBuild();
virtual class dtNavMesh* getNavMesh() { return m_navMesh; }
void buildTile(const float* pos);
void removeTile(const float* pos);

View File

@@ -0,0 +1,176 @@
//
// Copyright (c) 2009 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 <string.h>
#include <float.h>
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "ExtraLinkTool.h"
#include "InputGeom.h"
#include "Sample.h"
#include "Recast.h"
#include "RecastDebugDraw.h"
#include "DetourDebugDraw.h"
#ifdef WIN32
# define snprintf _snprintf
#endif
static void drawCross(const float* p, const float s, const float dy)
{
glBegin(GL_LINES);
glVertex3f(p[0]-s,p[1]+dy,p[2]);
glVertex3f(p[0]+s,p[1]+dy,p[2]);
glVertex3f(p[0],p[1]-s+dy,p[2]);
glVertex3f(p[0],p[1]+s+dy,p[2]);
glVertex3f(p[0],p[1]+dy,p[2]-s);
glVertex3f(p[0],p[1]+dy,p[2]+s);
glEnd();
}
ExtraLinkTool::ExtraLinkTool() :
m_sample(0),
m_hitPosSet(0)
{
}
ExtraLinkTool::~ExtraLinkTool()
{
}
void ExtraLinkTool::init(Sample* sample)
{
m_sample = sample;
}
void ExtraLinkTool::reset()
{
m_hitPosSet = false;
}
void ExtraLinkTool::handleMenu()
{
if (m_hitPosSet)
{
imguiValue("Click to set link start.");
}
else
{
imguiValue("Click to set link end.");
}
}
void ExtraLinkTool::handleClick(const float* p, bool shift)
{
if (!m_sample) return;
InputGeom* geom = m_sample->getInputGeom();
if (!geom) return;
if (shift)
{
// Delete
float nearestDist = FLT_MAX;
int nearestIndex = -1;
for (int i = 0; i < geom->getExtraLinkCount(); ++i)
{
ExtraLink* link = geom->getExtraLink(i);
float d;
d = vdistSqr(p, link->spos);
if (d < nearestDist)
{
nearestDist = d;
nearestIndex = i;
}
d = vdistSqr(p, link->epos);
if (d < nearestDist)
{
nearestDist = d;
nearestIndex = i;
}
}
if (nearestIndex != -1 &&
sqrtf(nearestDist) < m_sample->getAgentRadius())
{
geom->deleteExtraLink(nearestIndex);
}
}
else
{
// Create
if (!m_hitPosSet)
{
vcopy(m_hitPos, p);
m_hitPosSet = true;
}
else
{
geom->addExtraLink(m_hitPos, p);
m_hitPosSet = false;
}
}
}
void ExtraLinkTool::handleRender()
{
if (m_hitPosSet)
{
const float s = m_sample->getAgentRadius();
glColor4ub(0,0,0,128);
glLineWidth(2.0f);
drawCross(m_hitPos, s, 0.1f);
glLineWidth(1.0f);
}
const float s = m_sample->getAgentRadius();
InputGeom* geom = m_sample->getInputGeom();
if (!geom) return;
DebugDrawGL dd;
const float linkCol[4] = {1,1,1,0.75f};
for (int i = 0; i < geom->getExtraLinkCount(); ++i)
{
ExtraLink* link = geom->getExtraLink(i);
duDebugDrawArc(&dd, link->spos, link->epos, linkCol, 2.0f);
glLineWidth(2.0f);
glColor4ub(0,0,0,255);
drawCross(link->spos, s, 0.1f);
drawCross(link->epos, s, 0.1f);
glLineWidth(1.0f);
}
}
void ExtraLinkTool::handleRenderOverlay(double* proj, double* model, int* view)
{
GLdouble x, y, z;
// Draw start and end point labels
if (m_hitPosSet && gluProject((GLdouble)m_hitPos[0], (GLdouble)m_hitPos[1], (GLdouble)m_hitPos[2],
model, proj, view, &x, &y, &z))
{
imguiDrawText((int)x, (int)(y-25), IMGUI_ALIGN_CENTER, "Start", imguiRGBA(0,0,0,220));
}
}

View File

@@ -0,0 +1,173 @@
//
// Copyright (c) 2009 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 "Recast.h"
#include "RecastLog.h"
#include "InputGeom.h"
#include "ChunkyTriMesh.h"
#include "MeshLoaderObj.h"
static bool intersectSegmentTriangle(const float* sp, const float* sq,
const float* a, const float* b, const float* c,
float &t)
{
float v, w;
float ab[3], ac[3], qp[3], ap[3], norm[3], e[3];
vsub(ab, b, a);
vsub(ac, c, a);
vsub(qp, sp, sq);
// Compute triangle normal. Can be precalculated or cached if
// intersecting multiple segments against the same triangle
vcross(norm, ab, ac);
// Compute denominator d. If d <= 0, segment is parallel to or points
// away from triangle, so exit early
float d = vdot(qp, norm);
if (d <= 0.0f) return false;
// Compute intersection t value of pq with plane of triangle. A ray
// intersects iff 0 <= t. Segment intersects iff 0 <= t <= 1. Delay
// dividing by d until intersection has been found to pierce triangle
vsub(ap, sp, a);
t = vdot(ap, norm);
if (t < 0.0f) return false;
if (t > d) return false; // For segment; exclude this code line for a ray test
// Compute barycentric coordinate components and test if within bounds
vcross(e, qp, ap);
v = vdot(ac, e);
if (v < 0.0f || v > d) return false;
w = -vdot(ab, e);
if (w < 0.0f || v + w > d) return false;
// Segment/ray intersects triangle. Perform delayed division
t /= d;
return true;
}
InputGeom::InputGeom() :
m_chunkyMesh(0),
m_mesh(0),
m_nlinks(0)
{
}
InputGeom::~InputGeom()
{
delete m_chunkyMesh;
delete m_mesh;
}
bool InputGeom::loadMesh(const char* filepath)
{
if (m_mesh)
{
delete m_chunkyMesh;
m_chunkyMesh = 0;
delete m_mesh;
m_mesh = 0;
m_nlinks = 0;
}
m_mesh = new rcMeshLoaderObj;
if (!m_mesh)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "loadMesh: Out of memory 'm_mesh'.");
return false;
}
if (!m_mesh->load(filepath))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath);
return false;
}
rcCalcBounds(m_mesh->getVerts(), m_mesh->getVertCount(), m_meshBMin, m_meshBMax);
m_chunkyMesh = new rcChunkyTriMesh;
if (!m_chunkyMesh)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'm_chunkyMesh'.");
return false;
}
if (!rcCreateChunkyTriMesh(m_mesh->getVerts(), m_mesh->getTris(), m_mesh->getTriCount(), 256, m_chunkyMesh))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Failed to build chunky mesh.");
return false;
}
return true;
}
bool InputGeom::raycastMesh(float* src, float* dst, float& tmin)
{
float dir[3];
vsub(dir, dst, src);
int nt = m_mesh->getTriCount();
const float* verts = m_mesh->getVerts();
const float* normals = m_mesh->getNormals();
const int* tris = m_mesh->getTris();
tmin = 1.0f;
bool hit = false;
for (int i = 0; i < nt*3; i += 3)
{
const float* n = &normals[i];
if (vdot(dir, n) > 0)
continue;
float t = 1;
if (intersectSegmentTriangle(src, dst,
&verts[tris[i]*3],
&verts[tris[i+1]*3],
&verts[tris[i+2]*3], t))
{
if (t < tmin)
tmin = t;
hit = true;
}
}
return hit;
}
void InputGeom::addExtraLink(const float* spos, const float* epos)
{
if (m_nlinks >= MAX_LINKS) return;
ExtraLink* link = &m_links[m_nlinks++];
vcopy(link->spos, spos);
vcopy(link->epos, epos);
}
void InputGeom::deleteExtraLink(int i)
{
m_nlinks--;
m_links[i] = m_links[m_nlinks];
}

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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>

View File

@@ -1,7 +1,26 @@
//
// Copyright (c) 2009 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 "Sample.h"
#include "InputGeom.h"
#include "Recast.h"
#include "RecastDebugDraw.h"
#include "imgui.h"
@@ -55,11 +74,8 @@ void DebugDrawGL::end()
Sample::Sample() :
m_verts(0),
m_nverts(0),
m_tris(0),
m_trinorms(0),
m_ntris(0),
m_geom(0),
m_navMesh(0),
m_tool(0)
{
resetCommonSettings();
@@ -67,6 +83,7 @@ Sample::Sample() :
Sample::~Sample()
{
delete m_navMesh;
delete m_tool;
}
@@ -92,33 +109,28 @@ void Sample::handleDebugMode()
void Sample::handleRender()
{
if (!m_verts || !m_tris || !m_trinorms)
if (!m_geom)
return;
DebugDrawGL dd;
// Draw mesh
duDebugDrawTriMesh(&dd, m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
// Draw bounds
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
float col[4] = {1,1,1,0.5f};
duDebugDrawBoxWire(&dd, m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
duDebugDrawBoxWire(&dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], col);
}
void Sample::handleRenderOverlay(double* proj, double* model, int* view)
{
}
void Sample::handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax)
void Sample::handleMeshChanged(InputGeom* geom)
{
m_verts = verts;
m_nverts = nverts;
m_tris = tris;
m_trinorms = trinorms;
m_ntris = ntris;
vcopy(m_bmin, bmin);
vcopy(m_bmax, bmax);
m_geom = geom;
}
void Sample::resetCommonSettings()
@@ -144,11 +156,16 @@ void Sample::handleCommonSettings()
imguiSlider("Cell Size", &m_cellSize, 0.1f, 1.0f, 0.01f);
imguiSlider("Cell Height", &m_cellHeight, 0.1f, 1.0f, 0.01f);
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
char text[64];
snprintf(text, 64, "Voxels %d x %d", gw, gh);
imguiValue(text);
if (m_geom)
{
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
int gw = 0, gh = 0;
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
char text[64];
snprintf(text, 64, "Voxels %d x %d", gw, gh);
imguiValue(text);
}
imguiSeparator();
imguiLabel("Agent");

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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>
@@ -5,6 +23,7 @@
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "InputGeom.h"
#include "Sample.h"
#include "Sample_SoloMeshSimple.h"
#include "Recast.h"
@@ -15,6 +34,7 @@
#include "DetourNavMeshBuilder.h"
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "ExtraLinkTool.h"
#ifdef WIN32
# define snprintf _snprintf
@@ -22,7 +42,6 @@
Sample_SoloMeshSimple::Sample_SoloMeshSimple() :
m_navMesh(0),
m_keepInterResults(false),
m_triflags(0),
m_solid(0),
@@ -70,6 +89,19 @@ void Sample_SoloMeshSimple::handleSettings()
void Sample_SoloMeshSimple::handleTools()
{
int type = !m_tool ? TOOL_NONE : m_tool->type();
if (imguiCheck("Test Navmesh", type == TOOL_NAVMESH_TESTER))
{
setTool(new NavMeshTesterTool);
}
if (imguiCheck("Create Extra Links", type == TOOL_EXTRA_LINK))
{
setTool(new ExtraLinkTool);
}
imguiSeparator();
if (m_tool)
m_tool->handleMenu();
}
@@ -81,7 +113,7 @@ void Sample_SoloMeshSimple::handleDebugMode()
for (int i = 0; i < MAX_DRAWMODE; ++i)
valid[i] = false;
if (m_verts && m_tris)
if (m_geom)
{
valid[DRAWMODE_NAVMESH] = m_navMesh != 0;
valid[DRAWMODE_NAVMESH_TRANS] = m_navMesh != 0;
@@ -151,7 +183,7 @@ void Sample_SoloMeshSimple::handleDebugMode()
void Sample_SoloMeshSimple::handleRender()
{
if (!m_verts || !m_tris || !m_trinorms)
if (!m_geom || !m_geom->getMesh())
return;
float col[4];
@@ -164,20 +196,25 @@ void Sample_SoloMeshSimple::handleRender()
if (m_drawMode == DRAWMODE_MESH)
{
// Draw mesh
duDebugDrawTriMeshSlope(&dd, m_verts, m_nverts, m_tris, m_trinorms, m_ntris, m_agentMaxSlope);
duDebugDrawTriMeshSlope(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(),
m_agentMaxSlope);
}
else if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
{
// Draw mesh
duDebugDrawTriMesh(&dd, m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
}
glDisable(GL_FOG);
glDepthMask(GL_FALSE);
// Draw bounds
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
col[0] = 1; col[1] = 1; col[2] = 1; col[3] = 0.5f;
duDebugDrawBoxWire(&dd, m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
duDebugDrawBoxWire(&dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], col);
if (m_navMesh &&
(m_drawMode == DRAWMODE_NAVMESH ||
@@ -271,11 +308,9 @@ void Sample_SoloMeshSimple::handleRenderOverlay(double* proj, double* model, int
m_tool->handleRenderOverlay(proj, model, view);
}
void Sample_SoloMeshSimple::handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax)
void Sample_SoloMeshSimple::handleMeshChanged(class InputGeom* geom)
{
Sample::handleMeshChanged(verts, nverts, tris, trinorms, ntris, bmin, bmax);
Sample::handleMeshChanged(geom);
delete m_navMesh;
m_navMesh = 0;
if (m_tool)
@@ -287,7 +322,7 @@ void Sample_SoloMeshSimple::handleMeshChanged(const float* verts, int nverts,
bool Sample_SoloMeshSimple::handleBuild()
{
if (!m_verts || ! m_tris)
if (!m_geom || !m_geom->getMesh())
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
@@ -296,6 +331,13 @@ bool Sample_SoloMeshSimple::handleBuild()
cleanup();
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMin();
const float* verts = m_geom->getMesh()->getVerts();
const int nverts = m_geom->getMesh()->getVertCount();
const int* tris = m_geom->getMesh()->getTris();
const int ntris = m_geom->getMesh()->getTriCount();
//
// Step 1. Initialize build config.
//
@@ -319,8 +361,8 @@ bool Sample_SoloMeshSimple::handleBuild()
// Set the area where the navigation will be build.
// Here the bounds of the input mesh are used, but the
// area could be specified by an user defined box, etc.
vcopy(m_cfg.bmin, m_bmin);
vcopy(m_cfg.bmax, m_bmax);
vcopy(m_cfg.bmin, bmin);
vcopy(m_cfg.bmax, bmax);
rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
// Reset build times gathering.
@@ -334,7 +376,7 @@ bool Sample_SoloMeshSimple::handleBuild()
{
rcGetLog()->log(RC_LOG_PROGRESS, "Building navigation:");
rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
rcGetLog()->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", m_nverts/1000.0f, m_ntris/1000.0f);
rcGetLog()->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", nverts/1000.0f, ntris/1000.0f);
}
//
@@ -359,20 +401,20 @@ bool Sample_SoloMeshSimple::handleBuild()
// Allocate array that can hold triangle flags.
// If you have multiple meshes you need to process, allocate
// and array which can hold the max number of triangles you need to process.
m_triflags = new unsigned char[m_ntris];
m_triflags = new unsigned char[ntris];
if (!m_triflags)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'triangleFlags' (%d).", m_ntris);
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'triangleFlags' (%d).", ntris);
return false;
}
// Find triangles which are walkable based on their slope and rasterize them.
// If your input data is multiple meshes, you can transform them here, calculate
// the flags for each of the meshes and rasterize them.
memset(m_triflags, 0, m_ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(m_cfg.walkableSlopeAngle, m_verts, m_nverts, m_tris, m_ntris, m_triflags);
rcRasterizeTriangles(m_verts, m_nverts, m_tris, m_triflags, m_ntris, *m_solid);
memset(m_triflags, 0, ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triflags);
rcRasterizeTriangles(verts, nverts, tris, m_triflags, ntris, *m_solid);
if (!m_keepInterResults)
{

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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>
@@ -5,6 +23,7 @@
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "InputGeom.h"
#include "Sample.h"
#include "Sample_SoloMeshTiled.h"
#include "Recast.h"
@@ -14,17 +33,16 @@
#include "DetourNavMeshBuilder.h"
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "ExtraLinkTool.h"
#ifdef WIN32
# define snprintf _snprintf
#endif
Sample_SoloMeshTiled::Sample_SoloMeshTiled() :
m_navMesh(0),
m_measurePerTileTimings(false),
m_keepInterResults(false),
m_tileSize(64),
m_chunkyMesh(0),
m_pmesh(0),
m_dmesh(0),
m_tileSet(0),
@@ -42,8 +60,6 @@ Sample_SoloMeshTiled::~Sample_SoloMeshTiled()
void Sample_SoloMeshTiled::cleanup()
{
delete m_chunkyMesh;
m_chunkyMesh = 0;
delete m_tileSet;
m_tileSet = 0;
delete m_pmesh;
@@ -63,14 +79,19 @@ void Sample_SoloMeshTiled::handleSettings()
imguiLabel("Tiling");
imguiSlider("TileSize", &m_tileSize, 16.0f, 1024.0f, 16.0f);
char text[64];
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
const int ts = (int)m_tileSize;
const int tw = (gw + ts-1) / ts;
const int th = (gh + ts-1) / ts;
snprintf(text, 64, "Tiles %d x %d", tw, th);
imguiValue(text);
if (m_geom)
{
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
char text[64];
int gw = 0, gh = 0;
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
const int ts = (int)m_tileSize;
const int tw = (gw + ts-1) / ts;
const int th = (gh + ts-1) / ts;
snprintf(text, 64, "Tiles %d x %d", tw, th);
imguiValue(text);
}
imguiSeparator();
if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
@@ -83,6 +104,19 @@ void Sample_SoloMeshTiled::handleSettings()
void Sample_SoloMeshTiled::handleTools()
{
int type = !m_tool ? TOOL_NONE : m_tool->type();
if (imguiCheck("Test Navmesh", type == TOOL_NAVMESH_TESTER))
{
setTool(new NavMeshTesterTool);
}
if (imguiCheck("Create Extra Links", type == TOOL_EXTRA_LINK))
{
setTool(new ExtraLinkTool);
}
imguiSeparator();
if (m_tool)
m_tool->handleMenu();
}
@@ -113,7 +147,7 @@ void Sample_SoloMeshTiled::handleDebugMode()
if (m_pmesh) hasPmesh = true;
if (m_dmesh) hasDmesh = true;
if (m_verts && m_tris)
if (m_geom)
{
valid[DRAWMODE_NAVMESH] = m_navMesh != 0;
valid[DRAWMODE_NAVMESH_TRANS] = m_navMesh != 0;
@@ -183,7 +217,7 @@ void Sample_SoloMeshTiled::handleDebugMode()
void Sample_SoloMeshTiled::handleRender()
{
if (!m_verts || !m_tris || !m_trinorms)
if (!m_geom || !m_geom->getMesh())
return;
float col[4];
@@ -196,25 +230,30 @@ void Sample_SoloMeshTiled::handleRender()
if (m_drawMode == DRAWMODE_MESH)
{
// Draw mesh
duDebugDrawTriMeshSlope(&dd, m_verts, m_nverts, m_tris, m_trinorms, m_ntris, m_agentMaxSlope);
duDebugDrawTriMeshSlope(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(),
m_agentMaxSlope);
}
else if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
{
// Draw mesh
duDebugDrawTriMesh(&dd, m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
}
glDisable(GL_FOG);
glDepthMask(GL_FALSE);
// Draw bounds
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
col[0] = 1; col[1] = 1; col[2] = 1; col[3] = 0.5f;
duDebugDrawBoxWire(&dd, m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
duDebugDrawBoxWire(&dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], col);
// Tiling grid.
const int ts = (int)m_tileSize;
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
int tw = (gw + ts-1) / ts;
int th = (gh + ts-1) / ts;
const float s = ts*m_cellSize;
@@ -225,9 +264,9 @@ void Sample_SoloMeshTiled::handleRender()
for (int x = 0; x < tw; ++x)
{
float fx, fy, fz;
fx = m_bmin[0] + x*s;
fy = m_bmin[1];
fz = m_bmin[2] + y*s;
fx = bmin[0] + x*s;
fy = bmin[1];
fz = bmin[2] + y*s;
glVertex3f(fx,fy,fz);
glVertex3f(fx+s,fy,fz);
@@ -543,11 +582,9 @@ void Sample_SoloMeshTiled::handleRenderOverlay(double* proj, double* model, int*
m_tool->handleRenderOverlay(proj, model, view);
}
void Sample_SoloMeshTiled::handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax)
void Sample_SoloMeshTiled::handleMeshChanged(class InputGeom* geom)
{
Sample::handleMeshChanged(verts, nverts, tris, trinorms, ntris, bmin, bmax);
Sample::handleMeshChanged(geom);
m_statTimePerTileSamples = 0;
m_statPolysPerTileSamples = 0;
if (m_tool)
@@ -559,7 +596,7 @@ void Sample_SoloMeshTiled::handleMeshChanged(const float* verts, int nverts,
bool Sample_SoloMeshTiled::handleBuild()
{
if (!m_verts || ! m_tris)
if (!m_geom || !m_geom->getMesh() || !m_geom->getChunkyMesh())
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
@@ -576,6 +613,13 @@ bool Sample_SoloMeshTiled::handleBuild()
cleanup();
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMin();
const float* verts = m_geom->getMesh()->getVerts();
const int nverts = m_geom->getMesh()->getVertCount();
const int ntris = m_geom->getMesh()->getTriCount();
const rcChunkyTriMesh* chunkyMesh = m_geom->getChunkyMesh();
// Init build configuration from GUI
memset(&m_cfg, 0, sizeof(m_cfg));
m_cfg.cs = m_cellSize;
@@ -597,8 +641,8 @@ bool Sample_SoloMeshTiled::handleBuild()
// Set the area where the navigation will be build.
// Here the bounds of the input mesh are used, but the
// area could be specified by an user defined box, etc.
vcopy(m_cfg.bmin, m_bmin);
vcopy(m_cfg.bmax, m_bmax);
vcopy(m_cfg.bmin, bmin);
vcopy(m_cfg.bmax, bmax);
rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
// Reset build times gathering.
@@ -629,30 +673,13 @@ bool Sample_SoloMeshTiled::handleBuild()
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'tileSet->tiles' (%d).", m_tileSet->height * m_tileSet->width);
return false;
}
// Build chunky trimesh for local polygon queries.
rcTimeVal chunkyStartTime = rcGetPerformanceTimer();
m_chunkyMesh = new rcChunkyTriMesh;
if (!m_chunkyMesh)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'm_chunkyMesh'.");
return false;
}
if (!rcCreateChunkyTriMesh(m_verts, m_tris, m_ntris, 256, m_chunkyMesh))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not build chunky mesh.");
return false;
}
rcTimeVal chunkyEndTime = rcGetPerformanceTimer();
if (rcGetLog())
{
rcGetLog()->log(RC_LOG_PROGRESS, "Building navigation:");
rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d tiles", m_tileSet->width, m_tileSet->height);
rcGetLog()->log(RC_LOG_PROGRESS, " - %.1f verts, %.1f tris", m_nverts/1000.0f, m_ntris/1000.0f);
rcGetLog()->log(RC_LOG_PROGRESS, " - %.1f verts, %.1f tris", nverts/1000.0f, ntris/1000.0f);
}
// Initialize per tile config.
@@ -662,11 +689,14 @@ bool Sample_SoloMeshTiled::handleBuild()
tileCfg.height = m_cfg.tileSize + m_cfg.borderSize*2;
// Allocate array that can hold triangle flags for all geom chunks.
unsigned char* triangleFlags = new unsigned char[m_chunkyMesh->maxTrisPerChunk];
unsigned char* triangleFlags = new unsigned char[chunkyMesh->maxTrisPerChunk];
if (!triangleFlags)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'triangleFlags' (%d).", m_chunkyMesh->maxTrisPerChunk);
{
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'triangleFlags' (%d).",
chunkyMesh->maxTrisPerChunk);
}
return false;
}
@@ -699,7 +729,7 @@ bool Sample_SoloMeshTiled::handleBuild()
tbmax[0] = tileCfg.bmax[0];
tbmax[1] = tileCfg.bmax[2];
int cid[256];// TODO: Make grow when returning too many items.
const int ncid = rcGetChunksInRect(m_chunkyMesh, tbmin, tbmax, cid, 256);
const int ncid = rcGetChunksInRect(chunkyMesh, tbmin, tbmax, cid, 256);
if (!ncid)
continue;
@@ -719,15 +749,15 @@ bool Sample_SoloMeshTiled::handleBuild()
for (int i = 0; i < ncid; ++i)
{
const rcChunkyTriMeshNode& node = m_chunkyMesh->nodes[cid[i]];
const int* tris = &m_chunkyMesh->tris[node.i*3];
const rcChunkyTriMeshNode& node = chunkyMesh->nodes[cid[i]];
const int* tris = &chunkyMesh->tris[node.i*3];
const int ntris = node.n;
memset(triangleFlags, 0, ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(tileCfg.walkableSlopeAngle,
m_verts, m_nverts, tris, ntris, triangleFlags);
verts, nverts, tris, ntris, triangleFlags);
rcRasterizeTriangles(m_verts, m_nverts, tris, triangleFlags, ntris, *solid);
rcRasterizeTriangles(verts, nverts, tris, triangleFlags, ntris, *solid);
}
rcFilterLedgeSpans(tileCfg.walkableHeight, tileCfg.walkableClimb, *solid);
@@ -756,7 +786,8 @@ bool Sample_SoloMeshTiled::handleBuild()
continue;
}
if (!rcBuildRegions(*chf, tileCfg.walkableRadius, tileCfg.borderSize, tileCfg.minRegionSize, tileCfg.mergeRegionSize))
if (!rcBuildRegions(*chf, tileCfg.walkableRadius, tileCfg.borderSize,
tileCfg.minRegionSize, tileCfg.mergeRegionSize))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: [%d,%d] Could not build regions.", x, y);
@@ -958,8 +989,6 @@ bool Sample_SoloMeshTiled::handleBuild()
{
const float pc = 100.0f / rcGetDeltaTimeUsec(totStartTime, totEndTime);
rcGetLog()->log(RC_LOG_PROGRESS, "Chunky Mesh: %.1fms (%.1f%%)", rcGetDeltaTimeUsec(chunkyStartTime, chunkyEndTime)/1000.0f, rcGetDeltaTimeUsec(chunkyStartTime, chunkyEndTime)*pc);
rcGetLog()->log(RC_LOG_PROGRESS, "Rasterize: %.1fms (%.1f%%)", m_buildTimes.rasterizeTriangles/1000.0f, m_buildTimes.rasterizeTriangles*pc);
rcGetLog()->log(RC_LOG_PROGRESS, "Build Compact: %.1fms (%.1f%%)", m_buildTimes.buildCompact/1000.0f, m_buildTimes.buildCompact*pc);

View File

@@ -23,6 +23,7 @@
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "InputGeom.h"
#include "Sample.h"
#include "Sample_TileMesh.h"
#include "Recast.h"
@@ -31,6 +32,8 @@
#include "DetourNavMesh.h"
#include "DetourNavMeshBuilder.h"
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "ExtraLinkTool.h"
#ifdef WIN32
# define snprintf _snprintf
@@ -150,8 +153,6 @@ public:
Sample_TileMesh::Sample_TileMesh() :
m_keepInterResults(false),
m_buildAll(true),
m_navMesh(0),
m_chunkyMesh(0),
m_triflags(0),
m_solid(0),
m_chf(0),
@@ -175,8 +176,6 @@ Sample_TileMesh::Sample_TileMesh() :
Sample_TileMesh::~Sample_TileMesh()
{
cleanup();
delete m_navMesh;
delete m_chunkyMesh;
}
void Sample_TileMesh::cleanup()
@@ -193,6 +192,8 @@ void Sample_TileMesh::cleanup()
m_pmesh = 0;
delete m_dmesh;
m_dmesh = 0;
delete m_navMesh;
m_navMesh = 0;
}
void Sample_TileMesh::handleSettings()
@@ -208,39 +209,53 @@ void Sample_TileMesh::handleSettings()
imguiLabel("Tiling");
imguiSlider("TileSize", &m_tileSize, 16.0f, 1024.0f, 16.0f);
char text[64];
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
const int ts = (int)m_tileSize;
const int tw = (gw + ts-1) / ts;
const int th = (gh + ts-1) / ts;
snprintf(text, 64, "Tiles %d x %d", tw, th);
imguiValue(text);
if (m_geom)
{
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
char text[64];
int gw = 0, gh = 0;
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
const int ts = (int)m_tileSize;
const int tw = (gw + ts-1) / ts;
const int th = (gh + ts-1) / ts;
snprintf(text, 64, "Tiles %d x %d", tw, th);
imguiValue(text);
// Max tiles and max polys affect how the tile IDs are caculated.
// There are 22 bits available for identifying a tile and a polygon.
int tileBits = rcMin((int)ilog2(nextPow2(tw*th)), 14);
if (tileBits > 14) tileBits = 14;
int polyBits = 22 - tileBits;
m_maxTiles = 1 << tileBits;
m_maxPolysPerTile = 1 << polyBits;
snprintf(text, 64, "Max Tiles %d", m_maxTiles);
imguiValue(text);
snprintf(text, 64, "Max Polys %d", m_maxPolysPerTile);
imguiValue(text);
// Max tiles and max polys affect how the tile IDs are caculated.
// There are 22 bits available for identifying a tile and a polygon.
int tileBits = rcMin((int)ilog2(nextPow2(tw*th)), 14);
if (tileBits > 14) tileBits = 14;
int polyBits = 22 - tileBits;
m_maxTiles = 1 << tileBits;
m_maxPolysPerTile = 1 << polyBits;
snprintf(text, 64, "Max Tiles %d", m_maxTiles);
imguiValue(text);
snprintf(text, 64, "Max Polys %d", m_maxPolysPerTile);
imguiValue(text);
}
else
{
m_maxTiles = 0;
m_maxPolysPerTile = 0;
}
}
void Sample_TileMesh::handleTools()
{
int type = !m_tool ? TOOL_NONE : m_tool->type();
if (imguiCheck("Test Navmesh", type == TOOL_NAVMESH_TESTER))
{
setTool(new NavMeshTesterTool);
}
if (imguiCheck("Create Tiles", type == TOOL_TILE_EDIT))
{
setTool(new NavMeshTileTool);
}
if (imguiCheck("Test Navmesh", type == TOOL_NAVMESH_TESTER))
if (imguiCheck("Create Extra Links", type == TOOL_EXTRA_LINK))
{
setTool(new NavMeshTesterTool);
setTool(new ExtraLinkTool);
}
imguiSeparator();
@@ -288,24 +303,27 @@ static void getPolyCenter(dtNavMesh* navMesh, dtPolyRef ref, float* center)
void Sample_TileMesh::handleRender()
{
if (!m_verts || !m_tris || !m_trinorms)
if (!m_geom || !m_geom->getMesh())
return;
DebugDrawGL dd;
// Draw mesh
duDebugDrawTriMesh(&dd, m_verts, m_nverts, m_tris, m_trinorms, m_ntris, 0);
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
glDepthMask(GL_FALSE);
// Draw bounds
float col[4] = {1,1,1,0.5f};
duDebugDrawBoxWire(&dd, m_bmin[0],m_bmin[1],m_bmin[2], m_bmax[0],m_bmax[1],m_bmax[2], col);
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
const float col[4] = {1,1,1,0.5f};
duDebugDrawBoxWire(&dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], col);
// Tiling grid.
const int ts = (int)m_tileSize;
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
int tw = (gw + ts-1) / ts;
int th = (gh + ts-1) / ts;
const float s = ts*m_cellSize;
@@ -316,9 +334,9 @@ void Sample_TileMesh::handleRender()
for (int x = 0; x < tw; ++x)
{
float fx, fy, fz;
fx = m_bmin[0] + x*s;
fy = m_bmin[1];
fz = m_bmin[2] + y*s;
fx = bmin[0] + x*s;
fy = bmin[1];
fz = bmin[2] + y*s;
glVertex3f(fx,fy,fz);
glVertex3f(fx+s,fy,fz);
@@ -368,22 +386,10 @@ void Sample_TileMesh::handleRenderOverlay(double* proj, double* model, int* view
m_tool->handleRenderOverlay(proj, model, view);
}
void Sample_TileMesh::handleMeshChanged(const float* verts, int nverts,
const int* tris, const float* trinorms, int ntris,
const float* bmin, const float* bmax)
void Sample_TileMesh::handleMeshChanged(class InputGeom* geom)
{
m_verts = verts;
m_nverts = nverts;
m_tris = tris;
m_trinorms = trinorms;
m_ntris = ntris;
vcopy(m_bmin, bmin);
vcopy(m_bmax, bmax);
delete m_chunkyMesh;
m_chunkyMesh = 0;
delete m_navMesh;
m_navMesh = 0;
Sample::handleMeshChanged(geom);
cleanup();
if (m_tool)
@@ -395,7 +401,7 @@ void Sample_TileMesh::handleMeshChanged(const float* verts, int nverts,
bool Sample_TileMesh::handleBuild()
{
if (!m_verts || !m_tris)
if (!m_geom || !m_geom->getMesh())
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: No vertices and triangles.");
@@ -410,29 +416,18 @@ bool Sample_TileMesh::handleBuild()
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not allocate navmesh.");
return false;
}
if (!m_navMesh->init(m_bmin, m_tileSize*m_cellSize, m_tileSize*m_cellSize, m_agentMaxClimb*m_cellHeight, m_maxTiles, m_maxPolysPerTile, 2048))
const float* bmin = m_geom->getMeshBoundsMin();
const float tileWorldWidth = m_tileSize*m_cellSize;
const float tileWorldHeight = m_tileSize*m_cellSize;
const float portalHeight = m_agentMaxClimb*m_cellHeight;
if (!m_navMesh->init(bmin, tileWorldWidth, tileWorldHeight, portalHeight, m_maxTiles, m_maxPolysPerTile, 2048))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init navmesh.");
return false;
}
// Build chunky mesh.
delete m_chunkyMesh;
m_chunkyMesh = new rcChunkyTriMesh;
if (!m_chunkyMesh)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Out of memory 'm_chunkyMesh'.");
return false;
}
if (!rcCreateChunkyTriMesh(m_verts, m_tris, m_ntris, 256, m_chunkyMesh))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not build chunky mesh.");
return false;
}
if (m_buildAll)
buildAllTiles();
@@ -447,19 +442,22 @@ void Sample_TileMesh::buildTile(const float* pos)
if (!m_navMesh)
return;
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
const float ts = m_tileSize*m_cellSize;
const int tx = (int)floorf((pos[0]-m_bmin[0]) / ts);
const int ty = (int)floorf((pos[2]-m_bmin[2]) / ts);
const int tx = (int)floorf((pos[0] - bmin[0]) / ts);
const int ty = (int)floorf((pos[2] - bmin[2]) / ts);
if (tx < 0 || ty < 0)
return;
m_tileBmin[0] = m_bmin[0] + tx*ts;
m_tileBmin[1] = m_bmin[1];
m_tileBmin[2] = m_bmin[2] + ty*ts;
m_tileBmin[0] = bmin[0] + tx*ts;
m_tileBmin[1] = bmin[1];
m_tileBmin[2] = bmin[2] + ty*ts;
m_tileBmax[0] = m_bmin[0] + (tx+1)*ts;
m_tileBmax[1] = m_bmax[1];
m_tileBmax[2] = m_bmin[2] + (ty+1)*ts;
m_tileBmax[0] = bmin[0] + (tx+1)*ts;
m_tileBmax[1] = bmax[1];
m_tileBmax[2] = bmin[2] + (ty+1)*ts;
m_tileCol[0] = 0.3f; m_tileCol[1] = 0.8f; m_tileCol[2] = 0; m_tileCol[3] = 1;
@@ -482,17 +480,22 @@ void Sample_TileMesh::removeTile(const float* pos)
if (!m_navMesh)
return;
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
const float ts = m_tileSize*m_cellSize;
const int tx = (int)floorf((pos[0]-m_bmin[0]) / ts);
const int ty = (int)floorf((pos[2]-m_bmin[2]) / ts);
const int tx = (int)floorf((pos[0] - bmin[0]) / ts);
const int ty = (int)floorf((pos[2] - bmin[2]) / ts);
if (tx < 0 || ty < 0)
return;
m_tileBmin[0] = m_bmin[0] + tx*ts;
m_tileBmin[1] = m_bmin[1];
m_tileBmin[2] = m_bmin[2] + ty*ts;
m_tileBmin[0] = bmin[0] + tx*ts;
m_tileBmin[1] = bmin[1];
m_tileBmin[2] = bmin[2] + ty*ts;
m_tileBmax[0] = m_bmin[0] + (tx+1)*ts;
m_tileBmax[1] = m_bmax[1];
m_tileBmax[2] = m_bmin[2] + (ty+1)*ts;
m_tileBmax[0] = bmin[0] + (tx+1)*ts;
m_tileBmax[1] = bmax[1];
m_tileBmax[2] = bmin[2] + (ty+1)*ts;
m_tileCol[0] = 0.8f; m_tileCol[1] = 0.1f; m_tileCol[2] = 0; m_tileCol[3] = 1;
@@ -504,8 +507,10 @@ void Sample_TileMesh::removeTile(const float* pos)
void Sample_TileMesh::buildAllTiles()
{
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
const int ts = (int)m_tileSize;
const int tw = (gw + ts-1) / ts;
const int th = (gh + ts-1) / ts;
@@ -515,13 +520,13 @@ void Sample_TileMesh::buildAllTiles()
{
for (int x = 0; x < tw; ++x)
{
m_tileBmin[0] = m_bmin[0] + x*tcs;
m_tileBmin[1] = m_bmin[1];
m_tileBmin[2] = m_bmin[2] + y*tcs;
m_tileBmin[0] = bmin[0] + x*tcs;
m_tileBmin[1] = bmin[1];
m_tileBmin[2] = bmin[2] + y*tcs;
m_tileBmax[0] = m_bmin[0] + (x+1)*tcs;
m_tileBmax[1] = m_bmax[1];
m_tileBmax[2] = m_bmin[2] + (y+1)*tcs;
m_tileBmax[0] = bmin[0] + (x+1)*tcs;
m_tileBmax[1] = bmax[1];
m_tileBmax[2] = bmin[2] + (y+1)*tcs;
int dataSize = 0;
unsigned char* data = buildTileMesh(m_tileBmin, m_tileBmax, dataSize);
@@ -539,8 +544,10 @@ void Sample_TileMesh::buildAllTiles()
void Sample_TileMesh::removeAllTiles()
{
const float* bmin = m_geom->getMeshBoundsMin();
const float* bmax = m_geom->getMeshBoundsMax();
int gw = 0, gh = 0;
rcCalcGridSize(m_bmin, m_bmax, m_cellSize, &gw, &gh);
rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
const int ts = (int)m_tileSize;
const int tw = (gw + ts-1) / ts;
const int th = (gh + ts-1) / ts;
@@ -552,7 +559,7 @@ void Sample_TileMesh::removeAllTiles()
unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bmax, int& dataSize)
{
if (!m_verts || ! m_tris)
if (!m_geom || !m_geom->getMesh() || !m_geom->getChunkyMesh())
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
@@ -561,6 +568,11 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
cleanup();
const float* verts = m_geom->getMesh()->getVerts();
const int nverts = m_geom->getMesh()->getVertCount();
const int ntris = m_geom->getMesh()->getTriCount();
const rcChunkyTriMesh* chunkyMesh = m_geom->getChunkyMesh();
// Init build configuration from GUI
memset(&m_cfg, 0, sizeof(m_cfg));
m_cfg.cs = m_cellSize;
@@ -599,7 +611,7 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
{
rcGetLog()->log(RC_LOG_PROGRESS, "Building navigation:");
rcGetLog()->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
rcGetLog()->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", m_nverts/1000.0f, m_ntris/1000.0f);
rcGetLog()->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", nverts/1000.0f, ntris/1000.0f);
}
// Allocate voxel heighfield where we rasterize our input data to.
@@ -620,11 +632,11 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
// Allocate array that can hold triangle flags.
// If you have multiple meshes you need to process, allocate
// and array which can hold the max number of triangles you need to process.
m_triflags = new unsigned char[m_chunkyMesh->maxTrisPerChunk];
m_triflags = new unsigned char[chunkyMesh->maxTrisPerChunk];
if (!m_triflags)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'triangleFlags' (%d).", m_chunkyMesh->maxTrisPerChunk);
rcGetLog()->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'triangleFlags' (%d).", chunkyMesh->maxTrisPerChunk);
return 0;
}
@@ -635,7 +647,7 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
tbmax[0] = m_cfg.bmax[0];
tbmax[1] = m_cfg.bmax[2];
int cid[256];// TODO: Make grow when returning too many items.
const int ncid = rcGetChunksInRect(m_chunkyMesh, tbmin, tbmax, cid, 256);
const int ncid = rcGetChunksInRect(chunkyMesh, tbmin, tbmax, cid, 256);
if (!ncid)
return 0;
@@ -643,17 +655,17 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
for (int i = 0; i < ncid; ++i)
{
const rcChunkyTriMeshNode& node = m_chunkyMesh->nodes[cid[i]];
const int* tris = &m_chunkyMesh->tris[node.i*3];
const rcChunkyTriMeshNode& node = chunkyMesh->nodes[cid[i]];
const int* tris = &chunkyMesh->tris[node.i*3];
const int ntris = node.n;
m_tileTriCount += ntris;
memset(m_triflags, 0, ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(m_cfg.walkableSlopeAngle,
m_verts, m_nverts, tris, ntris, m_triflags);
verts, nverts, tris, ntris, m_triflags);
rcRasterizeTriangles(m_verts, m_nverts, tris, m_triflags, ntris, *m_solid);
rcRasterizeTriangles(verts, nverts, tris, m_triflags, ntris, *m_solid);
}
if (!m_keepInterResults)

View File

@@ -1,3 +1,21 @@
//
// Copyright (c) 2009 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.
//
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
@@ -13,7 +31,7 @@
#include "imguiRenderGL.h"
#include "Recast.h"
#include "RecastDebugDraw.h"
#include "MeshLoaderObj.h"
#include "InputGeom.h"
#include "Sample_SoloMeshSimple.h"
#include "Sample_SoloMeshTiled.h"
@@ -24,16 +42,6 @@
#endif
/*GLFont g_font;
void drawText(int x, int y, int dir, const char* text, unsigned int col)
{
if (dir < 0)
g_font.drawText((float)x - g_font.getTextLength(text), (float)y, text, col);
else
g_font.drawText((float)x, (float)y, text, col);
}*/
struct FileList
{
static const int MAX_FILES = 256;
@@ -114,80 +122,6 @@ static void scanDirectory(const char* path, const char* ext, FileList& list)
list.sort();
}
bool intersectSegmentTriangle(const float* sp, const float* sq,
const float* a, const float* b, const float* c,
float &t)
{
float v, w;
float ab[3], ac[3], qp[3], ap[3], norm[3], e[3];
vsub(ab, b, a);
vsub(ac, c, a);
vsub(qp, sp, sq);
// Compute triangle normal. Can be precalculated or cached if
// intersecting multiple segments against the same triangle
vcross(norm, ab, ac);
// Compute denominator d. If d <= 0, segment is parallel to or points
// away from triangle, so exit early
float d = vdot(qp, norm);
if (d <= 0.0f) return false;
// Compute intersection t value of pq with plane of triangle. A ray
// intersects iff 0 <= t. Segment intersects iff 0 <= t <= 1. Delay
// dividing by d until intersection has been found to pierce triangle
vsub(ap, sp, a);
t = vdot(ap, norm);
if (t < 0.0f) return false;
if (t > d) return false; // For segment; exclude this code line for a ray test
// Compute barycentric coordinate components and test if within bounds
vcross(e, qp, ap);
v = vdot(ac, e);
if (v < 0.0f || v > d) return false;
w = -vdot(ab, e);
if (w < 0.0f || v + w > d) return false;
// Segment/ray intersects triangle. Perform delayed division
t /= d;
return true;
}
static bool raycast(rcMeshLoaderObj& mesh, float* src, float* dst, float& tmin)
{
float dir[3];
vsub(dir, dst, src);
int nt = mesh.getTriCount();
const float* verts = mesh.getVerts();
const float* normals = mesh.getNormals();
const int* tris = mesh.getTris();
tmin = 1.0f;
bool hit = false;
for (int i = 0; i < nt*3; i += 3)
{
const float* n = &normals[i];
if (vdot(dir, n) > 0)
continue;
float t = 1;
if (intersectSegmentTriangle(src, dst,
&verts[tris[i]*3],
&verts[tris[i+1]*3],
&verts[tris[i+2]*3], t))
{
if (t < tmin)
tmin = t;
hit = true;
}
}
return hit;
}
struct SampleItem
{
Sample* (*create)();
@@ -272,13 +206,11 @@ int main(int argc, char *argv[])
FileList meshFiles;
char meshName[128] = "Choose Mesh...";
rcMeshLoaderObj* mesh = 0;
float meshBMin[3], meshBMax[3];
InputGeom* geom = 0;
float mpos[3];
bool mposSet = false;
Sample* sample = 0;
rcLog log;
@@ -331,11 +263,11 @@ int main(int argc, char *argv[])
else if (event.button.button == SDL_BUTTON_LEFT)
{
// Hit test mesh.
if (mesh && sample)
if (geom && sample)
{
// Hit test mesh.
float t;
if (raycast(*mesh, rays, raye, t))
if (geom->raycastMesh(rays, raye, t))
{
if (SDL_GetModState() & KMOD_CTRL)
{
@@ -544,16 +476,18 @@ int main(int argc, char *argv[])
scanDirectory("Meshes", ".obj", meshFiles);
}
}
if (mesh)
if (geom)
{
char text[64];
snprintf(text, 64, "Verts: %.1fk Tris: %.1fk", mesh->getVertCount()/1000.0f, mesh->getTriCount()/1000.0f);
snprintf(text, 64, "Verts: %.1fk Tris: %.1fk",
geom->getMesh()->getVertCount()/1000.0f,
geom->getMesh()->getTriCount()/1000.0f);
imguiValue(text);
}
imguiSeparator();
}
if (mesh && sample)
if (geom && sample)
{
sample->handleSettings();
@@ -610,11 +544,9 @@ int main(int argc, char *argv[])
{
delete sample;
sample = newSample;
if (mesh && sample)
if (geom && sample)
{
sample->handleMeshChanged(mesh->getVerts(), mesh->getVertCount(),
mesh->getTris(), mesh->getNormals(), mesh->getTriCount(),
meshBMin, meshBMax);
sample->handleMeshChanged(geom);
}
showSample = false;
}
@@ -642,42 +574,47 @@ int main(int argc, char *argv[])
meshName[sizeof(meshName)-1] = '\0';
showLevels = false;
delete mesh;
mesh = 0;
delete geom;
geom = 0;
char path[256];
strcpy(path, "Meshes/");
strcat(path, meshName);
mesh = new rcMeshLoaderObj;
if (!mesh || !mesh->load(path))
geom = new InputGeom;
if (!geom || !geom->loadMesh(path))
{
delete mesh;
mesh = 0;
delete geom;
geom = 0;
showLog = true;
logScroll = 0;
printf("Build log %s:\n", meshName);
for (int i = 0; i < log.getMessageCount(); ++i)
printf("%s\n", log.getMessageText(i));
}
if (mesh)
rcCalcBounds(mesh->getVerts(), mesh->getVertCount(), meshBMin, meshBMax);
if (sample)
if (sample && geom)
{
sample->handleMeshChanged(mesh->getVerts(), mesh->getVertCount(),
mesh->getTris(), mesh->getNormals(), mesh->getTriCount(),
meshBMin, meshBMax);
sample->handleMeshChanged(geom);
}
if (geom)
{
const float* bmin = geom->getMeshBoundsMin();
const float* bmax = geom->getMeshBoundsMax();
// Reset camera and fog to match the mesh bounds.
camr = sqrtf(rcSqr(bmax[0]-bmin[0]) +
rcSqr(bmax[1]-bmin[1]) +
rcSqr(bmax[2]-bmin[2])) / 2;
camx = (bmax[0] + bmin[0]) / 2 + camr;
camy = (bmax[1] + bmin[1]) / 2 + camr;
camz = (bmax[2] + bmin[2]) / 2 + camr;
camr *= 3;
rx = 45;
ry = -45;
glFogf(GL_FOG_START, camr*0.2f);
glFogf(GL_FOG_END, camr*1.25f);
}
// Reset camera and fog to match the mesh bounds.
camr = sqrtf(rcSqr(meshBMax[0]-meshBMin[0]) +
rcSqr(meshBMax[1]-meshBMin[1]) +
rcSqr(meshBMax[2]-meshBMin[2])) / 2;
camx = (meshBMax[0] + meshBMin[0]) / 2 + camr;
camy = (meshBMax[1] + meshBMin[1]) / 2 + camr;
camz = (meshBMax[2] + meshBMin[2]) / 2 + camr;
camr *= 3;
rx = 45;
ry = -45;
glFogf(GL_FOG_START, camr*0.2f);
glFogf(GL_FOG_END, camr*1.25f);
}
imguiEndScrollArea();
@@ -695,7 +632,7 @@ int main(int argc, char *argv[])
}
// Tools
if (showTools && showMenu && mesh && sample)
if (showTools && showMenu && geom && sample)
{
if (imguiBeginScrollArea("Tools", 10, height - 10 - 250, 200, 250, &toolsScroll))
mouseOverMenu = true;
@@ -737,7 +674,7 @@ int main(int argc, char *argv[])
SDL_Quit();
delete sample;
delete mesh;
delete geom;
return 0;
}