PnP TerrainCreator - Forum

The PnP TerrainCreator Forum
It is currently Tue Dec 12, 2017 8:04 am

All times are UTC




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: Ogre3D 1.7 export
PostPosted: Fri Jan 22, 2010 1:13 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
This is a guide for exporting a terrain made in PnP TerrainCreator to Ogre 1.7.

We are using demoterrain, and due to the limit of 6 image layers per terrain page in Ogre, we are going to retexture it, using the following 4 textures:
gras.jpg | slope: 0 - 50 | height: 35 - 20000
moos1.jpg | slope: 35 - 90 | height: 0 - 35
moos2.jpg | slope: 50 - 90
schlamm_getrocknet2.jpg | slope: 0 - 35 | height: 0 - 35

Use power of four textures!
The nVidia texture tool needs them to be of that size, eg 512.

Setup the texture plugin using the above automated texturing parameters, and retexture the terrain.

You should see something like this:
Attachment:
pnptc_terrain.jpg
pnptc_terrain.jpg [ 59.29 KiB | Viewed 7404 times ]

(Sorry about the lack of light)

The limit of 6 layers is when using a global light map and a normal map, and then diffuse/specular, normal/height maps for the layer textures.
A SM2 card has a limit of 16 texture units in one pass.
It is possible to write your own multi-pass material generator, though. Making it possible to use more textures.

Now we are going to export it to Ogre.

First, we need to export the heightmap.
Right-click on the terrain page and select the RAW heightmap export plugin, using the following settings:
Attachment:
heightmapExport.jpg
heightmapExport.jpg [ 13.64 KiB | Viewed 52595 times ]

This should give a full scale RAW heightmap file.

Next, we need to export the splatting maps.
Choose the alphamap export plugin, and use the following settings:
Attachment:
alphamapExport.jpg
alphamapExport.jpg [ 19.46 KiB | Viewed 52593 times ]

Would probably be a good idea to check power of two.

Should leave you with the following textures:
gras_00000_00000_000.PNG
moos1_00000_00000_000.PNG
moos2_00000_00000_000.PNG
schlamm_getrocknet2_00000_00000_000.PNG

Now, we need to turn the four diffuse textures into what the default Ogre terrain material generator expects:
diffuse_specular and normal_height.

Here's one way to generate those textures:

1) Get ShaderMap CL from http://www.shadermap.renderingsystems.com/
2) Create a bat file with the following contents:
Code:
CD "C:\Program Files\ShaderMap CL 1.2.2"

START /WAIT shadermap.exe cdiff "<texture_directory>\<texture_name>" -disp (60,100,12,xy) -norm (100,200,xy,0) -spec (100,-50,52,xy) -v


Replace the directory and texture name with what you want to generate maps for.

3) Generate the maps by running the bat script, once for each texture.

4) Use the following code to combine the images:
Code:
   Ogre::Image combined;

   combined.loadTwoImagesAsRGBA("moos1.jpg", "moos1_SPEC.bmp",
      Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::PF_BYTE_RGBA);
   combined.save("moos1_diffusespecular.png");

   combined.loadTwoImagesAsRGBA("moos1_NORM.tga", "moos1_DISP.bmp",
      Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::PF_BYTE_RGBA);
   combined.save("moos1_normalheight.png");

You need to have the 16 source texture somewhere in declared resource location, so just put a directory called terraintex in 'media' and add a line to resources.cfg so that Ogre picks it up, ie '../media/terraintex'

5) Get the nVidida texture tools (DDS Utilities) and convert the output textures to dds.
Place the generated png's in the ddsutilities directory, open up a console and run this:
Code:
nvdxt.exe -all -dxt3


6) Done. :wink:

Of course, you can replace step 4 with whatever method you have to load a greyscale map into the alphachannel, using Photoshop or the Gimp or any other tool.

Now we have a heightmap, a set of 8 textures and 4 alphamap textures.
And we are ready to load that into Ogre.

Code:
   // a light for the ligthmap
   Ogre::Vector3 lightdir(0, -0.3, 0.75);
   lightdir.normalise();
   Ogre::Light* l = sceneMgr->createLight("tstLight");
   l->setType(Ogre::Light::LT_DIRECTIONAL);
   l->setDirection(lightdir);
   l->setDiffuseColour(Ogre::ColourValue(1.0, 1.0, 1.0));
   l->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));
   sceneMgr->setAmbientLight(Ogre::ColourValue(0.6, 0.6, 0.6));

   // global terrain options
   Ogre::TerrainGlobalOptions::setMaxPixelError(1); // set to 1 if using 1 unit/1 metre (ie pagesize of 1024)
   Ogre::TerrainGlobalOptions::setCompositeMapDistance(2000);
   Ogre::TerrainGlobalOptions::setLightMapDirection(lightdir);
   Ogre::TerrainGlobalOptions::setCompositeMapAmbient(sceneMgr->getAmbientLight());
   Ogre::TerrainGlobalOptions::setCompositeMapDiffuse(l->getDiffuseColour());

   // create new instance of Ogre::Terrain
   mTerrain = OGRE_NEW Ogre::Terrain(sceneMgr);

   // load the heightmap from the RAW file
   Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource("demoraw.raw", "General" );
   size_t size = stream.get()->size();
   if(size != 1025 * 1025 * 4)
   {
      OGRE_EXCEPT( Ogre::Exception::ERR_INTERNAL_ERROR, "Size of stream does not match terrainsize!", "TerrainPage" );
   }
   float* buffer = OGRE_ALLOC_T(float, size, Ogre::MEMCATEGORY_GENERAL);
   stream->read(buffer, size);

   // import settings
   Ogre::Terrain::ImportData imp;
   imp.terrainSize = 1025;
   imp.worldSize = 1024;
   imp.inputFloat = buffer;
   imp.minBatchSize = 33;
   imp.maxBatchSize = 65;

   // textures
   imp.layerList.resize(4);
   imp.layerList[0].textureNames.push_back("gras_diffusespecular.dds");
   imp.layerList[0].textureNames.push_back("gras_normalheight.dds");
   imp.layerList[0].worldSize = 30;
   imp.layerList[1].textureNames.push_back("moos1_diffusespecular.dds");
   imp.layerList[1].textureNames.push_back("moos1_normalheight.dds");
   imp.layerList[1].worldSize = 30;
   imp.layerList[2].textureNames.push_back("schlamm_getrocknet2_diffusespecular.dds");
   imp.layerList[2].textureNames.push_back("schlamm_getrocknet2_normalheight.dds");
   imp.layerList[2].worldSize = 30;
   imp.layerList[3].textureNames.push_back("moos2_diffusespecular.dds");
   imp.layerList[3].textureNames.push_back("moos2_normalheight.dds");
   imp.layerList[3].worldSize = 20;

   mTerrain->prepare(imp);
   mTerrain->load();

   // blend maps (alphamaps)
   Ogre::String blendImages[4];
   blendImages[0] = "gras_00000_00000_000.PNG";
   blendImages[1] = "moos1_00000_00000_000.PNG";
   blendImages[2] = "schlamm_getrocknet2_00000_00000_000.PNG";
   blendImages[3] = "moos2_00000_00000_000.PNG";

   // load those blendmaps into the layers
   for(int j = 1;j < mTerrain->getLayerCount();j++)
   {
      Ogre::TerrainLayerBlendMap *blendmap = mTerrain->getLayerBlendMap(j);
      Ogre::Image img;
      img.load(blendImages[j],"General");
      int blendmapsize = mTerrain->getLayerBlendMapSize();
      if(img.getWidth() != blendmapsize)
         img.resize(blendmapsize, blendmapsize);

      float *ptr = blendmap->getBlendPointer();
      Ogre::uint8 *data = static_cast<Ogre::uint8*>(img.getPixelBox().data);

      for(int bp = 0;bp < blendmapsize * blendmapsize;bp++)
         ptr[bp] = static_cast<float>(data[bp]) / 255.0f;

      blendmap->dirty();
      blendmap->update();
   }

   // clean up
   mTerrain->freeTemporaryResources();

   // adjust the position of the terrain (Ogre uses the centre of the terrain as 0,0,0
   mTerrain->setPosition(Ogre::Vector3(512,0,512));


So, all we need is to compile and run our terrain application, and this is what we see:
Attachment:
screenshot01222010_152120213.jpg
screenshot01222010_152120213.jpg [ 105.03 KiB | Viewed 7406 times ]

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Last edited by jacmoe on Tue Feb 02, 2010 4:27 pm, edited 3 times in total.

Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Fri Jan 22, 2010 4:14 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
This tutorial is now written. :wink:

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Fri Jan 22, 2010 10:37 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
Notice that there are no configuration files here. Everything is done in code. :wink:
It's very flexible, so the route I took in the mini-tutorial isn't the only route.

I'll get back to this topic when the paging has been fully implemented, and give an example of exporting/importing multiple terrain pages.


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Mon Feb 01, 2010 2:23 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
I am almost ready to write a section on how to use multiple terrain pages with Ogre 1.7 - as soon as I've got a clean test application up, I'll update this topic.

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Mon Feb 01, 2010 3:17 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
One small request:

The Ogre scene exporter translates the y component by pagesize, because the Ogre 1.6 terrain has it's origin at the opposite corner of the terrain than PnPTC (x forward, z left)
However, the new terrain component has the origin at the centre.

Right now, I take that into account by manually adjusting object positions, like this:
Code:
Ogre::Vector3 adjust(pagesize * 0.5, 0, pagesize * 0.5);
Ogre::Vector3 house2_pos(111.603996, 1834.977295, 885.291992);
house2_pos -= adjust;

Then they match up with the terrain page.
Now, for each page, I do this:
Code:
        Ogre::Vector3 offset(Ogre::Vector3::ZERO);
   mTerrainPage->getTerrainGroup()->convertTerrainSlotToWorldPosition(1,0, &offset);
   house2_pos += offset;

That code converts the object position to world position.

Would be nice to have the option of choosing the origin. :)

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Mon Feb 01, 2010 9:51 pm 
Offline
Programmierdochfix
User avatar

Joined: Tue Apr 27, 2004 12:53 pm
Posts: 892
Location: Braunschweig
How do you export object positions? Do you use the ogre scene xml exporter? I could add such an option to it.


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Mon Feb 01, 2010 9:55 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
I use the Ogre scene exporter, and it's perfect. :)
The only thing I would want is the option of choosing between origin at the centre of the terrain, or at the corner (which is the current option)

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Mon Feb 01, 2010 9:57 pm 
Offline
Programmierdochfix
User avatar

Joined: Tue Apr 27, 2004 12:53 pm
Posts: 892
Location: Braunschweig
Ok, I'll add this option and post the updated exorter here.


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Mon Feb 01, 2010 10:04 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
It's at line 478 in PnPTCOgreSceneExportPlugin.cpp:
Code:
      
            // we need to move z pagesize units, since the terrain origin in Ogre3D is at x/z 0 with y up, whereas PnPTC is x/y 0 with z up.
            vecPos.z = iPatchSize - vecPos.z;

So it would probably be:
Code:
      
            vecPos.y = iPatchSize*0.5 - vecPos.y;
            vecPos.z = iPatchSize*0.5 - vecPos.z;


Or, even better:
Code:
            vecPos.y -= adjustVector;

Where the adjustVector is either (iPatchSize,0,0) or (iPatchSize*0.f,0,iPatchSize*0.5) - off the top of my head.
Not sure. :)

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Tue Feb 02, 2010 4:25 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
I just updated the mini-tutorial to using a max pixel-error of 1, instead of 8.
Otherwise the terrain will not be accurate enough for the default scale (1 metre to 1 unit). :)

If you're curious, here's the difference between a max pixel error of 8, and a max pixel error of 1:

Attachment:
File comment: Ogre::TerrainGlobalOptions::setMaxPixelError(8);
screenshot02012010_000505777.jpg
screenshot02012010_000505777.jpg [ 91.36 KiB | Viewed 7067 times ]


Attachment:
File comment: Ogre::TerrainGlobalOptions::setMaxPixelError(1);
screenshot02012010_151240458.jpg
screenshot02012010_151240458.jpg [ 94.11 KiB | Viewed 7194 times ]


So, a big difference. :)
Had me stumped for over a week, this one.

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Thu Jun 24, 2010 8:54 pm 
Offline
User avatar

Joined: Mon Dec 22, 2008 8:24 pm
Posts: 64
Location: Denmark
Could you please fix the images?

There's absolutely no use in putting a lot of work into making a tutorial and uploading images when they're not kept...

_________________
/* when invited to a free lunch, you should not complain about the quality of the caviar */


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Fri Jun 25, 2010 2:22 pm 
Offline
Programmierdochfix
User avatar

Joined: Tue Apr 27, 2004 12:53 pm
Posts: 892
Location: Braunschweig
Sorry for this, we moved to a new server a couple of days ago. As it seems, some of the attachment files got lost on the way. I restored them; so all images should be back again.


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Wed Nov 21, 2012 7:59 pm 
Offline

Joined: Sun Nov 18, 2012 10:23 pm
Posts: 2
Thank you very much for this nice tutorial.
I can follow it without problems and get my terrain loaded in Ogre, except for the blendmaps :cry:

When executing the following codeline I get an exception:
Code:
Ogre::TerrainLayerBlendMap *blendmap = mTerrain->getLayerBlendMap(j);


The exception in Ogre.log is:
Quote:
20:41:58: OGRE EXCEPTION(2:InvalidParametersException): Invalid layer index in Terrain::getLayerBlendMap at ..\..\..\..\..\Components\Terrain\src\OgreTerrain.cpp (line 2547)


I ripped off the for-loop and tried with single testlines:
Quote:
Ogre::TerrainLayerBlendMap *blendmap = mTerrain->getLayerBlendMap(0);
Ogre::TerrainLayerBlendMap *blendmap = mTerrain->getLayerBlendMap(1);


Both give me same OGRE exception :(

I'm also wondering a little bit about your "for" loop:
You start with "i=1". However you also use "i" as index for the blendmaps string array (Ogre::String blendImages[4];).
But this is zero-based.. so you never access index 0 at this line?:
Code:
img.load(blendImages[j],"General");


This is the full block I'm struggling with:
Code:
   // load those blendmaps into the layers
   for(int j = 1;j < mTerrain->getLayerCount();j++)
   {
      Ogre::TerrainLayerBlendMap *blendmap = mTerrain->getLayerBlendMap(j);
      Ogre::Image img;
      img.load(blendImages[j],"General");
      int blendmapsize = mTerrain->getLayerBlendMapSize();
      if(img.getWidth() != blendmapsize)
         img.resize(blendmapsize, blendmapsize);

      float *ptr = blendmap->getBlendPointer();
      Ogre::uint8 *data = static_cast<Ogre::uint8*>(img.getPixelBox().data);

      for(int bp = 0;bp < blendmapsize * blendmapsize;bp++)
         ptr[bp] = static_cast<float>(data[bp]) / 255.0f;

      blendmap->dirty();
      blendmap->update();
   }


I'm using the Ogre 1.7.4 SDK and a command-line test which contains like 100% of your tutorial code (+ some missing parts like creating the Ogre root)
Thx for help :-)

EDIT:
Ok. Guess I misunderstood it... I get it now :-)
But this might be also still useful for someone else.
The problem was that I was just using a single texture-layer (I thought: keep it simple, haha, bad thing this time).
It seems the first layer is the "default" layer? so it doesn't have a blendmap?
Cause as soon as I added another layer, I was able to do this without problems:
Quote:
terrain->getLayerBlendMap(1);


That also explains why you are using the "i=1" loop.


Top
 Profile  
 
 Post subject: Re: Ogre3D 1.7 export
PostPosted: Wed Nov 21, 2012 9:21 pm 
Offline

Joined: Sun Nov 18, 2012 10:23 pm
Posts: 2
There is still one thing that doesn't work for me from this tutorial :(

I can now add the blendmaps, however because the blendmap codeblock only applies the blendmaps for the texture layers 1 and above,
my "default" layer at [0] shows the first added texture, which is the specular texture:

in this tutorial it would be the ""gras_diffusespecular.dds"":
Code:
imp.layerList[0].textureNames.push_back("gras_diffusespecular.dds");
imp.layerList[0].textureNames.push_back("gras_normalheight.dds");


I can change this by just adding the default/nonsplit texture at layer 0, instead of the diffuse and specular ones, like:
Code:
imp.layerList[0].textureNames.push_back("gras.dds");


But is this correct?

Thanks


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron