772 lines
21 KiB
C++
772 lines
21 KiB
C++
|
/*
|
||
|
* Copyright (C) 2012 Open Source Robotics Foundation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
*/
|
||
|
/**
|
||
|
* File: MovableText.cpp
|
||
|
*
|
||
|
* description: This create create a billboarding object that display a text.
|
||
|
*
|
||
|
* @author 2003 by cTh see gavocanov@rambler.ru
|
||
|
* @update 2006 by barraq see nospam@barraquand.com
|
||
|
* @update 2007 by independentCreations see independentCreations@gmail.com
|
||
|
*/
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
// Ensure that windows types like LONGLONG are defined
|
||
|
#include <windows.h>
|
||
|
#endif
|
||
|
|
||
|
#include <boost/thread/recursive_mutex.hpp>
|
||
|
|
||
|
#include "gazebo/common/common.hh"
|
||
|
#include "gazebo/common/Assert.hh"
|
||
|
#include "gazebo/math/gzmath.hh"
|
||
|
#include "gazebo/rendering/MovableText.hh"
|
||
|
|
||
|
#define POS_TEX_BINDING 0
|
||
|
#define COLOUR_BINDING 1
|
||
|
|
||
|
using namespace gazebo;
|
||
|
using namespace rendering;
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
MovableText::MovableText()
|
||
|
: camera(NULL),
|
||
|
renderWindow(NULL) ,
|
||
|
font(NULL) ,
|
||
|
viewportAspectCoef(0.75),
|
||
|
spaceWidth(0) ,
|
||
|
updateColors(true) ,
|
||
|
vertAlign(V_BELOW) ,
|
||
|
horizAlign(H_LEFT) ,
|
||
|
onTop(false) ,
|
||
|
baseline(0.0)
|
||
|
{
|
||
|
this->renderOp.vertexData = NULL;
|
||
|
|
||
|
this->dirty = true;
|
||
|
this->mutex = new boost::recursive_mutex();
|
||
|
this->aabb = new Ogre::AxisAlignedBox;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
MovableText::~MovableText()
|
||
|
{
|
||
|
delete this->renderOp.vertexData;
|
||
|
delete this->mutex;
|
||
|
delete this->aabb;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::Load(const std::string &name_,
|
||
|
const std::string &text_,
|
||
|
const std::string &fontName_,
|
||
|
float charHeight_,
|
||
|
const common::Color &color_)
|
||
|
{
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
this->text = text_;
|
||
|
this->color = color_;
|
||
|
this->fontName = fontName_;
|
||
|
this->charHeight = charHeight_;
|
||
|
this->mName = name_;
|
||
|
|
||
|
if (this->mName == "")
|
||
|
throw Ogre::Exception(Ogre::Exception::ERR_INVALIDPARAMS,
|
||
|
"Trying to create MovableText without name",
|
||
|
"MovableText::MovableText");
|
||
|
|
||
|
if (this->text == "")
|
||
|
throw Ogre::Exception(Ogre::Exception::ERR_INVALIDPARAMS,
|
||
|
"Trying to create MovableText without text",
|
||
|
"MovableText::MovableText");
|
||
|
|
||
|
this->dirty = true;
|
||
|
}
|
||
|
|
||
|
this->SetFontName(this->fontName);
|
||
|
|
||
|
this->_setupGeometry();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::Update()
|
||
|
{
|
||
|
if (this->dirty)
|
||
|
{
|
||
|
this->_setupGeometry();
|
||
|
this->dirty = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetFontName(const std::string &newFontName)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
if ((Ogre::MaterialManager::getSingletonPtr()->resourceExists(
|
||
|
this->mName + "Material")))
|
||
|
{
|
||
|
Ogre::MaterialManager::getSingleton().remove(this->mName + "Material");
|
||
|
}
|
||
|
|
||
|
if (this->fontName != newFontName || this->material.isNull() || !this->font)
|
||
|
{
|
||
|
this->fontName = newFontName;
|
||
|
|
||
|
this->font = (Ogre::Font*)Ogre::FontManager::getSingleton().getByName(
|
||
|
this->fontName).getPointer();
|
||
|
|
||
|
if (!this->font)
|
||
|
{
|
||
|
throw Ogre::Exception(Ogre::Exception::ERR_ITEM_NOT_FOUND,
|
||
|
"Could not find font " + fontName,
|
||
|
"MovableText::setFontName");
|
||
|
}
|
||
|
|
||
|
this->font->load();
|
||
|
|
||
|
if (!this->material.isNull())
|
||
|
{
|
||
|
Ogre::MaterialManager::getSingletonPtr()->remove(
|
||
|
this->material->getName());
|
||
|
this->material.setNull();
|
||
|
}
|
||
|
|
||
|
this->material = this->font->getMaterial()->clone(this->mName + "Material");
|
||
|
|
||
|
if (!this->material->isLoaded())
|
||
|
this->material->load();
|
||
|
|
||
|
this->material->setDepthCheckEnabled(!this->onTop);
|
||
|
this->material->setDepthBias(!this->onTop, 0);
|
||
|
this->material->setDepthWriteEnabled(this->onTop);
|
||
|
this->material->setLightingEnabled(false);
|
||
|
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetText(const std::string &newText)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
if (this->text != newText)
|
||
|
{
|
||
|
this->text = newText;
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetColor(const common::Color &newColor)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
if (this->color != newColor)
|
||
|
{
|
||
|
this->color = newColor;
|
||
|
this->updateColors = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetCharHeight(float _height)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
if (!math::equal(this->charHeight, _height))
|
||
|
{
|
||
|
this->charHeight = _height;
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetSpaceWidth(float _width)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
if (!math::equal(this->spaceWidth, _width))
|
||
|
{
|
||
|
this->spaceWidth = _width;
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetTextAlignment(const HorizAlign &h, const VertAlign &v)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
if (this->horizAlign != h)
|
||
|
{
|
||
|
this->horizAlign = h;
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
|
||
|
if (this->vertAlign != v)
|
||
|
{
|
||
|
this->vertAlign = v;
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetBaseline(float _base)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
if (!math::equal(this->baseline, _base))
|
||
|
{
|
||
|
this->baseline = _base;
|
||
|
this->needUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::SetShowOnTop(bool show)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
if (this->onTop != show && !this->material.isNull())
|
||
|
{
|
||
|
this->onTop = show;
|
||
|
|
||
|
this->material->setDepthBias(!this->onTop, 0);
|
||
|
this->material->setDepthCheckEnabled(!this->onTop);
|
||
|
this->material->setDepthWriteEnabled(this->onTop);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
bool MovableText::GetShowOnTop() const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return this->onTop;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
math::Box MovableText::GetAABB(void)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return math::Box(
|
||
|
math::Vector3(this->aabb->getMinimum().x,
|
||
|
this->aabb->getMinimum().y,
|
||
|
this->aabb->getMinimum().z),
|
||
|
math::Vector3(this->aabb->getMaximum().x,
|
||
|
this->aabb->getMaximum().y,
|
||
|
this->aabb->getMaximum().z));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::_setupGeometry()
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
GZ_ASSERT(this->font, "font class member is null");
|
||
|
GZ_ASSERT(!this->material.isNull(), "material class member is null");
|
||
|
|
||
|
Ogre::VertexDeclaration *decl = NULL;
|
||
|
Ogre::VertexBufferBinding *bind = NULL;
|
||
|
Ogre::HardwareVertexBufferSharedPtr ptbuf;
|
||
|
Ogre::HardwareVertexBufferSharedPtr cbuf;
|
||
|
float *pVert = NULL;
|
||
|
float largestWidth = 0;
|
||
|
float left = 0;
|
||
|
float top = 0;
|
||
|
size_t offset = 0;
|
||
|
float maxSquaredRadius = 0.0f;
|
||
|
bool first = true;
|
||
|
std::string::iterator i;
|
||
|
bool newLine = true;
|
||
|
float len = 0.0f;
|
||
|
|
||
|
// for calculation of AABB
|
||
|
Ogre::Vector3 min(0, 0, 0);
|
||
|
Ogre::Vector3 max(0, 0, 0);
|
||
|
Ogre::Vector3 currPos(0, 0, 0);
|
||
|
|
||
|
unsigned int vertexCount = static_cast<unsigned int>(this->text.size() * 6);
|
||
|
|
||
|
|
||
|
if (this->renderOp.vertexData)
|
||
|
{
|
||
|
// Removed this test as it causes problems when replacing a caption
|
||
|
// of the same size: replacing "Hello" with "hello"
|
||
|
// as well as when changing the text alignment
|
||
|
// if (this->renderOp.vertexData->vertexCount != vertexCount)
|
||
|
{
|
||
|
delete this->renderOp.vertexData;
|
||
|
this->renderOp.vertexData = NULL;
|
||
|
this->updateColors = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!this->renderOp.vertexData)
|
||
|
this->renderOp.vertexData = new Ogre::VertexData();
|
||
|
|
||
|
this->renderOp.indexData = 0;
|
||
|
this->renderOp.vertexData->vertexStart = 0;
|
||
|
this->renderOp.vertexData->vertexCount = vertexCount;
|
||
|
this->renderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
|
||
|
this->renderOp.useIndexes = false;
|
||
|
|
||
|
decl = this->renderOp.vertexData->vertexDeclaration;
|
||
|
bind = this->renderOp.vertexData->vertexBufferBinding;
|
||
|
|
||
|
// create/bind positions/tex.ccord. buffer
|
||
|
if (!decl->findElementBySemantic(Ogre::VES_POSITION))
|
||
|
decl->addElement(POS_TEX_BINDING, offset, Ogre::VET_FLOAT3,
|
||
|
Ogre::VES_POSITION);
|
||
|
|
||
|
offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
|
||
|
|
||
|
if (!decl->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES))
|
||
|
decl->addElement(POS_TEX_BINDING, offset, Ogre::VET_FLOAT2,
|
||
|
Ogre::VES_TEXTURE_COORDINATES, 0);
|
||
|
|
||
|
ptbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
|
||
|
decl->getVertexSize(POS_TEX_BINDING),
|
||
|
this->renderOp.vertexData->vertexCount,
|
||
|
Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
|
||
|
|
||
|
bind->setBinding(POS_TEX_BINDING, ptbuf);
|
||
|
|
||
|
// Colours - store these in a separate buffer because they change less often
|
||
|
if (!decl->findElementBySemantic(Ogre::VES_DIFFUSE))
|
||
|
decl->addElement(COLOUR_BINDING, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
|
||
|
|
||
|
cbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
|
||
|
decl->getVertexSize(COLOUR_BINDING),
|
||
|
this->renderOp.vertexData->vertexCount,
|
||
|
Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
|
||
|
|
||
|
bind->setBinding(COLOUR_BINDING, cbuf);
|
||
|
|
||
|
pVert = static_cast<float*>(ptbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
|
||
|
|
||
|
// Derive space width from a capital A
|
||
|
if (math::equal(this->spaceWidth, 0.0f))
|
||
|
this->spaceWidth =
|
||
|
this->font->getGlyphAspectRatio('A') * this->charHeight * 2.0;
|
||
|
|
||
|
if (this->vertAlign == MovableText::V_ABOVE)
|
||
|
{
|
||
|
// Raise the first line of the caption
|
||
|
top += this->charHeight;
|
||
|
|
||
|
for (i = this->text.begin(); i != this->text.end(); ++i)
|
||
|
{
|
||
|
if (*i == '\n')
|
||
|
top += this->charHeight * 2.0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = this->text.begin(); i != this->text.end(); ++i)
|
||
|
{
|
||
|
if (newLine)
|
||
|
{
|
||
|
len = 0.0;
|
||
|
for (std::string::iterator j = i; j != this->text.end(); ++j)
|
||
|
{
|
||
|
Ogre::Font::CodePoint character = *j;
|
||
|
if (character == 0x000D // CR
|
||
|
|| character == 0x0085) // NEL
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
else if (character == 0x0020) // space
|
||
|
{
|
||
|
len += this->spaceWidth;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
len += this->font->getGlyphAspectRatio(character) *
|
||
|
this->charHeight * 2.0 * this->viewportAspectCoef;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
newLine = false;
|
||
|
}
|
||
|
|
||
|
Ogre::Font::CodePoint character = (*i);
|
||
|
|
||
|
if (character == 0x000D // CR
|
||
|
|| character == 0x0085) // NEL
|
||
|
{
|
||
|
top -= this->charHeight * 2.0;
|
||
|
newLine = true;
|
||
|
|
||
|
// Also reduce tri count
|
||
|
this->renderOp.vertexData->vertexCount -= 6;
|
||
|
continue;
|
||
|
}
|
||
|
else if (character == 0x0020) // space
|
||
|
{
|
||
|
// Just leave a gap, no tris
|
||
|
left += this->spaceWidth;
|
||
|
|
||
|
// Also reduce tri count
|
||
|
this->renderOp.vertexData->vertexCount -= 6;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
float horiz_height = this->font->getGlyphAspectRatio(character) *
|
||
|
this->viewportAspectCoef;
|
||
|
|
||
|
const Ogre::Font::UVRect& uvRect = this->font->getGlyphTexCoords(character);
|
||
|
|
||
|
// each vert is (x, y, z, u, v)
|
||
|
//------------------------------------------------------------------------
|
||
|
// First tri
|
||
|
//
|
||
|
// Upper left
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
*pVert++ = left;
|
||
|
else
|
||
|
*pVert++ = left - (len/2.0);
|
||
|
|
||
|
*pVert++ = top;
|
||
|
*pVert++ = 0;
|
||
|
*pVert++ = uvRect.left;
|
||
|
*pVert++ = uvRect.top;
|
||
|
|
||
|
// Deal with bounds
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
currPos = Ogre::Vector3(left, top, 0);
|
||
|
else
|
||
|
currPos = Ogre::Vector3(left - (len/2.0), top, 0);
|
||
|
|
||
|
if (first)
|
||
|
{
|
||
|
min = max = currPos;
|
||
|
maxSquaredRadius = currPos.squaredLength();
|
||
|
first = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
min.makeFloor(currPos);
|
||
|
max.makeCeil(currPos);
|
||
|
maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
|
||
|
}
|
||
|
|
||
|
top -= this->charHeight * 2.0;
|
||
|
|
||
|
// Bottom left
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
*pVert++ = left;
|
||
|
else
|
||
|
*pVert++ = left - (len / 2.0);
|
||
|
|
||
|
*pVert++ = top;
|
||
|
*pVert++ = 0;
|
||
|
*pVert++ = uvRect.left;
|
||
|
*pVert++ = uvRect.bottom;
|
||
|
|
||
|
// Deal with bounds
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
currPos = Ogre::Vector3(left, top, 0);
|
||
|
else
|
||
|
currPos = Ogre::Vector3(left - (len/2), top, 0);
|
||
|
|
||
|
min.makeFloor(currPos);
|
||
|
max.makeCeil(currPos);
|
||
|
maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
|
||
|
|
||
|
|
||
|
top += this->charHeight * 2.0;
|
||
|
left += horiz_height * this->charHeight * 2.0;
|
||
|
|
||
|
// Top right
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
*pVert++ = left;
|
||
|
else
|
||
|
*pVert++ = left - (len/2.0);
|
||
|
|
||
|
*pVert++ = top;
|
||
|
*pVert++ = 0;
|
||
|
*pVert++ = uvRect.right;
|
||
|
*pVert++ = uvRect.top;
|
||
|
|
||
|
// Deal with bounds
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
currPos = Ogre::Vector3(left, top, 0);
|
||
|
else
|
||
|
currPos = Ogre::Vector3(left - (len/2), top, 0);
|
||
|
|
||
|
min.makeFloor(currPos);
|
||
|
max.makeFloor(currPos);
|
||
|
maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
// Second tri
|
||
|
//
|
||
|
// Top right (again)
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
*pVert++ = left;
|
||
|
else
|
||
|
*pVert++ = left - (len/2.0);
|
||
|
*pVert++ = top;
|
||
|
*pVert++ = 0;
|
||
|
*pVert++ = uvRect.right;
|
||
|
*pVert++ = uvRect.top;
|
||
|
|
||
|
// Deal with bounds
|
||
|
currPos = Ogre::Vector3(left, top, 0);
|
||
|
min.makeFloor(currPos);
|
||
|
max.makeFloor(currPos);
|
||
|
maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
|
||
|
|
||
|
|
||
|
top -= this->charHeight * 2.0;
|
||
|
left -= horiz_height * this->charHeight * 2.0;
|
||
|
|
||
|
// Bottom left (again)
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
*pVert++ = left;
|
||
|
else
|
||
|
*pVert++ = left - (len/2.0);
|
||
|
*pVert++ = top;
|
||
|
*pVert++ = 0;
|
||
|
*pVert++ = uvRect.left;
|
||
|
*pVert++ = uvRect.bottom;
|
||
|
|
||
|
// Deal with bounds
|
||
|
currPos = Ogre::Vector3(left, top, 0);
|
||
|
min.makeFloor(currPos);
|
||
|
max.makeFloor(currPos);
|
||
|
maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
|
||
|
|
||
|
|
||
|
left += horiz_height * this->charHeight * 2.0;
|
||
|
|
||
|
// Bottom right
|
||
|
if (this->horizAlign == MovableText::H_LEFT)
|
||
|
*pVert++ = left;
|
||
|
else
|
||
|
*pVert++ = left - (len/2.0);
|
||
|
*pVert++ = top;
|
||
|
*pVert++ = 0;
|
||
|
*pVert++ = uvRect.right;
|
||
|
*pVert++ = uvRect.bottom;
|
||
|
|
||
|
// Deal with bounds
|
||
|
currPos = Ogre::Vector3(left, top, 0);
|
||
|
min.makeFloor(currPos);
|
||
|
max.makeFloor(currPos);
|
||
|
maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength());
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
// Go back up with top
|
||
|
top += this->charHeight * 2.0;
|
||
|
|
||
|
float currentWidth = (left + 1.0)/2.0;
|
||
|
if (currentWidth > largestWidth)
|
||
|
{
|
||
|
largestWidth = currentWidth;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Unlock vertex buffer
|
||
|
ptbuf->unlock();
|
||
|
|
||
|
|
||
|
|
||
|
// update AABB/Sphere radius
|
||
|
this->aabb->setMinimum(min);
|
||
|
this->aabb->setMaximum(max);
|
||
|
this->radius = Ogre::Math::Sqrt(maxSquaredRadius);
|
||
|
|
||
|
if (this->updateColors)
|
||
|
this->_updateColors();
|
||
|
|
||
|
this->needUpdate = false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::_updateColors(void)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
Ogre::RGBA clr;
|
||
|
Ogre::HardwareVertexBufferSharedPtr vbuf;
|
||
|
Ogre::RGBA *pDest = NULL;
|
||
|
unsigned int i;
|
||
|
|
||
|
GZ_ASSERT(this->font, "font class member is null");
|
||
|
GZ_ASSERT(!this->material.isNull(), "material class member is null");
|
||
|
|
||
|
// Convert to system-specific
|
||
|
Ogre::ColourValue cv(this->color.r, this->color.g,
|
||
|
this->color.b, this->color.a);
|
||
|
Ogre::Root::getSingleton().convertColourValue(cv, &clr);
|
||
|
|
||
|
vbuf = this->renderOp.vertexData->vertexBufferBinding->getBuffer(
|
||
|
COLOUR_BINDING);
|
||
|
|
||
|
pDest = static_cast<Ogre::RGBA*>(
|
||
|
vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
|
||
|
|
||
|
for (i = 0; i < this->renderOp.vertexData->vertexCount; ++i)
|
||
|
{
|
||
|
*pDest++ = clr;
|
||
|
}
|
||
|
|
||
|
vbuf->unlock();
|
||
|
this->updateColors = false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Ogre::Quaternion & MovableText::getWorldOrientation(void) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
GZ_ASSERT(this->camera, "camera class member is null");
|
||
|
return const_cast<Ogre::Quaternion&>(this->camera->getDerivedOrientation());
|
||
|
// return mParentNode->_getDerivedOrientation();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Ogre::Vector3 & MovableText::getWorldPosition(void) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
GZ_ASSERT(mParentNode, "mParentNode class member is null");
|
||
|
return mParentNode->_getDerivedPosition();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Ogre::AxisAlignedBox &MovableText::getBoundingBox(void) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return *this->aabb;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Ogre::String &MovableText::getMovableType() const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
static Ogre::String movType = "MovableText";
|
||
|
return movType;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::getWorldTransforms(Ogre::Matrix4 * xform) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
if (this->isVisible() && this->camera)
|
||
|
{
|
||
|
Ogre::Matrix3 rot3x3, scale3x3 = Ogre::Matrix3::IDENTITY;
|
||
|
|
||
|
// store rotation in a matrix
|
||
|
this->camera->getDerivedOrientation().ToRotationMatrix(rot3x3);
|
||
|
// mParentNode->_getDerivedOrientation().ToRotationMatrix(rot3x3);
|
||
|
|
||
|
// parent node position
|
||
|
Ogre::Vector3 ppos = mParentNode->_getDerivedPosition() +
|
||
|
Ogre::Vector3::UNIT_Z * this->baseline;
|
||
|
|
||
|
// apply scale
|
||
|
scale3x3[0][0] = mParentNode->_getDerivedScale().x / 2;
|
||
|
scale3x3[1][1] = mParentNode->_getDerivedScale().y / 2;
|
||
|
scale3x3[2][2] = mParentNode->_getDerivedScale().z / 2;
|
||
|
|
||
|
// apply all transforms to xform
|
||
|
*xform = (rot3x3 * scale3x3);
|
||
|
xform->setTrans(ppos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
float MovableText::getBoundingRadius() const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return this->radius;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
float MovableText::getSquaredViewDepth(const Ogre::Camera * /*cam_*/) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::getRenderOperation(Ogre::RenderOperation & op)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
|
||
|
if (this->isVisible())
|
||
|
{
|
||
|
if (this->needUpdate)
|
||
|
this->_setupGeometry();
|
||
|
if (this->updateColors)
|
||
|
this->_updateColors();
|
||
|
op = this->renderOp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Ogre::MaterialPtr &MovableText::getMaterial(void) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
GZ_ASSERT(!this->material.isNull(), "material class member is null");
|
||
|
return this->material;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Ogre::LightList &MovableText::getLights(void) const
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return this->lightList;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::_notifyCurrentCamera(Ogre::Camera *cam)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
this->camera = cam;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::_updateRenderQueue(Ogre::RenderQueue* queue)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
if (this->isVisible())
|
||
|
{
|
||
|
if (this->needUpdate)
|
||
|
this->_setupGeometry();
|
||
|
|
||
|
if (this->updateColors)
|
||
|
this->_updateColors();
|
||
|
|
||
|
queue->addRenderable(this, mRenderQueueID,
|
||
|
OGRE_RENDERABLE_DEFAULT_PRIORITY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void MovableText::visitRenderables(Ogre::Renderable::Visitor* /*visitor*/,
|
||
|
bool /*debug*/)
|
||
|
{
|
||
|
boost::recursive_mutex::scoped_lock lock(*this->mutex);
|
||
|
return;
|
||
|
}
|