fixed bug #21800 [CppTest]Node: Scene3D when player outof terrain app will no response.

This commit is contained in:
Vincent Yang 2015-08-07 17:36:35 +08:00
parent cb751e3c1a
commit 354f64ec51
3 changed files with 23 additions and 39 deletions

View File

@ -29,6 +29,11 @@ Ray::Ray()
{ {
} }
Ray::Ray(const Ray& ray)
{
set(ray._origin, ray._direction);
}
Ray::Ray(const Vec3& origin, const Vec3& direction) Ray::Ray(const Vec3& origin, const Vec3& direction)
{ {
set(origin, direction); set(origin, direction);

View File

@ -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<Chunk *> closeList; std::set<Chunk *> closeList;
Vec2 start = Vec2(ray._origin.x,ray._origin.z); Vec2 start = Vec2(ray._origin.x,ray._origin.z);
Vec2 dir = Vec2(ray._direction.x,ray._direction.z); Vec2 dir = Vec2(ray._direction.x,ray._direction.z);

View File

@ -869,53 +869,28 @@ void Scene3DTestScene::onTouchEnd(Touch* touch, Event* event)
if(_player) if(_player)
{ {
Vec3 nearP(location.x, location.y, 0.0f), farP(location.x, location.y, 1.0f); 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(); auto size = Director::getInstance()->getWinSize();
camera->unprojectGL(size, &nearP, &nearP); camera->unprojectGL(size, &nearP, &nearP);
camera->unprojectGL(size, &farP, &farP); 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; Vec3 dir = farP - nearP;
dir.normalize(); dir.normalize();
Vec3 rayStep = 15*dir; Vec3 collisionPoint;
Vec3 rayPos = nearP; bool isInTerrain = _terrain->getIntersectionPoint(Ray(nearP, dir), collisionPoint);
Vec3 rayStartPosition = nearP; if (!isInTerrain)
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)
{ {
lastRayPosition = rayPos; _player->idle();
rayPos += rayStep;
height = _terrain->getHeight(rayPos.x,rayPos.z);
} }
else
Vec3 startPosition = lastRayPosition;
Vec3 endPosition = rayPos;
for (int i= 0; i< 32; i++)
{ {
// Binary search pass dir = collisionPoint - _player->getPosition3D();
Vec3 middlePoint = (startPosition + endPosition) * 0.5f; dir.y = 0;
if (middlePoint.y < height) dir.normalize();
endPosition = middlePoint; _player->_headingAngle = -1*acos(dir.dot(Vec3(0,0,-1)));
else dir.cross(dir,Vec3(0,0,-1),&_player->_headingAxis);
startPosition = middlePoint; _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(); event->stopPropagation();
} }