PuzzleSDK
NavMeshTest.cpp
浏览该文件的文档.
1/****************************************************************************
2 Copyright (c) 2012 cocos2d-x.org
3 Copyright (c) 2015-2016 Chukong Technologies Inc.
4 Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
5
6 http://www.cocos2d-x.org
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 ****************************************************************************/
26
27#include "NavMeshTest.h"
28#include "physics3d/CCPhysics3DWorld.h"
29#include "physics3d/CCPhysics3D.h"
30#include "3d/CCBundle3D.h"
31#include "2d/CCLight.h"
32
35
37{
38 float time;
39};
40
41NavMeshTests::NavMeshTests()
42{
43#if ( CC_USE_NAVMESH == 0 ) || ( CC_USE_PHYSICS == 0 )
45#else
46 ADD_TEST_CASE(NavMeshBasicTestDemo);
47 ADD_TEST_CASE(NavMeshAdvanceTestDemo);
48#endif
49};
50
51#if ( CC_USE_NAVMESH == 0 ) || ( CC_USE_PHYSICS == 0 )
53{
54 TTFConfig ttfConfig("fonts/arial.ttf", 16);
55 auto label = Label::createWithTTF(ttfConfig, "Should define CC_USE_NAVMESH & CC_USE_PHYSICS\n to run this test case");
56
57 auto size = Director::getInstance()->getWinSize();
58 label->setPosition(Vec2(size.width / 2, size.height / 2));
59
60 addChild(label);
61
63}
64#else
65
66NavMeshBaseTestDemo::NavMeshBaseTestDemo()
67 : _camera(nullptr)
68 , _needMoveAgents(false)
69{
70
71}
72
73NavMeshBaseTestDemo::~NavMeshBaseTestDemo()
74{
75 for (auto iter : _agents){
76 AgentUserData *data = static_cast<AgentUserData *>(iter.first->getUserData());
77 delete data;
78 }
79}
80
81bool NavMeshBaseTestDemo::init()
82{
83 if (!TestCase::init()) return false;
84
85 if (initWithPhysics()){
86
87 _angle = 0.0f;
88
89 Size size = Director::getInstance()->getWinSize();
90 _camera = Camera::createPerspective(30.0f, size.width / size.height, 1.0f, 1000.0f);
91 _camera->setPosition3D(Vec3(0.0f, 50.0f, 100.0f));
92 _camera->lookAt(Vec3(0.0f, 0.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
93 _camera->setCameraFlag(CameraFlag::USER1);
94 this->addChild(_camera);
95
96 auto listener = EventListenerTouchAllAtOnce::create();
97 listener->onTouchesBegan = CC_CALLBACK_2(NavMeshBaseTestDemo::onTouchesBegan, this);
98 listener->onTouchesMoved = CC_CALLBACK_2(NavMeshBaseTestDemo::onTouchesMoved, this);
99 listener->onTouchesEnded = CC_CALLBACK_2(NavMeshBaseTestDemo::onTouchesEnded, this);
100 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
101
102 initScene();
103 scheduleUpdate();
104 }
105
106
107 return true;
108}
109
110void NavMeshBaseTestDemo::onTouchesBegan(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
111{
112 _needMoveAgents = true;
113 touchesBegan(touches, event);
114}
115
116void NavMeshBaseTestDemo::onTouchesMoved(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
117{
118 if (touches.size() && _camera)
119 {
120 auto touch = touches[0];
121 auto delta = touch->getDelta();
122
123 _angle -= CC_DEGREES_TO_RADIANS(delta.x);
124 _camera->setPosition3D(Vec3(100.0f * sinf(_angle), 50.0f, 100.0f * cosf(_angle)));
125 _camera->lookAt(Vec3(0.0f, 0.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
126
127 if (delta.lengthSquared() > 16)
128 {
129 _needMoveAgents = false;
130 }
131 }
132 touchesMoved(touches, event);
133}
134
135void NavMeshBaseTestDemo::onTouchesEnded(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
136{
137 touchesEnded(touches, event);
138}
139
140void NavMeshBaseTestDemo::initScene()
141{
142 getPhysics3DWorld()->setDebugDrawEnable(false);
143 //create mesh
144 std::vector<Vec3> trianglesList = Bundle3D::getTrianglesList("NavMesh/scene.obj");
145
146 Physics3DRigidBodyDes rbDes;
147 rbDes.mass = 0.0f;
148 rbDes.shape = Physics3DShape::createMesh(&trianglesList[0], (int)trianglesList.size() / 3);
149 auto rigidBody = Physics3DRigidBody::create(&rbDes);
150 auto component = Physics3DComponent::create(rigidBody);
151 auto sprite = Sprite3D::create("NavMesh/scene.obj");
152 sprite->addComponent(component);
153 sprite->setCameraMask((unsigned short)CameraFlag::USER1);
154 this->addChild(sprite);
155 setPhysics3DDebugCamera(_camera);
156
157 auto navMesh = NavMesh::create("NavMesh/all_tiles_tilecache.bin", "NavMesh/geomset.txt");
158 navMesh->setDebugDrawEnable(true);
159 setNavMesh(navMesh);
160 setNavMeshDebugCamera(_camera);
161
162
163 auto ambientLight = AmbientLight::create(Color3B(64, 64, 64));
164 ambientLight->setCameraMask((unsigned short)CameraFlag::USER1);
165 this->addChild(ambientLight);
166
167 auto dirLight = DirectionLight::create(Vec3(1.2f, -1.1f, 0.5f), Color3B(255, 255, 255));
168 dirLight->setCameraMask((unsigned short)CameraFlag::USER1);
169 this->addChild(dirLight);
170}
171
172void NavMeshBaseTestDemo::createAgent(const Vec3 &pos)
173{
174 std::string filePath = "Sprite3DTest/girl.c3b";
175 NavMeshAgentParam param;
176 param.radius = 2.0f;
177 param.height = 8.0f;
178 param.maxSpeed = 8.0f;
179 auto agent = NavMeshAgent::create(param);
180 auto agentNode = Sprite3D::create(filePath);
181 agent->setOrientationRefAxes(Vec3(-1.0f, 0.0f, 1.0f));
182 AgentUserData *data = new AgentUserData{ 0.0f };
183 agent->setUserData(data);
184 agentNode->setScale(0.05f);
185 agentNode->addComponent(agent);
186
187 auto node = Node::create();
188 node->addChild(agentNode);
189 node->setPosition3D(pos);
190 node->setCameraMask((unsigned short)CameraFlag::USER1);
191 this->addChild(node);
192
193
194 auto animation = Animation3D::create(filePath);
195 auto animate = Animate3D::create(animation);
196 if (animate){
197 agentNode->runAction(RepeatForever::create(animate));
198 animate->setSpeed(0);
199 }
200
201 _agents.push_back(std::make_pair(agent, animate));
202}
203
204void NavMeshBaseTestDemo::createObstacle(const Vec3 &pos)
205{
206 auto obstacle = NavMeshObstacle::create(2.0f, 8.0f);
207 auto obstacleNode = Sprite3D::create("Sprite3DTest/cylinder.c3b");
208 obstacleNode->setPosition3D(pos + Vec3(0.0f, -0.5f, 0.0f));
209 obstacleNode->setRotation3D(Vec3(-90.0f, 0.0f, 0.0f));
210 obstacleNode->setScale(0.3f);
211 obstacleNode->addComponent(obstacle);
212 obstacleNode->setCameraMask((unsigned short)CameraFlag::USER1);
213 this->addChild(obstacleNode);
214}
215
216Vec3 jump(const Vec3* pV1, const Vec3* pV2, float height, float t)
217{
218 Vec3 pOut;
219 pOut.x = pV1->x + t * (pV2->x - pV1->x);
220 pOut.y = pV1->y + t * (pV2->y - pV1->y);
221 pOut.z = pV1->z + t * (pV2->z - pV1->z);
222 pOut.y += height * sinf((float)M_PI * t);
223 return pOut;
224}
225
226void NavMeshBaseTestDemo::moveAgents(const cocos2d::Vec3 &des)
227{
228 for (auto iter : _agents){
229 NavMeshAgent::MoveCallback callback = [](NavMeshAgent *agent, float totalTimeAfterMove){
230 AgentUserData *data = static_cast<AgentUserData *>(agent->getUserData());
231 if (agent->isOnOffMeshLink()){
232 agent->setAutoTraverseOffMeshLink(false);
233 agent->setAutoOrientation(false);
234 OffMeshLinkData linkdata = agent->getCurrentOffMeshLinkData();
235
236 agent->getOwner()->setPosition3D(jump(&linkdata.startPosition, &linkdata.endPosition, 10.0f, data->time));
237 Vec3 dir = linkdata.endPosition - linkdata.startPosition;
238 dir.y = 0.0f;
239 dir.normalize();
240 Vec3 axes;
241 Vec3 refAxes = Vec3(-1.0f, 0.0f, 1.0f);
242 refAxes.normalize();
243 Vec3::cross(refAxes, dir, &axes);
244 float angle = Vec3::dot(refAxes, dir);
245 agent->getOwner()->setRotationQuat(Quaternion(axes, acosf(angle)));
246 data->time += 0.01f;
247 if (1.0f < data->time){
248 agent->completeOffMeshLink();
249 agent->setAutoOrientation(true);
250 data->time = 0.0f;
251 }
252 }
253 };
254 iter.first->move(des, callback);
255 }
256}
257
258void NavMeshBaseTestDemo::update(float delta)
259{
260 for (auto iter : _agents){
261 float speed = iter.first->getCurrentVelocity().length() * 0.2f;
262 iter.second->setSpeed(0.0f < speed ? speed : 0.0f);
263 }
264}
265
266NavMeshBasicTestDemo::NavMeshBasicTestDemo()
267{
268
269}
270
271NavMeshBasicTestDemo::~NavMeshBasicTestDemo()
272{
273}
274
275std::string NavMeshBasicTestDemo::title() const
276{
277 return "Navigation Mesh Test";
278}
279
280std::string NavMeshBasicTestDemo::subtitle() const
281{
282 return "Basic Test";
283}
284
285void NavMeshBasicTestDemo::touchesEnded(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
286{
287 if (!_needMoveAgents) return;
288 if (!touches.empty()){
289 auto touch = touches[0];
290 auto location = touch->getLocationInView();
291 Vec3 nearP(location.x, location.y, 0.0f), farP(location.x, location.y, 1.0f);
292
293 auto size = Director::getInstance()->getWinSize();
294 _camera->unproject(size, &nearP, &nearP);
295 _camera->unproject(size, &farP, &farP);
296
297 Physics3DWorld::HitResult result;
298 getPhysics3DWorld()->rayCast(nearP, farP, &result);
299 moveAgents(result.hitPosition);
300 }
301}
302
303bool NavMeshBasicTestDemo::init()
304{
305 if (!NavMeshBaseTestDemo::init()) return false;
306
307 TTFConfig ttfConfig("fonts/arial.ttf", 15);
308 _debugLabel = Label::createWithTTF(ttfConfig, "Debug Draw ON");
309 _debugLabel->retain();
310 auto menuItem1 = MenuItemLabel::create(_debugLabel, [=](Ref*){
311 bool enabledDebug = !getNavMesh()->isDebugDrawEnabled();
312 getNavMesh()->setDebugDrawEnable(enabledDebug);
313 if (enabledDebug){
314 _debugLabel->setString("Debug Draw ON");
315 }
316 else{
317 _debugLabel->setString("Debug Draw OFF");
318 }
319 });
320 menuItem1->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
321 menuItem1->setPosition(Vec2(VisibleRect::left().x, VisibleRect::top().y - 100));
322 auto menu = Menu::create(menuItem1, nullptr);
323 menu->setPosition(Vec2::ZERO);
324 addChild(menu);
325
326 return true;
327}
328
329void NavMeshBasicTestDemo::onEnter()
330{
331 NavMeshBaseTestDemo::onEnter();
332
333 Physics3DWorld::HitResult result;
334 getPhysics3DWorld()->rayCast(Vec3(0.0f, 50.0f, 0.0f), Vec3(0.0f, -50.0f, 0.0f), &result);
335 createAgent(result.hitPosition);
336}
337
338NavMeshAdvanceTestDemo::NavMeshAdvanceTestDemo()
339{
340
341}
342
343NavMeshAdvanceTestDemo::~NavMeshAdvanceTestDemo()
344{
345
346}
347
348bool NavMeshAdvanceTestDemo::init()
349{
350 if (!NavMeshBaseTestDemo::init()) return false;
351
352 TTFConfig ttfConfig("fonts/arial.ttf", 15);
353 _obstacleLabel = Label::createWithTTF(ttfConfig, "Create Obstacle");
354 _obstacleLabel->retain();
355 _agentLabel = Label::createWithTTF(ttfConfig, "Create Agent");
356 _agentLabel->retain();
357 _debugLabel = Label::createWithTTF(ttfConfig, "Debug Draw ON");
358 _debugLabel->retain();
359
360 auto menuItem0 = MenuItemLabel::create(_obstacleLabel, [=](Ref*){
361 float x = cocos2d::random(-50.0f, 50.0f);
362 float z = cocos2d::random(-50.0f, 50.0f);
363 Physics3DWorld::HitResult result;
364 getPhysics3DWorld()->rayCast(Vec3(x, 50.0f, z), Vec3(x, -50.0f, z), &result);
365 createObstacle(result.hitPosition);
366 });
367 menuItem0->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
368 menuItem0->setPosition(Vec2(VisibleRect::left().x, VisibleRect::top().y - 50));
369
370 auto menuItem1 = MenuItemLabel::create(_agentLabel, [=](Ref*){
371 float x = cocos2d::random(-50.0f, 50.0f);
372 float z = cocos2d::random(-50.0f, 50.0f);
373 Physics3DWorld::HitResult result;
374 getPhysics3DWorld()->rayCast(Vec3(x, 50.0f, z), Vec3(x, -50.0f, z), &result);
375 createAgent(result.hitPosition);
376 });
377 menuItem1->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
378 menuItem1->setPosition(Vec2(VisibleRect::left().x, VisibleRect::top().y - 100));
379
380 auto menuItem2 = MenuItemLabel::create(_debugLabel, [=](Ref*){
381 bool enabledDebug = !getNavMesh()->isDebugDrawEnabled();
382 getNavMesh()->setDebugDrawEnable(enabledDebug);
383 if (enabledDebug){
384 _debugLabel->setString("Debug Draw ON");
385 }
386 else{
387 _debugLabel->setString("Debug Draw OFF");
388 }
389 });
390 menuItem2->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
391 menuItem2->setPosition(Vec2(VisibleRect::left().x, VisibleRect::top().y - 150));
392
393 auto menu = Menu::create(menuItem0, menuItem1, menuItem2, nullptr);
394 menu->setPosition(Vec2::ZERO);
395 addChild(menu);
396
397 return true;
398}
399
400void NavMeshAdvanceTestDemo::onEnter()
401{
402 NavMeshBaseTestDemo::onEnter();
403
404 Physics3DWorld::HitResult result;
405 getPhysics3DWorld()->rayCast(Vec3(0.0f, 50.0f, 0.0f), Vec3(0.0f, -50.0f, 0.0f), &result);
406 createAgent(result.hitPosition);
407}
408
409std::string NavMeshAdvanceTestDemo::title() const
410{
411 return "Navigation Mesh Test";
412}
413
414std::string NavMeshAdvanceTestDemo::subtitle() const
415{
416 return "Advance Test";
417}
418
419void NavMeshAdvanceTestDemo::touchesEnded(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
420{
421 if (!_needMoveAgents) return;
422 if (!touches.empty()){
423 auto touch = touches[0];
424 auto location = touch->getLocationInView();
425 Vec3 nearP(location.x, location.y, 0.0f), farP(location.x, location.y, 1.0f);
426
427 auto size = Director::getInstance()->getWinSize();
428 _camera->unproject(size, &nearP, &nearP);
429 _camera->unproject(size, &farP, &farP);
430
431 Physics3DWorld::HitResult result;
432 getPhysics3DWorld()->rayCast(nearP, farP, &result);
433 moveAgents(result.hitPosition);
434 }
435}
436
437#endif
#define ADD_TEST_CASE(__className__)
Definition: BaseTest.h:211
USING_NS_CC_EXT
Definition: NavMeshTest.cpp:33
USING_NS_CC
Definition: NavMeshTest.cpp:34
virtual void onEnter() override
Definition: NavMeshTest.cpp:52
virtual void onEnter() override
Definition: BaseTest.cpp:430
static cocos2d::Vec2 top()
Definition: VisibleRect.cpp:57
static cocos2d::Vec2 left()
Definition: VisibleRect.cpp:45