OpenCS: preliminary port of cell rendering to OSG

c++11
scrawl 10 years ago
parent aedafe651a
commit 72400747f2

@ -81,7 +81,7 @@ opencs_units (view/render
opencs_units_noqt (view/render
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
lightingbright object cell terrainstorage textoverlay
lightingbright object cell terrainstorage
)
opencs_hdrs_noqt (view/render

@ -970,3 +970,8 @@ void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
{
emit idListChanged();
}
const VFS::Manager* CSMWorld::Data::getVFS() const
{
return mResourcesManager.getVFS();
}

@ -45,6 +45,11 @@
class QAbstractItemModel;
namespace VFS
{
class Manager;
}
namespace ESM
{
class ESMReader;
@ -121,6 +126,8 @@ namespace CSMWorld
virtual ~Data();
const VFS::Manager* getVFS() const;
const IdCollection<ESM::Global>& getGlobals() const;
IdCollection<ESM::Global>& getGlobals();

@ -5,8 +5,6 @@
#include <stdexcept>
#include <algorithm>
#include <OgreResourceGroupManager.h>
#include <components/vfs/manager.hpp>
#include <components/misc/stringops.hpp>

@ -3,6 +3,11 @@
#include <stdexcept>
CSMWorld::ResourcesManager::ResourcesManager()
: mVFS(NULL)
{
}
void CSMWorld::ResourcesManager::addResources (const Resources& resources)
{
mResources.insert (std::make_pair (resources.getType(), resources));
@ -12,6 +17,7 @@ void CSMWorld::ResourcesManager::addResources (const Resources& resources)
void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs)
{
mVFS = vfs;
mResources.clear();
static const char * const sMeshTypes[] = { "nif", 0 };
@ -24,6 +30,11 @@ void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs)
addResources (Resources (vfs, "videos", UniversalId::Type_Video));
}
const VFS::Manager* CSMWorld::ResourcesManager::getVFS() const
{
return mVFS;
}
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const
{
std::map<UniversalId::Type, Resources>::const_iterator iter = mResources.find (type);

@ -16,6 +16,7 @@ namespace CSMWorld
class ResourcesManager
{
std::map<UniversalId::Type, Resources> mResources;
const VFS::Manager* mVFS;
private:
@ -23,6 +24,10 @@ namespace CSMWorld
public:
ResourcesManager();
const VFS::Manager* getVFS() const;
void setVFS(const VFS::Manager* vfs);
const Resources& get (UniversalId::Type type) const;

@ -1,8 +1,7 @@
#include "cell.hpp"
#include <OgreSceneManager.h>
#include <OgreSceneNode.h>
#include <osg/Group>
#include <components/misc/stringops.hpp>
#include <components/esm/loadland.hpp>
@ -50,7 +49,7 @@ bool CSVRender::Cell::addObjects (int start, int end)
std::string id = Misc::StringUtils::lowerCase (references.data (
references.index (i, idColumn)).toString().toUtf8().constData());
//mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false, mPhysics)));
mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false)));
modified = true;
}
}
@ -58,12 +57,11 @@ bool CSVRender::Cell::addObjects (int start, int end)
return modified;
}
CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
const std::string& id, const Ogre::Vector3& origin)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mSceneMgr(sceneManager), mX(0), mY(0)
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mX(0), mY(0)
{
mCellNode = sceneManager->getRootSceneNode()->createChildSceneNode();
mCellNode->setPosition (origin);
mCellNode = new osg::Group;
rootNode->addChild(mCellNode);
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
@ -72,6 +70,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
addObjects (0, rows-1);
/*
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
int landIndex = land.searchId(mId);
if (landIndex != -1)
@ -84,14 +83,15 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
mTerrain->loadCell(esmLand->mX,
esmLand->mY);
float verts = ESM::Land::LAND_SIZE;
float worldsize = ESM::Land::REAL_SIZE;
//float verts = ESM::Land::LAND_SIZE;
//float worldsize = ESM::Land::REAL_SIZE;
mX = esmLand->mX;
mY = esmLand->mY;
//mPhysics->addHeightField(sceneManager,
// esmLand->mLandData->mHeights, mX, mY, 0, worldsize / (verts-1), verts);
}
}
*/
}
CSVRender::Cell::~Cell()
@ -103,7 +103,7 @@ CSVRender::Cell::~Cell()
iter!=mObjects.end(); ++iter)
delete iter->second;
mCellNode->getCreator()->destroySceneNode (mCellNode);
mCellNode->getParent(0)->removeChild(mCellNode);
}
bool CSVRender::Cell::referenceableDataChanged (const QModelIndex& topLeft,
@ -190,8 +190,8 @@ bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft,
// add new objects
for (std::map<std::string, bool>::iterator iter (ids.begin()); iter!=ids.end(); ++iter)
{
//mObjects.insert (std::make_pair (
// iter->first, new Object (mData, mCellNode, iter->first, false, mPhysics)));
mObjects.insert (std::make_pair (
iter->first, new Object (mData, mCellNode, iter->first, false)));
modified = true;
}

@ -7,7 +7,7 @@
#include <boost/shared_ptr.hpp>
#include <OgreVector3.h>
#include <osg/ref_ptr>
#ifndef Q_MOC_RUN
#include <components/terrain/terraingrid.hpp>
@ -17,10 +17,9 @@
class QModelIndex;
namespace Ogre
namespace osg
{
class SceneManager;
class SceneNode;
class Group;
}
namespace CSMWorld
@ -34,10 +33,9 @@ namespace CSVRender
{
CSMWorld::Data& mData;
std::string mId;
Ogre::SceneNode *mCellNode;
osg::ref_ptr<osg::Group> mCellNode;
std::map<std::string, Object *> mObjects;
std::auto_ptr<Terrain::TerrainGrid> mTerrain;
Ogre::SceneManager *mSceneMgr;
int mX;
int mY;
@ -53,7 +51,7 @@ namespace CSVRender
public:
Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, const std::string& id, const Ogre::Vector3& origin = Ogre::Vector3 (0, 0, 0));
Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id);
~Cell();

@ -1,6 +1,9 @@
#include "object.hpp"
#include <stdexcept>
#include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include "../../model/world/data.hpp"
#include "../../model/world/ref.hpp"
@ -51,14 +54,23 @@ void CSVRender::Object::update()
}
else
{
NifOsg::Loader loader;
loader.resourceManager = mVFS;
try
{
NifOsg::Loader loader;
loader.resourceManager = mVFS;
std::string path = "meshes\\" + model;
std::string path = "meshes\\" + model;
Nif::NIFFilePtr file(new Nif::NIFFile(mVFS->get(path), path));
Nif::NIFFilePtr file(new Nif::NIFFile(mVFS->get(path), path));
mBaseNode->addChild(loader.load(file));
mBaseNode->removeChildren(0, mBaseNode->getNumChildren());
mBaseNode->addChild(loader.load(file));
}
catch (std::exception& e)
{
// TODO: use error marker mesh
std::cerr << e.what() << std::endl;
}
//mObject->setVisibilityFlags (Element_Reference);
}
@ -66,29 +78,21 @@ void CSVRender::Object::update()
void CSVRender::Object::adjust()
{
/*
if (mReferenceId.empty())
return;
const CSMWorld::CellRef& reference = getReference();
// position
if (!mForceBaseToZero)
mBase->setPosition (Ogre::Vector3 (
reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
mBaseNode->setPosition(mForceBaseToZero ? osg::Vec3() : osg::Vec3f(reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
// orientation
Ogre::Quaternion xr (Ogre::Radian (-reference.mPos.rot[0]), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr (Ogre::Radian (-reference.mPos.rot[1]), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr (Ogre::Radian (-reference.mPos.rot[2]), Ogre::Vector3::UNIT_Z);
mBase->setOrientation (xr*yr*zr);
osg::Quat xr (-reference.mPos.rot[0], osg::Vec3f(1,0,0));
osg::Quat yr (-reference.mPos.rot[1], osg::Vec3f(0,1,0));
osg::Quat zr (-reference.mPos.rot[2], osg::Vec3f(0,0,1));
mBaseNode->setAttitude(zr*yr*xr);
// scale
mBase->setScale (reference.mScale, reference.mScale, reference.mScale);
*/
mBaseNode->setScale(osg::Vec3(reference.mScale, reference.mScale, reference.mScale));
}
const CSMWorld::CellRef& CSVRender::Object::getReference() const
@ -99,11 +103,11 @@ const CSMWorld::CellRef& CSVRender::Object::getReference() const
return mData.getReferences().getRecord (mReferenceId).get();
}
CSVRender::Object::Object (const VFS::Manager* vfs, const CSMWorld::Data& data, osg::Group* parentNode,
CSVRender::Object::Object (const CSMWorld::Data& data, osg::Group* parentNode,
const std::string& id, bool referenceable, bool forceBaseToZero)
: mVFS(vfs), mData (data), mBaseNode(0), mParentNode(parentNode), mForceBaseToZero (forceBaseToZero)
: mVFS(data.getVFS()), mData (data), mBaseNode(0), mParentNode(parentNode), mForceBaseToZero (forceBaseToZero)
{
mBaseNode = new osg::Group;
mBaseNode = new osg::PositionAttitudeTransform;
parentNode->addChild(mBaseNode);
if (referenceable)

@ -10,6 +10,7 @@ class QModelIndex;
namespace osg
{
class PositionAttitudeTransform;
class Group;
}
@ -36,7 +37,7 @@ namespace CSVRender
const CSMWorld::Data& mData;
std::string mReferenceId;
std::string mReferenceableId;
osg::ref_ptr<osg::Group> mBaseNode;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
osg::Group* mParentNode;
const VFS::Manager* mVFS;
bool mForceBaseToZero;
@ -61,7 +62,7 @@ namespace CSVRender
public:
Object (const VFS::Manager* vfs, const CSMWorld::Data& data, osg::Group *cellNode,
Object (const CSMWorld::Data& data, osg::Group *cellNode,
const std::string& id, bool referenceable,
bool forceBaseToZero = false);
/// \param forceBaseToZero If this is a reference ignore the coordinates and place

@ -5,16 +5,9 @@
#include <QMouseEvent>
#include <OgreCamera.h>
#include <OgreSceneManager.h>
#include <OgreManualObject.h>
#include <OgreOverlayContainer.h>
#include <OgreOverlayManager.h>
#include <OgreRoot.h>
#include <OgreSceneQuery.h>
#include <osgGA/TrackballManipulator>
#include <components/esm/loadland.hpp>
#include "textoverlay.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/world/idtable.hpp"
@ -29,7 +22,6 @@
bool CSVRender::PagedWorldspaceWidget::adjustCells()
{
bool modified = false;
//bool setCamera = false;
const CSMWorld::IdCollection<CSMWorld::Cell>& cells = mDocument.getData().getCells();
@ -44,17 +36,6 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
if (!mSelection.has (iter->first) || index==-1 ||
cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted)
{
// delete overlays
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator itOverlay = mTextOverlays.find(iter->first);
if(itOverlay != mTextOverlays.end())
{
delete itOverlay->second;
mTextOverlays.erase(itOverlay);
}
// destroy manual objects
//getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace));
delete iter->second;
mCells.erase (iter++);
@ -64,43 +45,16 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
{
// check if name or region field has changed
// FIXME: config setting
std::string name = cells.getRecord(index).get().mName;
std::string region = cells.getRecord(index).get().mRegion;
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator it = mTextOverlays.find(iter->first);
if(it != mTextOverlays.end())
{
if(it->second->getDesc() != "") // previously had name
{
if(name != it->second->getDesc()) // new name
{
if(name != "")
it->second->setDesc(name);
else // name deleted, use region
it->second->setDesc(region);
it->second->update();
}
}
else if(name != "") // name added
{
it->second->setDesc(name);
it->second->update();
}
else if(region != it->second->getDesc()) // new region
{
it->second->setDesc(region);
it->second->update();
}
modified = true;
}
//std::string name = cells.getRecord(index).get().mName;
//std::string region = cells.getRecord(index).get().mRegion;
// cell marker update goes here
++iter;
}
}
}
//if (mCells.begin()==mCells.end())
//setCamera = true;
// add
for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end();
++iter)
@ -110,111 +64,18 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted &&
mCells.find (*iter)==mCells.end())
{
#if 0
Cell *cell = new Cell (mDocument.getData(), getSceneManager(),
Cell *cell = new Cell (mDocument.getData(), mRootNode,
iter->getId (mWorldspace));
mCells.insert (std::make_pair (*iter, cell));
float height = cell->getTerrainHeightAt(Ogre::Vector3(
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
0));
if (setCamera)
{
setCamera = false;
getCamera()->setPosition (
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height);
// better camera position at the start
getCamera()->move(getCamera()->getDirection() * -6000); // FIXME: config setting
}
Ogre::ManualObject* manual =
getSceneManager()->createManualObject("manual" + iter->getId(mWorldspace));
manual->begin("BaseWhite", Ogre::RenderOperation::OT_LINE_LIST);
// define start and end point (x, y, z)
manual-> position(ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height);
manual-> position(ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height+200); // FIXME: config setting
manual->end();
manual->setBoundingBox(Ogre::AxisAlignedBox(
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height,
ESM::Land::REAL_SIZE * iter->getX() + ESM::Land::REAL_SIZE/2,
ESM::Land::REAL_SIZE * iter->getY() + ESM::Land::REAL_SIZE/2,
height+200));
getSceneManager()->getRootSceneNode()->createChildSceneNode()->attachObject(manual);
manual->setVisible(false);
CSVRender::TextOverlay *textDisp =
new CSVRender::TextOverlay(manual, getCamera(), iter->getId(mWorldspace));
textDisp->enable(true);
textDisp->setCaption(iter->getId(mWorldspace));
std::string desc = cells.getRecord(index).get().mName;
if(desc == "") desc = cells.getRecord(index).get().mRegion;
textDisp->setDesc(desc); // FIXME: config setting
textDisp->update();
mTextOverlays.insert(std::make_pair(*iter, textDisp));
/*
if(!mOverlayMask)
{
mOverlayMask = new OverlayMask(mTextOverlays, getViewport());
addRenderTargetListener(mOverlayMask);
}
*/
#endif
modified = true;
}
}
return modified;
}
void CSVRender::PagedWorldspaceWidget::mousePressEvent (QMouseEvent *event)
{
if(event->button() == Qt::RightButton)
{
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator iter = mTextOverlays.begin();
for(; iter != mTextOverlays.end(); ++iter)
{
if(mDisplayCellCoord &&
iter->second->isEnabled() && iter->second->container().contains(event->x(), event->y()))
{
return;
}
}
}
WorldspaceWidget::mousePressEvent(event);
}
void CSVRender::PagedWorldspaceWidget::mouseReleaseEvent (QMouseEvent *event)
{
if(event->button() == Qt::RightButton)
{
std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator iter = mTextOverlays.begin();
for(; iter != mTextOverlays.end(); ++iter)
{
if(mDisplayCellCoord &&
iter->second->isEnabled() && iter->second->container().contains(event->x(), event->y()))
{
std::cout << "clicked: " << iter->second->getCaption() << std::endl;
return;
}
}
}
WorldspaceWidget::mouseReleaseEvent(event);
}
if (modified)
mView->setCameraManipulator(new osgGA::TrackballManipulator);
void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event)
{
WorldspaceWidget::mouseDoubleClickEvent(event);
return modified;
}
void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons (
@ -344,25 +205,9 @@ CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget()
{
for (std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
iter!=mCells.end(); ++iter)
{
delete iter->second;
//getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace));
}
for (std::map<CSMWorld::CellCoordinates, TextOverlay *>::iterator iter (mTextOverlays.begin());
iter != mTextOverlays.end(); ++iter)
{
delete iter->second;
}
/*
if(mOverlayMask)
{
removeRenderTargetListener(mOverlayMask);
delete mOverlayMask;
}
*/
}
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)

@ -28,7 +28,6 @@ namespace CSVRender
std::string mWorldspace;
CSVWidget::SceneToolToggle *mControlElements;
bool mDisplayCellCoord;
std::map<CSMWorld::CellCoordinates, TextOverlay *> mTextOverlays;
private:
@ -86,12 +85,6 @@ namespace CSVRender
virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool);
virtual void mousePressEvent (QMouseEvent *event);
virtual void mouseReleaseEvent (QMouseEvent *event);
virtual void mouseDoubleClickEvent (QMouseEvent *event);
signals:
void cellSelectionChanged (const CSMWorld::CellSelection& selection);

@ -1,9 +1,6 @@
#include "previewwidget.hpp"
#include <OgreSceneManager.h>
#include <OgreSceneNode.h>
#include <osgGA/TrackballManipulator>
#include "../../model/world/data.hpp"
@ -11,7 +8,7 @@
CSVRender::PreviewWidget::PreviewWidget (const VFS::Manager* vfs, CSMWorld::Data& data,
const std::string& id, bool referenceable, QWidget *parent)
: SceneWidget (parent), mData (data), mObject(vfs, data, mRootNode, id, referenceable)
: SceneWidget (parent), mData (data), mObject(data, mRootNode, id, referenceable)
{
//setNavigation (&mOrbit);

@ -58,6 +58,10 @@ SceneWidget::SceneWidget(QWidget *parent, Qt::WindowFlags f)
mView->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f );
mRootNode = new osg::Group;
// TODO: move to utility file
mRootNode->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
mRootNode->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
mView->setSceneData(mRootNode);
// Press S to reveal profiling stats

@ -1,359 +0,0 @@
#include "textoverlay.hpp"
#include <OgreCamera.h>
#include <OgreMaterialManager.h>
#include <OgreTechnique.h>
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <OgreFontManager.h>
#include <OgreTextAreaOverlayElement.h>
#include <OgreEntity.h>
#include <OgreViewport.h>
#include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h>
namespace CSVRender
{
// Things to do:
// - configurable font size in pixels (automatically calulate everything else from it)
// - configurable texture to use
// - try material script
// - decide whether to use QPaint (http://www.ogre3d.org/tikiwiki/Ogre+overlays+using+Qt)
// http://www.ogre3d.org/tikiwiki/ObjectTextDisplay
// http://www.ogre3d.org/tikiwiki/MovableTextOverlay
// http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures
// http://www.ogre3d.org/tikiwiki/ManualObject
TextOverlay::TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String& id)
: mOverlay(0), mCaption(""), mDesc(""), mEnabled(true), mCamera(camera), mObj(obj), mId(id)
, mOnScreen(false) , mInstance(0), mFontHeight(16) // FIXME: make font height configurable
{
if(id == "" || !camera || !obj)
throw std::runtime_error("TextOverlay could not be created.");
// setup font
Ogre::FontManager &fontMgr = Ogre::FontManager::getSingleton();
if (fontMgr.resourceExists("DejaVuLGC"))
mFont = fontMgr.getByName("DejaVuLGC","General");
else
{
mFont = fontMgr.create("DejaVuLGC","General");
mFont->setType(Ogre::FT_TRUETYPE);
mFont->setSource("DejaVuLGCSansMono.ttf");
mFont->setTrueTypeSize(mFontHeight);
mFont->setTrueTypeResolution(96);
}
if(!mFont.isNull())
mFont->load();
else
throw std::runtime_error("TextOverlay font not loaded.");
// setup overlay
Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton();
mOverlay = overlayMgr.getByName("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance));
// FIXME: this logic is badly broken as it is possible to delete an earlier instance
while(mOverlay != NULL)
{
mInstance++;
mOverlay = overlayMgr.getByName("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance));
}
mOverlay = overlayMgr.create("CellIDPanel"+mId+Ogre::StringConverter::toString(mInstance));
// create texture
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName("DynamicTransBlue");
if(texture.isNull())
{
texture = Ogre::TextureManager::getSingleton().createManual(
"DynamicTransBlue", // name
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, // type
8, 8, // width & height
0, // number of mipmaps
Ogre::PF_BYTE_BGRA, // pixel format
Ogre::TU_DEFAULT); // usage; should be TU_DYNAMIC_WRITE_ONLY_DISCARDABLE for
// textures updated very often (e.g. each frame)
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
// Fill in some pixel data. This will give a semi-transparent blue,
// but this is of course dependent on the chosen pixel format.
for (size_t j = 0; j < 8; j++)
{
for(size_t i = 0; i < 8; i++)
{
*pDest++ = 255; // B
*pDest++ = 0; // G
*pDest++ = 0; // R
*pDest++ = 63; // A
}
pDest += pixelBox.getRowSkip() * Ogre::PixelUtil::getNumElemBytes(pixelBox.format);
}
pixelBuffer->unlock();
}
// setup material for containers
Ogre::MaterialPtr mQuadMaterial = Ogre::MaterialManager::getSingleton().getByName(
"TransOverlayMaterial");
if(mQuadMaterial.isNull())
{
Ogre::MaterialPtr mQuadMaterial = Ogre::MaterialManager::getSingleton().create(
"TransOverlayMaterial",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true );
Ogre::Pass *pass = mQuadMaterial->getTechnique( 0 )->getPass( 0 );
pass->setLightingEnabled( false );
pass->setDepthWriteEnabled( false );
pass->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
Ogre::TextureUnitState *tex = pass->createTextureUnitState("MyCustomState", 0);
tex->setTextureName("DynamicTransBlue");
tex->setTextureFiltering( Ogre::TFO_ANISOTROPIC );
mQuadMaterial->load();
}
mContainer = static_cast<Ogre::OverlayContainer*>(overlayMgr.createOverlayElement(
"Panel", "container"+mId +"#"+Ogre::StringConverter::toString(mInstance)));
mContainer->setMaterialName("TransOverlayMaterial");
mOverlay->add2D(mContainer);
// setup text area overlay element
mElement = static_cast<Ogre::TextAreaOverlayElement*>(overlayMgr.createOverlayElement(
"TextArea", "text"+mId +"#"+Ogre::StringConverter::toString(mInstance)));
mElement->setMetricsMode(Ogre::GMM_RELATIVE);
mElement->setDimensions(1.0, 1.0);
mElement->setMetricsMode(Ogre::GMM_PIXELS);
mElement->setPosition(2*fontHeight()/3, 1.3*fontHeight()/3); // 1.3 & 2 = fudge factor
mElement->setFontName("DejaVuLGC");
mElement->setCharHeight(fontHeight()); // NOTE: seems that this is required as well as font->setTrueTypeSize()
mElement->setHorizontalAlignment(Ogre::GHA_LEFT);
//mElement->setColour(Ogre::ColourValue(1.0, 1.0, 1.0)); // R, G, B
mElement->setColour(Ogre::ColourValue(1.0, 1.0, 0)); // yellow
mContainer->addChild(mElement);
mOverlay->show();
}
void TextOverlay::getScreenCoordinates(const Ogre::Vector3& position, Ogre::Real& x, Ogre::Real& y)
{
Ogre::Vector3 hcsPosition = mCamera->getProjectionMatrix() * (mCamera->getViewMatrix() * position);
x = 1.0f - ((hcsPosition.x * 0.5f) + 0.5f); // 0 <= x <= 1 // left := 0,right := 1
y = ((hcsPosition.y * 0.5f) + 0.5f); // 0 <= y <= 1 // bottom := 0,top := 1
}
void TextOverlay::getMinMaxEdgesOfAABBIn2D(float& MinX, float& MinY, float& MaxX, float& MaxY,
bool top)
{
MinX = 0, MinY = 0, MaxX = 0, MaxY = 0;
float X[4]; // the 2D dots of the AABB in screencoordinates
float Y[4];
if(!mObj->isInScene())
return;
const Ogre::AxisAlignedBox &AABB = mObj->getWorldBoundingBox(true); // the AABB of the target
Ogre::Vector3 cornersOfAABB[4];
if(top)
{
cornersOfAABB[0] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_TOP);
cornersOfAABB[1] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_TOP);
cornersOfAABB[2] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_TOP);
cornersOfAABB[3] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_TOP);
}
else
{
cornersOfAABB[0] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM);
cornersOfAABB[1] = AABB.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM);
cornersOfAABB[2] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM);
cornersOfAABB[3] = AABB.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM);
}
//The normal vector of the plane. This points directly infront of the camera.
Ogre::Vector3 cameraPlainNormal = mCamera->getDerivedOrientation().zAxis();
//the plane that devides the space before and behind the camera.
Ogre::Plane CameraPlane = Ogre::Plane(cameraPlainNormal, mCamera->getDerivedPosition());
for (int i = 0; i < 4; i++)
{
X[i] = 0;
Y[i] = 0;
getScreenCoordinates(cornersOfAABB[i],X[i],Y[i]); // transfor into 2d dots
if (CameraPlane.getSide(cornersOfAABB[i]) == Ogre::Plane::NEGATIVE_SIDE)
{
if (i == 0) // accept the first set of values, no matter how bad it might be.
{
MinX = X[i];
MinY = Y[i];
MaxX = X[i];
MaxY = Y[i];
}
else // now compare if you get "better" values
{
if (MinX > X[i]) MinX = X[i];
if (MinY > Y[i]) MinY = Y[i];
if (MaxX < X[i]) MaxX = X[i];
if (MaxY < Y[i]) MaxY = Y[i];
}
}
else
{
MinX = 0;
MinY = 0;
MaxX = 0;
MaxY = 0;
break;
}
}
}
TextOverlay::~TextOverlay()
{
Ogre::OverlayManager::OverlayMapIterator iter = Ogre::OverlayManager::getSingleton().getOverlayIterator();
if(!iter.hasMoreElements())
mOverlay->hide();
Ogre::OverlayManager *overlayMgr = Ogre::OverlayManager::getSingletonPtr();
mContainer->removeChild("text"+mId+"#"+Ogre::StringConverter::toString(mInstance));
mOverlay->remove2D(mContainer);
if(!iter.hasMoreElements())
overlayMgr->destroy(mOverlay);
}
void TextOverlay::show(bool show)
{
if(show && mOnScreen)
mContainer->show();
else
mContainer->hide();
}
void TextOverlay::enable(bool enable)
{
if(enable == mOverlay->isVisible())
return;
mEnabled = enable;
if(enable)
mOverlay->show();
else
mOverlay->hide();
}
bool TextOverlay::isEnabled()
{
return mEnabled;
}
void TextOverlay::setCaption(const Ogre::String& text)
{
if(mCaption == text)
return;
mCaption = text;
mElement->setCaption(text);
}
void TextOverlay::setDesc(const Ogre::String& text)
{
if(mDesc == text)
return;
mDesc = text;
mElement->setCaption(mCaption + ((text == "") ? "" : ("\n" + text)));
}
Ogre::FontPtr TextOverlay::getFont()
{
return mFont;
}
int TextOverlay::textWidth()
{
float captionWidth = 0;
float descWidth = 0;
for(Ogre::String::const_iterator i = mCaption.begin(); i < mCaption.end(); ++i)
{
if(*i == 0x0020)
captionWidth += getFont()->getGlyphAspectRatio(0x0030);
else
captionWidth += getFont()->getGlyphAspectRatio(*i);
}
for(Ogre::String::const_iterator i = mDesc.begin(); i < mDesc.end(); ++i)
{
if(*i == 0x0020)
descWidth += getFont()->getGlyphAspectRatio(0x0030);
else
descWidth += getFont()->getGlyphAspectRatio(*i);
}
captionWidth *= fontHeight();
descWidth *= fontHeight();
return (int) std::max(captionWidth, descWidth);
}
int TextOverlay::fontHeight()
{
return mFontHeight;
}
void TextOverlay::update()
{
float min_x, max_x, min_y, max_y;
getMinMaxEdgesOfAABBIn2D(min_x, min_y, max_x, max_y, false);
if ((min_x>0.0) && (max_x<1.0) && (min_y>0.0) && (max_y<1.0))
{
mOnScreen = true;
mContainer->show();
}
else
{
mOnScreen = false;
mContainer->hide();
return;
}
getMinMaxEdgesOfAABBIn2D(min_x, min_y, max_x, max_y);
Ogre::OverlayManager &overlayMgr = Ogre::OverlayManager::getSingleton();
float viewportWidth = std::max(overlayMgr.getViewportWidth(), 1); // zero at the start
float viewportHeight = std::max(overlayMgr.getViewportHeight(), 1); // zero at the start
int width = fontHeight()*2/3 + textWidth() + fontHeight()*2/3; // add margins
int height = fontHeight()/3 + fontHeight() + fontHeight()/3;
if(mDesc != "")
height = fontHeight()/3 + 2*fontHeight() + fontHeight()/3;
float relTextWidth = width / viewportWidth;
float relTextHeight = height / viewportHeight;
float posX = 1 - (min_x + max_x + relTextWidth)/2;
float posY = 1 - max_y - (relTextHeight-fontHeight()/3/viewportHeight);
mContainer->setMetricsMode(Ogre::GMM_RELATIVE);
mContainer->setPosition(posX, posY);
mContainer->setDimensions(relTextWidth, relTextHeight);
mPos = QRect(posX*viewportWidth, posY*viewportHeight, width, height);
}
QRect TextOverlay::container()
{
return mPos;
}
}

@ -1,66 +0,0 @@
#ifndef OPENCS_VIEW_TEXTOVERLAY_H
#define OPENCS_VIEW_TEXTOVERLAY_H
#include <QRect>
#include <OgreString.h>
#include <OgreFont.h>
namespace Ogre
{
class MovableObject;
class Camera;
class Font;
class Overlay;
class OverlayContainer;
class TextAreaOverlayElement;
}
namespace CSVRender
{
class TextOverlay
{
Ogre::Overlay* mOverlay;
Ogre::OverlayContainer* mContainer;
Ogre::TextAreaOverlayElement* mElement;
Ogre::String mCaption;
Ogre::String mDesc;
const Ogre::MovableObject* mObj;
const Ogre::Camera* mCamera;
Ogre::FontPtr mFont;
int mFontHeight; // in pixels
Ogre::String mId;
QRect mPos;
bool mEnabled;
bool mOnScreen;
int mInstance;
Ogre::FontPtr getFont();
int textWidth();
int fontHeight();
void getScreenCoordinates(const Ogre::Vector3& position, Ogre::Real& x, Ogre::Real& y);
void getMinMaxEdgesOfAABBIn2D(float& MinX, float& MinY, float& MaxX, float& MaxY,
bool top = true);
public:
TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String &id);
virtual ~TextOverlay();
void enable(bool enable); // controlled from scene widget toolbar visibility mask
void show(bool show); // for updating from render target listener
bool isEnabled();
void setCaption(const Ogre::String& text);
void setDesc(const Ogre::String& text);
void update();
QRect container(); // for detection of mouse click on the overlay
Ogre::String getCaption() { return mCaption; } // FIXME: debug
Ogre::String getDesc() { return mDesc; }
};
}
#endif // OPENCS_VIEW_TEXTOVERLAY_H

@ -3,8 +3,7 @@
#include <sstream>
#include <OgreColourValue.h>
#include <OgreCamera.h>
#include <osgGA/TrackballManipulator>
#include <QtGui/qevent.h>
@ -49,7 +48,10 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string&
update();
//mCell.reset (new Cell (document.getData(), getSceneManager(), mCellId));
mCell.reset (new Cell (document.getData(), mRootNode, mCellId));
mView->setCameraManipulator(new osgGA::TrackballManipulator);
//mView->setCameraManipulator(new osgGA::FirstPersonManipulator);
}
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
@ -91,7 +93,8 @@ bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld:
return false;
mCellId = data.begin()->getId();
//mCell.reset (new Cell (getDocument().getData(), getSceneManager(), mCellId));
// FIXME: we shouldn't need to rebuild the whole cell
mCell.reset (new Cell (getDocument().getData(), mRootNode, mCellId));
update();
emit cellChanged(*data.begin());

@ -3,10 +3,6 @@
#include <algorithm>
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include <QtGui/qevent.h>
#include "../../model/world/universalid.hpp"

Loading…
Cancel
Save