diff --git a/cocos/3d/CCRay.cpp b/cocos/3d/CCRay.cpp index bf41c23440..645c716a63 100755 --- a/cocos/3d/CCRay.cpp +++ b/cocos/3d/CCRay.cpp @@ -29,6 +29,11 @@ Ray::Ray() { } +Ray::Ray(const Ray& ray) +{ + set(ray._origin, ray._direction); +} + Ray::Ray(const Vec3& origin, const Vec3& direction) { set(origin, direction); diff --git a/cocos/3d/CCTerrain.cpp b/cocos/3d/CCTerrain.cpp index 96e9690800..461a3eb5ba 100644 --- a/cocos/3d/CCTerrain.cpp +++ b/cocos/3d/CCTerrain.cpp @@ -541,8 +541,12 @@ cocos2d::Vec3 Terrain::getIntersectionPoint(const Ray & ray) const } } -bool Terrain::getIntersectionPoint(const Ray & ray, Vec3 & intersectionPoint) const +bool Terrain::getIntersectionPoint(const Ray & ray_, Vec3 & intersectionPoint) const { + // convert ray from world space to local space + Ray ray(ray_); + getWorldToNodeTransform().transformPoint(&(ray._origin)); + std::set closeList; Vec2 start = Vec2(ray._origin.x,ray._origin.z); Vec2 dir = Vec2(ray._direction.x,ray._direction.z); diff --git a/tests/cpp-tests/Classes/Scene3DTest/Scene3DTest.cpp b/tests/cpp-tests/Classes/Scene3DTest/Scene3DTest.cpp index fd2e8cbbee..b9816d02b6 100644 --- a/tests/cpp-tests/Classes/Scene3DTest/Scene3DTest.cpp +++ b/tests/cpp-tests/Classes/Scene3DTest/Scene3DTest.cpp @@ -869,53 +869,28 @@ void Scene3DTestScene::onTouchEnd(Touch* touch, Event* event) if(_player) { Vec3 nearP(location.x, location.y, 0.0f), farP(location.x, location.y, 1.0f); - // first, convert screen touch location to the world location on near and far plane + // convert screen touch location to the world location on near and far plane auto size = Director::getInstance()->getWinSize(); camera->unprojectGL(size, &nearP, &nearP); camera->unprojectGL(size, &farP, &farP); - // second, convert world location to terrain's local position on near/far plane - auto worldToNodeMat = _terrain->getNodeToWorldTransform(); - worldToNodeMat.inverse(); - worldToNodeMat.transformPoint(&nearP); - worldToNodeMat.transformPoint(&farP); - // create a ray from point which on near plane to point which on far plane Vec3 dir = farP - nearP; dir.normalize(); - Vec3 rayStep = 15*dir; - Vec3 rayPos = nearP; - Vec3 rayStartPosition = nearP; - Vec3 lastRayPosition =rayPos; - rayPos += rayStep; - // Linear search - Loop until find a point inside and outside the terrain Vector3 - float height = _terrain->getHeight(rayPos.x,rayPos.z); - - while (rayPos.y > height) + Vec3 collisionPoint; + bool isInTerrain = _terrain->getIntersectionPoint(Ray(nearP, dir), collisionPoint); + if (!isInTerrain) { - lastRayPosition = rayPos; - rayPos += rayStep; - height = _terrain->getHeight(rayPos.x,rayPos.z); + _player->idle(); } - - Vec3 startPosition = lastRayPosition; - Vec3 endPosition = rayPos; - - for (int i= 0; i< 32; i++) + else { - // Binary search pass - Vec3 middlePoint = (startPosition + endPosition) * 0.5f; - if (middlePoint.y < height) - endPosition = middlePoint; - else - startPosition = middlePoint; + dir = collisionPoint - _player->getPosition3D(); + dir.y = 0; + dir.normalize(); + _player->_headingAngle = -1*acos(dir.dot(Vec3(0,0,-1))); + dir.cross(dir,Vec3(0,0,-1),&_player->_headingAxis); + _player->_targetPos=collisionPoint; + _player->forward(); } - Vec3 collisionPoint = (startPosition + endPosition) * 0.5f; - dir = collisionPoint - _player->getPosition3D(); - dir.y = 0; - dir.normalize(); - _player->_headingAngle = -1*acos(dir.dot(Vec3(0,0,-1))); - dir.cross(dir,Vec3(0,0,-1),&_player->_headingAxis); - _player->_targetPos=collisionPoint; - _player->forward(); } event->stopPropagation(); }