ObjectTitle         Display a title (text overlay) above a MovableObject
Print

Yet Another?

I was having some wonky perspective issues with ObjectTextDisplay and I needed something that could automatically center the title-- so I decided to write my own solution. (See ObjectTitle::update for a walk-through of my approach).

The Code

ObjectTitle.h

#ifndef __ObjectTitle_H__
#define __ObjectTitle_H__
 
#include "Ogre.h"
 
class ObjectTitle
{
    const Ogre::MovableObject* object;
    const Ogre::Camera* camera;
    Ogre::Overlay* overlay;
    Ogre::OverlayElement* textArea;
    Ogre::OverlayContainer* container;
    Ogre::Vector2 textDim;
    Ogre::Font* font;
 
    Ogre::Vector2 getTextDimensions(Ogre::String text);
public:
 
    ObjectTitle(const Ogre::String& name, Ogre::MovableObject* object, Ogre::Camera* camera, const Ogre::String& title,
        const Ogre::String& fontName, const Ogre::ColourValue& color = Ogre::ColourValue::White);
 
    ~ObjectTitle();
 
    void setTitle(const Ogre::String& title);
 
    void update();
};
 
#endif

 

ObjectTitle.cpp

#include "ObjectTitle.h"
#include <OgreFontManager.h>
 
using namespace Ogre;
 
ObjectTitle::ObjectTitle(const String& name, MovableObject* object, Camera* camera, const String& title, 
    const String& fontName, const Ogre::ColourValue& color) : object(object), camera(camera)
{
    overlay = OverlayManager::getSingleton().create(name+"_TitleOverlay");
    container = (OverlayContainer*)OverlayManager::getSingleton().createOverlayElement("Panel", name+"_TitleContainer");
    overlay->add2D(container);
 
    textArea = OverlayManager::getSingleton().createOverlayElement("TextArea", name+"_TitleTextArea");
    textArea->setDimensions(0.8, 0.8);
    textArea->setMetricsMode(GMM_PIXELS);
    textArea->setPosition(0.1, 0.1);
 
    FontManager::getSingleton().load(fontName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
    font = (Font*)FontManager::getSingleton().getByName(fontName).getPointer();
    textArea->setParameter("font_name", fontName);
    textArea->setParameter("char_height", font->getParameter("size"));
    textArea->setParameter("horz_align", "left");
    textArea->setColour(color);
    textArea->setCaption(title);
 
    container->addChild(textArea);
    overlay->show();
 
    textDim = getTextDimensions(title);
    container->setDimensions(textDim.x, textDim.y);
}
 
ObjectTitle::~ObjectTitle()
{
    OverlayManager *overlayManager = OverlayManager::getSingletonPtr();
    container->removeChild(textArea->getName());
    overlay->remove2D(container);
    overlayManager->destroyOverlayElement(textArea);
    overlayManager->destroyOverlayElement(container);
    overlayManager->destroy(overlay);
}
 
void ObjectTitle::setTitle(const String& title)
{
    textArea->setCaption(title);
    textDim = getTextDimensions(title);
    container->setDimensions(textDim.x, textDim.y);
}
 
void ObjectTitle::update()
{
    if(!object->isInScene())
    {
        overlay->hide();
        return;
    }
 
    // Derive the average point between the top-most corners of the object's bounding box
    const Ogre::AxisAlignedBox &AABB = object->getWorldBoundingBox(true);
    Ogre::Vector3 point = (AABB.getCorner(AxisAlignedBox::FAR_LEFT_TOP)
        + AABB.getCorner(AxisAlignedBox::FAR_RIGHT_TOP)
        + AABB.getCorner(AxisAlignedBox::NEAR_LEFT_TOP)
        + AABB.getCorner(AxisAlignedBox::NEAR_RIGHT_TOP)) / 4;
 
    // Is the camera facing that point? If not, hide the overlay and return.
    Ogre::Plane cameraPlane = Plane(Vector3(camera->getDerivedOrientation().zAxis()), camera->getDerivedPosition());
    if(cameraPlane.getSide(point) != Plane::NEGATIVE_SIDE)
    {
        overlay->hide();
        return;
    }
 
    // Derive the 2D screen-space coordinates for that point
    point = camera->getProjectionMatrix() * (camera->getViewMatrix() * point);
 
    // Transform from coordinate space [-1, 1] to [0, 1]
    Real x = (point.x / 2) + 0.5f;
    Real y = 1 - ((point.y / 2) + 0.5f);
 
    // Update the position (centering the text)
    container->setPosition(x - (textDim.x / 2), y);
    overlay->show();
}
 
Vector2 ObjectTitle::getTextDimensions(String text)
{
    Real charHeight = StringConverter::parseReal(font->getParameter("size"));
 
    Vector2 result(0, 0);
 
    for(String::iterator i = text.begin(); i < text.end(); i++)
    {   
        if (*i == 0x0020)
            result.x += font->getGlyphAspectRatio(0x0030);
        else
            result.x += font->getGlyphAspectRatio(*i);
    }
 
    result.x = (result.x * charHeight) / (float)camera->getViewport()->getActualWidth();
    result.y = charHeight / (float)camera->getViewport()->getActualHeight();
 
    return result;
}

 
--Ajs15822? 08:08, 7 February 2008 (GMT)


Contributors to this page: jacmoe111451 points  and Ajs15822 .
Page last modified on Saturday 02 of January, 2010 05:42:24 GMT by jacmoe111451 points .


The content on this page is licensed under the terms of the Creative Commons Attribution-ShareAlike License.
As an exception, any source code contributed within the content is released into the Public Domain.