diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b2ed0a767..483a74eef 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "components/esm/records.hpp" #include @@ -92,6 +93,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) std::string effect; MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); + + //If the region has changed if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){ timer.restart(); @@ -248,6 +251,11 @@ void OMW::Engine::loadBSA() std::cout << "Adding " << iter->second.string() << std::endl; addBSA (iter->second.string()); } + + std::string m = mDataDir.string(); + std::cout << "Data dir" << m << "\n"; + addDir(m, mFSStrict); + } // add resources directory @@ -345,9 +353,6 @@ void OMW::Engine::go() mOgre.configure(!isFile(ogreCfg.c_str()), cfgUserDir, plugCfg, false); - addResourcesDirectory (mDataDir / "Meshes"); - addResourcesDirectory (mDataDir / "Textures"); - // This has to be added BEFORE MyGUI is initialized, as it needs // to find core.xml here. addResourcesDirectory(mResDir / "mygui"); @@ -384,7 +389,7 @@ void OMW::Engine::go() mOgre.getCamera(), mEnvironment.mWorld->getStore(), (mDataDir), - mUseSound); + mUseSound, mFSStrict); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8cde67671..0bd133f21 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -34,7 +34,7 @@ namespace MWClass if (!model.empty()) { MWRender::Rendering rendering (cellRender, ref->ref); - cellRender.insertMesh ("meshes\\" + model); + cellRender.insertMesh("meshes\\" + model); cellRender.insertActorPhysics(); ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index bb5578f6d..9ef5e6f40 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -95,8 +95,7 @@ namespace MWClass upperright[uppernumbers++] = npcName + "chest"; neckandup[neckNumbers++] = npcName + "chest"; } - //std::cout << "GETTING NPC PART"; - //Orgre::SceneNode test = cellRender.getNpcPart(); + const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); @@ -113,8 +112,6 @@ namespace MWClass const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st"); - //std::cout << "RACE" << bodyRaceID << "\n"; - Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75); if (groin){ @@ -124,10 +121,9 @@ namespace MWClass } if (tail) { cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "tail"); - //std::cout << "TAIL\n"; } - //addresses[1] = npcName + "groin"; + if(upperleg){ cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, kOgrePi, npcName + "upper leg", addresses, numbers); //-18 cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers); @@ -218,9 +214,6 @@ namespace MWClass if(hand) { - //std::cout << "WE FOUND A HAND\n"; - //-50, 0, -120 - //std::cout << "WE FOUND HANDS\n"; std::string pass; if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0) pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF"; @@ -230,7 +223,6 @@ namespace MWClass cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 upperleft[uppernumbers] = npcName + "hand"; upperright[uppernumbers++] = npcName + "hand2"; - //cellRender.rotateMesh(Ogre::Vector3(0, 0,0), kOgrePi, upperleft, uppernumbers); cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); } @@ -244,7 +236,6 @@ namespace MWClass else pass =hands->model; //-50, 0, -120 cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 - //cellRender.insertMesh("meshes\\" + hands->model, Ogre::Vector3(42, 0,110), Ogre::Vector3(1, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 upperleft[uppernumbers] = npcName + "hand"; upperright[uppernumbers++] = npcName + "hand2"; diff --git a/apps/openmw/mwrender/exterior.hpp b/apps/openmw/mwrender/exterior.hpp index 40d9c60ae..6c7f6effc 100644 --- a/apps/openmw/mwrender/exterior.hpp +++ b/apps/openmw/mwrender/exterior.hpp @@ -6,6 +6,7 @@ #include "OgreColourValue.h" #include +#include namespace Ogre { @@ -74,6 +75,7 @@ namespace MWRender virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst); virtual void insertMesh(const std::string &mesh); + virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements); virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements); diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index ad0ecf69d..7fe228f40 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -182,11 +182,11 @@ void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, void InteriorCellRender::insertMesh(const std::string &mesh) { - assert (insert); + assert (insert); - NIFLoader::load(mesh); - MovableObject *ent = scene.getMgr()->createEntity(mesh); - insert->attachObject(ent); + NIFLoader::load(mesh); + MovableObject *ent = scene.getMgr()->createEntity(mesh); + insert->attachObject(ent); if (mInsertMesh.empty()) mInsertMesh = mesh; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 564ebe941..970118a13 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -84,20 +84,25 @@ namespace MWSound // finding. It takes DOS paths (any case, \\ slashes or / slashes) // relative to the sound dir, and translates them into full paths // of existing files in the filesystem, if they exist. + bool FSstrict; FileFinder::FileFinder files; + FileFinder::FileFinderStrict strict; + FileFinder::FileFinder musicpath; + FileFinder::FileFinderStrict musicpathStrict; SoundImpl(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &str, - const std::string &soundDir) + const std::string &soundDir, const std::string &musicDir, bool fsstrict) : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) , updater(mgr) , cameraTracker(mgr) , store(str) - , files(soundDir) + , files(soundDir), strict(soundDir) + ,musicpath(musicDir), musicpathStrict(musicDir) { + FSstrict = fsstrict; cout << "Sound output: " << SOUND_OUT << endl; cout << "Sound decoder: " << SOUND_IN << endl; - // Attach the camera to the camera tracker cameraTracker.followCamera(camera); @@ -111,6 +116,8 @@ namespace MWSound cameraTracker.unfollowCamera(); } + + static std::string toMp3(std::string str) { std::string::size_type i = str.rfind('.'); @@ -122,28 +129,76 @@ namespace MWSound return str; } - bool hasFile(const std::string &str) + bool hasFile(const std::string &str, bool music = false) { - if(files.has(str)) return true; - // Not found? Try with .mp3 - return files.has(toMp3(str)); + if(FSstrict == false) + { + if(music) + { + if(musicpath.has(str)) return true; + + // Not found? Try with .mp3 + return musicpath.has(toMp3(str)); + } + else + { + if(files.has(str)) return true; + return files.has(toMp3(str)); + } + } + else + { + if(music) + { + if(musicpathStrict.has(str)) return true; + + // Not found? Try with .mp3 + return musicpathStrict.has(toMp3(str)); + } + else + { + if(strict.has(str)) return true; + return strict.has(toMp3(str)); + } + } } // Convert a Morrowind sound path (eg. Fx\funny.wav) to full path // with proper slash conversion (eg. datadir/Sound/Fx/funny.wav) - std::string convertPath(const std::string &str) + std::string convertPath(const std::string &str, bool music = false) { - // Search and return - if(files.has(str)) - return files.lookup(str); - - // Try mp3 if the wav wasn't found - std::string mp3 = toMp3(str); - if(files.has(mp3)) - return files.lookup(mp3); + if(FSstrict == false) + { + // Search and return + if(music && musicpath.has(str)) + return musicpath.lookup(str); + else if(files.has(str)) + return files.lookup(str); + + // Try mp3 if the wav wasn't found + std::string mp3 = toMp3(str); + if(music && musicpath.has(mp3)) + return musicpath.lookup(mp3); + else if(files.has(mp3)) + return files.lookup(mp3); + } + else + { + if(music && musicpathStrict.has(str)) + return musicpathStrict.lookup(str); + else if(strict.has(str)) + return strict.lookup(str); + + // Try mp3 if the wav wasn't found + std::string mp3 = toMp3(str); + if(music && musicpathStrict.has(mp3)) + return musicpathStrict.lookup(mp3); + else if(strict.has(str)) + return strict.lookup(mp3); + } - // Give up - return ""; + // Give up + return ""; } // Convert a soundId to file name, and modify the volume @@ -304,15 +359,31 @@ namespace MWSound } }; + void SoundManager::streamMusicFull (const std::string& filename) + { + if(!mData) return; + + // Play the sound and tell it to stream, if possible. TODO: + // Store the reference, the jukebox will need to check status, + // control volume etc. + if (mData->music) + mData->music->stop(); + mData->music = mData->mgr->load(filename); + mData->music->setStreaming(true); + mData->music->setVolume(0.4); + mData->music->play(); + + } + SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &store, boost::filesystem::path dataDir, - bool useSound) - : mData(NULL) + bool useSound, bool fsstrict) + : mData(NULL), fsStrict (fsstrict) { MP3Lookup(dataDir / "Music/Explore/"); if(useSound) - mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string()); + mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string(), (dataDir / "Music").string(), fsstrict); } SoundManager::~SoundManager() @@ -321,6 +392,16 @@ namespace MWSound delete mData; } + void SoundManager::streamMusic(const std::string& filename) + { + if(mData->hasFile(filename, true)) + { + std::string fullpath = mData->convertPath(filename, true); + streamMusicFull(fullpath); + } + } + + void SoundManager::MP3Lookup(boost::filesystem::path dir) { boost::filesystem::directory_iterator dir_iter(dir), dir_end; @@ -353,7 +434,7 @@ namespace MWSound try { std::cout << "Playing " << music << "\n"; - streamMusic(music); + streamMusicFull(music); } catch(std::exception &e) { @@ -397,21 +478,6 @@ namespace MWSound return !mData->isPlaying(ptr, "_say_sound"); } - void SoundManager::streamMusic (const std::string& filename) - { - if(!mData) return; - - // Play the sound and tell it to stream, if possible. TODO: - // Store the reference, the jukebox will need to check status, - // control volume etc. - if (mData->music) - mData->music->stop(); - mData->music = mData->mgr->load(filename); - mData->music->setStreaming(true); - mData->music->setVolume(0.4); - mData->music->play(); - - } void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 8c48986db..ab9559176 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -27,19 +27,28 @@ namespace MWSound // Hide implementation details - engine.cpp is compiling // enough as it is. struct SoundImpl; - + SoundImpl *mData; std::vector files; - + bool fsStrict; + + void streamMusicFull (const std::string& filename); + ///< Play a soundifle + /// \param absolute filename public: + SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, - boost::filesystem::path dataDir, bool useSound); + boost::filesystem::path dataDir, bool useSound, bool fsstrict); ~SoundManager(); + void streamMusic(const std::string& filename); + ///< Play a soundifle + /// \param filename name of a sound file in "Music/" in the data directory. + void startRandomTitle(); void MP3Lookup(boost::filesystem::path dir); - //struct SoundImpl; + bool isMusicPlaying(); SoundImpl getMData(); @@ -51,9 +60,7 @@ namespace MWSound bool sayDone (MWWorld::Ptr reference) const; ///< Is actor not speaking? - void streamMusic (const std::string& filename); - ///< Play a soundifle - /// \param filename name of a sound file in "Music/" in the data directory. + void playSound (const std::string& soundId, float volume, float pitch); ///< Play a sound, independently of 3D-position diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 4691eb546..f29b8b237 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -23,6 +23,7 @@ #include "bsa_archive.hpp" +#include #include #include #include @@ -32,7 +33,186 @@ using namespace Ogre; using namespace Mangle::Stream; +struct ciLessBoost : std::binary_function +{ + bool operator() (const std::string & s1, const std::string & s2) const { + //case insensitive version of is_less + return lexicographical_compare(s1, s2, boost::algorithm::is_iless()); + } +}; + +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 comparePortion(std::string file1, std::string file2, int start, int size) const + { + for(int i = start; i < start+size; i++) + { + char one = file1.at(i); + char two = file2.at(i); + if(tolower(one) != tolower(two) ) + return false; + } + return true; + } + + public: + + DirArchive(const String& name) + : FileSystemArchive(name, "Dir"), currentdir (name) + { + mType = "Dir"; + std::string s = name; + cutoff = s.size() + 1; + if(fsstrict == false) + populateMap(currentdir); + + } + void populateMap(boost::filesystem::path d){ + //need to cut off first + boost::filesystem::directory_iterator dir_iter(d), dir_end; + std::vector filesind; + boost::filesystem::path f; + for(;dir_iter != dir_end; dir_iter++) + { + if(boost::filesystem::is_directory(*dir_iter)) + populateMap(*dir_iter); + else + { + + f = *dir_iter; + std::string s = f.string(); + + std::string small; + if(cutoff < s.size()) + small = s.substr(cutoff, s.size() - cutoff); + else + small = s.substr(cutoff - 1, s.size() - cutoff); + + filesind.push_back(small); + } + } + std::string small; + std::string original = d.string(); + if(cutoff < original.size()) + small = original.substr(cutoff, original.size() - cutoff); + else + small = original.substr(cutoff - 1, original.size() - cutoff); + m[small] = filesind; + + } + + bool isCaseSensitive() const { return fsstrict; } + + // The archive is loaded in the constructor, and never unloaded. + void load() {} + void unload() {} + + bool exists(const String& filename) { + std::string copy = filename; + + + + for (unsigned int i = 0; i < filename.size(); i++) + { + if(copy.at(i) == '\\' ){ + copy.replace(i, 1, "/"); + } + } + + + if(copy.at(0) == '\\' || copy.at(0) == '/') + { + copy.erase(0, 1); + } + if(fsstrict == true) + { + //std::cout << "fsstrict " << copy << "\n"; + return FileSystemArchive::exists(copy); + } + + + int last = copy.size() - 1; + int i = last; + + for (;last >= 0; i--) + { + if(copy.at(i) == '/' || copy.at(i) == '\\') + break; + } + + std::string folder = copy.substr(0, i); //folder with no slash + + std::vector& current = m[folder]; + + for(std::vector::iterator iter = current.begin(); iter != current.end(); iter++) + { + if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){ + return FileSystemArchive::exists(*iter); + } + } + + + return false; + } + + DataStreamPtr open(const String& filename, bool readonly = true) const + { + std::map, ciLessBoost> mlocal = m; + std::string copy = filename; + + + + for (unsigned int i = 0; i < filename.size(); i++) + { + if(copy.at(i) == '\\' ){ + copy.replace(i, 1, "/"); + } + } + + + if(copy.at(0) == '\\' || copy.at(0) == '/') + { + copy.erase(0, 1); + } + + if(fsstrict == true) + { + return FileSystemArchive::open(copy, readonly); + } + + + int last = copy.size() - 1; + int i = last; + + for (;last >= 0; i--) + { + if(copy.at(i) == '/' || copy.at(i) == '\\') + break; + } + + std::string folder = copy.substr(0, i); //folder with no slash + std::vector current = mlocal[folder]; + + for(std::vector::iterator iter = current.begin(); iter != current.end(); iter++) + { + if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){ + return FileSystemArchive::open(*iter, readonly); + } + } + DataStreamPtr p; + return p; + } + +}; + class BSAArchive : public Archive { BSAFile arc; @@ -145,7 +325,27 @@ public: void destroyInstance( Archive* arch) { delete arch; } }; +class DirArchiveFactory : public FileSystemArchiveFactory +{ +public: + const String& getType() const + { + static String name = "Dir"; + return name; + } + + Archive *createInstance( const String& name ) + { + return new DirArchive(name); + } + + void destroyInstance( Archive* arch) { delete arch; } +}; + + static bool init = false; +static bool init2 = false; + static void insertBSAFactory() { if(!init) @@ -155,6 +355,15 @@ static void insertBSAFactory() } } +static void insertDirFactory() +{ + if(!init2) + { + ArchiveManager::getSingleton().addArchiveFactory( new DirArchiveFactory ); + init2 = true; + } +} + // The function below is the only publicly exposed part of this file void addBSA(const std::string& name, const std::string& group) @@ -163,3 +372,11 @@ void addBSA(const std::string& name, const std::string& group) ResourceGroupManager::getSingleton(). addResourceLocation(name, "BSA", group); } +void addDir(const std::string& name, const bool& fs, const std::string& group) +{ + fsstrict = fs; + insertDirFactory(); + + ResourceGroupManager::getSingleton(). + addResourceLocation(name, "Dir", group); +} diff --git a/components/bsa/bsa_archive.hpp b/components/bsa/bsa_archive.hpp index bde6d9c3b..bf7e7ee51 100644 --- a/components/bsa/bsa_archive.hpp +++ b/components/bsa/bsa_archive.hpp @@ -22,6 +22,9 @@ */ #include +#include +#include +#include #ifndef _BSA_ARCHIVE_H_ #define _BSA_ARCHIVE_H_ @@ -29,5 +32,6 @@ /// Add the given BSA file as an input archive in the Ogre resource /// system. void addBSA(const std::string& file, const std::string& group="General"); +void addDir(const std::string& file, const bool& fs, const std::string& group="General"); #endif diff --git a/components/file_finder/file_finder.hpp b/components/file_finder/file_finder.hpp index cfa07dce9..0e1e07226 100644 --- a/components/file_finder/file_finder.hpp +++ b/components/file_finder/file_finder.hpp @@ -20,9 +20,9 @@ class FileFinderT void add(const boost::filesystem::path &pth) { - std::string file = pth.string(); - std::string key = file.substr(cut); - owner->table[key] = file; + std::string file = pth.string(); + std::string key = file.substr(cut); + owner->table[key] = file; } }; @@ -50,17 +50,18 @@ public: bool has(const std::string& file) const { - return table.find(file) != table.end(); + return table.find(file) != table.end(); } // Find the full path from a relative path. const std::string &lookup(const std::string& file) const { - return table.find(file)->second; + return table.find(file)->second; } }; // The default is to use path_less for equality checks typedef FileFinderT FileFinder; +typedef FileFinderT FileFinderStrict; } #endif diff --git a/components/file_finder/filename_less.hpp b/components/file_finder/filename_less.hpp index 9f251b1c8..bc3186ce9 100644 --- a/components/file_finder/filename_less.hpp +++ b/components/file_finder/filename_less.hpp @@ -44,6 +44,41 @@ struct path_less return compareString(a.c_str(), b.c_str()) < 0; } }; + +struct path_slash +{ + int compareChar(char a, char b) const + { + if(a>b) return 1; + else if(a namespace Nif { @@ -433,67 +434,70 @@ public: class NiKeyframeData : public Record { -public: - void read(NIFFile *nif) - { - // Rotations first - int count = nif->getInt(); - if(count) - { - int type = nif->getInt(); - - if(type == 1) - nif->skip(count*4*5); // time + quaternion - else if(type == 3) - nif->skip(count*4*8); // rot1 + tension+bias+continuity - else if(type == 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"); - } - - // Then translation - count = nif->getInt(); - if(count) - { - int type = nif->getInt(); - - if(type == 1) nif->getFloatLen(count*4); // time + translation - else if(type == 2) - nif->getFloatLen(count*10); // trans1 + forward + backward - else if(type == 3) - nif->getFloatLen(count*7); // trans1 + tension,bias,continuity - else nif->fail("Unknown translation type"); - } - - // Finally, scalings - count = nif->getInt(); - if(count) - { - int type = nif->getInt(); - - int size = 0; - if(type == 1) size = 2; // time+scale - else if(type == 2) size = 4; // 1 + forward + backward (floats) - else if(type == 3) size = 5; // 1 + tbc - else nif->fail("Unknown scaling type"); - nif->getFloatLen(count*size); - } - } + public: + + void read(NIFFile *nif) + { + // Rotations first + int count = nif->getInt(); + if(count) + { + int type = nif->getInt(); + + if(type == 1) + nif->skip(count*4*5); // time + quaternion + else if(type == 3) + nif->skip(count*4*8); // rot1 + tension+bias+continuity + else if(type == 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"); + } + + // Then translation + count = nif->getInt(); + + if(count) + { + int type = nif->getInt(); + + if(type == 1) + nif->getFloatLen(count*4); // time + translation + else if(type == 2) + nif->getFloatLen(count*10); // trans1 + forward + backward + else if(type == 3) + nif->getFloatLen(count*7); // trans1 + tension,bias,continuity + else nif->fail("Unknown translation type"); + } + + // Finally, scalings + count = nif->getInt(); + if(count) + { + int type = nif->getInt(); + + int size = 0; + if(type == 1) size = 2; // time+scale + else if(type == 2) size = 4; // 1 + forward + backward (floats) + else if(type == 3) size = 5; // 1 + tbc + else nif->fail("Unknown scaling type"); + nif->getFloatLen(count*size); + } + } }; } // Namespace diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 2db51b003..318c39909 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -81,11 +81,11 @@ Vector3 NIFLoader::convertVector3(const Nif::Vector& vec) Quaternion NIFLoader::convertRotation(const Nif::Matrix& rot) { Real matrix[3][3]; - + for (int i=0; i<3; i++) for (int j=0; j<3; j++) matrix[i][j] = rot.v[i].array[j]; - + return Quaternion(Matrix3(matrix)); } @@ -265,7 +265,7 @@ void NIFLoader::createMaterial(const String &name, } else pass->setDepthWriteEnabled(true); */ - + // Add transparency if NiAlphaProperty was present if (alphaFlags != -1) @@ -346,16 +346,16 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std sub->vertexData = new VertexData(); sub->vertexData->vertexCount = numVerts; sub->useSharedVertices = false; - + VertexDeclaration *decl = sub->vertexData->vertexDeclaration; decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION); - + HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true); - + VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; bind->setBinding(nextBuf++, vbuf); @@ -692,7 +692,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou if (verIndex < data->normals.length) { Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3); - + for (int j=0; j<3; j++) (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; } @@ -852,7 +852,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, } for (; itrafo, bounds, bone); } @@ -867,7 +867,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, Tri Chest */ if((isChest && stack < 10 ) || (isHands && counter < 3) || !(isChest || isHands)){ //(isBeast && isChest && stack < 10 && counter == skincounter ) - + std::string name = node->name.toString(); //if (isChest) //std::cout << "NAME: " << name << "\n"; @@ -894,15 +894,15 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, //if(isBeast && isChest) //cout << "Handling Shape, Stack " << stack <<"\n"; - - + + counter++; } /*if(isHands){ //cout << "Handling Shape, Stack " << stack <<"\n"; counter++; }*/ - + } stack--; @@ -923,7 +923,7 @@ void NIFLoader::loadResource(Resource *resource) //std::cout <<"NAME:" << name; //if(name.length() >= 20) // {std::string split = name.substr(name.length() - 20, 20); - //if(name == + //if(name == //std::cout <<"NAME:" << name << "LEN: " << name.length() << "\n"; const std::string test ="meshes\\b\\B_N_Dark Elf_M_Skins.NIF"; const std::string test2 ="meshes\\b\\B_N_Dark Elf_M_Skins.nif"; @@ -951,15 +951,15 @@ void NIFLoader::loadResource(Resource *resource) const std::string test24 ="meshes\\b\\B_N_High Elf_M_Skins.nif"; //std::cout <<"LEN1:" << test.length() << "TEST: " << test << "\n"; - - + + if(name.compare(test) == 0 || name.compare(test2) == 0 || name.compare(test3) == 0 || name.compare(test4) == 0 || name.compare(test5) == 0 || name.compare(test6) == 0 || name.compare(test7) == 0 || name.compare(test8) == 0 || name.compare(test9) == 0 || name.compare(test10) == 0 || name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 || name.compare(test14) == 0 || name.compare(test15) == 0 || name.compare(test16) == 0 || name.compare(test17) == 0 || name.compare(test18) == 0 || name.compare(test19) == 0 || name.compare(test20) == 0 || name.compare(test21) == 0 || name.compare(test22) == 0 || name.compare(test23) == 0 || name.compare(test24) == 0 - + ){ //std::cout << "Welcome Chest\n"; isChest = true; @@ -1028,7 +1028,7 @@ void NIFLoader::loadResource(Resource *resource) std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; isChest = true; }*/ - + //if(split== "Skins.NIF") // std::cout << "\nSPECIAL PROPS\n"; resourceName = ""; @@ -1100,14 +1100,14 @@ void NIFLoader::loadResource(Resource *resource) // mesh->setSkeletonName(getSkeletonName()); } -MeshPtr NIFLoader::load(const std::string &name, +MeshPtr NIFLoader::load(const std::string &name, const std::string &group) { MeshManager *m = MeshManager::getSingletonPtr(); // Check if the resource already exists ResourcePtr ptr = m->getByName(name, group); MeshPtr resize; - + const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif"; const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif"; const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif"; @@ -1118,8 +1118,8 @@ MeshPtr NIFLoader::load(const std::string &name, const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif"; const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif"; - if (!ptr.isNull()){ - + if (!ptr.isNull()){ + //if(pieces > 1) //cout << "It exists\n"; resize = MeshPtr(ptr); @@ -1130,17 +1130,17 @@ MeshPtr NIFLoader::load(const std::string &name, { resize = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr()); //cout <<"EXISTING" << name << "\n"; - + //if(pieces > 1) //cout << "Creating it\n"; - - + + //resize->load(); //resize->reload(); //return 0; ResourcePtr ptr = m->getByName(name, group); resize = MeshPtr(ptr); - + //NIFLoader::getSingletonPtr()-> /*ResourcePtr ptr = m->getByName(name, group); if (!ptr.isNull()){ @@ -1151,7 +1151,7 @@ MeshPtr NIFLoader::load(const std::string &name, } return resize; } - + /* 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 cec9d95d7..ed0661293 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -73,11 +73,11 @@ class NIFLoader : Ogre::ManualResourceLoader virtual void loadResource(Ogre::Resource *resource); - static Ogre::MeshPtr load(const std::string &name, + static Ogre::MeshPtr load(const std::string &name, const std::string &group="General"); - + Ogre::Vector3 convertVector3(const Nif::Vector& vec); Ogre::Quaternion convertRotation(const Nif::Matrix& rot); @@ -113,7 +113,7 @@ class NIFLoader : Ogre::ManualResourceLoader { return resourceName + ".skel"; } - + // This is the interface to the Ogre resource system. It allows us to // load NIFs from BSAs, in the file system and in any other place we // tell Ogre to look (eg. in zip or rar files.) It's also used to @@ -131,8 +131,7 @@ class NIFLoader : Ogre::ManualResourceLoader int counter; int numbers; int stack; - - std::multimap MaterialMap; + std::multimap MaterialMap; // pointer to the ogre mesh which is currently build Ogre::Mesh *mesh;