Skip to main content

History: BloodyMess Ogre::Terrain Heightfield

Source of version: 6 (current)

Copy to clipboard
            {INCLUDE(page="BloodyMess tpl")}{INCLUDE}

%help%~hs~__Help:__ For any problems you encounter while working with these code, please visit the [http://www.ogre3d.org/addonforums/viewtopic.php?f=6&t=10859|thread in the NxOgre forum].

!!{img src="img/wiki_up/NxOgreCube.png" alt="NxOgreCube.png"} BloodyMess Ogre::Terrain heightfield
This code shows how to create a matching heightfield from the new Ogre::Terrain, a new feature in Ogre 1.7.

It does everything in realtime, so there is no need to use flour to create an .xhf or flip and rotate the ((-Height Map|heightmap)).

Thanks to XpLoDWilD for solving an issue with vertex under the origin.

{CODE(wrap="1", colors="c++")}void loadTerrainGeometry(const Ogre::String& name, float* data, Ogre::uint16 size, Ogre::Real worldSize, Ogre::Real minHeight, Ogre::Real maxHeight, const Ogre::Vector3& position)
{
	// Create the manual heightfield
	NxOgre::ManualHeightField *mhf = OGRE_NEW_T(NxOgre::ManualHeightField, Ogre::MEMCATEGORY_GENERAL)();
	mhf->begin(size, size);
	Ogre::Real normMin = -32768.0f;
	Ogre::Real normMax = 32767.0f;
	// Sample the data to the manual heightfield
	for(int x = 0; x < size; ++x)
	{
		NxOgre::Enums::HeightFieldTesselation tess = NxOgre::Enums::HeightFieldTesselation_NW_SE;
		for(int z = size-1; z >= 0; --z)
		{
			Ogre::Real height = data[(size * z) + x];
			short sample = (short)(((height - minHeight) / (maxHeight - minHeight)) * (normMax - normMin) + normMin);
			mhf->sample(sample, 0, 0, tess);
			if(tess == NxOgre::Enums::HeightFieldTesselation_NE_SW)
				tess = NxOgre::Enums::HeightFieldTesselation_NW_SE;
			else
				tess = NxOgre::Enums::HeightFieldTesselation_NE_SW;
		}
	}
	// Create the actual heightfield
	NxOgre::HeightField *hf = mhf->end(name.c_str());
	Ogre::Real hf_size = worldSize + (worldSize / size);
	Ogre::Real hf_height = (maxHeight - minHeight) / 2.0f;
	Ogre::Real hf_pose_x = position.x - (worldSize / 2.0f);
	Ogre::Real hf_pose_y = position.y + ((maxHeight + minHeight) / 2.0f);
	Ogre::Real hf_pose_z = position.z - (worldSize / 2.0f);
#if NxOgreVersionMajor <= 1 && NxOgreVersionMinor <= 5
	NxOgre::HeightFieldGeometry* hfg = new NxOgre::HeightFieldGeometry(hf, NxOgre::Vec3(hf_size, hf_height, hf_size));
	hfg->setLocalPose(NxOgre::Matrix44(NxOgre::Vec3(hf_pose_x, hf_pose_y, hf_pose_z)));
	mScene->createSceneGeometry(hfg);
#else
	NxOgre::HeightFieldGeometryDescription desc(hf, NxOgre::Vec3(hf_size, hf_height, hf_size));
	mScene->createSceneGeometry(desc, NxOgre::Matrix44(NxOgre::Vec3(hf_pose_x, hf_pose_y, hf_pose_z)));
#endif
	// Free memory
	OGRE_DELETE_T(mhf, ManualHeightField, Ogre::MEMCATEGORY_GENERAL);
}{CODE}

You can use it like that, with "terrain" being a pointer to your Ogre::Terrain.
{CODE(wrap="1", colors="c++")}loadTerrainGeometry(terrain->getMaterialName(), terrain->getHeightData(), terrain->getSize(),
	terrain->getWorldSize(), terrain->getMinHeight(), terrain->getMaxHeight(), terrain->getPosition());{CODE}
Or you can supply the data yourself.

{INCLUDE(page="NxOgre tpl")}{INCLUDE}
---
Alias: (alias(BloodyMess_Ogre::Terrain_Heightfield))