28#include "physics3d/CCPhysics3DWorld.h"
29#include "physics3d/CCPhysics3D.h"
30#include "3d/CCBundle3D.h"
31#include "2d/CCLight.h"
41NavMeshTests::NavMeshTests()
43#if ( CC_USE_NAVMESH == 0 ) || ( CC_USE_PHYSICS == 0 )
51#if ( CC_USE_NAVMESH == 0 ) || ( CC_USE_PHYSICS == 0 )
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");
57 auto size = Director::getInstance()->getWinSize();
58 label->setPosition(Vec2(size.width / 2, size.height / 2));
66NavMeshBaseTestDemo::NavMeshBaseTestDemo()
68 , _needMoveAgents(false)
73NavMeshBaseTestDemo::~NavMeshBaseTestDemo()
75 for (
auto iter : _agents){
81bool NavMeshBaseTestDemo::init()
83 if (!TestCase::init())
return false;
85 if (initWithPhysics()){
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);
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);
110void NavMeshBaseTestDemo::onTouchesBegan(
const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
112 _needMoveAgents =
true;
113 touchesBegan(touches, event);
116void NavMeshBaseTestDemo::onTouchesMoved(
const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
118 if (touches.size() && _camera)
120 auto touch = touches[0];
121 auto delta = touch->getDelta();
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));
127 if (delta.lengthSquared() > 16)
129 _needMoveAgents =
false;
132 touchesMoved(touches, event);
135void NavMeshBaseTestDemo::onTouchesEnded(
const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
137 touchesEnded(touches, event);
140void NavMeshBaseTestDemo::initScene()
142 getPhysics3DWorld()->setDebugDrawEnable(
false);
144 std::vector<Vec3> trianglesList = Bundle3D::getTrianglesList(
"NavMesh/scene.obj");
146 Physics3DRigidBodyDes rbDes;
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);
157 auto navMesh = NavMesh::create(
"NavMesh/all_tiles_tilecache.bin",
"NavMesh/geomset.txt");
158 navMesh->setDebugDrawEnable(
true);
160 setNavMeshDebugCamera(_camera);
163 auto ambientLight = AmbientLight::create(Color3B(64, 64, 64));
164 ambientLight->setCameraMask((
unsigned short)CameraFlag::USER1);
165 this->addChild(ambientLight);
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);
172void NavMeshBaseTestDemo::createAgent(
const Vec3 &pos)
174 std::string filePath =
"Sprite3DTest/girl.c3b";
175 NavMeshAgentParam param;
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));
183 agent->setUserData(data);
184 agentNode->setScale(0.05f);
185 agentNode->addComponent(agent);
187 auto node = Node::create();
188 node->addChild(agentNode);
189 node->setPosition3D(pos);
190 node->setCameraMask((
unsigned short)CameraFlag::USER1);
191 this->addChild(node);
194 auto animation = Animation3D::create(filePath);
195 auto animate = Animate3D::create(animation);
197 agentNode->runAction(RepeatForever::create(animate));
198 animate->setSpeed(0);
201 _agents.push_back(std::make_pair(agent, animate));
204void NavMeshBaseTestDemo::createObstacle(
const Vec3 &pos)
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);
216Vec3 jump(
const Vec3* pV1,
const Vec3* pV2,
float height,
float t)
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);
226void NavMeshBaseTestDemo::moveAgents(
const cocos2d::Vec3 &des)
228 for (
auto iter : _agents){
229 NavMeshAgent::MoveCallback callback = [](NavMeshAgent *agent,
float totalTimeAfterMove){
231 if (agent->isOnOffMeshLink()){
232 agent->setAutoTraverseOffMeshLink(
false);
233 agent->setAutoOrientation(
false);
234 OffMeshLinkData linkdata = agent->getCurrentOffMeshLinkData();
236 agent->getOwner()->setPosition3D(jump(&linkdata.startPosition, &linkdata.endPosition, 10.0f, data->
time));
237 Vec3 dir = linkdata.endPosition - linkdata.startPosition;
241 Vec3 refAxes = Vec3(-1.0f, 0.0f, 1.0f);
243 Vec3::cross(refAxes, dir, &axes);
244 float angle = Vec3::dot(refAxes, dir);
245 agent->getOwner()->setRotationQuat(Quaternion(axes, acosf(angle)));
247 if (1.0f < data->
time){
248 agent->completeOffMeshLink();
249 agent->setAutoOrientation(
true);
254 iter.first->move(des, callback);
258void NavMeshBaseTestDemo::update(
float delta)
260 for (
auto iter : _agents){
261 float speed = iter.first->getCurrentVelocity().length() * 0.2f;
262 iter.second->setSpeed(0.0f < speed ? speed : 0.0f);
266NavMeshBasicTestDemo::NavMeshBasicTestDemo()
271NavMeshBasicTestDemo::~NavMeshBasicTestDemo()
275std::string NavMeshBasicTestDemo::title()
const
277 return "Navigation Mesh Test";
280std::string NavMeshBasicTestDemo::subtitle()
const
285void NavMeshBasicTestDemo::touchesEnded(
const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
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);
293 auto size = Director::getInstance()->getWinSize();
294 _camera->unproject(size, &nearP, &nearP);
295 _camera->unproject(size, &farP, &farP);
297 Physics3DWorld::HitResult result;
298 getPhysics3DWorld()->rayCast(nearP, farP, &result);
299 moveAgents(result.hitPosition);
303bool NavMeshBasicTestDemo::init()
305 if (!NavMeshBaseTestDemo::init())
return false;
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);
314 _debugLabel->setString(
"Debug Draw ON");
317 _debugLabel->setString(
"Debug Draw OFF");
320 menuItem1->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
322 auto menu = Menu::create(menuItem1,
nullptr);
323 menu->setPosition(Vec2::ZERO);
329void NavMeshBasicTestDemo::onEnter()
331 NavMeshBaseTestDemo::onEnter();
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);
338NavMeshAdvanceTestDemo::NavMeshAdvanceTestDemo()
343NavMeshAdvanceTestDemo::~NavMeshAdvanceTestDemo()
348bool NavMeshAdvanceTestDemo::init()
350 if (!NavMeshBaseTestDemo::init())
return false;
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();
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);
367 menuItem0->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
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);
377 menuItem1->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
380 auto menuItem2 = MenuItemLabel::create(_debugLabel, [=](Ref*){
381 bool enabledDebug = !getNavMesh()->isDebugDrawEnabled();
382 getNavMesh()->setDebugDrawEnable(enabledDebug);
384 _debugLabel->setString(
"Debug Draw ON");
387 _debugLabel->setString(
"Debug Draw OFF");
390 menuItem2->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
393 auto menu = Menu::create(menuItem0, menuItem1, menuItem2,
nullptr);
394 menu->setPosition(Vec2::ZERO);
400void NavMeshAdvanceTestDemo::onEnter()
402 NavMeshBaseTestDemo::onEnter();
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);
409std::string NavMeshAdvanceTestDemo::title()
const
411 return "Navigation Mesh Test";
414std::string NavMeshAdvanceTestDemo::subtitle()
const
416 return "Advance Test";
419void NavMeshAdvanceTestDemo::touchesEnded(
const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event)
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);
427 auto size = Director::getInstance()->getWinSize();
428 _camera->unproject(size, &nearP, &nearP);
429 _camera->unproject(size, &farP, &farP);
431 Physics3DWorld::HitResult result;
432 getPhysics3DWorld()->rayCast(nearP, farP, &result);
433 moveAgents(result.hitPosition);
#define ADD_TEST_CASE(__className__)
virtual void onEnter() override
virtual void onEnter() override
static cocos2d::Vec2 top()
static cocos2d::Vec2 left()