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: Projecting 3D position and size to 2D
View page
Source of version: 6
(current)
One way to have HUD Elements like targeting indicators or playernames positioned on 3D objects is projecting the 3D position to 2D and positioning the HUD Elements there. The following code can be used to do that. {maketoc} !!!Projecting position {CODE(wrap="1", colors="c++")}using namespace Ogre; /// returns true if in front of the cam, and fills x,y with clamped screencoords in [-1;1] // cam->getProjectionMatrix() is cached inside ogre bool ProjectPos (Camera* cam,const Ogre::Vector3& pos,Ogre::Real& x,Ogre::Real& y) { Vector3 eyeSpacePos = cam->getViewMatrix(true) * pos; // z < 0 means in front of cam if (eyeSpacePos.z < 0) { // calculate projected pos Vector3 screenSpacePos = cam->getProjectionMatrix() * eyeSpacePos; x = screenSpacePos.x; y = screenSpacePos.y; return true; } else { x = (-eyeSpacePos.x > 0) ? -1 : 1; y = (-eyeSpacePos.y > 0) ? -1 : 1; return false; } }{CODE} !!!Projecting position and radius {CODE(wrap="1", colors="c++")}using namespace Ogre; /// returns true if in front of the cam, and fills x,y with clamped screencoords in [-1;1] /// and fills cx,cy with projected size on screen in [0;1] // cam->getProjectionMatrix() is cached inside ogre bool ProjectSizeAndPos (Camera* cam,const Ogre::Vector3& pos,const Ogre::Real rad,Ogre::Real& x,Ogre::Real& y,Ogre::Real& cx,Ogre::Real& cy) { Camera* cam = mCamera; Vector3 eyeSpacePos = cam->getViewMatrix(true) * pos; // z < 0 means in front of cam if (eyeSpacePos.z < 0) { // calculate projected pos Vector3 screenSpacePos = cam->getProjectionMatrix() * eyeSpacePos; x = screenSpacePos.x; y = screenSpacePos.y; // calculate projected size Vector3 spheresize(rad, rad, eyeSpacePos.z); spheresize = cam->getProjectionMatrix() * spheresize; cx = spheresize.x; cy = spheresize.y; return true; } else { cx = 0; cy = 0; x = (-eyeSpacePos.x > 0) ? -1 : 1; y = (-eyeSpacePos.y > 0) ? -1 : 1; return false; } }{CODE} !!!Notes * a return value of true just means in front of the cam, not visible on screen (e.g. it might be too far on left) * to check if the object is visible, check if the projected x,y are in [[-1;1] * to check if the object is partially visible, check if the projected x is in [[-1-cx/2;1+cx/2] (y analogue with cy) !!!Tracking a hierarchical position When tracking the position of a scenenode pMyChildNode that is the child of another scenenode pMyParentNode, probably SceneNode::getWorldPosition() should be used to get an absolute position. When only the position of pMyParentNode is updated, the pMyChildNode->getWorldPosition() will normally only be update after rendering a frame, this leads to the projected position lagging behind one frame. This can be prevented by either : * calling pMyChildNode->needUpdate() right before calculating the projected position * calling pMyParentNode->_update(/*bool updateChildren=*/true,/*bool parentHasChanged=*/false) when moving the parent * also pMyChildNode->setListener() can be used to install a listener that is called at a time where getWorldPosition() will return the correct position, so that could be a good place to recalculate the projected position, but it also depends on the camera position, it would also have to be updated every time the camera moves, so pCamera->setListener() will also be needed. The problem is that this way, the position will be recalculated twice if the cam and the parent change, if that happens every frame, it might be better to recalculate right before rendering a frame and using _update() or needUpdate() instead of the listeners. --- Alias: (alias(Projecting_3D_position_and_size_to_2D))
Search by Tags
Search Wiki by Freetags
Latest Changes
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
Critter AI
Mogre Add-ons
MOGRE
Mogre MyGUI wrapper
MOGRE Editable Terrain Manager
...more
Search
Find
Advanced
Search Help
Online Users
24 online users