Merge pull request #12019 from super626/v3

getIntersectionPoint failed when there is no intersection on the terrain
This commit is contained in:
子龙山人 2015-06-08 11:26:19 +08:00
commit c5ba7eef8b
4 changed files with 83 additions and 12 deletions

View File

@ -278,7 +278,7 @@ void Terrain::setChunksLOD(Vec3 cameraPos)
} }
} }
float Terrain::getHeight(float x, float z, Vec3 * normal) float Terrain::getHeight(float x, float z, Vec3 * normal) const
{ {
Vec2 pos(x,z); Vec2 pos(x,z);
@ -307,6 +307,10 @@ float Terrain::getHeight(float x, float z, Vec3 * normal)
if(image_x>=_imageWidth-1 || image_y >=_imageHeight-1 || image_x<0 || image_y<0) if(image_x>=_imageWidth-1 || image_y >=_imageHeight-1 || image_x<0 || image_y<0)
{ {
if (normal)
{
normal->setZero();
}
return 0; return 0;
}else }else
{ {
@ -327,12 +331,12 @@ float Terrain::getHeight(float x, float z, Vec3 * normal)
} }
} }
float Terrain::getHeight(Vec2 pos, Vec3*Normal) float Terrain::getHeight(Vec2 pos, Vec3*Normal) const
{ {
return getHeight(pos.x,pos.y,Normal); return getHeight(pos.x,pos.y,Normal);
} }
float Terrain::getImageHeight(int pixel_x,int pixel_y) float Terrain::getImageHeight(int pixel_x,int pixel_y) const
{ {
int byte_stride =1; int byte_stride =1;
switch (_heightMapImage->getRenderFormat()) switch (_heightMapImage->getRenderFormat())
@ -472,7 +476,7 @@ Terrain::~Terrain()
#endif #endif
} }
cocos2d::Vec3 Terrain::getNormal(int pixel_x, int pixel_y) cocos2d::Vec3 Terrain::getNormal(int pixel_x, int pixel_y) const
{ {
float a = getImageHeight(pixel_x,pixel_y)*getScaleY(); float a = getImageHeight(pixel_x,pixel_y)*getScaleY();
float b = getImageHeight(pixel_x,pixel_y+1)*getScaleY(); float b = getImageHeight(pixel_x,pixel_y+1)*getScaleY();
@ -486,7 +490,7 @@ cocos2d::Vec3 Terrain::getNormal(int pixel_x, int pixel_y)
return normal; return normal;
} }
cocos2d::Vec3 Terrain::getIntersectionPoint(const Ray & ray) cocos2d::Vec3 Terrain::getIntersectionPoint(const Ray & ray) const
{ {
Vec3 dir = ray._direction; Vec3 dir = ray._direction;
dir.normalize(); dir.normalize();
@ -496,12 +500,14 @@ cocos2d::Vec3 Terrain::getIntersectionPoint(const Ray & ray)
Vec3 lastRayPosition =rayPos; Vec3 lastRayPosition =rayPos;
rayPos += rayStep; rayPos += rayStep;
// Linear search - Loop until find a point inside and outside the terrain Vector3 // Linear search - Loop until find a point inside and outside the terrain Vector3
float height = getHeight(rayPos.x,rayPos.z); Vec3 normal;
float height = getHeight(rayPos.x, rayPos.z, &normal);
while (rayPos.y > height) while (rayPos.y > height)
{ {
lastRayPosition = rayPos; lastRayPosition = rayPos;
rayPos += rayStep; rayPos += rayStep;
if (normal.isZero())
return Vec3(0, 0, 0);
height = getHeight(rayPos.x,rayPos.z); height = getHeight(rayPos.x,rayPos.z);
} }
@ -521,6 +527,47 @@ cocos2d::Vec3 Terrain::getIntersectionPoint(const Ray & ray)
return collisionPoint; return collisionPoint;
} }
bool Terrain::getIntersectionPoint(const Ray & ray, Vec3 & intersectionPoint) const
{
Vec3 dir = ray._direction;
dir.normalize();
Vec3 rayStep = _terrainData._chunkSize.width*0.25*dir;
Vec3 rayPos = ray._origin;
Vec3 rayStartPosition = ray._origin;
Vec3 lastRayPosition = rayPos;
rayPos += rayStep;
// Linear search - Loop until find a point inside and outside the terrain Vector3
Vec3 normal;
float height = getHeight(rayPos.x, rayPos.z, &normal);
while (rayPos.y > height)
{
lastRayPosition = rayPos;
rayPos += rayStep;
if (normal.isZero())
{
intersectionPoint = Vec3(0, 0, 0);
return false;
}
height = getHeight(rayPos.x, rayPos.z);
}
Vec3 startPosition = lastRayPosition;
Vec3 endPosition = rayPos;
for (int i = 0; i < 32; i++)
{
// Binary search pass
Vec3 middlePoint = (startPosition + endPosition) * 0.5f;
if (middlePoint.y < height)
endPosition = middlePoint;
else
startPosition = middlePoint;
}
Vec3 collisionPoint = (startPosition + endPosition) * 0.5f;
intersectionPoint = collisionPoint;
return true;
}
void Terrain::setMaxDetailMapAmount(int max_value) void Terrain::setMaxDetailMapAmount(int max_value)
{ {
_maxDetailMapValue = max_value; _maxDetailMapValue = max_value;

View File

@ -302,22 +302,22 @@ public:
* @param normal the specified position's normal vector in terrain . if this argument is NULL or nullptr,Normal calculation shall be skip. * @param normal the specified position's normal vector in terrain . if this argument is NULL or nullptr,Normal calculation shall be skip.
* @return the height value of the specified position of the terrain, if the (X,Z) position is out of the terrain bounds,it shall return 0; * @return the height value of the specified position of the terrain, if the (X,Z) position is out of the terrain bounds,it shall return 0;
**/ **/
float getHeight(float x, float z, Vec3 * normal= nullptr); float getHeight(float x, float z, Vec3 * normal= nullptr) const;
/**get specified position's height mapping to the terrain,use bi-linear interpolation method /**get specified position's height mapping to the terrain,use bi-linear interpolation method
* @param pos the position (X,Z) * @param pos the position (X,Z)
* @param normal the specified position's normal vector in terrain . if this argument is NULL or nullptr,Normal calculation shall be skip. * @param normal the specified position's normal vector in terrain . if this argument is NULL or nullptr,Normal calculation shall be skip.
* @return the height value of the specified position of the terrain, if the (X,Z) position is out of the terrain bounds,it shall return 0; * @return the height value of the specified position of the terrain, if the (X,Z) position is out of the terrain bounds,it shall return 0;
**/ **/
float getHeight(Vec2 pos, Vec3*Normal = nullptr); float getHeight(Vec2 pos, Vec3*Normal = nullptr) const;
/**get the normal of the specified pistion in terrain /**get the normal of the specified pistion in terrain
* @return the normal vector of the specified position of the terrain. * @return the normal vector of the specified position of the terrain.
* @note the fast normal calculation may not get precise normal vector. * @note the fast normal calculation may not get precise normal vector.
**/ **/
Vec3 getNormal(int pixelX, int pixelY); Vec3 getNormal(int pixelX, int pixelY) const;
/**get height from the raw height filed*/ /**get height from the raw height filed*/
float getImageHeight(int pixelX, int pixelY); float getImageHeight(int pixelX, int pixelY) const;
/**show the wireline instead of the surface,Debug Use only. /**show the wireline instead of the surface,Debug Use only.
* @Note only support desktop platform * @Note only support desktop platform
**/ **/
@ -344,7 +344,15 @@ public:
* Ray-Terrain intersection. * Ray-Terrain intersection.
* @return the intersection point * @return the intersection point
*/ */
Vec3 getIntersectionPoint(const Ray & ray); Vec3 getIntersectionPoint(const Ray & ray) const;
/**
* Ray-Terrain intersection.
* @param ray to hit the terrain
* @param intersectionPoint hit point if hitted
* @return true if hit, false otherwise
*/
bool getIntersectionPoint(const Ray & ray, Vec3 & intersectionPoint) const;
/** /**
* set the MaxDetailAmount. * set the MaxDetailAmount.

View File

@ -67,6 +67,16 @@ Physics3DWorld* Physics3DWorld::create(Physics3DWorldDes* info)
return world; return world;
} }
void Physics3DWorld::setGravity(const Vec3& gravity)
{
_btPhyiscsWorld->setGravity(convertVec3TobtVector3(gravity));
}
Vec3 Physics3DWorld::getGravity() const
{
return convertbtVector3ToVec3(_btPhyiscsWorld->getGravity());
}
bool Physics3DWorld::init(Physics3DWorldDes* info) bool Physics3DWorld::init(Physics3DWorldDes* info)
{ {
///collision configuration contains default setup for memory, collision setup ///collision configuration contains default setup for memory, collision setup

View File

@ -90,6 +90,12 @@ public:
*/ */
static Physics3DWorld* create(Physics3DWorldDes* info); static Physics3DWorld* create(Physics3DWorldDes* info);
/** set gravity for the physics world */
void setGravity(const Vec3& gravity);
/** get current gravity */
Vec3 getGravity() const;
/** Add a Physics3DObject. */ /** Add a Physics3DObject. */
void addPhysics3DObject(Physics3DObject* physicsObj); void addPhysics3DObject(Physics3DObject* physicsObj);