ObjectTitle

From Ogre Wiki

Jump to: navigation, search

Contents

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)

Personal tools
administration