PagingLandScapeRaySceneQuery::execute problem ?

bleubleu

12-01-2007 04:44:24

Hi!

I am integrating OgreOde with PLSM2. In order to detect collisions with the ground, i simply cast rays in the NEGATIVE_UNIT_Y direction using the RSQ_Height query mask in order to get the maximum speed. Very Simple.

When I am doing this, I only want the terrain height and I dont want to detect any other kind of intersection in my scene. However, the execute() function of the PLSM ray scene query keeps testing against the movable objects in the scene. No matter what I do, it always ends up calling PagingLandScapeOctreeRaySceneQuery::execute(listener).

The "noSpecializedQueries" variable and the RSQ_Entities flag seems to control this but they are mutually exclusive and they both do the same exact thing. Am i wrong ? (see the last 2 if's in the code)

There is a lot of commented code in this function and it is getting a little bit messy.


void PagingLandScapeRaySceneQuery::execute(RaySceneQueryListener* listener)
{
ulong mask = getQueryMask();
ulong type_mask = getQueryTypeMask();

static WorldFragment worldFrag;
worldFrag.fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION;

const Vector3& dir = mRay.getDirection();
const Vector3& origin = mRay.getOrigin();

bool noSpecializedQueries = true;
bool noTerrainQuery = true;

PagingLandScapeSceneManager* mSceneMgr = static_cast<PagingLandScapeSceneManager*>(mParentSceneMgr);

// Exclusive Specialized Queries
// Straight up / down?
if ((mask & RSQ_Height) ||
(mask & RSQ_Height_no_interpolation) ||
dir == Vector3::UNIT_Y ||
dir == Vector3::NEGATIVE_UNIT_Y)
{
noTerrainQuery = false;
//noSpecializedQueries = false;

Real height;
if (mask & RSQ_Height_no_interpolation)
height = mSceneMgr->getData2DManager()->getWorldHeight(origin.x, origin.z);
else
height = mSceneMgr->getData2DManager()->getInterpolatedWorldHeight(origin.x, origin.z);

worldFrag.singleIntersection.x = origin.x;
worldFrag.singleIntersection.z = origin.z;
worldFrag.singleIntersection.y = height;

worldFrag.singleIntersection += mSceneMgr->getOptions()->position; //consider terrain offset

//if (!listener->queryResult(&worldFrag, (worldFrag.singleIntersection - origin).length()))
//if (!listener->queryResult(&worldFrag, 0))
// return;
listener->queryResult(&worldFrag, 0);
}
else if (mask & RSQ_FirstTerrain)
{
noTerrainQuery = false;
//noSpecializedQueries = false;

Real resFactor = 1.0f;
// Only bother if the non-default mask has been set
if((mask & RSQ_1xRes) == 0)
{
if(mask & RSQ_2xRes)
{
resFactor = 0.5f;
}
else if(mask & RSQ_4xRes)
{
resFactor = 0.25f;
}
//if(mask & RSQ_8xRes)
//{
// resFactor = 0.125f;
//}
}
if (mSceneMgr->intersectSegmentTerrain(
origin, dir*resFactor,
&worldFrag.singleIntersection))
{
//if (!listener->queryResult(&worldFrag, (worldFrag.singleIntersection - origin).length()))
//if (!listener->queryResult(&worldFrag, 0))
// return;
listener->queryResult(&worldFrag, 0);
}
}
else if (mask & RSQ_AllTerrain)
{
noTerrainQuery = false;
//noSpecializedQueries = false;

Real resFactor = 1.0f;
// Only bother if the non-default mask has been set
if((mask & RSQ_1xRes) == 0)
{
if(mask & RSQ_2xRes)
{
resFactor = 0.5f;
}
else if(mask & RSQ_4xRes)
{
resFactor = 0.25f;
}
//else if(mask & RSQ_8xRes)
//{
// resFactor = 0.125f;
//}
}


const Vector3 raydir (mRay.getDirection());
const Vector3 raymove (raydir * resFactor);
const Real distmove = 1 * resFactor;
const Real maxHeight = mSceneMgr->getData2DManager()->getMaxHeight ();
const Real MaxTerrainX = mSceneMgr->getOptions()->maxScaledX;
const Real MaxTerrainZ = mSceneMgr->getOptions()->maxScaledZ;

Vector3 ray (mRay.getOrigin());
Real dist = 0.0f;

// while ray is inside or ray is outside but raydir going inside
while ((ray.y < 0 && raydir.y > 0) ||
(ray.y > maxHeight && raydir.y < 0) ||
(ray.x < -MaxTerrainX && raydir.x > 0) ||
(ray.x > MaxTerrainX && raydir.x < 0) ||
(ray.z < -MaxTerrainZ && raydir.z > 0) ||
(ray.z > MaxTerrainZ && raydir.z < 0))
{
ray += raymove;
dist += distmove;
if (ray.y < maxHeight)// no need to do complex tests
{
const Vector3 land (getHeightAt(ray));
if (ray.y < land.y)
{
WorldFragment* frag = new WorldFragment();
//fragmentList.push_back(frag);

frag->fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION;
frag->singleIntersection = land;

if (!listener->queryResult(frag, dist))
break;
}
}
}
}

// Could want entities and terrain or or just entities, or didn't say nothing...
if(mask & RSQ_Entities)
{
noSpecializedQueries = false;
// Check for entity contacts
PagingLandScapeOctreeRaySceneQuery::execute(listener);
}

if (noSpecializedQueries)
{
/*
if (noTerrainQuery)
{
setQueryMask(mask | RSQ_AllTerrain | RSQ_Entities);
// Check for terrain contacts
PagingLandScapeRaySceneQuery::execute(listener);
setQueryMask(mask);
}
*/
// Check for entity contacts
PagingLandScapeOctreeRaySceneQuery::execute(listener);
}
}


Keep up the excellent work.

Mat

tuan kuranes

12-01-2007 13:05:58

what version of PLSM2 is that ?

Current version do not use those flags anymore, check changelog sticky post for difference/information about that...

btw, current OgreOde works directly with PLSM2, just change a define in landscape demo.

bleubleu

12-01-2007 15:53:06

I simply use the version on your website (http://tuan.kuranes.free.fr/OgreSDK_PLSM2_source.zip). I just updated from the CVS everything seems so much cleaner.

Yes i did try the OgreODE landscape demo but not with the PLSM2 flag. Will do that later. Thanks!

Last question. in the PagingLandScapeData2DManager::getInterpolatedWorldHeight() method, is there a way to force using the most detailed LOD and avoid any kind of stiching. Because the way I see it, objects should collide on the actual terrain, not on a simplified LOD, right ?

Mat

tuan kuranes

12-01-2007 16:00:41

Last question. in the PagingLandScapeData2DManager::getInterpolatedWorldHeight() method, is there a way to force using the most detailed LOD and avoid any kind of stiching. Because the way I see it, objects should collide on the actual terrain, not on a simplified LOD, right ?
It does actually compile with actual terrain. but you can force actual terrain under camera to be at max lod. (MaxLodUnderCam=yes in config file for instance)