OGRE Wiki
Support and community documentation for Ogre3D
Ogre Forums
ogre3d.org
Log in
Username:
Password:
CapsLock is on.
Remember me (for 1 year)
Log in
Home
Tutorials
Tutorials Home
Basic Tutorials
Intermediate Tutorials
Mad Marx Tutorials
In Depth Tutorials
Older Tutorials
External Tutorials
Cookbook
Cookbook Home
CodeBank
Snippets
Experiences
Ogre Articles
Libraries
Libraries Home
Alternative Languages
Assembling A Toolset
Development Tools
OGRE Libraries
List of Libraries
Tools
Tools Home
DCC Tools
DCC Tutorials
DCC Articles
DCC Resources
Assembling a production pipeline
Development
Development Home
Roadmap
Building Ogre
Installing the Ogre SDK
Setting Up An Application
Ogre Wiki Tutorial Framework
Frequently Asked Questions
Google Summer Of Code
Help Requested
Ogre Core Articles
Community
Community Home
Projects Using Ogre
Recommended Reading
Contractors
Wiki
Immediate Wiki Tasklist
Wiki Ideas
Wiki Guidelines
Article Writing Guidelines
Wiki Styles
Wiki Page Tracker
Ogre Wiki Help
Ogre Wiki Help Overview
Help - Basic Syntax
Help - Images
Help - Pages and Structures
Help - Wiki Plugins
Toolbox
Freetags
Categories
List Pages
Structures
Trackers
Statistics
Rankings
List Galleries
Ogre Lexicon
Comments
History: Getting Surface Normals for Ogre 1.7 terrain
View page
Source of version: 3
(current)
After spending a couple of hours yesterday looking for a guide on how to generate surface normals for the new terrain system in Ogre 1.7, I realized that there is very little information. So after a couple of hours worth of playing with the new terrain functions, I believe that I've found a better solution than the standard raycasting method and would like to share my findings. the following code block uses my own environment manager class to get the loaded terrain, you must change it to return a pointer to your loaded terrain {CODE()} Ogre::Image image; Ogre::Terrain* terrain; terrain = GameServices::EnvironmentManager()->GetTerrainGroup()->getTerrain(0,0); //0,0 is where my terrain was created terrain->getTerrainNormalMap()->convertToImage(image); {CODE} this is optional if you would like to save your terrain to an image file to visually verify its correctness, or to simply be able to load it from a file rather than generate it each time you run your game. The second parameter in the load function is the resource group under which the image has been loaded, be sure to change this as necessary for your application. {CODE()} image.save("normalMap.png"); image.load("normalMap.png", "General"); {CODE} a 2d image only has two axes, no height, so we use x and z coords (y is height) {CODE()} Ogre::Vector3 posVec(m_sceneNode->getPosition().x, m_sceneNode()->getPosition().z,0); Ogre::ColourValue tempColor = image.getColourAt(posVec.x, posVec.y, 0); {CODE} RGB values map a surface normal from 0 to 1, however valid normal axis values are -1.0 to 1.0, so we convert from one coordinate system to another {CODE()} Ogre::Vector3 normal((tempColor.r*2.0f)-1.0f, (tempColor.g*2.0f)-1.0f,(tempColor.b*2.0f)-1.0f); {CODE} !!Orient an Object to the Terrain __At this point you have your surface normal, the following code may or may not be useful to you__ this will give you the axis directly to the right of your current position __CAUTION: this is not the vector you are looking for if the surface normal is the UNIT_Y, be sure to check for this beforehand__ {CODE()} Ogre::Vector3 right = normal.crossProduct(Ogre::Vector3::UNIT_Y); {CODE} gives you a forward vector from the right vector {CODE()} Ogre::Vector3 forward = right.crossProduct(normal);{CODE} If you have a rough terrain and need to smooth out the transitions as your scene node moves along the terrain, an alternate method is to use a weighted system for calculating the new normal prior to orienting your object: {CODE()} Quaternion currentOrientation = sceneNode->getOrientation(); Vector3 localY = currentOrientation.yAxis(); float weight = 0.10; // Weight of the new normal Vector3 newNormal = localY * ( 1 - weight ) + terrainNormal * weight; Ogre::Radian inclinationAngle = Math::ACos(localY.dotProduct(newNormal)); if(inclinationAngle.valueRadians() != 0.0f) { Vector3 inclinationAxis = ( localY.crossProduct( newNormal) ).normalisedCopy(); Quaternion inclination = Quaternion(inclinationAngle, inclinationAxis); // Can't just call rotate, have to multiply inclination first or things get a little crazy //sceneNode->rotate(inclination); sceneNode->setOrientation( inclination * currentOrientation ); } {CODE} Play around with weight. Setting it very small will rotate your object more slowly. This is still a linear approach, so it's only useful for smoothing it out a bit. If you want it to simulate torque due to gravity, you'll have to get a little more fancy.
Search by Tags
Search Wiki by Freetags
Latest Changes
Ogre 2.1 FAQ
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
Critter AI
Mogre Add-ons
MOGRE
Mogre MyGUI wrapper
...more
Search
Find
Advanced
Search Help
Online Users
144 online users