diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 4f6b2a875d..4e360f6ebd 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -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 diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 67f6822c7c..07b18cc235 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -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(); +} diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 02f7bc4526..bb4c9a4a80 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -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& getGlobals() const; IdCollection& getGlobals(); diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp index 158793173b..4dd480e773 100644 --- a/apps/opencs/model/world/resources.cpp +++ b/apps/opencs/model/world/resources.cpp @@ -5,8 +5,6 @@ #include #include -#include - #include #include diff --git a/apps/opencs/model/world/resourcesmanager.cpp b/apps/opencs/model/world/resourcesmanager.cpp index 218937924d..3e2f72d93d 100644 --- a/apps/opencs/model/world/resourcesmanager.cpp +++ b/apps/opencs/model/world/resourcesmanager.cpp @@ -3,6 +3,11 @@ #include +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::const_iterator iter = mResources.find (type); diff --git a/apps/opencs/model/world/resourcesmanager.hpp b/apps/opencs/model/world/resourcesmanager.hpp index ee939389f9..1ce06f2d3d 100644 --- a/apps/opencs/model/world/resourcesmanager.hpp +++ b/apps/opencs/model/world/resourcesmanager.hpp @@ -16,6 +16,7 @@ namespace CSMWorld class ResourcesManager { std::map 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; diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 28ce1dd6cc..2c540dee65 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -1,8 +1,7 @@ #include "cell.hpp" -#include -#include +#include #include #include @@ -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 ( *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& 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::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; } diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index 8c7d7e23ae..259ab1779e 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -7,7 +7,7 @@ #include -#include +#include #ifndef Q_MOC_RUN #include @@ -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 mCellNode; std::map mObjects; std::auto_ptr 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(); diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index 9bc7aa2605..50c227d494 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -1,6 +1,9 @@ #include "object.hpp" +#include + #include +#include #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); + 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); - 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); - - // 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) diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index 431867d6b5..9efbcf5dc4 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -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 mBaseNode; + osg::ref_ptr 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 diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index ca4678d497..737a64efaa 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -5,16 +5,9 @@ #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#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& 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::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::string name = cells.getRecord(index).get().mName; + //std::string region = cells.getRecord(index).get().mRegion; + + // cell marker update goes here - std::map::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; - } ++iter; } } } - //if (mCells.begin()==mCells.end()) - //setCamera = true; - // add for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end(); ++iter) @@ -110,113 +64,20 @@ 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; } } + if (modified) + mView->setCameraManipulator(new osgGA::TrackballManipulator); + return modified; } -void CSVRender::PagedWorldspaceWidget::mousePressEvent (QMouseEvent *event) -{ - if(event->button() == Qt::RightButton) - { - std::map::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::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); -} - -void CSVRender::PagedWorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) -{ - WorldspaceWidget::mouseDoubleClickEvent(event); -} - void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons ( CSVWidget::SceneToolToggle2 *tool) { @@ -346,23 +207,7 @@ CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget() iter!=mCells.end(); ++iter) { delete iter->second; - - //getSceneManager()->destroyManualObject("manual"+iter->first.getId(mWorldspace)); } - - for (std::map::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) diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 1bc9c3c5c8..64a0bccd1a 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -28,7 +28,6 @@ namespace CSVRender std::string mWorldspace; CSVWidget::SceneToolToggle *mControlElements; bool mDisplayCellCoord; - std::map 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); diff --git a/apps/opencs/view/render/previewwidget.cpp b/apps/opencs/view/render/previewwidget.cpp index c3f8384353..22185effc5 100644 --- a/apps/opencs/view/render/previewwidget.cpp +++ b/apps/opencs/view/render/previewwidget.cpp @@ -1,9 +1,6 @@ #include "previewwidget.hpp" -#include -#include - #include #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); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 195e550a32..98ddf67c3b 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -58,6 +58,10 @@ SceneWidget::SceneWidget(QWidget *parent, Qt::WindowFlags f) mView->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast(traits->width)/static_cast(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 diff --git a/apps/opencs/view/render/textoverlay.cpp b/apps/opencs/view/render/textoverlay.cpp deleted file mode 100644 index 656ea959c7..0000000000 --- a/apps/opencs/view/render/textoverlay.cpp +++ /dev/null @@ -1,359 +0,0 @@ -#include "textoverlay.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -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(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(overlayMgr.createOverlayElement( - "Panel", "container"+mId +"#"+Ogre::StringConverter::toString(mInstance))); - mContainer->setMaterialName("TransOverlayMaterial"); - mOverlay->add2D(mContainer); - - // setup text area overlay element - mElement = static_cast(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; -} - -} diff --git a/apps/opencs/view/render/textoverlay.hpp b/apps/opencs/view/render/textoverlay.hpp deleted file mode 100644 index dbb347e567..0000000000 --- a/apps/opencs/view/render/textoverlay.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef OPENCS_VIEW_TEXTOVERLAY_H -#define OPENCS_VIEW_TEXTOVERLAY_H - -#include - -#include -#include - -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 diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index fd63567c78..46c010fd2c 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -3,8 +3,7 @@ #include -#include -#include +#include #include @@ -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::vectorgetId(); - //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()); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 68a3acdb91..f5068bb473 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -3,10 +3,6 @@ #include -#include -#include -#include - #include #include "../../model/world/universalid.hpp"