From bef4bef5d229e7f4f5335f6a4e3a6f83a8fc5d80 Mon Sep 17 00:00:00 2001 From: Mark Siewert Date: Sun, 10 Jun 2012 11:14:46 +0200 Subject: [PATCH 001/126] - Add support for loading multiple esm/esp files. Selection in omwlauncher is recognized and applied. - Quick hack for multiple terrain palettes. Prevents crashes and/or wrong textures in masters/plugins beyond the first. - Support deleting parent entries from the list. --- apps/openmw/engine.cpp | 30 ++++++++++++++----- apps/openmw/engine.hpp | 8 +++-- apps/openmw/main.cpp | 26 +++++++++------- apps/openmw/mwrender/terrain.cpp | 24 +++++++++++---- apps/openmw/mwrender/terrain.hpp | 5 +++- apps/openmw/mwworld/world.cpp | 32 +++++++++++++++----- apps/openmw/mwworld/world.hpp | 3 +- components/esm/esm_reader.hpp | 8 +++++ components/esm/loadland.cpp | 1 + components/esm/loadland.hpp | 1 + components/esm_store/reclists.hpp | 50 ++++++++++++++++++++++++------- components/esm_store/store.cpp | 7 +++++ 12 files changed, 148 insertions(+), 47 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index e192b1f88..4fd43fa3f 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -228,18 +228,32 @@ void OMW::Engine::setCell (const std::string& cellName) // Set master file (esm) // - If the given name does not have an extension, ".esm" is added automatically -// - Currently OpenMW only supports one master at the same time. void OMW::Engine::addMaster (const std::string& master) { - assert (mMaster.empty()); - mMaster = master; + mMaster.push_back(master); + std::string &str = mMaster.back(); - // Append .esm if not already there - std::string::size_type sep = mMaster.find_last_of ("."); + // Append .esm if not already there + std::string::size_type sep = str.find_last_of ("."); if (sep == std::string::npos) { - mMaster += ".esm"; + str += ".esm"; + } +} + +// Add plugin file (esp) + +void OMW::Engine::addPlugin (const std::string& plugin) +{ + mPlugins.push_back(plugin); + std::string &str = mPlugins.back(); + + // Append .esp if not already there + std::string::size_type sep = str.find_last_of ("."); + if (sep == std::string::npos) + { + str += ".esp"; } } @@ -341,8 +355,8 @@ void OMW::Engine::go() MWGui::CursorReplace replacer; // Create the world - mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, - mResDir, mNewGame, mEncoding, mFallbackMap)); + mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins, + mResDir, mNewGame, mEncoding, mFallbackMap) ); // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index cf1ef3b9c..1cbc63609 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -68,7 +68,8 @@ namespace OMW boost::filesystem::path mResDir; OEngine::Render::OgreRenderer *mOgre; std::string mCellName; - std::string mMaster; + std::vector mMaster; + std::vector mPlugins; int mFpsLevel; bool mDebug; bool mVerboseScripts; @@ -124,9 +125,12 @@ namespace OMW /// Set master file (esm) /// - If the given name does not have an extension, ".esm" is added automatically - /// - Currently OpenMW only supports one master at the same time. void addMaster(const std::string& master); + /// Same as "addMaster", but for plugin files (esp) + /// - If the given name does not have an extension, ".esp" is added automatically + void addPlugin(const std::string& plugin); + /// Enable fps counter void showFPS(int level); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 68aa12fb3..3a63361f9 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -239,19 +239,23 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat master.push_back("Morrowind"); } - if (master.size() > 1) - { - std::cout - << "Ignoring all but the first master file (multiple master files not yet supported)." - << std::endl; - } - engine.addMaster(master[0]); - StringsVector plugin = variables["plugin"].as(); - if (!plugin.empty()) - { - std::cout << "Ignoring plugin files (plugins not yet supported)." << std::endl; + int cnt = master.size() + plugin.size(); + if (cnt > 255) + { + std::cerr + << "Error: Trying to load more than 255 master and plugin files! This will break all combaibility and is not supported!" + << std::endl; + return false; } + for (std::vector::size_type i = 0; i < master.size(); i++) + { + engine.addMaster(master[i]); + } + for (std::vector::size_type i = 0; i < plugin.size(); i++) + { + engine.addPlugin(plugin[i]); + } // startup-settings engine.setCell(variables["start"].as()); diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 4dac750c7..9247d42cf 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -156,7 +156,7 @@ namespace MWRender std::map indexes; initTerrainTextures(&terrainData, cellX, cellY, x * numTextures, y * numTextures, - numTextures, indexes); + numTextures, indexes, land->plugin); if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL) { @@ -218,8 +218,14 @@ namespace MWRender void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData, int cellX, int cellY, int fromX, int fromY, int size, - std::map& indexes) + std::map& indexes, + size_t plugin) { + // FIXME: In a multiple esm configuration, we have multiple palettes. Since this code + // crosses cell boundaries, we no longer have a unique terrain palette. Instead, we need + // to adopt the following code for a dynamic palette. And this is evil - the current design + // does not work well for this task... + assert(terrainData != NULL && "Must have valid terrain data"); assert(fromX >= 0 && fromY >= 0 && "Can't get a terrain texture on terrain outside the current cell"); @@ -232,12 +238,16 @@ namespace MWRender // //If we don't sort the ltex indexes, the splatting order may differ between //cells which may lead to inconsistent results when shading between cells + int num = MWBase::Environment::get().getWorld()->getStore().landTexts.getSizePlugin(plugin); std::set ltexIndexes; for ( int y = fromY - 1; y < fromY + size + 1; y++ ) { for ( int x = fromX - 1; x < fromX + size + 1; x++ ) { - ltexIndexes.insert(getLtexIndexAt(cellX, cellY, x, y)); + int idx = getLtexIndexAt(cellX, cellY, x, y); + if (idx > num) + idx = 0; + ltexIndexes.insert(idx); } } @@ -249,7 +259,7 @@ namespace MWRender iter != ltexIndexes.end(); ++iter ) { - const uint16_t ltexIndex = *iter; + uint16_t ltexIndex = *iter; //this is the base texture, so we can ignore this at present if ( ltexIndex == baseTexture ) { @@ -262,8 +272,10 @@ namespace MWRender { //NB: All vtex ids are +1 compared to the ltex ids - assert( (int)MWBase::Environment::get().getWorld()->getStore().landTexts.getSize() >= (int)ltexIndex - 1 && + /* + assert( (int)mEnvironment.mWorld->getStore().landTexts.getSizePlugin(plugin) >= (int)ltexIndex - 1 && "LAND.VTEX must be within the bounds of the LTEX array"); + */ std::string texture; if ( ltexIndex == 0 ) @@ -272,7 +284,7 @@ namespace MWRender } else { - texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1)->texture; + texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1, plugin)->texture; //TODO this is needed due to MWs messed up texture handling texture = texture.substr(0, texture.rfind(".")) + ".dds"; } diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index 273ede084..5bda71eef 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -63,11 +63,14 @@ namespace MWRender{ * @param size the size (number of splats) to get * @param indexes a mapping of ltex index to the terrain texture layer that * can be used by initTerrainBlendMaps + * @param plugin the index of the plugin providing the texture list for this + * cell data; required because MW uses texture data on a per-plugin base */ void initTerrainTextures(Ogre::Terrain::ImportData* terrainData, int cellX, int cellY, int fromX, int fromY, int size, - std::map& indexes); + std::map& indexes, + size_t plugin = 0); /** * Creates the blend (splatting maps) for the given terrain from the ltex data. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index e8d555689..fe3ddd5a8 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -176,7 +176,8 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, - const std::string& master, const boost::filesystem::path& resDir, bool newGame, + const std::vector& master, + const std::vector& plugins, const boost::filesystem::path& resDir, bool newGame, const std::string& encoding, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mNextDynamicRecord (0), mCells (mStore, mEsm, *this), @@ -189,15 +190,32 @@ namespace MWWorld mWeatherManager = new MWWorld::WeatherManager(mRendering); - boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); + int idx = 0; + for (std::vector::size_type i = 0; i < master.size(); i++, idx++) + { + boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i])); + + std::cout << "Loading ESM " << masterPath.string() << "\n"; - std::cout << "Loading ESM " << masterPath.string() << "\n"; + // This parses the ESM file and loads a sample cell + mEsm.setEncoding(encoding); + mEsm.open (masterPath.string()); + mEsm.setIndex(idx); + mStore.load (mEsm); + } - // This parses the ESM file and loads a sample cell - mEsm.setEncoding(encoding); - mEsm.open (masterPath.string()); - mStore.load (mEsm); + for (std::vector::size_type i = 0; i < plugins.size(); i++, idx++) + { + boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i])); + + std::cout << "Loading ESP " << pluginPath.string() << "\n"; + // This parses the ESP file and loads a sample cell + mEsm.setEncoding(encoding); + mEsm.open (pluginPath.string()); + mEsm.setIndex(idx); + mStore.load (mEsm); + } MWRender::Player* play = &(mRendering->getPlayer()); mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this); mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index e8391773b..9e36765ff 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -117,7 +117,8 @@ namespace MWWorld World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, - const std::string& master, const boost::filesystem::path& resDir, bool newGame, + const std::vector& master, + const std::vector& plugins, const boost::filesystem::path& resDir, bool newGame, const std::string& encoding, std::map fallbackMap); ~World(); diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 340482891..4d61c3575 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -193,6 +193,14 @@ public: void openRaw(const std::string &file); + // This is a quick hack for multiple esm/esp files. Each plugin introduces its own + // terrain palette, but ESMReader does not pass a reference to the correct plugin + // to the individual load() methods. This hack allows to pass this reference + // indirectly to the load() method. + int idx; + void setIndex(const int index) {idx = index;} + const int getIndex() {return idx;} + /************************************************************************* * * Medium-level reading shortcuts diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 96afdf831..822952c91 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -23,6 +23,7 @@ Land::~Land() void Land::load(ESMReader &esm) { mEsm = &esm; + plugin = mEsm->getIndex(); // Get the grid location esm.getSubNameIs("INTV"); diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index ebc314a28..d03012d38 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -17,6 +17,7 @@ struct Land int flags; // Only first four bits seem to be used, don't know what // they mean. int X, Y; // Map coordinates. + int plugin; // Plugin index, used to reference the correct material palette. // File context. This allows the ESM reader to be 'reset' to this // location later when we are ready to load the full data set. diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 48bf050cd..dd66d718a 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -26,6 +26,7 @@ namespace ESMS virtual void load(ESMReader &esm, const std::string &id) = 0; virtual int getSize() = 0; + virtual void remove(const std::string &id) {}; virtual void listIdentifier (std::vector& identifier) const = 0; static std::string toLower (const std::string& name) @@ -57,6 +58,14 @@ namespace ESMS list[id2].load(esm); } + // Delete the given object ID + void remove(const std::string &id) + { + std::string id2 = toLower (id); + + list.erase(id2); + } + // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { @@ -268,38 +277,57 @@ namespace ESMS { virtual ~LTexList() {} - // TODO: For multiple ESM/ESP files we need one list per file. - std::vector ltex; + // For multiple ESM/ESP files we need one list per file. + typedef std::vector LandTextureList; + std::vector ltex; LTexList() { + ltex.push_back(LandTextureList()); + LandTextureList <exl = ltex[0]; // More than enough to hold Morrowind.esm. - ltex.reserve(128); + ltexl.reserve(128); } - const LandTexture* search(size_t index) const + const LandTexture* search(size_t index, size_t plugin) const { - assert(index < ltex.size()); - return <ex.at(index); + assert(plugin < ltex.size()); + const LandTextureList <exl = ltex[plugin]; + + assert(index < ltexl.size()); + return <exl.at(index); } int getSize() { return ltex.size(); } int getSize() const { return ltex.size(); } - virtual void listIdentifier (std::vector& identifier) const {} + int getSizePlugin(size_t plugin) { assert(plugin < ltex.size()); return ltex[plugin].size(); } + int getSizePlugin(size_t plugin) const { assert(plugin < ltex.size()); return ltex[plugin].size(); } - void load(ESMReader &esm, const std::string &id) + virtual void listIdentifier (std::vector& identifier) const {} + + void load(ESMReader &esm, const std::string &id, size_t plugin) { LandTexture lt; lt.load(esm); lt.id = id; // Make sure we have room for the structure - if(lt.index + 1 > (int)ltex.size()) - ltex.resize(lt.index+1); + if (plugin >= ltex.size()) { + ltex.resize(plugin+1); + } + LandTextureList <exl = ltex[plugin]; + if(lt.index + 1 > (int)ltexl.size()) + ltexl.resize(lt.index+1); // Store it - ltex[lt.index] = lt; + ltexl[lt.index] = lt; + } + + void load(ESMReader &esm, const std::string &id) + { + size_t plugin = esm.getIndex(); + load(esm, id, plugin); } }; diff --git a/components/esm_store/store.cpp b/components/esm_store/store.cpp index c676601e5..b6972355c 100644 --- a/components/esm_store/store.cpp +++ b/components/esm_store/store.cpp @@ -67,6 +67,13 @@ void ESMStore::load(ESMReader &esm) { // Load it std::string id = esm.getHNOString("NAME"); + // ... unless it got deleted! + if (esm.isNextSub("DELE")) { + esm.skipRecord(); + all.erase(id); + it->second->remove(id); + continue; + } it->second->load(esm, id); if (n.val==ESM::REC_DIAL) From 395a7600fd061c73a24007d902c3148a31bb5038 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 10 Jul 2012 23:13:03 -0700 Subject: [PATCH 002/126] Initialize identify transform when declaring the identity object --- components/nif/nif_types.hpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/components/nif/nif_types.hpp b/components/nif/nif_types.hpp index 705ed5994..f364cd2d4 100644 --- a/components/nif/nif_types.hpp +++ b/components/nif/nif_types.hpp @@ -41,17 +41,9 @@ struct Transformation static const Transformation& getIdentity() { - static Transformation identity; - static bool iset = false; - if (!iset) - { - identity.scale = 1.0f; - identity.rotation[0][0] = 1.0f; - identity.rotation[1][1] = 1.0f; - identity.rotation[2][2] = 1.0f; - iset = true; - } - + static const Transformation identity = { + Ogre::Vector3::ZERO, Ogre::Matrix3::IDENTITY, 1.0f, Ogre::Vector3::ZERO + }; return identity; } }; From 8e324c90dcecf5c5655f89aaa37e693587bd4950 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 11 Jul 2012 06:37:17 -0700 Subject: [PATCH 003/126] Constify some RecordPtrT methods --- components/nif/record_ptr.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/nif/record_ptr.hpp b/components/nif/record_ptr.hpp index 755094147..7e6a43f53 100644 --- a/components/nif/record_ptr.hpp +++ b/components/nif/record_ptr.hpp @@ -71,18 +71,21 @@ public: } /// Look up the actual object from the index - X* getPtr() + X* getPtr() const { assert(ptr != NULL); return ptr; } - X& get() { return *getPtr(); } + X& get() const + { return *getPtr(); } /// Syntactic sugar - X* operator->() { return getPtr(); } + X* operator->() const + { return getPtr(); } /// Pointers are allowed to be empty - bool empty() { return ptr == NULL; } + bool empty() const + { return ptr == NULL; } }; /** A list of references to other records. These are read as a list, From 7e8c146de629b387d71a9eb5406f9e43a4640c31 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 11 Jul 2012 06:39:03 -0700 Subject: [PATCH 004/126] Constify some RecordListT methods --- components/nif/record_ptr.hpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/components/nif/record_ptr.hpp b/components/nif/record_ptr.hpp index 7e6a43f53..8f8fc244a 100644 --- a/components/nif/record_ptr.hpp +++ b/components/nif/record_ptr.hpp @@ -114,17 +114,13 @@ public: list[i].post(nif); } - X& operator[](size_t index) - { - return list.at(index).get(); - } + X& operator[](size_t index) const + { return list.at(index).get(); } - bool has(size_t index) - { - return !list.at(index).empty(); - } + bool has(size_t index) const + { return !list.at(index).empty(); } - size_t length() + size_t length() const { return list.size(); } }; From 645b507ba06a34be6aaa9a75eb1a6b2cc409da48 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 05:37:56 -0700 Subject: [PATCH 005/126] Return a reference to the RecordPtr from operator[] for consistency RecordListT is supposed to be a list of RecordPtrT objects. --- components/nif/nif_file.cpp | 4 ++-- components/nif/node.hpp | 4 ++-- components/nif/record_ptr.hpp | 7 ++----- components/nifbullet/bullet_nif_loader.cpp | 12 ++++++------ components/nifogre/ogre_nif_loader.cpp | 18 ++++++++---------- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 36badbf0d..231349302 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -205,8 +205,8 @@ void NiSkinInstance::post(NIFFile *nif) for(size_t i=0; ifail("Oops: Missing bone! Don't know how to handle this."); - bones[i].makeBone(i, data->bones[i]); + bones[i]->makeBone(i, data->bones[i]); } } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 64ef1e3e9..e7ba03276 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -151,8 +151,8 @@ struct NiNode : Node for(size_t i = 0;i < children.length();i++) { // Why would a unique list of children contain empty refs? - if(children.has(i)) - children[i].parent = this; + if(!children[i].empty()) + children[i]->parent = this; } } }; diff --git a/components/nif/record_ptr.hpp b/components/nif/record_ptr.hpp index 8f8fc244a..ef5bb1dee 100644 --- a/components/nif/record_ptr.hpp +++ b/components/nif/record_ptr.hpp @@ -114,11 +114,8 @@ public: list[i].post(nif); } - X& operator[](size_t index) const - { return list.at(index).get(); } - - bool has(size_t index) const - { return !list.at(index).empty(); } + const Ptr& operator[](size_t index) const + { return list.at(index); } size_t length() const { return list.size(); } diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 4105c4c79..bfcaf36e5 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -138,9 +138,9 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node) int n = list.length(); for (int i=0; itrafo,hasCollisionNode,isCollisionNode,raycastingOnly); + handleNode(list[i].getPtr(), flags,&node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly); } } } @@ -239,8 +239,8 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, int n = list.length(); for (int i=0; itrafo, hasCollisionNode,true,raycastingOnly); + if (!list[i].empty()) + handleNode(list[i].getPtr(), flags,&node->trafo, hasCollisionNode,true,raycastingOnly); } } } diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index aca1966b9..643d7acf8 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -649,10 +649,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou for (int i=0; irecType == RC_NiTexturingProperty) t = static_cast(pr); else if (pr->recType == RC_NiMaterialProperty) @@ -803,13 +802,13 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou { if(mSkel.isNull()) { - std::cout << "No skeleton for :" << shape->skin->bones[boneIndex].name << std::endl; + std::cout << "No skeleton for :" << shape->skin->bones[boneIndex]->name << std::endl; break; } //get the bone from bones array of skindata - if(!mSkel->hasBone(shape->skin->bones[boneIndex].name)) + if(!mSkel->hasBone(shape->skin->bones[boneIndex]->name)) std::cout << "We don't have this bone"; - bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name); + bonePtr = mSkel->getBone(shape->skin->bones[boneIndex]->name); // final_vector = old_vector + old_rotation*new_vector*old_scale @@ -817,7 +816,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou Nif::NiSkinData::BoneInfoCopy boneinfocopy; boneinfocopy.trafo.rotation = it->trafo.rotation; boneinfocopy.trafo.trans = it->trafo.trans; - boneinfocopy.bonename = shape->skin->bones[boneIndex].name; + boneinfocopy.bonename = shape->skin->bones[boneIndex]->name; boneinfocopy.bonehandle = bonePtr->getHandle(); copy.boneinfo.push_back(boneinfocopy); for (unsigned int i=0; iweights.size(); i++) @@ -1138,9 +1137,8 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, int n = list.length(); for (int i = 0; itrafo, bounds, bone, boneSequence); + if (!list[i].empty()) + handleNode(list[i].getPtr(), flags, &node->trafo, bounds, bone, boneSequence); } } else if (node->recType == RC_NiTriShape && bNiTri) From b7b9f1133305ad05450b3c8e5ed83c523075ebb7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 06:47:38 -0700 Subject: [PATCH 006/126] Add generic classes to help deal with NIF keys --- components/nif/nif_file.hpp | 88 +++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index a21882c6d..9e0f6972b 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -98,6 +100,12 @@ public: throw std::runtime_error(err); } + void warn(const std::string &msg) + { + std::cerr<< "NIFFile Warning: "< +struct KeyT { + float mTime; + T mValue; + T mForwardValue; // Only for Quadratic interpolation + T mBackwardValue; // Only for Quadratic interpolation + float mTension; // Only for TBC interpolation + float mBias; // Only for TBC interpolation + float mContinuity; // Only for TBC interpolation +}; +typedef KeyT FloatKey; +typedef KeyT Vector3Key; +typedef KeyT QuaternionKey; + +template +struct KeyListT { + typedef std::vector< KeyT > VecType; + + static const int sLinearInterpolation = 1; + static const int sQuadraticInterpolation = 2; + static const int sTBCInterpolation = 3; + + int mInterpolationType; + VecType mKeys; + + void read(NIFFile *nif) + { + size_t count = nif->getInt(); + if(count == 0) return; + + mInterpolationType = nif->getInt(); + mKeys.resize(count); + if(mInterpolationType == sLinearInterpolation) + { + for(size_t i = 0;i < count;i++) + { + KeyT &key = mKeys[i]; + key.mTime = nif->getFloat(); + key.mValue = (nif->*getValue)(); + } + } + else if(mInterpolationType == sQuadraticInterpolation) + { + for(size_t i = 0;i < count;i++) + { + KeyT &key = mKeys[i]; + key.mTime = nif->getFloat(); + key.mValue = (nif->*getValue)(); + key.mForwardValue = (nif->*getValue)(); + key.mBackwardValue = (nif->*getValue)(); + } + } + else if(mInterpolationType == sTBCInterpolation) + { + for(size_t i = 0;i < count;i++) + { + KeyT &key = mKeys[i]; + key.mTime = nif->getFloat(); + key.mValue = (nif->*getValue)(); + key.mTension = nif->getFloat(); + key.mBias = nif->getFloat(); + key.mContinuity = nif->getFloat(); + } + } + else + nif->warn("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType)); + } +}; +typedef KeyListT FloatKeyList; +typedef KeyListT Vector3KeyList; +typedef KeyListT QuaternionKeyList; + } // Namespace #endif From b292665de90d444d69ea9af0750cb117db233859 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 08:00:26 -0700 Subject: [PATCH 007/126] Use key lists to store some NIF data types --- components/nif/data.hpp | 47 +++++++++-------------------------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index ad670bc5e..552e53b68 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -202,61 +202,34 @@ public: class NiPosData : public Record { public: + Vector3KeyList mKeyList; + void read(NIFFile *nif) { - int count = nif->getInt(); - int type = nif->getInt(); - if(type != 1 && type != 2) - nif->fail("Cannot handle NiPosData type"); - - // TODO: Could make structs of these. Seems to be identical to - // translation in NiKeyframeData. - for(int i=0; igetFloat(); - nif->getVector3(); // This isn't really shared between type 1 - // and type 2, most likely - if(type == 2) - { - nif->getVector3(); - nif->getVector3(); - } - } + mKeyList.read(nif); } }; class NiUVData : public Record { public: + FloatKeyList mKeyList[4]; + void read(NIFFile *nif) { - // TODO: This is claimed to be a "float animation key", which is - // also used in FloatData and KeyframeData. We could probably - // reuse and refactor a lot of this if we actually use it at some - // point. - for(int i=0; i<2; i++) - { - int count = nif->getInt(); - if(count) - { - nif->getInt(); // always 2 - nif->skip(count * (sizeof(float) + 3*sizeof(float))); // Really one time float + one vector - } - } - // Always 0 - nif->getInt(); - nif->getInt(); + for(int i = 0;i < 4;i++) + mKeyList[i].read(nif); } }; class NiFloatData : public Record { public: + FloatKeyList mKeyList; + void read(NIFFile *nif) { - int count = nif->getInt(); - nif->getInt(); // always 2 - nif->skip(count * (sizeof(float) + 3*sizeof(float))); // Really one time float + one vector + mKeyList.read(nif); } }; From 86b37c6c11b59ff7a9c6bf7c214b12ef9c53eb66 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 11:21:52 -0700 Subject: [PATCH 008/126] Move the velocity out of the transformation object --- components/nif/nif_file.hpp | 1 - components/nif/nif_types.hpp | 3 +-- components/nif/node.hpp | 2 ++ components/nifbullet/bullet_nif_loader.cpp | 1 - components/nifogre/ogre_nif_loader.cpp | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index 9e0f6972b..fa152f14d 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -179,7 +179,6 @@ public: t.pos = getVector3(); t.rotation = getMatrix3(); t.scale = getFloat(); - t.velocity = getVector3(); return t; } diff --git a/components/nif/nif_types.hpp b/components/nif/nif_types.hpp index f364cd2d4..a5fb61361 100644 --- a/components/nif/nif_types.hpp +++ b/components/nif/nif_types.hpp @@ -37,12 +37,11 @@ struct Transformation Ogre::Vector3 pos; Ogre::Matrix3 rotation; float scale; - Ogre::Vector3 velocity; static const Transformation& getIdentity() { static const Transformation identity = { - Ogre::Vector3::ZERO, Ogre::Matrix3::IDENTITY, 1.0f, Ogre::Vector3::ZERO + Ogre::Vector3::ZERO, Ogre::Matrix3::IDENTITY, 1.0f }; return identity; } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index e7ba03276..293793009 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -43,6 +43,7 @@ public: // Node flags. Interpretation depends somewhat on the type of node. int flags; Transformation trafo; + Ogre::Vector3 velocity; // Unused? Might be a run-time game state PropertyList props; // Bounding box info @@ -57,6 +58,7 @@ public: flags = nif->getUShort(); trafo = nif->getTrafo(); + velocity = nif->getVector3(); props.read(nif); hasBounds = !!nif->getInt(); diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index bfcaf36e5..c3b34e039 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -204,7 +204,6 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, // For both position and rotation we have that: // final_vector = old_vector + old_rotation*new_vector*old_scale final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale; - final.velocity = trafo->velocity + trafo->rotation*final.velocity*trafo->scale; // Merge the rotations together final.rotation = trafo->rotation * final.rotation; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 643d7acf8..36c5d3b1b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1121,7 +1121,6 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, // For both position and rotation we have that: // final_vector = old_vector + old_rotation*new_vector*old_scale final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale; - final.velocity = trafo->velocity + trafo->rotation*final.velocity*trafo->scale; // Merge the rotations together final.rotation = trafo->rotation * final.rotation; From 3f11b6b1ae961cc745a8624904f1f728b7aea246 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 12:01:11 -0700 Subject: [PATCH 009/126] Cleanup a couple unneeded misc component references --- components/nif/record.hpp | 2 +- components/nifogre/ogre_nif_loader.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 84f253eb8..5c4141fa9 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -24,7 +24,7 @@ #ifndef _NIF_RECORD_H_ #define _NIF_RECORD_H_ -#include +#include namespace Nif { diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 36c5d3b1b..014384dd4 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -40,7 +40,6 @@ typedef unsigned char ubyte; using namespace std; using namespace Nif; -using namespace Misc; using namespace NifOgre; NIFLoader& NIFLoader::getSingleton() From 9995dff943592d85b2d3b9e2bbeaa75a74807dfd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 14:33:50 -0700 Subject: [PATCH 010/126] Use a key list for NiColorData --- components/nif/data.hpp | 12 ++---------- components/nif/nif_file.hpp | 2 ++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 552e53b68..b7e2f172f 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -275,19 +275,11 @@ public: class NiColorData : public Record { public: - struct ColorData - { - float time; - Ogre::Vector4 rgba; - }; + Vector4KeyList mKeyList; void read(NIFFile *nif) { - int count = nif->getInt(); - nif->getInt(); // always 1 - - // Skip the data - nif->skip(count * 5*sizeof(float)); + mKeyList.read(nif); } }; diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index fa152f14d..c33790742 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -223,6 +223,7 @@ struct KeyT { }; typedef KeyT FloatKey; typedef KeyT Vector3Key; +typedef KeyT Vector4Key; typedef KeyT QuaternionKey; template @@ -281,6 +282,7 @@ struct KeyListT { }; typedef KeyListT FloatKeyList; typedef KeyListT Vector3KeyList; +typedef KeyListT Vector4KeyList; typedef KeyListT QuaternionKeyList; } // Namespace From 386ac56bdab827ef604362787d232d8278ff1d7e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 20:12:18 -0700 Subject: [PATCH 011/126] Remove the NIF loader and code to manually transform the vertices This currently breaks just about everything. They should come back as it's all reimplemented, though. --- apps/openmw/engine.cpp | 7 +- apps/openmw/mwrender/animation.cpp | 660 +++------- apps/openmw/mwrender/animation.hpp | 53 +- apps/openmw/mwrender/creatureanimation.cpp | 56 +- apps/openmw/mwrender/npcanimation.cpp | 1294 +++++++++----------- apps/openmw/mwrender/npcanimation.hpp | 94 +- components/bsa/bsa_archive.cpp | 54 +- components/nif/data.hpp | 20 - components/nif/node.hpp | 36 - components/nifbullet/bullet_nif_loader.cpp | 2 +- components/nifogre/ogre_nif_loader.cpp | 1112 +---------------- components/nifogre/ogre_nif_loader.hpp | 98 +- libs/openengine/bullet/physic.cpp | 2 +- 13 files changed, 873 insertions(+), 2615 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 45b4ab514..fded32560 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -75,11 +75,8 @@ void OMW::Engine::executeLocalScripts() localScripts.setIgnore (MWWorld::Ptr()); } -void OMW::Engine::setAnimationVerbose(bool animverbose){ - if(animverbose){ - NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true); - NifOgre::NIFLoader::getSingletonPtr()->setVerbosePath(mCfgMgr.getLogPath().string()); - } +void OMW::Engine::setAnimationVerbose(bool animverbose) +{ } bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index f0a6ab683..7e50706f9 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -6,498 +6,236 @@ #include #include -namespace MWRender{ - std::map Animation::mUniqueIDs; +namespace MWRender { - Animation::Animation(OEngine::Render::OgreRenderer& _rend) - : insert(NULL) - , mRend(_rend) - , vecRotPos() - , time(0.0f) - , startTime(0.0f) - , stopTime(0.0f) - , animate(0) - , rindexI() - , tindexI() - , shapeNumber(0) - , shapeIndexI() - , shapes(NULL) - , transformations(NULL) - , textmappings(NULL) - , base(NULL) - { - } +std::map Animation::mUniqueIDs; - Animation::~Animation() - { - } - - std::string Animation::getUniqueID(std::string mesh){ - int counter; - std::string copy = mesh; - std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower); - if(mUniqueIDs.find(copy) == mUniqueIDs.end()){ - counter = mUniqueIDs[copy] = 0; - } - else{ - mUniqueIDs[copy] = mUniqueIDs[copy] + 1; - counter = mUniqueIDs[copy]; - } - - std::stringstream out; - if(counter > 99 && counter < 1000) - out << "0"; - else if(counter > 9) - out << "00"; - else - out << "000"; - out << counter; - return out.str(); +Animation::Animation(OEngine::Render::OgreRenderer& _rend) + : insert(NULL) + , mRend(_rend) + , time(0.0f) + , startTime(0.0f) + , stopTime(0.0f) + , animate(0) + , rindexI() + , tindexI() + , shapeNumber(0) + , shapeIndexI() + , transformations(NULL) + , textmappings(NULL) + , base(NULL) +{ } - void Animation::startScript(std::string groupname, int mode, int loops){ - //If groupname is recognized set animate to true - //Set the start time and stop time - //How many times to loop - if(groupname == "all"){ - animate = loops; - time = startTime; - } - else if(textmappings){ - std::string startName = groupname + ": loop start"; - std::string stopName = groupname + ": loop stop"; +Animation::~Animation() +{ +} - bool first = false; - - if(loops > 1){ - startName = groupname + ": loop start"; - stopName = groupname + ": loop stop"; - - for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ - - std::string current = iter->first.substr(0, startName.size()); - std::transform(current.begin(), current.end(), current.begin(), ::tolower); - std::string current2 = iter->first.substr(0, stopName.size()); - std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); - - if(current == startName){ - startTime = iter->second; - animate = loops; - time = startTime; - first = true; - } - if(current2 == stopName){ - stopTime = iter->second; - if(first) - break; - } - } - } - if(!first){ - startName = groupname + ": start"; - stopName = groupname + ": stop"; - - for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ - - std::string current = iter->first.substr(0, startName.size()); - std::transform(current.begin(), current.end(), current.begin(), ::tolower); - std::string current2 = iter->first.substr(0, stopName.size()); - std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); - - if(current == startName){ - startTime = iter->second; - animate = loops; - time = startTime; - first = true; - } - if(current2 == stopName){ - stopTime = iter->second; - if(first) - break; - } - } - } - - } - - } - void Animation::stopScript(){ - animate = 0; +void Animation::startScript(std::string groupname, int mode, int loops) +{ + //If groupname is recognized set animate to true + //Set the start time and stop time + //How many times to loop + if(groupname == "all") + { + animate = loops; + time = startTime; } + else if(textmappings) + { + std::string startName = groupname + ": loop start"; + std::string stopName = groupname + ": loop stop"; - void Animation::handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ - shapeNumber = 0; + bool first = false; - if (allshapes == NULL || creaturemodel == NULL || skel == NULL) + if(loops > 1) { - return; + startName = groupname + ": loop start"; + stopName = groupname + ": loop stop"; + + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++) + { + std::string current = iter->first.substr(0, startName.size()); + std::transform(current.begin(), current.end(), current.begin(), ::tolower); + std::string current2 = iter->first.substr(0, stopName.size()); + std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); + + if(current == startName) + { + startTime = iter->second; + animate = loops; + time = startTime; + first = true; + } + if(current2 == stopName) + { + stopTime = iter->second; + if(first) + break; + } + } } - std::vector::iterator allshapesiter; - for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++) + if(!first) + { + startName = groupname + ": start"; + stopName = groupname + ": stop"; + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++) + { + std::string current = iter->first.substr(0, startName.size()); + std::transform(current.begin(), current.end(), current.begin(), ::tolower); + std::string current2 = iter->first.substr(0, stopName.size()); + std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); + + if(current == startName) { - //std::map vecPosRot; - - Nif::NiTriShapeCopy& copy = *allshapesiter; - std::vector* allvertices = ©.vertices; - - - - //std::set vertices; - //std::set normals; - //std::vector boneinfovector = copy.boneinfo; - std::map >* verticesToChange = ©.vertsToWeights; - - //std::cout << "Name " << copy.sname << "\n"; - Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); - Ogre::Real* pReal = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); - - - std::vector initialVertices = copy.morph.getInitialVertices(); - //Each shape has multiple indices - if(initialVertices.size() ) - { - - if(copy.vertices.size() == initialVertices.size()) - { - //Create if it doesn't already exist - if(shapeIndexI.size() == static_cast (shapeNumber)) - { - std::vector vec; - shapeIndexI.push_back(vec); - } - if(time >= copy.morph.getStartTime() && time <= copy.morph.getStopTime()){ - float x; - for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++){ - int j = 0; - if(shapeIndexI[shapeNumber].size() <= i) - shapeIndexI[shapeNumber].push_back(0); - - - if(timeIndex(time,copy.morph.getRelevantTimes()[i],(shapeIndexI[shapeNumber])[i], j, x)){ - int indexI = (shapeIndexI[shapeNumber])[i]; - std::vector relevantData = (copy.morph.getRelevantData()[i]); - float v1 = relevantData[indexI].x; - float v2 = relevantData[j].x; - float t = v1 + (v2 - v1) * x; - if ( t < 0 ) t = 0; - if ( t > 1 ) t = 1; - if( t != 0 && initialVertices.size() == copy.morph.getAdditionalVertices()[i].size()) - { - for (unsigned int v = 0; v < initialVertices.size(); v++){ - initialVertices[v] += ((copy.morph.getAdditionalVertices()[i])[v]) * t; - } - } - - } - - - - } - - allvertices = &initialVertices; - } - shapeNumber++; - } - } - - - if(verticesToChange->size() > 0){ - - for(std::map >::iterator iter = verticesToChange->begin(); - iter != verticesToChange->end(); iter++) - { - std::vector inds = iter->second; - int verIndex = iter->first; - Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; - Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); - Ogre::Bone *bonePtr = 0; - - - - Ogre::Vector3 vecPos; - Ogre::Quaternion vecRot; - std::map::iterator result = vecRotPos.find(boneinfocopy); - - if(result == vecRotPos.end()){ - bonePtr = skel->getBone(boneinfocopy->bonename); - - vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; - vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - - - PosAndRot both; - both.vecPos = vecPos; - both.vecRot = vecRot; - vecRotPos[boneinfocopy] = both; - - } - else{ - PosAndRot both = result->second; - vecPos = both.vecPos; - vecRot = both.vecRot; - } - - Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; - - - - for(std::size_t i = 1; i < inds.size(); i++){ - boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); - result = vecRotPos.find(boneinfocopy); - - - if(result == vecRotPos.end()){ - bonePtr = skel->getBone(boneinfocopy->bonename); - vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; - vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - - PosAndRot both; - both.vecPos = vecPos; - both.vecRot = vecRot; - vecRotPos[boneinfocopy] = both; - - } - else{ - PosAndRot both = result->second; - vecPos = both.vecPos; - vecRot = both.vecRot; - } - - - absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; - - - } - Ogre::Real* addr = (pReal + 3 * verIndex); - *addr = absVertPos.x; - *(addr+1) = absVertPos.y; - *(addr+2) = absVertPos.z; - + startTime = iter->second; + animate = loops; + time = startTime; + first = true; } - - - - - } - else - { - //Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename); - Ogre::Quaternion shaperot = copy.trafo.rotation; - Ogre::Vector3 shapetrans = copy.trafo.trans; - float shapescale = copy.trafo.scale; - std::vector boneSequence = copy.boneSequence; - - Ogre::Vector3 transmult; - Ogre::Quaternion rotmult; - float scale; - if(boneSequence.size() > 0){ - std::vector::iterator boneSequenceIter = boneSequence.begin(); - if(skel->hasBone(*boneSequenceIter)){ - Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); - - - - - transmult = bonePtr->getPosition(); - rotmult = bonePtr->getOrientation(); - scale = bonePtr->getScale().x; - boneSequenceIter++; - - for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++) - { - if(skel->hasBone(*boneSequenceIter)){ - Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); - // Computes C = B + AxC*scale - transmult = transmult + rotmult * bonePtr->getPosition(); - rotmult = rotmult * bonePtr->getOrientation(); - scale = scale * bonePtr->getScale().x; - } - //std::cout << "Bone:" << *boneSequenceIter << " "; - } - transmult = transmult + rotmult * shapetrans; - rotmult = rotmult * shaperot; - scale = shapescale * scale; - - //std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n"; - } - } - else - { - transmult = shapetrans; - rotmult = shaperot; - scale = shapescale; - } - - - - - // Computes C = B + AxC*scale - // final_vector = old_vector + old_rotation*new_vector*old_scale/ - - for(unsigned int i = 0; i < allvertices->size(); i++){ - Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i]; - Ogre::Real* addr = pReal + i * 3; - *addr = current.x; - *(addr+1) = current.y; - *(addr + 2) = current.z; - - }/* - for(int i = 0; i < allnormals.size(); i++){ - Ogre::Vector3 current =rotmult * allnormals[i]; - Ogre::Real* addr = pRealNormal + i * 3; - *addr = current.x; - *(addr+1) = current.y; - *(addr + 2) = current.z; - - }*/ - - } - vbuf->unlock(); - - } + if(current2 == stopName) + { + stopTime = iter->second; + if(first) + break; + } + } + } } - bool Animation::timeIndex( float time, const std::vector & times, int & i, int & j, float & x ){ - int count; - if ( (count = times.size()) > 0 ) - { - if ( time <= times[0] ) - { - i = j = 0; - x = 0.0; - return true; - } - if ( time >= times[count - 1] ) - { - i = j = count - 1; - x = 0.0; - return true; - } - - if ( i < 0 || i >= count ) - i = 0; - - float tI = times[i]; - if ( time > tI ) - { - j = i + 1; - float tJ; - while ( time >= ( tJ = times[j]) ) - { - i = j++; - tI = tJ; - } - x = ( time - tI ) / ( tJ - tI ); - return true; - } - else if ( time < tI ) - { - j = i - 1; - float tJ; - while ( time <= ( tJ = times[j] ) ) - { - i = j--; - tI = tJ; - } - x = ( time - tI ) / ( tJ - tI ); - return true; - } - else - { - j = i; - x = 0.0; - return true; - } - } - else - return false; } - void Animation::handleAnimationTransforms(){ + +void Animation::stopScript() +{ + animate = 0; +} +bool Animation::timeIndex(float time, const std::vector ×, int &i, int &j, float &x) +{ + size_t count; + if((count=times.size()) == 0) + return false; + + if(time <= times[0]) + { + i = j = 0; + x = 0.0; + return true; + } + if(time >= times[count-1]) + { + i = j = count - 1; + x = 0.0; + return true; + } + + if(i < 0 || (size_t)i >= count) + i = 0; + + float tI = times[i]; + if(time > tI) + { + j = i + 1; + float tJ; + while(time >= (tJ=times[j])) + { + i = j++; + tI = tJ; + } + x = (time-tI) / (tJ-tI); + return true; + } + + if(time < tI) + { + j = i - 1; + float tJ; + while(time <= (tJ=times[j])) + { + i = j--; + tI = tJ; + } + x = (time-tI) / (tJ-tI); + return true; + } + + j = i; + x = 0.0; + return true; +} + +void Animation::handleAnimationTransforms() +{ Ogre::SkeletonInstance* skel = base->getSkeleton(); - Ogre::Bone* b = skel->getRootBone(); - b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick - - skel->_updateTransforms(); - //skel->_notifyManualBonesDirty(); - - base->getAllAnimationStates()->_notifyDirty(); - //base->_updateAnimation(); - //base->_notifyMoved(); - + b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick + skel->_updateTransforms(); + //skel->_notifyManualBonesDirty(); + base->getAllAnimationStates()->_notifyDirty(); + //base->_updateAnimation(); + //base->_notifyMoved(); std::vector::iterator iter; int slot = 0; - if(transformations){ - for(iter = transformations->begin(); iter != transformations->end(); iter++){ - if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) - { + if(transformations) + { + for(iter = transformations->begin(); iter != transformations->end(); iter++) + { + if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) + { + slot++; + continue; + } + + float x; + float x2; + + const std::vector &quats = iter->getQuat(); + const std::vector &ttime = iter->gettTime(); + const std::vector &rtime = iter->getrTime(); + const std::vector &translist1 = iter->getTranslist1(); + + int rindexJ = rindexI[slot]; + timeIndex(time, rtime, rindexI[slot], rindexJ, x2); + + int tindexJ = tindexI[slot]; + timeIndex(time, ttime, tindexI[slot], tindexJ, x); + + Ogre::Vector3 t; + Ogre::Quaternion r; + + bool bTrans = translist1.size() > 0; + bool bQuats = quats.size() > 0; + if(skel->hasBone(iter->getBonename())) + { + Ogre::Bone* bone = skel->getBone(iter->getBonename()); + if(bTrans) + { + Ogre::Vector3 v1 = translist1[tindexI[slot]]; + Ogre::Vector3 v2 = translist1[tindexJ]; + t = (v1 + (v2 - v1) * x); + bone->setPosition(t); + } + if(bQuats) + { + r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); + bone->setOrientation(r); + } + } + slot++; - continue; - } - - float x; - float x2; - - const std::vector & quats = iter->getQuat(); - - const std::vector & ttime = iter->gettTime(); - - - const std::vector & rtime = iter->getrTime(); - int rindexJ = rindexI[slot]; - - timeIndex(time, rtime, rindexI[slot], rindexJ, x2); - int tindexJ = tindexI[slot]; - - - const std::vector & translist1 = iter->getTranslist1(); - - timeIndex(time, ttime, tindexI[slot], tindexJ, x); - - Ogre::Vector3 t; - Ogre::Quaternion r; - - bool bTrans = translist1.size() > 0; - - - bool bQuats = quats.size() > 0; - - if(skel->hasBone(iter->getBonename())){ - Ogre::Bone* bone = skel->getBone(iter->getBonename()); - if(bTrans){ - Ogre::Vector3 v1 = translist1[tindexI[slot]]; - Ogre::Vector3 v2 = translist1[tindexJ]; - t = (v1 + (v2 - v1) * x); - bone->setPosition(t); - - } - if(bQuats){ - r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); - bone->setOrientation(r); - } - - - - - - } - - - slot++; - } - skel->_updateTransforms(); + } + skel->_updateTransforms(); base->getAllAnimationStates()->_notifyDirty(); -} + } } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 4ab60cff4..9d5404305 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -12,60 +12,47 @@ -namespace MWRender{ +namespace MWRender { -struct PosAndRot{ +struct PosAndRot { Ogre::Quaternion vecRot; Ogre::Vector3 vecPos; }; -class Animation{ - - protected: +class Animation { +protected: Ogre::SceneNode* insert; OEngine::Render::OgreRenderer &mRend; - std::map vecRotPos; static std::map mUniqueIDs; - - - - float time; - float startTime; - float stopTime; - int animate; - //Represents a rotation index for each bone - std::vectorrindexI; + float startTime; + float stopTime; + int animate; + //Represents a rotation index for each bone + std::vectorrindexI; //Represents a translation index for each bone - std::vectortindexI; - - //Only shapes with morphing data will use a shape number - int shapeNumber; - std::vector > shapeIndexI; - - //Ogre::SkeletonInstance* skel; - std::vector* shapes; //All the NiTriShapeData for a creature - + std::vectortindexI; + //Only shapes with morphing data will use a shape number + int shapeNumber; + std::vector > shapeIndexI; std::vector* transformations; std::map* textmappings; Ogre::Entity* base; - void handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel); void handleAnimationTransforms(); bool timeIndex( float time, const std::vector & times, int & i, int & j, float & x ); - std::string getUniqueID(std::string mesh); - public: - Animation(OEngine::Render::OgreRenderer& _rend); - virtual void runAnimation(float timepassed) = 0; - void startScript(std::string groupname, int mode, int loops); - void stopScript(); +public: + Animation(OEngine::Render::OgreRenderer& _rend); + virtual void runAnimation(float timepassed) = 0; + void startScript(std::string groupname, int mode, int loops); + void stopScript(); - virtual ~Animation(); - + virtual ~Animation(); }; + } #endif diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index e1fa7868c..6bdd58ac3 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -12,20 +12,22 @@ using namespace Ogre; using namespace NifOgre; namespace MWRender{ -CreatureAnimation::~CreatureAnimation(){ - +CreatureAnimation::~CreatureAnimation() +{ } -CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend): Animation(_rend){ + +CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend): Animation(_rend) +{ insert = ptr.getRefData().getBaseNode(); - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); - if(!ref->base->model.empty()){ - const std::string &mesh = "meshes\\" + ref->base->model; - std::string meshNumbered = mesh + getUniqueID(mesh) + ">|"; - NifOgre::NIFLoader::load(meshNumbered); - base = mRend.getScene()->createEntity(meshNumbered); + if(!ref->base->model.empty()) + { + std::string mesh = "meshes\\" + ref->base->model; + + NifOgre::NIFLoader::load(mesh); + base = mRend.getScene()->createEntity(mesh); base->setVisibilityFlags(RV_Actors); bool transparent = false; @@ -48,33 +50,22 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - std::string meshZero = mesh + "0000>|"; - - if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){ - - for(std::size_t init = 0; init < transformations->size(); init++){ - rindexI.push_back(0); - tindexI.push_back(0); - } - stopTime = transformations->begin()->getStopTime(); - startTime = transformations->begin()->getStartTime(); - shapes = (NIFLoader::getSingletonPtr())->getShapes(meshZero); - } - textmappings = NIFLoader::getSingletonPtr()->getTextIndices(meshZero); insert->attachObject(base); } } -void CreatureAnimation::runAnimation(float timepassed){ - vecRotPos.clear(); - if(animate > 0){ - //Add the amount of time passed to time +void CreatureAnimation::runAnimation(float timepassed) +{ + if(animate > 0) + { + //Add the amount of time passed to time - //Handle the animation transforms dependent on time + //Handle the animation transforms dependent on time - //Handle the shapes dependent on animation transforms + //Handle the shapes dependent on animation transforms time += timepassed; - if(time >= stopTime){ + if(time >= stopTime) + { animate--; //std::cout << "Stopping the animation\n"; if(animate == 0) @@ -84,8 +75,7 @@ void CreatureAnimation::runAnimation(float timepassed){ } handleAnimationTransforms(); - handleShapes(shapes, base, base->getSkeleton()); + } +} - } -} } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index fa88b7277..fa33d18ff 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -13,13 +13,16 @@ using namespace Ogre; using namespace NifOgre; -namespace MWRender{ -NpcAnimation::~NpcAnimation(){ +namespace MWRender{ + +NpcAnimation::~NpcAnimation() +{ } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv): Animation(_rend), mStateID(-1), inv(_inv), timeToChange(0), +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv) + : Animation(_rend), mStateID(-1), inv(_inv), timeToChange(0), robe(inv.end()), helmet(inv.end()), shirt(inv.end()), cuirass(inv.end()), greaves(inv.end()), leftpauldron(inv.end()), rightpauldron(inv.end()), @@ -27,98 +30,59 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere leftglove(inv.end()), rightglove(inv.end()), skirtiter(inv.end()), pants(inv.end()), lclavicle(0), - rclavicle(0), - rupperArm(0), - lupperArm(0), - rUpperLeg(0), - lUpperLeg(0), - lForearm(0), - rForearm(0), - lWrist(0), - rWrist(0), - rKnee(0), - lKnee(0), - neck(0), - rAnkle(0), - lAnkle(0), - groin(0), - lfoot(0), - rfoot(0) + rclavicle(0), + rupperArm(0), + lupperArm(0), + rUpperLeg(0), + lUpperLeg(0), + lForearm(0), + rForearm(0), + lWrist(0), + rWrist(0), + rKnee(0), + lKnee(0), + neck(0), + rAnkle(0), + lAnkle(0), + groin(0), + lfoot(0), + rfoot(0) +{ + MWWorld::LiveCellRef *ref = ptr.get(); + + for (int init = 0; init < 27; init++) { - MWWorld::LiveCellRef *ref = - ptr.get(); - Ogre::Entity* blank = 0; - std::vector* blankshape = 0; - zero = std::make_pair(blank, blankshape); - chest = std::make_pair(blank, blankshape); - tail = std::make_pair(blank, blankshape); - lFreeFoot = std::make_pair(blank, blankshape); - rFreeFoot = std::make_pair(blank, blankshape); - rhand = std::make_pair(blank, blankshape); - lhand = std::make_pair(blank, blankshape); - skirt = std::make_pair(blank, blankshape); - for (int init = 0; init < 27; init++){ - partslots[init] = -1; //each slot is empty - partpriorities[init] = 0; - } + partslots[init] = -1; //each slot is empty + partpriorities[init] = 0; + } + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Race *race = store.races.find(ref->base->race); - //Part selection on last character of the file string - // " Tri Chest - // * Tri Tail - // : Tri Left Foot - // < Tri Right Foot - // > Tri Left Hand - // ? Tri Right Hand - // | Normal + std::string hairID = ref->base->hair; + std::string headID = ref->base->head; + headModel = "meshes\\" + store.bodyParts.find(headID)->model; + hairModel = "meshes\\" + store.bodyParts.find(hairID)->model; + npcName = ref->base->name; - //Mirroring Parts on second to last character - //suffix == '*' - // vector = Ogre::Vector3(-1,1,1); - // suffix == '?' - // vector = Ogre::Vector3(1,-1,1); - // suffix == '<' - // vector = Ogre::Vector3(1,1,-1); + isFemale = !!(ref->base->flags&ESM::NPC::Female); + isBeast = !!(race->data.flags&ESM::Race::Beast); + bodyRaceID = "b_n_"+race->name; + std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); - std::string hairID = ref->base->hair; - std::string headID = ref->base->head; - headModel = "meshes\\" + - MWBase::Environment::get().getWorld()->getStore().bodyParts.find(headID)->model; + /*std::cout << "Race: " << ref->base->race ; + if(female) + std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; + else + std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; + */ - hairModel = "meshes\\" + - MWBase::Environment::get().getWorld()->getStore().bodyParts.find(hairID)->model; - npcName = ref->base->name; - - //ESMStore::Races r = - const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().races.find(ref->base->race); - - - bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); - isFemale = tolower(secondtolast) == 'f'; - std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); - isBeast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; - - /*std::cout << "Race: " << ref->base->race ; - if(female){ - std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; - } - else{ - std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; - }*/ - - - - std::string smodel = "meshes\\base_anim.nif"; - if(isBeast) - smodel = "meshes\\base_animkna.nif"; - - insert = ptr.getRefData().getBaseNode(); - assert(insert); - - NifOgre::NIFLoader::load(smodel); + insert = ptr.getRefData().getBaseNode(); + assert(insert); + std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); + NifOgre::NIFLoader::load(smodel); base = mRend.getScene()->createEntity(smodel); base->setVisibilityFlags(RV_Actors); @@ -134,372 +98,290 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere while (passIt.hasMoreElements()) { Ogre::Pass* pass = passIt.getNext(); - if (pass->getDepthWriteEnabled() == false) transparent = true; } } } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - - base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones //stay in the same place when we skipanim, or open a gui window - - - if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){ - - for(unsigned int init = 0; init < transformations->size(); init++){ - rindexI.push_back(0); - tindexI.push_back(0); - } - - stopTime = transformations->begin()->getStopTime(); - startTime = transformations->begin()->getStartTime(); - } - textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel); insert->attachObject(base); + if(isFemale) + insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); + else + insert->scale(race->data.height.male, race->data.height.male, race->data.height.male); - - if(isFemale) - insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); - else - insert->scale(race->data.height.male, race->data.height.male, race->data.height.male); - updateParts(); - + updateParts(); } -void NpcAnimation::updateParts(){ +void NpcAnimation::updateParts() +{ + bool apparelChanged = false; - bool apparelChanged = false; + //inv.getSlot(MWWorld::InventoryStore::Slot_Robe); + if(robe != inv.getSlot(MWWorld::InventoryStore::Slot_Robe)) + { + // A robe was added or removed + robe = inv.getSlot(MWWorld::InventoryStore::Slot_Robe); + removePartGroup(MWWorld::InventoryStore::Slot_Robe); + apparelChanged = true; + } + if(skirtiter != inv.getSlot(MWWorld::InventoryStore::Slot_Skirt)) + { + skirtiter = inv.getSlot(MWWorld::InventoryStore::Slot_Skirt); + removePartGroup(MWWorld::InventoryStore::Slot_Skirt); + apparelChanged = true; + } + if(helmet != inv.getSlot(MWWorld::InventoryStore::Slot_Helmet)) + { + helmet = inv.getSlot(MWWorld::InventoryStore::Slot_Helmet); + removePartGroup(MWWorld::InventoryStore::Slot_Helmet); + apparelChanged = true; + } + if(cuirass != inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)) + { + cuirass = inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass); + removePartGroup(MWWorld::InventoryStore::Slot_Cuirass); + apparelChanged = true; + } + if(greaves != inv.getSlot(MWWorld::InventoryStore::Slot_Greaves)) + { + greaves = inv.getSlot(MWWorld::InventoryStore::Slot_Greaves); + removePartGroup(MWWorld::InventoryStore::Slot_Greaves); + apparelChanged = true; + } + if(leftpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)) + { + leftpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron); + removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron); + apparelChanged = true; + } + if(rightpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)) + { + rightpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron); + removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron); + apparelChanged = true; + } + if(!isBeast && boots != inv.getSlot(MWWorld::InventoryStore::Slot_Boots)) + { + boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); + removePartGroup(MWWorld::InventoryStore::Slot_Boots); + apparelChanged = true; + } + if(leftglove != inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)) + { + leftglove = inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet); + removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet); + apparelChanged = true; + } + if(rightglove != inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)) + { + rightglove = inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet); + removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet); + apparelChanged = true; + } + if(shirt != inv.getSlot(MWWorld::InventoryStore::Slot_Shirt)) + { + shirt = inv.getSlot(MWWorld::InventoryStore::Slot_Shirt); + removePartGroup(MWWorld::InventoryStore::Slot_Shirt); + apparelChanged = true; + } + if(pants != inv.getSlot(MWWorld::InventoryStore::Slot_Pants)) + { + pants = inv.getSlot(MWWorld::InventoryStore::Slot_Pants); + removePartGroup(MWWorld::InventoryStore::Slot_Pants); + apparelChanged = true; + } + if(apparelChanged) + { + if(robe != inv.end()) + { + MWWorld::Ptr ptr = *robe; - //inv.getSlot(MWWorld::InventoryStore::Slot_Robe); - if(robe != inv.getSlot(MWWorld::InventoryStore::Slot_Robe)){ - //A robe was added or removed - removePartGroup(MWWorld::InventoryStore::Slot_Robe); - robe = inv.getSlot(MWWorld::InventoryStore::Slot_Robe); - apparelChanged = true; - } - if(skirtiter != inv.getSlot(MWWorld::InventoryStore::Slot_Skirt)){ - //A robe was added or removed - removePartGroup(MWWorld::InventoryStore::Slot_Skirt); - skirtiter = inv.getSlot(MWWorld::InventoryStore::Slot_Skirt); - apparelChanged = true; - } - if(helmet != inv.getSlot(MWWorld::InventoryStore::Slot_Helmet)){ - apparelChanged = true; - helmet = inv.getSlot(MWWorld::InventoryStore::Slot_Helmet); - removePartGroup(MWWorld::InventoryStore::Slot_Helmet); - + const ESM::Clothing *clothes = (ptr.get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts); + reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_Skirt, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RKnee, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LKnee, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RForearm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LForearm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5); } - if(cuirass != inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)){ - cuirass = inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass); - removePartGroup(MWWorld::InventoryStore::Slot_Cuirass); - apparelChanged = true; - - } - if(greaves != inv.getSlot(MWWorld::InventoryStore::Slot_Greaves)){ - greaves = inv.getSlot(MWWorld::InventoryStore::Slot_Greaves); - removePartGroup(MWWorld::InventoryStore::Slot_Greaves); - apparelChanged = true; - } - if(leftpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)){ - leftpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron); - removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron); - apparelChanged = true; - - } - if(rightpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)){ - rightpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron); - removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron); - apparelChanged = true; - - } - if(!isBeast && boots != inv.getSlot(MWWorld::InventoryStore::Slot_Boots)){ - boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); - removePartGroup(MWWorld::InventoryStore::Slot_Boots); - apparelChanged = true; - - } - if(leftglove != inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)){ - leftglove = inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet); - removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet); - apparelChanged = true; - - } - if(rightglove != inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)){ - rightglove = inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet); - removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet); - apparelChanged = true; - - } - if(shirt != inv.getSlot(MWWorld::InventoryStore::Slot_Shirt)){ - shirt = inv.getSlot(MWWorld::InventoryStore::Slot_Shirt); - removePartGroup(MWWorld::InventoryStore::Slot_Shirt); - apparelChanged = true; - - } - if(pants != inv.getSlot(MWWorld::InventoryStore::Slot_Pants)){ - pants = inv.getSlot(MWWorld::InventoryStore::Slot_Pants); - removePartGroup(MWWorld::InventoryStore::Slot_Pants); - apparelChanged = true; + if(skirtiter != inv.end()) + { + MWWorld::Ptr ptr = *skirtiter; + const ESM::Clothing *clothes = (ptr.get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts); + reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4); + reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Skirt, 4); + reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4); } - if(apparelChanged){ + if(helmet != inv.end()) + { + removeIndividualPart(ESM::PRT_Hair); + const ESM::Armor *armor = (helmet->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts); + } + if(cuirass != inv.end()) + { + const ESM::Armor *armor = (cuirass->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts); + } + if(greaves != inv.end()) + { + const ESM::Armor *armor = (greaves->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts); + } - if(robe != inv.end()) + if(leftpauldron != inv.end()) + { + const ESM::Armor *armor = (leftpauldron->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts); + } + if(rightpauldron != inv.end()) + { + const ESM::Armor *armor = (rightpauldron->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); + } + if(!isBeast && boots != inv.end()) + { + if(boots->getTypeName() == typeid(ESM::Clothing).name()) { - MWWorld::Ptr ptr = *robe; - - const ESM::Clothing *clothes = (ptr.get())->base; + const ESM::Clothing *clothes = (boots->get())->base; std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts); - reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_Skirt, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RKnee, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LKnee, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RForearm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LForearm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts); } - if(skirtiter != inv.end()) + else if(boots->getTypeName() == typeid(ESM::Armor).name()) { - MWWorld::Ptr ptr = *skirtiter; - - const ESM::Clothing *clothes = (ptr.get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts); - reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4); - reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Skirt, 4); - reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4); - } - - if(helmet != inv.end()){ - removeIndividualPart(ESM::PRT_Hair); - const ESM::Armor *armor = (helmet->get())->base; + const ESM::Armor *armor = (boots->get())->base; std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts); - - } - if(cuirass != inv.end()){ - const ESM::Armor *armor = (cuirass->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts); - - } - if(greaves != inv.end()){ - const ESM::Armor *armor = (greaves->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts); - - } - - if(leftpauldron != inv.end()){ - const ESM::Armor *armor = (leftpauldron->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts); - - } - if(rightpauldron != inv.end()){ - const ESM::Armor *armor = (rightpauldron->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); - - } - if(!isBeast && boots != inv.end()){ - if(boots->getTypeName() == typeid(ESM::Clothing).name()){ - const ESM::Clothing *clothes = (boots->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts); - } - else if(boots->getTypeName() == typeid(ESM::Armor).name()) - { - const ESM::Armor *armor = (boots->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts); - } - - } - if(leftglove != inv.end()){ - if(leftglove->getTypeName() == typeid(ESM::Clothing).name()){ - const ESM::Clothing *clothes = (leftglove->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts); - } - else - { - const ESM::Armor *armor = (leftglove->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts); - } - - } - if(rightglove != inv.end()){ - if(rightglove->getTypeName() == typeid(ESM::Clothing).name()){ - const ESM::Clothing *clothes = (rightglove->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts); - } - else - { - const ESM::Armor *armor = (rightglove->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts); - } - - } - - if(shirt != inv.end()){ - const ESM::Clothing *clothes = (shirt->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts); - } - if(pants != inv.end()){ - const ESM::Clothing *clothes = (pants->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts); + addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts); } } + if(leftglove != inv.end()) + { + if(leftglove->getTypeName() == typeid(ESM::Clothing).name()) + { + const ESM::Clothing *clothes = (leftglove->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts); + } + else + { + const ESM::Armor *armor = (leftglove->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts); + } + } + if(rightglove != inv.end()) + { + if(rightglove->getTypeName() == typeid(ESM::Clothing).name()) + { + const ESM::Clothing *clothes = (rightglove->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts); + } + else + { + const ESM::Armor *armor = (rightglove->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts); + } - if(partpriorities[ESM::PRT_Head] < 1){ - addOrReplaceIndividualPart(ESM::PRT_Head, -1,1,headModel); - } - if(partpriorities[ESM::PRT_Hair] < 1 && partpriorities[ESM::PRT_Head] <= 1){ - addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1,hairModel); - } - if(partpriorities[ESM::PRT_Neck] < 1){ - const ESM::BodyPart *neckPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "neck"); - if(neckPart) - addOrReplaceIndividualPart(ESM::PRT_Neck, -1,1,"meshes\\" + neckPart->model); - } - if(partpriorities[ESM::PRT_Cuirass] < 1){ - const ESM::BodyPart *chestPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "chest"); - if(chestPart) - addOrReplaceIndividualPart(ESM::PRT_Cuirass, -1,1,"meshes\\" + chestPart->model); - } - - if(partpriorities[ESM::PRT_Groin] < 1){ - const ESM::BodyPart *groinPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "groin"); - if(groinPart) - addOrReplaceIndividualPart(ESM::PRT_Groin, -1,1,"meshes\\" + groinPart->model); - } - if(partpriorities[ESM::PRT_RHand] < 1){ - const ESM::BodyPart *handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hand"); - if(!handPart) - handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hands"); - if(handPart) - addOrReplaceIndividualPart(ESM::PRT_RHand, -1,1,"meshes\\" + handPart->model); - } - if(partpriorities[ESM::PRT_LHand] < 1){ - const ESM::BodyPart *handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hand"); - if(!handPart) - handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hands"); - if(handPart) - addOrReplaceIndividualPart(ESM::PRT_LHand, -1,1,"meshes\\" + handPart->model); - } - - if(partpriorities[ESM::PRT_RWrist] < 1){ - const ESM::BodyPart *wristPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "wrist"); - if(wristPart) - addOrReplaceIndividualPart(ESM::PRT_RWrist, -1,1,"meshes\\" + wristPart->model); - } - if(partpriorities[ESM::PRT_LWrist] < 1){ - const ESM::BodyPart *wristPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "wrist"); - if(wristPart) - addOrReplaceIndividualPart(ESM::PRT_LWrist, -1,1,"meshes\\" + wristPart->model); - } - if(partpriorities[ESM::PRT_RForearm] < 1){ - const ESM::BodyPart *forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "forearm"); - if(bodyRaceID == "b_n_argonian_f_") - forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search ("b_n_argonian_m_forearm"); - if(forearmPart) - addOrReplaceIndividualPart(ESM::PRT_RForearm, -1,1,"meshes\\" + forearmPart->model); - } - if(partpriorities[ESM::PRT_LForearm] < 1){ - const ESM::BodyPart *forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "forearm"); - if(bodyRaceID == "b_n_argonian_f_") - forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search ("b_n_argonian_m_forearm"); - if(forearmPart) - addOrReplaceIndividualPart(ESM::PRT_LForearm, -1,1,"meshes\\" + forearmPart->model); - } - if(partpriorities[ESM::PRT_RUpperarm] < 1){ - const ESM::BodyPart *armPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper arm"); - if(armPart) - addOrReplaceIndividualPart(ESM::PRT_RUpperarm, -1,1,"meshes\\" + armPart->model); - } - if(partpriorities[ESM::PRT_LUpperarm] < 1){ - const ESM::BodyPart *armPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper arm"); - if(armPart) - addOrReplaceIndividualPart(ESM::PRT_LUpperarm, -1,1,"meshes\\" + armPart->model); - } - if(partpriorities[ESM::PRT_RFoot] < 1){ - const ESM::BodyPart *footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "foot"); - if(isBeast && !footPart) - footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "feet"); - if(footPart) - addOrReplaceIndividualPart(ESM::PRT_RFoot, -1,1,"meshes\\" + footPart->model); - } - if(partpriorities[ESM::PRT_LFoot] < 1){ - const ESM::BodyPart *footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "foot"); - if(isBeast && !footPart) - footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "feet"); - if(footPart) - addOrReplaceIndividualPart(ESM::PRT_LFoot, -1,1,"meshes\\" + footPart->model); - } - if(partpriorities[ESM::PRT_RAnkle] < 1){ - const ESM::BodyPart *anklePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "ankle"); - if(anklePart) - addOrReplaceIndividualPart(ESM::PRT_RAnkle, -1,1,"meshes\\" + anklePart->model); - } - if(partpriorities[ESM::PRT_LAnkle] < 1){ - const ESM::BodyPart *anklePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "ankle"); - if(anklePart) - addOrReplaceIndividualPart(ESM::PRT_LAnkle, -1,1,"meshes\\" + anklePart->model); - } - if(partpriorities[ESM::PRT_RKnee] < 1){ - const ESM::BodyPart *kneePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "knee"); - if(kneePart) - addOrReplaceIndividualPart(ESM::PRT_RKnee, -1,1,"meshes\\" + kneePart->model); - } - if(partpriorities[ESM::PRT_LKnee] < 1){ - const ESM::BodyPart *kneePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "knee"); - if(kneePart) - addOrReplaceIndividualPart(ESM::PRT_LKnee, -1,1,"meshes\\" + kneePart->model); - } - if(partpriorities[ESM::PRT_RLeg] < 1){ - const ESM::BodyPart *legPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper leg"); - if(legPart) - addOrReplaceIndividualPart(ESM::PRT_RLeg, -1,1,"meshes\\" + legPart->model); - } - if(partpriorities[ESM::PRT_LLeg] < 1){ - const ESM::BodyPart *legPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper leg"); - if(legPart) - addOrReplaceIndividualPart(ESM::PRT_LLeg, -1,1,"meshes\\" + legPart->model); - } - if(partpriorities[ESM::PRT_Tail] < 1){ - const ESM::BodyPart *tailPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "tail"); - if(tailPart) - addOrReplaceIndividualPart(ESM::PRT_Tail, -1,1,"meshes\\" + tailPart->model); - } - - + } + if(shirt != inv.end()) + { + const ESM::Clothing *clothes = (shirt->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts); + } + if(pants != inv.end()) + { + const ESM::Clothing *clothes = (pants->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts); + } + } + if(partpriorities[ESM::PRT_Head] < 1) + addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, headModel); + if(partpriorities[ESM::PRT_Hair] < 1 && partpriorities[ESM::PRT_Head] <= 1) + addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, hairModel); + static const struct { + ESM::PartReferenceType type; + const char name[2][12]; + } PartTypeList[] = { + { ESM::PRT_Neck, { "neck", "" } }, + { ESM::PRT_Cuirass, { "chest", "" } }, + { ESM::PRT_Groin, { "groin", "" } }, + { ESM::PRT_RHand, { "hand", "hands" } }, + { ESM::PRT_LHand, { "hand", "hands" } }, + { ESM::PRT_RWrist, { "wrist", "" } }, + { ESM::PRT_LWrist, { "wrist", "" } }, + { ESM::PRT_RForearm, { "forearm", "" } }, + { ESM::PRT_LForearm, { "forearm", "" } }, + { ESM::PRT_RUpperarm, { "upper arm", "" } }, + { ESM::PRT_LUpperarm, { "upper arm", "" } }, + { ESM::PRT_RFoot, { "foot", "feet" } }, + { ESM::PRT_LFoot, { "foot", "feet" } }, + { ESM::PRT_RAnkle, { "ankle", "" } }, + { ESM::PRT_LAnkle, { "ankle", "" } }, + { ESM::PRT_RKnee, { "knee", "" } }, + { ESM::PRT_LKnee, { "knee", "" } }, + { ESM::PRT_RLeg, { "upper leg", "" } }, + { ESM::PRT_LLeg, { "upper leg", "" } }, + { ESM::PRT_Tail, { "tail", "" } } + }; + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++) + { + if(partpriorities[PartTypeList[i].type] < 1) + { + const ESM::BodyPart *part = NULL; + bool tryfemale = isFemale; + int ni = 0; + do { + part = store.bodyParts.search(bodyRaceID+(tryfemale?"_f_":"_m_")+PartTypeList[i].name[ni]); + if(part) break; + ni ^= 1; + if(ni == 0) + { + if(!tryfemale) + break; + tryfemale = false; + } + } while(1); + if(part) + addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->model); + } + } } -Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ +Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) +{ NIFLoader::load(mesh); Ogre::Entity* part = mRend.getScene()->createEntity(mesh); @@ -508,361 +390,275 @@ Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::stri base->attachObjectToBone(bonename, part); return part; } -void NpcAnimation::insertFootPart(int type, const std::string &mesh){ - std::string meshAndSuffix = mesh; - if(type == ESM::PRT_LFoot) - meshAndSuffix += "*|"; - NIFLoader::load(meshAndSuffix); - Ogre::Entity* part = mRend.getScene()->createEntity(meshAndSuffix); - std::vector* shape = ((NIFLoader::getSingletonPtr())->getShapes(meshAndSuffix)); - if(shape == 0){ - if(type == ESM::PRT_LFoot){ - base->attachObjectToBone("Left Foot", part); - lfoot = part; - } - else if (type == ESM::PRT_RFoot){ - base->attachObjectToBone("Right Foot", part); - rfoot = part; - } - } - else{ - if(type == ESM::PRT_LFoot) - lFreeFoot = insertFreePart(mesh, "::"); - else if (type == ESM::PRT_RFoot) - rFreeFoot = insertFreePart(mesh, ":<"); + +void NpcAnimation::runAnimation(float timepassed) +{ + if(timeToChange > .2) + { + timeToChange = 0; + updateParts(); } - - -} -std::pair*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string& suffix){ - - std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; - NIFLoader::load(meshNumbered); - - Ogre::Entity* part = mRend.getScene()->createEntity(meshNumbered); - part->setVisibilityFlags(RV_Actors); - - insert->attachObject(part); - - std::vector* shape = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix)); - if(shape){ - handleShapes(shape, part, base->getSkeleton()); - } - std::pair*> pair = std::make_pair(part, shape); - return pair; -} - - - - -void NpcAnimation::runAnimation(float timepassed){ - - if(timeToChange > .2){ - - timeToChange = 0; - - updateParts(); - } - - timeToChange += timepassed; + timeToChange += timepassed; //1. Add the amount of time passed to time - //2. Handle the animation transforms dependent on time + //2. Handle the animation transforms dependent on time - //3. Handle the shapes dependent on animation transforms - if(animate > 0){ + //3. Handle the shapes dependent on animation transforms + if(animate > 0) + { time += timepassed; - - if(time > stopTime){ + if(time > stopTime) + { animate--; - if(animate == 0) time = stopTime; else time = startTime + (time - stopTime); } - handleAnimationTransforms(); - - - vecRotPos.clear(); - - - if(lFreeFoot.first) - handleShapes(lFreeFoot.second, lFreeFoot.first, base->getSkeleton()); - if(rFreeFoot.first) - handleShapes(rFreeFoot.second, rFreeFoot.first, base->getSkeleton()); - - if(chest.first) - handleShapes(chest.second, chest.first, base->getSkeleton()); - if(tail.first) - handleShapes(tail.second, tail.first, base->getSkeleton()); - if(skirt.first){ - handleShapes(skirt.second, skirt.first, base->getSkeleton()); - } - if(lhand.first) - handleShapes(lhand.second, lhand.first, base->getSkeleton()); - if(rhand.first) - handleShapes(rhand.second, rhand.first, base->getSkeleton()); - -} + handleAnimationTransforms(); + } } -void NpcAnimation::removeIndividualPart(int type){ +void NpcAnimation::removeIndividualPart(int type) +{ partpriorities[type] = 0; partslots[type] = -1; - if(type == ESM::PRT_Head && head){ //0 - base->detachObjectFromBone(head); - head = 0; - } - else if(type == ESM::PRT_Hair && hair){//1 - base->detachObjectFromBone(hair); - hair = 0; - } - else if(type == ESM::PRT_Neck && neck){//2 - base->detachObjectFromBone(neck); - neck = 0; - } - else if(type == ESM::PRT_Cuirass && chest.first){//3 - insert->detachObject(chest.first); - chest = zero; - } - else if(type == ESM::PRT_Groin && groin){//4 - base->detachObjectFromBone(groin); - groin = 0; - } - else if(type == ESM::PRT_Skirt && skirt.first){//5 - insert->detachObject(skirt.first); - skirt = zero; - } - else if(type == ESM::PRT_RHand && rhand.first){//6 - insert->detachObject(rhand.first); - rhand = zero; - } - else if(type == ESM::PRT_LHand && lhand.first){//7 - insert->detachObject(lhand.first); - lhand = zero; - } - else if(type == ESM::PRT_RWrist && rWrist){//8 - base->detachObjectFromBone(rWrist); - rWrist = 0; - } - else if(type == ESM::PRT_LWrist && lWrist){//9 - base->detachObjectFromBone(lWrist); - lWrist = 0; - } - else if(type == ESM::PRT_Shield){//10 - - } - else if(type == ESM::PRT_RForearm && rForearm){//11 - base->detachObjectFromBone(rForearm); - rForearm = 0; - } - else if(type == ESM::PRT_LForearm && lForearm){//12 - base->detachObjectFromBone(lForearm); - lForearm = 0; - } - else if(type == ESM::PRT_RUpperarm && rupperArm){//13 - base->detachObjectFromBone(rupperArm); - rupperArm = 0; - } - else if(type == ESM::PRT_LUpperarm && lupperArm){//14 - base->detachObjectFromBone(lupperArm); - lupperArm = 0; - } - else if(type == ESM::PRT_RFoot){ //15 - if(rfoot){ - base->detachObjectFromBone(rfoot); - rfoot = 0; - } - else if(rFreeFoot.first){ - insert->detachObject(rFreeFoot.first); - rFreeFoot = zero; - } - } - else if(type == ESM::PRT_LFoot){ //16 - if(lfoot){ - base->detachObjectFromBone(lfoot); - lfoot = 0; - } - else if(lFreeFoot.first){ - insert->detachObject(lFreeFoot.first); - lFreeFoot = zero; - } - } - else if(type == ESM::PRT_RAnkle && rAnkle){ //17 - base->detachObjectFromBone(rAnkle); - rAnkle = 0; - } - else if(type == ESM::PRT_LAnkle && lAnkle){ //18 - base->detachObjectFromBone(lAnkle); - lAnkle = 0; - } - else if(type == ESM::PRT_RKnee && rKnee){ //19 - base->detachObjectFromBone(rKnee); - rKnee = 0; - } - else if(type == ESM::PRT_LKnee && lKnee){ //20 - base->detachObjectFromBone(lKnee); - lKnee = 0; - } - else if(type == ESM::PRT_RLeg && rUpperLeg){ //21 - base->detachObjectFromBone(rUpperLeg); - rUpperLeg = 0; - } - else if(type == ESM::PRT_LLeg && lUpperLeg){ //22 - base->detachObjectFromBone(lUpperLeg); - lUpperLeg = 0; - } - else if(type == ESM::PRT_RPauldron && rclavicle){ //23 - base->detachObjectFromBone(rclavicle); - rclavicle = 0; - } - else if(type == ESM::PRT_LPauldron && lclavicle){ //24 - base->detachObjectFromBone(lclavicle); - lclavicle = 0; - } - else if(type == ESM::PRT_Weapon){ //25 - - } - else if(type == ESM::PRT_Tail && tail.first){ //26 - insert->detachObject(tail.first); - tail = zero; - } - - - - + if(type == ESM::PRT_Head && head) //0 + { + base->detachObjectFromBone(head); + head = 0; } - - void NpcAnimation::reserveIndividualPart(int type, int group, int priority){ - if(priority > partpriorities[type]){ - removeIndividualPart(type); - partpriorities[type] = priority; - partslots[type] = group; - } + else if(type == ESM::PRT_Hair && hair) //1 + { + base->detachObjectFromBone(hair); + hair = 0; } - - void NpcAnimation::removePartGroup(int group){ - for(int i = 0; i < 27; i++){ - if(partslots[i] == group){ - removeIndividualPart(i); - } - } + else if(type == ESM::PRT_Neck && neck) //2 + { + base->detachObjectFromBone(neck); + neck = 0; } - bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh){ - if(priority > partpriorities[type]){ - removeIndividualPart(type); - partslots[type] = group; - partpriorities[type] = priority; - switch(type){ - case ESM::PRT_Head: //0 - head = insertBoundedPart(mesh, "Head"); - break; - case ESM::PRT_Hair: //1 - hair = insertBoundedPart(mesh, "Head"); - break; - case ESM::PRT_Neck: //2 - neck = insertBoundedPart(mesh, "Neck"); - break; - case ESM::PRT_Cuirass: //3 - chest = insertFreePart(mesh, ":\""); - break; - case ESM::PRT_Groin: //4 - groin = insertBoundedPart(mesh, "Groin"); - break; - case ESM::PRT_Skirt: //5 - skirt = insertFreePart(mesh, ":|"); - break; - case ESM::PRT_RHand: //6 - rhand = insertFreePart(mesh, ":?"); - break; - case ESM::PRT_LHand: //7 - lhand = insertFreePart(mesh, ":>"); - break; - case ESM::PRT_RWrist: //8 - rWrist = insertBoundedPart(mesh, "Right Wrist"); - break; - case ESM::PRT_LWrist: //9 - lWrist = insertBoundedPart(mesh + "*|", "Left Wrist"); - break; - case ESM::PRT_Shield: //10 - break; - case ESM::PRT_RForearm: //11 - rForearm = insertBoundedPart(mesh, "Right Forearm"); - break; - case ESM::PRT_LForearm: //12 - lForearm = insertBoundedPart(mesh + "*|", "Left Forearm"); - break; - case ESM::PRT_RUpperarm: //13 - rupperArm = insertBoundedPart(mesh, "Right Upper Arm"); - break; - case ESM::PRT_LUpperarm: //14 - lupperArm = insertBoundedPart(mesh + "*|", "Left Upper Arm"); - break; - case ESM::PRT_RFoot: //15 - insertFootPart(type, mesh); - break; - case ESM::PRT_LFoot: //16 - insertFootPart(type, mesh); - break; - case ESM::PRT_RAnkle: //17 - rAnkle = insertBoundedPart(mesh , "Right Ankle"); - break; - case ESM::PRT_LAnkle: //18 - lAnkle = insertBoundedPart(mesh + "*|", "Left Ankle"); - break; - case ESM::PRT_RKnee: //19 - rKnee = insertBoundedPart(mesh , "Right Knee"); - break; - case ESM::PRT_LKnee: //20 - lKnee = insertBoundedPart(mesh + "*|", "Left Knee"); - break; - case ESM::PRT_RLeg: //21 - rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg"); - break; - case ESM::PRT_LLeg: //22 - lUpperLeg = insertBoundedPart(mesh + "*|", "Left Upper Leg"); - break; - case ESM::PRT_RPauldron: //23 - rclavicle = insertBoundedPart(mesh , "Right Clavicle"); - break; - case ESM::PRT_LPauldron: //24 - lclavicle = insertBoundedPart(mesh + "*|", "Left Clavicle"); - break; - case ESM::PRT_Weapon: //25 - break; - case ESM::PRT_Tail: //26 - tail = insertFreePart(mesh, ":*"); - break; - - - } - return true; - } - return false; + else if(type == ESM::PRT_Groin && groin)//4 + { + base->detachObjectFromBone(groin); + groin = 0; } - - void NpcAnimation::addPartGroup(int group, int priority, std::vector& parts){ - for(std::size_t i = 0; i < parts.size(); i++) - { - ESM::PartReference part = parts[i]; - - const ESM::BodyPart *bodypart = 0; - - if(isFemale) - bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (part.female); - if(!bodypart) - bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (part.male); - if(bodypart){ - addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model); - } - else - reserveIndividualPart(part.part, group, priority); - - } + else if(type == ESM::PRT_RWrist && rWrist)//8 + { + base->detachObjectFromBone(rWrist); + rWrist = 0; + } + else if(type == ESM::PRT_LWrist && lWrist) //9 + { + base->detachObjectFromBone(lWrist); + lWrist = 0; + } + else if(type == ESM::PRT_Shield) //10 + { + } + else if(type == ESM::PRT_RForearm && rForearm) //11 + { + base->detachObjectFromBone(rForearm); + rForearm = 0; + } + else if(type == ESM::PRT_LForearm && lForearm) //12 + { + base->detachObjectFromBone(lForearm); + lForearm = 0; + } + else if(type == ESM::PRT_RUpperarm && rupperArm) //13 + { + base->detachObjectFromBone(rupperArm); + rupperArm = 0; + } + else if(type == ESM::PRT_LUpperarm && lupperArm) //14 + { + base->detachObjectFromBone(lupperArm); + lupperArm = 0; + } + else if(type == ESM::PRT_RFoot && rfoot) //15 + { + base->detachObjectFromBone(rfoot); + rfoot = 0; + } + else if(type == ESM::PRT_LFoot && lfoot) //16 + { + base->detachObjectFromBone(lfoot); + lfoot = 0; + } + else if(type == ESM::PRT_RAnkle && rAnkle) //17 + { + base->detachObjectFromBone(rAnkle); + rAnkle = 0; + } + else if(type == ESM::PRT_LAnkle && lAnkle) //18 + { + base->detachObjectFromBone(lAnkle); + lAnkle = 0; + } + else if(type == ESM::PRT_RKnee && rKnee) //19 + { + base->detachObjectFromBone(rKnee); + rKnee = 0; + } + else if(type == ESM::PRT_LKnee && lKnee) //20 + { + base->detachObjectFromBone(lKnee); + lKnee = 0; + } + else if(type == ESM::PRT_RLeg && rUpperLeg) //21 + { + base->detachObjectFromBone(rUpperLeg); + rUpperLeg = 0; + } + else if(type == ESM::PRT_LLeg && lUpperLeg) //22 + { + base->detachObjectFromBone(lUpperLeg); + lUpperLeg = 0; + } + else if(type == ESM::PRT_RPauldron && rclavicle) //23 + { + base->detachObjectFromBone(rclavicle); + rclavicle = 0; + } + else if(type == ESM::PRT_LPauldron && lclavicle) //24 + { + base->detachObjectFromBone(lclavicle); + lclavicle = 0; + } + else if(type == ESM::PRT_Weapon) //25 + { } } + +void NpcAnimation::reserveIndividualPart(int type, int group, int priority) +{ + if(priority > partpriorities[type]) + { + removeIndividualPart(type); + partpriorities[type] = priority; + partslots[type] = group; + } +} + +void NpcAnimation::removePartGroup(int group) +{ + for(int i = 0; i < 27; i++) + { + if(partslots[i] == group) + removeIndividualPart(i); + } +} + +bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh) +{ + if(priority <= partpriorities[type]) + return false; + + removeIndividualPart(type); + partslots[type] = group; + partpriorities[type] = priority; + switch(type) + { + case ESM::PRT_Head: //0 + head = insertBoundedPart(mesh, "Head"); + break; + case ESM::PRT_Hair: //1 + hair = insertBoundedPart(mesh, "Head"); + break; + case ESM::PRT_Neck: //2 + neck = insertBoundedPart(mesh, "Neck"); + break; + case ESM::PRT_Cuirass: //3 + break; + case ESM::PRT_Groin: //4 + groin = insertBoundedPart(mesh, "Groin"); + break; + case ESM::PRT_Skirt: //5 + break; + case ESM::PRT_RHand: //6 + break; + case ESM::PRT_LHand: //7 + break; + case ESM::PRT_RWrist: //8 + rWrist = insertBoundedPart(mesh, "Right Wrist"); + break; + case ESM::PRT_LWrist: //9 + lWrist = insertBoundedPart(mesh, "Left Wrist"); + break; + case ESM::PRT_Shield: //10 + break; + case ESM::PRT_RForearm: //11 + rForearm = insertBoundedPart(mesh, "Right Forearm"); + break; + case ESM::PRT_LForearm: //12 + lForearm = insertBoundedPart(mesh, "Left Forearm"); + break; + case ESM::PRT_RUpperarm: //13 + rupperArm = insertBoundedPart(mesh, "Right Upper Arm"); + break; + case ESM::PRT_LUpperarm: //14 + lupperArm = insertBoundedPart(mesh, "Left Upper Arm"); + break; + case ESM::PRT_RFoot: //15 + lupperArm = insertBoundedPart(mesh, "Right Foot"); + break; + case ESM::PRT_LFoot: //16 + lupperArm = insertBoundedPart(mesh, "Left Foot"); + break; + case ESM::PRT_RAnkle: //17 + rAnkle = insertBoundedPart(mesh, "Right Ankle"); + break; + case ESM::PRT_LAnkle: //18 + lAnkle = insertBoundedPart(mesh, "Left Ankle"); + break; + case ESM::PRT_RKnee: //19 + rKnee = insertBoundedPart(mesh, "Right Knee"); + break; + case ESM::PRT_LKnee: //20 + lKnee = insertBoundedPart(mesh, "Left Knee"); + break; + case ESM::PRT_RLeg: //21 + rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg"); + break; + case ESM::PRT_LLeg: //22 + lUpperLeg = insertBoundedPart(mesh, "Left Upper Leg"); + break; + case ESM::PRT_RPauldron: //23 + rclavicle = insertBoundedPart(mesh , "Right Clavicle"); + break; + case ESM::PRT_LPauldron: //24 + lclavicle = insertBoundedPart(mesh, "Left Clavicle"); + break; + case ESM::PRT_Weapon: //25 + break; + case ESM::PRT_Tail: //26 + break; + } + return true; +} + +void NpcAnimation::addPartGroup(int group, int priority, std::vector &parts) +{ + for(std::size_t i = 0; i < parts.size(); i++) + { + ESM::PartReference &part = parts[i]; + + const ESM::BodyPart *bodypart = 0; + if(isFemale) + bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.female); + if(!bodypart) + bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.male); + + if(bodypart) + addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model); + else + reserveIndividualPart(part.part, group, priority); + } +} + +} diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 8f4f8181d..151af4163 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -20,54 +20,43 @@ namespace MWRender{ class NpcAnimation: public Animation{ private: - MWWorld::InventoryStore& inv; - int mStateID; - //Free Parts - std::pair*> chest; - std::pair*> skirt; - std::pair*> lhand; - std::pair*> rhand; - std::pair*> tail; - std::pair*> lFreeFoot; - std::pair*> rFreeFoot; + MWWorld::InventoryStore& inv; + int mStateID; - int partslots[27]; //Each part slot is taken by clothing, armor, or is empty - int partpriorities[27]; - std::pair*> zero; + int partslots[27]; //Each part slot is taken by clothing, armor, or is empty + int partpriorities[27]; + //Bounded Parts + Ogre::Entity* lclavicle; + Ogre::Entity* rclavicle; + Ogre::Entity* rupperArm; + Ogre::Entity* lupperArm; + Ogre::Entity* rUpperLeg; + Ogre::Entity* lUpperLeg; + Ogre::Entity* lForearm; + Ogre::Entity* rForearm; + Ogre::Entity* lWrist; + Ogre::Entity* rWrist; + Ogre::Entity* rKnee; + Ogre::Entity* lKnee; + Ogre::Entity* neck; + Ogre::Entity* rAnkle; + Ogre::Entity* lAnkle; + Ogre::Entity* groin; + Ogre::Entity* lfoot; + Ogre::Entity* rfoot; + Ogre::Entity* hair; + Ogre::Entity* head; - - //Bounded Parts - Ogre::Entity* lclavicle; - Ogre::Entity* rclavicle; - Ogre::Entity* rupperArm; - Ogre::Entity* lupperArm; - Ogre::Entity* rUpperLeg; - Ogre::Entity* lUpperLeg; - Ogre::Entity* lForearm; - Ogre::Entity* rForearm; - Ogre::Entity* lWrist; - Ogre::Entity* rWrist; - Ogre::Entity* rKnee; - Ogre::Entity* lKnee; - Ogre::Entity* neck; - Ogre::Entity* rAnkle; - Ogre::Entity* lAnkle; - Ogre::Entity* groin; - Ogre::Entity* lfoot; - Ogre::Entity* rfoot; - Ogre::Entity* hair; - Ogre::Entity* head; - - Ogre::SceneNode* insert; + Ogre::SceneNode* insert; bool isBeast; bool isFemale; - std::string headModel; - std::string hairModel; - std::string npcName; - std::string bodyRaceID; - float timeToChange; - MWWorld::ContainerStoreIterator robe; + std::string headModel; + std::string hairModel; + std::string npcName; + std::string bodyRaceID; + float timeToChange; + MWWorld::ContainerStoreIterator robe; MWWorld::ContainerStoreIterator helmet; MWWorld::ContainerStoreIterator shirt; MWWorld::ContainerStoreIterator cuirass; @@ -80,22 +69,19 @@ private: MWWorld::ContainerStoreIterator rightglove; MWWorld::ContainerStoreIterator skirtiter; - public: - NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); - virtual ~NpcAnimation(); - Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); - std::pair*> insertFreePart(const std::string &mesh, const std::string& suffix); - void insertFootPart(int type, const std::string &mesh); - virtual void runAnimation(float timepassed); - void updateParts(); +public: + NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); + virtual ~NpcAnimation(); + Ogre::Entity* insertBoundedPart(const std::string &mesh, const std::string &bonename); + virtual void runAnimation(float timepassed); + void updateParts(); void removeIndividualPart(int type); void reserveIndividualPart(int type, int group, int priority); bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh); - void removePartGroup(int group); + void removePartGroup(int group); void addPartGroup(int group, int priority, std::vector& parts); - - }; + } #endif diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index e9ce3f615..dd12a53ff 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -64,28 +64,13 @@ static bool fsstrict = false; /// An OGRE Archive wrapping a BSAFile archive class DirArchive: public Ogre::FileSystemArchive { - boost::filesystem::path currentdir; std::map, ciLessBoost> m; unsigned int cutoff; bool findFile(const String& filename, std::string& copy) const { - { - String passed = filename; - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); - else if(filename.at(filename.length() - 2) == '"') - passed = filename.substr(0, filename.length() - 9); - else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' - || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' - || filename.at(filename.length() - 1) == '|') - passed = filename.substr(0, filename.length() - 2); - - - copy = passed; - } - + copy = filename; std::replace(copy.begin(), copy.end(), '\\', '/'); if(copy.at(0) == '/') @@ -225,46 +210,23 @@ public: // OGRE's fault. You should NOT expect an open() command not to // have any side effects on the archive, and hence this function // should not have been declared const in the first place. - BSAFile *narc = (BSAFile*)&arc; + BSAFile *narc = const_cast(&arc); - String passed = filename; - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); - else if(filename.at(filename.length() - 2) == '"') - passed = filename.substr(0, filename.length() - 9); - else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' - || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' - || filename.at(filename.length() - 1) == '|') - passed = filename.substr(0, filename.length() - 2); - - // Open the file - StreamPtr strm = narc->getFile(passed.c_str()); + StreamPtr strm = narc->getFile(filename.c_str()); // Wrap it into an Ogre::DataStream. return DataStreamPtr(new Mangle2OgreStream(strm)); } -bool exists(const String& filename) { - return cexists(filename); -} + bool exists(const String& filename) { + return arc.exists(filename.c_str()); + } - // Check if the file exists. bool cexists(const String& filename) const { - String passed = filename; - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); - else if(filename.at(filename.length() - 2) == '"') - passed = filename.substr(0, filename.length() - 9); - else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' - || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' - || filename.at(filename.length() - 1) == '|') - passed = filename.substr(0, filename.length() - 2); - - + return arc.exists(filename.c_str()); + } -return arc.exists(passed.c_str()); -} time_t getModifiedTime(const String&) { return 0; } // This is never called as far as I can see. diff --git a/components/nif/data.hpp b/components/nif/data.hpp index b7e2f172f..2d1e8bd3b 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -326,12 +326,6 @@ public: Ogre::Vector3 trans; // Translation float scale; // Probably scale (always 1) }; - struct BoneTrafoCopy - { - Ogre::Quaternion rotation; - Ogre::Vector3 trans; - float scale; - }; struct VertWeight { @@ -339,26 +333,12 @@ public: float weight; }; - struct BoneInfo { BoneTrafo trafo; Ogre::Vector4 unknown; std::vector weights; }; - struct BoneInfoCopy - { - std::string bonename; - unsigned short bonehandle; - BoneTrafoCopy trafo; - Ogre::Vector4 unknown; - //std::vector weights; - }; - struct IndividualWeight - { - float weight; - unsigned int boneinfocopyindex; - }; BoneTrafo trafo; std::vector bones; diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 293793009..1f1b91a46 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -110,20 +110,6 @@ public: } }; -struct NiTriShapeCopy -{ - std::string sname; - std::vector boneSequence; - Nif::NiSkinData::BoneTrafoCopy trafo; - //Ogre::Quaternion initialBoneRotation; - //Ogre::Vector3 initialBoneTranslation; - std::vector vertices; - std::vector normals; - std::vector boneinfo; - std::map > vertsToWeights; - Nif::NiMorphData morph; -}; - struct NiNode : Node { NodeList children; @@ -184,28 +170,6 @@ struct NiTriShape : Node data.post(nif); skin.post(nif); } - - NiTriShapeCopy clone() - { - NiTriShapeCopy copy; - copy.sname = name; - float *ptr = (float*)&data->vertices[0]; - float *ptrNormals = (float*)&data->normals[0]; - int numVerts = data->vertices.size() / 3; - for(int i = 0; i < numVerts; i++) - { - float *current = (float*) (ptr + i * 3); - copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2))); - - if(ptrNormals) - { - float *currentNormals = (float*) (ptrNormals + i * 3); - copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2))); - } - } - - return copy; - } }; struct NiCamera : Node diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index c3b34e039..5f562504b 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -79,7 +79,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) // of the early stages of development. Right now we WANT to catch // every error as early and intrusively as possible, as it's most // likely a sign of incomplete code rather than faulty input. - Nif::NIFFile nif(resourceName); + Nif::NIFFile nif(resourceName.substr(0, resourceName.length()-7)); if (nif.numRecords() < 1) { warn("Found no records in NIF."); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 014384dd4..883cf7fce 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -42,28 +42,6 @@ using namespace std; using namespace Nif; using namespace NifOgre; -NIFLoader& NIFLoader::getSingleton() -{ - static NIFLoader instance; - return instance; -} - -NIFLoader* NIFLoader::getSingletonPtr() -{ - return &getSingleton(); -} - -void NIFLoader::warn(string msg) -{ - std::cerr << "NIFLoader: Warn:" << msg << "\n"; -} - -void NIFLoader::fail(string msg) -{ - std::cerr << "NIFLoader: Fail: "<< msg << std::endl; - assert(1); -} - // Helper class that computes the bounding box and of a mesh class BoundsFinder @@ -149,6 +127,19 @@ public: } }; + +void NIFLoader::warn(const std::string &msg) +{ + std::cerr << "NIFLoader: Warn:" << msg << "\n"; +} + +void NIFLoader::fail(const std::string &msg) +{ + std::cerr << "NIFLoader: Fail: "<< msg << std::endl; + assert(1); +} + + // Conversion of blend / test mode from NIF -> OGRE. // Not in use yet, so let's comment it out. /* @@ -193,12 +184,7 @@ static CompareFunction getTestMode(int mode) } */ -void NIFLoader::setOutputAnimFiles(bool output){ - mOutputAnimFiles = output; -} -void NIFLoader::setVerbosePath(std::string path){ - verbosePath = path; -} +#if 0 void NIFLoader::createMaterial(const Ogre::String &name, const Ogre::Vector3 &ambient, const Ogre::Vector3 &diffuse, @@ -211,17 +197,6 @@ void NIFLoader::createMaterial(const Ogre::String &name, Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(name, resourceGroup); - //Hardware Skinning code, textures may be the wrong color if enabled - - /* if(!mSkel.isNull()){ - material->removeAllTechniques(); - - Ogre::Technique* tech = material->createTechnique(); - //tech->setSchemeName("blahblah"); - Pass* pass = tech->createPass(); - pass->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTexture");*/ - - // This assigns the texture to this material. If the texture name is // a file name, and this file exists (in a resource directory), it // will automatically be loaded when needed. If not (such as for @@ -302,14 +277,14 @@ void NIFLoader::createMaterial(const Ogre::String &name, { bool split = Settings::Manager::getBool("split", "Shadows"); const int numsplits = 3; - for (int i = 0; i < (split ? numsplits : 1); ++i) - { + for (int i = 0; i < (split ? numsplits : 1); ++i) + { Ogre::TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState(); tu->setName("shadowMap" + Ogre::StringConverter::toString(i)); tu->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW); tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER); tu->setTextureBorderColour(Ogre::ColourValue::White); - } + } } if (Settings::Manager::getBool("shaders", "Objects")) @@ -340,1067 +315,28 @@ void NIFLoader::createMaterial(const Ogre::String &name, material->setSelfIllumination(emissive[0], emissive[1], emissive[2]); material->setShininess(glossiness); } +#endif -// Takes a name and adds a unique part to it. This is just used to -// make sure that all materials are given unique names. -Ogre::String NIFLoader::getUniqueName(const Ogre::String &input) -{ - static int addon = 0; - static char buf[8]; - snprintf(buf, 8, "_%d", addon++); - - // Don't overflow the buffer - if (addon > 999999) addon = 0; - - return input + buf; -} - -// Check if the given texture name exists in the real world. If it -// does not, change the string IN PLACE to say .dds instead and try -// that. The texture may still not exist, but no information of value -// is lost in that case. -void NIFLoader::findRealTexture(Ogre::String &texName) -{ - if(Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName)) - return; - - // Change texture extension to .dds - Ogre::String::size_type pos = texName.rfind('.'); - texName.replace(pos, texName.length(), ".dds"); -} - -//Handle node at top - -// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given -// mesh. -void NIFLoader::createOgreSubMesh(NiTriShape *shape, const Ogre::String &material, std::list &vertexBoneAssignments) -{ - // cout << "s:" << shape << "\n"; - NiTriShapeData *data = shape->data.getPtr(); - Ogre::SubMesh *sub = mesh->createSubMesh(shape->name); - - int nextBuf = 0; - - // This function is just one long stream of Ogre-barf, but it works - // great. - - // Add vertices - int numVerts = data->vertices.size() / 3; - sub->vertexData = new Ogre::VertexData(); - sub->vertexData->vertexCount = numVerts; - sub->useSharedVertices = false; - - Ogre::VertexDeclaration *decl = sub->vertexData->vertexDeclaration; - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - - Ogre::HardwareVertexBufferSharedPtr vbuf = - Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - numVerts, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false); - - if(flip) - { - float *datamod = new float[data->vertices.size()]; - //std::cout << "Shape" << shape->name.toString() << "\n"; - for(int i = 0; i < numVerts; i++) - { - int index = i * 3; - const float *pos = &data->vertices[index]; - Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); - original = mTransform * original; - mBoundingBox.merge(original); - datamod[index] = original.x; - datamod[index+1] = original.y; - datamod[index+2] = original.z; - } - vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); - delete [] datamod; - } - else - { - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->vertices[0], false); - } - - - Ogre::VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; - bind->setBinding(nextBuf++, vbuf); - - if (data->normals.size()) - { - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - - if(flip) - { - Ogre::Quaternion rotation = mTransform.extractQuaternion(); - rotation.normalise(); - - float *datamod = new float[data->normals.size()]; - for(int i = 0; i < numVerts; i++) - { - int index = i * 3; - const float *pos = &data->normals[index]; - Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); - original = rotation * original; - if (mNormaliseNormals) - { - original.normalise(); - } - - - datamod[index] = original.x; - datamod[index+1] = original.y; - datamod[index+2] = original.z; - } - vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); - delete [] datamod; - } - else - { - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->normals[0], false); - } - bind->setBinding(nextBuf++, vbuf); - } - - - // Vertex colors - if (data->colors.size()) - { - const float *colors = &data->colors[0]; - Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); - std::vector colorsRGB(numVerts); - Ogre::RGBA *pColour = &colorsRGB.front(); - for (int i=0; iconvertColourValue(Ogre::ColourValue(colors[0],colors[1],colors[2], - colors[3]),pColour++); - colors += 4; - } - decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); - vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), - numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true); - bind->setBinding(nextBuf++, vbuf); - } - - if (data->uvlist.size()) - { - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); - vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2), - numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,false); - - if(flip) - { - float *datamod = new float[data->uvlist.size()]; - - for(unsigned int i = 0; i < data->uvlist.size(); i+=2){ - float x = data->uvlist[i]; - - float y = data->uvlist[i + 1]; - - datamod[i] =x; - datamod[i + 1] =y; - } - vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); - delete [] datamod; - } - else - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[0], false); - bind->setBinding(nextBuf++, vbuf); - } - - // Triangle faces - The total number of triangle points - int numFaces = data->triangles.size(); - if (numFaces) - { - - sub->indexData->indexCount = numFaces; - sub->indexData->indexStart = 0; - Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton(). - createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, numFaces, - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); - - if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){ - - sub->indexData->indexBuffer = ibuf; - - uint16_t *datamod = new uint16_t[numFaces]; - int index = 0; - for (size_t i = 0; i < sub->indexData->indexCount; i+=3) - { - - const short *pos = &data->triangles[index]; - uint16_t i0 = (uint16_t) *(pos+0); - uint16_t i1 = (uint16_t) *(pos+1); - uint16_t i2 = (uint16_t) *(pos+2); - - //std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n"; - - - datamod[index] = i2; - datamod[index+1] = i1; - datamod[index+2] = i0; - - index += 3; - } - - ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false); - delete [] datamod; - - } - else - ibuf->writeData(0, ibuf->getSizeInBytes(), &data->triangles[0], false); - sub->indexData->indexBuffer = ibuf; - } - - // Set material if one was given - if (!material.empty()) sub->setMaterialName(material); - - //add vertex bone assignments - - for (std::list::iterator it = vertexBoneAssignments.begin(); - it != vertexBoneAssignments.end(); it++) - { - sub->addBoneAssignment(*it); - } - if(mSkel.isNull()) - needBoneAssignments.push_back(sub); -} - -// Helper math functions. Reinventing linear algebra for the win! - -// Computes C = B + AxC*scale -static void vectorMulAdd(const Ogre::Matrix3 &A, const Ogre::Vector3 &B, float *C, float scale) -{ - // Keep the original values - float a = C[0]; - float b = C[1]; - float c = C[2]; - - // Perform matrix multiplication, scaling and addition - for (int i=0;i<3;i++) - C[i] = B[i] + (a*A[i][0] + b*A[i][1] + c*A[i][2])*scale; -} - -// Computes B = AxB (matrix*vector) -static void vectorMul(const Ogre::Matrix3 &A, float *C) -{ - // Keep the original values - float a = C[0]; - float b = C[1]; - float c = C[2]; - - // Perform matrix multiplication, scaling and addition - for (int i=0;i<3;i++) - C[i] = a*A[i][0] + b*A[i][1] + c*A[i][2]; -} - - -void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds, Transformation original, std::vector boneSequence) -{ - assert(shape != NULL); - - bool saveTheShape = inTheSkeletonTree; - // Interpret flags - bool hidden = (flags & 0x01) != 0; // Not displayed - bool collide = (flags & 0x02) != 0; // Use mesh for collision - bool bbcollide = (flags & 0x04) != 0; // Use bounding box for collision - - // Bounding box collision isn't implemented, always use mesh for now. - if (bbcollide) - { - collide = true; - bbcollide = false; - } - - // If the object was marked "NCO" earlier, it shouldn't collide with - // anything. - if (flags & 0x800) - { - collide = false; - bbcollide = false; - } - - if (!collide && !bbcollide && hidden) - // This mesh apparently isn't being used for anything, so don't - // bother setting it up. - return; - - // Material name for this submesh, if any - Ogre::String material; - - // Skip the entire material phase for hidden nodes - if (!hidden) - { - // These are set below if present - NiTexturingProperty *t = NULL; - NiMaterialProperty *m = NULL; - NiAlphaProperty *a = NULL; - - // Scan the property list for material information - PropertyList &list = shape->props; - int n = list.length(); - for (int i=0; irecType == RC_NiTexturingProperty) - t = static_cast(pr); - else if (pr->recType == RC_NiMaterialProperty) - m = static_cast(pr); - else if (pr->recType == RC_NiAlphaProperty) - a = static_cast(pr); - } - - // Texture - Ogre::String texName; - if (t && t->textures[0].inUse) - { - NiSourceTexture *st = t->textures[0].texture.getPtr(); - if (st->external) - { - /* findRealTexture checks if the file actually - exists. If it doesn't, and the name ends in .tga, it - will try replacing the extension with .dds instead - and search for that. Bethesda at some at some point - converted all their BSA textures from tga to dds for - increased load speed, but all texture file name - references were kept as .tga. - - The function replaces the name in place (that's why - we cast away the const modifier), but this is no - problem since all the nif data is stored in a local - throwaway buffer. - */ - texName = "textures\\" + st->filename; - findRealTexture(texName); - } - else warn("Found internal texture, ignoring."); - } - - // Alpha modifiers - int alphaFlags = -1; - ubyte alphaTest = 0; - if (a) - { - alphaFlags = a->flags; - alphaTest = a->data.threshold; - } - - // Material - if (m || !texName.empty()) - { - // If we're here, then this mesh has a material. Thus we - // need to calculate a snappy material name. It should - // contain the mesh name (mesh->getName()) but also has to - // be unique. One mesh may use many materials. - material = getUniqueName(mesh->getName()); - - if (m) - { - // Use NiMaterialProperty data to create the data - const S_MaterialProperty *d = &m->data; - - std::multimap::iterator itr = MaterialMap.find(texName); - std::multimap::iterator lastElement; - lastElement = MaterialMap.upper_bound(texName); - if (itr != MaterialMap.end()) - { - for ( ; itr != lastElement; ++itr) - { - //std::cout << "OK!"; - //MaterialPtr mat = MaterialManager::getSingleton().getByName(itr->second,recourceGroup); - material = itr->second; - //if( mat->getA - } - } - else - { - //std::cout << "new"; - createMaterial(material, d->ambient, d->diffuse, d->specular, d->emissive, - d->glossiness, d->alpha, alphaFlags, alphaTest, texName); - MaterialMap.insert(std::make_pair(texName,material)); - } - } - else - { - // We only have a texture name. Create a default - // material for it. - const Ogre::Vector3 zero(0.0f), one(1.0f); - createMaterial(material, one, one, zero, zero, 0.0f, 1.0f, - alphaFlags, alphaTest, texName); - } - } - } // End of material block, if(!hidden) ... - - /* Do in-place transformation of all the vertices and normals. This - is pretty messy stuff, but we need it to make the sub-meshes - appear in the correct place. Neither Ogre nor Bullet support - nested levels of sub-meshes with transformations applied to each - level. - */ - NiTriShapeData *data = shape->data.getPtr(); - int numVerts = data->vertices.size() / 3; - - float *ptr = (float*)&data->vertices[0]; - float *optr = ptr; - - std::list vertexBoneAssignments; - - Nif::NiTriShapeCopy copy = shape->clone(); - - if(!shape->controller.empty()) - { - Nif::Controller* cont = shape->controller.getPtr(); - if(cont->recType == RC_NiGeomMorpherController) - { - Nif::NiGeomMorpherController* morph = dynamic_cast (cont); - copy.morph = morph->data.get(); - copy.morph.setStartTime(morph->timeStart); - copy.morph.setStopTime(morph->timeStop); - saveTheShape = true; - } - - } - //use niskindata for the position of vertices. - if (!shape->skin.empty()) - { - - - - // vector that stores if the position of a vertex is absolute - std::vector vertexPosAbsolut(numVerts,false); - std::vector vertexPosOriginal(numVerts, Ogre::Vector3::ZERO); - std::vector vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO); - - float *ptrNormals = (float*)&data->normals[0]; - //the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex] - //the first one contains a link to the bone, the second vertex transformation - //relative to the bone - int boneIndex = 0; - Ogre::Bone *bonePtr; - Ogre::Vector3 vecPos; - Ogre::Quaternion vecRot; - - std::vector boneList = shape->skin->data->bones; - - /* - Iterate through the boneList which contains what vertices are linked to - the bone (it->weights array) and at what position (it->trafo) - That position is added to every vertex. - */ - for (std::vector::iterator it = boneList.begin(); - it != boneList.end(); it++) - { - if(mSkel.isNull()) - { - std::cout << "No skeleton for :" << shape->skin->bones[boneIndex]->name << std::endl; - break; - } - //get the bone from bones array of skindata - if(!mSkel->hasBone(shape->skin->bones[boneIndex]->name)) - std::cout << "We don't have this bone"; - bonePtr = mSkel->getBone(shape->skin->bones[boneIndex]->name); - - // final_vector = old_vector + old_rotation*new_vector*old_scale - - - Nif::NiSkinData::BoneInfoCopy boneinfocopy; - boneinfocopy.trafo.rotation = it->trafo.rotation; - boneinfocopy.trafo.trans = it->trafo.trans; - boneinfocopy.bonename = shape->skin->bones[boneIndex]->name; - boneinfocopy.bonehandle = bonePtr->getHandle(); - copy.boneinfo.push_back(boneinfocopy); - for (unsigned int i=0; iweights.size(); i++) - { - vecPos = bonePtr->_getDerivedPosition() + - bonePtr->_getDerivedOrientation() * it->trafo.trans; - - vecRot = bonePtr->_getDerivedOrientation() * it->trafo.rotation; - unsigned int verIndex = it->weights[i].vertex; - //boneinfo.weights.push_back(*(it->weights.ptr + i)); - Nif::NiSkinData::IndividualWeight ind; - ind.weight = it->weights[i].weight; - ind.boneinfocopyindex = copy.boneinfo.size() - 1; - if(copy.vertsToWeights.find(verIndex) == copy.vertsToWeights.end()) - { - std::vector blank; - blank.push_back(ind); - copy.vertsToWeights[verIndex] = blank; - } - else - { - copy.vertsToWeights[verIndex].push_back(ind); - } - - //Check if the vertex is relativ, FIXME: Is there a better solution? - if (vertexPosAbsolut[verIndex] == false) - { - //apply transformation to the vertices - Ogre::Vector3 absVertPos = vecPos + vecRot * Ogre::Vector3(ptr + verIndex *3); - absVertPos = absVertPos * it->weights[i].weight; - vertexPosOriginal[verIndex] = Ogre::Vector3(ptr + verIndex *3); - - mBoundingBox.merge(absVertPos); - //convert it back to float * - for (int j=0; j<3; j++) - (ptr + verIndex*3)[j] = absVertPos[j]; - - //apply rotation to the normals (not every vertex has a normal) - //FIXME: I guessed that vertex[i] = normal[i], is that true? - if (verIndex < data->normals.size()) - { - Ogre::Vector3 absNormalsPos = vecRot * Ogre::Vector3(ptrNormals + verIndex *3); - absNormalsPos = absNormalsPos * it->weights[i].weight; - vertexNormalOriginal[verIndex] = Ogre::Vector3(ptrNormals + verIndex *3); - - for (int j=0; j<3; j++) - (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; - } - - vertexPosAbsolut[verIndex] = true; - } - else - { - Ogre::Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex]; - absVertPos = absVertPos * it->weights[i].weight; - Ogre::Vector3 old = Ogre::Vector3(ptr + verIndex *3); - absVertPos = absVertPos + old; - - mBoundingBox.merge(absVertPos); - //convert it back to float * - for (int j=0; j<3; j++) - (ptr + verIndex*3)[j] = absVertPos[j]; - - //apply rotation to the normals (not every vertex has a normal) - //FIXME: I guessed that vertex[i] = normal[i], is that true? - if (verIndex < data->normals.size()) - { - Ogre::Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex]; - absNormalsPos = absNormalsPos * it->weights[i].weight; - Ogre::Vector3 oldNormal = Ogre::Vector3(ptrNormals + verIndex *3); - absNormalsPos = absNormalsPos + oldNormal; - - for (int j=0; j<3; j++) - (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; - } - } - - - Ogre::VertexBoneAssignment vba; - vba.boneIndex = bonePtr->getHandle(); - vba.vertexIndex = verIndex; - vba.weight = it->weights[i].weight; - - - vertexBoneAssignments.push_back(vba); - } - - - boneIndex++; - } - - - } - else - { - - copy.boneSequence = boneSequence; - // Rotate, scale and translate all the vertices, - const Ogre::Matrix3 &rot = shape->trafo.rotation; - const Ogre::Vector3 &pos = shape->trafo.pos; - float scale = shape->trafo.scale; - - copy.trafo.trans = original.pos; - copy.trafo.rotation = original.rotation; - copy.trafo.scale = original.scale; - //We don't use velocity for anything yet, so it does not need to be saved - - // Computes C = B + AxC*scale - for (int i=0; inormals.size()) - { - ptr = (float*)&data->normals[0]; - for (int i=0; igetNumBones() - 1; - for(int i = 0; i < numVerts; i++){ - Ogre::VertexBoneAssignment vba; - vba.boneIndex = boneIndex; - vba.vertexIndex = i; - vba.weight = 1; - vertexBoneAssignments.push_back(vba); - } - } - } - - if (!hidden) - { - // Add this vertex set to the bounding box - bounds.add(optr, numVerts); - if(saveTheShape) - shapes.push_back(copy); - - // Create the submesh - createOgreSubMesh(shape, material, vertexBoneAssignments); - } -} - -void NIFLoader::calculateTransform() -{ - // Calculate transform - Ogre::Matrix4 transform = Ogre::Matrix4::IDENTITY; - transform = Ogre::Matrix4::getScale(vector) * transform; - - // Check whether we have to flip vertex winding. - // We do have to, if we changed our right hand base. - // We can test it by using the cross product from X and Y and see, if it is a non-negative - // projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet, - // but the test is cheap either way. - Ogre::Matrix3 m3; - transform.extract3x3Matrix(m3); - - if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0) - { - mFlipVertexWinding = true; - } - - mTransform = transform; -} -void NIFLoader::handleNode(Nif::Node *node, int flags, - const Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence) -{ - // Accumulate the flags from all the child nodes. This works for all - // the flags we currently use, at least. - flags |= node->flags; - - // Check for extra data - Extra *e = node; - while (!e->extra.empty()) - { - // Get the next extra data in the list - e = e->extra.getPtr(); - assert(e != NULL); - - if (e->recType == RC_NiStringExtraData) - { - // String markers may contain important information - // affecting the entire subtree of this node - NiStringExtraData *sd = (NiStringExtraData*)e; - - if (sd->string == "NCO") - // No collision. Use an internal flag setting to mark this. - flags |= 0x800; - else if (sd->string == "MRK") - // Marker objects. These are only visible in the - // editor. Until and unless we add an editor component to - // the engine, just skip this entire node. - return; - } - - if (e->recType == RC_NiTextKeyExtraData){ - Nif::NiTextKeyExtraData* extra = dynamic_cast (e); - - std::ofstream file; - - if(mOutputAnimFiles){ - std::string cut = ""; - for(unsigned int i = 0; i < name.length(); i++) - { - if(!(name.at(i) == '\\' || name.at(i) == '/' || name.at(i) == '>' || name.at(i) == '<' || name.at(i) == '?' || name.at(i) == '*' || name.at(i) == '|' || name.at(i) == ':' || name.at(i) == '"')) - { - cut += name.at(i); - } - } - - std::cout << "Outputting " << cut << "\n"; - - file.open((verbosePath + "/Indices" + cut + ".txt").c_str()); - } - - for(std::vector::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++) - { - std::string text = textiter->text; - - replace(text.begin(), text.end(), '\n', '/'); - - text.erase(std::remove(text.begin(), text.end(), '\r'), text.end()); - std::size_t i = 0; - while(i < text.length()){ - while(i < text.length() && text.at(i) == '/' ){ - i++; - } - std::size_t first = i; - int length = 0; - while(i < text.length() && text.at(i) != '/' ){ - i++; - length++; - } - if(first < text.length()){ - //length = text.length() - first; - std::string sub = text.substr(first, length); - - if(mOutputAnimFiles) - file << "Time: " << textiter->time << "|" << sub << "\n"; - - textmappings[sub] = textiter->time; - } - } - } - file.close(); - } - } - - Ogre::Bone *bone = 0; - - // create skeleton or add bones - if (node->recType == RC_NiNode) - { - //FIXME: "Bip01" isn't every time the root bone - if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton - { - inTheSkeletonTree = true; - - mSkel = Ogre::SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true); - } - else if (!mSkel.isNull() && !parentBone) - inTheSkeletonTree = false; - - if (!mSkel.isNull()) //if there is a skeleton - { - std::string name = node->name; - - // Quick-n-dirty workaround for the fact that several - // bones may have the same name. - if(!mSkel->hasBone(name)) - { - boneSequence.push_back(name); - bone = mSkel->createBone(name); - - if (parentBone) - parentBone->addChild(bone); - - bone->setInheritOrientation(true); - bone->setPosition(node->trafo.pos); - bone->setOrientation(node->trafo.rotation); - } - } - } - Transformation original = node->trafo; - // Apply the parent transformation to this node. We overwrite the - // existing data with the final transformation. - if (trafo) - { - // Get a non-const reference to the node's data, since we're - // overwriting it. TODO: Is this necessary? - Transformation &final = node->trafo; - - // For both position and rotation we have that: - // final_vector = old_vector + old_rotation*new_vector*old_scale - final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale; - - // Merge the rotations together - final.rotation = trafo->rotation * final.rotation; - - // Scale - final.scale *= trafo->scale; - } - - // For NiNodes, loop through children - if (node->recType == RC_NiNode) - { - NodeList &list = ((NiNode*)node)->children; - int n = list.length(); - for (int i = 0; itrafo, bounds, bone, boneSequence); - } - } - else if (node->recType == RC_NiTriShape && bNiTri) - { - std::string nodename = node->name; - - if (triname == "") - { - handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); - } - else if(nodename.length() >= triname.length()) - { - std::transform(nodename.begin(), nodename.end(), nodename.begin(), ::tolower); - if(triname == nodename.substr(0, triname.length())) - handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); - } - } -} void NIFLoader::loadResource(Ogre::Resource *resource) { - inTheSkeletonTree = false; - allanim.clear(); - shapes.clear(); - needBoneAssignments.clear(); - // needBoneAssignments.clear(); - mBoundingBox.setNull(); - mesh = 0; - mSkel.setNull(); - flip = false; - name = resource->getName(); - char suffix = name.at(name.length() - 2); - bool addAnim = true; - bool hasAnim = false; - bool linkSkeleton = true; - //bool baddin = false; - bNiTri = true; - if(name == "meshes\\base_anim.nif" || name == "meshes\\base_animkna.nif") - { - bNiTri = false; - } - - if(suffix == '*') - { - vector = Ogre::Vector3(-1,1,1); - flip = true; - } - else if(suffix == '?'){ - vector = Ogre::Vector3(1,-1,1); - flip = true; - } - else if(suffix == '<'){ - vector = Ogre::Vector3(1,1,-1); - flip = true; - } - else if(suffix == '>') - { - //baddin = true; - bNiTri = true; - std::string sub = name.substr(name.length() - 6, 4); - - if(sub.compare("0000") != 0) - addAnim = false; - - } - else if(suffix == ':') - { - //baddin = true; - linkSkeleton = false; - bNiTri = true; - std::string sub = name.substr(name.length() - 6, 4); - - if(sub.compare("0000") != 0) - addAnim = false; - - } - - switch(name.at(name.length() - 1)) - { - case '"': - triname = "tri chest"; - break; - case '*': - triname = "tri tail"; - break; - case ':': - triname = "tri left foot"; - break; - case '<': - triname = "tri right foot"; - break; - case '>': - triname = "tri left hand"; - break; - case '?': - triname = "tri right hand"; - break; - default: - triname = ""; - break; - } - if(flip) - { - calculateTransform(); - } - // Get the mesh - mesh = dynamic_cast(resource); - assert(mesh); - - // Look it up - resourceName = mesh->getName(); - - - // Helper that computes bounding boxes for us. - BoundsFinder bounds; - - // Load the NIF. TODO: Wrap this in a try-catch block once we're out - // of the early stages of development. Right now we WANT to catch - // every error as early and intrusively as possible, as it's most - // likely a sign of incomplete code rather than faulty input. - NIFFile nif(resourceName); - if (nif.numRecords() < 1) - { - warn("Found no records in NIF."); - return; - } - - // The first record is assumed to be the root node - Record *r = nif.getRecord(0); - assert(r != NULL); - - Nif::Node *node = dynamic_cast(r); - - if (node == NULL) - { - warn("First record in file was not a node, but a " + - r->recName + ". Skipping file."); - return; - } - - // Handle the node - std::vector boneSequence; - - - - handleNode(node, 0, NULL, bounds, 0, boneSequence); - if(addAnim) - { - for(int i = 0; i < nif.numRecords(); i++) - { - Nif::NiKeyframeController *f = dynamic_cast(nif.getRecord(i)); - - if(f != NULL) - { - hasAnim = true; - Nif::Node *o = dynamic_cast(f->target.getPtr()); - Nif::NiKeyframeDataPtr data = f->data; - - if (f->timeStart >= 10000000000000000.0f) - continue; - data->setBonename(o->name); - data->setStartTime(f->timeStart); - data->setStopTime(f->timeStop); - - allanim.push_back(data.get()); - } - } - } - // set the bounding value. - if (bounds.isValid()) - { - mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(), - bounds.maxX(), bounds.maxY(), bounds.maxZ())); - mesh->_setBoundingSphereRadius(bounds.getRadius()); - } - if(hasAnim && addAnim){ - allanimmap[name] = allanim; - alltextmappings[name] = textmappings; - } - if(!mSkel.isNull() && shapes.size() > 0 && addAnim) - { - allshapesmap[name] = shapes; - - } - - if(flip){ - mesh->_setBounds(mBoundingBox, false); - } - - if (!mSkel.isNull() ) - { - for(std::vector::iterator iter = needBoneAssignments.begin(); iter != needBoneAssignments.end(); iter++) - { - int boneIndex = mSkel->getNumBones() - 1; - Ogre::VertexBoneAssignment vba; - vba.boneIndex = boneIndex; - vba.vertexIndex = 0; - vba.weight = 1; - - - (*iter)->addBoneAssignment(vba); - } - //Don't link on npc parts to eliminate redundant skeletons - //Will have to be changed later slightly for robes/skirts - if(linkSkeleton) - mesh->_notifySkeleton(mSkel); - } + warn("Found no records in NIF."); } - - - - Ogre::MeshPtr NIFLoader::load(const std::string &name, const std::string &group) { + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - Ogre::MeshManager *m = Ogre::MeshManager::getSingletonPtr(); // Check if the resource already exists - Ogre::ResourcePtr ptr = m->getByName(name, group); - Ogre::MeshPtr themesh; - if (!ptr.isNull()){ - themesh = Ogre::MeshPtr(ptr); - } - else // Nope, create a new one. + Ogre::MeshPtr themesh = meshMgr.getByName(name, group); + if(themesh.isNull()) { - themesh = Ogre::MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr()); + static NIFLoader loader; + themesh = meshMgr.createManual(name, group, &loader); } return themesh; } -/* -This function shares much of the same code handleShapes() in MWRender::Animation -This function also creates new position and normal buffers for submeshes. -This function points to existing texture and IndexData buffers -*/ - -std::vector* NIFLoader::getAnim(std::string lowername){ - - std::map,ciLessBoost>::iterator iter = allanimmap.find(lowername); - std::vector* pass = 0; - if(iter != allanimmap.end()) - pass = &(iter->second); - return pass; - -} -std::vector* NIFLoader::getShapes(std::string lowername){ - - std::map,ciLessBoost>::iterator iter = allshapesmap.find(lowername); - std::vector* pass = 0; - if(iter != allshapesmap.end()) - pass = &(iter->second); - return pass; -} - -std::map* NIFLoader::getTextIndices(std::string lowername){ - std::map, ciLessBoost>::iterator iter = alltextmappings.find(lowername); - std::map* pass = 0; - if(iter != alltextmappings.end()) - pass = &(iter->second); - return pass; -} - - - /* More code currently not in use, from the old D source. This was used in the first attempt at loading NIF meshes, where each submesh diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 64efc70c7..bc1ef304c 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -67,12 +67,9 @@ namespace Nif namespace NifOgre { - - /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into - something Ogre can use. Later it will also handle the insertion of - collision meshes into Bullet / OgreBullet. + something Ogre can use. You have to insert meshes manually into Ogre like this: @@ -86,93 +83,18 @@ namespace NifOgre */ class NIFLoader : Ogre::ManualResourceLoader { - public: - static int numberOfMeshes; - static NIFLoader& getSingleton(); - static NIFLoader* getSingletonPtr(); +public: + virtual void loadResource(Ogre::Resource *resource); - virtual void loadResource(Ogre::Resource *resource); - - static Ogre::MeshPtr load(const std::string &name, - const std::string &group="General"); - //void insertMeshInsideBase(Ogre::Mesh* mesh); - std::vector* getAnim(std::string name); - std::vector* getShapes(std::string name); - std::map* getTextIndices(std::string name); - - - void setOutputAnimFiles(bool output); - void setVerbosePath(std::string path); - - private: - - NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false), - mFlipVertexWinding(false), mOutputAnimFiles(false), inTheSkeletonTree(false) {} - NIFLoader(NIFLoader& n) {} - - void calculateTransform(); - - - void warn(std::string msg); - void fail(std::string msg); - - void handleNode( Nif::Node *node, int flags, - const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence); - - void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds, Nif::Transformation original, std::vector boneSequence); - - void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list &vertexBoneAssignments); - - void createMaterial(const Ogre::String &name, - const Ogre::Vector3 &ambient, - const Ogre::Vector3 &diffuse, - const Ogre::Vector3 &specular, - const Ogre::Vector3 &emissive, - float glossiness, float alpha, - int alphaFlags, float alphaTest, - const Ogre::String &texName); - - void findRealTexture(Ogre::String &texName); - - Ogre::String getUniqueName(const Ogre::String &input); - - //returns the skeleton name of this mesh - std::string getSkeletonName() - { - return resourceName + ".skel"; - } - - std::string verbosePath; - std::string resourceName; - std::string resourceGroup; - Ogre::Matrix4 mTransform; - Ogre::AxisAlignedBox mBoundingBox; - bool flip; - bool mNormaliseNormals; - bool mFlipVertexWinding; - bool bNiTri; - bool mOutputAnimFiles; - std::multimap MaterialMap; - - // pointer to the ogre mesh which is currently build - Ogre::Mesh *mesh; - Ogre::SkeletonPtr mSkel; - Ogre::Vector3 vector; - std::vector shapes; - std::string name; - std::string triname; - std::vector allanim; - - std::map textmappings; - std::map,ciLessBoost> alltextmappings; - std::map,ciLessBoost> allanimmap; - std::map,ciLessBoost> allshapesmap; - std::vector mAnim; - std::vector mS; - std::vector needBoneAssignments; - bool inTheSkeletonTree; + static Ogre::MeshPtr load(const std::string &name, + const std::string &group="General"); +private: + NIFLoader() {} + NIFLoader(NIFLoader& n) {} + void warn(const std::string &msg); + void fail(const std::string &msg); }; } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 11c18010e..61d0c7b0e 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -336,7 +336,7 @@ namespace Physic char uniqueID[8]; sprintf( uniqueID, "%07.3f", scale ); std::string sid = uniqueID; - std::string outputstring = mesh + uniqueID + "\"|"; + std::string outputstring = mesh + uniqueID; //std::cout << "The string" << outputstring << "\n"; //get the shape from the .nif From ecdd4ee23f329cce4d48796f5a27a9af2eb22d5f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 20:55:11 -0700 Subject: [PATCH 012/126] Load NiMorphData and NiKeyframeData using proper key lists --- apps/openmw/mwrender/animation.cpp | 65 ----- components/nif/data.hpp | 371 ++--------------------------- 2 files changed, 19 insertions(+), 417 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 7e50706f9..13b797734 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -171,71 +171,6 @@ bool Animation::timeIndex(float time, const std::vector ×, int &i, i void Animation::handleAnimationTransforms() { - Ogre::SkeletonInstance* skel = base->getSkeleton(); - - Ogre::Bone* b = skel->getRootBone(); - b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick - - skel->_updateTransforms(); - //skel->_notifyManualBonesDirty(); - - base->getAllAnimationStates()->_notifyDirty(); - //base->_updateAnimation(); - //base->_notifyMoved(); - - std::vector::iterator iter; - int slot = 0; - if(transformations) - { - for(iter = transformations->begin(); iter != transformations->end(); iter++) - { - if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) - { - slot++; - continue; - } - - float x; - float x2; - - const std::vector &quats = iter->getQuat(); - const std::vector &ttime = iter->gettTime(); - const std::vector &rtime = iter->getrTime(); - const std::vector &translist1 = iter->getTranslist1(); - - int rindexJ = rindexI[slot]; - timeIndex(time, rtime, rindexI[slot], rindexJ, x2); - - int tindexJ = tindexI[slot]; - timeIndex(time, ttime, tindexI[slot], tindexJ, x); - - Ogre::Vector3 t; - Ogre::Quaternion r; - - bool bTrans = translist1.size() > 0; - bool bQuats = quats.size() > 0; - if(skel->hasBone(iter->getBonename())) - { - Ogre::Bone* bone = skel->getBone(iter->getBonename()); - if(bTrans) - { - Ogre::Vector3 v1 = translist1[tindexI[slot]]; - Ogre::Vector3 v2 = translist1[tindexJ]; - t = (v1 + (v2 - v1) * x); - bone->setPosition(t); - } - if(bQuats) - { - r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); - bone->setOrientation(r); - } - } - - slot++; - } - skel->_updateTransforms(); - base->getAllAnimationStates()->_notifyDirty(); - } } } diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 2d1e8bd3b..208337f35 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -373,378 +373,45 @@ public: } }; -class NiMorphData : public Record +struct NiMorphData : public Record { - float startTime; - float stopTime; - std::vector initialVertices; - std::vector > relevantTimes; - std::vector > relevantData; - std::vector > additionalVertices; - -public: - float getStartTime() const - { return startTime; } - float getStopTime() const - { return stopTime; } - - void setStartTime(float time) - { startTime = time; } - void setStopTime(float time) - { stopTime = time; } - - const std::vector& getInitialVertices() const - { return initialVertices; } - const std::vector >& getRelevantData() const - { return relevantData; } - const std::vector >& getRelevantTimes() const - { return relevantTimes; } - const std::vector >& getAdditionalVertices() const - { return additionalVertices; } + struct MorphData { + FloatKeyList mData; + std::vector mVertices; + }; + std::vector mMorphs; void read(NIFFile *nif) { int morphCount = nif->getInt(); int vertCount = nif->getInt(); nif->getChar(); - int magic = nif->getInt(); - /*int type =*/ nif->getInt(); - for(int i = 0; i < vertCount; i++) + mMorphs.resize(morphCount); + for(int i=0; igetFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - initialVertices.push_back(Ogre::Vector3(x, y, z)); - } + mMorphs[i].mData.read(nif); - for(int i=1; igetInt(); - /*type =*/ nif->getInt(); - std::vector current; - std::vector currentTime; - for(int i = 0; i < magic; i++) - { - // Time, data, forward, backward tangents - float time = nif->getFloat(); - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - current.push_back(Ogre::Vector3(x,y,z)); - currentTime.push_back(time); - //nif->getFloatLen(4*magic); - } - - if(magic) - { - relevantData.push_back(current); - relevantTimes.push_back(currentTime); - } - - std::vector verts; - for(int i = 0; i < vertCount; i++) - { - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - verts.push_back(Ogre::Vector3(x, y, z)); - } - additionalVertices.push_back(verts); + mMorphs[i].mVertices.resize(vertCount); + for(int j = 0;j < vertCount;j++) + mMorphs[i].mVertices[j] = nif->getVector3(); } } }; -class NiKeyframeData : public Record +struct NiKeyframeData : public Record { - std::string bonename; - //Rotations - std::vector quats; - std::vector tbc; - std::vector rottime; - float startTime; - float stopTime; - int rtype; - - //Translations - std::vector translist1; - std::vector translist2; - std::vector translist3; - std::vector transtbc; - std::vector transtime; - int ttype; - - //Scalings - std::vector scalefactor; - std::vector scaletime; - std::vector forwards; - std::vector backwards; - std::vector tbcscale; - int stype; - -public: - void clone(const NiKeyframeData &c) - { - quats = c.getQuat(); - tbc = c.getrTbc(); - rottime = c.getrTime(); - - //types - ttype = c.getTtype(); - rtype = c.getRtype(); - stype = c.getStype(); - - - translist1 = c.getTranslist1(); - translist2 = c.getTranslist2(); - translist3 = c.getTranslist3(); - - transtime = c.gettTime(); - - bonename = c.getBonename(); - } - - void setBonename(std::string bone) - { bonename = bone; } - void setStartTime(float start) - { startTime = start; } - void setStopTime(float end) - { stopTime = end; } + QuaternionKeyList mRotations; + Vector3KeyList mTranslations; + FloatKeyList mScales; void read(NIFFile *nif) { - // Rotations first - int count = nif->getInt(); - //std::vector quat(count); - //std::vector rottime(count); - if(count) - { - //TYPE1 LINEAR_KEY - //TYPE2 QUADRATIC_KEY - //TYPE3 TBC_KEY - //TYPE4 XYZ_ROTATION_KEY - //TYPE5 UNKNOWN_KEY - rtype = nif->getInt(); - //std::cout << "Count: " << count << "Type: " << type << "\n"; - - if(rtype == 1) - { - //We need to actually read in these values instead of skipping them - //nif->skip(count*4*5); // time + quaternion - for (int i = 0; i < count; i++) - { - float time = nif->getFloat(); - float w = nif->getFloat(); - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z)); - quats.push_back(quat); - rottime.push_back(time); - //if(time == 0.0 || time > 355.5) - // std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n"; - } - } - else if(rtype == 3) - { - //Example - node 116 in base_anim.nif - for (int i = 0; i < count; i++) - { - float time = nif->getFloat(); - float w = nif->getFloat(); - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - - float tbcx = nif->getFloat(); - float tbcy = nif->getFloat(); - float tbcz = nif->getFloat(); - - Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z)); - Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz); - quats.push_back(quat); - rottime.push_back(time); - tbc.push_back(vec); - //if(time == 0.0 || time > 355.5) - // std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n"; - } - } - else if(rtype == 4) - { - for(int j=0;jgetFloat(); // time - for(int i=0; i<3; i++) - { - int cnt = nif->getInt(); - int type = nif->getInt(); - if(type == 1) - nif->skip(cnt*4*2); // time + unknown - else if(type == 2) - nif->skip(cnt*4*4); // time + unknown vector - else - nif->fail("Unknown sub-rotation type"); - } - } - } - else - nif->fail("Unknown rotation type in NiKeyframeData"); - } - //first = false; - - // Then translation - count = nif->getInt(); - if(count) - { - ttype = nif->getInt(); - - //std::cout << "TransCount:" << count << " Type: " << type << "\n"; - if(ttype == 1) - { - for(int i = 0; i < count; i++) - { - float time = nif->getFloat(); - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - - Ogre::Vector3 trans = Ogre::Vector3(x, y, z); - translist1.push_back(trans); - transtime.push_back(time); - } - //nif->getFloatLen(count*4); // time + translation - } - else if(ttype == 2) - { - //Example - node 116 in base_anim.nif - for(int i = 0; i < count; i++) - { - float time = nif->getFloat(); - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - float x2 = nif->getFloat(); - float y2 = nif->getFloat(); - float z2 = nif->getFloat(); - float x3 = nif->getFloat(); - float y3 = nif->getFloat(); - float z3 = nif->getFloat(); - - Ogre::Vector3 trans = Ogre::Vector3(x, y, z); - Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2); - Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3); - transtime.push_back(time); - translist1.push_back(trans); - translist2.push_back(trans2); - translist3.push_back(trans3); - } - - //nif->getFloatLen(count*10); // trans1 + forward + backward - } - else if(ttype == 3) - { - for(int i = 0; i < count; i++) - { - float time = nif->getFloat(); - float x = nif->getFloat(); - float y = nif->getFloat(); - float z = nif->getFloat(); - float t = nif->getFloat(); - float b = nif->getFloat(); - float c = nif->getFloat(); - Ogre::Vector3 trans = Ogre::Vector3(x, y, z); - Ogre::Vector3 tbc = Ogre::Vector3(t, b, c); - translist1.push_back(trans); - transtbc.push_back(tbc); - transtime.push_back(time); - } - //nif->getFloatLen(count*7); // trans1 + tension,bias,continuity - } - else nif->fail("Unknown translation type"); - } - - // Finally, scalings - count = nif->getInt(); - if(count) - { - stype = nif->getInt(); - - for(int i = 0; i < count; i++) - { - //int size = 0; - if(stype >= 1 && stype < 4) - { - float time = nif->getFloat(); - float scale = nif->getFloat(); - scaletime.push_back(time); - scalefactor.push_back(scale); - //size = 2; // time+scale - } - else - nif->fail("Unknown scaling type"); - - if(stype == 2) - { - //size = 4; // 1 + forward + backward (floats) - float forward = nif->getFloat(); - float backward = nif->getFloat(); - forwards.push_back(forward); - backwards.push_back(backward); - } - else if(stype == 3) - { - //size = 5; // 1 + tbc - float tbcx = nif->getFloat(); - float tbcy = nif->getFloat(); - float tbcz = nif->getFloat(); - Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz); - tbcscale.push_back(vec); - } - } - } - else - stype = 0; + mRotations.read(nif); + mTranslations.read(nif); + mScales.read(nif); } - - int getRtype() const - { return rtype; } - int getStype() const - { return stype; } - int getTtype() const - { return ttype; } - float getStartTime() const - { return startTime; } - float getStopTime() const - { return stopTime; } - const std::vector& getQuat() const - { return quats; } - const std::vector& getrTbc() const - { return tbc; } - const std::vector& getrTime() const - { return rottime; } - - const std::vector& getTranslist1() const - { return translist1; } - const std::vector& getTranslist2() const - { return translist2; } - const std::vector& getTranslist3() const - { return translist3; } - const std::vector& gettTime() const - { return transtime; } - const std::vector& getScalefactor() const - { return scalefactor; } - const std::vector& getForwards() const - { return forwards; } - const std::vector& getBackwards() const - { return backwards; } - const std::vector& getScaleTbc() const - { return tbcscale; } - - const std::vector& getsTime() const - { return scaletime; } - const std::string& getBonename() const - { return bonename; } }; } // Namespace From 9436ca4b0cea93fcd53cba5884d360518cfe1bf9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 13 Jul 2012 09:32:58 -0700 Subject: [PATCH 013/126] Use vectors for ShapeData properties --- components/nif/data.hpp | 16 ++++++++----- components/nif/nif_file.hpp | 26 ++++++++++++++++++++++ components/nifbullet/bullet_nif_loader.cpp | 17 ++++++-------- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 208337f35..d08ba7b32 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -96,7 +96,9 @@ public: class ShapeData : public Record { public: - std::vector vertices, normals, colors, uvlist; + std::vector vertices, normals; + std::vector colors; + std::vector< std::vector > uvlist; Ogre::Vector3 center; float radius; @@ -105,16 +107,16 @@ public: int verts = nif->getUShort(); if(nif->getInt()) - nif->getFloats(vertices, verts*3); + nif->getVector3s(vertices, verts); if(nif->getInt()) - nif->getFloats(normals, verts*3); + nif->getVector3s(normals, verts); center = nif->getVector3(); radius = nif->getFloat(); if(nif->getInt()) - nif->getFloats(colors, verts*4); + nif->getVector4s(colors, verts); // Only the first 6 bits are used as a count. I think the rest are // flags of some sort. @@ -122,7 +124,11 @@ public: uvs &= 0x3f; if(nif->getInt()) - nif->getFloats(uvlist, uvs*verts*2); + { + uvlist.resize(uvs); + for(int i = 0;i < uvs;i++) + nif->getVector2s(uvlist[i], verts); + } } }; diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index c33790742..f6c23ec9a 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -142,6 +143,13 @@ public: unsigned short getUShort() { return read_le16(); } int getInt() { return read_le32(); } float getFloat() { return read_le32f(); } + Ogre::Vector2 getVector2() + { + float a[2]; + for(size_t i = 0;i < 2;i++) + a[i] = getFloat(); + return Ogre::Vector2(a); + } Ogre::Vector3 getVector3() { float a[3]; @@ -208,6 +216,24 @@ public: for(size_t i = 0;i < vec.size();i++) vec[i] = getFloat(); } + void getVector2s(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getVector2(); + } + void getVector3s(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getVector3(); + } + void getVector4s(std::vector &vec, size_t size) + { + vec.resize(size); + for(size_t i = 0;i < vec.size();i++) + vec[i] = getVector4(); + } }; diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 5f562504b..bdf508f6c 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -271,19 +271,16 @@ void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags Nif::NiTriShapeData *data = shape->data.getPtr(); - float* vertices = &data->vertices[0]; - short* triangles = &data->triangles[0]; + const std::vector &vertices = data->vertices; const Ogre::Matrix3 &rot = shape->trafo.rotation; const Ogre::Vector3 &pos = shape->trafo.pos; - float scale = shape->trafo.scale; - for(unsigned int i=0; i < data->triangles.size(); i = i+3) + float scale = shape->trafo.scale * parentScale; + short* triangles = &data->triangles[0]; + for(size_t i = 0;i < data->triangles.size();i+=3) { - Ogre::Vector3 b1(vertices[triangles[i+0]*3]*parentScale,vertices[triangles[i+0]*3+1]*parentScale,vertices[triangles[i+0]*3+2]*parentScale); - Ogre::Vector3 b2(vertices[triangles[i+1]*3]*parentScale,vertices[triangles[i+1]*3+1]*parentScale,vertices[triangles[i+1]*3+2]*parentScale); - Ogre::Vector3 b3(vertices[triangles[i+2]*3]*parentScale,vertices[triangles[i+2]*3+1]*parentScale,vertices[triangles[i+2]*3+2]*parentScale); - b1 = pos + rot*b1*scale; - b2 = pos + rot*b2*scale; - b3 = pos + rot*b3*scale; + Ogre::Vector3 b1 = pos + rot*vertices[triangles[i+0]]*scale; + Ogre::Vector3 b2 = pos + rot*vertices[triangles[i+1]]*scale; + Ogre::Vector3 b3 = pos + rot*vertices[triangles[i+2]]*scale; mTriMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z)); } } From fdfe40a55a3bf0744cb7fb3a6d548c0eb35e34e5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 13 Jul 2012 13:41:08 -0700 Subject: [PATCH 014/126] Use a different loader object for each NIF mesh --- components/nifogre/ogre_nif_loader.cpp | 6 ++++-- components/nifogre/ogre_nif_loader.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 883cf7fce..efe9ddea6 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -128,6 +128,8 @@ public: }; +NIFLoader::LoaderMap NIFLoader::sLoaders; + void NIFLoader::warn(const std::string &msg) { std::cerr << "NIFLoader: Warn:" << msg << "\n"; @@ -331,8 +333,8 @@ Ogre::MeshPtr NIFLoader::load(const std::string &name, const std::string &group) Ogre::MeshPtr themesh = meshMgr.getByName(name, group); if(themesh.isNull()) { - static NIFLoader loader; - themesh = meshMgr.createManual(name, group, &loader); + NIFLoader *loader = &sLoaders[name]; + themesh = meshMgr.createManual(name, group, loader); } return themesh; } diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index bc1ef304c..985c64e0d 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -41,7 +41,7 @@ #include #include -#include +#include // For warning messages #include using namespace boost::algorithm; @@ -90,11 +90,11 @@ public: const std::string &group="General"); private: - NIFLoader() {} - NIFLoader(NIFLoader& n) {} - void warn(const std::string &msg); void fail(const std::string &msg); + + typedef std::map LoaderMap; + static LoaderMap sLoaders; }; } From 939d0d2fc5b4a1a8d78e708ed7c519a2ca5416e2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 13 Jul 2012 18:25:35 -0700 Subject: [PATCH 015/126] Return a list of meshes and the skeleton from NIFLoader::load --- apps/openmw/mwrender/creatureanimation.cpp | 5 +- apps/openmw/mwrender/npcanimation.cpp | 12 +- apps/openmw/mwrender/objects.cpp | 5 +- apps/openmw/mwrender/sky.cpp | 206 +++++++++++---------- apps/openmw/mwrender/sky.hpp | 5 +- components/nifogre/ogre_nif_loader.cpp | 12 +- components/nifogre/ogre_nif_loader.hpp | 20 +- 7 files changed, 146 insertions(+), 119 deletions(-) diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 6bdd58ac3..0690a7be7 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,8 +26,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O { std::string mesh = "meshes\\" + ref->base->model; - NifOgre::NIFLoader::load(mesh); - base = mRend.getScene()->createEntity(mesh); + // FIXME: There can be more than one! + NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(mesh); + base = mRend.getScene()->createEntity(meshes[0].first->getName()); base->setVisibilityFlags(RV_Actors); bool transparent = false; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index fa33d18ff..d6600bc1b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -82,8 +82,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere assert(insert); std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - NifOgre::NIFLoader::load(smodel); - base = mRend.getScene()->createEntity(smodel); + + // FIXME: There can be more than one! + NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(smodel); + base = mRend.getScene()->createEntity(meshes[0].first->getName()); base->setVisibilityFlags(RV_Actors); bool transparent = false; @@ -382,9 +384,9 @@ void NpcAnimation::updateParts() Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) { - - NIFLoader::load(mesh); - Ogre::Entity* part = mRend.getScene()->createEntity(mesh); + // FIXME: There can be more than one! + NifOgre::MeshPairList meshes = NIFLoader::load(mesh); + Ogre::Entity* part = mRend.getScene()->createEntity(meshes[0].first->getName()); part->setVisibilityFlags(RV_Actors); base->attachObjectToBone(bonename, part); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index fb2bfb3c5..ea58ec716 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -92,8 +92,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); - NifOgre::NIFLoader::load(mesh); - Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh); + // FIXME: There can be more than one! + NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(mesh); + Ogre::Entity *ent = mRenderer.getScene()->createEntity(meshes[0].first->getName()); Ogre::Vector3 extents = ent->getBoundingBox().getSize(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 45e48240b..8f49e03df 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -453,16 +453,6 @@ void SkyManager::create() HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); // Stars - /// \todo sky_night_02.nif (available in Bloodmoon) - MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); - Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif"); - night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); - night1_ent->setVisibilityFlags(RV_Sky); - night1_ent->setCastShadows(false); - - mAtmosphereNight = mRootNode->createChildSceneNode(); - mAtmosphereNight->attachObject(night1_ent); - // Stars vertex shader HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); @@ -517,35 +507,35 @@ void SkyManager::create() stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - for (unsigned int i=0; igetNumSubEntities(); ++i) + /// \todo sky_night_02.nif (available in Bloodmoon) + mAtmosphereNight = mRootNode->createChildSceneNode(); + NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); + for(size_t i = 0;i < meshes.size();i++) { - MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); - mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); - mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); - mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); - mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); - mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); - mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); - mStarsMaterials[i] = mp; + Entity* night1_ent = mSceneMgr->createEntity(meshes[i].first->getName()); + night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); + night1_ent->setVisibilityFlags(RV_Sky); + night1_ent->setCastShadows(false); + + mAtmosphereNight->attachObject(night1_ent); + + for (unsigned int i=0; igetNumSubEntities(); ++i) + { + MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); + mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); + mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); + mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); + mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); + mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); + mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); + mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); + mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); + mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); + mStarsMaterials.push_back(mp); + } } // Atmosphere (day) - mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); - Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif"); - atmosphere_ent->setCastShadows(false); - - ModVertexAlpha(atmosphere_ent, 0); - - atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly); - atmosphere_ent->setVisibilityFlags(RV_Sky); - mAtmosphereDay = mRootNode->createChildSceneNode(); - mAtmosphereDay->attachObject(atmosphere_ent); - mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); - // Atmosphere shader HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); @@ -555,22 +545,21 @@ void SkyManager::create() StringUtil::StrStreamType outStream; outStream << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float4 color : COLOR, \n" - " out float4 oPosition : POSITION, \n" - " out float4 oVertexColor : TEXCOORD0, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" - " oPosition = mul( worldViewProj, position ); \n" + "void main_vp( \n" + " float4 position : POSITION, \n" + " in float4 color : COLOR, \n" + " out float4 oPosition : POSITION, \n" + " out float4 oVertexColor : TEXCOORD0, \n" + " uniform float4x4 worldViewProj \n" + ") \n" + "{ \n" + " oPosition = mul( worldViewProj, position ); \n" " oVertexColor = color; \n" "}"; vshader->setSource(outStream.str()); vshader->load(); vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); HighLevelGpuProgramPtr fshader = mgr.createProgram("Atmosphere_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); @@ -580,15 +569,15 @@ void SkyManager::create() StringUtil::StrStreamType _outStream; _outStream << - "void main_fp( \n" - " in float4 iVertexColor : TEXCOORD0, \n" - " out float4 oColor : COLOR, \n"; + "void main_fp( \n" + " in float4 iVertexColor : TEXCOORD0, \n" + " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) _outStream << " out float4 oColor1 : COLOR1, \n"; _outStream << " uniform float4 emissive \n" - ") \n" - "{ \n" + ") \n" + "{ \n" " oColor = iVertexColor * emissive; \n"; if (RenderingManager::useMRT()) _outStream << " oColor1 = float4(1, 0, 0, 1); \n"; @@ -598,19 +587,36 @@ void SkyManager::create() fshader->load(); fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); + + mAtmosphereDay = mRootNode->createChildSceneNode(); + meshes = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); + for(size_t i = 0;i < meshes.size();i++) + { + Entity* atmosphere_ent = mSceneMgr->createEntity(meshes[i].first->getName()); + atmosphere_ent->setCastShadows(false); + + ModVertexAlpha(atmosphere_ent, 0); + + atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly); + atmosphere_ent->setVisibilityFlags(RV_Sky); + mAtmosphereDay->attachObject(atmosphere_ent); + + mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); + mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere"); + atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial); + + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); + + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); + mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); + } // Clouds - NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); - Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif"); - clouds_ent->setVisibilityFlags(RV_Sky); - clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); - SceneNode* clouds_node = mRootNode->createChildSceneNode(); - clouds_node->attachObject(clouds_ent); - mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); - mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); - clouds_ent->setCastShadows(false); - // Clouds vertex shader HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); @@ -618,24 +624,23 @@ void SkyManager::create() vshader2->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream3; outStream3 << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float4 color : COLOR, \n" + "void main_vp( \n" + " float4 position : POSITION, \n" + " in float4 color : COLOR, \n" " out float4 oColor : TEXCOORD1, \n" " in float2 uv : TEXCOORD0, \n" " out float2 oUV : TEXCOORD0, \n" - " out float4 oPosition : POSITION, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" + " out float4 oPosition : POSITION, \n" + " uniform float4x4 worldViewProj \n" + ") \n" + "{ \n" " oUV = uv; \n" " oColor = color; \n" - " oPosition = mul( worldViewProj, position ); \n" + " oPosition = mul( worldViewProj, position ); \n" "}"; vshader2->setSource(outStream3.str()); vshader2->load(); vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName()); // Clouds fragment shader mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, @@ -644,10 +649,10 @@ void SkyManager::create() mCloudFragmentShader->setParameter("entry_point", "main_fp"); StringUtil::StrStreamType outStream2; outStream2 << - "void main_fp( \n" + "void main_fp( \n" " in float2 uv : TEXCOORD0, \n" " in float4 color : TEXCOORD1, \n" - " out float4 oColor : COLOR, \n"; + " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) outStream2 << " out float4 oColor1 : COLOR1, \n"; outStream2 << @@ -658,8 +663,8 @@ void SkyManager::create() " uniform float speed, \n" " uniform float opacity, \n" " uniform float4 emissive \n" - ") \n" - "{ \n" + ") \n" + "{ \n" " uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction " float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n" " oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"; @@ -670,31 +675,36 @@ void SkyManager::create() mCloudFragmentShader->setSource(outStream2.str()); mCloudFragmentShader->load(); mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName()); + + SceneNode* clouds_node = mRootNode->createChildSceneNode(); + meshes = NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); + for(size_t i = 0;i < meshes.size();i++) + { + Entity* clouds_ent = mSceneMgr->createEntity(meshes[i].first->getName()); + clouds_ent->setVisibilityFlags(RV_Sky); + clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); + clouds_node->attachObject(clouds_ent); + + mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); + mCloudMaterial = mCloudMaterial->clone("Clouds"); + clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial); + + mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); + clouds_ent->setCastShadows(false); + + mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName()); + mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName()); + ModVertexAlpha(clouds_ent, 1); + + mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); + mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); + mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); + mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates(); + mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds"); + mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(""); + } setCloudsOpacity(0.75); - ModVertexAlpha(clouds_ent, 1); - - // I'm not sure if the materials are being used by any other objects - // Make a unique "modifiable" copy of the materials to be sure - mCloudMaterial = mCloudMaterial->clone("Clouds"); - clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial); - mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere"); - atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial); - - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); - mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - - mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates(); - mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds"); - mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(""); - mCreated = true; } @@ -851,7 +861,7 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) else { mAtmosphereNight->setVisible(true); - for (int i=0; i<7; ++i) + for (size_t i=0; igetTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade); mStarsOpacity = weather.mNightFade; } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index e11745e82..7b7cc2d16 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -1,13 +1,14 @@ #ifndef _GAME_RENDER_SKY_H #define _GAME_RENDER_SKY_H +#include + #include #include #include #include #include -#include "sky.hpp" #include "../mwworld/weather.hpp" namespace Ogre @@ -195,7 +196,7 @@ namespace MWRender Ogre::MaterialPtr mCloudMaterial; Ogre::MaterialPtr mAtmosphereMaterial; - Ogre::MaterialPtr mStarsMaterials[7]; + std::vector mStarsMaterials; Ogre::HighLevelGpuProgramPtr mCloudFragmentShader; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index efe9ddea6..a479e78a5 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -322,12 +322,16 @@ void NIFLoader::createMaterial(const Ogre::String &name, void NIFLoader::loadResource(Ogre::Resource *resource) { - warn("Found no records in NIF."); + warn("Found no records in NIF for "+resource->getName()); } -Ogre::MeshPtr NIFLoader::load(const std::string &name, const std::string &group) +MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, const std::string &group) { Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); + MeshPairList ret; + + if(skel != NULL) + skel->setNull(); // Check if the resource already exists Ogre::MeshPtr themesh = meshMgr.getByName(name, group); @@ -336,7 +340,9 @@ Ogre::MeshPtr NIFLoader::load(const std::string &name, const std::string &group) NIFLoader *loader = &sLoaders[name]; themesh = meshMgr.createManual(name, group, loader); } - return themesh; + ret.push_back(std::make_pair(themesh, std::string())); + + return ret; } diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 985c64e0d..1eef7eb37 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -67,6 +68,12 @@ namespace Nif namespace NifOgre { + +/** This holds a list of meshes along with the names of their parent nodes + */ +typedef std::vector< std::pair > MeshPairList; + + /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into something Ogre can use. @@ -75,19 +82,18 @@ namespace NifOgre NIFLoader::load("somemesh.nif"); - Afterwards, you can use the mesh name "somemesh.nif" normally to - create entities and so on. The mesh isn't loaded from disk until - OGRE needs it for rendering. Thus the above load() command is not - very resource intensive, and can safely be done for a large number - of meshes at load time. + This returns a list of meshes used by the model, as well as the names of + their parent nodes (as they pertain to the skeleton, which is optionally + returned in the second argument if it exists). */ class NIFLoader : Ogre::ManualResourceLoader { public: virtual void loadResource(Ogre::Resource *resource); - static Ogre::MeshPtr load(const std::string &name, - const std::string &group="General"); + static MeshPairList load(const std::string &name, + Ogre::SkeletonPtr *skel=NULL, + const std::string &group="General"); private: void warn(const std::string &msg); From 5a381006e52e6815f4f86f8eeec09f6c1e8c15eb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 14 Jul 2012 09:20:09 -0700 Subject: [PATCH 016/126] Fix parsing of some key lists It seems some still want you to read the interpolation type even when there's no keys. --- components/nif/data.hpp | 4 ++-- components/nif/nif_file.hpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index d08ba7b32..63df23b27 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -394,9 +394,9 @@ struct NiMorphData : public Record nif->getChar(); mMorphs.resize(morphCount); - for(int i=0; igetInt(); - if(count == 0) return; + if(count == 0 && !force) + return; mInterpolationType = nif->getInt(); mKeys.resize(count); From 6a447c88fb8349e17846dde2ef0d83c2fe24be58 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 06:45:21 -0700 Subject: [PATCH 017/126] Create meshes from the NiTriShapes in the NIF. This doesn't actually load them yet. It's also very slow for certain NIFs. --- components/nifogre/ogre_nif_loader.cpp | 72 ++++++++++++++++++++++---- components/nifogre/ogre_nif_loader.hpp | 9 +++- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index a479e78a5..40740ac56 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -132,13 +132,13 @@ NIFLoader::LoaderMap NIFLoader::sLoaders; void NIFLoader::warn(const std::string &msg) { - std::cerr << "NIFLoader: Warn:" << msg << "\n"; + std::cerr << "NIFLoader: Warn: " << msg << std::endl; } void NIFLoader::fail(const std::string &msg) { std::cerr << "NIFLoader: Fail: "<< msg << std::endl; - assert(1); + abort(); } @@ -325,24 +325,74 @@ void NIFLoader::loadResource(Ogre::Resource *resource) warn("Found no records in NIF for "+resource->getName()); } +void NIFLoader::createMeshes(const std::string &name, const std::string &group, Nif::Node *node, MeshPairList &meshes, int flags) +{ + flags |= node->flags; + + // TODO: Check for extra data + + if(node->recType == Nif::RC_NiTriShape) + { + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); + std::string fullname = name+"@"+node->name; + + Ogre::MeshPtr mesh = meshMgr.getByName(fullname); + if(mesh.isNull()) + { + NIFLoader *loader = &sLoaders[fullname]; + loader->mName = name; + loader->mShapeName = node->name; + + mesh = meshMgr.createManual(fullname, group, loader); + } + + meshes.push_back(std::make_pair(mesh, (node->parent ? node->parent->name : std::string()))); + } + else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode && + node->recType != Nif::RC_NiRotatingParticles) + warn("Unhandled mesh node type: "+node->recName); + + Nif::NiNode *ninode = dynamic_cast(node); + if(ninode) + { + Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + createMeshes(name, group, children[i].getPtr(), meshes, flags); + } + } +} + MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, const std::string &group) { - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - MeshPairList ret; + MeshPairList meshes; if(skel != NULL) skel->setNull(); - // Check if the resource already exists - Ogre::MeshPtr themesh = meshMgr.getByName(name, group); - if(themesh.isNull()) + Nif::NIFFile nif(name); + if (nif.numRecords() < 1) { - NIFLoader *loader = &sLoaders[name]; - themesh = meshMgr.createManual(name, group, loader); + nif.warn("Found no records in NIF."); + return meshes; } - ret.push_back(std::make_pair(themesh, std::string())); - return ret; + // The first record is assumed to be the root node + Nif::Record *r = nif.getRecord(0); + assert(r != NULL); + + Nif::Node *node = dynamic_cast(r); + if(node == NULL) + { + nif.warn("First record in file was not a node, but a "+ + r->recName+". Skipping file."); + return meshes; + } + + createMeshes(name, group, node, meshes); + + return meshes; } diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 1eef7eb37..092cc23a8 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -96,8 +96,13 @@ public: const std::string &group="General"); private: - void warn(const std::string &msg); - void fail(const std::string &msg); + std::string mName; + std::string mShapeName; + + static void warn(const std::string &msg); + static void fail(const std::string &msg); + + static void createMeshes(const std::string &name, const std::string &group, Nif::Node *node, MeshPairList &meshes, int flags=0); typedef std::map LoaderMap; static LoaderMap sLoaders; From 300730a834d49b25f52d7002b737062070e88b93 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 11:11:49 -0700 Subject: [PATCH 018/126] Create the skeleton resource from NIFs Note they are not loaded yet. --- components/nifogre/ogre_nif_loader.cpp | 64 ++++++++++++++++++++++++-- components/nifogre/ogre_nif_loader.hpp | 4 +- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 40740ac56..99ccb7fb1 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -128,6 +128,60 @@ public: }; +struct NIFSkeletonLoader : public Ogre::ManualResourceLoader { + +static void warn(const std::string &msg) +{ + std::cerr << "NIFSkeletonLoader: Warn: " << msg << std::endl; +} + +static void fail(const std::string &msg) +{ + std::cerr << "NIFSkeletonLoader: Fail: "<< msg << std::endl; + abort(); +} + +void loadResource(Ogre::Resource *resource) +{ + warn("Found no records in NIF for "+resource->getName()); +} + +static bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node, Ogre::SkeletonPtr *skel) +{ + if(node->boneTrafo != NULL) + { + Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); + + Ogre::SkeletonPtr tmp = skelMgr.getByName(name); + if(tmp.isNull()) + { + static NIFSkeletonLoader loader; + tmp = skelMgr.create(name, group, true, &loader); + } + + if(skel) *skel = tmp; + return true; + } + + Nif::NiNode *ninode = dynamic_cast(node); + if(ninode) + { + Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + { + if(createSkeleton(name, group, children[i].getPtr(), skel)) + return true; + } + } + } + return false; +} + +}; + + NIFLoader::LoaderMap NIFLoader::sLoaders; void NIFLoader::warn(const std::string &msg) @@ -325,7 +379,8 @@ void NIFLoader::loadResource(Ogre::Resource *resource) warn("Found no records in NIF for "+resource->getName()); } -void NIFLoader::createMeshes(const std::string &name, const std::string &group, Nif::Node *node, MeshPairList &meshes, int flags) + +void NIFLoader::createMeshes(const std::string &name, const std::string &group, bool hasSkel, Nif::Node *node, MeshPairList &meshes, int flags) { flags |= node->flags; @@ -342,6 +397,7 @@ void NIFLoader::createMeshes(const std::string &name, const std::string &group, NIFLoader *loader = &sLoaders[fullname]; loader->mName = name; loader->mShapeName = node->name; + loader->mHasSkel = hasSkel; mesh = meshMgr.createManual(fullname, group, loader); } @@ -359,11 +415,12 @@ void NIFLoader::createMeshes(const std::string &name, const std::string &group, for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - createMeshes(name, group, children[i].getPtr(), meshes, flags); + createMeshes(name, group, hasSkel, children[i].getPtr(), meshes, flags); } } } + MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, const std::string &group) { MeshPairList meshes; @@ -390,7 +447,8 @@ MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, c return meshes; } - createMeshes(name, group, node, meshes); + bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node, skel); + createMeshes(name, group, hasSkel, node, meshes); return meshes; } diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 092cc23a8..c90d65395 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -98,11 +98,13 @@ public: private: std::string mName; std::string mShapeName; + bool mHasSkel; static void warn(const std::string &msg); static void fail(const std::string &msg); - static void createMeshes(const std::string &name, const std::string &group, Nif::Node *node, MeshPairList &meshes, int flags=0); + static void createMeshes(const std::string &name, const std::string &group, bool hasSkel, + Nif::Node *node, MeshPairList &meshes, int flags=0); typedef std::map LoaderMap; static LoaderMap sLoaders; From 69ed73399ab367c445372d6a1610785e3e122502 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 11:37:36 -0700 Subject: [PATCH 019/126] Avoid exposing the NIF mesh resource loading class --- components/nifogre/ogre_nif_loader.cpp | 120 ++++++++++++++----------- components/nifogre/ogre_nif_loader.hpp | 18 +--- 2 files changed, 70 insertions(+), 68 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 99ccb7fb1..079e6425b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -182,20 +182,6 @@ static bool createSkeleton(const std::string &name, const std::string &group, Ni }; -NIFLoader::LoaderMap NIFLoader::sLoaders; - -void NIFLoader::warn(const std::string &msg) -{ - std::cerr << "NIFLoader: Warn: " << msg << std::endl; -} - -void NIFLoader::fail(const std::string &msg) -{ - std::cerr << "NIFLoader: Fail: "<< msg << std::endl; - abort(); -} - - // Conversion of blend / test mode from NIF -> OGRE. // Not in use yet, so let's comment it out. /* @@ -374,51 +360,81 @@ void NIFLoader::createMaterial(const Ogre::String &name, #endif -void NIFLoader::loadResource(Ogre::Resource *resource) +class NIFMeshLoader : Ogre::ManualResourceLoader { - warn("Found no records in NIF for "+resource->getName()); -} + std::string mName; + std::string mGroup; + std::string mShapeName; + bool mHasSkel; - -void NIFLoader::createMeshes(const std::string &name, const std::string &group, bool hasSkel, Nif::Node *node, MeshPairList &meshes, int flags) -{ - flags |= node->flags; - - // TODO: Check for extra data - - if(node->recType == Nif::RC_NiTriShape) + void warn(const std::string &msg) { - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - std::string fullname = name+"@"+node->name; - - Ogre::MeshPtr mesh = meshMgr.getByName(fullname); - if(mesh.isNull()) - { - NIFLoader *loader = &sLoaders[fullname]; - loader->mName = name; - loader->mShapeName = node->name; - loader->mHasSkel = hasSkel; - - mesh = meshMgr.createManual(fullname, group, loader); - } - - meshes.push_back(std::make_pair(mesh, (node->parent ? node->parent->name : std::string()))); + std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; } - else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode && - node->recType != Nif::RC_NiRotatingParticles) - warn("Unhandled mesh node type: "+node->recName); - Nif::NiNode *ninode = dynamic_cast(node); - if(ninode) + void fail(const std::string &msg) { - Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) + std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; + abort(); + } + + + typedef std::map LoaderMap; + static LoaderMap sLoaders; + +public: + NIFMeshLoader() + : mHasSkel(false) + { } + NIFMeshLoader(const std::string &name, const std::string &group, bool hasSkel) + : mName(name), mGroup(group), mHasSkel(hasSkel) + { } + + virtual void loadResource(Ogre::Resource *resource) + { + warn("Found no records in NIF for "+resource->getName()); + } + + void createMeshes(Nif::Node *node, MeshPairList &meshes, int flags=0) + { + flags |= node->flags; + + // TODO: Check for extra data + + if(node->recType == Nif::RC_NiTriShape) { - if(!children[i].empty()) - createMeshes(name, group, hasSkel, children[i].getPtr(), meshes, flags); + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); + std::string fullname = mName+"@"+node->name; + + Ogre::MeshPtr mesh = meshMgr.getByName(fullname); + if(mesh.isNull()) + { + NIFMeshLoader *loader = &sLoaders[fullname]; + *loader = *this; + loader->mShapeName = node->name; + + mesh = meshMgr.createManual(fullname, mGroup, loader); + } + + meshes.push_back(std::make_pair(mesh, (node->parent ? node->parent->name : std::string()))); + } + else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode && + node->recType != Nif::RC_NiRotatingParticles) + warn("Unhandled mesh node type: "+node->recName); + + Nif::NiNode *ninode = dynamic_cast(node); + if(ninode) + { + Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + createMeshes(children[i].getPtr(), meshes, flags); + } } } -} +}; +NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, const std::string &group) @@ -448,7 +464,9 @@ MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, c } bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node, skel); - createMeshes(name, group, hasSkel, node, meshes); + + NIFMeshLoader meshldr(name, group, hasSkel); + meshldr.createMeshes(node, meshes); return meshes; } diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index c90d65395..431af1163 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -86,28 +86,12 @@ typedef std::vector< std::pair > MeshPairList; their parent nodes (as they pertain to the skeleton, which is optionally returned in the second argument if it exists). */ -class NIFLoader : Ogre::ManualResourceLoader +class NIFLoader { public: - virtual void loadResource(Ogre::Resource *resource); - static MeshPairList load(const std::string &name, Ogre::SkeletonPtr *skel=NULL, const std::string &group="General"); - -private: - std::string mName; - std::string mShapeName; - bool mHasSkel; - - static void warn(const std::string &msg); - static void fail(const std::string &msg); - - static void createMeshes(const std::string &name, const std::string &group, bool hasSkel, - Nif::Node *node, MeshPairList &meshes, int flags=0); - - typedef std::map LoaderMap; - static LoaderMap sLoaders; }; } From 9028cfe83c707a95c0c1e9a8582eb05936d931d8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 12:02:47 -0700 Subject: [PATCH 020/126] Look for the NiTriShape when the mesh resource wants to load It's still not loaded yet. --- components/nifogre/ogre_nif_loader.cpp | 32 +++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 079e6425b..6896ac8fb 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -379,6 +379,31 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } + bool findTriShape(Ogre::Mesh *mesh, Nif::Node *node) + { + if(node->recType == Nif::RC_NiTriShape && mShapeName == node->name) + { + warn("Not loading shape \""+mShapeName+"\" in "+mName); + return true; + } + + Nif::NiNode *ninode = dynamic_cast(node); + if(ninode) + { + Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + { + if(findTriShape(mesh, children[i].getPtr())) + return true; + } + } + } + return false; + } + + typedef std::map LoaderMap; static LoaderMap sLoaders; @@ -392,7 +417,12 @@ public: virtual void loadResource(Ogre::Resource *resource) { - warn("Found no records in NIF for "+resource->getName()); + Ogre::Mesh *mesh = dynamic_cast(resource); + assert(mesh && "Attempting to load a mesh into a non-mesh resource!"); + + Nif::NIFFile nif(mName); + Nif::Node *node = dynamic_cast(nif.getRecord(0)); + findTriShape(mesh, node); } void createMeshes(Nif::Node *node, MeshPairList &meshes, int flags=0) From 3029c221efb8cc6070196eef806712e8e538c388 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 12:59:39 -0700 Subject: [PATCH 021/126] Create materials when creating meshes --- components/nifogre/ogre_nif_loader.cpp | 148 ++++++++++++++++++++++--- 1 file changed, 131 insertions(+), 17 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 6896ac8fb..b0e92d82f 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -226,26 +226,131 @@ static CompareFunction getTestMode(int mode) } */ -#if 0 -void NIFLoader::createMaterial(const Ogre::String &name, - const Ogre::Vector3 &ambient, - const Ogre::Vector3 &diffuse, - const Ogre::Vector3 &specular, - const Ogre::Vector3 &emissive, - float glossiness, float alpha, - int alphaFlags, float alphaTest, - const Ogre::String &texName) -{ - Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(name, resourceGroup); +class NIFMaterialLoader { + +static std::multimap MaterialMap; + +static void warn(const std::string &msg) +{ + std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; +} + +static void fail(const std::string &msg) +{ + std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; + abort(); +} + +public: +static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &name, const Ogre::String &group) +{ + Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); + Ogre::MaterialPtr material = matMgr.getByName(name); + if(!material.isNull()) + return name; + + Ogre::Vector3 ambient(1.0f); + Ogre::Vector3 diffuse(1.0f); + Ogre::Vector3 specular(0.0f); + Ogre::Vector3 emissive(0.0f); + float glossiness = 0.0f; + float alpha = 1.0f; + int alphaFlags = -1; + ubyte alphaTest = 0; + Ogre::String texName; + + // These are set below if present + const NiTexturingProperty *t = NULL; + const NiMaterialProperty *m = NULL; + const NiAlphaProperty *a = NULL; + + // Scan the property list for material information + const PropertyList &list = shape->props; + for (size_t i = 0;i < list.length();i++) + { + // Entries may be empty + if (list[i].empty()) continue; + + const Property *pr = list[i].getPtr(); + if (pr->recType == RC_NiTexturingProperty) + t = static_cast(pr); + else if (pr->recType == RC_NiMaterialProperty) + m = static_cast(pr); + else if (pr->recType == RC_NiAlphaProperty) + a = static_cast(pr); + else + warn("Skipped property type: "+pr->recName); + } + + // Texture + if (t && t->textures[0].inUse) + { + NiSourceTexture *st = t->textures[0].texture.getPtr(); + if (st->external) + { + /* Bethesda at some at some point converted all their BSA + * textures from tga to dds for increased load speed, but all + * texture file name references were kept as .tga. + */ + texName = "textures\\" + st->filename; + if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName)) + { + Ogre::String::size_type pos = texName.rfind('.'); + texName.replace(pos, texName.length(), ".dds"); + } + } + else warn("Found internal texture, ignoring."); + } + + // Alpha modifiers + if (a) + { + alphaFlags = a->flags; + alphaTest = a->data.threshold; + } + + // Material + if(m) + { + ambient = m->data.ambient; + diffuse = m->data.diffuse; + specular = m->data.specular; + emissive = m->data.emissive; + glossiness = m->data.glossiness; + alpha = m->data.alpha; + } + + Ogre::String matname = name; + if (m || !texName.empty()) + { + // If we're here, then this mesh has a material. Thus we + // need to calculate a snappy material name. It should + // contain the mesh name (mesh->getName()) but also has to + // be unique. One mesh may use many materials. + std::multimap::iterator itr = MaterialMap.find(texName); + std::multimap::iterator lastElement; + lastElement = MaterialMap.upper_bound(texName); + if (itr != MaterialMap.end()) + { + for ( ; itr != lastElement; ++itr) + { + //std::cout << "OK!"; + //MaterialPtr mat = MaterialManager::getSingleton().getByName(itr->second,recourceGroup); + return itr->second; + //if( mat->getA + } + } + } + + // No existing material like this. Create a new one. + material = matMgr.create(matname, group, true); // This assigns the texture to this material. If the texture name is // a file name, and this file exists (in a resource directory), it // will automatically be loaded when needed. If not (such as for // internal NIF textures that we might support later), we should // already have inserted a manual loader for the texture. - - if (!texName.empty()) { Ogre::Pass *pass = material->getTechnique(0)->getPass(0); @@ -356,8 +461,13 @@ void NIFLoader::createMaterial(const Ogre::String &name, material->setSpecular(specular[0], specular[1], specular[2], alpha); material->setSelfIllumination(emissive[0], emissive[1], emissive[2]); material->setShininess(glossiness); + + MaterialMap.insert(std::make_pair(texName, matname)); + return matname; } -#endif + +}; +std::multimap NIFMaterialLoader::MaterialMap; class NIFMeshLoader : Ogre::ManualResourceLoader @@ -365,6 +475,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::string mName; std::string mGroup; std::string mShapeName; + std::string mMaterialName; bool mHasSkel; void warn(const std::string &msg) @@ -433,20 +544,23 @@ public: if(node->recType == Nif::RC_NiTriShape) { + NiTriShape *shape = dynamic_cast(node); + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - std::string fullname = mName+"@"+node->name; + std::string fullname = mName+"@"+shape->name; Ogre::MeshPtr mesh = meshMgr.getByName(fullname); if(mesh.isNull()) { NIFMeshLoader *loader = &sLoaders[fullname]; *loader = *this; - loader->mShapeName = node->name; + loader->mShapeName = shape->name; + loader->mMaterialName = NIFMaterialLoader::getMaterial(shape, fullname, mGroup); mesh = meshMgr.createManual(fullname, mGroup, loader); } - meshes.push_back(std::make_pair(mesh, (node->parent ? node->parent->name : std::string()))); + meshes.push_back(std::make_pair(mesh, (shape->parent ? shape->parent->name : std::string()))); } else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode && node->recType != Nif::RC_NiRotatingParticles) From 441a5c2da20f595da6fd5d8ad0b98c2f6c4b9f07 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 14:12:12 -0700 Subject: [PATCH 022/126] Load NiTriShapes into Ogre meshes --- components/nifogre/ogre_nif_loader.cpp | 173 ++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index b0e92d82f..884d8f64e 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -490,11 +490,182 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } + // Convert NiTriShape to Ogre::SubMesh + void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape *shape) + { + const Nif::NiTriShapeData *data = shape->data.getPtr(); + const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); + std::vector srcVerts = data->vertices; + std::vector srcNorms = data->normals; + if(skin != NULL) + { +#if 0 + // Convert vertices and normals back to bone space + std::vector newVerts(srcVerts.size(), Vector3(0,0,0)); + std::vector newNorms(srcNorms.size(), Vector3(0,0,0)); + + NiSkinDataRef data = skin->GetSkinData(); + const std::vector &bones = skin->GetBones(); + for(size_t b = 0;b < bones.size();b++) + { + Matrix44 mat = data->GetBoneTransform(b) * bones[b]->GetWorldTransform(); + + const std::vector &weights = data->GetBoneWeights(b); + for(size_t i = 0;i < weights.size();i++) + { + size_t index = weights[i].index; + float weight = weights[i].weight; + + newVerts.at(index) += (mat*srcVerts[index]) * weight; + if(newNorms.size() > index) + { + for(size_t j = 0;j < 3;j++) + { + newNorms[index][j] += mat[0][j]*srcNorms[index][0] * weight; + newNorms[index][j] += mat[1][j]*srcNorms[index][1] * weight; + newNorms[index][j] += mat[2][j]*srcNorms[index][2] * weight; + } + } + } + } + + srcVerts = newVerts; + srcNorms = newNorms; +#endif + } + + // Set the bounding box first + BoundsFinder bounds; + bounds.add(&srcVerts[0][0], srcVerts.size()); + mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(), + bounds.maxX(), bounds.maxY(), bounds.maxZ())); + mesh->_setBoundingSphereRadius(bounds.getRadius()); + + // This function is just one long stream of Ogre-barf, but it works + // great. + Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr(); + Ogre::HardwareVertexBufferSharedPtr vbuf; + Ogre::HardwareIndexBufferSharedPtr ibuf; + Ogre::VertexBufferBinding *bind; + Ogre::VertexDeclaration *decl; + int nextBuf = 0; + + Ogre::SubMesh *sub = mesh->createSubMesh(shape->name); + + // Add vertices + sub->useSharedVertices = false; + sub->vertexData = new Ogre::VertexData(); + sub->vertexData->vertexStart = 0; + sub->vertexData->vertexCount = srcVerts.size(); + + decl = sub->vertexData->vertexDeclaration; + bind = sub->vertexData->vertexBufferBinding; + if(srcVerts.size()) + { + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), + srcVerts.size(), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, + true); + vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true); + + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + bind->setBinding(nextBuf++, vbuf); + } + + // Vertex normals + if(srcNorms.size()) + { + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), + srcNorms.size(), Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, + true); + vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true); + + decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); + bind->setBinding(nextBuf++, vbuf); + } + + // Vertex colors + const std::vector &colors = data->colors; + if(colors.size()) + { + Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); + std::vector colorsRGB(colors.size()); + for(size_t i = 0;i < colorsRGB.size();i++) + { + Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]); + rs->convertColourValue(clr, &colorsRGB[i]); + } + vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), + colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, + true); + vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true); + decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); + bind->setBinding(nextBuf++, vbuf); + } + + // Texture UV coordinates + size_t numUVs = data->uvlist.size(); + if(numUVs) + { + size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); + vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size()*numUVs, + Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); + for(size_t i = 0;i < numUVs;i++) + { + const std::vector &uvlist = data->uvlist[i]; + vbuf->writeData(i*srcVerts.size()*elemSize, elemSize*srcVerts.size(), &uvlist[0], true); + decl->addElement(nextBuf, i*srcVerts.size()*elemSize, Ogre::VET_FLOAT2, + Ogre::VES_TEXTURE_COORDINATES, i); + } + bind->setBinding(nextBuf++, vbuf); + } + + // Triangle faces + const std::vector &srcIdx = data->triangles; + if(srcIdx.size()) + { + ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(), + Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); + ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true); + sub->indexData->indexBuffer = ibuf; + sub->indexData->indexCount = srcIdx.size(); + sub->indexData->indexStart = 0; + } + + // Assign bone weights for this TriShape +#if 0 + if(skin != NULL) + { + // Get the skeleton resource, so weights can be applied + Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); + Ogre::SkeletonPtr skel = skelMgr->getByName(mesh->getSkeletonName()); + + NiSkinDataRef data = skin->GetSkinData(); + const std::vector &bones = skin->GetBones(); + for(size_t i = 0;i < bones.size();i++) + { + Ogre::VertexBoneAssignment boneInf; + boneInf.boneIndex = skel->getBone(bones[i]->GetName())->getHandle(); + + const std::vector &weights = data->GetBoneWeights(i); + for(size_t j = 0;j < weights.size();j++) + { + boneInf.vertexIndex = weights[j].index; + boneInf.weight = weights[j].weight; + sub->addBoneAssignment(boneInf); + } + } + } +#endif + + if(mMaterialName.length() > 0) + sub->setMaterialName(mMaterialName); + } + bool findTriShape(Ogre::Mesh *mesh, Nif::Node *node) { if(node->recType == Nif::RC_NiTriShape && mShapeName == node->name) { - warn("Not loading shape \""+mShapeName+"\" in "+mName); + handleNiTriShape(mesh, dynamic_cast(node)); return true; } From 61f32eca77bcf93e25d609987cddb72cc2bbc0f8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 15:23:49 -0700 Subject: [PATCH 023/126] Add methods to get a node's local and full transform as a 4x4 matrix --- components/nif/nif_file.cpp | 14 ++++++++++++++ components/nif/node.hpp | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 231349302..789bae5e3 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -210,3 +210,17 @@ void NiSkinInstance::post(NIFFile *nif) bones[i]->makeBone(i, data->bones[i]); } } + +Ogre::Matrix4 Node::getLocalTransform() +{ + Ogre::Matrix4 mat4; + mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation)); + return mat4; +} + +Ogre::Matrix4 Node::getWorldTransform() +{ + if(parent != NULL) + return getLocalTransform() * parent->getWorldTransform(); + return getLocalTransform(); +} diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 1f1b91a46..f7d3c6e96 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -24,6 +24,8 @@ #ifndef _NIF_NODE_H_ #define _NIF_NODE_H_ +#include + #include "controlled.hpp" #include "data.hpp" #include "property.hpp" @@ -108,6 +110,9 @@ public: boneTrafo = &bi.trafo; boneIndex = ind; } + + Ogre::Matrix4 getLocalTransform(); + Ogre::Matrix4 getWorldTransform(); }; struct NiNode : Node From b1f7fd9f7b39b9728839b84693ab8617be739fd5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 17:00:27 -0700 Subject: [PATCH 024/126] Pre-transform the mesh vertices when there's no skinning or skeleton --- components/nif/nif_file.cpp | 2 +- components/nifogre/ogre_nif_loader.cpp | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 789bae5e3..308196f32 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -213,7 +213,7 @@ void NiSkinInstance::post(NIFFile *nif) Ogre::Matrix4 Node::getLocalTransform() { - Ogre::Matrix4 mat4; + Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY); mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation)); return mat4; } diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 884d8f64e..01551a702 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -533,12 +533,33 @@ class NIFMeshLoader : Ogre::ManualResourceLoader srcNorms = newNorms; #endif } + else if(!mHasSkel) + { + // No skinning and no skeleton, so just transform the vertices and + // normals into position. + Ogre::Matrix4 mat4 = shape->getWorldTransform(); + for(size_t i = 0;i < srcVerts.size();i++) + { + Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f); + vec4 = mat4*vec4; + srcVerts[i] = Ogre::Vector3(&vec4[0]); + } + for(size_t i = 0;i < srcNorms.size();i++) + { + Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f); + vec4 = mat4*vec4; + srcNorms[i] = Ogre::Vector3(&vec4[0]); + } + } // Set the bounding box first BoundsFinder bounds; bounds.add(&srcVerts[0][0], srcVerts.size()); - mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(), - bounds.maxX(), bounds.maxY(), bounds.maxZ())); + // No idea why this offset is needed. It works fine without it if the + // vertices weren't transformed first, but otherwise it fails later on + // when the object is being inserted into the scene. + mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f, + bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f)); mesh->_setBoundingSphereRadius(bounds.getRadius()); // This function is just one long stream of Ogre-barf, but it works From ad75b47472dbf3856120fe2ee8b65d352395b34c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Jul 2012 19:07:31 -0700 Subject: [PATCH 025/126] Build and set up a skeleton for meshes --- components/nifogre/ogre_nif_loader.cpp | 72 +++++++++++++++++++------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 01551a702..1db0b92a5 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -141,9 +141,35 @@ static void fail(const std::string &msg) abort(); } + +void buildBones(Ogre::Skeleton *skel, Nif::NiNode *node, Ogre::Bone *parent=NULL) +{ + Ogre::Bone *bone = skel->createBone(node->name); + if(parent) parent->addChild(bone); + + bone->setOrientation(node->trafo.rotation); + bone->setPosition(node->trafo.pos); + bone->setScale(Ogre::Vector3(node->trafo.scale)); + bone->setBindingPose(); + bone->setInitialState(); + + const Nif::NodeList &children = node->children; + for(size_t i = 0;i < children.length();i++) + { + Nif::NiNode *next; + if(!children[i].empty() && (next=dynamic_cast(children[i].getPtr()))) + buildBones(skel, next, bone); + } +} + void loadResource(Ogre::Resource *resource) { - warn("Found no records in NIF for "+resource->getName()); + Ogre::Skeleton *skel = dynamic_cast(resource); + OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); + + Nif::NIFFile nif(skel->getName()); + Nif::NiNode *node = dynamic_cast(nif.getRecord(0)); + buildBones(skel, node); } static bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node, Ogre::SkeletonPtr *skel) @@ -499,21 +525,29 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::vector srcNorms = data->normals; if(skin != NULL) { -#if 0 - // Convert vertices and normals back to bone space - std::vector newVerts(srcVerts.size(), Vector3(0,0,0)); - std::vector newNorms(srcNorms.size(), Vector3(0,0,0)); + // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be + // explicitly attached later. + mesh->setSkeletonName(mName); - NiSkinDataRef data = skin->GetSkinData(); - const std::vector &bones = skin->GetBones(); - for(size_t b = 0;b < bones.size();b++) + // Convert vertices and normals to bone space from bind position. It would be + // better to transform the bones into bind position, but there doesn't seem to + // be a reliable way to do that. + std::vector newVerts(srcVerts.size(), Ogre::Vector3(0.0f)); + std::vector newNorms(srcNorms.size(), Ogre::Vector3(1.0f)); + + const Nif::NiSkinData *data = skin->data.getPtr(); + const Nif::NodeList &bones = skin->bones; + for(size_t b = 0;b < bones.length();b++) { - Matrix44 mat = data->GetBoneTransform(b) * bones[b]->GetWorldTransform(); + Ogre::Matrix4 mat(Ogre::Matrix4::IDENTITY); + mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), + Ogre::Quaternion(data->bones[b].trafo.rotation)); + mat = mat * bones[b]->getWorldTransform(); - const std::vector &weights = data->GetBoneWeights(b); + const std::vector &weights = data->bones[b].weights; for(size_t i = 0;i < weights.size();i++) { - size_t index = weights[i].index; + size_t index = weights[i].vertex; float weight = weights[i].weight; newVerts.at(index) += (mat*srcVerts[index]) * weight; @@ -531,7 +565,6 @@ class NIFMeshLoader : Ogre::ManualResourceLoader srcVerts = newVerts; srcNorms = newNorms; -#endif } else if(!mHasSkel) { @@ -653,30 +686,29 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } // Assign bone weights for this TriShape -#if 0 if(skin != NULL) { // Get the skeleton resource, so weights can be applied Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); Ogre::SkeletonPtr skel = skelMgr->getByName(mesh->getSkeletonName()); + skel->touch(); - NiSkinDataRef data = skin->GetSkinData(); - const std::vector &bones = skin->GetBones(); - for(size_t i = 0;i < bones.size();i++) + const Nif::NiSkinData *data = skin->data.getPtr(); + const Nif::NodeList &bones = skin->bones; + for(size_t i = 0;i < bones.length();i++) { Ogre::VertexBoneAssignment boneInf; - boneInf.boneIndex = skel->getBone(bones[i]->GetName())->getHandle(); + boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle(); - const std::vector &weights = data->GetBoneWeights(i); + const std::vector &weights = data->bones[i].weights; for(size_t j = 0;j < weights.size();j++) { - boneInf.vertexIndex = weights[j].index; + boneInf.vertexIndex = weights[j].vertex; boneInf.weight = weights[j].weight; sub->addBoneAssignment(boneInf); } } } -#endif if(mMaterialName.length() > 0) sub->setMaterialName(mMaterialName); From a539e98274971f9495075b7092a5ba264c3e7994 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 10:48:48 -0700 Subject: [PATCH 026/126] Handle all meshes when inserting objects into the scene --- apps/openmw/mwrender/objects.cpp | 69 ++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index ea58ec716..2ff9de9a4 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -92,12 +92,19 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); - // FIXME: There can be more than one! + Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(mesh); - Ogre::Entity *ent = mRenderer.getScene()->createEntity(meshes[0].first->getName()); + std::vector entities(meshes.size()); + for(size_t i = 0;i < meshes.size();i++) + { + entities[i] = mRenderer.getScene()->createEntity(meshes[i].first->getName()); - - Ogre::Vector3 extents = ent->getBoundingBox().getSize(); + const Ogre::AxisAlignedBox &tmp = entities[i]->getBoundingBox(); + bounds.merge(Ogre::AxisAlignedBox(insert->_getDerivedPosition() + tmp.getMinimum(), + insert->_getDerivedPosition() + tmp.getMaximum()) + ); + } + Ogre::Vector3 extents = bounds.getSize(); extents *= insert->getScale(); float size = std::max(std::max(extents.x, extents.y), extents.z); @@ -109,42 +116,42 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) if (mBounds.find(ptr.getCell()) == mBounds.end()) mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; - - Ogre::AxisAlignedBox bounds = ent->getBoundingBox(); - bounds = Ogre::AxisAlignedBox( - insert->_getDerivedPosition() + bounds.getMinimum(), - insert->_getDerivedPosition() + bounds.getMaximum() - ); - - bounds.scale(insert->getScale()); mBounds[ptr.getCell()].merge(bounds); bool transparent = false; - for (unsigned int i=0; igetNumSubEntities(); ++i) + for(size_t i = 0;i < entities.size();i++) { - Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while (techIt.hasMoreElements()) + Ogre::Entity *ent = entities[i]; + for (unsigned int i=0; igetNumSubEntities(); ++i) { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while (passIt.hasMoreElements()) + Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); + Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); + while (techIt.hasMoreElements()) { - Ogre::Pass* pass = passIt.getNext(); + Ogre::Technique* tech = techIt.getNext(); + Ogre::Technique::PassIterator passIt = tech->getPassIterator(); + while (passIt.hasMoreElements()) + { + Ogre::Pass* pass = passIt.getNext(); - if (pass->getDepthWriteEnabled() == false) - transparent = true; + if (pass->getDepthWriteEnabled() == false) + transparent = true; + } } } } if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) { - insert->attachObject(ent); + for(size_t i = 0;i < entities.size();i++) + { + Ogre::Entity *ent = entities[i]; + insert->attachObject(ent); - ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); - ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); - ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); + ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); + ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + } } else { @@ -184,15 +191,19 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) // - there will be too many batches. sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); - sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); - sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); sg->setCastShadows(true); sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - mRenderer.getScene()->destroyEntity(ent); + for(size_t i = 0;i < entities.size();i++) + { + Ogre::Entity *ent = entities[i]; + sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); + + mRenderer.getScene()->destroyEntity(ent); + } } } From 75ce10c580cdf673586e8122f060b3c7876380d9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 11:31:45 -0700 Subject: [PATCH 027/126] Don't load data for hidden meshes --- components/nifogre/ogre_nif_loader.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 1db0b92a5..044c9cd72 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -755,6 +755,13 @@ public: Ogre::Mesh *mesh = dynamic_cast(resource); assert(mesh && "Attempting to load a mesh into a non-mesh resource!"); + if(!mShapeName.length()) + { + if(mHasSkel) + mesh->setSkeletonName(mName); + return; + } + Nif::NIFFile nif(mName); Nif::Node *node = dynamic_cast(nif.getRecord(0)); findTriShape(mesh, node); @@ -778,8 +785,11 @@ public: { NIFMeshLoader *loader = &sLoaders[fullname]; *loader = *this; - loader->mShapeName = shape->name; - loader->mMaterialName = NIFMaterialLoader::getMaterial(shape, fullname, mGroup); + if(!(flags&0x01)) // Not hidden + { + loader->mShapeName = shape->name; + loader->mMaterialName = NIFMaterialLoader::getMaterial(shape, fullname, mGroup); + } mesh = meshMgr.createManual(fullname, mGroup, loader); } From 12f17858828b6134a8716fb9971bd97d49aa57ae Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 11:43:16 -0700 Subject: [PATCH 028/126] Use default bone names for duplicate names --- components/nifogre/ogre_nif_loader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 044c9cd72..9c0e2e10f 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -144,7 +144,11 @@ static void fail(const std::string &msg) void buildBones(Ogre::Skeleton *skel, Nif::NiNode *node, Ogre::Bone *parent=NULL) { - Ogre::Bone *bone = skel->createBone(node->name); + Ogre::Bone *bone; + if(!skel->hasBone(node->name)) + bone = skel->createBone(node->name); + else + bone = skel->createBone(); if(parent) parent->addChild(bone); bone->setOrientation(node->trafo.rotation); From 63e40d6e92e4b55b7c05984a10e1ae59a5f0e8ed Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 13:16:11 -0700 Subject: [PATCH 029/126] Fix world transform calculation --- components/nif/nif_file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 308196f32..3313d89ab 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -221,6 +221,6 @@ Ogre::Matrix4 Node::getLocalTransform() Ogre::Matrix4 Node::getWorldTransform() { if(parent != NULL) - return getLocalTransform() * parent->getWorldTransform(); + return parent->getWorldTransform() * getLocalTransform(); return getLocalTransform(); } From df76c324a4af9681c39d95b187562fc2220c2024 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 13:34:56 -0700 Subject: [PATCH 030/126] Handle the MRK text string marker --- components/nifogre/ogre_nif_loader.cpp | 28 +++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9c0e2e10f..7a7b9e572 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -771,15 +771,33 @@ public: findTriShape(mesh, node); } - void createMeshes(Nif::Node *node, MeshPairList &meshes, int flags=0) + void createMeshes(const Nif::Node *node, MeshPairList &meshes, int flags=0) { flags |= node->flags; - // TODO: Check for extra data + Nif::ExtraPtr e = node->extra; + while(!e.empty()) + { + Nif::NiStringExtraData *sd = dynamic_cast(e.getPtr()); + if(sd != NULL) + { + // String markers may contain important information + // affecting the entire subtree of this obj + if(sd->string == "MRK") + { + // Marker objects. These are only visible in the + // editor. + flags |= 0x01; + } + } + else + warn("Unhandled extra data type "+e->recType); + e = e->extra; + } if(node->recType == Nif::RC_NiTriShape) { - NiTriShape *shape = dynamic_cast(node); + const NiTriShape *shape = dynamic_cast(node); Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); std::string fullname = mName+"@"+shape->name; @@ -804,10 +822,10 @@ public: node->recType != Nif::RC_NiRotatingParticles) warn("Unhandled mesh node type: "+node->recName); - Nif::NiNode *ninode = dynamic_cast(node); + const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { - Nif::NodeList &children = ninode->children; + const Nif::NodeList &children = ninode->children; for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) From bf26f029f92cac2857c886c246b3df11de75d773 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 13:47:19 -0700 Subject: [PATCH 031/126] Fix some skinning-related transformations --- components/nifogre/ogre_nif_loader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 7a7b9e572..cffab724e 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -546,7 +546,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader Ogre::Matrix4 mat(Ogre::Matrix4::IDENTITY); mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), Ogre::Quaternion(data->bones[b].trafo.rotation)); - mat = mat * bones[b]->getWorldTransform(); + mat = bones[b]->getWorldTransform() * mat; const std::vector &weights = data->bones[b].weights; for(size_t i = 0;i < weights.size();i++) @@ -559,9 +559,9 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { for(size_t j = 0;j < 3;j++) { - newNorms[index][j] += mat[0][j]*srcNorms[index][0] * weight; - newNorms[index][j] += mat[1][j]*srcNorms[index][1] * weight; - newNorms[index][j] += mat[2][j]*srcNorms[index][2] * weight; + newNorms[index][j] += mat[j][0]*srcNorms[index][0] * weight; + newNorms[index][j] += mat[j][1]*srcNorms[index][1] * weight; + newNorms[index][j] += mat[j][2]*srcNorms[index][2] * weight; } } } From fefbf86531f84c07766bb4b61f95f6345e8c3c73 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 14:30:23 -0700 Subject: [PATCH 032/126] Use Ogre's matrix ops to transform normals --- components/nifogre/ogre_nif_loader.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index cffab724e..29ead0461 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -557,12 +557,9 @@ class NIFMeshLoader : Ogre::ManualResourceLoader newVerts.at(index) += (mat*srcVerts[index]) * weight; if(newNorms.size() > index) { - for(size_t j = 0;j < 3;j++) - { - newNorms[index][j] += mat[j][0]*srcNorms[index][0] * weight; - newNorms[index][j] += mat[j][1]*srcNorms[index][1] * weight; - newNorms[index][j] += mat[j][2]*srcNorms[index][2] * weight; - } + Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f); + vec4 = mat*vec4 * weight; + newNorms[index] += Ogre::Vector3(&vec4[0]); } } } From 65c20f128f8c6552da1707c072c23698a40d8364 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 Jul 2012 21:18:33 -0700 Subject: [PATCH 033/126] Build bones for non-NiNode nodes (NiTriShapes, etc) --- components/nifogre/ogre_nif_loader.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 29ead0461..c0f3c25d0 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -142,7 +142,7 @@ static void fail(const std::string &msg) } -void buildBones(Ogre::Skeleton *skel, Nif::NiNode *node, Ogre::Bone *parent=NULL) +void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent=NULL) { Ogre::Bone *bone; if(!skel->hasBone(node->name)) @@ -157,12 +157,15 @@ void buildBones(Ogre::Skeleton *skel, Nif::NiNode *node, Ogre::Bone *parent=NULL bone->setBindingPose(); bone->setInitialState(); - const Nif::NodeList &children = node->children; - for(size_t i = 0;i < children.length();i++) + const Nif::NiNode *ninode = dynamic_cast(node); + if(ninode) { - Nif::NiNode *next; - if(!children[i].empty() && (next=dynamic_cast(children[i].getPtr()))) - buildBones(skel, next, bone); + const Nif::NodeList &children = ninode->children; + for(size_t i = 0;i < children.length();i++) + { + if(!children[i].empty()) + buildBones(skel, children[i].getPtr(), bone); + } } } @@ -172,7 +175,7 @@ void loadResource(Ogre::Resource *resource) OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); Nif::NIFFile nif(skel->getName()); - Nif::NiNode *node = dynamic_cast(nif.getRecord(0)); + const Nif::Node *node = dynamic_cast(nif.getRecord(0)); buildBones(skel, node); } From 93f0043afc098b7384b1b02e389c478052bc47bc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 10:04:21 -0700 Subject: [PATCH 034/126] Set the mesh's attach point as the NiTriShape's node --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c0f3c25d0..fef7054f7 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -816,7 +816,7 @@ public: mesh = meshMgr.createManual(fullname, mGroup, loader); } - meshes.push_back(std::make_pair(mesh, (shape->parent ? shape->parent->name : std::string()))); + meshes.push_back(std::make_pair(mesh, shape->name)); } else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode && node->recType != Nif::RC_NiRotatingParticles) From 0a4a141f2e94925f24f60b09e85e4a365ef336d5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 11:23:34 -0700 Subject: [PATCH 035/126] Support multiple meshes for creatures --- apps/openmw/mwrender/animation.cpp | 1 - apps/openmw/mwrender/animation.hpp | 4 +- apps/openmw/mwrender/creatureanimation.cpp | 43 ++++++++++++---------- apps/openmw/mwrender/npcanimation.hpp | 1 + 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 08176077c..17c3f62ac 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -23,7 +23,6 @@ Animation::Animation(OEngine::Render::OgreRenderer& _rend) , mShapeIndexI() , mTransformations(NULL) , mTextmappings(NULL) - , mBase(NULL) { } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 0e96b4d4d..ea18865da 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -1,6 +1,8 @@ #ifndef _GAME_RENDER_ANIMATION_H #define _GAME_RENDER_ANIMATION_H +#include + #include #include "../mwworld/actiontalk.hpp" #include @@ -37,7 +39,7 @@ protected: std::vector* mTransformations; std::map* mTextmappings; - Ogre::Entity* mBase; + std::vector mBase; void handleAnimationTransforms(); bool timeIndex( float time, const std::vector & times, int & i, int & j, float & x ); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 99800f06c..b42feec68 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,32 +26,35 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O { std::string mesh = "meshes\\" + ref->base->model; - // FIXME: There can be more than one! NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(mesh); - mBase = mRend.getScene()->createEntity(meshes[0].first->getName()); - mBase->setVisibilityFlags(RV_Actors); - - bool transparent = false; - for (unsigned int i=0; i < mBase->getNumSubEntities(); ++i) + for(size_t i = 0;i < meshes.size();i++) { - Ogre::MaterialPtr mat = mBase->getSubEntity(i)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while (techIt.hasMoreElements()) - { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while (passIt.hasMoreElements()) - { - Ogre::Pass* pass = passIt.getNext(); + mBase.push_back(mRend.getScene()->createEntity(meshes[i].first->getName())); + Ogre::Entity *base = mBase.back(); + base->setVisibilityFlags(RV_Actors); - if (pass->getDepthWriteEnabled() == false) - transparent = true; + bool transparent = false; + for (unsigned int j=0;j < base->getNumSubEntities() && !transparent; ++j) + { + Ogre::MaterialPtr mat = base->getSubEntity(j)->getMaterial(); + Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); + while (techIt.hasMoreElements() && !transparent) + { + Ogre::Technique* tech = techIt.getNext(); + Ogre::Technique::PassIterator passIt = tech->getPassIterator(); + while (passIt.hasMoreElements() && !transparent) + { + Ogre::Pass* pass = passIt.getNext(); + + if (pass->getDepthWriteEnabled() == false) + transparent = true; + } } } - } - mBase->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - mInsert->attachObject(mBase); + mInsert->attachObject(base); + } } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 82d847091..651f0ffe2 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -41,6 +41,7 @@ private: Ogre::Entity* head; Ogre::SceneNode* mInsert; + Ogre::Entity *mBase; // FIXME: Temporary! bool isBeast; bool isFemale; std::string headModel; From 89cfe778f04df460a03fa3d3f4e00eccec54ee19 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 11:38:20 -0700 Subject: [PATCH 036/126] Support multiple entities for the NPC base --- apps/openmw/mwrender/npcanimation.cpp | 91 ++++++++++++++------------- apps/openmw/mwrender/npcanimation.hpp | 2 +- 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index cede30c96..e8e24473c 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -45,7 +45,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere lAnkle(0), groin(0), lfoot(0), - rfoot(0) + rfoot(0), + mSkelBase(0) { MWWorld::LiveCellRef *ref = ptr.get(); @@ -82,33 +83,39 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - // FIXME: There can be more than one! NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(smodel); - mBase = mRend.getScene()->createEntity(meshes[0].first->getName()); - - mBase->setVisibilityFlags(RV_Actors); - bool transparent = false; - for (unsigned int i=0; igetNumSubEntities(); ++i) + for(size_t i = 0;i < meshes.size();i++) { - Ogre::MaterialPtr mat = mBase->getSubEntity(i)->getMaterial(); - Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); - while (techIt.hasMoreElements()) + mBase.push_back(mRend.getScene()->createEntity(meshes[i].first->getName())); + Ogre::Entity *base = mBase.back(); + + if(!mSkelBase && base->hasSkeleton()) + mSkelBase = base; + + base->setVisibilityFlags(RV_Actors); + bool transparent = false; + for(unsigned int j=0;j < base->getNumSubEntities();++j) { - Ogre::Technique* tech = techIt.getNext(); - Ogre::Technique::PassIterator passIt = tech->getPassIterator(); - while (passIt.hasMoreElements()) + Ogre::MaterialPtr mat = base->getSubEntity(j)->getMaterial(); + Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); + while (techIt.hasMoreElements()) { - Ogre::Pass* pass = passIt.getNext(); - if (pass->getDepthWriteEnabled() == false) - transparent = true; + Ogre::Technique* tech = techIt.getNext(); + Ogre::Technique::PassIterator passIt = tech->getPassIterator(); + while (passIt.hasMoreElements()) + { + Ogre::Pass* pass = passIt.getNext(); + if (pass->getDepthWriteEnabled() == false) + transparent = true; + } } } - } - mBase->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - mBase->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones - //stay in the same place when we skipanim, or open a gui window + base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones + //stay in the same place when we skipanim, or open a gui window - mInsert->attachObject(mBase); + mInsert->attachObject(base); + } if(isFemale) mInsert->scale(race->data.height.female, race->data.height.female, race->data.height.female); @@ -388,7 +395,7 @@ Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, const std Ogre::Entity* part = mRend.getScene()->createEntity(meshes[0].first->getName()); part->setVisibilityFlags(RV_Actors); - mBase->attachObjectToBone(bonename, part); + mSkelBase->attachObjectToBone(bonename, part); return part; } @@ -430,32 +437,32 @@ void NpcAnimation::removeIndividualPart(int type) if(type == ESM::PRT_Head && head) //0 { - mBase->detachObjectFromBone(head); + mSkelBase->detachObjectFromBone(head); head = 0; } else if(type == ESM::PRT_Hair && hair) //1 { - mBase->detachObjectFromBone(hair); + mSkelBase->detachObjectFromBone(hair); hair = 0; } else if(type == ESM::PRT_Neck && neck) //2 { - mBase->detachObjectFromBone(neck); + mSkelBase->detachObjectFromBone(neck); neck = 0; } else if(type == ESM::PRT_Groin && groin)//4 { - mBase->detachObjectFromBone(groin); + mSkelBase->detachObjectFromBone(groin); groin = 0; } else if(type == ESM::PRT_RWrist && rWrist)//8 { - mBase->detachObjectFromBone(rWrist); + mSkelBase->detachObjectFromBone(rWrist); rWrist = 0; } else if(type == ESM::PRT_LWrist && lWrist) //9 { - mBase->detachObjectFromBone(lWrist); + mSkelBase->detachObjectFromBone(lWrist); lWrist = 0; } else if(type == ESM::PRT_Shield) //10 @@ -463,72 +470,72 @@ void NpcAnimation::removeIndividualPart(int type) } else if(type == ESM::PRT_RForearm && rForearm) //11 { - mBase->detachObjectFromBone(rForearm); + mSkelBase->detachObjectFromBone(rForearm); rForearm = 0; } else if(type == ESM::PRT_LForearm && lForearm) //12 { - mBase->detachObjectFromBone(lForearm); + mSkelBase->detachObjectFromBone(lForearm); lForearm = 0; } else if(type == ESM::PRT_RUpperarm && rupperArm) //13 { - mBase->detachObjectFromBone(rupperArm); + mSkelBase->detachObjectFromBone(rupperArm); rupperArm = 0; } else if(type == ESM::PRT_LUpperarm && lupperArm) //14 { - mBase->detachObjectFromBone(lupperArm); + mSkelBase->detachObjectFromBone(lupperArm); lupperArm = 0; } else if(type == ESM::PRT_RFoot && rfoot) //15 { - mBase->detachObjectFromBone(rfoot); + mSkelBase->detachObjectFromBone(rfoot); rfoot = 0; } else if(type == ESM::PRT_LFoot && lfoot) //16 { - mBase->detachObjectFromBone(lfoot); + mSkelBase->detachObjectFromBone(lfoot); lfoot = 0; } else if(type == ESM::PRT_RAnkle && rAnkle) //17 { - mBase->detachObjectFromBone(rAnkle); + mSkelBase->detachObjectFromBone(rAnkle); rAnkle = 0; } else if(type == ESM::PRT_LAnkle && lAnkle) //18 { - mBase->detachObjectFromBone(lAnkle); + mSkelBase->detachObjectFromBone(lAnkle); lAnkle = 0; } else if(type == ESM::PRT_RKnee && rKnee) //19 { - mBase->detachObjectFromBone(rKnee); + mSkelBase->detachObjectFromBone(rKnee); rKnee = 0; } else if(type == ESM::PRT_LKnee && lKnee) //20 { - mBase->detachObjectFromBone(lKnee); + mSkelBase->detachObjectFromBone(lKnee); lKnee = 0; } else if(type == ESM::PRT_RLeg && rUpperLeg) //21 { - mBase->detachObjectFromBone(rUpperLeg); + mSkelBase->detachObjectFromBone(rUpperLeg); rUpperLeg = 0; } else if(type == ESM::PRT_LLeg && lUpperLeg) //22 { - mBase->detachObjectFromBone(lUpperLeg); + mSkelBase->detachObjectFromBone(lUpperLeg); lUpperLeg = 0; } else if(type == ESM::PRT_RPauldron && rclavicle) //23 { - mBase->detachObjectFromBone(rclavicle); + mSkelBase->detachObjectFromBone(rclavicle); rclavicle = 0; } else if(type == ESM::PRT_LPauldron && lclavicle) //24 { - mBase->detachObjectFromBone(lclavicle); + mSkelBase->detachObjectFromBone(lclavicle); lclavicle = 0; } else if(type == ESM::PRT_Weapon) //25 diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 651f0ffe2..a60c8d7fe 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -41,7 +41,7 @@ private: Ogre::Entity* head; Ogre::SceneNode* mInsert; - Ogre::Entity *mBase; // FIXME: Temporary! + Ogre::Entity *mSkelBase; // Entity with the base skeleton (temporary) bool isBeast; bool isFemale; std::string headModel; From c6cc82a51a6df78113dbc2a6e838dfc9231b5704 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 12:19:50 -0700 Subject: [PATCH 037/126] Handle multiple entities per NPC part --- apps/openmw/mwrender/npcanimation.cpp | 181 ++++++++------------------ apps/openmw/mwrender/npcanimation.hpp | 43 +++--- 2 files changed, 79 insertions(+), 145 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index e8e24473c..ce22da779 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -28,24 +28,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere boots(mInv.end()), leftglove(mInv.end()), rightglove(mInv.end()), skirtiter(mInv.end()), pants(mInv.end()), - lclavicle(0), - rclavicle(0), - rupperArm(0), - lupperArm(0), - rUpperLeg(0), - lUpperLeg(0), - lForearm(0), - rForearm(0), - lWrist(0), - rWrist(0), - rKnee(0), - lKnee(0), - neck(0), - rAnkle(0), - lAnkle(0), - groin(0), - lfoot(0), - rfoot(0), mSkelBase(0) { MWWorld::LiveCellRef *ref = ptr.get(); @@ -388,15 +370,19 @@ void NpcAnimation::updateParts() } } -Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) +std::vector NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) { - // FIXME: There can be more than one! NifOgre::MeshPairList meshes = NIFLoader::load(mesh); - Ogre::Entity* part = mRend.getScene()->createEntity(meshes[0].first->getName()); - part->setVisibilityFlags(RV_Actors); + std::vector parts; + for(size_t i = 0;i < meshes.size();i++) + { + parts.push_back(mRend.getScene()->createEntity(meshes[i].first->getName())); + Ogre::Entity *part = parts.back(); - mSkelBase->attachObjectToBone(bonename, part); - return part; + part->setVisibilityFlags(RV_Actors); + mSkelBase->attachObjectToBone(bonename, part); + } + return parts; } void NpcAnimation::runAnimation(float timepassed) @@ -430,114 +416,61 @@ void NpcAnimation::runAnimation(float timepassed) } } +void NpcAnimation::removeEntities(std::vector &entities) +{ + for(size_t i = 0;i < entities.size();i++) + mSkelBase->detachObjectFromBone(entities[i]); + entities.clear(); +} + void NpcAnimation::removeIndividualPart(int type) { mPartPriorities[type] = 0; mPartslots[type] = -1; - if(type == ESM::PRT_Head && head) //0 - { - mSkelBase->detachObjectFromBone(head); - head = 0; - } - else if(type == ESM::PRT_Hair && hair) //1 - { - mSkelBase->detachObjectFromBone(hair); - hair = 0; - } - else if(type == ESM::PRT_Neck && neck) //2 - { - mSkelBase->detachObjectFromBone(neck); - neck = 0; - } - else if(type == ESM::PRT_Groin && groin)//4 - { - mSkelBase->detachObjectFromBone(groin); - groin = 0; - } - else if(type == ESM::PRT_RWrist && rWrist)//8 - { - mSkelBase->detachObjectFromBone(rWrist); - rWrist = 0; - } - else if(type == ESM::PRT_LWrist && lWrist) //9 - { - mSkelBase->detachObjectFromBone(lWrist); - lWrist = 0; - } + if(type == ESM::PRT_Head) //0 + removeEntities(head); + else if(type == ESM::PRT_Hair) //1 + removeEntities(hair); + else if(type == ESM::PRT_Neck) //2 + removeEntities(neck); + else if(type == ESM::PRT_Groin)//4 + removeEntities(groin); + else if(type == ESM::PRT_RWrist)//8 + removeEntities(rWrist); + else if(type == ESM::PRT_LWrist) //9 + removeEntities(lWrist); else if(type == ESM::PRT_Shield) //10 { } - else if(type == ESM::PRT_RForearm && rForearm) //11 - { - mSkelBase->detachObjectFromBone(rForearm); - rForearm = 0; - } - else if(type == ESM::PRT_LForearm && lForearm) //12 - { - mSkelBase->detachObjectFromBone(lForearm); - lForearm = 0; - } - else if(type == ESM::PRT_RUpperarm && rupperArm) //13 - { - mSkelBase->detachObjectFromBone(rupperArm); - rupperArm = 0; - } - else if(type == ESM::PRT_LUpperarm && lupperArm) //14 - { - mSkelBase->detachObjectFromBone(lupperArm); - lupperArm = 0; - } - else if(type == ESM::PRT_RFoot && rfoot) //15 - { - mSkelBase->detachObjectFromBone(rfoot); - rfoot = 0; - } - else if(type == ESM::PRT_LFoot && lfoot) //16 - { - mSkelBase->detachObjectFromBone(lfoot); - lfoot = 0; - } - else if(type == ESM::PRT_RAnkle && rAnkle) //17 - { - mSkelBase->detachObjectFromBone(rAnkle); - rAnkle = 0; - } - else if(type == ESM::PRT_LAnkle && lAnkle) //18 - { - mSkelBase->detachObjectFromBone(lAnkle); - lAnkle = 0; - } - else if(type == ESM::PRT_RKnee && rKnee) //19 - { - mSkelBase->detachObjectFromBone(rKnee); - rKnee = 0; - } - else if(type == ESM::PRT_LKnee && lKnee) //20 - { - mSkelBase->detachObjectFromBone(lKnee); - lKnee = 0; - } - else if(type == ESM::PRT_RLeg && rUpperLeg) //21 - { - mSkelBase->detachObjectFromBone(rUpperLeg); - rUpperLeg = 0; - } - else if(type == ESM::PRT_LLeg && lUpperLeg) //22 - { - mSkelBase->detachObjectFromBone(lUpperLeg); - lUpperLeg = 0; - } - else if(type == ESM::PRT_RPauldron && rclavicle) //23 - { - mSkelBase->detachObjectFromBone(rclavicle); - rclavicle = 0; - } - else if(type == ESM::PRT_LPauldron && lclavicle) //24 - { - mSkelBase->detachObjectFromBone(lclavicle); - lclavicle = 0; - } + else if(type == ESM::PRT_RForearm) //11 + removeEntities(rForearm); + else if(type == ESM::PRT_LForearm) //12 + removeEntities(lForearm); + else if(type == ESM::PRT_RUpperarm) //13 + removeEntities(rupperArm); + else if(type == ESM::PRT_LUpperarm) //14 + removeEntities(lupperArm); + else if(type == ESM::PRT_RFoot) //15 + removeEntities(rfoot); + else if(type == ESM::PRT_LFoot) //16 + removeEntities(lfoot); + else if(type == ESM::PRT_RAnkle) //17 + removeEntities(rAnkle); + else if(type == ESM::PRT_LAnkle) //18 + removeEntities(lAnkle); + else if(type == ESM::PRT_RKnee) //19 + removeEntities(rKnee); + else if(type == ESM::PRT_LKnee) //20 + removeEntities(lKnee); + else if(type == ESM::PRT_RLeg) //21 + removeEntities(rUpperLeg); + else if(type == ESM::PRT_LLeg) //22 + removeEntities(lUpperLeg); + else if(type == ESM::PRT_RPauldron) //23 + removeEntities(rclavicle); + else if(type == ESM::PRT_LPauldron) //24 + removeEntities(lclavicle); else if(type == ESM::PRT_Weapon) //25 { } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index a60c8d7fe..7830b68cc 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -19,26 +19,26 @@ private: int mPartPriorities[27]; //Bounded Parts - Ogre::Entity* lclavicle; - Ogre::Entity* rclavicle; - Ogre::Entity* rupperArm; - Ogre::Entity* lupperArm; - Ogre::Entity* rUpperLeg; - Ogre::Entity* lUpperLeg; - Ogre::Entity* lForearm; - Ogre::Entity* rForearm; - Ogre::Entity* lWrist; - Ogre::Entity* rWrist; - Ogre::Entity* rKnee; - Ogre::Entity* lKnee; - Ogre::Entity* neck; - Ogre::Entity* rAnkle; - Ogre::Entity* lAnkle; - Ogre::Entity* groin; - Ogre::Entity* lfoot; - Ogre::Entity* rfoot; - Ogre::Entity* hair; - Ogre::Entity* head; + std::vector lclavicle; + std::vector rclavicle; + std::vector rupperArm; + std::vector lupperArm; + std::vector rUpperLeg; + std::vector lUpperLeg; + std::vector lForearm; + std::vector rForearm; + std::vector lWrist; + std::vector rWrist; + std::vector rKnee; + std::vector lKnee; + std::vector neck; + std::vector rAnkle; + std::vector lAnkle; + std::vector groin; + std::vector lfoot; + std::vector rfoot; + std::vector hair; + std::vector head; Ogre::SceneNode* mInsert; Ogre::Entity *mSkelBase; // Entity with the base skeleton (temporary) @@ -65,9 +65,10 @@ private: public: NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); virtual ~NpcAnimation(); - Ogre::Entity* insertBoundedPart(const std::string &mesh, const std::string &bonename); + std::vector insertBoundedPart(const std::string &mesh, const std::string &bonename); virtual void runAnimation(float timepassed); void updateParts(); + void removeEntities(std::vector &entities); void removeIndividualPart(int type); void reserveIndividualPart(int type, int group, int priority); From 3dedac5cb14623911a43de2027c8f86077586e8d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 13:40:03 -0700 Subject: [PATCH 038/126] Create mesh entities for objects when loading the NIF --- apps/openmw/mwrender/objects.cpp | 23 +++++++-------- components/nifogre/ogre_nif_loader.cpp | 39 ++++++++++++++++++++++++++ components/nifogre/ogre_nif_loader.hpp | 12 ++++++++ 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 2ff9de9a4..bc1a4a521 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -93,13 +93,10 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; - NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(mesh); - std::vector entities(meshes.size()); - for(size_t i = 0;i < meshes.size();i++) + NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, mesh); + for(size_t i = 0;i < entities.mEntities.size();i++) { - entities[i] = mRenderer.getScene()->createEntity(meshes[i].first->getName()); - - const Ogre::AxisAlignedBox &tmp = entities[i]->getBoundingBox(); + const Ogre::AxisAlignedBox &tmp = entities.mEntities[i]->getBoundingBox(); bounds.merge(Ogre::AxisAlignedBox(insert->_getDerivedPosition() + tmp.getMinimum(), insert->_getDerivedPosition() + tmp.getMaximum()) ); @@ -119,9 +116,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) mBounds[ptr.getCell()].merge(bounds); bool transparent = false; - for(size_t i = 0;i < entities.size();i++) + for(size_t i = 0;i < entities.mEntities.size();i++) { - Ogre::Entity *ent = entities[i]; + Ogre::Entity *ent = entities.mEntities[i]; for (unsigned int i=0; igetNumSubEntities(); ++i) { Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); @@ -143,10 +140,9 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) { - for(size_t i = 0;i < entities.size();i++) + for(size_t i = 0;i < entities.mEntities.size();i++) { - Ogre::Entity *ent = entities[i]; - insert->attachObject(ent); + Ogre::Entity *ent = entities.mEntities[i]; ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); @@ -197,9 +193,10 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - for(size_t i = 0;i < entities.size();i++) + for(size_t i = 0;i < entities.mEntities.size();i++) { - Ogre::Entity *ent = entities[i]; + Ogre::Entity *ent = entities.mEntities[i]; + insert->detachObject(ent); sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); mRenderer.getScene()->destroyEntity(ent); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index fef7054f7..c90083619 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -871,6 +872,44 @@ MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, c return meshes; } +EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string &name, const std::string &group) +{ + EntityList entitylist; + + MeshPairList meshes = load(name, NULL, group); + if(meshes.size() == 0) + return entitylist; + + Ogre::SceneManager *sceneMgr = parent->getCreator(); + for(size_t i = 0;i < meshes.size();i++) + { + entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].first->getName())); + Ogre::Entity *entity = entitylist.mEntities.back(); + if(!entitylist.mSkelBase && entity->hasSkeleton()) + entitylist.mSkelBase = entity; + } + + if(entitylist.mSkelBase) + { + parent->attachObject(entitylist.mSkelBase); + for(size_t i = 0;i < entitylist.mEntities.size();i++) + { + Ogre::Entity *entity = entitylist.mEntities[i]; + if(entity != entitylist.mSkelBase && entity->hasSkeleton()) + entity->shareSkeletonInstanceWith(entitylist.mSkelBase); + else if(entity != entitylist.mSkelBase) + entitylist.mSkelBase->attachObjectToBone(meshes[i].second, entity); + } + } + else + { + for(size_t i = 0;i < entitylist.mEntities.size();i++) + parent->attachObject(entitylist.mEntities[i]); + } + + return entitylist; +} + /* More code currently not in use, from the old D source. This was used in the first attempt at loading NIF meshes, where each submesh diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 4e9ffc31e..bd6f99b2f 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -58,6 +58,14 @@ namespace Nif namespace NifOgre { +struct EntityList { + std::vector mEntities; + Ogre::Entity *mSkelBase; + + EntityList() : mSkelBase(0) + { } +}; + /** This holds a list of meshes along with the names of their parent nodes */ typedef std::vector< std::pair > MeshPairList; @@ -81,6 +89,10 @@ public: static MeshPairList load(const std::string &name, Ogre::SkeletonPtr *skel=NULL, const std::string &group="General"); + + static EntityList createEntities(Ogre::SceneNode *parent, + const std::string &name, + const std::string &group="General"); }; } From 3efd2030e206099f613d99aadee3ddce3e959a6b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 14:11:07 -0700 Subject: [PATCH 039/126] Create entities when loading NIFs for creatures --- apps/openmw/mwrender/creatureanimation.cpp | 17 +++++++---------- components/nifogre/ogre_nif_loader.cpp | 3 +++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index b42feec68..92930e8d4 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,17 +26,16 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O { std::string mesh = "meshes\\" + ref->base->model; - NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(mesh); - for(size_t i = 0;i < meshes.size();i++) + NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mInsert, mesh); + mBase = entities.mEntities; + for(size_t i = 0;i < mBase.size();i++) { - mBase.push_back(mRend.getScene()->createEntity(meshes[i].first->getName())); - Ogre::Entity *base = mBase.back(); - base->setVisibilityFlags(RV_Actors); + mBase[i]->setVisibilityFlags(RV_Actors); bool transparent = false; - for (unsigned int j=0;j < base->getNumSubEntities() && !transparent; ++j) + for (unsigned int j=0;j < mBase[i]->getNumSubEntities() && !transparent; ++j) { - Ogre::MaterialPtr mat = base->getSubEntity(j)->getMaterial(); + Ogre::MaterialPtr mat = mBase[i]->getSubEntity(j)->getMaterial(); Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); while (techIt.hasMoreElements() && !transparent) { @@ -51,9 +50,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O } } } - base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - - mInsert->attachObject(base); + mBase[i]->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } } } diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c90083619..79eaa6680 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -896,7 +896,10 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string { Ogre::Entity *entity = entitylist.mEntities[i]; if(entity != entitylist.mSkelBase && entity->hasSkeleton()) + { entity->shareSkeletonInstanceWith(entitylist.mSkelBase); + parent->attachObject(entity); + } else if(entity != entitylist.mSkelBase) entitylist.mSkelBase->attachObjectToBone(meshes[i].second, entity); } From a590db2cf46da03e5fd8642f629424a039c3434a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 15:43:40 -0700 Subject: [PATCH 040/126] Create entities when loading NIFs for the NPC base --- apps/openmw/mwrender/npcanimation.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index ce22da779..86a58c849 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -65,14 +65,12 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load(smodel); - for(size_t i = 0;i < meshes.size();i++) + NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mInsert, smodel); + mBase = entities.mEntities; + mSkelBase = entities.mSkelBase; + for(size_t i = 0;i < mBase.size();i++) { - mBase.push_back(mRend.getScene()->createEntity(meshes[i].first->getName())); - Ogre::Entity *base = mBase.back(); - - if(!mSkelBase && base->hasSkeleton()) - mSkelBase = base; + Ogre::Entity *base = mBase[i]; base->setVisibilityFlags(RV_Actors); bool transparent = false; @@ -95,8 +93,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones //stay in the same place when we skipanim, or open a gui window - - mInsert->attachObject(base); } if(isFemale) From 94f3e7a6c069cc9d4de5959a343bc06d0d66b320 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 16:00:03 -0700 Subject: [PATCH 041/126] Store the entity list in the object --- apps/openmw/mwrender/animation.hpp | 3 ++- apps/openmw/mwrender/creatureanimation.cpp | 14 +++++++------- apps/openmw/mwrender/npcanimation.cpp | 15 ++++++--------- apps/openmw/mwrender/npcanimation.hpp | 1 - 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index ea18865da..def7f226c 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -3,6 +3,7 @@ #include +#include #include #include "../mwworld/actiontalk.hpp" #include @@ -39,7 +40,7 @@ protected: std::vector* mTransformations; std::map* mTextmappings; - std::vector mBase; + NifOgre::EntityList mEntityList; void handleAnimationTransforms(); bool timeIndex( float time, const std::vector & times, int & i, int & j, float & x ); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 92930e8d4..fd2855154 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,16 +26,16 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O { std::string mesh = "meshes\\" + ref->base->model; - NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mInsert, mesh); - mBase = entities.mEntities; - for(size_t i = 0;i < mBase.size();i++) + mEntityList = NifOgre::NIFLoader::createEntities(mInsert, mesh); + for(size_t i = 0;i < mEntityList.mEntities.size();i++) { - mBase[i]->setVisibilityFlags(RV_Actors); + Ogre::Entity *ent = mEntityList.mEntities[i]; + ent->setVisibilityFlags(RV_Actors); bool transparent = false; - for (unsigned int j=0;j < mBase[i]->getNumSubEntities() && !transparent; ++j) + for (unsigned int j=0;j < ent->getNumSubEntities() && !transparent; ++j) { - Ogre::MaterialPtr mat = mBase[i]->getSubEntity(j)->getMaterial(); + Ogre::MaterialPtr mat = ent->getSubEntity(j)->getMaterial(); Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); while (techIt.hasMoreElements() && !transparent) { @@ -50,7 +50,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O } } } - mBase[i]->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); + ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 86a58c849..cdef5ce8b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -27,8 +27,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere leftpauldron(mInv.end()), rightpauldron(mInv.end()), boots(mInv.end()), leftglove(mInv.end()), rightglove(mInv.end()), skirtiter(mInv.end()), - pants(mInv.end()), - mSkelBase(0) + pants(mInv.end()) { MWWorld::LiveCellRef *ref = ptr.get(); @@ -65,12 +64,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mInsert, smodel); - mBase = entities.mEntities; - mSkelBase = entities.mSkelBase; - for(size_t i = 0;i < mBase.size();i++) + mEntityList = NifOgre::NIFLoader::createEntities(mInsert, smodel); + for(size_t i = 0;i < mEntityList.mEntities.size();i++) { - Ogre::Entity *base = mBase[i]; + Ogre::Entity *base = mEntityList.mEntities[i]; base->setVisibilityFlags(RV_Actors); bool transparent = false; @@ -376,7 +373,7 @@ std::vector NpcAnimation::insertBoundedPart(const std::string &me Ogre::Entity *part = parts.back(); part->setVisibilityFlags(RV_Actors); - mSkelBase->attachObjectToBone(bonename, part); + mEntityList.mSkelBase->attachObjectToBone(bonename, part); } return parts; } @@ -415,7 +412,7 @@ void NpcAnimation::runAnimation(float timepassed) void NpcAnimation::removeEntities(std::vector &entities) { for(size_t i = 0;i < entities.size();i++) - mSkelBase->detachObjectFromBone(entities[i]); + mEntityList.mSkelBase->detachObjectFromBone(entities[i]); entities.clear(); } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 7830b68cc..f27642720 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -41,7 +41,6 @@ private: std::vector head; Ogre::SceneNode* mInsert; - Ogre::Entity *mSkelBase; // Entity with the base skeleton (temporary) bool isBeast; bool isFemale; std::string headModel; From 496343b714e9b78dbb3297307122775cac57db03 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 16:36:43 -0700 Subject: [PATCH 042/126] Use the proper member for the NIF type string --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 79eaa6680..305e66df1 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -792,7 +792,7 @@ public: } } else - warn("Unhandled extra data type "+e->recType); + warn("Unhandled extra data type "+e->recName); e = e->extra; } From 1c544682d5bf12b152cb3e868b90e22085806af3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 16:45:01 -0700 Subject: [PATCH 043/126] Stub handling for NiTextKeyExtraData to suppress some spam --- components/nifogre/ogre_nif_loader.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 305e66df1..761924488 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -779,8 +779,9 @@ public: Nif::ExtraPtr e = node->extra; while(!e.empty()) { - Nif::NiStringExtraData *sd = dynamic_cast(e.getPtr()); - if(sd != NULL) + Nif::NiStringExtraData *sd; + Nif::NiTextKeyExtraData *td; + if((sd=dynamic_cast(e.getPtr())) != NULL) { // String markers may contain important information // affecting the entire subtree of this obj @@ -791,6 +792,10 @@ public: flags |= 0x01; } } + else if((td=dynamic_cast(e.getPtr())) != NULL) + { + // TODO: Read and store text keys somewhere + } else warn("Unhandled extra data type "+e->recName); e = e->extra; From 92546ca18d034300b12b179dc099e1cee37c005f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 20:23:09 -0700 Subject: [PATCH 044/126] Move the last bits of code to createEntities --- apps/openmw/mwrender/npcanimation.cpp | 14 ++++---------- apps/openmw/mwrender/sky.cpp | 22 +++++++++------------- components/nifogre/ogre_nif_loader.hpp | 2 +- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index cdef5ce8b..439f6fa2d 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -365,16 +365,10 @@ void NpcAnimation::updateParts() std::vector NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) { - NifOgre::MeshPairList meshes = NIFLoader::load(mesh); - std::vector parts; - for(size_t i = 0;i < meshes.size();i++) - { - parts.push_back(mRend.getScene()->createEntity(meshes[i].first->getName())); - Ogre::Entity *part = parts.back(); - - part->setVisibilityFlags(RV_Actors); - mEntityList.mSkelBase->attachObjectToBone(bonename, part); - } + NifOgre::EntityList entities = NIFLoader::createEntities(mInsert, mesh); + std::vector &parts = entities.mEntities; + for(size_t i = 0;i < parts.size();i++) + parts[i]->setVisibilityFlags(RV_Actors); return parts; } diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 8f49e03df..682a96419 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -509,16 +509,14 @@ void SkyManager::create() /// \todo sky_night_02.nif (available in Bloodmoon) mAtmosphereNight = mRootNode->createChildSceneNode(); - NifOgre::MeshPairList meshes = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); - for(size_t i = 0;i < meshes.size();i++) + NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mAtmosphereNight, "meshes\\sky_night_01.nif"); + for(size_t i = 0;i < entities.mEntities.size();i++) { - Entity* night1_ent = mSceneMgr->createEntity(meshes[i].first->getName()); + Entity* night1_ent = entities.mEntities[i]; night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); night1_ent->setVisibilityFlags(RV_Sky); night1_ent->setCastShadows(false); - mAtmosphereNight->attachObject(night1_ent); - for (unsigned int i=0; igetNumSubEntities(); ++i) { MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); @@ -589,17 +587,16 @@ void SkyManager::create() fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); mAtmosphereDay = mRootNode->createChildSceneNode(); - meshes = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); - for(size_t i = 0;i < meshes.size();i++) + entities = NifOgre::NIFLoader::createEntities(mAtmosphereDay, "meshes\\sky_atmosphere.nif"); + for(size_t i = 0;i < entities.mEntities.size();i++) { - Entity* atmosphere_ent = mSceneMgr->createEntity(meshes[i].first->getName()); + Entity* atmosphere_ent = entities.mEntities[i]; atmosphere_ent->setCastShadows(false); ModVertexAlpha(atmosphere_ent, 0); atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly); atmosphere_ent->setVisibilityFlags(RV_Sky); - mAtmosphereDay->attachObject(atmosphere_ent); mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere"); @@ -677,13 +674,12 @@ void SkyManager::create() mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); SceneNode* clouds_node = mRootNode->createChildSceneNode(); - meshes = NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); - for(size_t i = 0;i < meshes.size();i++) + entities = NifOgre::NIFLoader::createEntities(clouds_node, "meshes\\sky_clouds_01.nif"); + for(size_t i = 0;i < entities.mEntities.size();i++) { - Entity* clouds_ent = mSceneMgr->createEntity(meshes[i].first->getName()); + Entity* clouds_ent = entities.mEntities[i]; clouds_ent->setVisibilityFlags(RV_Sky); clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); - clouds_node->attachObject(clouds_ent); mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); mCloudMaterial = mCloudMaterial->clone("Clouds"); diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index bd6f99b2f..f21069b75 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -85,11 +85,11 @@ typedef std::vector< std::pair > MeshPairList; */ class NIFLoader { -public: static MeshPairList load(const std::string &name, Ogre::SkeletonPtr *skel=NULL, const std::string &group="General"); +public: static EntityList createEntities(Ogre::SceneNode *parent, const std::string &name, const std::string &group="General"); From b04c3cbcac64988ec3a964a1b323946c6d56abbe Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 21:42:47 -0700 Subject: [PATCH 045/126] Store the entities' root node in the EntityList --- components/nifogre/ogre_nif_loader.cpp | 1 + components/nifogre/ogre_nif_loader.hpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 761924488..c74f1fe0d 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -885,6 +885,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string if(meshes.size() == 0) return entitylist; + entitylist.mRootNode = parent; Ogre::SceneManager *sceneMgr = parent->getCreator(); for(size_t i = 0;i < meshes.size();i++) { diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index f21069b75..70f467295 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -61,8 +61,9 @@ namespace NifOgre struct EntityList { std::vector mEntities; Ogre::Entity *mSkelBase; + Ogre::SceneNode *mRootNode; - EntityList() : mSkelBase(0) + EntityList() : mSkelBase(0), mRootNode(0) { } }; From a32740cf5ee1712299be24d00d8ba67d90fe2e29 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 22:41:26 -0700 Subject: [PATCH 046/126] Remove an unused parameter --- components/nifogre/ogre_nif_loader.cpp | 20 ++++++++------------ components/nifogre/ogre_nif_loader.hpp | 4 +--- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c74f1fe0d..9c294f8c3 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -180,20 +180,19 @@ void loadResource(Ogre::Resource *resource) buildBones(skel, node); } -static bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node, Ogre::SkeletonPtr *skel) +static bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) { if(node->boneTrafo != NULL) { Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); - Ogre::SkeletonPtr tmp = skelMgr.getByName(name); - if(tmp.isNull()) + Ogre::SkeletonPtr skel = skelMgr.getByName(name); + if(skel.isNull()) { static NIFSkeletonLoader loader; - tmp = skelMgr.create(name, group, true, &loader); + skel = skelMgr.create(name, group, true, &loader); } - if(skel) *skel = tmp; return true; } @@ -205,7 +204,7 @@ static bool createSkeleton(const std::string &name, const std::string &group, Ni { if(!children[i].empty()) { - if(createSkeleton(name, group, children[i].getPtr(), skel)) + if(createSkeleton(name, group, children[i].getPtr())) return true; } } @@ -843,13 +842,10 @@ public: NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; -MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, const std::string &group) +MeshPairList NIFLoader::load(const std::string &name, const std::string &group) { MeshPairList meshes; - if(skel != NULL) - skel->setNull(); - Nif::NIFFile nif(name); if (nif.numRecords() < 1) { @@ -869,7 +865,7 @@ MeshPairList NIFLoader::load(const std::string &name, Ogre::SkeletonPtr *skel, c return meshes; } - bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node, skel); + bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node); NIFMeshLoader meshldr(name, group, hasSkel); meshldr.createMeshes(node, meshes); @@ -881,7 +877,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string { EntityList entitylist; - MeshPairList meshes = load(name, NULL, group); + MeshPairList meshes = load(name, group); if(meshes.size() == 0) return entitylist; diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 70f467295..3f58097c0 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -86,9 +86,7 @@ typedef std::vector< std::pair > MeshPairList; */ class NIFLoader { - static MeshPairList load(const std::string &name, - Ogre::SkeletonPtr *skel=NULL, - const std::string &group="General"); + static MeshPairList load(const std::string &name, const std::string &group); public: static EntityList createEntities(Ogre::SceneNode *parent, From 4109d0d9232b13813f53a74e78afcffb7f772b45 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 17 Jul 2012 22:47:56 -0700 Subject: [PATCH 047/126] Destroy entities removed from the NPC --- apps/openmw/mwrender/npcanimation.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 439f6fa2d..d740dd7db 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -405,8 +405,12 @@ void NpcAnimation::runAnimation(float timepassed) void NpcAnimation::removeEntities(std::vector &entities) { + Ogre::SceneManager *sceneMgr = mInsert->getCreator(); for(size_t i = 0;i < entities.size();i++) + { mEntityList.mSkelBase->detachObjectFromBone(entities[i]); + sceneMgr->destroyEntity(entities[i]); + } entities.clear(); } From 02d39080c8e3f66d7ff77d5cc9617d8ba4174767 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 00:17:39 -0700 Subject: [PATCH 048/126] Destroy entities when they're done with. --- apps/openmw/mwrender/animation.cpp | 5 +++++ apps/openmw/mwrender/npcanimation.cpp | 20 ++++++++++++++++++++ apps/openmw/mwrender/npcanimation.hpp | 1 - 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 17c3f62ac..fddfe7b8a 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace MWRender { @@ -28,6 +29,10 @@ Animation::Animation(OEngine::Render::OgreRenderer& _rend) Animation::~Animation() { + Ogre::SceneManager *sceneMgr = mInsert->getCreator(); + for(size_t i = 0;i < mEntityList.mEntities.size();i++) + sceneMgr->destroyEntity(mEntityList.mEntities[i]); + mEntityList.mEntities.clear(); } void Animation::startScript(std::string groupname, int mode, int loops) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index d740dd7db..51bad3d0e 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -17,6 +17,26 @@ using namespace NifOgre; namespace MWRender{ NpcAnimation::~NpcAnimation() { + removeEntities(head); + removeEntities(hair); + removeEntities(neck); + removeEntities(groin); + removeEntities(rWrist); + removeEntities(lWrist); + removeEntities(rForearm); + removeEntities(lForearm); + removeEntities(rupperArm); + removeEntities(lupperArm); + removeEntities(rfoot); + removeEntities(lfoot); + removeEntities(rAnkle); + removeEntities(lAnkle); + removeEntities(rKnee); + removeEntities(lKnee); + removeEntities(rUpperLeg); + removeEntities(lUpperLeg); + removeEntities(rclavicle); + removeEntities(lclavicle); } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index f27642720..6fb549408 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -40,7 +40,6 @@ private: std::vector hair; std::vector head; - Ogre::SceneNode* mInsert; bool isBeast; bool isFemale; std::string headModel; From 6611b0b317986430bac19cb57058cefb1d8c4af4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 10:09:16 -0700 Subject: [PATCH 049/126] Use an array instead of a bunch of nearly-identical if blocks --- apps/openmw/mwrender/npcanimation.cpp | 100 ++++++++------------------ 1 file changed, 28 insertions(+), 72 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 51bad3d0e..eb5fceb0e 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -123,79 +123,35 @@ void NpcAnimation::updateParts() { bool apparelChanged = false; - //mInv.getSlot(MWWorld::InventoryStore::Slot_Robe); - if(robe != mInv.getSlot(MWWorld::InventoryStore::Slot_Robe)) + const struct { + MWWorld::ContainerStoreIterator *iter; + int slot; + } slotlist[] = { + { &robe, MWWorld::InventoryStore::Slot_Robe }, + { &skirtiter, MWWorld::InventoryStore::Slot_Skirt }, + { &helmet, MWWorld::InventoryStore::Slot_Helmet }, + { &cuirass, MWWorld::InventoryStore::Slot_Cuirass }, + { &greaves, MWWorld::InventoryStore::Slot_Greaves }, + { &leftpauldron, MWWorld::InventoryStore::Slot_LeftPauldron }, + { &rightpauldron, MWWorld::InventoryStore::Slot_RightPauldron }, + { &boots, MWWorld::InventoryStore::Slot_Boots }, // !isBeast + { &leftglove, MWWorld::InventoryStore::Slot_LeftGauntlet }, + { &rightglove, MWWorld::InventoryStore::Slot_RightGauntlet }, + { &shirt, MWWorld::InventoryStore::Slot_Shirt }, + { &pants, MWWorld::InventoryStore::Slot_Pants }, + }; + for(size_t i = 0;i < sizeof(slotlist)/sizeof(slotlist[0]);i++) { - // A robe was added or removed - robe = mInv.getSlot(MWWorld::InventoryStore::Slot_Robe); - removePartGroup(MWWorld::InventoryStore::Slot_Robe); - apparelChanged = true; - } - if(skirtiter != mInv.getSlot(MWWorld::InventoryStore::Slot_Skirt)) - { - skirtiter = mInv.getSlot(MWWorld::InventoryStore::Slot_Skirt); - removePartGroup(MWWorld::InventoryStore::Slot_Skirt); - apparelChanged = true; - } - if(helmet != mInv.getSlot(MWWorld::InventoryStore::Slot_Helmet)) - { - helmet = mInv.getSlot(MWWorld::InventoryStore::Slot_Helmet); - removePartGroup(MWWorld::InventoryStore::Slot_Helmet); - apparelChanged = true; - } - if(cuirass != mInv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)) - { - cuirass = mInv.getSlot(MWWorld::InventoryStore::Slot_Cuirass); - removePartGroup(MWWorld::InventoryStore::Slot_Cuirass); - apparelChanged = true; - } - if(greaves != mInv.getSlot(MWWorld::InventoryStore::Slot_Greaves)) - { - greaves = mInv.getSlot(MWWorld::InventoryStore::Slot_Greaves); - removePartGroup(MWWorld::InventoryStore::Slot_Greaves); - apparelChanged = true; - } - if(leftpauldron != mInv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)) - { - leftpauldron = mInv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron); - removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron); - apparelChanged = true; - } - if(rightpauldron != mInv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)) - { - rightpauldron = mInv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron); - removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron); - apparelChanged = true; - } - if(!isBeast && boots != mInv.getSlot(MWWorld::InventoryStore::Slot_Boots)) - { - boots = mInv.getSlot(MWWorld::InventoryStore::Slot_Boots); - removePartGroup(MWWorld::InventoryStore::Slot_Boots); - apparelChanged = true; - } - if(leftglove != mInv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)) - { - leftglove = mInv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet); - removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet); - apparelChanged = true; - } - if(rightglove != mInv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)) - { - rightglove = mInv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet); - removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet); - apparelChanged = true; - } - if(shirt != mInv.getSlot(MWWorld::InventoryStore::Slot_Shirt)) - { - shirt = mInv.getSlot(MWWorld::InventoryStore::Slot_Shirt); - removePartGroup(MWWorld::InventoryStore::Slot_Shirt); - apparelChanged = true; - } - if(pants != mInv.getSlot(MWWorld::InventoryStore::Slot_Pants)) - { - pants = mInv.getSlot(MWWorld::InventoryStore::Slot_Pants); - removePartGroup(MWWorld::InventoryStore::Slot_Pants); - apparelChanged = true; + if(slotlist[i].iter == &boots && isBeast) + continue; + + MWWorld::ContainerStoreIterator iter = mInv.getSlot(slotlist[i].slot); + if(*slotlist[i].iter != iter) + { + *slotlist[i].iter = iter; + removePartGroup(slotlist[i].slot); + apparelChanged = true; + } } if(apparelChanged) From 04e496a6ca4e1329c95b084b77e14572b0c61455 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 10:26:25 -0700 Subject: [PATCH 050/126] Store the entity lists for NPC parts --- apps/openmw/mwrender/npcanimation.cpp | 18 ++++++----- apps/openmw/mwrender/npcanimation.hpp | 44 +++++++++++++-------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index eb5fceb0e..b4e39ff15 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -339,13 +339,13 @@ void NpcAnimation::updateParts() } } -std::vector NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) +NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) { NifOgre::EntityList entities = NIFLoader::createEntities(mInsert, mesh); std::vector &parts = entities.mEntities; for(size_t i = 0;i < parts.size();i++) parts[i]->setVisibilityFlags(RV_Actors); - return parts; + return entities; } void NpcAnimation::runAnimation(float timepassed) @@ -379,15 +379,19 @@ void NpcAnimation::runAnimation(float timepassed) } } -void NpcAnimation::removeEntities(std::vector &entities) +void NpcAnimation::removeEntities(NifOgre::EntityList &entities) { + assert(&entities != &mEntityList); + Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < entities.size();i++) + for(size_t i = 0;i < entities.mEntities.size();i++) { - mEntityList.mSkelBase->detachObjectFromBone(entities[i]); - sceneMgr->destroyEntity(entities[i]); + mEntityList.mSkelBase->detachObjectFromBone(entities.mEntities[i]); + sceneMgr->destroyEntity(entities.mEntities[i]); } - entities.clear(); + entities.mEntities.clear(); + entities.mSkelBase = NULL; + entities.mRootNode = NULL; } void NpcAnimation::removeIndividualPart(int type) diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 6fb549408..1eec1294f 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -19,26 +19,26 @@ private: int mPartPriorities[27]; //Bounded Parts - std::vector lclavicle; - std::vector rclavicle; - std::vector rupperArm; - std::vector lupperArm; - std::vector rUpperLeg; - std::vector lUpperLeg; - std::vector lForearm; - std::vector rForearm; - std::vector lWrist; - std::vector rWrist; - std::vector rKnee; - std::vector lKnee; - std::vector neck; - std::vector rAnkle; - std::vector lAnkle; - std::vector groin; - std::vector lfoot; - std::vector rfoot; - std::vector hair; - std::vector head; + NifOgre::EntityList lclavicle; + NifOgre::EntityList rclavicle; + NifOgre::EntityList rupperArm; + NifOgre::EntityList lupperArm; + NifOgre::EntityList rUpperLeg; + NifOgre::EntityList lUpperLeg; + NifOgre::EntityList lForearm; + NifOgre::EntityList rForearm; + NifOgre::EntityList lWrist; + NifOgre::EntityList rWrist; + NifOgre::EntityList rKnee; + NifOgre::EntityList lKnee; + NifOgre::EntityList neck; + NifOgre::EntityList rAnkle; + NifOgre::EntityList lAnkle; + NifOgre::EntityList groin; + NifOgre::EntityList lfoot; + NifOgre::EntityList rfoot; + NifOgre::EntityList hair; + NifOgre::EntityList head; bool isBeast; bool isFemale; @@ -63,10 +63,10 @@ private: public: NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); virtual ~NpcAnimation(); - std::vector insertBoundedPart(const std::string &mesh, const std::string &bonename); + NifOgre::EntityList insertBoundedPart(const std::string &mesh, const std::string &bonename); virtual void runAnimation(float timepassed); void updateParts(); - void removeEntities(std::vector &entities); + void removeEntities(NifOgre::EntityList &entities); void removeIndividualPart(int type); void reserveIndividualPart(int type, int group, int priority); From db948969c98cd032915a7aae450f1d522ab48bba Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 11:14:13 -0700 Subject: [PATCH 051/126] Attach NPC parts to the proper bone --- apps/openmw/mwrender/npcanimation.cpp | 3 +- components/nifogre/ogre_nif_loader.cpp | 43 ++++++++++++++++++++++++++ components/nifogre/ogre_nif_loader.hpp | 6 ++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index b4e39ff15..991ef827e 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -341,7 +341,8 @@ void NpcAnimation::updateParts() NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) { - NifOgre::EntityList entities = NIFLoader::createEntities(mInsert, mesh); + NifOgre::EntityList entities = NIFLoader::createEntities(mEntityList.mSkelBase, bonename, + mInsert->getCreator(), mesh); std::vector &parts = entities.mEntities; for(size_t i = 0;i < parts.size();i++) parts[i]->setVisibilityFlags(RV_Actors); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9c294f8c3..44992eea4 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -915,6 +915,49 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string return entitylist; } +EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bonename, + Ogre::SceneManager *sceneMgr, + const std::string &name, + const std::string &group) +{ + EntityList entitylist; + + MeshPairList meshes = load(name, group); + if(meshes.size() == 0) + return entitylist; + + for(size_t i = 0;i < meshes.size();i++) + { + entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].first->getName())); + Ogre::Entity *entity = entitylist.mEntities.back(); + if(!entitylist.mSkelBase && entity->hasSkeleton()) + entitylist.mSkelBase = entity; + } + + if(entitylist.mSkelBase) + { + parent->attachObjectToBone(bonename, entitylist.mSkelBase); + for(size_t i = 0;i < entitylist.mEntities.size();i++) + { + Ogre::Entity *entity = entitylist.mEntities[i]; + if(entity != entitylist.mSkelBase && entity->hasSkeleton()) + { + entity->shareSkeletonInstanceWith(entitylist.mSkelBase); + parent->attachObjectToBone(bonename, entity); + } + else if(entity != entitylist.mSkelBase) + entitylist.mSkelBase->attachObjectToBone(meshes[i].second, entity); + } + } + else + { + for(size_t i = 0;i < entitylist.mEntities.size();i++) + parent->attachObjectToBone(bonename, entitylist.mEntities[i]); + } + + return entitylist; +} + /* More code currently not in use, from the old D source. This was used in the first attempt at loading NIF meshes, where each submesh diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 3f58097c0..2348a9b10 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -58,6 +58,7 @@ namespace Nif namespace NifOgre { +// FIXME: This should not be in NifOgre, it works agnostic of what model format is used struct EntityList { std::vector mEntities; Ogre::Entity *mSkelBase; @@ -89,6 +90,11 @@ class NIFLoader static MeshPairList load(const std::string &name, const std::string &group); public: + static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, + Ogre::SceneManager *sceneMgr, + const std::string &name, + const std::string &group="General"); + static EntityList createEntities(Ogre::SceneNode *parent, const std::string &name, const std::string &group="General"); From 3b29d280b91c31113cde0860722fc4484769a164 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 12:47:16 -0700 Subject: [PATCH 052/126] Filter out skinned shapes that don't match the bone name --- components/nifogre/ogre_nif_loader.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 44992eea4..d72c45abd 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -926,12 +926,23 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(meshes.size() == 0) return entitylist; + std::string filter = "Tri "+bonename; for(size_t i = 0;i < meshes.size();i++) { - entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].first->getName())); - Ogre::Entity *entity = entitylist.mEntities.back(); - if(!entitylist.mSkelBase && entity->hasSkeleton()) - entitylist.mSkelBase = entity; + Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first->getName()); + if(ent->hasSkeleton()) + { + if(meshes[i].second.length() < filter.length() || filter.compare(meshes[i].second) != 0) + { + sceneMgr->destroyEntity(ent); + meshes.erase(meshes.begin()+i); + i--; + continue; + } + if(!entitylist.mSkelBase) + entitylist.mSkelBase = ent; + } + entitylist.mEntities.push_back(ent); } if(entitylist.mSkelBase) @@ -946,7 +957,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo parent->attachObjectToBone(bonename, entity); } else if(entity != entitylist.mSkelBase) - entitylist.mSkelBase->attachObjectToBone(meshes[i].second, entity); + parent->attachObjectToBone(bonename, entity); } } else From e8ff304562ff6d87bd9781c3a6a6e6b1fd07963f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 12:53:45 -0700 Subject: [PATCH 053/126] Fix the initial normal vector for vertex fixups --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index d72c45abd..23e1e99d5 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -540,7 +540,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // better to transform the bones into bind position, but there doesn't seem to // be a reliable way to do that. std::vector newVerts(srcVerts.size(), Ogre::Vector3(0.0f)); - std::vector newNorms(srcNorms.size(), Ogre::Vector3(1.0f)); + std::vector newNorms(srcNorms.size(), Ogre::Vector3(0.0f)); const Nif::NiSkinData *data = skin->data.getPtr(); const Nif::NodeList &bones = skin->bones; From 2890904fb543c8555578fcb2e486d9812279a332 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 15:27:33 -0700 Subject: [PATCH 054/126] Use lowercase names for the mesh and skeleton resources To reduce the risk of duplicates due to different capitalizations. --- components/nifogre/ogre_nif_loader.cpp | 5 ++++- components/nifogre/ogre_nif_loader.hpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 23e1e99d5..6e2aa1663 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -807,6 +807,7 @@ public: Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); std::string fullname = mName+"@"+shape->name; + std::transform(fullname.begin(), fullname.end(), fullname.begin(), ::tolower); Ogre::MeshPtr mesh = meshMgr.getByName(fullname); if(mesh.isNull()) { @@ -842,10 +843,12 @@ public: NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; -MeshPairList NIFLoader::load(const std::string &name, const std::string &group) +MeshPairList NIFLoader::load(std::string name, const std::string &group) { MeshPairList meshes; + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + Nif::NIFFile nif(name); if (nif.numRecords() < 1) { diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 2348a9b10..b0b1ce27b 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -87,7 +87,7 @@ typedef std::vector< std::pair > MeshPairList; */ class NIFLoader { - static MeshPairList load(const std::string &name, const std::string &group); + static MeshPairList load(std::string name, const std::string &group); public: static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, From 04b244cf9e63225e69ed707d44b9a71746471a6c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 17:18:21 -0700 Subject: [PATCH 055/126] Use the mesh's skeleton to transform shapes into "bind pose" instead of the NIF nodes --- components/nifogre/ogre_nif_loader.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 6e2aa1663..9fd3d44f1 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -526,6 +526,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // Convert NiTriShape to Ogre::SubMesh void handleNiTriShape(Ogre::Mesh *mesh, Nif::NiTriShape *shape) { + Ogre::SkeletonPtr skel; const Nif::NiTriShapeData *data = shape->data.getPtr(); const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); std::vector srcVerts = data->vertices; @@ -536,6 +537,11 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // explicitly attached later. mesh->setSkeletonName(mName); + // Get the skeleton resource, so vertices can be transformed into the bones' initial state. + Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); + skel = skelMgr->getByName(mName); + skel->touch(); + // Convert vertices and normals to bone space from bind position. It would be // better to transform the bones into bind position, but there doesn't seem to // be a reliable way to do that. @@ -546,10 +552,13 @@ class NIFMeshLoader : Ogre::ManualResourceLoader const Nif::NodeList &bones = skin->bones; for(size_t b = 0;b < bones.length();b++) { - Ogre::Matrix4 mat(Ogre::Matrix4::IDENTITY); + Ogre::Bone *bone = skel->getBone(bones[b]->name); + Ogre::Matrix4 mat, mat2; mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), Ogre::Quaternion(data->bones[b].trafo.rotation)); - mat = bones[b]->getWorldTransform() * mat; + mat2.makeTransform(bone->_getDerivedPosition(), bone->_getDerivedScale(), + bone->_getDerivedOrientation()); + mat = mat2 * mat; const std::vector &weights = data->bones[b].weights; for(size_t i = 0;i < weights.size();i++) @@ -692,11 +701,6 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // Assign bone weights for this TriShape if(skin != NULL) { - // Get the skeleton resource, so weights can be applied - Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - Ogre::SkeletonPtr skel = skelMgr->getByName(mesh->getSkeletonName()); - skel->touch(); - const Nif::NiSkinData *data = skin->data.getPtr(); const Nif::NodeList &bones = skin->bones; for(size_t i = 0;i < bones.length();i++) From 626dcd54dc1da12647be1316a6010fe30e689da3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 17:26:51 -0700 Subject: [PATCH 056/126] Store the skeleton name with the mesh resource loader instead of a flag --- components/nifogre/ogre_nif_loader.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9fd3d44f1..c4e1398f9 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -509,7 +509,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader std::string mGroup; std::string mShapeName; std::string mMaterialName; - bool mHasSkel; + std::string mSkelName; void warn(const std::string &msg) { @@ -535,7 +535,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader { // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be // explicitly attached later. - mesh->setSkeletonName(mName); + mesh->setSkeletonName(mSkelName); // Get the skeleton resource, so vertices can be transformed into the bones' initial state. Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); @@ -579,7 +579,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader srcVerts = newVerts; srcNorms = newNorms; } - else if(!mHasSkel) + else if(mSkelName.length() == 0) { // No skinning and no skeleton, so just transform the vertices and // normals into position. @@ -752,10 +752,9 @@ class NIFMeshLoader : Ogre::ManualResourceLoader public: NIFMeshLoader() - : mHasSkel(false) { } - NIFMeshLoader(const std::string &name, const std::string &group, bool hasSkel) - : mName(name), mGroup(group), mHasSkel(hasSkel) + NIFMeshLoader(const std::string &name, const std::string &group, const std::string skelName) + : mName(name), mGroup(group), mSkelName(skelName) { } virtual void loadResource(Ogre::Resource *resource) @@ -765,8 +764,8 @@ public: if(!mShapeName.length()) { - if(mHasSkel) - mesh->setSkeletonName(mName); + if(mSkelName.length() > 0) + mesh->setSkeletonName(mSkelName); return; } @@ -874,7 +873,7 @@ MeshPairList NIFLoader::load(std::string name, const std::string &group) bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node); - NIFMeshLoader meshldr(name, group, hasSkel); + NIFMeshLoader meshldr(name, group, (hasSkel ? name : std::string())); meshldr.createMeshes(node, meshes); return meshes; From 5154188110d7bcf223c4c73198b370de19d556bc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 18:29:25 -0700 Subject: [PATCH 057/126] Allow specifying an alternate skeleton for mesh skinning --- components/nifogre/ogre_nif_loader.cpp | 18 +++++++++++------- components/nifogre/ogre_nif_loader.hpp | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c4e1398f9..8e73c2503 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -539,7 +539,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader // Get the skeleton resource, so vertices can be transformed into the bones' initial state. Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - skel = skelMgr->getByName(mName); + skel = skelMgr->getByName(mSkelName); skel->touch(); // Convert vertices and normals to bone space from bind position. It would be @@ -808,7 +808,9 @@ public: const NiTriShape *shape = dynamic_cast(node); Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - std::string fullname = mName+"@"+shape->name; + std::string fullname = mName+"@shape="+shape->name; + if(mSkelName.length() > 0 && mName != mSkelName) + fullname += "@skel="+mSkelName; std::transform(fullname.begin(), fullname.end(), fullname.begin(), ::tolower); Ogre::MeshPtr mesh = meshMgr.getByName(fullname); @@ -846,11 +848,12 @@ public: NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; -MeshPairList NIFLoader::load(std::string name, const std::string &group) +MeshPairList NIFLoader::load(std::string name, std::string skelName, const std::string &group) { MeshPairList meshes; std::transform(name.begin(), name.end(), name.begin(), ::tolower); + std::transform(skelName.begin(), skelName.end(), skelName.begin(), ::tolower); Nif::NIFFile nif(name); if (nif.numRecords() < 1) @@ -873,7 +876,7 @@ MeshPairList NIFLoader::load(std::string name, const std::string &group) bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node); - NIFMeshLoader meshldr(name, group, (hasSkel ? name : std::string())); + NIFMeshLoader meshldr(name, group, (hasSkel ? skelName : std::string())); meshldr.createMeshes(node, meshes); return meshes; @@ -883,7 +886,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string { EntityList entitylist; - MeshPairList meshes = load(name, group); + MeshPairList meshes = load(name, name, group); if(meshes.size() == 0) return entitylist; @@ -928,7 +931,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo { EntityList entitylist; - MeshPairList meshes = load(name, group); + MeshPairList meshes = load(name, parent->getMesh()->getSkeletonName(), group); if(meshes.size() == 0) return entitylist; @@ -953,13 +956,14 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(entitylist.mSkelBase) { + entitylist.mSkelBase->shareSkeletonInstanceWith(parent); parent->attachObjectToBone(bonename, entitylist.mSkelBase); for(size_t i = 0;i < entitylist.mEntities.size();i++) { Ogre::Entity *entity = entitylist.mEntities[i]; if(entity != entitylist.mSkelBase && entity->hasSkeleton()) { - entity->shareSkeletonInstanceWith(entitylist.mSkelBase); + entity->shareSkeletonInstanceWith(parent); parent->attachObjectToBone(bonename, entity); } else if(entity != entitylist.mSkelBase) diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index b0b1ce27b..49d19fdb8 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -87,7 +87,7 @@ typedef std::vector< std::pair > MeshPairList; */ class NIFLoader { - static MeshPairList load(std::string name, const std::string &group); + static MeshPairList load(std::string name, std::string skelName, const std::string &group); public: static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, From d9b64b77ec170935744d57db669d354c9a39dba5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 18:38:55 -0700 Subject: [PATCH 058/126] Attach skinned parts to the scene node instead of the named bone --- apps/openmw/mwrender/npcanimation.cpp | 2 +- components/nifogre/ogre_nif_loader.cpp | 7 ++++--- components/nifogre/ogre_nif_loader.hpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 991ef827e..00583d427 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -342,7 +342,7 @@ void NpcAnimation::updateParts() NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) { NifOgre::EntityList entities = NIFLoader::createEntities(mEntityList.mSkelBase, bonename, - mInsert->getCreator(), mesh); + mInsert, mesh); std::vector &parts = entities.mEntities; for(size_t i = 0;i < parts.size();i++) parts[i]->setVisibilityFlags(RV_Actors); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 8e73c2503..646ec6c0b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -925,7 +925,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string } EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bonename, - Ogre::SceneManager *sceneMgr, + Ogre::SceneNode *parentNode, const std::string &name, const std::string &group) { @@ -935,6 +935,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(meshes.size() == 0) return entitylist; + Ogre::SceneManager *sceneMgr = parentNode->getCreator(); std::string filter = "Tri "+bonename; for(size_t i = 0;i < meshes.size();i++) { @@ -957,14 +958,14 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(entitylist.mSkelBase) { entitylist.mSkelBase->shareSkeletonInstanceWith(parent); - parent->attachObjectToBone(bonename, entitylist.mSkelBase); + parentNode->attachObject(entitylist.mSkelBase); for(size_t i = 0;i < entitylist.mEntities.size();i++) { Ogre::Entity *entity = entitylist.mEntities[i]; if(entity != entitylist.mSkelBase && entity->hasSkeleton()) { entity->shareSkeletonInstanceWith(parent); - parent->attachObjectToBone(bonename, entity); + parentNode->attachObject(entity); } else if(entity != entitylist.mSkelBase) parent->attachObjectToBone(bonename, entity); diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 49d19fdb8..76e94975c 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -91,7 +91,7 @@ class NIFLoader public: static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, - Ogre::SceneManager *sceneMgr, + Ogre::SceneNode *parentNode, const std::string &name, const std::string &group="General"); From 4af1bce659722bd06c89a492bfb291f231891d06 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 20:14:23 -0700 Subject: [PATCH 059/126] Restore and fix some missing parts --- apps/openmw/mwrender/npcanimation.cpp | 16 ++++++++++++++++ apps/openmw/mwrender/npcanimation.hpp | 4 ++++ components/nifogre/ogre_nif_loader.cpp | 3 ++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 00583d427..62e9fd580 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -20,7 +20,10 @@ NpcAnimation::~NpcAnimation() removeEntities(head); removeEntities(hair); removeEntities(neck); + removeEntities(chest); removeEntities(groin); + removeEntities(rHand); + removeEntities(lHand); removeEntities(rWrist); removeEntities(lWrist); removeEntities(rForearm); @@ -37,6 +40,7 @@ NpcAnimation::~NpcAnimation() removeEntities(lUpperLeg); removeEntities(rclavicle); removeEntities(lclavicle); + removeEntities(tail); } @@ -406,8 +410,14 @@ void NpcAnimation::removeIndividualPart(int type) removeEntities(hair); else if(type == ESM::PRT_Neck) //2 removeEntities(neck); + else if(type == ESM::PRT_Cuirass)//3 + removeEntities(chest); else if(type == ESM::PRT_Groin)//4 removeEntities(groin); + else if(type == ESM::PRT_RHand)//6 + removeEntities(rHand); + else if(type == ESM::PRT_LHand)//7 + removeEntities(lHand); else if(type == ESM::PRT_RWrist)//8 removeEntities(rWrist); else if(type == ESM::PRT_LWrist) //9 @@ -446,6 +456,8 @@ void NpcAnimation::removeIndividualPart(int type) else if(type == ESM::PRT_Weapon) //25 { } + else if(type == ESM::PRT_Tail) //26 + removeEntities(tail); } void NpcAnimation::reserveIndividualPart(int type, int group, int priority) @@ -487,6 +499,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, neck = insertBoundedPart(mesh, "Neck"); break; case ESM::PRT_Cuirass: //3 + chest = insertBoundedPart(mesh, "Chest"); break; case ESM::PRT_Groin: //4 groin = insertBoundedPart(mesh, "Groin"); @@ -494,8 +507,10 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, case ESM::PRT_Skirt: //5 break; case ESM::PRT_RHand: //6 + rHand = insertBoundedPart(mesh, "Right Hand"); break; case ESM::PRT_LHand: //7 + lHand = insertBoundedPart(mesh, "Left Hand"); break; case ESM::PRT_RWrist: //8 rWrist = insertBoundedPart(mesh, "Right Wrist"); @@ -550,6 +565,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, case ESM::PRT_Weapon: //25 break; case ESM::PRT_Tail: //26 + tail = insertBoundedPart(mesh, "Tail"); break; } return true; diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 1eec1294f..9dda169e2 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -38,7 +38,11 @@ private: NifOgre::EntityList lfoot; NifOgre::EntityList rfoot; NifOgre::EntityList hair; + NifOgre::EntityList rHand; + NifOgre::EntityList lHand; NifOgre::EntityList head; + NifOgre::EntityList chest; + NifOgre::EntityList tail; bool isBeast; bool isFemale; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 646ec6c0b..e8bc6133a 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -942,7 +942,8 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first->getName()); if(ent->hasSkeleton()) { - if(meshes[i].second.length() < filter.length() || filter.compare(meshes[i].second) != 0) + if(meshes[i].second.length() < filter.length() || + meshes[i].second.compare(0, filter.length(), filter) != 0) { sceneMgr->destroyEntity(ent); meshes.erase(meshes.begin()+i); From bd74ab027a16801da7db778f62c9f4a898517cda Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 21:21:49 -0700 Subject: [PATCH 060/126] Mirror left-sided parts --- components/nifogre/ogre_nif_loader.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index e8bc6133a..c470363b0 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -956,6 +957,10 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo entitylist.mEntities.push_back(ent); } + Ogre::Vector3 scale(1.0f); + if(bonename.find("Left") != std::string::npos) + scale.x *= -1.0f; + if(entitylist.mSkelBase) { entitylist.mSkelBase->shareSkeletonInstanceWith(parent); @@ -969,13 +974,19 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo parentNode->attachObject(entity); } else if(entity != entitylist.mSkelBase) - parent->attachObjectToBone(bonename, entity); + { + Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entity); + tag->setScale(scale); + } } } else { for(size_t i = 0;i < entitylist.mEntities.size();i++) - parent->attachObjectToBone(bonename, entitylist.mEntities[i]); + { + Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entitylist.mEntities[i]); + tag->setScale(scale); + } } return entitylist; From b505d4ace0977522aab257b86caca4cad1d320af Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 21:39:50 -0700 Subject: [PATCH 061/126] Fix feet and entity part detachment --- apps/openmw/mwrender/npcanimation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 62e9fd580..138a8eb86 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -391,7 +391,7 @@ void NpcAnimation::removeEntities(NifOgre::EntityList &entities) Ogre::SceneManager *sceneMgr = mInsert->getCreator(); for(size_t i = 0;i < entities.mEntities.size();i++) { - mEntityList.mSkelBase->detachObjectFromBone(entities.mEntities[i]); + entities.mEntities[i]->detachFromParent(); sceneMgr->destroyEntity(entities.mEntities[i]); } entities.mEntities.clear(); @@ -533,10 +533,10 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, lupperArm = insertBoundedPart(mesh, "Left Upper Arm"); break; case ESM::PRT_RFoot: //15 - lupperArm = insertBoundedPart(mesh, "Right Foot"); + rfoot = insertBoundedPart(mesh, "Right Foot"); break; case ESM::PRT_LFoot: //16 - lupperArm = insertBoundedPart(mesh, "Left Foot"); + lfoot = insertBoundedPart(mesh, "Left Foot"); break; case ESM::PRT_RAnkle: //17 rAnkle = insertBoundedPart(mesh, "Right Ankle"); From c9b1f72d81b00f9e809b278885795d5300557a16 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 22:31:07 -0700 Subject: [PATCH 062/126] Use a case-insensitive compare for the part filter --- components/nifogre/ogre_nif_loader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c470363b0..639ebaa12 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -944,7 +944,8 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(ent->hasSkeleton()) { if(meshes[i].second.length() < filter.length() || - meshes[i].second.compare(0, filter.length(), filter) != 0) + !boost::algorithm::lexicographical_compare(meshes[i].second.substr(0, filter.length()), + filter, boost::algorithm::is_iequal())) { sceneMgr->destroyEntity(ent); meshes.erase(meshes.begin()+i); From 6caa39629d85f22320eff0abd5def679a043a0c4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 18 Jul 2012 22:32:26 -0700 Subject: [PATCH 063/126] Reimplement the skirt part --- apps/openmw/mwrender/npcanimation.cpp | 4 ++++ apps/openmw/mwrender/npcanimation.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 138a8eb86..9f28dbf13 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -22,6 +22,7 @@ NpcAnimation::~NpcAnimation() removeEntities(neck); removeEntities(chest); removeEntities(groin); + removeEntities(skirt); removeEntities(rHand); removeEntities(lHand); removeEntities(rWrist); @@ -414,6 +415,8 @@ void NpcAnimation::removeIndividualPart(int type) removeEntities(chest); else if(type == ESM::PRT_Groin)//4 removeEntities(groin); + else if(type == ESM::PRT_Skirt)//5 + removeEntities(skirt); else if(type == ESM::PRT_RHand)//6 removeEntities(rHand); else if(type == ESM::PRT_LHand)//7 @@ -505,6 +508,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, groin = insertBoundedPart(mesh, "Groin"); break; case ESM::PRT_Skirt: //5 + skirt = insertBoundedPart(mesh, "Groin"); break; case ESM::PRT_RHand: //6 rHand = insertBoundedPart(mesh, "Right Hand"); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 9dda169e2..d4b2a5b9e 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -35,6 +35,7 @@ private: NifOgre::EntityList rAnkle; NifOgre::EntityList lAnkle; NifOgre::EntityList groin; + NifOgre::EntityList skirt; NifOgre::EntityList lfoot; NifOgre::EntityList rfoot; NifOgre::EntityList hair; From a86ed46ec495329b5fafc08e5893bdaa43afac2b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 11:00:26 -0700 Subject: [PATCH 064/126] Use the race ID specified in the ref base's record instead of the race record The latter is localized and doesn't match with international versions. --- apps/openmw/mwrender/npcanimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 9f28dbf13..a693a6b46 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -74,7 +74,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere isFemale = !!(ref->base->flags&ESM::NPC::Female); isBeast = !!(race->data.flags&ESM::Race::Beast); - bodyRaceID = "b_n_"+race->name; + bodyRaceID = "b_n_"+ref->base->race; std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); /*std::cout << "Race: " << ref->base->race ; From e7602199530baab8c74664af037ff71564b24733 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 11:36:36 -0700 Subject: [PATCH 065/126] Use a unique loader for each skeleton resource --- components/nifogre/ogre_nif_loader.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 639ebaa12..66b711737 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -130,7 +130,7 @@ public: }; -struct NIFSkeletonLoader : public Ogre::ManualResourceLoader { +class NIFSkeletonLoader : public Ogre::ManualResourceLoader { static void warn(const std::string &msg) { @@ -171,6 +171,11 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent= } } + +typedef std::map LoaderMap; +static LoaderMap sLoaders; + +public: void loadResource(Ogre::Resource *resource) { Ogre::Skeleton *skel = dynamic_cast(resource); @@ -181,7 +186,7 @@ void loadResource(Ogre::Resource *resource) buildBones(skel, node); } -static bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) +bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) { if(node->boneTrafo != NULL) { @@ -190,8 +195,8 @@ static bool createSkeleton(const std::string &name, const std::string &group, Ni Ogre::SkeletonPtr skel = skelMgr.getByName(name); if(skel.isNull()) { - static NIFSkeletonLoader loader; - skel = skelMgr.create(name, group, true, &loader); + NIFSkeletonLoader *loader = &sLoaders[name]; + skel = skelMgr.create(name, group, true, loader); } return true; @@ -214,6 +219,7 @@ static bool createSkeleton(const std::string &name, const std::string &group, Ni } }; +NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders; // Conversion of blend / test mode from NIF -> OGRE. @@ -875,7 +881,8 @@ MeshPairList NIFLoader::load(std::string name, std::string skelName, const std:: return meshes; } - bool hasSkel = NIFSkeletonLoader::createSkeleton(name, group, node); + NIFSkeletonLoader skelldr; + bool hasSkel = skelldr.createSkeleton(name, group, node); NIFMeshLoader meshldr(name, group, (hasSkel ? skelName : std::string())); meshldr.createMeshes(node, meshes); From f6c837468f1c250d75f2dba1a2fc297c518899fc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 11:44:08 -0700 Subject: [PATCH 066/126] Load the proper NIF skeleton --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 66b711737..8795efbdf 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -882,7 +882,7 @@ MeshPairList NIFLoader::load(std::string name, std::string skelName, const std:: } NIFSkeletonLoader skelldr; - bool hasSkel = skelldr.createSkeleton(name, group, node); + bool hasSkel = skelldr.createSkeleton(skelName, group, node); NIFMeshLoader meshldr(name, group, (hasSkel ? skelName : std::string())); meshldr.createMeshes(node, meshes); From c2acf47d880d2adfd20a9f6b3eca680a2ec0e31b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 20:30:10 -0700 Subject: [PATCH 067/126] Store the list of keyframe controllers when building the bones --- components/nifogre/ogre_nif_loader.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 8795efbdf..8ba5c9752 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -144,7 +144,7 @@ static void fail(const std::string &msg) } -void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent=NULL) +void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector &ctrls, Ogre::Bone *parent=NULL) { Ogre::Bone *bone; if(!skel->hasBone(node->name)) @@ -159,6 +159,14 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent= bone->setBindingPose(); bone->setInitialState(); + Nif::ControllerPtr ctrl = node->controller; + while(!ctrl.empty()) + { + if(ctrl->recType == Nif::RC_NiKeyframeController) + ctrls.push_back(static_cast(ctrl.getPtr())); + ctrl = ctrl->next; + } + const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { @@ -166,7 +174,7 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent= for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - buildBones(skel, children[i].getPtr(), bone); + buildBones(skel, children[i].getPtr(), ctrls, bone); } } } @@ -183,7 +191,13 @@ void loadResource(Ogre::Resource *resource) Nif::NIFFile nif(skel->getName()); const Nif::Node *node = dynamic_cast(nif.getRecord(0)); - buildBones(skel, node); + + std::vector ctrls; + buildBones(skel, node, ctrls); + + // TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file + if(ctrls.size() == 0) // No animations? Then we're done. + return; } bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) From 0986cd5962d8dfa3279d761d7352ee441e11ae61 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 20:48:12 -0700 Subject: [PATCH 068/126] Get the animation controller target names --- components/nifogre/ogre_nif_loader.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 8ba5c9752..8cdb2e99b 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -195,9 +195,27 @@ void loadResource(Ogre::Resource *resource) std::vector ctrls; buildBones(skel, node, ctrls); + std::vector targets; // TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file if(ctrls.size() == 0) // No animations? Then we're done. return; + + float maxtime = 0.0f; + for(size_t i = 0;i < ctrls.size();i++) + { + Nif::NiKeyframeController *ctrl = ctrls[i]; + maxtime = std::max(maxtime, ctrl->timeStop); + Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); + if(target != NULL) + targets.push_back(target->name); + } + + if(targets.size() != ctrls.size()) + { + warn("Target size mismatch ("+Ogre::StringConverter::toString(targets.size())+" targets, "+ + Ogre::StringConverter::toString(ctrls.size())+" controllers)"); + return; + } } bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) From 4210880c061ea7698e0a96cd0ef7292b55a06c14 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 21:46:16 -0700 Subject: [PATCH 069/126] Load the animation tracks into Ogre --- components/nifogre/ogre_nif_loader.cpp | 97 ++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 8cdb2e99b..eea53e963 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -180,6 +180,15 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector vectors */ +template +struct KeyTimeSort +{ + bool operator()(const Nif::KeyT &lhs, const Nif::KeyT &rhs) const + { return lhs.mTime < rhs.mTime; } +}; + + typedef std::map LoaderMap; static LoaderMap sLoaders; @@ -216,6 +225,94 @@ void loadResource(Ogre::Resource *resource) Ogre::StringConverter::toString(ctrls.size())+" controllers)"); return; } + + Ogre::Animation *anim = skel->createAnimation("default", maxtime); + /* HACK: Pre-create the node tracks by matching the track IDs with the + * bone IDs. Otherwise, Ogre animates the wrong bones. */ + size_t bonecount = skel->getNumBones(); + for(size_t i = 0;i < bonecount;i++) + anim->createNodeTrack(i, skel->getBone(i)); + + for(size_t i = 0;i < ctrls.size();i++) + { + Nif::NiKeyframeController *kfc = ctrls[i]; + Nif::NiKeyframeData *kf = kfc->data.getPtr(); + + /* Get the keyframes and make sure they're sorted first to last */ + QuaternionKeyList quatkeys = kf->mRotations; + Vector3KeyList trankeys = kf->mTranslations; + FloatKeyList scalekeys = kf->mScales; + std::sort(quatkeys.mKeys.begin(), quatkeys.mKeys.end(), KeyTimeSort()); + std::sort(trankeys.mKeys.begin(), trankeys.mKeys.end(), KeyTimeSort()); + std::sort(scalekeys.mKeys.begin(), scalekeys.mKeys.end(), KeyTimeSort()); + + QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin(); + Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin(); + FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin(); + + Ogre::Bone *bone = skel->getBone(targets[i]); + const Ogre::Quaternion startquat = bone->getInitialOrientation(); + const Ogre::Vector3 starttrans = bone->getInitialPosition(); + const Ogre::Vector3 startscale = bone->getInitialScale(); + Ogre::NodeAnimationTrack *nodetrack = anim->getNodeTrack(bone->getHandle()); + + Ogre::Quaternion lastquat, curquat; + Ogre::Vector3 lasttrans(0.0f), curtrans(0.0f); + Ogre::Vector3 lastscale(1.0f), curscale(1.0f); + if(quatiter != quatkeys.mKeys.end()) + lastquat = curquat = startquat.Inverse() * quatiter->mValue; + if(traniter != trankeys.mKeys.end()) + lasttrans = curtrans = traniter->mValue - starttrans; + if(scaleiter != scalekeys.mKeys.end()) + lastscale = curscale = Ogre::Vector3(scaleiter->mValue) / startscale; + bool didlast = false; + while(!didlast) + { + float curtime = kfc->timeStop; + if(quatiter != quatkeys.mKeys.end()) + curtime = std::min(curtime, quatiter->mTime); + if(traniter != trankeys.mKeys.end()) + curtime = std::min(curtime, traniter->mTime); + if(scaleiter != scalekeys.mKeys.end()) + curtime = std::min(curtime, scaleiter->mTime); + + curtime = std::max(curtime, kfc->timeStart); + if(curtime >= kfc->timeStop) + { + didlast = true; + curtime = kfc->timeStop; + } + + // Get the latest quaternion, translation, and scale for the + // current time + while(quatiter != quatkeys.mKeys.end() && curtime >= quatiter->mTime) + { + lastquat = curquat; + curquat = startquat.Inverse() * quatiter->mValue; + quatiter++; + } + while(traniter != trankeys.mKeys.end() && curtime >= traniter->mTime) + { + lasttrans = curtrans; + curtrans = traniter->mValue - starttrans; + traniter++; + } + while(scaleiter != scalekeys.mKeys.end() && curtime >= scaleiter->mTime) + { + lastscale = curscale; + curscale = Ogre::Vector3(scaleiter->mValue) / startscale; + scaleiter++; + } + + Ogre::TransformKeyFrame *kframe; + kframe = nodetrack->createNodeKeyFrame(curtime); + // FIXME: These should be interpolated since they don't all fall on the same time + kframe->setRotation(curquat); + kframe->setTranslate(curtrans); + kframe->setScale(curscale); + } + } + anim->optimise(); } bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) From 8b5b74f9ee3ec4b291e87d92fb01bfd78b177638 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Jul 2012 22:34:26 -0700 Subject: [PATCH 070/126] Add a quick hack to let "playgroup all" work on creatures and NPCs --- apps/openmw/mwrender/creatureanimation.cpp | 42 +++++++++++++++------- apps/openmw/mwrender/npcanimation.cpp | 42 +++++++++++++++------- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index fd2855154..492749553 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -52,6 +52,18 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O } ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } + + if(mEntityList.mSkelBase) + { + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + state->setEnabled(true); + state->setLoop(false); + } + } } } @@ -59,20 +71,26 @@ void CreatureAnimation::runAnimation(float timepassed) { if(mAnimate > 0) { - //Add the amount of time passed to time - - //Handle the animation transforms dependent on time - - //Handle the shapes dependent on animation transforms mTime += timepassed; - if(mTime >= mStopTime) + + if(mEntityList.mSkelBase) { - mAnimate--; - //std::cout << "Stopping the animation\n"; - if(mAnimate == 0) - mTime = mStopTime; - else - mTime = mStartTime + (mTime - mStopTime); + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + state->setTimePosition(mTime); + if(state->getTimePosition() >= state->getLength()) + { + mAnimate--; + //std::cout << "Stopping the animation\n"; + if(mAnimate == 0) + mTime = state->getLength(); + else + mTime = mTime - state->getLength(); + } + } } handleAnimationTransforms(); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a693a6b46..8c34acba2 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -117,6 +117,18 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere //stay in the same place when we skipanim, or open a gui window } + if(mEntityList.mSkelBase) + { + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + state->setEnabled(true); + state->setLoop(false); + } + } + if(isFemale) mInsert->scale(race->data.height.female, race->data.height.female, race->data.height.female); else @@ -361,24 +373,30 @@ void NpcAnimation::runAnimation(float timepassed) timeToChange = 0; updateParts(); } - timeToChange += timepassed; - //1. Add the amount of time passed to time - - //2. Handle the animation transforms dependent on time - - //3. Handle the shapes dependent on animation transforms if(mAnimate > 0) { mTime += timepassed; - if(mTime > mStopTime) + + if(mEntityList.mSkelBase) { - mAnimate--; - if(mAnimate == 0) - mTime = mStopTime; - else - mTime = mStartTime + (mTime - mStopTime); + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + state->setTimePosition(mTime); + if(state->getTimePosition() >= state->getLength()) + { + mAnimate--; + //std::cout << "Stopping the animation\n"; + if(mAnimate == 0) + mTime = state->getLength(); + else + mTime = mTime - state->getLength(); + } + } } handleAnimationTransforms(); From 66860825cfd4cc74154eb9fb147ed3e73506211c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 20 Jul 2012 00:29:22 -0700 Subject: [PATCH 071/126] Remove some unused and unneeded bits from the Animation class --- apps/openmw/mwrender/animation.cpp | 137 +-------------------- apps/openmw/mwrender/animation.hpp | 14 --- apps/openmw/mwrender/creatureanimation.cpp | 2 - apps/openmw/mwrender/npcanimation.cpp | 2 - 4 files changed, 1 insertion(+), 154 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index fddfe7b8a..06fd34e3c 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -15,15 +15,7 @@ Animation::Animation(OEngine::Render::OgreRenderer& _rend) : mInsert(NULL) , mRend(_rend) , mTime(0.0f) - , mStartTime(0.0f) - , mStopTime(0.0f) , mAnimate(0) - , mRindexI() - , mTindexI() - , mShapeNumber(0) - , mShapeIndexI() - , mTransformations(NULL) - , mTextmappings(NULL) { } @@ -37,79 +29,11 @@ Animation::~Animation() void Animation::startScript(std::string groupname, int mode, int loops) { - //If groupname is recognized set animate to true - //Set the start time and stop time - //How many times to loop if(groupname == "all") { mAnimate = loops; - mTime = mStartTime; + mTime = 0.0f; } - else if(mTextmappings) - { - std::string startName = groupname + ": loop start"; - std::string stopName = groupname + ": loop stop"; - - bool first = false; - - if(loops > 1) - { - startName = groupname + ": loop start"; - stopName = groupname + ": loop stop"; - - for(std::map::iterator iter = mTextmappings->begin(); iter != mTextmappings->end(); iter++) - { - std::string current = iter->first.substr(0, startName.size()); - std::transform(current.begin(), current.end(), current.begin(), ::tolower); - std::string current2 = iter->first.substr(0, stopName.size()); - std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); - - if(current == startName) - { - mStartTime = iter->second; - mAnimate = loops; - mTime = mStartTime; - first = true; - } - if(current2 == stopName) - { - mStopTime = iter->second; - if(first) - break; - } - } - } - - if(!first) - { - startName = groupname + ": start"; - stopName = groupname + ": stop"; - - for(std::map::iterator iter = mTextmappings->begin(); iter != mTextmappings->end(); iter++) - { - std::string current = iter->first.substr(0, startName.size()); - std::transform(current.begin(), current.end(), current.begin(), ::tolower); - std::string current2 = iter->first.substr(0, stopName.size()); - std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); - - if(current == startName) - { - mStartTime = iter->second; - mAnimate = loops; - mTime = mStartTime; - first = true; - } - if(current2 == stopName) - { - mStopTime = iter->second; - if(first) - break; - } - } - } - - } - } @@ -118,63 +42,4 @@ void Animation::stopScript() mAnimate = 0; } - -bool Animation::timeIndex(float time, const std::vector ×, int &i, int &j, float &x) -{ - size_t count; - if((count=times.size()) == 0) - return false; - - if(time <= times[0]) - { - i = j = 0; - x = 0.0; - return true; - } - if(time >= times[count-1]) - { - i = j = count - 1; - x = 0.0; - return true; - } - - if(i < 0 || (size_t)i >= count) - i = 0; - - float tI = times[i]; - if(time > tI) - { - j = i + 1; - float tJ; - while(time >= (tJ=times[j])) - { - i = j++; - tI = tJ; - } - x = (time-tI) / (tJ-tI); - return true; - } - - if(time < tI) - { - j = i - 1; - float tJ; - while(time <= (tJ=times[j])) - { - i = j--; - tI = tJ; - } - x = (time-tI) / (tJ-tI); - return true; - } - - j = i; - x = 0.0; - return true; -} - -void Animation::handleAnimationTransforms() -{ -} - } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index def7f226c..bed02f85f 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -26,23 +26,9 @@ protected: static std::map sUniqueIDs; float mTime; - float mStartTime; - float mStopTime; int mAnimate; - //Represents a rotation index for each bone - std::vectormRindexI; - //Represents a translation index for each bone - std::vectormTindexI; - //Only shapes with morphing data will use a shape number - int mShapeNumber; - std::vector > mShapeIndexI; - - std::vector* mTransformations; - std::map* mTextmappings; NifOgre::EntityList mEntityList; - void handleAnimationTransforms(); - bool timeIndex( float time, const std::vector & times, int & i, int & j, float & x ); public: Animation(OEngine::Render::OgreRenderer& _rend); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 492749553..ee1fd45ba 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -92,8 +92,6 @@ void CreatureAnimation::runAnimation(float timepassed) } } } - - handleAnimationTransforms(); } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 8c34acba2..4d2ca557d 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -398,8 +398,6 @@ void NpcAnimation::runAnimation(float timepassed) } } } - - handleAnimationTransforms(); } } From 2db80a1504576d15df11b9988fb5beabf3f4bf8e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 20 Jul 2012 00:53:12 -0700 Subject: [PATCH 072/126] Rename a couple methods to match their scripting counterparts --- apps/openmw/mwrender/actors.cpp | 8 +++----- apps/openmw/mwrender/animation.cpp | 4 ++-- apps/openmw/mwrender/animation.hpp | 8 ++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index b37921b0c..a64397d49 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -122,15 +122,13 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store){ void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){ if(mAllActors.find(ptr) != mAllActors.end()) - mAllActors[ptr]->startScript(groupName, mode, number); + mAllActors[ptr]->playGroup(groupName, mode, number); } void Actors::skipAnimation (const MWWorld::Ptr& ptr){ if(mAllActors.find(ptr) != mAllActors.end()) - mAllActors[ptr]->stopScript(); + mAllActors[ptr]->skipAnim(); } void Actors::update (float duration){ for(std::map::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) - { - (iter->second)->runAnimation(duration); - } + iter->second->runAnimation(duration); } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 06fd34e3c..1f0a99518 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -27,7 +27,7 @@ Animation::~Animation() mEntityList.mEntities.clear(); } -void Animation::startScript(std::string groupname, int mode, int loops) +void Animation::playGroup(std::string groupname, int mode, int loops) { if(groupname == "all") { @@ -37,7 +37,7 @@ void Animation::startScript(std::string groupname, int mode, int loops) } -void Animation::stopScript() +void Animation::skipAnim() { mAnimate = 0; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index bed02f85f..0ed4545f2 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -32,11 +32,11 @@ protected: public: Animation(OEngine::Render::OgreRenderer& _rend); - virtual void runAnimation(float timepassed) = 0; - void startScript(std::string groupname, int mode, int loops); - void stopScript(); - virtual ~Animation(); + + void playGroup(std::string groupname, int mode, int loops); + void skipAnim(); + virtual void runAnimation(float timepassed) = 0; }; } From 4bc93ecd1a9c851e5bff3d3670f0dd74e7d61201 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 20 Jul 2012 11:09:05 -0700 Subject: [PATCH 073/126] Use the skeleton name for the main animation --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index eea53e963..2aa7cd433 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -226,7 +226,7 @@ void loadResource(Ogre::Resource *resource) return; } - Ogre::Animation *anim = skel->createAnimation("default", maxtime); + Ogre::Animation *anim = skel->createAnimation(skel->getName(), maxtime); /* HACK: Pre-create the node tracks by matching the track IDs with the * bone IDs. Otherwise, Ogre animates the wrong bones. */ size_t bonecount = skel->getNumBones(); From fcaa8aae06d791c37daab0897f4fd19f6b2129b5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 11:26:09 -0700 Subject: [PATCH 074/126] Don't skip animation state updates for NPCs --- apps/openmw/mwrender/npcanimation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 4d2ca557d..f66ab8403 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -113,8 +113,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere } } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones - //stay in the same place when we skipanim, or open a gui window } if(mEntityList.mSkelBase) From 81ce8dbe122db57110a32996975356bb057e0e91 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 14:41:26 -0700 Subject: [PATCH 075/126] Combine animation handling into the base class --- apps/openmw/mwrender/animation.cpp | 29 ++++++++++++++++++++++ apps/openmw/mwrender/animation.hpp | 2 +- apps/openmw/mwrender/creatureanimation.cpp | 25 ++----------------- apps/openmw/mwrender/npcanimation.cpp | 25 +------------------ 4 files changed, 33 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 1f0a99518..88f6cebe6 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -42,4 +42,33 @@ void Animation::skipAnim() mAnimate = 0; } +void Animation::runAnimation(float timepassed) +{ + if(mAnimate != 0) + { + mTime += timepassed; + + if(mEntityList.mSkelBase) + { + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + state->setTimePosition(mTime); + if(mTime >= state->getLength()) + { + if(mAnimate != -1) + mAnimate--; + //std::cout << "Stopping the animation\n"; + if(mAnimate == 0) + mTime = state->getLength(); + else + mTime = mTime - state->getLength(); + } + } + } + } +} + } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 0ed4545f2..5de314df1 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -36,7 +36,7 @@ public: void playGroup(std::string groupname, int mode, int loops); void skipAnim(); - virtual void runAnimation(float timepassed) = 0; + virtual void runAnimation(float timepassed); }; } diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index ee1fd45ba..9d2a58a1e 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -69,30 +69,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O void CreatureAnimation::runAnimation(float timepassed) { - if(mAnimate > 0) - { - mTime += timepassed; + // Placeholder - if(mEntityList.mSkelBase) - { - Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); - Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); - while(as.hasMoreElements()) - { - Ogre::AnimationState *state = as.getNext(); - state->setTimePosition(mTime); - if(state->getTimePosition() >= state->getLength()) - { - mAnimate--; - //std::cout << "Stopping the animation\n"; - if(mAnimate == 0) - mTime = state->getLength(); - else - mTime = mTime - state->getLength(); - } - } - } - } + Animation::runAnimation(timepassed); } } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index f66ab8403..3cca110e3 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -373,30 +373,7 @@ void NpcAnimation::runAnimation(float timepassed) } timeToChange += timepassed; - if(mAnimate > 0) - { - mTime += timepassed; - - if(mEntityList.mSkelBase) - { - Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); - Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); - while(as.hasMoreElements()) - { - Ogre::AnimationState *state = as.getNext(); - state->setTimePosition(mTime); - if(state->getTimePosition() >= state->getLength()) - { - mAnimate--; - //std::cout << "Stopping the animation\n"; - if(mAnimate == 0) - mTime = state->getLength(); - else - mTime = mTime - state->getLength(); - } - } - } - } + Animation::runAnimation(timepassed); } void NpcAnimation::removeEntities(NifOgre::EntityList &entities) From c5b9098517714827d575166de0163aaed26e1398 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 17:09:16 -0700 Subject: [PATCH 076/126] Remove an unused field from EntityList --- apps/openmw/mwrender/npcanimation.cpp | 1 - components/nifogre/ogre_nif_loader.cpp | 1 - components/nifogre/ogre_nif_loader.hpp | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 3cca110e3..e89122e4b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -388,7 +388,6 @@ void NpcAnimation::removeEntities(NifOgre::EntityList &entities) } entities.mEntities.clear(); entities.mSkelBase = NULL; - entities.mRootNode = NULL; } void NpcAnimation::removeIndividualPart(int type) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 2aa7cd433..2c5b7e324 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1027,7 +1027,6 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string if(meshes.size() == 0) return entitylist; - entitylist.mRootNode = parent; Ogre::SceneManager *sceneMgr = parent->getCreator(); for(size_t i = 0;i < meshes.size();i++) { diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 76e94975c..a9195f2fb 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -62,9 +62,8 @@ namespace NifOgre struct EntityList { std::vector mEntities; Ogre::Entity *mSkelBase; - Ogre::SceneNode *mRootNode; - EntityList() : mSkelBase(0), mRootNode(0) + EntityList() : mSkelBase(0) { } }; From e81fc42daaf0adc5ae296b7781aea4270f299b9d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 17:12:41 -0700 Subject: [PATCH 077/126] Remove the beast-race special cases from updateParts The special handling should happen at a much lower level, and prevent the objects from being equipped in the first place. --- apps/openmw/mwrender/npcanimation.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index e89122e4b..415de5859 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -149,7 +149,7 @@ void NpcAnimation::updateParts() { &greaves, MWWorld::InventoryStore::Slot_Greaves }, { &leftpauldron, MWWorld::InventoryStore::Slot_LeftPauldron }, { &rightpauldron, MWWorld::InventoryStore::Slot_RightPauldron }, - { &boots, MWWorld::InventoryStore::Slot_Boots }, // !isBeast + { &boots, MWWorld::InventoryStore::Slot_Boots }, { &leftglove, MWWorld::InventoryStore::Slot_LeftGauntlet }, { &rightglove, MWWorld::InventoryStore::Slot_RightGauntlet }, { &shirt, MWWorld::InventoryStore::Slot_Shirt }, @@ -157,9 +157,6 @@ void NpcAnimation::updateParts() }; for(size_t i = 0;i < sizeof(slotlist)/sizeof(slotlist[0]);i++) { - if(slotlist[i].iter == &boots && isBeast) - continue; - MWWorld::ContainerStoreIterator iter = mInv.getSlot(slotlist[i].slot); if(*slotlist[i].iter != iter) { @@ -235,7 +232,7 @@ void NpcAnimation::updateParts() std::vector parts = armor->parts.parts; addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); } - if(!isBeast && boots != mInv.end()) + if(boots != mInv.end()) { if(boots->getTypeName() == typeid(ESM::Clothing).name()) { From 77446a0d58fde458f1ba01788f2854e1e2b1b558 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 17:39:57 -0700 Subject: [PATCH 078/126] Fix skipAnim, only skip one animation update --- apps/openmw/mwrender/animation.cpp | 6 ++++-- apps/openmw/mwrender/animation.hpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 88f6cebe6..653a506e8 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -16,6 +16,7 @@ Animation::Animation(OEngine::Render::OgreRenderer& _rend) , mRend(_rend) , mTime(0.0f) , mAnimate(0) + , mSkipFrame(false) { } @@ -39,12 +40,12 @@ void Animation::playGroup(std::string groupname, int mode, int loops) void Animation::skipAnim() { - mAnimate = 0; + mSkipFrame = true; } void Animation::runAnimation(float timepassed) { - if(mAnimate != 0) + if(mAnimate != 0 && !mSkipFrame) { mTime += timepassed; @@ -69,6 +70,7 @@ void Animation::runAnimation(float timepassed) } } } + mSkipFrame = false; } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 5de314df1..ae1477666 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -27,6 +27,7 @@ protected: float mTime; int mAnimate; + bool mSkipFrame; NifOgre::EntityList mEntityList; From d8cb6855437813e1145f213c3cb83f43b0580923 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 18:03:01 -0700 Subject: [PATCH 079/126] Interpolate keyframes when creating them Probably not fully correct, but better than nothing. --- components/nifogre/ogre_nif_loader.cpp | 28 ++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 2c5b7e324..e695cd959 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -306,10 +306,30 @@ void loadResource(Ogre::Resource *resource) Ogre::TransformKeyFrame *kframe; kframe = nodetrack->createNodeKeyFrame(curtime); - // FIXME: These should be interpolated since they don't all fall on the same time - kframe->setRotation(curquat); - kframe->setTranslate(curtrans); - kframe->setScale(curscale); + if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin()) + kframe->setRotation(curquat); + else + { + QuaternionKeyList::VecType::const_iterator last = quatiter-1; + float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime); + kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat)); + } + if(traniter == trankeys.mKeys.end() || traniter == trankeys.mKeys.begin()) + kframe->setTranslate(curtrans); + else + { + Vector3KeyList::VecType::const_iterator last = traniter-1; + float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime); + kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff)); + } + if(scaleiter == scalekeys.mKeys.end() || scaleiter == scalekeys.mKeys.begin()) + kframe->setScale(curscale); + else + { + FloatKeyList::VecType::const_iterator last = scaleiter-1; + float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime); + kframe->setScale(lastscale + ((curscale-lastscale)*diff)); + } } } anim->optimise(); From 4035d7370e5288898d1e590030b1aa4f853bad28 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Jul 2012 22:04:05 -0700 Subject: [PATCH 080/126] Fix name/filter comparison --- components/nifogre/ogre_nif_loader.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index e695cd959..c34f69404 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -25,6 +25,8 @@ #include "ogre_nif_loader.hpp" +#include + #include #include #include @@ -1080,6 +1082,11 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string return entitylist; } +static bool checklow(const char &a, const char &b) +{ + return ::tolower(a) == ::tolower(b); +} + EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bonename, Ogre::SceneNode *parentNode, const std::string &name, @@ -1099,8 +1106,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(ent->hasSkeleton()) { if(meshes[i].second.length() < filter.length() || - !boost::algorithm::lexicographical_compare(meshes[i].second.substr(0, filter.length()), - filter, boost::algorithm::is_iequal())) + std::mismatch(filter.begin(), filter.end(), meshes[i].second.begin(), checklow).first != filter.end()) { sceneMgr->destroyEntity(ent); meshes.erase(meshes.begin()+i); From 1fef0860887fd41a1b775efb9f7f278f9b30fd3f Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 23 Jul 2012 15:36:12 +0200 Subject: [PATCH 081/126] Revert "Merge remote-tracking branch 'mark76/multiple_esm_esp' into nif-cleanup" This reverts commit 546b640022e3ec111b5c795c3fc1d067c3b1a684, reversing changes made to fcaa8aae06d791c37daab0897f4fd19f6b2129b5. --- apps/openmw/engine.cpp | 30 +++++-------------- apps/openmw/engine.hpp | 8 ++--- apps/openmw/main.cpp | 28 ++++++++--------- apps/openmw/mwrender/terrain.cpp | 24 ++++----------- apps/openmw/mwrender/terrain.hpp | 5 +--- apps/openmw/mwworld/worldimp.cpp | 32 +++++--------------- apps/openmw/mwworld/worldimp.hpp | 3 +- components/esm/esm_reader.hpp | 8 ----- components/esm/loadland.cpp | 1 - components/esm/loadland.hpp | 1 - components/esm_store/reclists.hpp | 50 +++++++------------------------ components/esm_store/store.cpp | 7 ----- 12 files changed, 48 insertions(+), 149 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f41d453b5..ab5b63071 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -207,32 +207,18 @@ void OMW::Engine::setCell (const std::string& cellName) // Set master file (esm) // - If the given name does not have an extension, ".esm" is added automatically +// - Currently OpenMW only supports one master at the same time. void OMW::Engine::addMaster (const std::string& master) { - mMaster.push_back(master); - std::string &str = mMaster.back(); + assert (mMaster.empty()); + mMaster = master; - // Append .esm if not already there - std::string::size_type sep = str.find_last_of ("."); + // Append .esm if not already there + std::string::size_type sep = mMaster.find_last_of ("."); if (sep == std::string::npos) { - str += ".esm"; - } -} - -// Add plugin file (esp) - -void OMW::Engine::addPlugin (const std::string& plugin) -{ - mPlugins.push_back(plugin); - std::string &str = mPlugins.back(); - - // Append .esp if not already there - std::string::size_type sep = str.find_last_of ("."); - if (sep == std::string::npos) - { - str += ".esp"; + mMaster += ".esm"; } } @@ -333,8 +319,8 @@ void OMW::Engine::go() MWGui::CursorReplace replacer; // Create the world - mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins, - mResDir, mNewGame, mEncoding, mFallbackMap) ); + mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, + mResDir, mNewGame, mEncoding, mFallbackMap)); // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 0582800c9..031cae551 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -64,8 +64,7 @@ namespace OMW boost::filesystem::path mResDir; OEngine::Render::OgreRenderer *mOgre; std::string mCellName; - std::vector mMaster; - std::vector mPlugins; + std::string mMaster; int mFpsLevel; bool mDebug; bool mVerboseScripts; @@ -121,12 +120,9 @@ namespace OMW /// Set master file (esm) /// - If the given name does not have an extension, ".esm" is added automatically + /// - Currently OpenMW only supports one master at the same time. void addMaster(const std::string& master); - /// Same as "addMaster", but for plugin files (esp) - /// - If the given name does not have an extension, ".esp" is added automatically - void addPlugin(const std::string& plugin); - /// Enable fps counter void showFPS(int level); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 9fe333a28..993ec6623 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -224,23 +224,19 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat master.push_back("Morrowind"); } - StringsVector plugin = variables["plugin"].as(); - int cnt = master.size() + plugin.size(); - if (cnt > 255) - { - std::cerr - << "Error: Trying to load more than 255 master and plugin files! This will break all combaibility and is not supported!" - << std::endl; - return false; - } - for (std::vector::size_type i = 0; i < master.size(); i++) + if (master.size() > 1) { - engine.addMaster(master[i]); - } - for (std::vector::size_type i = 0; i < plugin.size(); i++) - { - engine.addPlugin(plugin[i]); - } + std::cout + << "Ignoring all but the first master file (multiple master files not yet supported)." + << std::endl; + } + engine.addMaster(master[0]); + + StringsVector plugin = variables["plugin"].as(); + if (!plugin.empty()) + { + std::cout << "Ignoring plugin files (plugins not yet supported)." << std::endl; + } // startup-settings engine.setCell(variables["start"].as()); diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 909836659..691e7c4af 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -141,7 +141,7 @@ namespace MWRender std::map indexes; initTerrainTextures(&terrainData, cellX, cellY, x * numTextures, y * numTextures, - numTextures, indexes, land->plugin); + numTextures, indexes); if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL) { @@ -200,14 +200,8 @@ namespace MWRender void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData, int cellX, int cellY, int fromX, int fromY, int size, - std::map& indexes, - size_t plugin) + std::map& indexes) { - // FIXME: In a multiple esm configuration, we have multiple palettes. Since this code - // crosses cell boundaries, we no longer have a unique terrain palette. Instead, we need - // to adopt the following code for a dynamic palette. And this is evil - the current design - // does not work well for this task... - assert(terrainData != NULL && "Must have valid terrain data"); assert(fromX >= 0 && fromY >= 0 && "Can't get a terrain texture on terrain outside the current cell"); @@ -220,16 +214,12 @@ namespace MWRender // //If we don't sort the ltex indexes, the splatting order may differ between //cells which may lead to inconsistent results when shading between cells - int num = MWBase::Environment::get().getWorld()->getStore().landTexts.getSizePlugin(plugin); std::set ltexIndexes; for ( int y = fromY - 1; y < fromY + size + 1; y++ ) { for ( int x = fromX - 1; x < fromX + size + 1; x++ ) { - int idx = getLtexIndexAt(cellX, cellY, x, y); - if (idx > num) - idx = 0; - ltexIndexes.insert(idx); + ltexIndexes.insert(getLtexIndexAt(cellX, cellY, x, y)); } } @@ -241,7 +231,7 @@ namespace MWRender iter != ltexIndexes.end(); ++iter ) { - uint16_t ltexIndex = *iter; + const uint16_t ltexIndex = *iter; //this is the base texture, so we can ignore this at present if ( ltexIndex == baseTexture ) { @@ -254,10 +244,8 @@ namespace MWRender { //NB: All vtex ids are +1 compared to the ltex ids - /* - assert( (int)mEnvironment.mWorld->getStore().landTexts.getSizePlugin(plugin) >= (int)ltexIndex - 1 && + assert( (int)MWBase::Environment::get().getWorld()->getStore().landTexts.getSize() >= (int)ltexIndex - 1 && "LAND.VTEX must be within the bounds of the LTEX array"); - */ std::string texture; if ( ltexIndex == 0 ) @@ -266,7 +254,7 @@ namespace MWRender } else { - texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1, plugin)->texture; + texture = MWBase::Environment::get().getWorld()->getStore().landTexts.search(ltexIndex-1)->texture; //TODO this is needed due to MWs messed up texture handling texture = texture.substr(0, texture.rfind(".")) + ".dds"; } diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index 94072fc40..c83d96cf4 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -71,14 +71,11 @@ namespace MWRender{ * @param size the size (number of splats) to get * @param indexes a mapping of ltex index to the terrain texture layer that * can be used by initTerrainBlendMaps - * @param plugin the index of the plugin providing the texture list for this - * cell data; required because MW uses texture data on a per-plugin base */ void initTerrainTextures(Ogre::Terrain::ImportData* terrainData, int cellX, int cellY, int fromX, int fromY, int size, - std::map& indexes, - size_t plugin = 0); + std::map& indexes); /** * Creates the blend (splatting maps) for the given terrain from the ltex data. diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ae517071e..a68f08e34 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -167,8 +167,7 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, - const std::vector& master, - const std::vector& plugins, const boost::filesystem::path& resDir, bool newGame, + const std::string& master, const boost::filesystem::path& resDir, bool newGame, const std::string& encoding, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mNextDynamicRecord (0), mCells (mStore, mEsm), @@ -181,32 +180,15 @@ namespace MWWorld mWeatherManager = new MWWorld::WeatherManager(mRendering); - int idx = 0; - for (std::vector::size_type i = 0; i < master.size(); i++, idx++) - { - boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i])); - - std::cout << "Loading ESM " << masterPath.string() << "\n"; + boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); - // This parses the ESM file and loads a sample cell - mEsm.setEncoding(encoding); - mEsm.open (masterPath.string()); - mEsm.setIndex(idx); - mStore.load (mEsm); - } + std::cout << "Loading ESM " << masterPath.string() << "\n"; - for (std::vector::size_type i = 0; i < plugins.size(); i++, idx++) - { - boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i])); - - std::cout << "Loading ESP " << pluginPath.string() << "\n"; + // This parses the ESM file and loads a sample cell + mEsm.setEncoding(encoding); + mEsm.open (masterPath.string()); + mStore.load (mEsm); - // This parses the ESP file and loads a sample cell - mEsm.setEncoding(encoding); - mEsm.open (pluginPath.string()); - mEsm.setIndex(idx); - mStore.load (mEsm); - } MWRender::Player* play = &(mRendering->getPlayer()); mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this); mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index af6232aaf..43b178fe3 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -93,8 +93,7 @@ namespace MWWorld World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, - const std::vector& master, - const std::vector& plugins, const boost::filesystem::path& resDir, bool newGame, + const std::string& master, const boost::filesystem::path& resDir, bool newGame, const std::string& encoding, std::map fallbackMap); virtual ~World(); diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 0326fdc04..13f1f4a01 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -189,14 +189,6 @@ public: void openRaw(const std::string &file); - // This is a quick hack for multiple esm/esp files. Each plugin introduces its own - // terrain palette, but ESMReader does not pass a reference to the correct plugin - // to the individual load() methods. This hack allows to pass this reference - // indirectly to the load() method. - int idx; - void setIndex(const int index) {idx = index;} - const int getIndex() {return idx;} - /************************************************************************* * * Medium-level reading shortcuts diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 822952c91..96afdf831 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -23,7 +23,6 @@ Land::~Land() void Land::load(ESMReader &esm) { mEsm = &esm; - plugin = mEsm->getIndex(); // Get the grid location esm.getSubNameIs("INTV"); diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index d03012d38..ebc314a28 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -17,7 +17,6 @@ struct Land int flags; // Only first four bits seem to be used, don't know what // they mean. int X, Y; // Map coordinates. - int plugin; // Plugin index, used to reference the correct material palette. // File context. This allows the ESM reader to be 'reset' to this // location later when we are ready to load the full data set. diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 668c4e58e..ffecfc8de 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -26,7 +26,6 @@ namespace ESMS virtual void load(ESMReader &esm, const std::string &id) = 0; virtual int getSize() = 0; - virtual void remove(const std::string &id) {}; virtual void listIdentifier (std::vector& identifier) const = 0; static std::string toLower (const std::string& name) @@ -58,14 +57,6 @@ namespace ESMS list[id2].load(esm); } - // Delete the given object ID - void remove(const std::string &id) - { - std::string id2 = toLower (id); - - list.erase(id2); - } - // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { @@ -277,57 +268,38 @@ namespace ESMS { virtual ~LTexList() {} - // For multiple ESM/ESP files we need one list per file. - typedef std::vector LandTextureList; - std::vector ltex; + // TODO: For multiple ESM/ESP files we need one list per file. + std::vector ltex; LTexList() { - ltex.push_back(LandTextureList()); - LandTextureList <exl = ltex[0]; // More than enough to hold Morrowind.esm. - ltexl.reserve(128); + ltex.reserve(128); } - const LandTexture* search(size_t index, size_t plugin) const + const LandTexture* search(size_t index) const { - assert(plugin < ltex.size()); - const LandTextureList <exl = ltex[plugin]; - - assert(index < ltexl.size()); - return <exl.at(index); + assert(index < ltex.size()); + return <ex.at(index); } int getSize() { return ltex.size(); } int getSize() const { return ltex.size(); } - int getSizePlugin(size_t plugin) { assert(plugin < ltex.size()); return ltex[plugin].size(); } - int getSizePlugin(size_t plugin) const { assert(plugin < ltex.size()); return ltex[plugin].size(); } + virtual void listIdentifier (std::vector& identifier) const {} - virtual void listIdentifier (std::vector& identifier) const {} - - void load(ESMReader &esm, const std::string &id, size_t plugin) + void load(ESMReader &esm, const std::string &id) { LandTexture lt; lt.load(esm); lt.id = id; // Make sure we have room for the structure - if (plugin >= ltex.size()) { - ltex.resize(plugin+1); - } - LandTextureList <exl = ltex[plugin]; - if(lt.index + 1 > (int)ltexl.size()) - ltexl.resize(lt.index+1); + if(lt.index + 1 > (int)ltex.size()) + ltex.resize(lt.index+1); // Store it - ltexl[lt.index] = lt; - } - - void load(ESMReader &esm, const std::string &id) - { - size_t plugin = esm.getIndex(); - load(esm, id, plugin); + ltex[lt.index] = lt; } }; diff --git a/components/esm_store/store.cpp b/components/esm_store/store.cpp index b6972355c..c676601e5 100644 --- a/components/esm_store/store.cpp +++ b/components/esm_store/store.cpp @@ -67,13 +67,6 @@ void ESMStore::load(ESMReader &esm) { // Load it std::string id = esm.getHNOString("NAME"); - // ... unless it got deleted! - if (esm.isNextSub("DELE")) { - esm.skipRecord(); - all.erase(id); - it->second->remove(id); - continue; - } it->second->load(esm, id); if (n.val==ESM::REC_DIAL) From ab35bfa32cb4642750538c77bf8996419d9bdc7a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 23 Jul 2012 18:19:34 +0200 Subject: [PATCH 082/126] fixed a sky issue --- apps/openmw/mwrender/sky.cpp | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index d78a3caff..d928995f4 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -287,21 +287,12 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) void SkyManager::create() { + assert(!mCreated); + sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor", sh::makeProperty(new sh::FloatValue(0))); - sh::Factory::getInstance().setSharedParameter ("cloudOpacity", - sh::makeProperty(new sh::FloatValue(1))); - sh::Factory::getInstance().setSharedParameter ("cloudColour", - sh::makeProperty(new sh::Vector3(1,1,1))); - sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", - sh::makeProperty(new sh::FloatValue(0))); - sh::Factory::getInstance().setSharedParameter ("nightFade", - sh::makeProperty(new sh::FloatValue(0))); - sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", ""); - sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", ""); - - // Create overlay used for thunderstorm + // Create light used for thunderstorm mLightning = mSceneMgr->createLight(); mLightning->setType (Ogre::Light::LT_DIRECTIONAL); mLightning->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); @@ -332,19 +323,15 @@ void SkyManager::create() night1_ent->setVisibilityFlags(RV_Sky); night1_ent->setCastShadows(false); - for (unsigned int i=0; igetNumSubEntities(); ++i) - { - std::string matName = "openmw_stars_" + boost::lexical_cast(i); - sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars"); + std::string matName = "openmw_stars_" + boost::lexical_cast(i); + sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars"); - std::string textureName = sh::retrieveValue( - sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (i)->getMaterialName ())->getProperty("diffuseMap"), NULL).get(); + std::string textureName = sh::retrieveValue( + sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (0)->getMaterialName ())->getProperty("diffuseMap"), NULL).get(); - m->setProperty ("texture", sh::makeProperty(new sh::StringValue(textureName))); + m->setProperty ("texture", sh::makeProperty(new sh::StringValue(textureName))); - night1_ent->getSubEntity(i)->setMaterialName (matName); - - } + night1_ent->getSubEntity(0)->setMaterialName (matName); } @@ -370,7 +357,6 @@ void SkyManager::create() Entity* clouds_ent = entities.mEntities[i]; clouds_ent->setVisibilityFlags(RV_Sky); clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); - clouds_node->attachObject(clouds_ent); clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds"); clouds_ent->setCastShadows(false); From 3aa53fea327b061af6208b99fcbe0cb8e39732ea Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 23 Jul 2012 23:06:53 +0400 Subject: [PATCH 083/126] wrong --- apps/openmw/mwworld/scene.cpp | 124 ---------------------------------- 1 file changed, 124 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 33c67aad8..b28a933b1 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -336,130 +336,6 @@ namespace MWWorld /// \todo this whole code needs major clean up, and doesn't belong in this class. - void Scene::insertObject (const Ptr& ptr, CellStore* cell) - { - std::string type = ptr.getTypeName(); - - MWWorld::Ptr newPtr; - - // insert into the correct CellRefList - if (type == typeid(ESM::Potion).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->potions.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->potions.list.back(), cell); - } - else if (type == typeid(ESM::Apparatus).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->appas.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->appas.list.back(), cell); - } - else if (type == typeid(ESM::Armor).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->armors.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->armors.list.back(), cell); - } - else if (type == typeid(ESM::Book).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->books.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->books.list.back(), cell); - } - else if (type == typeid(ESM::Clothing).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->clothes.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->clothes.list.back(), cell); - } - else if (type == typeid(ESM::Ingredient).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->ingreds.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->ingreds.list.back(), cell); - } - else if (type == typeid(ESM::Light).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->lights.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->lights.list.back(), cell); - } - else if (type == typeid(ESM::Tool).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->lockpicks.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->lockpicks.list.back(), cell); - } - else if (type == typeid(ESM::Repair).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->repairs.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->repairs.list.back(), cell); - } - else if (type == typeid(ESM::Probe).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->probes.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->probes.list.back(), cell); - } - else if (type == typeid(ESM::Weapon).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->weapons.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->weapons.list.back(), cell); - } - else if (type == typeid(ESM::Miscellaneous).name()) - { - - // if this is gold, we need to fetch the correct mesh depending on the amount of gold. - if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) - { - int goldAmount = ptr.getRefData().getCount(); - - std::string base = "Gold_001"; - if (goldAmount >= 100) - base = "Gold_100"; - else if (goldAmount >= 25) - base = "Gold_025"; - else if (goldAmount >= 10) - base = "Gold_010"; - else if (goldAmount >= 5) - base = "Gold_005"; - - MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); - - MWWorld::LiveCellRef* ref = newRef.getPtr().get(); - - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); - - ESM::Position& p = newPtr.getRefData().getPosition(); - p.pos[0] = ptr.getRefData().getPosition().pos[0]; - p.pos[1] = ptr.getRefData().getPosition().pos[1]; - p.pos[2] = ptr.getRefData().getPosition().pos[2]; - } - else - { - MWWorld::LiveCellRef* ref = ptr.get(); - - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); - } - } - else - throw std::runtime_error("Trying to insert object of unhandled type"); - - - - newPtr.getRefData().setCount(ptr.getRefData().getCount()); - ptr.getRefData().setCount(0); - newPtr.getRefData().enable(); - - mRendering.addObject(newPtr); - MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); - - } void Scene::addObjectToScene (const Ptr& ptr) { From 9a2690f84921696f8894cdaf8b8ee5e2de9843d8 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 23 Jul 2012 23:07:28 +0400 Subject: [PATCH 084/126] Revert "wrong" This reverts commit 3aa53fea327b061af6208b99fcbe0cb8e39732ea. --- apps/openmw/mwworld/scene.cpp | 124 ++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index b28a933b1..33c67aad8 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -336,6 +336,130 @@ namespace MWWorld /// \todo this whole code needs major clean up, and doesn't belong in this class. + void Scene::insertObject (const Ptr& ptr, CellStore* cell) + { + std::string type = ptr.getTypeName(); + + MWWorld::Ptr newPtr; + + // insert into the correct CellRefList + if (type == typeid(ESM::Potion).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->potions.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->potions.list.back(), cell); + } + else if (type == typeid(ESM::Apparatus).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->appas.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->appas.list.back(), cell); + } + else if (type == typeid(ESM::Armor).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->armors.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->armors.list.back(), cell); + } + else if (type == typeid(ESM::Book).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->books.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->books.list.back(), cell); + } + else if (type == typeid(ESM::Clothing).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->clothes.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->clothes.list.back(), cell); + } + else if (type == typeid(ESM::Ingredient).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->ingreds.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->ingreds.list.back(), cell); + } + else if (type == typeid(ESM::Light).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->lights.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->lights.list.back(), cell); + } + else if (type == typeid(ESM::Tool).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->lockpicks.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->lockpicks.list.back(), cell); + } + else if (type == typeid(ESM::Repair).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->repairs.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->repairs.list.back(), cell); + } + else if (type == typeid(ESM::Probe).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->probes.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->probes.list.back(), cell); + } + else if (type == typeid(ESM::Weapon).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->weapons.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->weapons.list.back(), cell); + } + else if (type == typeid(ESM::Miscellaneous).name()) + { + + // if this is gold, we need to fetch the correct mesh depending on the amount of gold. + if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + int goldAmount = ptr.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 100) + base = "Gold_100"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; + + MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); + + MWWorld::LiveCellRef* ref = newRef.getPtr().get(); + + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + + ESM::Position& p = newPtr.getRefData().getPosition(); + p.pos[0] = ptr.getRefData().getPosition().pos[0]; + p.pos[1] = ptr.getRefData().getPosition().pos[1]; + p.pos[2] = ptr.getRefData().getPosition().pos[2]; + } + else + { + MWWorld::LiveCellRef* ref = ptr.get(); + + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + } + } + else + throw std::runtime_error("Trying to insert object of unhandled type"); + + + + newPtr.getRefData().setCount(ptr.getRefData().getCount()); + ptr.getRefData().setCount(0); + newPtr.getRefData().enable(); + + mRendering.addObject(newPtr); + MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); + + } void Scene::addObjectToScene (const Ptr& ptr) { From d36d6aacf49741ccee9c6a6138f55b4123fd9b07 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 23 Jul 2012 23:56:20 +0400 Subject: [PATCH 085/126] move Scene::insertObject to CellStore::insertObject, part 1 --- apps/openmw/mwworld/cellstore.cpp | 107 +++++++++++++++++++++++++ apps/openmw/mwworld/cellstore.hpp | 6 ++ apps/openmw/mwworld/scene.cpp | 126 ------------------------------ 3 files changed, 113 insertions(+), 126 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 60a7eb6e1..51a46ec3c 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -121,4 +121,111 @@ namespace MWWorld } } } + + /// \todo this whole code needs major clean up + void CellStore::insertObject(const Ptr &ptr) + { + std::string type = ptr.getTypeName(); + + MWWorld::Ptr newPtr; + + // insert into the correct CellRefList + if (type == typeid(ESM::Potion).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&potions.insert(*ref), cell); + } + else if (type == typeid(ESM::Apparatus).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&appas.insert(*ref), cell); + } + else if (type == typeid(ESM::Armor).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&armors.insert(*ref), cell); + } + else if (type == typeid(ESM::Book).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&books.insert(*ref), cell); + } + else if (type == typeid(ESM::Clothing).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&clothes.insert(*ref), cell); + } + else if (type == typeid(ESM::Ingredient).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&ingreds.insert(*ref), cell); + } + else if (type == typeid(ESM::Light).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&lights.insert(*ref), cell); + } + else if (type == typeid(ESM::Tool).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&lockpicks.insert(*ref), cell); + } + else if (type == typeid(ESM::Repair).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&repairs.insert(*ref), cell); + } + else if (type == typeid(ESM::Probe).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&probes.insert(*ref), cell); + } + else if (type == typeid(ESM::Weapon).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&weapons.insert(*ref), cell); + } + else if (type == typeid(ESM::Miscellaneous).name()) + { + + // if this is gold, we need to fetch the correct mesh depending on the amount of gold. + if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + int goldAmount = ptr.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 100) + base = "Gold_100"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; + + MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); + + MWWorld::LiveCellRef* ref = + newRef.getPtr().get(); + + newPtr = MWWorld::Ptr(&miscItems.insert(*ref), cell); + + ESM::Position& p = newPtr.getRefData().getPosition(); + p.pos[0] = ptr.getRefData().getPosition().pos[0]; + p.pos[1] = ptr.getRefData().getPosition().pos[1]; + p.pos[2] = ptr.getRefData().getPosition().pos[2]; + } + else + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&miscItems.insert(*ref), cell); + } + } + else + throw std::runtime_error("Trying to insert object of unhandled type"); + + newPtr.getRefData().setCount(ptr.getRefData().getCount()); + ptr.getRefData().setCount(0); + newPtr.getRefData().enable(); + } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index de3ac12ae..89724bca4 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -7,6 +7,7 @@ #include #include "refdata.hpp" +#include "ptr.hpp" namespace ESMS { @@ -63,6 +64,11 @@ namespace MWWorld list.push_back(LiveRef(ref, obj)); } + const LiveRef &insert(LiveRef &item) { + list.push_back(item); + return list.back(); + } + LiveRef *find (const std::string& name) { for (typename std::list::iterator iter (list.begin()); iter!=list.end(); ++iter) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 33c67aad8..d2725b00e 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -335,132 +335,6 @@ namespace MWWorld } - /// \todo this whole code needs major clean up, and doesn't belong in this class. - void Scene::insertObject (const Ptr& ptr, CellStore* cell) - { - std::string type = ptr.getTypeName(); - - MWWorld::Ptr newPtr; - - // insert into the correct CellRefList - if (type == typeid(ESM::Potion).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->potions.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->potions.list.back(), cell); - } - else if (type == typeid(ESM::Apparatus).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->appas.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->appas.list.back(), cell); - } - else if (type == typeid(ESM::Armor).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->armors.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->armors.list.back(), cell); - } - else if (type == typeid(ESM::Book).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->books.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->books.list.back(), cell); - } - else if (type == typeid(ESM::Clothing).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->clothes.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->clothes.list.back(), cell); - } - else if (type == typeid(ESM::Ingredient).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->ingreds.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->ingreds.list.back(), cell); - } - else if (type == typeid(ESM::Light).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->lights.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->lights.list.back(), cell); - } - else if (type == typeid(ESM::Tool).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->lockpicks.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->lockpicks.list.back(), cell); - } - else if (type == typeid(ESM::Repair).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->repairs.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->repairs.list.back(), cell); - } - else if (type == typeid(ESM::Probe).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->probes.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->probes.list.back(), cell); - } - else if (type == typeid(ESM::Weapon).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->weapons.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->weapons.list.back(), cell); - } - else if (type == typeid(ESM::Miscellaneous).name()) - { - - // if this is gold, we need to fetch the correct mesh depending on the amount of gold. - if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) - { - int goldAmount = ptr.getRefData().getCount(); - - std::string base = "Gold_001"; - if (goldAmount >= 100) - base = "Gold_100"; - else if (goldAmount >= 25) - base = "Gold_025"; - else if (goldAmount >= 10) - base = "Gold_010"; - else if (goldAmount >= 5) - base = "Gold_005"; - - MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); - - MWWorld::LiveCellRef* ref = newRef.getPtr().get(); - - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); - - ESM::Position& p = newPtr.getRefData().getPosition(); - p.pos[0] = ptr.getRefData().getPosition().pos[0]; - p.pos[1] = ptr.getRefData().getPosition().pos[1]; - p.pos[2] = ptr.getRefData().getPosition().pos[2]; - } - else - { - MWWorld::LiveCellRef* ref = ptr.get(); - - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); - } - } - else - throw std::runtime_error("Trying to insert object of unhandled type"); - - - - newPtr.getRefData().setCount(ptr.getRefData().getCount()); - ptr.getRefData().setCount(0); - newPtr.getRefData().enable(); - - mRendering.addObject(newPtr); - MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); - - } - void Scene::addObjectToScene (const Ptr& ptr) { mRendering.addObject (ptr); From b76022517935b7d5e16f34100143c0beec3fa253 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 24 Jul 2012 00:00:10 +0400 Subject: [PATCH 086/126] wrong branch This reverts commit d36d6aacf49741ccee9c6a6138f55b4123fd9b07. --- apps/openmw/mwworld/cellstore.cpp | 107 ------------------------- apps/openmw/mwworld/cellstore.hpp | 6 -- apps/openmw/mwworld/scene.cpp | 126 ++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 113 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 51a46ec3c..60a7eb6e1 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -121,111 +121,4 @@ namespace MWWorld } } } - - /// \todo this whole code needs major clean up - void CellStore::insertObject(const Ptr &ptr) - { - std::string type = ptr.getTypeName(); - - MWWorld::Ptr newPtr; - - // insert into the correct CellRefList - if (type == typeid(ESM::Potion).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&potions.insert(*ref), cell); - } - else if (type == typeid(ESM::Apparatus).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&appas.insert(*ref), cell); - } - else if (type == typeid(ESM::Armor).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&armors.insert(*ref), cell); - } - else if (type == typeid(ESM::Book).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&books.insert(*ref), cell); - } - else if (type == typeid(ESM::Clothing).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&clothes.insert(*ref), cell); - } - else if (type == typeid(ESM::Ingredient).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&ingreds.insert(*ref), cell); - } - else if (type == typeid(ESM::Light).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&lights.insert(*ref), cell); - } - else if (type == typeid(ESM::Tool).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&lockpicks.insert(*ref), cell); - } - else if (type == typeid(ESM::Repair).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&repairs.insert(*ref), cell); - } - else if (type == typeid(ESM::Probe).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&probes.insert(*ref), cell); - } - else if (type == typeid(ESM::Weapon).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&weapons.insert(*ref), cell); - } - else if (type == typeid(ESM::Miscellaneous).name()) - { - - // if this is gold, we need to fetch the correct mesh depending on the amount of gold. - if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) - { - int goldAmount = ptr.getRefData().getCount(); - - std::string base = "Gold_001"; - if (goldAmount >= 100) - base = "Gold_100"; - else if (goldAmount >= 25) - base = "Gold_025"; - else if (goldAmount >= 10) - base = "Gold_010"; - else if (goldAmount >= 5) - base = "Gold_005"; - - MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); - - MWWorld::LiveCellRef* ref = - newRef.getPtr().get(); - - newPtr = MWWorld::Ptr(&miscItems.insert(*ref), cell); - - ESM::Position& p = newPtr.getRefData().getPosition(); - p.pos[0] = ptr.getRefData().getPosition().pos[0]; - p.pos[1] = ptr.getRefData().getPosition().pos[1]; - p.pos[2] = ptr.getRefData().getPosition().pos[2]; - } - else - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&miscItems.insert(*ref), cell); - } - } - else - throw std::runtime_error("Trying to insert object of unhandled type"); - - newPtr.getRefData().setCount(ptr.getRefData().getCount()); - ptr.getRefData().setCount(0); - newPtr.getRefData().enable(); - } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 89724bca4..de3ac12ae 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -7,7 +7,6 @@ #include #include "refdata.hpp" -#include "ptr.hpp" namespace ESMS { @@ -64,11 +63,6 @@ namespace MWWorld list.push_back(LiveRef(ref, obj)); } - const LiveRef &insert(LiveRef &item) { - list.push_back(item); - return list.back(); - } - LiveRef *find (const std::string& name) { for (typename std::list::iterator iter (list.begin()); iter!=list.end(); ++iter) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index d2725b00e..33c67aad8 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -335,6 +335,132 @@ namespace MWWorld } + /// \todo this whole code needs major clean up, and doesn't belong in this class. + void Scene::insertObject (const Ptr& ptr, CellStore* cell) + { + std::string type = ptr.getTypeName(); + + MWWorld::Ptr newPtr; + + // insert into the correct CellRefList + if (type == typeid(ESM::Potion).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->potions.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->potions.list.back(), cell); + } + else if (type == typeid(ESM::Apparatus).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->appas.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->appas.list.back(), cell); + } + else if (type == typeid(ESM::Armor).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->armors.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->armors.list.back(), cell); + } + else if (type == typeid(ESM::Book).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->books.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->books.list.back(), cell); + } + else if (type == typeid(ESM::Clothing).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->clothes.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->clothes.list.back(), cell); + } + else if (type == typeid(ESM::Ingredient).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->ingreds.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->ingreds.list.back(), cell); + } + else if (type == typeid(ESM::Light).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->lights.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->lights.list.back(), cell); + } + else if (type == typeid(ESM::Tool).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->lockpicks.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->lockpicks.list.back(), cell); + } + else if (type == typeid(ESM::Repair).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->repairs.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->repairs.list.back(), cell); + } + else if (type == typeid(ESM::Probe).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->probes.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->probes.list.back(), cell); + } + else if (type == typeid(ESM::Weapon).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + cell->weapons.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->weapons.list.back(), cell); + } + else if (type == typeid(ESM::Miscellaneous).name()) + { + + // if this is gold, we need to fetch the correct mesh depending on the amount of gold. + if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + int goldAmount = ptr.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 100) + base = "Gold_100"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; + + MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); + + MWWorld::LiveCellRef* ref = newRef.getPtr().get(); + + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + + ESM::Position& p = newPtr.getRefData().getPosition(); + p.pos[0] = ptr.getRefData().getPosition().pos[0]; + p.pos[1] = ptr.getRefData().getPosition().pos[1]; + p.pos[2] = ptr.getRefData().getPosition().pos[2]; + } + else + { + MWWorld::LiveCellRef* ref = ptr.get(); + + cell->miscItems.list.push_back( *ref ); + newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); + } + } + else + throw std::runtime_error("Trying to insert object of unhandled type"); + + + + newPtr.getRefData().setCount(ptr.getRefData().getCount()); + ptr.getRefData().setCount(0); + newPtr.getRefData().enable(); + + mRendering.addObject(newPtr); + MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); + + } + void Scene::addObjectToScene (const Ptr& ptr) { mRendering.addObject (ptr); From f67983bbee071b886f27682c322fb66628db2b44 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 23 Jul 2012 13:37:05 -0700 Subject: [PATCH 087/126] Don't assume one sub-entity for the night sky entities --- apps/openmw/mwrender/sky.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index d928995f4..3dd038659 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -316,22 +316,25 @@ void SkyManager::create() // Stars mAtmosphereNight = mRootNode->createChildSceneNode(); NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mAtmosphereNight, "meshes\\sky_night_01.nif"); - for(size_t i = 0;i < entities.mEntities.size();i++) + for(size_t i = 0, matidx = 0;i < entities.mEntities.size();i++) { Entity* night1_ent = entities.mEntities[i]; night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); night1_ent->setVisibilityFlags(RV_Sky); night1_ent->setCastShadows(false); - std::string matName = "openmw_stars_" + boost::lexical_cast(i); - sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars"); + for (unsigned int j=0; jgetNumSubEntities(); ++j) + { + std::string matName = "openmw_stars_" + boost::lexical_cast(matidx++); + sh::MaterialInstance* m = sh::Factory::getInstance().createMaterialInstance(matName, "openmw_stars"); - std::string textureName = sh::retrieveValue( - sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (0)->getMaterialName ())->getProperty("diffuseMap"), NULL).get(); + std::string textureName = sh::retrieveValue( + sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity(j)->getMaterialName())->getProperty("diffuseMap"), NULL).get(); - m->setProperty ("texture", sh::makeProperty(new sh::StringValue(textureName))); + m->setProperty("texture", sh::makeProperty(new sh::StringValue(textureName))); - night1_ent->getSubEntity(0)->setMaterialName (matName); + night1_ent->getSubEntity(j)->setMaterialName(matName); + } } From 8c8228a15ca76b45b8a059830ea2f49689df3e1c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 24 Jul 2012 00:08:53 +0200 Subject: [PATCH 088/126] fix terrain num lights setting --- apps/openmw/mwrender/renderingmanager.cpp | 1 + files/materials/terrain.shader | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c5449cfba..bee4bd68a 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -110,6 +110,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setGlobalSetting ("fog", "true"); sh::Factory::getInstance ().setGlobalSetting ("lighting", "true"); sh::Factory::getInstance ().setGlobalSetting ("num_lights", Settings::Manager::getString ("num lights", "Objects")); + sh::Factory::getInstance ().setGlobalSetting ("terrain_num_lights", Settings::Manager::getString ("num lights", "Terrain")); sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index a562d1ec3..601f287a0 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -161,7 +161,7 @@ #if LIGHTING shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) - @shForeach(@shGlobalSettingString(num_lights)) + @shForeach(@shGlobalSettingString(terrain_num_lights)) shUniform(float4, lightPosObjSpace@shIterator) @shAutoConstant(lightPosObjSpace@shIterator, light_position_object_space, @shIterator) shUniform(float4, lightAttenuation@shIterator) @shAutoConstant(lightAttenuation@shIterator, light_attenuation, @shIterator) shUniform(float4, lightDiffuse@shIterator) @shAutoConstant(lightDiffuse@shIterator, light_diffuse_colour, @shIterator) @@ -298,7 +298,7 @@ float3 diffuse = float3(0,0,0); float d; - @shForeach(@shGlobalSettingString(num_lights)) + @shForeach(@shGlobalSettingString(terrain_num_lights)) lightDir = lightPosObjSpace@shIterator.xyz - (objSpacePosition.xyz * lightPosObjSpace@shIterator.w); d = length(lightDir); From 36be1536d90a5d927854e0c66eca5efbe17c4767 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 23 Jul 2012 17:20:47 -0700 Subject: [PATCH 089/126] Return text keys from NIFs when creating entities --- apps/openmw/mwrender/creatureanimation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 2 +- apps/openmw/mwrender/objects.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 6 ++-- components/nifogre/ogre_nif_loader.cpp | 36 ++++++++++++++++------ components/nifogre/ogre_nif_loader.hpp | 8 +++-- 6 files changed, 37 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 9d2a58a1e..4086f4f7a 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,7 +26,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O { std::string mesh = "meshes\\" + ref->base->model; - mEntityList = NifOgre::NIFLoader::createEntities(mInsert, mesh); + mEntityList = NifOgre::NIFLoader::createEntities(mInsert, NULL, mesh); for(size_t i = 0;i < mEntityList.mEntities.size();i++) { Ogre::Entity *ent = mEntityList.mEntities[i]; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 415de5859..47135b35d 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -89,7 +89,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - mEntityList = NifOgre::NIFLoader::createEntities(mInsert, smodel); + mEntityList = NifOgre::NIFLoader::createEntities(mInsert, NULL, smodel); for(size_t i = 0;i < mEntityList.mEntities.size();i++) { Ogre::Entity *base = mEntityList.mEntities[i]; diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 3af99b469..ecd1328c4 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -93,7 +93,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; - NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, mesh); + NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, NULL, mesh); for(size_t i = 0;i < entities.mEntities.size();i++) { const Ogre::AxisAlignedBox &tmp = entities.mEntities[i]->getBoundingBox(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index a87f56ad8..9e551ba2a 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -327,7 +327,7 @@ void SkyManager::create() // Stars mAtmosphereNight = mRootNode->createChildSceneNode(); - NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mAtmosphereNight, "meshes\\sky_night_01.nif"); + NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mAtmosphereNight, NULL, "meshes\\sky_night_01.nif"); for(size_t i = 0, matidx = 0;i < entities.mEntities.size();i++) { Entity* night1_ent = entities.mEntities[i]; @@ -352,7 +352,7 @@ void SkyManager::create() // Atmosphere (day) mAtmosphereDay = mRootNode->createChildSceneNode(); - entities = NifOgre::NIFLoader::createEntities(mAtmosphereDay, "meshes\\sky_atmosphere.nif"); + entities = NifOgre::NIFLoader::createEntities(mAtmosphereDay, NULL, "meshes\\sky_atmosphere.nif"); for(size_t i = 0;i < entities.mEntities.size();i++) { Entity* atmosphere_ent = entities.mEntities[i]; @@ -366,7 +366,7 @@ void SkyManager::create() // Clouds SceneNode* clouds_node = mRootNode->createChildSceneNode(); - entities = NifOgre::NIFLoader::createEntities(clouds_node, "meshes\\sky_clouds_01.nif"); + entities = NifOgre::NIFLoader::createEntities(clouds_node, NULL, "meshes\\sky_clouds_01.nif"); for(size_t i = 0;i < entities.mEntities.size();i++) { Entity* clouds_ent = entities.mEntities[i]; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 3338b8cdd..9df8dd916 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -342,8 +342,23 @@ void loadResource(Ogre::Resource *resource) anim->optimise(); } -bool createSkeleton(const std::string &name, const std::string &group, Nif::Node *node) +bool createSkeleton(const std::string &name, const std::string &group, TextKeyMap *textkeys, const Nif::Node *node) { + if(textkeys) + { + Nif::ExtraPtr e = node->extra; + while(!e.empty()) + { + if(e->recType == Nif::RC_NiTextKeyExtraData) + { + const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); + for(size_t i = 0;i < tk->list.size();i++) + (*textkeys)[tk->list[i].time] = tk->list[i].text; + } + e = e->extra; + } + } + if(node->boneTrafo != NULL) { Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); @@ -355,18 +370,19 @@ bool createSkeleton(const std::string &name, const std::string &group, Nif::Node skel = skelMgr.create(name, group, true, loader); } - return true; + if(!textkeys || textkeys->size() > 0) + return true; } - Nif::NiNode *ninode = dynamic_cast(node); + const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { - Nif::NodeList &children = ninode->children; + const Nif::NodeList &children = ninode->children; for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) { - if(createSkeleton(name, group, children[i].getPtr())) + if(createSkeleton(name, group, textkeys, children[i].getPtr())) return true; } } @@ -965,7 +981,7 @@ public: NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; -MeshPairList NIFLoader::load(std::string name, std::string skelName, const std::string &group) +MeshPairList NIFLoader::load(std::string name, std::string skelName, TextKeyMap *textkeys, const std::string &group) { MeshPairList meshes; @@ -992,7 +1008,7 @@ MeshPairList NIFLoader::load(std::string name, std::string skelName, const std:: } NIFSkeletonLoader skelldr; - bool hasSkel = skelldr.createSkeleton(skelName, group, node); + bool hasSkel = skelldr.createSkeleton(skelName, group, textkeys, node); NIFMeshLoader meshldr(name, group, (hasSkel ? skelName : std::string())); meshldr.createMeshes(node, meshes); @@ -1000,11 +1016,11 @@ MeshPairList NIFLoader::load(std::string name, std::string skelName, const std:: return meshes; } -EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, const std::string &name, const std::string &group) +EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textkeys, const std::string &name, const std::string &group) { EntityList entitylist; - MeshPairList meshes = load(name, name, group); + MeshPairList meshes = load(name, name, textkeys, group); if(meshes.size() == 0) return entitylist; @@ -1053,7 +1069,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo { EntityList entitylist; - MeshPairList meshes = load(name, parent->getMesh()->getSkeletonName(), group); + MeshPairList meshes = load(name, parent->getMesh()->getSkeletonName(), NULL, group); if(meshes.size() == 0) return entitylist; diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index a9195f2fb..b6610d8a7 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -58,7 +58,8 @@ namespace Nif namespace NifOgre { -// FIXME: This should not be in NifOgre, it works agnostic of what model format is used +// FIXME: These should not be in NifOgre, it works agnostic of what model format is used +typedef std::map TextKeyMap; struct EntityList { std::vector mEntities; Ogre::Entity *mSkelBase; @@ -67,11 +68,11 @@ struct EntityList { { } }; + /** This holds a list of meshes along with the names of their parent nodes */ typedef std::vector< std::pair > MeshPairList; - /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into something Ogre can use. @@ -86,7 +87,7 @@ typedef std::vector< std::pair > MeshPairList; */ class NIFLoader { - static MeshPairList load(std::string name, std::string skelName, const std::string &group); + static MeshPairList load(std::string name, std::string skelName, TextKeyMap *textkeys, const std::string &group); public: static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, @@ -95,6 +96,7 @@ public: const std::string &group="General"); static EntityList createEntities(Ogre::SceneNode *parent, + TextKeyMap *textkeys, const std::string &name, const std::string &group="General"); }; From f953d7f8c0c0145def6fc81f265d931adfca15bf Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 23 Jul 2012 17:27:35 -0700 Subject: [PATCH 090/126] Store text keys from base NIF animations --- apps/openmw/mwrender/animation.hpp | 1 + apps/openmw/mwrender/creatureanimation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index ae1477666..dd1fdc95e 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -30,6 +30,7 @@ protected: bool mSkipFrame; NifOgre::EntityList mEntityList; + NifOgre::TextKeyMap mTextKeys; public: Animation(OEngine::Render::OgreRenderer& _rend); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 4086f4f7a..7fb153bd1 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -26,7 +26,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O { std::string mesh = "meshes\\" + ref->base->model; - mEntityList = NifOgre::NIFLoader::createEntities(mInsert, NULL, mesh); + mEntityList = NifOgre::NIFLoader::createEntities(mInsert, &mTextKeys, mesh); for(size_t i = 0;i < mEntityList.mEntities.size();i++) { Ogre::Entity *ent = mEntityList.mEntities[i]; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 47135b35d..4f98aebc4 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -89,7 +89,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); - mEntityList = NifOgre::NIFLoader::createEntities(mInsert, NULL, smodel); + mEntityList = NifOgre::NIFLoader::createEntities(mInsert, &mTextKeys, smodel); for(size_t i = 0;i < mEntityList.mEntities.size();i++) { Ogre::Entity *base = mEntityList.mEntities[i]; From 9a7a629d0f82bd224a518901757d3282c23015ad Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Jul 2012 13:51:48 -0700 Subject: [PATCH 091/126] Add support for playing animation groups --- apps/openmw/mwrender/animation.cpp | 137 +++++++++++++++++++++++++---- apps/openmw/mwrender/animation.hpp | 8 ++ 2 files changed, 129 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 653a506e8..27ab3995a 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -7,6 +7,7 @@ #include #include + namespace MWRender { std::map Animation::sUniqueIDs; @@ -28,16 +29,117 @@ Animation::~Animation() mEntityList.mEntities.clear(); } -void Animation::playGroup(std::string groupname, int mode, int loops) -{ - if(groupname == "all") + +struct checklow { + bool operator()(const char &a, const char &b) const { - mAnimate = loops; - mTime = 0.0f; + return ::tolower(a) == ::tolower(b); } +}; + +bool Animation::findGroupTimes(const std::string &groupname, float *starttime, float *stoptime, float *loopstarttime, float *loopstoptime) +{ + const std::string &start = groupname+": start"; + const std::string &startloop = groupname+": loop start"; + const std::string &stop = groupname+": stop"; + const std::string &stoploop = groupname+": loop stop"; + + *starttime = -1.0f; + *stoptime = -1.0f; + *loopstarttime = -1.0f; + *loopstoptime = -1.0f; + + NifOgre::TextKeyMap::const_iterator iter; + for(iter = mTextKeys.begin();iter != mTextKeys.end();iter++) + { + if(*starttime >= 0.0f && *stoptime >= 0.0f && *loopstarttime >= 0.0f && *loopstoptime >= 0.0f) + return true; + + std::string::const_iterator strpos = iter->second.begin(); + std::string::const_iterator strend = iter->second.end(); + + while(strpos != strend) + { + size_t strlen = strend-strpos; + std::string::const_iterator striter; + + if(start.size() <= strlen && + ((striter=std::mismatch(strpos, strend, start.begin(), checklow()).first) == strend || + *striter == '\r' || *striter == '\n')) + { + *starttime = iter->first; + *loopstarttime = iter->first; + } + else if(startloop.size() <= strlen && + ((striter=std::mismatch(strpos, strend, startloop.begin(), checklow()).first) == strend || + *striter == '\r' || *striter == '\n')) + { + *loopstarttime = iter->first; + } + else if(stoploop.size() <= strlen && + ((striter=std::mismatch(strpos, strend, stoploop.begin(), checklow()).first) == strend || + *striter == '\r' || *striter == '\n')) + { + *loopstoptime = iter->first; + } + else if(stop.size() <= strlen && + ((striter=std::mismatch(strpos, strend, stop.begin(), checklow()).first) == strend || + *striter == '\r' || *striter == '\n')) + { + *stoptime = iter->first; + if(*loopstoptime < 0.0f) + *loopstoptime = iter->first; + break; + } + + strpos = std::find(strpos+1, strend, '\n'); + while(strpos != strend && *strpos == '\n') + strpos++; + } + } + + return (*starttime >= 0.0f && *stoptime >= 0.0f && *loopstarttime >= 0.0f && *loopstoptime >= 0.0f); } +void Animation::playGroup(std::string groupname, int mode, int loops) +{ + float start, stop, loopstart, loopstop; + + if(groupname == "all") + { + mLoopStartTime = mStartTime = 0.0f; + mLoopStopTime = mStopTime = 0.0f; + + if(mEntityList.mSkelBase) + { + Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); + Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); + while(as.hasMoreElements()) + { + Ogre::AnimationState *state = as.getNext(); + mLoopStopTime = mStopTime = state->getLength(); + break; + } + } + + mAnimate = loops; + mTime = mStartTime; + } + else if(findGroupTimes(groupname, &start, &stop, &loopstart, &loopstop)) + { + mStartTime = start; + mStopTime = stop; + mLoopStartTime = loopstart; + mLoopStopTime = loopstop; + + mAnimate = loops; + mTime = mStartTime; + } + else + throw std::runtime_error("Failed to find animation group "+groupname); +} + void Animation::skipAnim() { mSkipFrame = true; @@ -45,9 +147,22 @@ void Animation::skipAnim() void Animation::runAnimation(float timepassed) { - if(mAnimate != 0 && !mSkipFrame) + if(mAnimate > 0 && !mSkipFrame) { mTime += timepassed; + if(mTime >= mLoopStopTime) + { + if(mAnimate > 1) + { + mAnimate--; + mTime = mTime - mLoopStopTime + mLoopStartTime; + } + else if(mTime >= mStopTime) + { + mAnimate--; + mTime = mStopTime; + } + } if(mEntityList.mSkelBase) { @@ -57,16 +172,6 @@ void Animation::runAnimation(float timepassed) { Ogre::AnimationState *state = as.getNext(); state->setTimePosition(mTime); - if(mTime >= state->getLength()) - { - if(mAnimate != -1) - mAnimate--; - //std::cout << "Stopping the animation\n"; - if(mAnimate == 0) - mTime = state->getLength(); - else - mTime = mTime - state->getLength(); - } } } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index dd1fdc95e..fb9330114 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -26,12 +26,20 @@ protected: static std::map sUniqueIDs; float mTime; + float mStartTime; + float mStopTime; + float mLoopStartTime; + float mLoopStopTime; + int mAnimate; bool mSkipFrame; NifOgre::EntityList mEntityList; NifOgre::TextKeyMap mTextKeys; + bool findGroupTimes(const std::string &groupname, float *starttime, float *stoptime, + float *loopstarttime, float *loopstoptime); + public: Animation(OEngine::Render::OgreRenderer& _rend); virtual ~Animation(); From 20121f3b0a1f5732cb4d76e66cc6e1039d0f048f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Jul 2012 13:56:28 -0700 Subject: [PATCH 092/126] Remove some unused stuff --- apps/openmw/mwrender/animation.cpp | 1 - apps/openmw/mwrender/animation.hpp | 6 ------ 2 files changed, 7 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 27ab3995a..6a04f62b5 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -10,7 +10,6 @@ namespace MWRender { -std::map Animation::sUniqueIDs; Animation::Animation(OEngine::Render::OgreRenderer& _rend) : mInsert(NULL) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index fb9330114..cb0e92367 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -14,16 +14,10 @@ namespace MWRender { -struct PosAndRot { - Ogre::Quaternion vecRot; - Ogre::Vector3 vecPos; -}; - class Animation { protected: Ogre::SceneNode* mInsert; OEngine::Render::OgreRenderer &mRend; - static std::map sUniqueIDs; float mTime; float mStartTime; From fd1e3f6ec55f1aee15fd0ab5514fdeb362370623 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Jul 2012 14:14:32 -0700 Subject: [PATCH 093/126] Add support for playgroup mode 2 --- apps/openmw/mwrender/animation.cpp | 33 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 6a04f62b5..f6beeb52f 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -107,8 +107,8 @@ void Animation::playGroup(std::string groupname, int mode, int loops) if(groupname == "all") { - mLoopStartTime = mStartTime = 0.0f; - mLoopStopTime = mStopTime = 0.0f; + start = loopstart = 0.0f; + loopstop = stop = 0.0f; if(mEntityList.mSkelBase) { @@ -117,26 +117,25 @@ void Animation::playGroup(std::string groupname, int mode, int loops) while(as.hasMoreElements()) { Ogre::AnimationState *state = as.getNext(); - mLoopStopTime = mStopTime = state->getLength(); + loopstop = stop = state->getLength(); break; } } - - mAnimate = loops; - mTime = mStartTime; } - else if(findGroupTimes(groupname, &start, &stop, &loopstart, &loopstop)) - { - mStartTime = start; - mStopTime = stop; - mLoopStartTime = loopstart; - mLoopStopTime = loopstop; - - mAnimate = loops; - mTime = mStartTime; - } - else + else if(!findGroupTimes(groupname, &start, &stop, &loopstart, &loopstop)) throw std::runtime_error("Failed to find animation group "+groupname); + + // FIXME: mode = 0 not yet supported + if(mode == 0) + mode = 1; + + mStartTime = start; + mStopTime = stop; + mLoopStartTime = loopstart; + mLoopStopTime = loopstop; + + mAnimate = loops; + mTime = ((mode==1) ? mStartTime : mLoopStartTime); } void Animation::skipAnim() From 13ab2baef0967333d8aad0eee6d964edb2a30734 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Jul 2012 14:42:01 -0700 Subject: [PATCH 094/126] Use a struct to hold the current animation times and remaining loop count --- apps/openmw/mwrender/animation.cpp | 61 +++++++++++++----------------- apps/openmw/mwrender/animation.hpp | 23 +++++++---- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index f6beeb52f..fe77da52b 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -15,7 +15,6 @@ Animation::Animation(OEngine::Render::OgreRenderer& _rend) : mInsert(NULL) , mRend(_rend) , mTime(0.0f) - , mAnimate(0) , mSkipFrame(false) { } @@ -36,22 +35,17 @@ struct checklow { } }; -bool Animation::findGroupTimes(const std::string &groupname, float *starttime, float *stoptime, float *loopstarttime, float *loopstoptime) +bool Animation::findGroupTimes(const std::string &groupname, Animation::GroupTimes *times) { const std::string &start = groupname+": start"; const std::string &startloop = groupname+": loop start"; const std::string &stop = groupname+": stop"; const std::string &stoploop = groupname+": loop stop"; - *starttime = -1.0f; - *stoptime = -1.0f; - *loopstarttime = -1.0f; - *loopstoptime = -1.0f; - NifOgre::TextKeyMap::const_iterator iter; for(iter = mTextKeys.begin();iter != mTextKeys.end();iter++) { - if(*starttime >= 0.0f && *stoptime >= 0.0f && *loopstarttime >= 0.0f && *loopstoptime >= 0.0f) + if(times->mStart >= 0.0f && times->mLoopStart >= 0.0f && times->mLoopStop >= 0.0f && times->mStop >= 0.0f) return true; std::string::const_iterator strpos = iter->second.begin(); @@ -66,28 +60,28 @@ bool Animation::findGroupTimes(const std::string &groupname, float *starttime, f ((striter=std::mismatch(strpos, strend, start.begin(), checklow()).first) == strend || *striter == '\r' || *striter == '\n')) { - *starttime = iter->first; - *loopstarttime = iter->first; + times->mStart = iter->first; + times->mLoopStart = iter->first; } else if(startloop.size() <= strlen && ((striter=std::mismatch(strpos, strend, startloop.begin(), checklow()).first) == strend || *striter == '\r' || *striter == '\n')) { - *loopstarttime = iter->first; + times->mLoopStart = iter->first; } else if(stoploop.size() <= strlen && ((striter=std::mismatch(strpos, strend, stoploop.begin(), checklow()).first) == strend || *striter == '\r' || *striter == '\n')) { - *loopstoptime = iter->first; + times->mLoopStop = iter->first; } else if(stop.size() <= strlen && ((striter=std::mismatch(strpos, strend, stop.begin(), checklow()).first) == strend || *striter == '\r' || *striter == '\n')) { - *stoptime = iter->first; - if(*loopstoptime < 0.0f) - *loopstoptime = iter->first; + times->mStop = iter->first; + if(times->mLoopStop < 0.0f) + times->mLoopStop = iter->first; break; } @@ -97,18 +91,19 @@ bool Animation::findGroupTimes(const std::string &groupname, float *starttime, f } } - return (*starttime >= 0.0f && *stoptime >= 0.0f && *loopstarttime >= 0.0f && *loopstoptime >= 0.0f); + return (times->mStart >= 0.0f && times->mLoopStart >= 0.0f && times->mLoopStop >= 0.0f && times->mStop >= 0.0f); } void Animation::playGroup(std::string groupname, int mode, int loops) { - float start, stop, loopstart, loopstop; + GroupTimes times; + times.mLoops = loops; if(groupname == "all") { - start = loopstart = 0.0f; - loopstop = stop = 0.0f; + times.mStart = times.mLoopStart = 0.0f; + times.mLoopStop = times.mStop = 0.0f; if(mEntityList.mSkelBase) { @@ -117,25 +112,21 @@ void Animation::playGroup(std::string groupname, int mode, int loops) while(as.hasMoreElements()) { Ogre::AnimationState *state = as.getNext(); - loopstop = stop = state->getLength(); + times.mLoopStop = times.mStop = state->getLength(); break; } } } - else if(!findGroupTimes(groupname, &start, &stop, &loopstart, &loopstop)) + else if(!findGroupTimes(groupname, ×)) throw std::runtime_error("Failed to find animation group "+groupname); // FIXME: mode = 0 not yet supported if(mode == 0) mode = 1; - mStartTime = start; - mStopTime = stop; - mLoopStartTime = loopstart; - mLoopStopTime = loopstop; + mCurGroup = times; - mAnimate = loops; - mTime = ((mode==1) ? mStartTime : mLoopStartTime); + mTime = ((mode==1) ? mCurGroup.mStart : mCurGroup.mLoopStart); } void Animation::skipAnim() @@ -145,20 +136,20 @@ void Animation::skipAnim() void Animation::runAnimation(float timepassed) { - if(mAnimate > 0 && !mSkipFrame) + if(mCurGroup.mLoops > 0 && !mSkipFrame) { mTime += timepassed; - if(mTime >= mLoopStopTime) + if(mTime >= mCurGroup.mLoopStop) { - if(mAnimate > 1) + if(mCurGroup.mLoops > 1) { - mAnimate--; - mTime = mTime - mLoopStopTime + mLoopStartTime; + mCurGroup.mLoops--; + mTime = mTime - mCurGroup.mLoopStop + mCurGroup.mLoopStart; } - else if(mTime >= mStopTime) + else if(mTime >= mCurGroup.mStop) { - mAnimate--; - mTime = mStopTime; + mCurGroup.mLoops--; + mTime = mCurGroup.mStop; } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index cb0e92367..c9b34a4e5 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -15,24 +15,33 @@ namespace MWRender { class Animation { + struct GroupTimes { + float mStart; + float mStop; + float mLoopStart; + float mLoopStop; + + size_t mLoops; + + GroupTimes() + : mStart(-1.0f), mStop(-1.0f), mLoopStart(-1.0f), mLoopStop(-1.0f), + mLoops(0) + { } + }; + protected: Ogre::SceneNode* mInsert; OEngine::Render::OgreRenderer &mRend; float mTime; - float mStartTime; - float mStopTime; - float mLoopStartTime; - float mLoopStopTime; + GroupTimes mCurGroup; - int mAnimate; bool mSkipFrame; NifOgre::EntityList mEntityList; NifOgre::TextKeyMap mTextKeys; - bool findGroupTimes(const std::string &groupname, float *starttime, float *stoptime, - float *loopstarttime, float *loopstoptime); + bool findGroupTimes(const std::string &groupname, GroupTimes *times); public: Animation(OEngine::Render::OgreRenderer& _rend); From 9f0c1eeb7b8562ac64206eebe81edd701eaba2e3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Jul 2012 14:54:12 -0700 Subject: [PATCH 095/126] Support playgroup mode 0 --- apps/openmw/mwrender/animation.cpp | 23 ++++++++++++++--------- apps/openmw/mwrender/animation.hpp | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index fe77da52b..46f3bdc0d 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -120,13 +120,14 @@ void Animation::playGroup(std::string groupname, int mode, int loops) else if(!findGroupTimes(groupname, ×)) throw std::runtime_error("Failed to find animation group "+groupname); - // FIXME: mode = 0 not yet supported - if(mode == 0) - mode = 1; - - mCurGroup = times; - - mTime = ((mode==1) ? mCurGroup.mStart : mCurGroup.mLoopStart); + if(mode == 0 && mCurGroup.mLoops > 0) + mNextGroup = times; + else + { + mCurGroup = times; + mNextGroup = GroupTimes(); + mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart); + } } void Animation::skipAnim() @@ -148,8 +149,12 @@ void Animation::runAnimation(float timepassed) } else if(mTime >= mCurGroup.mStop) { - mCurGroup.mLoops--; - mTime = mCurGroup.mStop; + if(mNextGroup.mLoops > 0) + mTime = mTime - mCurGroup.mStop + mNextGroup.mStart; + else + mTime = mCurGroup.mStop; + mCurGroup = mNextGroup; + mNextGroup = GroupTimes(); } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index c9b34a4e5..3611d35c0 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -35,6 +35,7 @@ protected: float mTime; GroupTimes mCurGroup; + GroupTimes mNextGroup; bool mSkipFrame; From 4f46c8a8db6cbe532492be39d6369e5360662cea Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 24 Jul 2012 14:59:25 -0700 Subject: [PATCH 096/126] Use a functor for the mismatch compare function --- components/nifogre/ogre_nif_loader.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9df8dd916..803300282 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1057,10 +1057,12 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textke return entitylist; } -static bool checklow(const char &a, const char &b) -{ - return ::tolower(a) == ::tolower(b); -} +struct checklow { + bool operator()(const char &a, const char &b) const + { + return ::tolower(a) == ::tolower(b); + } +}; EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bonename, Ogre::SceneNode *parentNode, @@ -1081,7 +1083,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo if(ent->hasSkeleton()) { if(meshes[i].second.length() < filter.length() || - std::mismatch(filter.begin(), filter.end(), meshes[i].second.begin(), checklow).first != filter.end()) + std::mismatch(filter.begin(), filter.end(), meshes[i].second.begin(), checklow()).first != filter.end()) { sceneMgr->destroyEntity(ent); meshes.erase(meshes.begin()+i); From 0f40e6fc65b4a983ef6a159cf6076d07a463324b Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Wed, 25 Jul 2012 00:47:08 +0200 Subject: [PATCH 097/126] find boost without components so we can use Boost_VERSION --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f124f1383..ea0c41fe2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,9 @@ if (UNIX AND NOT APPLE) find_package (Threads) endif() +# find boost without components so we can use Boost_VERSION +find_package(Boost REQUIRED) + set(BOOST_COMPONENTS system filesystem program_options thread) if (Boost_VERSION LESS 104900) From 61cb012ee7dd1f356af408bccc1ed9a59b2461af Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 24 Jul 2012 11:15:20 +0400 Subject: [PATCH 098/126] moving Scene::insertObject to CellStore::insertObject, part 1 --- apps/openmw/mwworld/cellstore.cpp | 116 ++++++++++++++++++++++++++- apps/openmw/mwworld/cellstore.hpp | 9 +++ apps/openmw/mwworld/scene.cpp | 129 ------------------------------ apps/openmw/mwworld/scene.hpp | 4 - apps/openmw/mwworld/worldimp.cpp | 3 +- 5 files changed, 126 insertions(+), 135 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 60a7eb6e1..22c94cf75 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -1,10 +1,12 @@ - #include "cellstore.hpp" #include #include +#include "ptr.hpp" +#include "manualref.hpp" + namespace MWWorld { CellStore::CellStore (const ESM::Cell *cell_) : cell (cell_), mState (State_Unloaded) @@ -121,4 +123,116 @@ namespace MWWorld } } } + + /// \todo this whole code needs major clean up + void CellStore::insertObject (const Ptr& ptr) + { + std::string type = ptr.getTypeName(); + + MWWorld::Ptr newPtr; + + // insert into the correct CellRefList + if (type == typeid(ESM::Potion).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&potions.insert(*ref), this); + } + else if (type == typeid(ESM::Apparatus).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&appas.insert(*ref), this); + } + else if (type == typeid(ESM::Armor).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&armors.insert(*ref), this); + } + else if (type == typeid(ESM::Book).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&books.insert(*ref), this); + } + else if (type == typeid(ESM::Clothing).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&clothes.insert(*ref), this); + } + else if (type == typeid(ESM::Ingredient).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&ingreds.insert(*ref), this); + } + else if (type == typeid(ESM::Light).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&lights.insert(*ref), this); + } + else if (type == typeid(ESM::Tool).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&lockpicks.insert(*ref), this); + } + else if (type == typeid(ESM::Repair).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&repairs.insert(*ref), this); + } + else if (type == typeid(ESM::Probe).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&probes.insert(*ref), this); + } + else if (type == typeid(ESM::Weapon).name()) + { + MWWorld::LiveCellRef* ref = ptr.get(); + newPtr = MWWorld::Ptr(&weapons.insert(*ref), this); + } + else if (type == typeid(ESM::Miscellaneous).name()) + { + + // if this is gold, we need to fetch the correct mesh depending on the amount of gold. + if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) + { + int goldAmount = ptr.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 100) + base = "Gold_100"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; + + MWWorld::ManualRef newRef( + MWBase::Environment::get().getWorld()->getStore(), + base); + + MWWorld::LiveCellRef* ref = + newRef.getPtr().get(); + + newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); + + ESM::Position& p = newPtr.getRefData().getPosition(); + p.pos[0] = ptr.getRefData().getPosition().pos[0]; + p.pos[1] = ptr.getRefData().getPosition().pos[1]; + p.pos[2] = ptr.getRefData().getPosition().pos[2]; + } + else + { + MWWorld::LiveCellRef* ref = + ptr.get(); + + newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); + } + } + else + throw std::runtime_error("Trying to insert object of unhandled type"); + + newPtr.getRefData().setCount(ptr.getRefData().getCount()); + ptr.getRefData().setCount(0); + newPtr.getRefData().enable(); + } + } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index de3ac12ae..3dcde9359 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -15,6 +15,8 @@ namespace ESMS namespace MWWorld { + class Ptr; + /// A reference to one object (of any type) in a cell. /// /// Constructing this with a CellRef instance in the constructor means that @@ -73,6 +75,11 @@ namespace MWWorld return 0; } + + LiveRef &insert(const LiveRef &item) { + list.push_back(item); + return list.back(); + } }; /// A storage struct for one single cell reference. @@ -165,6 +172,8 @@ namespace MWWorld void listRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm); void loadRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm); + + void insertObject(const MWWorld::Ptr &ptr); }; } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 33c67aad8..9786c24d9 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -9,8 +9,6 @@ #include "../mwgui/window_manager.hpp" -#include "../mwworld/manualref.hpp" /// FIXME - #include "player.hpp" #include "localscripts.hpp" @@ -334,133 +332,6 @@ namespace MWWorld insertCellRefList(mRendering, cell.weapons, cell, *mPhysics); } - - /// \todo this whole code needs major clean up, and doesn't belong in this class. - void Scene::insertObject (const Ptr& ptr, CellStore* cell) - { - std::string type = ptr.getTypeName(); - - MWWorld::Ptr newPtr; - - // insert into the correct CellRefList - if (type == typeid(ESM::Potion).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->potions.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->potions.list.back(), cell); - } - else if (type == typeid(ESM::Apparatus).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->appas.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->appas.list.back(), cell); - } - else if (type == typeid(ESM::Armor).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->armors.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->armors.list.back(), cell); - } - else if (type == typeid(ESM::Book).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->books.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->books.list.back(), cell); - } - else if (type == typeid(ESM::Clothing).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->clothes.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->clothes.list.back(), cell); - } - else if (type == typeid(ESM::Ingredient).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->ingreds.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->ingreds.list.back(), cell); - } - else if (type == typeid(ESM::Light).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->lights.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->lights.list.back(), cell); - } - else if (type == typeid(ESM::Tool).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->lockpicks.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->lockpicks.list.back(), cell); - } - else if (type == typeid(ESM::Repair).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->repairs.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->repairs.list.back(), cell); - } - else if (type == typeid(ESM::Probe).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->probes.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->probes.list.back(), cell); - } - else if (type == typeid(ESM::Weapon).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - cell->weapons.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->weapons.list.back(), cell); - } - else if (type == typeid(ESM::Miscellaneous).name()) - { - - // if this is gold, we need to fetch the correct mesh depending on the amount of gold. - if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) - { - int goldAmount = ptr.getRefData().getCount(); - - std::string base = "Gold_001"; - if (goldAmount >= 100) - base = "Gold_100"; - else if (goldAmount >= 25) - base = "Gold_025"; - else if (goldAmount >= 10) - base = "Gold_010"; - else if (goldAmount >= 5) - base = "Gold_005"; - - MWWorld::ManualRef newRef (MWBase::Environment::get().getWorld()->getStore(), base); - - MWWorld::LiveCellRef* ref = newRef.getPtr().get(); - - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); - - ESM::Position& p = newPtr.getRefData().getPosition(); - p.pos[0] = ptr.getRefData().getPosition().pos[0]; - p.pos[1] = ptr.getRefData().getPosition().pos[1]; - p.pos[2] = ptr.getRefData().getPosition().pos[2]; - } - else - { - MWWorld::LiveCellRef* ref = ptr.get(); - - cell->miscItems.list.push_back( *ref ); - newPtr = MWWorld::Ptr(&cell->miscItems.list.back(), cell); - } - } - else - throw std::runtime_error("Trying to insert object of unhandled type"); - - - - newPtr.getRefData().setCount(ptr.getRefData().getCount()); - ptr.getRefData().setCount(0); - newPtr.getRefData().enable(); - - mRendering.addObject(newPtr); - MWWorld::Class::get(newPtr).insertObject(newPtr, *mPhysics); - - } - void Scene::addObjectToScene (const Ptr& ptr) { mRendering.addObject (ptr); diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index c0b93796a..f5f4b640b 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -88,10 +88,6 @@ namespace MWWorld void insertCell (Ptr::CellStore &cell); - /// this method is only meant for dropping objects into the gameworld from a container - /// and thus only handles object types that can be placed in a container - void insertObject (const Ptr& object, CellStore* cell); - void update (float duration); void addObjectToScene (const Ptr& ptr); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a68f08e34..4ffcd33f8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1021,7 +1021,8 @@ namespace MWWorld pos.pos[1] = -result.second[2]; pos.pos[2] = result.second[1]; - mWorldScene->insertObject(object, cell); + cell->insertObject(object); + //TODO mWorldScene->addObjectToScene /// \todo retrieve the bounds of the object and translate it accordingly From 71253c64ab8f11205fef1dc191be78275ff80937 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 24 Jul 2012 12:30:59 +0400 Subject: [PATCH 099/126] moving part 2, adding position parameter, stable --- apps/openmw/mwworld/cellstore.cpp | 13 +++++++++++-- apps/openmw/mwworld/cellstore.hpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 16 +++++++--------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 22c94cf75..088c0c623 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -4,8 +4,12 @@ #include +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + #include "ptr.hpp" #include "manualref.hpp" +#include "class.hpp" namespace MWWorld { @@ -125,7 +129,7 @@ namespace MWWorld } /// \todo this whole code needs major clean up - void CellStore::insertObject (const Ptr& ptr) + const MWWorld::Ptr CellStore::insertObject (const Ptr& ptr, const ESM::Position &pos) { std::string type = ptr.getTypeName(); @@ -213,11 +217,12 @@ namespace MWWorld newRef.getPtr().get(); newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); - + /* ESM::Position& p = newPtr.getRefData().getPosition(); p.pos[0] = ptr.getRefData().getPosition().pos[0]; p.pos[1] = ptr.getRefData().getPosition().pos[1]; p.pos[2] = ptr.getRefData().getPosition().pos[2]; + */ } else { @@ -230,9 +235,13 @@ namespace MWWorld else throw std::runtime_error("Trying to insert object of unhandled type"); + newPtr.getRefData().getPosition() = pos; + newPtr.getRefData().setCount(ptr.getRefData().getCount()); ptr.getRefData().setCount(0); newPtr.getRefData().enable(); + + return newPtr; } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 3dcde9359..1bf233a50 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -155,6 +155,8 @@ namespace MWWorld forEachImp (functor, weapons); } + const MWWorld::Ptr insertObject(const MWWorld::Ptr &ptr, const ESM::Position &pos); + private: template @@ -172,8 +174,6 @@ namespace MWWorld void listRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm); void loadRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm); - - void insertObject(const MWWorld::Ptr &ptr); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 4ffcd33f8..efb17a709 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1016,13 +1016,13 @@ namespace MWWorld else cell = getPlayer().getPlayer().getCell(); - ESM::Position& pos = object.getRefData().getPosition(); + ESM::Position pos = getPlayer().getPlayer().getRefData().getPosition(); pos.pos[0] = result.second[0]; pos.pos[1] = -result.second[2]; pos.pos[2] = result.second[1]; - cell->insertObject(object); - //TODO mWorldScene->addObjectToScene + MWWorld::Ptr dropped = cell->insertObject(object, pos); + mWorldScene->addObjectToScene(dropped); /// \todo retrieve the bounds of the object and translate it accordingly @@ -1044,14 +1044,12 @@ namespace MWWorld { MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell(); - float* playerPos = getPlayer().getPlayer().getRefData().getPosition().pos; + ESM::Position &pos = + getPlayer().getPlayer().getRefData().getPosition(); - ESM::Position& pos = object.getRefData().getPosition(); - pos.pos[0] = playerPos[0]; - pos.pos[1] = playerPos[1]; - pos.pos[2] = playerPos[2]; + MWWorld::Ptr dropped = cell->insertObject(object, pos); - mWorldScene->insertObject(object, cell); + mWorldScene->addObjectToScene(dropped); } void World::processChangedSettings(const Settings::CategorySettingVector& settings) From 87050e48c8d757afe2c1fe9819c06bb9c7d978e6 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 24 Jul 2012 18:52:08 +0400 Subject: [PATCH 100/126] physics getObjectHeight(), MWWorld::Class::getModel() definition --- apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 2 ++ apps/openmw/mwworld/physicssystem.cpp | 10 ++++++++++ apps/openmw/mwworld/physicssystem.hpp | 2 ++ libs/openengine/bullet/physic.cpp | 21 +++++++++++++++++++++ libs/openengine/bullet/physic.hpp | 2 ++ 6 files changed, 42 insertions(+) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 65fa91666..f973301c5 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -212,4 +212,9 @@ namespace MWWorld void Class::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const { } + + std::string Class::getModel() const + { + return ""; + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 3d3ed71ec..5f16ef593 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -204,6 +204,8 @@ namespace MWWorld virtual void adjustScale(const MWWorld::Ptr& ptr,float& scale) const; virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; + + virtual std::string getModel() const; }; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index bf5c001db..db1db0505 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -14,6 +14,7 @@ #include "../mwbase/world.hpp" // FIXME #include "ptr.hpp" +#include "class.hpp" using namespace Ogre; namespace MWWorld @@ -365,4 +366,13 @@ namespace MWWorld addActor (node->getName(), model, node->getPosition()); } + float PhysicsSystem::getObjectHeight(const MWWorld::Ptr &ptr) { + std::string model = MWWorld::Class::get(ptr).getModel(); + if (model.empty()) { + return 0.0; + } + float scale = ptr.getRefData().getBaseNode()->getScale().x; + return mEngine->getObjectHeight(model, scale); + } + } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index a6b679833..61e2590bd 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -65,6 +65,8 @@ namespace MWWorld void setCurrentWater(bool hasWater, int waterHeight); + float getObjectHeight(const MWWorld::Ptr &ptr); + private: OEngine::Render::OgreRenderer &mRender; OEngine::Physic::PhysicEngine* mEngine; diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 61d0c7b0e..416d0c09d 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -568,4 +568,25 @@ namespace Physic return results2; } + + float PhysicEngine::getObjectHeight(const std::string &mesh, float scale) { + char uniqueID[8]; + sprintf( uniqueID, "%07.3f", scale ); + std::string sid = uniqueID; + std::string outputstring = mesh + uniqueID + "\"|"; + + mShapeLoader->load(outputstring, "General"); + BulletShapeManager::getSingletonPtr()->load(outputstring, "General"); + BulletShapePtr shape = + BulletShapeManager::getSingleton().getByName(outputstring, "General"); + + + btTransform trans; + btVector3 min, max; + + trans.setIdentity(); + shape->Shape->getAabb(trans, min, max); + + return max.z() - min.z(); + } }}; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 3988c75a4..22c5fa274 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -221,6 +221,8 @@ namespace Physic bool toggleDebugRendering(); + float getObjectHeight(const std::string &mesh, float scale); + /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). */ From 6a3a728a56f76d2a74277f1b52b77355c649b3e0 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 24 Jul 2012 20:22:11 +0400 Subject: [PATCH 101/126] Class::getModel implementation --- apps/openmw/mwclass/activator.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/activator.hpp | 2 ++ apps/openmw/mwclass/apparatus.cpp | 31 ++++++++++++++------------- apps/openmw/mwclass/apparatus.hpp | 2 ++ apps/openmw/mwclass/armor.cpp | 28 +++++++++++++----------- apps/openmw/mwclass/armor.hpp | 1 + apps/openmw/mwclass/book.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/book.hpp | 2 ++ apps/openmw/mwclass/clothing.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/clothing.hpp | 2 ++ apps/openmw/mwclass/container.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/container.hpp | 2 ++ apps/openmw/mwclass/creature.cpp | 18 +++++++++++----- apps/openmw/mwclass/creature.hpp | 2 ++ apps/openmw/mwclass/door.cpp | 29 ++++++++++++++----------- apps/openmw/mwclass/door.hpp | 2 ++ apps/openmw/mwclass/ingredient.cpp | 27 ++++++++++++----------- apps/openmw/mwclass/ingredient.hpp | 2 ++ apps/openmw/mwclass/light.cpp | 25 +++++++++++++++------ apps/openmw/mwclass/light.hpp | 2 ++ apps/openmw/mwclass/lockpick.cpp | 30 +++++++++++++------------- apps/openmw/mwclass/lockpick.hpp | 2 ++ apps/openmw/mwclass/misc.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/misc.hpp | 2 ++ apps/openmw/mwclass/npc.cpp | 30 +++++++++++++++----------- apps/openmw/mwclass/npc.hpp | 2 ++ apps/openmw/mwclass/potion.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/potion.hpp | 2 ++ apps/openmw/mwclass/probe.cpp | 30 +++++++++++++------------- apps/openmw/mwclass/probe.hpp | 2 ++ apps/openmw/mwclass/repair.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/repair.hpp | 2 ++ apps/openmw/mwclass/static.cpp | 28 +++++++++++++----------- apps/openmw/mwclass/static.hpp | 2 ++ apps/openmw/mwclass/weapon.cpp | 29 +++++++++++++------------ apps/openmw/mwclass/weapon.hpp | 1 + apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- apps/openmw/mwworld/physicssystem.cpp | 3 +-- 39 files changed, 312 insertions(+), 237 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 81a47ccb0..33baad7ca 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -19,32 +19,33 @@ namespace MWClass { void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Activator::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Activator::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Activator::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 223dd0a36..2e947a9fc 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -28,6 +28,8 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 7e3c3b8f9..dd255f9f8 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -22,34 +22,35 @@ namespace MWClass { - void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const + void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Apparatus::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Apparatus::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Apparatus::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index f33f92e2c..fa77eec93 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -48,6 +48,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 380c596d7..8bbb198cc 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -27,31 +27,33 @@ namespace MWClass { void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Armor::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Armor::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Armor::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index a63806162..181a4ce61 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -66,6 +66,7 @@ namespace MWClass const; ///< Generate action for using via inventory menu + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index a37da0fd7..62b6c8204 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -23,32 +23,33 @@ namespace MWClass { void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Book::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Book::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Book::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index ee3aac8d8..20ea89274 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -50,6 +50,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 6c34b5e56..e1ec5a61c 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -25,32 +25,33 @@ namespace MWClass { void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Clothing::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Clothing::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Clothing::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index aba317be0..6b5fe1e96 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -59,6 +59,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 8dd27db42..7c5719b8e 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -54,32 +54,33 @@ namespace MWClass void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Container::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Container::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } boost::shared_ptr Container::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 739c75c77..17a9ac4ea 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -51,6 +51,8 @@ namespace MWClass ///< Unlock object static void registerSelf(); + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 83370478f..178a6f536 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -86,17 +86,25 @@ namespace MWClass } void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()){ + physics.insertActorPhysics(ptr, model); + } + MWBase::Environment::get().getMechanicsManager()->addActor (ptr); + } + + std::string Creature::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); + assert (ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertActorPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - - MWBase::Environment::get().getMechanicsManager()->addActor (ptr); + return ""; } std::string Creature::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 1274be09a..b994e0831 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -54,6 +54,8 @@ namespace MWClass /// effects). Throws an exception, if the object can't hold other objects. static void registerSelf(); + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index b0bba2c03..1274219a9 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -25,30 +25,33 @@ namespace MWClass { void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { - MWWorld::LiveCellRef *ref = + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Door::getModel(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } + return ""; } std::string Door::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 63d1c1ab8..2612df41c 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -38,6 +38,8 @@ namespace MWClass ///< Return name of the script attached to ptr static void registerSelf(); + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 01146fe67..a2f14c02c 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -23,30 +23,33 @@ namespace MWClass { void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Ingredient::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Ingredient::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } + return ""; } std::string Ingredient::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 4c45bd69c..ad87dd46c 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -44,6 +44,8 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 15cd89ac2..37d7d1eec 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -28,8 +28,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + const std::string &model = ref->base->model; MWRender::Objects& objects = renderingInterface.getObjects(); @@ -50,20 +50,31 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + const std::string &model = ref->base->model; - if(!model.empty()){ + if(!model.empty()) { physics.insertObjectPhysics(ptr, "meshes\\" + model); } - - if (!ref->base->sound.empty()) - { - MWBase::Environment::get().getSoundManager()->playSound3D (ptr, ref->base->sound, 1.0, 1.0, MWSound::Play_Loop); + if (!ref->base->sound.empty()) { + MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->base->sound, 1.0, 1.0, MWSound::Play_Loop); } } + std::string Light::getModel(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + assert (ref->base != NULL); + + const std::string &model = ref->base->model; + if (!model.empty()) { + return "meshes\\" + model; + } + return ""; + } + std::string Light::getName (const MWWorld::Ptr& ptr) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 91193dfdc..ab8854efd 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -52,6 +52,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index d3d60315f..ae2b5de89 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -25,35 +25,35 @@ namespace MWClass { void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Lockpick::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } - std::string Lockpick::getName (const MWWorld::Ptr& ptr) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 26aab584c..45a02d40d 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -52,6 +52,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 8484a5dd1..89c1ef25f 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -27,32 +27,33 @@ namespace MWClass { void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Miscellaneous::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Miscellaneous::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index da5f0df96..23b5e9564 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -44,6 +44,8 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 80bff73fa..a5525fcda 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -125,25 +125,29 @@ namespace MWClass void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const { + physics.insertActorPhysics(ptr, getModel(ptr)); + MWBase::Environment::get().getMechanicsManager()->addActor(ptr); + } + std::string Npc::getModel(const MWWorld::Ptr &ptr) const + { MWWorld::LiveCellRef *ref = ptr.get(); - - assert (ref->base != NULL); - - + assert(ref->base != NULL); std::string headID = ref->base->head; - std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; + int end = headID.find_last_of("head_") - 4; + std::string bodyRaceID = headID.substr(0, end); - std::string smodel = "meshes\\base_anim.nif"; - if(beast) - smodel = "meshes\\base_animkna.nif"; - physics.insertActorPhysics(ptr, smodel); - - - MWBase::Environment::get().getMechanicsManager()->addActor (ptr); + std::string model = "meshes\\base_anim.nif"; + if (bodyRaceID == "b_n_khajiit_m_" || + bodyRaceID == "b_n_khajiit_f_" || + bodyRaceID == "b_n_argonian_m_" || + bodyRaceID == "b_n_argonian_f_") + { + model = "meshes\\base_animkna.nif"; + } + return model; } std::string Npc::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index b32a162a1..0ea45d132 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -88,6 +88,8 @@ namespace MWClass virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; static void registerSelf(); + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 45cb07840..92a951d03 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -25,32 +25,33 @@ namespace MWClass { void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Potion::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Potion::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Potion::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 101f4cefa..39edfd760 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -47,6 +47,8 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index f3a8406f5..033eee4c5 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -25,35 +25,35 @@ namespace MWClass { void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Probe::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Probe::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } - std::string Probe::getName (const MWWorld::Ptr& ptr) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 51b046fda..ff10eb9d6 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -52,6 +52,8 @@ namespace MWClass virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 464ba1091..4258ad106 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -23,32 +23,33 @@ namespace MWClass { void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Repair::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Repair::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Repair::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 1e935e154..689850b90 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -44,6 +44,8 @@ namespace MWClass virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; ///< Return name of inventory icon. + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 9b166b076..a14adc300 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -13,31 +13,33 @@ namespace MWClass { void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), true); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Static::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Static::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); + assert(ref->base != NULL); - assert (ref->base != NULL); const std::string &model = ref->base->model; - - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } + return ""; } std::string Static::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index c223df1ac..3066933e4 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -19,6 +19,8 @@ namespace MWClass /// can return an empty string. static void registerSelf(); + + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 099312d2c..6412a46b1 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -25,32 +25,33 @@ namespace MWClass { void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - assert (ref->base != NULL); - const std::string &model = ref->base->model; - - if (!model.empty()) - { + const std::string model = getModel(ptr); + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); - objects.insertMesh(ptr, "meshes\\" + model); + objects.insertMesh(ptr, model); } } void Weapon::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const + { + const std::string model = getModel(ptr); + if(!model.empty()) { + physics.insertObjectPhysics(ptr, model); + } + } + + std::string Weapon::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); - + assert(ref->base != NULL); const std::string &model = ref->base->model; - assert (ref->base != NULL); - if(!model.empty()){ - physics.insertObjectPhysics(ptr, "meshes\\" + model); + if (!model.empty()) { + return "meshes\\" + model; } - + return ""; } std::string Weapon::getName (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 92d703b4a..eaf5b60a4 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -66,6 +66,7 @@ namespace MWClass const; ///< Generate action for using via inventory menu + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index f973301c5..729746f6b 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -213,7 +213,7 @@ namespace MWWorld { } - std::string Class::getModel() const + std::string Class::getModel(const MWWorld::Ptr &ptr) const { return ""; } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 5f16ef593..c8b51eeab 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -205,7 +205,7 @@ namespace MWWorld virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; - virtual std::string getModel() const; + virtual std::string getModel(const MWWorld::Ptr &ptr) const; }; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index db1db0505..1eba439a8 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -367,12 +367,11 @@ namespace MWWorld } float PhysicsSystem::getObjectHeight(const MWWorld::Ptr &ptr) { - std::string model = MWWorld::Class::get(ptr).getModel(); + std::string model = MWWorld::Class::get(ptr).getModel(ptr); if (model.empty()) { return 0.0; } float scale = ptr.getRefData().getBaseNode()->getScale().x; return mEngine->getObjectHeight(model, scale); } - } From e1c7d1f52936988f2093db7a9800093c1cfac927 Mon Sep 17 00:00:00 2001 From: greye Date: Tue, 24 Jul 2012 22:08:23 +0400 Subject: [PATCH 102/126] fixed item sinking --- apps/openmw/mwworld/physicssystem.cpp | 31 ++++++++++++++------------- apps/openmw/mwworld/scene.cpp | 6 ++++++ apps/openmw/mwworld/worldimp.cpp | 4 ++-- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 1eba439a8..2b3d4b0f4 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -349,29 +349,30 @@ namespace MWWorld throw std::logic_error ("can't find player"); } - void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ + void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ - Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); + Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); - // unused - //Ogre::Vector3 objPos = node->getPosition(); + addObject( + node->getName(), + model, + node->getOrientation(), + node->getScale().x, + node->getPosition()); + } - addObject (node->getName(), model, node->getOrientation(), - node->getScale().x, node->getPosition()); - } + void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){ + Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); + addActor (node->getName(), model, node->getPosition()); + } - void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){ - Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); - // std::cout << "Adding node with name" << node->getName(); - addActor (node->getName(), model, node->getPosition()); - } - - float PhysicsSystem::getObjectHeight(const MWWorld::Ptr &ptr) { + float PhysicsSystem::getObjectHeight(const MWWorld::Ptr &ptr) + { std::string model = MWWorld::Class::get(ptr).getModel(ptr); if (model.empty()) { return 0.0; } float scale = ptr.getRefData().getBaseNode()->getScale().x; return mEngine->getObjectHeight(model, scale); - } + } } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 9786c24d9..b78669ef5 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -335,6 +335,12 @@ namespace MWWorld void Scene::addObjectToScene (const Ptr& ptr) { mRendering.addObject (ptr); + + float *pos = ptr.getRefData().getPosition().pos; + pos[2] += mPhysics->getObjectHeight(ptr) / 2; + + ptr.getRefData().getBaseNode()->setPosition(pos[0], pos[1], pos[2]); + MWWorld::Class::get (ptr).insertObject (ptr, *mPhysics); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index efb17a709..3d409570b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1024,8 +1024,6 @@ namespace MWWorld MWWorld::Ptr dropped = cell->insertObject(object, pos); mWorldScene->addObjectToScene(dropped); - /// \todo retrieve the bounds of the object and translate it accordingly - return true; } @@ -1047,6 +1045,8 @@ namespace MWWorld ESM::Position &pos = getPlayer().getPlayer().getRefData().getPosition(); + /// \todo fix item dropping at player object center position + MWWorld::Ptr dropped = cell->insertObject(object, pos); mWorldScene->addObjectToScene(dropped); From aff05b9d36f102634334219b61ea253a4e7a8dc7 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 00:03:31 +0400 Subject: [PATCH 103/126] local script registration --- apps/openmw/mwworld/worldimp.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3d409570b..670b3e512 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1023,6 +1023,9 @@ namespace MWWorld MWWorld::Ptr dropped = cell->insertObject(object, pos); mWorldScene->addObjectToScene(dropped); + mLocalScripts.add( + MWWorld::Class::get(dropped).getScript(), + dropped); return true; } @@ -1050,6 +1053,9 @@ namespace MWWorld MWWorld::Ptr dropped = cell->insertObject(object, pos); mWorldScene->addObjectToScene(dropped); + mLocalScripts.add( + MWWorld::Class::get(dropped).getScript(), + dropped); } void World::processChangedSettings(const Settings::CategorySettingVector& settings) From d5fe378a6622445076dea86779a318d6b18e57c5 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 10:02:43 +0400 Subject: [PATCH 104/126] Revert "local script registration" This reverts commit 0686399a306319a4c49e1009d10215a9c0e65ec2. --- apps/openmw/mwworld/worldimp.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 670b3e512..3d409570b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1023,9 +1023,6 @@ namespace MWWorld MWWorld::Ptr dropped = cell->insertObject(object, pos); mWorldScene->addObjectToScene(dropped); - mLocalScripts.add( - MWWorld::Class::get(dropped).getScript(), - dropped); return true; } @@ -1053,9 +1050,6 @@ namespace MWWorld MWWorld::Ptr dropped = cell->insertObject(object, pos); mWorldScene->addObjectToScene(dropped); - mLocalScripts.add( - MWWorld::Class::get(dropped).getScript(), - dropped); } void World::processChangedSettings(const Settings::CategorySettingVector& settings) From bcc47cd5fb00858c481fff542fad19cac52a79f8 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 10:47:59 +0400 Subject: [PATCH 105/126] local scripts, move placing to World::placeObject(Ptr, CellStore, Position) --- apps/openmw/mwbase/world.hpp | 8 ++++++++ apps/openmw/mwworld/worldimp.cpp | 22 ++++++++++++++++------ apps/openmw/mwworld/worldimp.hpp | 3 +++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 6937cbf3b..f257b723e 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -54,6 +54,14 @@ namespace MWBase World& operator= (const World&); ///< not implemented + protected: + + virtual void + placeObject( + const MWWorld::Ptr &ptr, + MWWorld::CellStore &cell, + const ESM::Position &pos) = 0; + public: enum RenderMode diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3d409570b..19cdcc334 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1021,8 +1021,7 @@ namespace MWWorld pos.pos[1] = -result.second[2]; pos.pos[2] = result.second[1]; - MWWorld::Ptr dropped = cell->insertObject(object, pos); - mWorldScene->addObjectToScene(dropped); + placeObject(object, *cell, pos); return true; } @@ -1038,6 +1037,20 @@ namespace MWWorld return true; } + void + World::placeObject(const Ptr &object, CellStore &cell, const ESM::Position &pos) + { + mLocalScripts.remove(object); + + MWWorld::Ptr dropped = cell.insertObject(object, pos); + mWorldScene->addObjectToScene(dropped); + + std::string script = MWWorld::Class::get(dropped).getScript(dropped); + if (!script.empty()) { + mLocalScripts.add(script, dropped); + } + } + void World::dropObjectOnGround (const Ptr& object) { MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell(); @@ -1046,10 +1059,7 @@ namespace MWWorld getPlayer().getPlayer().getRefData().getPosition(); /// \todo fix item dropping at player object center position - - MWWorld::Ptr dropped = cell->insertObject(object, pos); - - mWorldScene->addObjectToScene(dropped); + placeObject(object, *cell, pos); } void World::processChangedSettings(const Settings::CategorySettingVector& settings) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 43b178fe3..d39871c21 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -89,6 +89,9 @@ namespace MWWorld bool moveObjectImp (const Ptr& ptr, float x, float y, float z); ///< @return true if the active cell (cell player is in) changed + virtual void + placeObject(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); + public: World (OEngine::Render::OgreRenderer& renderer, From e7666d3a7fd22a9489ec60244678cd3664532003 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 17:18:17 +0400 Subject: [PATCH 106/126] move responsibility for cell changing from CellStore::insertObject to Class::moveToCell --- apps/openmw/mwclass/activator.cpp | 10 +++ apps/openmw/mwclass/activator.hpp | 4 + apps/openmw/mwclass/apparatus.cpp | 9 +++ apps/openmw/mwclass/apparatus.hpp | 4 + apps/openmw/mwclass/armor.cpp | 9 +++ apps/openmw/mwclass/armor.hpp | 3 + apps/openmw/mwclass/book.cpp | 8 ++ apps/openmw/mwclass/book.hpp | 3 + apps/openmw/mwclass/clothing.cpp | 9 +++ apps/openmw/mwclass/clothing.hpp | 3 + apps/openmw/mwclass/container.cpp | 9 +++ apps/openmw/mwclass/container.hpp | 4 + apps/openmw/mwclass/creature.cpp | 9 +++ apps/openmw/mwclass/creature.hpp | 3 + apps/openmw/mwclass/door.cpp | 9 +++ apps/openmw/mwclass/door.hpp | 3 + apps/openmw/mwclass/ingredient.cpp | 9 +++ apps/openmw/mwclass/ingredient.hpp | 3 + apps/openmw/mwclass/light.cpp | 9 +++ apps/openmw/mwclass/light.hpp | 3 + apps/openmw/mwclass/lockpick.cpp | 9 +++ apps/openmw/mwclass/lockpick.hpp | 3 + apps/openmw/mwclass/misc.cpp | 36 +++++++++ apps/openmw/mwclass/misc.hpp | 3 + apps/openmw/mwclass/npc.cpp | 9 +++ apps/openmw/mwclass/npc.hpp | 3 + apps/openmw/mwclass/potion.cpp | 10 +++ apps/openmw/mwclass/potion.hpp | 3 + apps/openmw/mwclass/probe.cpp | 10 +++ apps/openmw/mwclass/probe.hpp | 5 +- apps/openmw/mwclass/repair.cpp | 9 +++ apps/openmw/mwclass/repair.hpp | 5 +- apps/openmw/mwclass/static.cpp | 9 +++ apps/openmw/mwclass/static.hpp | 3 + apps/openmw/mwclass/weapon.cpp | 9 +++ apps/openmw/mwclass/weapon.hpp | 3 + apps/openmw/mwworld/cellstore.cpp | 119 ----------------------------- apps/openmw/mwworld/cellstore.hpp | 6 +- apps/openmw/mwworld/class.cpp | 31 ++++++++ apps/openmw/mwworld/class.hpp | 14 ++++ apps/openmw/mwworld/worldimp.cpp | 4 +- 41 files changed, 300 insertions(+), 126 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 33baad7ca..d0f09e80e 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -94,4 +94,14 @@ namespace MWClass return info; } + + MWWorld::Ptr + Activator::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.activators.insert(*ref), &cell); + } } + diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 2e947a9fc..26aafb717 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -7,6 +7,10 @@ namespace MWClass { class Activator : public MWWorld::Class { + + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index dd255f9f8..6322c963e 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -149,4 +149,13 @@ namespace MWClass { return boost::shared_ptr(new MWWorld::ActionAlchemy()); } + + MWWorld::Ptr + Apparatus::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.appas.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index fa77eec93..9352e0617 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -7,6 +7,10 @@ namespace MWClass { class Apparatus : public MWWorld::Class { + + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 8bbb198cc..aeefcd42b 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -276,4 +276,13 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); } + + MWWorld::Ptr + Armor::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.armors.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 181a4ce61..960b6dad5 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Armor : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 62b6c8204..1517f090a 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -157,4 +157,12 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionRead(ptr)); } + MWWorld::Ptr + Book::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.books.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 20ea89274..adbf2d64b 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Book : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index e1ec5a61c..86c031db0 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -227,4 +227,13 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); } + + MWWorld::Ptr + Clothing::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.clothes.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 6b5fe1e96..2c0d0b8a5 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Clothing : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 7c5719b8e..2543f6acd 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -207,4 +207,13 @@ namespace MWClass { ptr.getCellRef().lockLevel = 0; } + + MWWorld::Ptr + Container::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.containers.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 17a9ac4ea..2f15d03d8 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -9,6 +9,10 @@ namespace MWClass { void ensureCustomData (const MWWorld::Ptr& ptr) const; + + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 178a6f536..8f885bf62 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -195,4 +195,13 @@ namespace MWClass return weight; } + + MWWorld::Ptr + Creature::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.creatures.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index b994e0831..38be98533 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -11,6 +11,9 @@ namespace MWClass { void ensureCustomData (const MWWorld::Ptr& ptr) const; + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual std::string getId (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 1274219a9..8eef54725 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -209,4 +209,13 @@ namespace MWClass return info; } + + MWWorld::Ptr + Door::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.doors.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 2612df41c..b89858556 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Door : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index a2f14c02c..02e77fa25 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -156,4 +156,13 @@ namespace MWClass return info; } + + MWWorld::Ptr + Ingredient::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.ingreds.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index ad87dd46c..44ee0ccd0 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Ingredient : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 37d7d1eec..e7b3af2b9 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -196,4 +196,13 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); } + + MWWorld::Ptr + Light::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.lights.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index ab8854efd..953078a35 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Light : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index ae2b5de89..e72e96822 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -165,4 +165,13 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); } + + MWWorld::Ptr + Lockpick::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.lockpicks.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 45a02d40d..216dc10c9 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Lockpick : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 89c1ef25f..37f608ed2 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -12,6 +12,7 @@ #include "../mwworld/actiontake.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/manualref.hpp" #include "../mwgui/window_manager.hpp" #include "../mwgui/tooltips.hpp" @@ -183,4 +184,39 @@ namespace MWClass return info; } + + MWWorld::Ptr + Miscellaneous::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::Ptr newPtr; + + const ESMS::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + if (MWWorld::Class::get(ptr).getName(ptr) == store.gameSettings.search("sGold")->str) { + int goldAmount = ptr.getRefData().getCount(); + + std::string base = "Gold_001"; + if (goldAmount >= 100) + base = "Gold_100"; + else if (goldAmount >= 25) + base = "Gold_025"; + else if (goldAmount >= 10) + base = "Gold_010"; + else if (goldAmount >= 5) + base = "Gold_005"; + + // Really, I have no idea why moving ref out of conditional + // scope causes list::push_back throwing std::bad_alloc + MWWorld::ManualRef newRef(store, base); + MWWorld::LiveCellRef *ref = + newRef.getPtr().get(); + newPtr = MWWorld::Ptr(&cell.miscItems.insert(*ref), &cell); + } else { + MWWorld::LiveCellRef *ref = + ptr.get(); + newPtr = MWWorld::Ptr(&cell.miscItems.insert(*ref), &cell); + } + return newPtr; + } } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 23b5e9564..2a314758f 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Miscellaneous : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index a5525fcda..c81397753 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -380,4 +380,13 @@ namespace MWClass y = 0; x = 0; } + + MWWorld::Ptr + Npc::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.npcs.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 0ea45d132..46fdc9b04 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -9,6 +9,9 @@ namespace MWClass { void ensureCustomData (const MWWorld::Ptr& ptr) const; + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual std::string getId (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 92a951d03..e0f9008c4 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -160,4 +160,14 @@ namespace MWClass return boost::shared_ptr ( new MWWorld::ActionApply (actor, ref->base->mId, actor)); } + + MWWorld::Ptr + Potion::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.potions.insert(*ref), &cell); + } } + diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 39edfd760..0cb40ead0 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Potion : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 033eee4c5..8e5fcfd19 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -164,4 +164,14 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); } + + MWWorld::Ptr + Probe::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.probes.insert(*ref), &cell); + } } + diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index ff10eb9d6..67831d766 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -7,9 +7,12 @@ namespace MWClass { class Probe : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 4258ad106..84d6e3b9e 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -146,4 +146,13 @@ namespace MWClass return info; } + + MWWorld::Ptr + Repair::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.repairs.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 689850b90..74d1d7378 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -7,9 +7,12 @@ namespace MWClass { class Repair : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index a14adc300..ee8bcfe81 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -53,4 +53,13 @@ namespace MWClass registerClass (typeid (ESM::Static).name(), instance); } + + MWWorld::Ptr + Static::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.statics.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 3066933e4..52b87abcd 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Static : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 6412a46b1..ccc5ff6ea 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -365,4 +365,13 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); } + + MWWorld::Ptr + Weapon::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return MWWorld::Ptr(&cell.weapons.insert(*ref), &cell); + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index eaf5b60a4..b18405488 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -7,6 +7,9 @@ namespace MWClass { class Weapon : public MWWorld::Class { + virtual MWWorld::Ptr + moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 088c0c623..eceb5ddc1 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -8,8 +8,6 @@ #include "../mwbase/world.hpp" #include "ptr.hpp" -#include "manualref.hpp" -#include "class.hpp" namespace MWWorld { @@ -127,121 +125,4 @@ namespace MWWorld } } } - - /// \todo this whole code needs major clean up - const MWWorld::Ptr CellStore::insertObject (const Ptr& ptr, const ESM::Position &pos) - { - std::string type = ptr.getTypeName(); - - MWWorld::Ptr newPtr; - - // insert into the correct CellRefList - if (type == typeid(ESM::Potion).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&potions.insert(*ref), this); - } - else if (type == typeid(ESM::Apparatus).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&appas.insert(*ref), this); - } - else if (type == typeid(ESM::Armor).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&armors.insert(*ref), this); - } - else if (type == typeid(ESM::Book).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&books.insert(*ref), this); - } - else if (type == typeid(ESM::Clothing).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&clothes.insert(*ref), this); - } - else if (type == typeid(ESM::Ingredient).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&ingreds.insert(*ref), this); - } - else if (type == typeid(ESM::Light).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&lights.insert(*ref), this); - } - else if (type == typeid(ESM::Tool).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&lockpicks.insert(*ref), this); - } - else if (type == typeid(ESM::Repair).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&repairs.insert(*ref), this); - } - else if (type == typeid(ESM::Probe).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&probes.insert(*ref), this); - } - else if (type == typeid(ESM::Weapon).name()) - { - MWWorld::LiveCellRef* ref = ptr.get(); - newPtr = MWWorld::Ptr(&weapons.insert(*ref), this); - } - else if (type == typeid(ESM::Miscellaneous).name()) - { - - // if this is gold, we need to fetch the correct mesh depending on the amount of gold. - if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) - { - int goldAmount = ptr.getRefData().getCount(); - - std::string base = "Gold_001"; - if (goldAmount >= 100) - base = "Gold_100"; - else if (goldAmount >= 25) - base = "Gold_025"; - else if (goldAmount >= 10) - base = "Gold_010"; - else if (goldAmount >= 5) - base = "Gold_005"; - - MWWorld::ManualRef newRef( - MWBase::Environment::get().getWorld()->getStore(), - base); - - MWWorld::LiveCellRef* ref = - newRef.getPtr().get(); - - newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); - /* - ESM::Position& p = newPtr.getRefData().getPosition(); - p.pos[0] = ptr.getRefData().getPosition().pos[0]; - p.pos[1] = ptr.getRefData().getPosition().pos[1]; - p.pos[2] = ptr.getRefData().getPosition().pos[2]; - */ - } - else - { - MWWorld::LiveCellRef* ref = - ptr.get(); - - newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); - } - } - else - throw std::runtime_error("Trying to insert object of unhandled type"); - - newPtr.getRefData().getPosition() = pos; - - newPtr.getRefData().setCount(ptr.getRefData().getCount()); - ptr.getRefData().setCount(0); - newPtr.getRefData().enable(); - - return newPtr; - } - } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 1bf233a50..0be0ef651 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -113,9 +113,9 @@ namespace MWWorld CellRefList ingreds; CellRefList creatureLists; CellRefList itemLists; - CellRefList lights; + CellRefList lights; CellRefList lockpicks; - CellRefList miscItems; + CellRefList miscItems; CellRefList npcs; CellRefList probes; CellRefList repairs; @@ -155,8 +155,6 @@ namespace MWWorld forEachImp (functor, weapons); } - const MWWorld::Ptr insertObject(const MWWorld::Ptr &ptr, const ESM::Position &pos); - private: template diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 729746f6b..6f2306fbe 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -5,7 +5,10 @@ #include +#include + #include "ptr.hpp" +#include "refdata.hpp" #include "nullaction.hpp" #include "containerstore.hpp" @@ -217,4 +220,32 @@ namespace MWWorld { return ""; } + + MWWorld::Ptr + Class::moveToCellImpl(const Ptr &ptr, CellStore &cell) const + { + throw std::runtime_error("unable to move class to cell"); + } + + MWWorld::Ptr + Class::moveToCell(const Ptr &ptr, CellStore &cell) const + { + Ptr newPtr = moveToCellImpl(ptr, cell); + + newPtr.getRefData().setCount(ptr.getRefData().getCount()); + ptr.getRefData().setCount(0); + newPtr.getRefData().enable(); + + return newPtr; + } + + MWWorld::Ptr + Class::moveToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const + { + Ptr newPtr = moveToCell(ptr, cell); + newPtr.getRefData().getPosition() = pos; + + return newPtr; + } } + diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index c8b51eeab..509433433 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -31,12 +31,18 @@ namespace MWGui struct ToolTipInfo; } +namespace ESM +{ + struct Position; +} + namespace MWWorld { class Ptr; class ContainerStore; class InventoryStore; class PhysicsSystem; + class CellStore; /// \brief Base class for referenceable esm records class Class @@ -51,6 +57,8 @@ namespace MWWorld Class(); + virtual Ptr moveToCellImpl(const Ptr &ptr, CellStore &cell) const; + public: /// NPC-stances. @@ -206,6 +214,12 @@ namespace MWWorld virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual Ptr + moveToCell(const Ptr &ptr, CellStore &cell) const; + + virtual Ptr + moveToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 19cdcc334..394a9e493 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1042,7 +1042,9 @@ namespace MWWorld { mLocalScripts.remove(object); - MWWorld::Ptr dropped = cell.insertObject(object, pos); + MWWorld::Ptr dropped = + MWWorld::Class::get(object).moveToCell(object, cell, pos); + mWorldScene->addObjectToScene(dropped); std::string script = MWWorld::Class::get(dropped).getScript(dropped); From 49b1d5e1275bfebcd508afb910d4d55644184c20 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 18:58:55 +0400 Subject: [PATCH 107/126] fix object placing --- apps/openmw/mwworld/physicssystem.cpp | 8 +++++--- apps/openmw/mwworld/physicssystem.hpp | 2 +- apps/openmw/mwworld/scene.cpp | 7 ++++++- libs/openengine/bullet/physic.cpp | 17 +++++++++++++---- libs/openengine/bullet/physic.hpp | 2 +- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 2b3d4b0f4..e4a019b69 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -366,13 +366,15 @@ namespace MWWorld addActor (node->getName(), model, node->getPosition()); } - float PhysicsSystem::getObjectHeight(const MWWorld::Ptr &ptr) + bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, float *min, float *max) { std::string model = MWWorld::Class::get(ptr).getModel(ptr); if (model.empty()) { - return 0.0; + return false; } float scale = ptr.getRefData().getBaseNode()->getScale().x; - return mEngine->getObjectHeight(model, scale); + mEngine->getObjectAABB(model, scale, min, max); + + return true; } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 61e2590bd..f81bcc373 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -65,7 +65,7 @@ namespace MWWorld void setCurrentWater(bool hasWater, int waterHeight); - float getObjectHeight(const MWWorld::Ptr &ptr); + bool getObjectAABB(const MWWorld::Ptr &ptr, float *min, float *max); private: OEngine::Render::OgreRenderer &mRender; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index b78669ef5..ce0acfe47 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -337,7 +337,12 @@ namespace MWWorld mRendering.addObject (ptr); float *pos = ptr.getRefData().getPosition().pos; - pos[2] += mPhysics->getObjectHeight(ptr) / 2; + float min[3], max[3]; + if (mPhysics->getObjectAABB(ptr, min, max)) { + pos[0] -= (min[0] + max[0]) / 2; + pos[1] -= (min[1] + max[1]) / 2; + pos[2] -= min[2]; + } ptr.getRefData().getBaseNode()->setPosition(pos[0], pos[1], pos[2]); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 416d0c09d..611c87d9f 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -12,6 +12,8 @@ #include +#include + #define BIT(x) (1<<(x)) namespace OEngine { @@ -569,7 +571,8 @@ namespace Physic return results2; } - float PhysicEngine::getObjectHeight(const std::string &mesh, float scale) { + void PhysicEngine::getObjectAABB(const std::string &mesh, float scale, float *min, float *max) + { char uniqueID[8]; sprintf( uniqueID, "%07.3f", scale ); std::string sid = uniqueID; @@ -582,11 +585,17 @@ namespace Physic btTransform trans; - btVector3 min, max; + btVector3 btmin, btmax; trans.setIdentity(); - shape->Shape->getAabb(trans, min, max); + shape->Shape->getAabb(trans, btmin, btmax); - return max.z() - min.z(); + min[0] = btmin.x(); + min[1] = btmin.y(); + min[2] = btmin.z(); + + max[0] = btmax.x(); + max[1] = btmax.y(); + max[2] = btmax.z(); } }}; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 22c5fa274..8701adc84 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -221,7 +221,7 @@ namespace Physic bool toggleDebugRendering(); - float getObjectHeight(const std::string &mesh, float scale); + void getObjectAABB(const std::string &mesh, float scale, float *min, float *max); /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). From cd04911f3c463ce6e8eb94f62020ee689b661c4f Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 20:25:53 +0400 Subject: [PATCH 108/126] dropping on the ground --- apps/openmw/mwworld/physicssystem.cpp | 16 ++++++++++++++++ apps/openmw/mwworld/physicssystem.hpp | 3 +++ apps/openmw/mwworld/worldimp.cpp | 13 ++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index e4a019b69..27d48fa39 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -122,6 +122,22 @@ namespace MWWorld return !(result.first == ""); } + std::pair + PhysicsSystem::castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len) + { + Ogre::Ray ray = Ogre::Ray(orig, dir); + Ogre::Vector3 to = ray.getPoint(len); + + btVector3 btFrom = btVector3(orig.x, orig.y, orig.z); + btVector3 btTo = btVector3(to.x, to.y, to.z); + + std::pair test = mEngine->rayTest(btFrom, btTo); + if (test.first == "") { + return std::make_pair(false, Ogre::Vector3()); + } + return std::make_pair(true, ray.getPoint(len * test.second)); + } + std::pair PhysicsSystem::castRay(float mouseX, float mouseY) { Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay( diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index f81bcc373..375a7c9de 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -54,6 +54,9 @@ namespace MWWorld // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); + std::pair + castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len); + std::pair castRay(float mouseX, float mouseY); ///< cast ray from the mouse, return true if it hit something and the first result (in OGRE coordinates) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 394a9e493..b9ab6ade2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1057,9 +1057,20 @@ namespace MWWorld { MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell(); - ESM::Position &pos = + ESM::Position pos = getPlayer().getPlayer().getRefData().getPosition(); + Ogre::Vector3 orig = + Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]); + Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1); + + float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2]; + len += 100.0; + + std::pair hit = + mPhysics->castRay(orig, dir, len); + pos.pos[2] = hit.second.z; + /// \todo fix item dropping at player object center position placeObject(object, *cell, pos); } From 3feb4ce61b5c4c402cff2d47d294712d263beefb Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 25 Jul 2012 19:33:21 +0200 Subject: [PATCH 109/126] terrain lod morph fix --- files/materials/terrain.shader | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 601f287a0..0458c4db9 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -55,7 +55,7 @@ shUniform(float2, lodMorph) @shAutoConstant(lodMorph, custom, 1001) shVertexInput(float2, uv0) - shVertexInput(float2, delta) // lodDelta, lodThreshold + shVertexInput(float2, uv1) // lodDelta, lodThreshold #if SHADOWS shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) @@ -85,11 +85,11 @@ // result is negative (it will only be -1 in fact, since after that // the vertex will never be indexed), we will achieve our aim. // sign(vertexLOD - targetLOD) == -1 is to morph - float toMorph = -min(0, sign(delta.y - lodMorph.y)); + float toMorph = -min(0, sign(uv1.y - lodMorph.y)); // morph // this assumes XZ terrain alignment - worldPos.y += delta.x * toMorph * lodMorph.x; + worldPos.y += uv1.x * toMorph * lodMorph.x; shOutputPosition = shMatrixMult(viewProjMatrix, worldPos); From 9f813aa26c3ed3a31767f1b75d637027b2fb47b4 Mon Sep 17 00:00:00 2001 From: greye Date: Wed, 25 Jul 2012 23:28:42 +0400 Subject: [PATCH 110/126] update resource naming in getObjectAABB() --- libs/openengine/bullet/physic.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 611c87d9f..d4b63676d 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -12,8 +12,6 @@ #include -#include - #define BIT(x) (1<<(x)) namespace OEngine { @@ -576,14 +574,13 @@ namespace Physic char uniqueID[8]; sprintf( uniqueID, "%07.3f", scale ); std::string sid = uniqueID; - std::string outputstring = mesh + uniqueID + "\"|"; + std::string outputstring = mesh + uniqueID; mShapeLoader->load(outputstring, "General"); BulletShapeManager::getSingletonPtr()->load(outputstring, "General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring, "General"); - btTransform trans; btVector3 btmin, btmax; From 37c7becb07326240881dc9d4bdfcb35404a68d94 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 25 Jul 2012 23:53:06 +0200 Subject: [PATCH 111/126] some potential compability fixes --- files/materials/objects.shader | 15 +++++++-------- files/materials/shadows.h | 10 +++++++--- files/materials/terrain.shader | 17 +++++++++-------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 238ccdcf6..dba239c14 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -192,7 +192,7 @@ #if SHADOWS || SHADOWS_PSSM float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; float fade = 1-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange); - shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); + shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1.0 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow); #endif #if !SHADOWS && !SHADOWS_PSSM @@ -205,13 +205,12 @@ #if UNDERWATER float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz; float3 waterEyePos = float3(1,1,1); - if (worldPos.y < waterLevel && waterEnabled == 1) - { - // NOTE: this calculation would be wrong for non-uniform scaling - float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); - caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); - } + // NOTE: this calculation would be wrong for non-uniform scaling + float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); + waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); + caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); + if (worldPos.y >= waterLevel || waterEnabled != 1) + caustics = float3(1,1,1); #endif diff --git a/files/materials/shadows.h b/files/materials/shadows.h index 769a4fea7..b1dc92d21 100644 --- a/files/materials/shadows.h +++ b/files/materials/shadows.h @@ -36,12 +36,16 @@ float pssmDepthShadow ( { float shadow; + float pcf1 = depthShadowPCF(shadowMap0, lightSpacePos0, invShadowmapSize0); + float pcf2 = depthShadowPCF(shadowMap1, lightSpacePos1, invShadowmapSize1); + float pcf3 = depthShadowPCF(shadowMap2, lightSpacePos2, invShadowmapSize2); + if (depth < pssmSplitPoints.x) - shadow = depthShadowPCF(shadowMap0, lightSpacePos0, invShadowmapSize0); + shadow = pcf1; else if (depth < pssmSplitPoints.y) - shadow = depthShadowPCF(shadowMap1, lightSpacePos1, invShadowmapSize1); + shadow = pcf2; else - shadow = depthShadowPCF(shadowMap2, lightSpacePos2, invShadowmapSize2); + shadow = pcf3; return shadow; } diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 0458c4db9..7ef26d035 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -224,13 +224,14 @@ float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz; float3 waterEyePos = float3(1,1,1); - if (worldPos.y < waterLevel) - { - // NOTE: this calculation would be wrong for non-uniform scaling - float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); - caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); - } + // NOTE: this calculation would be wrong for non-uniform scaling + float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); + waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); + caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); + if (worldPos.y >= waterLevel) + caustics = float3(1,1,1); + + #endif @@ -285,7 +286,7 @@ #if SHADOWS || SHADOWS_PSSM float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; float fade = 1-((depth - shadowFar_fadeStart.y) / fadeRange); - shadow = (depth > shadowFar_fadeStart.x) ? 1 : ((depth > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); + shadow = (depth > shadowFar_fadeStart.x) ? 1.0 : ((depth > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow); #endif #if !SHADOWS && !SHADOWS_PSSM From 26595f22f66efcb84c97b3fd7baac9eb03895e24 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 26 Jul 2012 16:14:11 +0400 Subject: [PATCH 112/126] float* -> Vector3, moveToCell -> copyToCell, fixed placeObject() --- apps/openmw/mwclass/activator.cpp | 2 +- apps/openmw/mwclass/activator.hpp | 2 +- apps/openmw/mwclass/apparatus.cpp | 2 +- apps/openmw/mwclass/apparatus.hpp | 2 +- apps/openmw/mwclass/armor.cpp | 2 +- apps/openmw/mwclass/armor.hpp | 2 +- apps/openmw/mwclass/book.cpp | 2 +- apps/openmw/mwclass/book.hpp | 2 +- apps/openmw/mwclass/clothing.cpp | 2 +- apps/openmw/mwclass/clothing.hpp | 2 +- apps/openmw/mwclass/container.cpp | 2 +- apps/openmw/mwclass/container.hpp | 2 +- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/creature.hpp | 2 +- apps/openmw/mwclass/door.cpp | 2 +- apps/openmw/mwclass/door.hpp | 2 +- apps/openmw/mwclass/ingredient.cpp | 2 +- apps/openmw/mwclass/ingredient.hpp | 2 +- apps/openmw/mwclass/light.cpp | 2 +- apps/openmw/mwclass/light.hpp | 2 +- apps/openmw/mwclass/lockpick.cpp | 2 +- apps/openmw/mwclass/lockpick.hpp | 2 +- apps/openmw/mwclass/misc.cpp | 2 +- apps/openmw/mwclass/misc.hpp | 2 +- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwclass/npc.hpp | 2 +- apps/openmw/mwclass/potion.cpp | 2 +- apps/openmw/mwclass/potion.hpp | 2 +- apps/openmw/mwclass/probe.cpp | 2 +- apps/openmw/mwclass/probe.hpp | 2 +- apps/openmw/mwclass/repair.cpp | 2 +- apps/openmw/mwclass/repair.hpp | 2 +- apps/openmw/mwclass/static.cpp | 2 +- apps/openmw/mwclass/static.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 2 +- apps/openmw/mwclass/weapon.hpp | 2 +- apps/openmw/mwworld/class.cpp | 11 +++++---- apps/openmw/mwworld/class.hpp | 6 ++--- apps/openmw/mwworld/physicssystem.cpp | 15 ++++++++++--- apps/openmw/mwworld/physicssystem.hpp | 2 +- apps/openmw/mwworld/scene.cpp | 32 +++++++++++++++------------ apps/openmw/mwworld/scene.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 26 +++++++++++++++------- libs/openengine/bullet/physic.cpp | 13 ++--------- libs/openengine/bullet/physic.hpp | 2 +- 45 files changed, 98 insertions(+), 83 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index d0f09e80e..9b0082efc 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -96,7 +96,7 @@ namespace MWClass } MWWorld::Ptr - Activator::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Activator::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 26aafb717..4165fbc08 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -9,7 +9,7 @@ namespace MWClass { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 6322c963e..9814b140c 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -151,7 +151,7 @@ namespace MWClass } MWWorld::Ptr - Apparatus::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Apparatus::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 9352e0617..7045f62d6 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -9,7 +9,7 @@ namespace MWClass { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index aeefcd42b..4624b94d9 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -278,7 +278,7 @@ namespace MWClass } MWWorld::Ptr - Armor::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Armor::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 960b6dad5..51c0ea21c 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -8,7 +8,7 @@ namespace MWClass class Armor : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 1517f090a..d8166347e 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -158,7 +158,7 @@ namespace MWClass } MWWorld::Ptr - Book::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Book::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index adbf2d64b..acb1aac06 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -8,7 +8,7 @@ namespace MWClass class Book : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 86c031db0..f55d6ed88 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -229,7 +229,7 @@ namespace MWClass } MWWorld::Ptr - Clothing::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Clothing::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 2c0d0b8a5..f7801848f 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -8,7 +8,7 @@ namespace MWClass class Clothing : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 2543f6acd..c6d22b3a5 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -209,7 +209,7 @@ namespace MWClass } MWWorld::Ptr - Container::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Container::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 2f15d03d8..006e4bd22 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -11,7 +11,7 @@ namespace MWClass virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8f885bf62..0f3141f5c 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -197,7 +197,7 @@ namespace MWClass } MWWorld::Ptr - Creature::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Creature::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 38be98533..f7a5e5874 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -12,7 +12,7 @@ namespace MWClass void ensureCustomData (const MWWorld::Ptr& ptr) const; virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 8eef54725..359e50ffb 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -211,7 +211,7 @@ namespace MWClass } MWWorld::Ptr - Door::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Door::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index b89858556..b0f86f12d 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -8,7 +8,7 @@ namespace MWClass class Door : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 02e77fa25..d8c8b4b3b 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -158,7 +158,7 @@ namespace MWClass } MWWorld::Ptr - Ingredient::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Ingredient::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 44ee0ccd0..1365c4a71 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -8,7 +8,7 @@ namespace MWClass class Ingredient : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index e7b3af2b9..f09d3ce36 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -198,7 +198,7 @@ namespace MWClass } MWWorld::Ptr - Light::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Light::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 953078a35..640e1705b 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -8,7 +8,7 @@ namespace MWClass class Light : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index e72e96822..20441b520 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -167,7 +167,7 @@ namespace MWClass } MWWorld::Ptr - Lockpick::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Lockpick::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 216dc10c9..0961b55b2 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -8,7 +8,7 @@ namespace MWClass class Lockpick : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 37f608ed2..cb6d40c43 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -186,7 +186,7 @@ namespace MWClass } MWWorld::Ptr - Miscellaneous::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Miscellaneous::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::Ptr newPtr; diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 2a314758f..a5a79a8f6 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -8,7 +8,7 @@ namespace MWClass class Miscellaneous : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index c81397753..81c0c85f5 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -382,7 +382,7 @@ namespace MWClass } MWWorld::Ptr - Npc::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Npc::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 46fdc9b04..e494fbaa7 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -10,7 +10,7 @@ namespace MWClass void ensureCustomData (const MWWorld::Ptr& ptr) const; virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index e0f9008c4..993dac6f6 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -162,7 +162,7 @@ namespace MWClass } MWWorld::Ptr - Potion::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Potion::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 0cb40ead0..d595f7e69 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -8,7 +8,7 @@ namespace MWClass class Potion : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 8e5fcfd19..450016209 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -166,7 +166,7 @@ namespace MWClass } MWWorld::Ptr - Probe::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Probe::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 67831d766..d9f90baf6 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -8,7 +8,7 @@ namespace MWClass class Probe : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 84d6e3b9e..829fe311a 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -148,7 +148,7 @@ namespace MWClass } MWWorld::Ptr - Repair::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Repair::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 74d1d7378..c58e38f96 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -8,7 +8,7 @@ namespace MWClass class Repair : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index ee8bcfe81..e317b740c 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -55,7 +55,7 @@ namespace MWClass } MWWorld::Ptr - Static::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Static::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 52b87abcd..e36b3d142 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -8,7 +8,7 @@ namespace MWClass class Static : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index ccc5ff6ea..b45953130 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -367,7 +367,7 @@ namespace MWClass } MWWorld::Ptr - Weapon::moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const + Weapon::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index b18405488..06cf88c5f 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -8,7 +8,7 @@ namespace MWClass class Weapon : public MWWorld::Class { virtual MWWorld::Ptr - moveToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; public: diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 6f2306fbe..6676ce1cf 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -222,27 +222,26 @@ namespace MWWorld } MWWorld::Ptr - Class::moveToCellImpl(const Ptr &ptr, CellStore &cell) const + Class::copyToCellImpl(const Ptr &ptr, CellStore &cell) const { throw std::runtime_error("unable to move class to cell"); } MWWorld::Ptr - Class::moveToCell(const Ptr &ptr, CellStore &cell) const + Class::copyToCell(const Ptr &ptr, CellStore &cell) const { - Ptr newPtr = moveToCellImpl(ptr, cell); + Ptr newPtr = copyToCellImpl(ptr, cell); newPtr.getRefData().setCount(ptr.getRefData().getCount()); - ptr.getRefData().setCount(0); newPtr.getRefData().enable(); return newPtr; } MWWorld::Ptr - Class::moveToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const + Class::copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const { - Ptr newPtr = moveToCell(ptr, cell); + Ptr newPtr = copyToCell(ptr, cell); newPtr.getRefData().getPosition() = pos; return newPtr; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 509433433..1bc592798 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -57,7 +57,7 @@ namespace MWWorld Class(); - virtual Ptr moveToCellImpl(const Ptr &ptr, CellStore &cell) const; + virtual Ptr copyToCellImpl(const Ptr &ptr, CellStore &cell) const; public: @@ -216,10 +216,10 @@ namespace MWWorld virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual Ptr - moveToCell(const Ptr &ptr, CellStore &cell) const; + copyToCell(const Ptr &ptr, CellStore &cell) const; virtual Ptr - moveToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const; + copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const; }; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 27d48fa39..45cfdd123 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -382,14 +382,23 @@ namespace MWWorld addActor (node->getName(), model, node->getPosition()); } - bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, float *min, float *max) + bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max) { std::string model = MWWorld::Class::get(ptr).getModel(ptr); if (model.empty()) { return false; } - float scale = ptr.getRefData().getBaseNode()->getScale().x; - mEngine->getObjectAABB(model, scale, min, max); + btVector3 btMin, btMax; + float scale = ptr.getCellRef().scale; + mEngine->getObjectAABB(model, scale, btMin, btMax); + + min.x = btMin.x(); + min.y = btMin.y(); + min.z = btMin.z(); + + max.x = btMax.x(); + max.y = btMax.y(); + max.z = btMax.z(); return true; } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 375a7c9de..e42fa536b 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -68,7 +68,7 @@ namespace MWWorld void setCurrentWater(bool hasWater, int waterHeight); - bool getObjectAABB(const MWWorld::Ptr &ptr, float *min, float *max); + bool getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max); private: OEngine::Render::OgreRenderer &mRender; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ce0acfe47..13e5ecb85 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -334,21 +334,10 @@ namespace MWWorld void Scene::addObjectToScene (const Ptr& ptr) { - mRendering.addObject (ptr); - - float *pos = ptr.getRefData().getPosition().pos; - float min[3], max[3]; - if (mPhysics->getObjectAABB(ptr, min, max)) { - pos[0] -= (min[0] + max[0]) / 2; - pos[1] -= (min[1] + max[1]) / 2; - pos[2] -= min[2]; - } - - ptr.getRefData().getBaseNode()->setPosition(pos[0], pos[1], pos[2]); - - MWWorld::Class::get (ptr).insertObject (ptr, *mPhysics); + mRendering.addObject(ptr); + MWWorld::Class::get(ptr).insertObject(ptr, *mPhysics); } - + void Scene::removeObjectFromScene (const Ptr& ptr) { MWBase::Environment::get().getMechanicsManager()->removeActor (ptr); @@ -356,4 +345,19 @@ namespace MWWorld mPhysics->removeObject (ptr.getRefData().getHandle()); mRendering.removeObject (ptr); } + + bool Scene::isCellActive(const CellStore &cell) + { + CellStoreCollection::iterator active = mActiveCells.begin(); + while (active != mActiveCells.end()) { + if ((*active)->cell->name == cell.cell->name && + (*active)->cell->data.gridX == cell.cell->data.gridX && + (*active)->cell->data.gridY == cell.cell->data.gridY) + { + return true; + } + ++active; + } + return false; + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index f5f4b640b..59e13dafe 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -95,6 +95,8 @@ namespace MWWorld void removeObjectFromScene (const Ptr& ptr); ///< Remove an object from the scene, but not from the world model. + + bool isCellActive(const CellStore &cell); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b9ab6ade2..59f6d7e86 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1022,6 +1022,7 @@ namespace MWWorld pos.pos[2] = result.second[1]; placeObject(object, *cell, pos); + object.getRefData().setCount(0); return true; } @@ -1040,16 +1041,25 @@ namespace MWWorld void World::placeObject(const Ptr &object, CellStore &cell, const ESM::Position &pos) { - mLocalScripts.remove(object); - + /// \todo add searching correct cell for position specified MWWorld::Ptr dropped = - MWWorld::Class::get(object).moveToCell(object, cell, pos); + MWWorld::Class::get(object).copyToCell(object, cell, pos); - mWorldScene->addObjectToScene(dropped); + Ogre::Vector3 min, max; + if (mPhysics->getObjectAABB(object, min, max)) { + float *pos = dropped.getRefData().getPosition().pos; + pos[0] -= (min.x + max.x) / 2; + pos[1] -= (min.y + max.y) / 2; + pos[2] -= min.z; + } - std::string script = MWWorld::Class::get(dropped).getScript(dropped); - if (!script.empty()) { - mLocalScripts.add(script, dropped); + if (mWorldScene->isCellActive(cell)) { + mWorldScene->addObjectToScene(dropped); + + std::string script = MWWorld::Class::get(dropped).getScript(dropped); + if (!script.empty()) { + mLocalScripts.add(script, dropped); + } } } @@ -1071,8 +1081,8 @@ namespace MWWorld mPhysics->castRay(orig, dir, len); pos.pos[2] = hit.second.z; - /// \todo fix item dropping at player object center position placeObject(object, *cell, pos); + object.getRefData().setCount(0); } void World::processChangedSettings(const Settings::CategorySettingVector& settings) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index d4b63676d..089825a9d 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -569,7 +569,7 @@ namespace Physic return results2; } - void PhysicEngine::getObjectAABB(const std::string &mesh, float scale, float *min, float *max) + void PhysicEngine::getObjectAABB(const std::string &mesh, float scale, btVector3 &min, btVector3 &max) { char uniqueID[8]; sprintf( uniqueID, "%07.3f", scale ); @@ -582,17 +582,8 @@ namespace Physic BulletShapeManager::getSingleton().getByName(outputstring, "General"); btTransform trans; - btVector3 btmin, btmax; - trans.setIdentity(); - shape->Shape->getAabb(trans, btmin, btmax); - min[0] = btmin.x(); - min[1] = btmin.y(); - min[2] = btmin.z(); - - max[0] = btmax.x(); - max[1] = btmax.y(); - max[2] = btmax.z(); + shape->Shape->getAabb(trans, min, max); } }}; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 8701adc84..9ae8e7607 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -221,7 +221,7 @@ namespace Physic bool toggleDebugRendering(); - void getObjectAABB(const std::string &mesh, float scale, float *min, float *max); + void getObjectAABB(const std::string &mesh, float scale, btVector3 &min, btVector3 &max); /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). From aa5f63ffcc2f3bc52b27c13e84f938f303b98a34 Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 26 Jul 2012 19:06:48 +0400 Subject: [PATCH 113/126] disabled items placing handling --- apps/openmw/mwworld/class.cpp | 6 +++++- apps/openmw/mwworld/worldimp.cpp | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 6676ce1cf..bb9b7d982 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -233,7 +233,11 @@ namespace MWWorld Ptr newPtr = copyToCellImpl(ptr, cell); newPtr.getRefData().setCount(ptr.getRefData().getCount()); - newPtr.getRefData().enable(); + if (ptr.getRefData().isEnabled()) { + newPtr.getRefData().enable(); + } else { + newPtr.getRefData().disable(); + } return newPtr; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 59f6d7e86..67d8a7cec 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1054,8 +1054,9 @@ namespace MWWorld } if (mWorldScene->isCellActive(cell)) { - mWorldScene->addObjectToScene(dropped); - + if (dropped.getRefData().isEnabled()) { + mWorldScene->addObjectToScene(dropped); + } std::string script = MWWorld::Class::get(dropped).getScript(dropped); if (!script.empty()) { mLocalScripts.add(script, dropped); From 620b6bf27b8605d69bf5aae24f8d7bb66c72ef67 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 26 Jul 2012 17:08:39 +0200 Subject: [PATCH 114/126] change url to work without publickey --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index f53c97677..d2a4cf0d3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "extern/shiny"] path = extern/shiny - url = git@github.com:scrawl/shiny.git + url = git://github.com/scrawl/shiny.git From d5e63a767ec05360cc7fdd974fe486140a1fa3cf Mon Sep 17 00:00:00 2001 From: greye Date: Thu, 26 Jul 2012 19:38:33 +0400 Subject: [PATCH 115/126] replace sprintf() with boost::format --- libs/openengine/bullet/physic.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 089825a9d..a778aef3a 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -11,6 +11,7 @@ #include "BtOgreExtras.h" #include +#include #define BIT(x) (1<<(x)) @@ -333,10 +334,8 @@ namespace Physic RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) { - char uniqueID[8]; - sprintf( uniqueID, "%07.3f", scale ); - std::string sid = uniqueID; - std::string outputstring = mesh + uniqueID; + std::string sid = (boost::format("%07.3f") % scale).str(); + std::string outputstring = mesh + sid; //std::cout << "The string" << outputstring << "\n"; //get the shape from the .nif @@ -571,10 +570,8 @@ namespace Physic void PhysicEngine::getObjectAABB(const std::string &mesh, float scale, btVector3 &min, btVector3 &max) { - char uniqueID[8]; - sprintf( uniqueID, "%07.3f", scale ); - std::string sid = uniqueID; - std::string outputstring = mesh + uniqueID; + std::string sid = (boost::format("%07.3f") % scale).str(); + std::string outputstring = mesh + sid; mShapeLoader->load(outputstring, "General"); BulletShapeManager::getSingletonPtr()->load(outputstring, "General"); From 7725190f89dec2f67c3e3ad5412584d575263192 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 26 Jul 2012 19:09:45 +0200 Subject: [PATCH 116/126] removed some redundant code --- apps/openmw/mwworld/class.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index bb9b7d982..5267e368d 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -232,13 +232,6 @@ namespace MWWorld { Ptr newPtr = copyToCellImpl(ptr, cell); - newPtr.getRefData().setCount(ptr.getRefData().getCount()); - if (ptr.getRefData().isEnabled()) { - newPtr.getRefData().enable(); - } else { - newPtr.getRefData().disable(); - } - return newPtr; } @@ -251,4 +244,3 @@ namespace MWWorld return newPtr; } } - From 6077965d27c036b7a1aad512490db253aa4251ce Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 26 Jul 2012 23:09:46 +0200 Subject: [PATCH 117/126] fix the directx startup issue on windows --- apps/openmw/mwrender/renderingmanager.cpp | 1 + extern/shiny | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index bee4bd68a..ae0e57219 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -72,6 +72,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const else lang = sh::Language_CG; mFactory->setCurrentLanguage (lang); + mFactory->loadAllFiles(); //The fog type must be set before any terrain objects are created as if the //fog type is set to FOG_NONE then the initially created terrain won't have any fog diff --git a/extern/shiny b/extern/shiny index 5546a5bd8..164bc8d3b 160000 --- a/extern/shiny +++ b/extern/shiny @@ -1 +1 @@ -Subproject commit 5546a5bd8474ef328dfedae2df42126cdaf9515f +Subproject commit 164bc8d3bfe860bd16ad89c0bd1b59f465c9bb24 From 281e15f58e0a290b2f8c79135f32d5315fe17ebd Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 26 Jul 2012 23:40:55 +0200 Subject: [PATCH 118/126] consider all material properties for nif material sharing, instead of just the texture --- components/nifogre/ogre_nif_loader.cpp | 47 ++++++++++++++++---------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 803300282..4393749fb 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -39,6 +39,7 @@ #include #include +#include #include @@ -441,7 +442,7 @@ static CompareFunction getTestMode(int mode) class NIFMaterialLoader { -static std::multimap MaterialMap; +static std::map MaterialMap; static void warn(const std::string &msg) { @@ -473,6 +474,8 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam ubyte alphaTest = 0; Ogre::String texName; + bool vertexColour = (shape->data->colors.size() != 0); + // These are set below if present const NiTexturingProperty *t = NULL; const NiMaterialProperty *m = NULL; @@ -537,23 +540,32 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam Ogre::String matname = name; if (m || !texName.empty()) { - // If we're here, then this mesh has a material. Thus we - // need to calculate a snappy material name. It should - // contain the mesh name (mesh->getName()) but also has to - // be unique. One mesh may use many materials. - std::multimap::iterator itr = MaterialMap.find(texName); - std::multimap::iterator lastElement; - lastElement = MaterialMap.upper_bound(texName); + // Generate a hash out of all properties that can affect the material. + size_t h = 0; + boost::hash_combine(h, ambient.x); + boost::hash_combine(h, ambient.y); + boost::hash_combine(h, ambient.z); + boost::hash_combine(h, diffuse.x); + boost::hash_combine(h, diffuse.y); + boost::hash_combine(h, diffuse.z); + boost::hash_combine(h, specular.x); + boost::hash_combine(h, specular.y); + boost::hash_combine(h, specular.z); + boost::hash_combine(h, emissive.x); + boost::hash_combine(h, emissive.y); + boost::hash_combine(h, emissive.z); + boost::hash_combine(h, texName); + boost::hash_combine(h, vertexColour); + boost::hash_combine(h, alphaFlags); + + std::map::iterator itr = MaterialMap.find(h); if (itr != MaterialMap.end()) { - for ( ; itr != lastElement; ++itr) - { - //std::cout << "OK!"; - //MaterialPtr mat = MaterialManager::getSingleton().getByName(itr->second,recourceGroup); - return itr->second; - //if( mat->getA - } + // a suitable material exists already - use it + return itr->second; } + // not found, create a new one + MaterialMap.insert(std::make_pair(h, matname)); } // No existing material like this. Create a new one. @@ -572,7 +584,7 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam instance->setProperty ("diffuseMap", sh::makeProperty(texName)); - if (shape->data->colors.size() != 0) + if (vertexColour) instance->setProperty ("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); // Add transparency if NiAlphaProperty was present @@ -628,12 +640,11 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam } */ - MaterialMap.insert(std::make_pair(texName, matname)); return matname; } }; -std::multimap NIFMaterialLoader::MaterialMap; +std::map NIFMaterialLoader::MaterialMap; class NIFMeshLoader : Ogre::ManualResourceLoader From 78fe6fdce5a837b6f8c2eb31a42390d99fdc25e5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 27 Jul 2012 12:00:10 +0200 Subject: [PATCH 119/126] Issue #351: Refactoring Action class --- apps/openmw/mwclass/door.cpp | 6 +++--- apps/openmw/mwclass/potion.cpp | 5 ++--- apps/openmw/mwgui/bookwindow.cpp | 4 +++- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/scrollwindow.cpp | 4 +++- apps/openmw/mwscript/interpretercontext.cpp | 3 ++- apps/openmw/mwworld/action.cpp | 11 +++++++++++ apps/openmw/mwworld/action.hpp | 10 +++++++--- apps/openmw/mwworld/actionalchemy.cpp | 2 +- apps/openmw/mwworld/actionalchemy.hpp | 3 +-- apps/openmw/mwworld/actionapply.cpp | 18 +++++++++--------- apps/openmw/mwworld/actionapply.hpp | 14 ++++++-------- apps/openmw/mwworld/actionequip.cpp | 2 +- apps/openmw/mwworld/actionequip.hpp | 4 ++-- apps/openmw/mwworld/actionopen.cpp | 2 +- apps/openmw/mwworld/actionopen.hpp | 3 ++- apps/openmw/mwworld/actionread.cpp | 2 +- apps/openmw/mwworld/actionread.hpp | 4 ++-- apps/openmw/mwworld/actiontake.cpp | 2 +- apps/openmw/mwworld/actiontake.hpp | 4 ++-- apps/openmw/mwworld/actiontalk.cpp | 2 +- apps/openmw/mwworld/actiontalk.hpp | 4 ++-- apps/openmw/mwworld/actionteleport.cpp | 4 ++-- apps/openmw/mwworld/actionteleport.hpp | 8 ++++---- apps/openmw/mwworld/nullaction.hpp | 4 +--- 25 files changed, 71 insertions(+), 56 deletions(-) create mode 100644 apps/openmw/mwworld/action.cpp diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 359e50ffb..6939c356e 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -40,7 +40,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Door::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -97,18 +97,18 @@ namespace MWClass if (ref->ref.teleport) { // teleport door + /// \todo remove this if clause once ActionTeleport can also support other actors if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()==actor) { // the player is using the door // The reason this is not 3D is that it would get interrupted when you teleport MWBase::Environment::get().getSoundManager()->playSound(openSound, 1.0, 1.0); return boost::shared_ptr ( - new MWWorld::ActionTeleportPlayer (ref->ref.destCell, ref->ref.doorDest)); + new MWWorld::ActionTeleport (ref->ref.destCell, ref->ref.doorDest)); } else { // another NPC or a creature is using the door - // TODO return action for teleporting other NPC/creature return boost::shared_ptr (new MWWorld::NullAction); } } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 993dac6f6..3d370ac32 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -40,7 +40,7 @@ namespace MWClass physics.insertObjectPhysics(ptr, model); } } - + std::string Potion::getModel(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = @@ -158,7 +158,7 @@ namespace MWClass MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); return boost::shared_ptr ( - new MWWorld::ActionApply (actor, ref->base->mId, actor)); + new MWWorld::ActionApply (actor, ref->base->mId)); } MWWorld::Ptr @@ -170,4 +170,3 @@ namespace MWClass return MWWorld::Ptr(&cell.potions.insert(*ref), &cell); } } - diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 1ea3da839..1e0301d8e 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -3,9 +3,11 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" #include "../mwinput/inputmanager.hpp" #include "../mwsound/soundmanager.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/player.hpp" #include "formatting.hpp" #include "window_manager.hpp" @@ -99,7 +101,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); MWWorld::ActionTake take(mBook); - take.execute(); + take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); mWindowManager.removeGuiMode(GM_Book); } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 23a96b1d3..926c35172 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -175,7 +175,7 @@ namespace MWGui boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); - action->execute(); + action->execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); // this is necessary for books/scrolls: if they are already in the player's inventory, // the "Take" button should not be visible. diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index e6ff71a14..00e5a01dc 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -1,8 +1,10 @@ #include "scrollwindow.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" #include "../mwinput/inputmanager.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/player.hpp" #include "../mwsound/soundmanager.hpp" #include "formatting.hpp" @@ -63,7 +65,7 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack); MWWorld::ActionTake take(mScroll); - take.execute(); + take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); mWindowManager.removeGuiMode(GM_Scroll); } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 5da512778..3a824473e 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -10,6 +10,7 @@ #include "../mwbase/world.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" #include "../mwgui/window_manager.hpp" @@ -236,7 +237,7 @@ namespace MWScript if (!mAction.get()) throw std::runtime_error ("activation failed, because no action to perform"); - mAction->execute(); + mAction->execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); mActivationHandled = true; } diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp new file mode 100644 index 000000000..0fcbf4a6f --- /dev/null +++ b/apps/openmw/mwworld/action.cpp @@ -0,0 +1,11 @@ + +#include "action.hpp" + +MWWorld::Action::Action() {} + +MWWorld::Action::~Action() {} + +void MWWorld::Action::execute (const Ptr& actor) +{ + executeImp (actor); +} diff --git a/apps/openmw/mwworld/action.hpp b/apps/openmw/mwworld/action.hpp index d5cf12779..c95648135 100644 --- a/apps/openmw/mwworld/action.hpp +++ b/apps/openmw/mwworld/action.hpp @@ -3,6 +3,8 @@ namespace MWWorld { + class Ptr; + /// \brief Abstract base for actions class Action { @@ -10,13 +12,15 @@ namespace MWWorld Action (const Action& action); Action& operator= (const Action& action); + virtual void executeImp (const Ptr& actor) = 0; + public: - Action() {} + Action(); - virtual ~Action() {} + virtual ~Action(); - virtual void execute() = 0; + void execute (const Ptr& actor); }; } diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index eb91b6946..a7ee4fd0e 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -5,7 +5,7 @@ namespace MWWorld { - void ActionAlchemy::execute() + void ActionAlchemy::executeImp (const Ptr& actor) { MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy); } diff --git a/apps/openmw/mwworld/actionalchemy.hpp b/apps/openmw/mwworld/actionalchemy.hpp index 739de419b..e6d1a7976 100644 --- a/apps/openmw/mwworld/actionalchemy.hpp +++ b/apps/openmw/mwworld/actionalchemy.hpp @@ -7,8 +7,7 @@ namespace MWWorld { class ActionAlchemy : public Action { - public: - virtual void execute (); + virtual void executeImp (const Ptr& actor); }; } diff --git a/apps/openmw/mwworld/actionapply.cpp b/apps/openmw/mwworld/actionapply.cpp index b330a70e7..595ee6cb3 100644 --- a/apps/openmw/mwworld/actionapply.cpp +++ b/apps/openmw/mwworld/actionapply.cpp @@ -5,24 +5,24 @@ namespace MWWorld { - ActionApply::ActionApply (const Ptr& target, const std::string& id, const Ptr& actor) - : mTarget (target), mId (id), mActor (actor) + ActionApply::ActionApply (const Ptr& target, const std::string& id) + : mTarget (target), mId (id) {} - void ActionApply::execute() + void ActionApply::executeImp (const Ptr& actor) { - MWWorld::Class::get (mTarget).apply (mTarget, mId, mActor); + MWWorld::Class::get (mTarget).apply (mTarget, mId, actor); } ActionApplyWithSkill::ActionApplyWithSkill (const Ptr& target, const std::string& id, - const Ptr& actor, int skillIndex, int usageType) - : mTarget (target), mId (id), mActor (actor), mSkillIndex (skillIndex), mUsageType (usageType) + int skillIndex, int usageType) + : mTarget (target), mId (id), mSkillIndex (skillIndex), mUsageType (usageType) {} - void ActionApplyWithSkill::execute() + void ActionApplyWithSkill::executeImp (const Ptr& actor) { - if (MWWorld::Class::get (mTarget).apply (mTarget, mId, mActor) && mUsageType!=-1) - MWWorld::Class::get (mTarget).skillUsageSucceeded (mActor, mSkillIndex, mUsageType); + if (MWWorld::Class::get (mTarget).apply (mTarget, mId, actor) && mUsageType!=-1) + MWWorld::Class::get (mTarget).skillUsageSucceeded (actor, mSkillIndex, mUsageType); } } diff --git a/apps/openmw/mwworld/actionapply.hpp b/apps/openmw/mwworld/actionapply.hpp index 972417e02..523bf9373 100644 --- a/apps/openmw/mwworld/actionapply.hpp +++ b/apps/openmw/mwworld/actionapply.hpp @@ -13,29 +13,27 @@ namespace MWWorld { Ptr mTarget; std::string mId; - Ptr mActor; + + virtual void executeImp (const Ptr& actor); public: - ActionApply (const Ptr& target, const std::string& id, const Ptr& actor); - - virtual void execute(); + ActionApply (const Ptr& target, const std::string& id); }; class ActionApplyWithSkill : public Action { Ptr mTarget; std::string mId; - Ptr mActor; int mSkillIndex; int mUsageType; + virtual void executeImp (const Ptr& actor); + public: - ActionApplyWithSkill (const Ptr& target, const std::string& id, const Ptr& actor, + ActionApplyWithSkill (const Ptr& target, const std::string& id, int skillIndex, int usageType); - - virtual void execute(); }; } diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 52b9437fd..20e0afb68 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -13,7 +13,7 @@ namespace MWWorld { } - void ActionEquip::execute () + void ActionEquip::executeImp (const Ptr& actor) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player); diff --git a/apps/openmw/mwworld/actionequip.hpp b/apps/openmw/mwworld/actionequip.hpp index 6cf3640f8..5685a294a 100644 --- a/apps/openmw/mwworld/actionequip.hpp +++ b/apps/openmw/mwworld/actionequip.hpp @@ -10,11 +10,11 @@ namespace MWWorld { Ptr mObject; + virtual void executeImp (const Ptr& actor); + public: /// @param item to equip ActionEquip (const Ptr& object); - - virtual void execute (); }; } diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index a70773af9..c73ef9149 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -15,7 +15,7 @@ namespace MWWorld mContainer = container; } - void ActionOpen::execute () + void ActionOpen::executeImp (const MWWorld::Ptr& actor) { if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) return; diff --git a/apps/openmw/mwworld/actionopen.hpp b/apps/openmw/mwworld/actionopen.hpp index eff26c78c..5666ff293 100644 --- a/apps/openmw/mwworld/actionopen.hpp +++ b/apps/openmw/mwworld/actionopen.hpp @@ -12,10 +12,11 @@ namespace MWWorld { Ptr mContainer; + virtual void executeImp (const MWWorld::Ptr& actor); + public: ActionOpen (const Ptr& container); ///< \param The Container the Player has activated. - virtual void execute (); }; } diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 1e03230c7..c81d79e03 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -11,7 +11,7 @@ namespace MWWorld { } - void ActionRead::execute () + void ActionRead::executeImp (const MWWorld::Ptr& actor) { LiveCellRef *ref = mObject.get(); diff --git a/apps/openmw/mwworld/actionread.hpp b/apps/openmw/mwworld/actionread.hpp index a4b495f79..9bb74fb88 100644 --- a/apps/openmw/mwworld/actionread.hpp +++ b/apps/openmw/mwworld/actionread.hpp @@ -10,11 +10,11 @@ namespace MWWorld { Ptr mObject; // book or scroll to read + virtual void executeImp (const MWWorld::Ptr& actor); + public: /// @param book or scroll to read ActionRead (const Ptr& object); - - virtual void execute (); }; } diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp index 39544b35d..5207f1a10 100644 --- a/apps/openmw/mwworld/actiontake.cpp +++ b/apps/openmw/mwworld/actiontake.cpp @@ -13,7 +13,7 @@ namespace MWWorld { ActionTake::ActionTake (const MWWorld::Ptr& object) : mObject (object) {} - void ActionTake::execute() + void ActionTake::executeImp (const Ptr& actor) { if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) return; diff --git a/apps/openmw/mwworld/actiontake.hpp b/apps/openmw/mwworld/actiontake.hpp index f495fc3c4..52a114acf 100644 --- a/apps/openmw/mwworld/actiontake.hpp +++ b/apps/openmw/mwworld/actiontake.hpp @@ -10,11 +10,11 @@ namespace MWWorld { MWWorld::Ptr mObject; + virtual void executeImp (const Ptr& actor); + public: ActionTake (const MWWorld::Ptr& object); - - virtual void execute(); }; } diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index a0f9d8c4c..78171bbe5 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -9,7 +9,7 @@ namespace MWWorld { ActionTalk::ActionTalk (const Ptr& actor) : mActor (actor) {} - void ActionTalk::execute() + void ActionTalk::executeImp (const Ptr& actor) { MWBase::Environment::get().getDialogueManager()->startDialogue (mActor); } diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp index 1b7b9b6d6..53adf9e53 100644 --- a/apps/openmw/mwworld/actiontalk.hpp +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -10,12 +10,12 @@ namespace MWWorld { Ptr mActor; + virtual void executeImp (const Ptr& actor); + public: ActionTalk (const Ptr& actor); ///< \param actor The actor the player is talking to - - virtual void execute(); }; } diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 8ae3244f8..9c87d37ae 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -6,12 +6,12 @@ namespace MWWorld { - ActionTeleportPlayer::ActionTeleportPlayer (const std::string& cellName, + ActionTeleport::ActionTeleport (const std::string& cellName, const ESM::Position& position) : mCellName (cellName), mPosition (position) {} - void ActionTeleportPlayer::execute() + void ActionTeleport::executeImp (const Ptr& actor) { if (mCellName.empty()) MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition); diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index 00efdc876..a13cb61b2 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -9,17 +9,17 @@ namespace MWWorld { - class ActionTeleportPlayer : public Action + class ActionTeleport : public Action { std::string mCellName; ESM::Position mPosition; + virtual void executeImp (const Ptr& actor); + public: - ActionTeleportPlayer (const std::string& cellName, const ESM::Position& position); + ActionTeleport (const std::string& cellName, const ESM::Position& position); ///< If cellName is empty, an exterior cell is asumed. - - virtual void execute(); }; } diff --git a/apps/openmw/mwworld/nullaction.hpp b/apps/openmw/mwworld/nullaction.hpp index c8e3368e4..7ef8b4a06 100644 --- a/apps/openmw/mwworld/nullaction.hpp +++ b/apps/openmw/mwworld/nullaction.hpp @@ -8,9 +8,7 @@ namespace MWWorld /// \brief Action: do nothing class NullAction : public Action { - public: - - virtual void execute() {} + virtual void executeImp (const Ptr& actor) {} }; } From 8b08928dae542758bdf59eb423cedf8b31e1082f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 27 Jul 2012 12:19:25 +0200 Subject: [PATCH 120/126] Issue #351: Added sound playing to Action --- apps/openmw/mwworld/action.cpp | 13 +++++++++++++ apps/openmw/mwworld/action.hpp | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp index 0fcbf4a6f..0a57d5f67 100644 --- a/apps/openmw/mwworld/action.cpp +++ b/apps/openmw/mwworld/action.cpp @@ -1,11 +1,24 @@ #include "action.hpp" +#include "../mwbase/environment.hpp" + +#include "../mwsound/soundmanager.hpp" + MWWorld::Action::Action() {} MWWorld::Action::~Action() {} void MWWorld::Action::execute (const Ptr& actor) { + if (!mSoundId.empty()) + MWBase::Environment::get().getSoundManager()->playSound3D (actor, mSoundId, 1.0, 1.0, + MWSound::Play_NoTrack); + executeImp (actor); } + +void MWWorld::Action::setSound (const std::string& id) +{ + mSoundId = id; +} diff --git a/apps/openmw/mwworld/action.hpp b/apps/openmw/mwworld/action.hpp index c95648135..a00f67951 100644 --- a/apps/openmw/mwworld/action.hpp +++ b/apps/openmw/mwworld/action.hpp @@ -1,6 +1,8 @@ #ifndef GAME_MWWORLD_ACTION_H #define GAME_MWWORLD_ACTION_H +#include + namespace MWWorld { class Ptr; @@ -8,6 +10,8 @@ namespace MWWorld /// \brief Abstract base for actions class Action { + std::string mSoundId; + // not implemented Action (const Action& action); Action& operator= (const Action& action); @@ -21,6 +25,8 @@ namespace MWWorld virtual ~Action(); void execute (const Ptr& actor); + + void setSound (const std::string& id); }; } From 0da3f2cb594abf9bd41698427b1c831d8a6a4dd8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 27 Jul 2012 12:27:22 +0200 Subject: [PATCH 121/126] Issue #314: Playing drink sound when using a potion --- apps/openmw/mwclass/potion.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 3d370ac32..d3f2912ea 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -157,8 +157,12 @@ namespace MWClass MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - return boost::shared_ptr ( + boost::shared_ptr action ( new MWWorld::ActionApply (actor, ref->base->mId)); + + action->setSound ("Drink"); + + return action; } MWWorld::Ptr From 90de02b901bde3e62bdf6438998f2365a3704e1f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 30 Jul 2012 11:43:28 +0200 Subject: [PATCH 122/126] Issue #350: console only script instructions --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/engine.cpp | 9 ++- apps/openmw/engine.hpp | 4 + apps/openmw/main.cpp | 10 ++- apps/openmw/mwgui/console.cpp | 10 ++- apps/openmw/mwgui/console.hpp | 5 +- apps/openmw/mwgui/window_manager.cpp | 4 +- apps/openmw/mwgui/window_manager.hpp | 2 +- apps/openmw/mwscript/consoleextensions.cpp | 24 ++++++ apps/openmw/mwscript/consoleextensions.hpp | 25 ++++++ apps/openmw/mwscript/docs/vmformat.txt | 13 +++- apps/openmw/mwscript/extensions.cpp | 18 ++++- apps/openmw/mwscript/extensions.hpp | 8 +- apps/openmw/mwscript/userextensions.cpp | 91 ++++++++++++++++++++++ apps/openmw/mwscript/userextensions.hpp | 25 ++++++ 15 files changed, 230 insertions(+), 20 deletions(-) create mode 100644 apps/openmw/mwscript/consoleextensions.cpp create mode 100644 apps/openmw/mwscript/consoleextensions.hpp create mode 100644 apps/openmw/mwscript/userextensions.cpp create mode 100644 apps/openmw/mwscript/userextensions.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8e424ad56..556b9a1ba 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -39,7 +39,7 @@ add_openmw_dir (mwscript locals scriptmanager compilercontext interpretercontext cellextensions miscextensions guiextensions soundextensions skyextensions statsextensions containerextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions - animationextensions transformationextensions + animationextensions transformationextensions consoleextensions userextensions ) add_openmw_dir (mwsound diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ab5b63071..d224ab71b 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -129,6 +129,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) , mCompileAll (false) , mScriptContext (0) , mFSStrict (false) + , mScriptConsoleMode (false) , mCfgMgr(configurationManager) { std::srand ( std::time(NULL) ); @@ -326,7 +327,8 @@ void OMW::Engine::go() MWScript::registerExtensions (mExtensions); mEnvironment.setWindowManager (new MWGui::WindowManager( - mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"))); + mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), + mScriptConsoleMode)); // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); @@ -490,3 +492,8 @@ void OMW::Engine::setFallbackValues(std::map fallbackMa { mFallbackMap = fallbackMap; } + +void OMW::Engine::setScriptConsoleMode (bool enabled) +{ + mScriptConsoleMode = enabled; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 031cae551..01b2dd8d6 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -73,6 +73,7 @@ namespace OMW bool mCompileAll; std::string mFocusName; std::map mFallbackMap; + bool mScriptConsoleMode; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; @@ -158,6 +159,9 @@ namespace OMW void setFallbackValues(std::map map); + /// Enable console-only script functionality + void setScriptConsoleMode (bool enabled); + private: Files::ConfigurationManager& mCfgMgr; }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 993ec6623..c54c5969b 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -124,12 +124,15 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("script-verbose", bpo::value()->implicit_value(true) ->default_value(false), "verbose script output") - ("new-game", bpo::value()->implicit_value(true) - ->default_value(false), "activate char gen/new game mechanics") - ("script-all", bpo::value()->implicit_value(true) ->default_value(false), "compile all scripts (excluding dialogue scripts) at startup") + ("script-console", bpo::value()->implicit_value(true) + ->default_value(false), "enable console-only script functionality") + + ("new-game", bpo::value()->implicit_value(true) + ->default_value(false), "activate char gen/new game mechanics") + ("fs-strict", bpo::value()->implicit_value(true) ->default_value(false), "strict file system handling (no case folding)") @@ -249,6 +252,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setCompileAll(variables["script-all"].as()); engine.setAnimationVerbose(variables["anim-verbose"].as()); engine.setFallbackValues(variables["fallback"].as().mMap); + engine.setScriptConsoleMode (variables["script-console"].as()); return true; } diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 4101165c1..39f36d28a 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -105,9 +105,10 @@ namespace MWGui } } - Console::Console(int w, int h, const Compiler::Extensions& extensions) + Console::Console(int w, int h, bool consoleOnlyScripts) : Layout("openmw_console.layout"), - mCompilerContext (MWScript::CompilerContext::Type_Console) + mCompilerContext (MWScript::CompilerContext::Type_Console), + mConsoleOnlyScripts (consoleOnlyScripts) { setCoord(10,10, w-10, h/2); @@ -126,7 +127,8 @@ namespace MWGui history->setVisibleVScroll(true); // compiler - mCompilerContext.setExtensions (&extensions); + MWScript::registerExtensions (mExtensions, mConsoleOnlyScripts); + mCompilerContext.setExtensions (&mExtensions); } void Console::enable() @@ -246,7 +248,7 @@ namespace MWGui { ConsoleInterpreterContext interpreterContext (*this, mPtr); Interpreter::Interpreter interpreter; - MWScript::installOpcodes (interpreter); + MWScript::installOpcodes (interpreter, mConsoleOnlyScripts); std::vector code; output.getCode (code); interpreter.run (&code[0], code.size(), interpreterContext); diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index eadf4aa4e..b01ebf7fa 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "../mwscript/compilercontext.hpp" @@ -24,8 +25,10 @@ namespace MWGui { private: + Compiler::Extensions mExtensions; MWScript::CompilerContext mCompilerContext; std::vector mNames; + bool mConsoleOnlyScripts; bool compile (const std::string& cmd, Compiler::Output& output); @@ -62,7 +65,7 @@ namespace MWGui StringList::iterator current; std::string editString; - Console(int w, int h, const Compiler::Extensions& extensions); + Console(int w, int h, bool consoleOnlyScripts); void enable(); diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index aa0595b85..25f0fc097 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -41,7 +41,7 @@ using namespace MWGui; WindowManager::WindowManager( - const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath) + const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, bool consoleOnlyScripts) : mGuiManager(NULL) , mHud(NULL) , mMap(NULL) @@ -113,7 +113,7 @@ WindowManager::WindowManager( mMenu = new MainMenu(w,h); mMap = new MapWindow(*this); mStatsWindow = new StatsWindow(*this); - mConsole = new Console(w,h, extensions); + mConsole = new Console(w,h, consoleOnlyScripts); mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); mInventoryWindow = new InventoryWindow(*this,mDragAndDrop); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index adab79942..51fde071d 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -94,7 +94,7 @@ namespace MWGui typedef std::vector FactionList; typedef std::vector SkillList; - WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath); + WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, bool consoleOnlyScripts); virtual ~WindowManager(); /** diff --git a/apps/openmw/mwscript/consoleextensions.cpp b/apps/openmw/mwscript/consoleextensions.cpp new file mode 100644 index 000000000..00b4f74e5 --- /dev/null +++ b/apps/openmw/mwscript/consoleextensions.cpp @@ -0,0 +1,24 @@ + +#include "consoleextensions.hpp" + +#include + +#include +#include +#include + +namespace MWScript +{ + namespace Console + { + void registerExtensions (Compiler::Extensions& extensions) + { + + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + + } + } +} diff --git a/apps/openmw/mwscript/consoleextensions.hpp b/apps/openmw/mwscript/consoleextensions.hpp new file mode 100644 index 000000000..b10bf06a8 --- /dev/null +++ b/apps/openmw/mwscript/consoleextensions.hpp @@ -0,0 +1,25 @@ +#ifndef GAME_SCRIPT_CONSOLEEXTENSIONS_H +#define GAME_SCRIPT_CONSOLEEXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + /// \brief Script functionality limited to the console + namespace Console + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index b979420dd..3ca93d4b2 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -169,5 +169,14 @@ op 0x2000164: SetScale op 0x2000165: SetScale, explicit reference op 0x2000166: SetAngle op 0x2000167: SetAngle, explicit reference -opcodes 0x2000168-0x3ffffff unused - +op 0x2000168: GetScale +op 0x2000169: GetScale, explicit reference +op 0x200016a: GetAngle +op 0x200016b: GetAngle, explicit reference +op 0x200016c: user1 (console only, requires --script-console switch) +op 0x200016d: user2 (console only, requires --script-console switch) +op 0x200016e: user3, explicit reference (console only, requires --script-console switch) +op 0x200016f: user3 (implicit reference, console only, requires --script-console switch) +op 0x2000170: user4, explicit reference (console only, requires --script-console switch) +op 0x2000171: user4 (implicit reference, console only, requires --script-console switch) +opcodes 0x2000172-0x3ffffff unused diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index b7425aca0..1b1560820 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -16,10 +16,12 @@ #include "dialogueextensions.hpp" #include "animationextensions.hpp" #include "transformationextensions.hpp" +#include "consoleextensions.hpp" +#include "userextensions.hpp" namespace MWScript { - void registerExtensions (Compiler::Extensions& extensions) + void registerExtensions (Compiler::Extensions& extensions, bool consoleOnly) { Cell::registerExtensions (extensions); Misc::registerExtensions (extensions); @@ -33,9 +35,15 @@ namespace MWScript Dialogue::registerExtensions (extensions); Animation::registerExtensions (extensions); Transformation::registerExtensions (extensions); + + if (consoleOnly) + { + Console::registerExtensions (extensions); + User::registerExtensions (extensions); + } } - void installOpcodes (Interpreter::Interpreter& interpreter) + void installOpcodes (Interpreter::Interpreter& interpreter, bool consoleOnly) { Interpreter::installOpcodes (interpreter); Cell::installOpcodes (interpreter); @@ -50,5 +58,11 @@ namespace MWScript Dialogue::installOpcodes (interpreter); Animation::installOpcodes (interpreter); Transformation::installOpcodes (interpreter); + + if (consoleOnly) + { + Console::installOpcodes (interpreter); + User::installOpcodes (interpreter); + } } } diff --git a/apps/openmw/mwscript/extensions.hpp b/apps/openmw/mwscript/extensions.hpp index 9738367a0..cb1aaf9db 100644 --- a/apps/openmw/mwscript/extensions.hpp +++ b/apps/openmw/mwscript/extensions.hpp @@ -13,9 +13,11 @@ namespace Interpreter namespace MWScript { - void registerExtensions (Compiler::Extensions& extensions); - - void installOpcodes (Interpreter::Interpreter& interpreter); + void registerExtensions (Compiler::Extensions& extensions, bool consoleOnly = false); + ///< \param consoleOnly include console only extensions + + void installOpcodes (Interpreter::Interpreter& interpreter, bool consoleOnly = false); + ///< \param consoleOnly include console only opcodes } #endif diff --git a/apps/openmw/mwscript/userextensions.cpp b/apps/openmw/mwscript/userextensions.cpp new file mode 100644 index 000000000..9c9738815 --- /dev/null +++ b/apps/openmw/mwscript/userextensions.cpp @@ -0,0 +1,91 @@ + +#include "userextensions.hpp" + +#include + +#include +#include +#include +#include + +#include "ref.hpp" + +namespace MWScript +{ + /// Temporary script extensions. + /// + /// \attention Do not commit changes to this file to a git repository! + namespace User + { + class OpUser1 : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + runtime.getContext().report ("user1: not in use"); + } + }; + + class OpUser2 : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + runtime.getContext().report ("user2: not in use"); + } + }; + + template + class OpUser3 : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { +// MWWorld::Ptr ptr = R()(runtime); + + runtime.getContext().report ("user3: not in use"); + } + }; + + template + class OpUser4 : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { +// MWWorld::Ptr ptr = R()(runtime); + + runtime.getContext().report ("user4: not in use"); + } + }; + + const int opcodeUser1 = 0x200016c; + const int opcodeUser2 = 0x200016d; + const int opcodeUser3 = 0x200016e; + const int opcodeUser3Explicit = 0x200016f; + const int opcodeUser4 = 0x2000170; + const int opcodeUser4Explicit = 0x2000171; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction ("user1", "", opcodeUser1); + extensions.registerInstruction ("user2", "", opcodeUser2); + extensions.registerInstruction ("user3", "", opcodeUser3, opcodeUser3); + extensions.registerInstruction ("user4", "", opcodeUser4, opcodeUser4); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5 (opcodeUser1, new OpUser1); + interpreter.installSegment5 (opcodeUser2, new OpUser2); + interpreter.installSegment5 (opcodeUser3, new OpUser3); + interpreter.installSegment5 (opcodeUser3Explicit, new OpUser3); + interpreter.installSegment5 (opcodeUser4, new OpUser4); + interpreter.installSegment5 (opcodeUser4Explicit, new OpUser4); + } + } +} diff --git a/apps/openmw/mwscript/userextensions.hpp b/apps/openmw/mwscript/userextensions.hpp new file mode 100644 index 000000000..3642eb5f4 --- /dev/null +++ b/apps/openmw/mwscript/userextensions.hpp @@ -0,0 +1,25 @@ +#ifndef GAME_SCRIPT_USEREXTENSIONS_H +#define GAME_SCRIPT_USEREXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + /// \brief Temporaty script functionality limited to the console + namespace User + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif From 23f8595b8767f97492e9aeb67d82a8a8cbd81543 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 30 Jul 2012 11:57:19 +0200 Subject: [PATCH 123/126] Issue #352: refactored script execution in console --- apps/openmw/mwgui/console.cpp | 49 +++++++++++++++++++---------------- apps/openmw/mwgui/console.hpp | 2 ++ 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 39f36d28a..fdcc67604 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -175,6 +175,32 @@ namespace MWGui print("#FF2222" + msg + "\n"); } + void Console::execute (const std::string& command) + { + // Log the command + print("#FFFFFF> " + command + "\n"); + + Compiler::Locals locals; + Compiler::Output output (locals); + + if (compile (command + "\n", output)) + { + try + { + ConsoleInterpreterContext interpreterContext (*this, mPtr); + Interpreter::Interpreter interpreter; + MWScript::installOpcodes (interpreter, mConsoleOnlyScripts); + std::vector code; + output.getCode (code); + interpreter.run (&code[0], code.size(), interpreterContext); + } + catch (const std::exception& error) + { + printError (std::string ("An exception has been thrown: ") + error.what()); + } + } + } + void Console::keyPress(MyGUI::WidgetPtr _sender, MyGUI::KeyCode key, MyGUI::Char _char) @@ -236,28 +262,7 @@ namespace MWGui current = command_history.end(); editString.clear(); - // Log the command - print("#FFFFFF> " + cm + "\n"); - - Compiler::Locals locals; - Compiler::Output output (locals); - - if (compile (cm + "\n", output)) - { - try - { - ConsoleInterpreterContext interpreterContext (*this, mPtr); - Interpreter::Interpreter interpreter; - MWScript::installOpcodes (interpreter, mConsoleOnlyScripts); - std::vector code; - output.getCode (code); - interpreter.run (&code[0], code.size(), interpreterContext); - } - catch (const std::exception& error) - { - printError (std::string ("An exception has been thrown: ") + error.what()); - } - } + execute (cm); command->setCaption(""); } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index b01ebf7fa..f587fefed 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -89,6 +89,8 @@ namespace MWGui /// Error message void printError(const std::string &msg); + void execute (const std::string& command); + private: void keyPress(MyGUI::WidgetPtr _sender, From fd6c155118fbe469fb78fc584eb3fbf98df7a80f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 30 Jul 2012 12:37:46 +0200 Subject: [PATCH 124/126] Issue #352: added --script-run switch --- apps/openmw/engine.cpp | 8 ++++++++ apps/openmw/engine.hpp | 4 ++++ apps/openmw/main.cpp | 6 ++++++ apps/openmw/mwgui/console.cpp | 16 ++++++++++++++++ apps/openmw/mwgui/console.hpp | 2 ++ apps/openmw/mwgui/window_manager.cpp | 5 +++++ apps/openmw/mwgui/window_manager.hpp | 2 ++ 7 files changed, 43 insertions(+) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d224ab71b..5e9aedf66 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -390,6 +390,9 @@ void OMW::Engine::go() << std::endl; } + if (!mStartupScript.empty()) + MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript); + // Start the main rendering loop mOgre->start(); @@ -497,3 +500,8 @@ void OMW::Engine::setScriptConsoleMode (bool enabled) { mScriptConsoleMode = enabled; } + +void OMW::Engine::setStartupScript (const std::string& path) +{ + mStartupScript = path; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 01b2dd8d6..57402c91e 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -74,6 +74,7 @@ namespace OMW std::string mFocusName; std::map mFallbackMap; bool mScriptConsoleMode; + std::string mStartupScript; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; @@ -162,6 +163,9 @@ namespace OMW /// Enable console-only script functionality void setScriptConsoleMode (bool enabled); + /// Set path for a script that is run on startup in the console. + void setStartupScript (const std::string& path); + private: Files::ConfigurationManager& mCfgMgr; }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index c54c5969b..fb1657ad4 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -130,6 +130,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("script-console", bpo::value()->implicit_value(true) ->default_value(false), "enable console-only script functionality") + ("script-run", bpo::value()->default_value(""), + "set a file that is execute in the console on startup\n\n" + "Note: The file contains a list of script lines, but not a complete scripts. " + "That means no begin/end and no variable declarations.") + ("new-game", bpo::value()->implicit_value(true) ->default_value(false), "activate char gen/new game mechanics") @@ -253,6 +258,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setAnimationVerbose(variables["anim-verbose"].as()); engine.setFallbackValues(variables["fallback"].as().mMap); engine.setScriptConsoleMode (variables["script-console"].as()); + engine.setStartupScript (variables["script-run"].as()); return true; } diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index fdcc67604..86c8940a1 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -2,6 +2,7 @@ #include "console.hpp" #include +#include #include #include @@ -201,6 +202,21 @@ namespace MWGui } } + void Console::executeFile (const std::string& path) + { + std::ifstream stream (path.c_str()); + + if (!stream.is_open()) + printError ("failed to open file: " + path); + else + { + std::string line; + + while (std::getline (stream, line)) + execute (line); + } + } + void Console::keyPress(MyGUI::WidgetPtr _sender, MyGUI::KeyCode key, MyGUI::Char _char) diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index f587fefed..1893b0148 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -91,6 +91,8 @@ namespace MWGui void execute (const std::string& command); + void executeFile (const std::string& command); + private: void keyPress(MyGUI::WidgetPtr _sender, diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 25f0fc097..659af0447 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -740,3 +740,8 @@ bool WindowManager::getWorldMouseOver() { return mHud->getWorldMouseOver(); } + +void WindowManager::executeInConsole (const std::string& path) +{ + mConsole->executeFile (path); +} diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 51fde071d..3653615a6 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -237,6 +237,8 @@ namespace MWGui void processChangedSettings(const Settings::CategorySettingVector& changed); + void executeInConsole (const std::string& path); + private: OEngine::GUI::MyGUIManager *mGuiManager; HUD *mHud; From 2ccecd839bdac85672cd3aa861cfa95f25c27f46 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 30 Jul 2012 12:43:23 +0200 Subject: [PATCH 125/126] improved the help text for --script-run; updated readme.txt --- apps/openmw/main.cpp | 2 +- readme.txt | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index fb1657ad4..0ca9dd6d9 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -131,7 +131,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ->default_value(false), "enable console-only script functionality") ("script-run", bpo::value()->default_value(""), - "set a file that is execute in the console on startup\n\n" + "select a file that is executed in the console on startup\n\n" "Note: The file contains a list of script lines, but not a complete scripts. " "That means no begin/end and no variable declarations.") diff --git a/readme.txt b/readme.txt index ded9bcd7b..ce3d115e3 100644 --- a/readme.txt +++ b/readme.txt @@ -66,9 +66,16 @@ Allowed options: --debug [=arg(=1)] (=0) debug mode --nosound [=arg(=1)] (=0) disable all sounds --script-verbose [=arg(=1)] (=0) verbose script output - --new-game [=arg(=1)] (=0) activate char gen/new game mechanics --script-all [=arg(=1)] (=0) compile all scripts (excluding dialogue scri pts) at startup + --script-console [=arg(=1)] (=0) enable console-only script functionality + --script-run arg select a file that is executed in the consol + e on startup + + Note: The file contains a list of script + lines, but not a complete scripts. That mean + s no begin/end and no variable declarations. + --new-game [=arg(=1)] (=0) activate char gen/new game mechanics --fs-strict [=arg(=1)] (=0) strict file system handling (no case folding ) --encoding arg (=win1252) Character encoding used in OpenMW game messa From e7a1ab9fa627e5509d0611d86b07e0ed9b65d5ce Mon Sep 17 00:00:00 2001 From: Michael Mc Donnell Date: Mon, 30 Jul 2012 15:04:14 -0400 Subject: [PATCH 126/126] Define OGRE_PLUGIN_DEBUG_SUFFIX in all cases. --- CMakeLists.txt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea0c41fe2..9ac6419ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,14 +235,13 @@ endif (APPLE) # Set up Ogre plugin folder & debug suffix set(DEBUG_SUFFIX "") -if (DEFINED CMAKE_BUILD_TYPE) - if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(DEBUG_SUFFIX "_d") - add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") - else() - add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") - endif() +if (DEFINED CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DEBUG_SUFFIX "_d") + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") +else() + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") endif() + add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}") add_definitions(-DOGRE_PLUGIN_DIR_DBG="${OGRE_PLUGIN_DIR_DBG}") add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")