PCZSM getHeightAt

yubgipenguin

15-02-2009 23:25:40

I can use getHeightAt by casting PCZone into TerrainZone but I can't do that in Python-Ogre.

RaySceneQuery also only has a bounding box info.

Is there some kind of a work-around to do that?

Or, do we need a patch to do that?

andy

16-02-2009 01:57:10

Can you send through code snipits to explain what you are after..

Currently Python-Ogre doesn't expose the inner workings of the scene managers except OgrePCZ hence getHeightAt in the terrain manger is not available (once I see you sample code I'll take a look at exposing it -- shouldn't be too hard)..

And I'm not sure what you mean by the RayQuery -- is there something missing -- again send through a little code and I'll take a look

regards

Andy

yubgipenguin

16-02-2009 08:00:06

Ok.. here you go.

First I need to know what a current terrain height value is at given x and z:

self.raySceneQuery = self.sceneManager.createRayQuery(ogre.Ray())
self.raySceneQuery.setSortByDistance(True)
self.raySceneQuery.setQueryTypeMask(ogre.SceneManager.WORLD_GEOMETRY_TYPE_MASK)
self.raySceneQuery.setWorldFragmentType(ogre.SceneQuery.WFT_SINGLE_INTERSECTION)

def GetHeightAtPos(x, z):
MAX_HEIGHT = 500
updateRay = ogre.Ray()
updateRay.setOrigin(ogre.Vector3(x, MAX_HEIGHT, z))
updateRay.setDirection(ogre.Vector3().NEGATIVE_UNIT_Y)
self.raySceneQuery.setRay(updateRay)
height = None
queryResults = self.raySceneQuery.execute()
for queryResult in queryResults:
if queryResult.worldFragment is not None:
height = queryResult.worldFragment.singleIntersection.y
return height


I currently use this code with TerrainSM(default ogre terrain manager).




I use it to ultimately achive this:

def MyLookAt(x, z):
x = float(x)
z = float(z)
height = GetHeightAtPos(x, z)
if height == None:
height = self.lastHeight
else:
self.lastHeight = height

oldPos = ogre.Vector3(x, height, z)
self.cameraNode2.setPosition(x, height+250, z)
self.cameraNode2.setOrientation(self.defNodeOrient)
self.camera2.lookAt(
self.cameraNode2._getDerivedPosition() + ogre.Vector3().NEGATIVE_UNIT_Z)
self.camera2.getParentSceneNode().pitch(ogre.Degree(goldenPitch))
self.camera2.getParentSceneNode().yaw(ogre.Degree(goldenYaw),
ogre.Node.TS_WORLD)

pos = GetPosLookingAt()
if pos == None:
pos = self.lastPos
else:
self.lastPos = pos

offsetPos = oldPos - pos
targetPos = oldPos + offsetPos
self.cameraNode.setPosition(targetPos.x, targetPos.y+250, targetPos.z)
self.cameraNode.setOrientation(self.defNodeOrient)
self.camera.lookAt(
self.cameraNode._getDerivedPosition() + ogre.Vector3().NEGATIVE_UNIT_Z)
self.camera.getParentSceneNode().pitch(ogre.Degree(goldenPitch))
self.camera.getParentSceneNode().yaw(ogre.Degree(goldenYaw),
ogre.Node.TS_WORLD)
self.cameraNode._updateBounds()

def GetPosLookingAt():
updateRay.setOrigin(self.camera2.getParentSceneNode().getPosition())
updateRay.setDirection(
self.camera2.getParentSceneNode().getOrientation() * \
ogre.Vector3().NEGATIVE_UNIT_Z)
self.raySceneQuery.setRay(updateRay)
pos = None
queryResults = self.raySceneQuery.execute()
for queryResult in queryResults:
if queryResult.worldFragment is not None:
pos = queryResult.worldFragment.singleIntersection
return pos


It tilts your camera with certain angles and while reserving that angle it centers given map's x,z at center of Viewport by looking at it.

RaySceneQuery fails a lot (not sure why) so I needed to save last positions and heights.

Unfortunately, using ogre.SceneManager.WORLD_GEOMETRY_TYPE_MASK to get the worldFragment value out of RaySceneQuery's result is not supported by PCZSM.

getHeightAt gives same result as GetHeightAtPos, which I wrote above, but getHeightAt is better because it never fails(it access through map's data directly). And it is supported by ETM, PLSM2 and PCZSM.

TerrainZone::getHeightAt is implemented in the ogre/PlugIns/OctreeZone/src/OgreTerrainZone.cpp/.h...
It's part of PCZSM's terrain manager...

In C++ you could use that function by casting PCZone into TerrainZone.