Google

a solution for getting terrain dimensions

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.

Moderators: OGRE Team, Moderators

a solution for getting terrain dimensions

Postby trilobite » Thu Jul 13, 2006 9:37 pm

I'm an old Genesis3d user, and I started fiddling with Ogre a few days ago. The Ogre terrain API is great, but until it's finished, some workarounds are necessary. This is my hack for getting terrain dimensions at load time (in this case, just the X-dimensions).

I hope it helps...

Code: Select all
void   ogre_testApp::DetermineTerrainX_Dimension()
{
   //   A hack for getting the X-dimension of your Ogre terrain at load time.
   //   the Ogre TerrainSceneManager creates your terrain and sets one corner at world center.
   //   this makes it inconvevnient when you'd like to know where terrain center is.
   //   the Ogre terrain scene manager API provides no direct way to determine the world
   //   coodinates of your world terrain geometry (at least not that I have found...)
   //   this method determines the X-dimension of your loaded terrain -- with which you can determine
   //   terrain center -- and with which you can accurately calculate offsets.
   //   Keep in mind, moving the terrain node causees misalignments with collision
   //   detection. So, use offsets, and leave sleeping terrains lie.
   //   Steps:
   //   1. initialize your Ogre terrain app as recommended
   //   2. after you use your scene manager to setWorldGeometry( your_terrain_config_file ), run this code.
   //   3. use the resulting value to offset the positions of other world resources loaded later,
   //   i.e., SceneNode::setPosition(...)  .
   //   this method aassumes we are starting in the upper-left (or is it lower-left?) corner of our terrain.
   //   basically, we start by hovering above one of the corners of the terrain.
   //   we make one trial test to see if we hit dirt. If so, then we walk it down the line,
   //   poking down all the way until we run out of terrain -- keeping track of our progress, mind you.

   int            iX_Width = 1;         //   our starting point. we'll assume at least a width of 1
   const   int      iY_Line = 1000;         //   make sure your query starts above your highest terrain
   const   int      iZ_Line = 1;         //   run our queries just inside the edge
   RaySceneQuery*   raySceneQuery = NULL;   //   our ray query machine
   Ray            updateRay;            //   our "sounding" tool - for poking down towards the ground
   bool         bFoundTerrain = false;   //   our finishing flag

   //   create a custom query machine and initialize its ray tool
   raySceneQuery = m_pSceneMgr->createRayQuery(Ray(Vector3(iX_Width, iY_Line, iZ_Line), Vector3::NEGATIVE_UNIT_Y));
   //   do an initial "sounding" to make sure you're in the right place
   //   poke down now and see if you hit anything
   RaySceneQueryResult& qryResult = raySceneQuery->execute();
   //   examine your results. If positive, then we are going down the line, baby.
   RaySceneQueryResult::iterator i = qryResult.begin();
   if (i != qryResult.end() && i->worldFragment)
   {
      bFoundTerrain = true;            //   set the flag
      iX_Width++;                     //   increment our known width
      raySceneQuery->clearResults();      //   clear it out
   }
   //   given that we found terrain on our first try, let's move over and try again
   //   keep moving until we don't hit dirt no more :-)
   while (bFoundTerrain)
   {
      updateRay.setOrigin(Vector3(iX_Width, iY_Line, iZ_Line));
      updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
      raySceneQuery->setRay(updateRay);
      RaySceneQueryResult& qryResult = raySceneQuery->execute();
      RaySceneQueryResult::iterator i = qryResult.begin();

      if (i != qryResult.end() && i->worldFragment)
      {
         bFoundTerrain = true;
         iX_Width++;
         m_rOffsetX = m_rOffsetZ = iX_Width;
         raySceneQuery->clearResults();
      }
      else
      {
         bFoundTerrain = false;
      }
   }
}

ImageLoading the Ogre at terrain center -- after using offsets from this method.
User avatar
trilobite
Silver Sponsor
Silver Sponsor
 
Posts: 106
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA

Postby jacmoe » Thu Jul 13, 2006 9:41 pm

Maybe you are ready to be introduced to the Paging (Landscape) SceneManager? :)
/* when invited to a free lunch, you should not complain about the quality of the caviar */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, Fueled by Passion.
Ogre AppWizards - Ogre project wizards for VC8, VC9, VC10 and Code::Blocks.
User avatar
jacmoe
OGRE Moderator
OGRE Moderator
 
Posts: 17873
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark

Postby Estrich » Fri Jul 14, 2006 12:35 pm

There's a simpler way to get the terrain dimensions - the getOptions() method from the TerrainSceneManager is your friend:

http://www.ogre3d.org/docs/api/html/classOgre_1_1TerrainSceneManager.html#Ogre_1_1TerrainSceneManagera36

You can then use the info in the TerrainOptions to calculate the dimensions.

http://www.ogre3d.org/docs/api/html/classOgre_1_1TerrainOptions.html

I did the same in our game and would post code but I'm currently at work.
Estrich
Regular
 
Posts: 79
Joined: Fri Mar 31, 2006 7:51 pm
Location: Linz, Austria

yes, I tried the getOption method first

Postby trilobite » Fri Jul 14, 2006 4:42 pm

but I had no success.

If you had good results, I would like to see your implementation. If it works, it would be far easier and less hacky than the method I posted here.
User avatar
trilobite
Silver Sponsor
Silver Sponsor
 
Posts: 106
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA

More on this topic

Postby trilobite » Fri Jul 14, 2006 6:16 pm

The generic,SceneManager declares the following virtual function:
Code: Select all
virtual bool getOption( const String& strKey, void* pDestValue );

OctreeSceneManager is derived from SceneManager. And TerrainSceneManager is derived from OctreeSceneManager.

OctereeSceneManager implements a virtual getOption(...), and it tests for the following keys:
"Size"
"Depth"
"ShowOctree"
"CullCamera"

TerrainSceneManager is derrived from OctreeSceneManager but does not have its own implementation of getOption(...); Although TerrainSceneManager does implement a virtual setOption(...) which tests for the following keys:
"PageSize"
"TileSize"
"PrimaryCamera"
"MaxMipMap"
"Scale"
"MaxPixelError"
"UseTriStrips"
"VertexProgramMorph"
"DetailTile"
"LodMorphStart"
"VertexNormals"
"VertexColours"
"MorphLODFactorParamName"
"MorphLODFactorParamIndex"
"CustomMaterialName"
"WorldTexture"
"DetailTexture"

So, given the code as it is in the latest Dragion release, when my terrainSceneManager calls getOption(...), there is only one choice, and that is to the OctreeSceneManager's implementation. And that is my explanation as to why I cannot get the PageSize.

Given this situation, it is very simple to override getOption(..) in TerrainSceneManager to complement its own getOption(...) method. But, as I am new to Ogre, I am cautious about making code changes that I know won't be reflected in future code release. Hence, my workaround.

I hope others can show me the error of my ways...
User avatar
trilobite
Silver Sponsor
Silver Sponsor
 
Posts: 106
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA

OK, here is a much simpler implementation

Postby trilobite » Sat Jul 15, 2006 7:41 pm

Here is a simpler implementation based on the size of the bounding box assigned to the terrain.

If you implement this method in your app, ignore and remove the code that I originally posted.

OctereeSceneManager::getOption(...) DOES report on the size of the bounding box, so get it and set your offsets like so...

Code: Select all
   AxisAlignedBox   bBoundingBox;

   if (m_pSceneMgr->getOption("Size", &bBoundingBox))
   {
      Vector3 vecMin = bBoundingBox.getMinimum();
      Vector3 vecMax = bBoundingBox.getMaximum();
      m_rOffsetX = vecMax.x - vecMin.x;
      m_rOffsetZ = vecMax.z - vecMin.z;
   }

Once you have your terrain dimensions, you can use these values to determine terrain placement in your world, and also determine "Terrain Center".

:-)
User avatar
trilobite
Silver Sponsor
Silver Sponsor
 
Posts: 106
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA

Postby Estrich » Sun Jul 16, 2006 10:59 pm

Glad you found a nicer solution :)

Anyway here's my code as i promised:

Code: Select all
TerrainOptions GameScene::getTerrainOptions() {
  TerrainOptions terrainOpt = (static_cast<TerrainSceneManager*>(mSceneMgr))->getOptions();
  Real width = terrainOpt.scale.x * terrainOpt.pageSize;
  Real height = terrainOpt.scale.z * terrainOpt.pageSize;
}


That will get you the width and height of the terrain in ogre units.
Estrich
Regular
 
Posts: 79
Joined: Fri Mar 31, 2006 7:51 pm
Location: Linz, Austria


Return to Using OGRE in practice

Who is online

Users browsing this forum: No registered users and 1 guest