In a game I'm making I have about a hundred objects lying around on a TerrainSceneManager terrain surface. Some or them are moving and but most are not. All I want is basic gravity and bounds checking (that means: if object is below ground then move it up to the surface).
At the moment I have solved this by having each object, in every frame, perform a rayscenequery straight downwards (it starts at height 100 which should always be above the object and is aimed atVector3::NEGATIVE_UNIT_Y). It expects that one of the results is the terrain, and checks "if object is below ground then move it up to ground altitude" and "if object is above ground altitude then add gravity acceleration downwards".
My problem is that this appears to be SLOW! Should performing 100 rayscenequeries every frame be slow? (i get about 8 FPS on a good computer, and I tracked it down to the rayscenequery->execute call using my timetracking system). In the future I will have thousands of objects, not just a hundred, so this performance is an issue.
Is there a less computation-intensive way to do these extremely rudimentary physics? I have included some pseudocode for my current solution below. Thanks for your help!
Code: Select all
for (all objects)
{
// perform rayscenequery
RaySceneQuery* mRayQuery = COgreFramework::getSingletonPtr()->m_pSceneMgr->createRayQuery(Ray(Vector3(objPos.x, 100.0, objPos.z), Vector3::NEGATIVE_UNIT_Y));
RaySceneQueryResult &result = mRayQuery->execute(); // this line computes VERY SLOWLY compared to everything else
// wander through the results
for (RaySceneQueryResult::iterator itr = result.begin(); itr != result.end(); itr++)
{
if (itr->worldFragment) // if it's a worldFragment
{
Real terrainHeight = itr->worldFragment->singleIntersection.y;
if (objPos.y == terrainHeight) // if on ground then add friction (almost never happens except when standing still anyway)
{
objectStatus[SpeedX] *= 0.9;
objectStatus[SpeedY] *= 0.9;
objectStatus[SpeedZ] *= 0.9;
}
if (objPos.y < terrainHeight) // if below ground then move it up and add friction
{
object->setPosition( Vector3(objPos.x, terrainHeight, objPos.z) );
objectStatus[SpeedY] = 0;
objectStatus[SpeedX] *= 0.9;
objectStatus[SpeedZ] *= 0.9;
}
if (objPos.y > terrainHeight) // if above ground then make it fall (add gravity)
{
objectStatus[SpeedY] -= CONST_GRAVITY*timeSinceLastFrame;
}
break; // only do the above the first time we find a worldFragment
}
}
}