From d6150b7482ab9eed2f3337cc30d18a55de64d4aa Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 30 Jul 2012 23:28:14 +0400 Subject: [PATCH] high-level implementation, unstable --- apps/openmw/mwclass/creature.hpp | 5 ++ apps/openmw/mwclass/npc.hpp | 5 ++ apps/openmw/mwrender/actors.cpp | 21 ++++++ apps/openmw/mwrender/actors.hpp | 1 + apps/openmw/mwrender/objects.cpp | 21 ++++++ apps/openmw/mwrender/objects.hpp | 2 + apps/openmw/mwrender/renderingmanager.cpp | 19 ++++- apps/openmw/mwworld/class.hpp | 5 ++ apps/openmw/mwworld/worldimp.cpp | 85 +++++++++++++++-------- 9 files changed, 135 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index f7a5e5874..4de877b31 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -59,6 +59,11 @@ namespace MWClass static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool + isActor() const { + return true; + } }; } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index e494fbaa7..edb6ca40f 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -93,6 +93,11 @@ namespace MWClass static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual bool + isActor() const { + return true; + } }; } diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index a64397d49..a73244305 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -132,3 +132,24 @@ void Actors::update (float duration){ for(std::map::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) iter->second->runAnimation(duration); } + +void +Actors::updateObjectCell(const MWWorld::Ptr &ptr) +{ + Ogre::SceneNode *node; + MWWorld::CellStore *newCell = ptr.getCell(); + + if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) { + node = mMwRoot->createChildSceneNode(); + mCellSceneNodes[newCell] = node; + } else { + node = mCellSceneNodes[newCell]; + } + node->addChild(ptr.getRefData().getBaseNode()); + if (Animation *anim = mAllActors[ptr]) { + /// \note Update key (Ptr's are compared only with refdata so mCell + /// on key is outdated), maybe redundant + mAllActors.erase(ptr); + mAllActors[ptr] = anim; + } +} diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index 4b0b2e572..336465b16 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -45,6 +45,7 @@ namespace MWRender{ void update (float duration); + void updateObjectCell(const MWWorld::Ptr &ptr); }; } #endif diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index ecd1328c4..a76ef09d1 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -11,6 +11,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/class.hpp" #include "renderconst.hpp" @@ -474,3 +475,23 @@ void Objects::rebuildStaticGeometry() it->second->build(); } } + +void +Objects::updateObjectCell(const MWWorld::Ptr &ptr) +{ + Ogre::SceneNode *node; + MWWorld::CellStore *newCell = ptr.getCell(); + + if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) { + node = mMwRoot->createChildSceneNode(); + mCellSceneNodes[newCell] = node; + } else { + node = mCellSceneNodes[newCell]; + } + node->addChild(ptr.getRefData().getBaseNode()); + + /// \note Still unaware how to move aabb and static w/o full rebuild, + /// moving static objects may cause problems + insertMesh(ptr, MWWorld::Class::get(ptr).getModel(ptr)); +} + diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 443f25ecf..630e5932c 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -95,6 +95,8 @@ public: void setMwRoot(Ogre::SceneNode* root); void rebuildStaticGeometry(); + + void updateObjectCell(const MWWorld::Ptr &ptr); }; } #endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ae0e57219..cec5569c8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -256,8 +256,25 @@ void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3 void RenderingManager::rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation){ } -void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store){ +void +RenderingManager::moveObjectToCell( + const MWWorld::Ptr& ptr, + const Ogre::Vector3& pos, + MWWorld::CellStore *store) +{ + Ogre::SceneNode *child = + mRendering.getScene()->getSceneNode(ptr.getRefData().getHandle()); + + Ogre::SceneNode *parent = child->getParentSceneNode(); + parent->removeChild(child); + + if (MWWorld::Class::get(ptr).isActor()) { + mActors.updateObjectCell(ptr); + } else { + mObjects.updateObjectCell(ptr); + } + child->setPosition(pos); } void RenderingManager::update (float duration){ diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 1bc592798..6ab92319d 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -220,6 +220,11 @@ namespace MWWorld virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const; + + virtual bool + isActor() const { + return false; + } }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 67d8a7cec..abed25079 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -545,47 +545,76 @@ namespace MWWorld bool World::moveObjectImp (const Ptr& ptr, float x, float y, float z) { - bool ret = false; - ptr.getRefData().getPosition().pos[0] = x; - ptr.getRefData().getPosition().pos[1] = y; - ptr.getRefData().getPosition().pos[2] = z; - if (ptr==mPlayer->getPlayer()) - { - //std::cout << "X:" << ptr.getRefData().getPosition().pos[0] << " Z: " << ptr.getRefData().getPosition().pos[1] << "\n"; + bool cellChanged = false, haveToMove = false; - Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); - if (currentCell) - { - if (!(currentCell->cell->data.flags & ESM::Cell::Interior)) + ESM::Position &pos = ptr.getRefData().getPosition(); + pos.pos[0] = x, pos.pos[1] = y, pos.pos[2] = z; + Ogre::Vector3 vec(x, y, z); + + CellStore *currCell; + // a bit ugly + if (ptr == mPlayer->getPlayer()) { + currCell = mWorldScene->getCurrentCell(); + } else { + currCell = ptr.getCell(); + } + + if (currCell) { + if (!(currCell->cell->data.flags & ESM::Cell::Interior)) { + // exterior -> adjust loaded cells + int cellX = 0, cellY = 0; + positionToIndex (x, y, cellX, cellY); + + if (currCell->cell->data.gridX != cellX || + currCell->cell->data.gridY != cellY) { - // exterior -> adjust loaded cells - int cellX = 0; - int cellY = 0; + if (ptr == mPlayer->getPlayer()) { + mWorldScene->changeCell(cellX, cellY, pos, false); + haveToMove = true; + } else { + CellStore *newCell = + MWBase::Environment::get().getWorld()->getExterior(cellX, cellY); - positionToIndex (x, y, cellX, cellY); + if (!mWorldScene->isCellActive(*currCell)) { + placeObject(ptr, *newCell, pos); + } else if (!mWorldScene->isCellActive(*newCell)) { + MWWorld::Class::get(ptr).copyToCell(ptr, *newCell); + mWorldScene->removeObjectFromScene(ptr); + mLocalScripts.remove(ptr); + } else { + MWWorld::Ptr copy = + MWWorld::Class::get(ptr).copyToCell(ptr, *newCell); - if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) - { - mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false); - ret = true; + mRendering->moveObjectToCell(copy, vec, currCell); + + /// \note Maybe mechanics actors change is redundant + /// because of Ptr comparing operators + if (MWWorld::Class::get(ptr).isActor()) { + MWMechanics::MechanicsManager *mechMgr = + MWBase::Environment::get().getMechanicsManager(); + + mechMgr->removeActor(ptr); + mechMgr->addActor(copy); + + haveToMove = true; + } + } + ptr.getRefData().setCount(0); } - + cellChanged = true; } } } - - /// \todo cell change for non-player ref - - mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z)); - - return ret; + if (haveToMove) { + mRendering->moveObject(ptr, vec); + mPhysics->moveObject(ptr.getRefData().getHandle(), vec); + } + return cellChanged; } void World::moveObject (const Ptr& ptr, float x, float y, float z) { moveObjectImp(ptr, x, y, z); - - mPhysics->moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z)); } void World::scaleObject (const Ptr& ptr, float scale)