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)
{
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;
Vec2 start = Vec2(ray._origin.x,ray._origin.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)
{
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();
}