diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 20c9312cd..b2b84255a 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -1,13 +1,17 @@ #include "engine.hpp" +#include "components/esm/loadcell.hpp" #include #include #include +#include "components/esm/records.hpp" +#include #include #include - +#include +#include #include #include "mwgui/window_manager.hpp" @@ -37,6 +41,9 @@ #include #include "mwgui/class.hpp" + +//using namespace ESM; + void OMW::Engine::executeLocalScripts() { for (MWWorld::World::ScriptList::const_iterator iter ( @@ -57,8 +64,77 @@ void OMW::Engine::executeLocalScripts() mIgnoreLocalPtr = MWWorld::Ptr(); } + bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) { + if(! (mEnvironment.mSoundManager->isMusicPlaying())) + { + // Play some good 'ol tunes + mEnvironment.mSoundManager->startRandomTitle(); + } + + std::string effect; + + + + MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayerPos().getPlayer().getCell(); + //If the region has changed + if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){ + timer.restart(); + if (test.name != current->cell->region) + { + total = 0; + test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); + } + + if(test.soundList.size() > 0) + { + std::vector::iterator soundIter = test.soundList.begin(); + //mEnvironment.mSoundManager + if(total == 0){ + while (!(soundIter == test.soundList.end())) + { + ESM::NAME32 go = soundIter->sound; + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + total += chance; + } + } + + srand ( time(NULL) ); + int r = rand() % total; //old random code + int pos = 0; + soundIter = test.soundList.begin(); + while (!(soundIter == test.soundList.end())) + { + const ESM::NAME32 go = soundIter->sound; + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + if( r - pos < chance) + { + effect = go.name; + //play sound + std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + mEnvironment.mSoundManager->playSound(effect, 20.0, 1.0); + + break; + + } + pos += chance; + } + } + + //mEnvironment.mSoundManager->playSound(effect, 1.0, 1.0); + //printf("REGION: %s\n", test.name); + + } + else if(current->cell->data.flags & current->cell->Interior) + { + test.name = ""; + } + try { mEnvironment.mFrameDuration = evt.timeSinceLastFrame; @@ -108,6 +184,7 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) { std::cerr << "Error in framelistener: " << e.what() << std::endl; } + //std::cout << "TESTING2"; return true; } @@ -217,6 +294,11 @@ void OMW::Engine::go() assert (!mCellName.empty()); assert (!mMaster.empty()); + test.name = ""; + total = 0; + + + std::cout << "Data directory: " << mDataDir << "\n"; const char* plugCfg = "plugins.cfg"; @@ -257,7 +339,7 @@ void OMW::Engine::go() mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), mOgre.getCamera(), mEnvironment.mWorld->getStore(), - (mDataDir / "Sound").file_string(), + (mDataDir), mUseSound); // Create script system @@ -306,16 +388,7 @@ void OMW::Engine::go() mOgre.getRoot()->addFrameListener (this); // Play some good 'ol tunes - std::string music = (mDataDir / "Music/Explore/mx_explore_5.mp3").file_string(); - try - { - std::cout << "Playing " << music << "\n"; - mEnvironment.mSoundManager->streamMusic(music); - } - catch(std::exception &e) - { - std::cout << " Music Error: " << e.what() << "\n"; - } + mEnvironment.mSoundManager->startRandomTitle(); // scripts if (mCompileAll) diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 01f339874..4f8f5af9c 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -12,6 +12,8 @@ #include "mwworld/environment.hpp" #include "mwworld/ptr.hpp" +#include + namespace Compiler { @@ -52,6 +54,8 @@ namespace OMW class Engine : private Ogre::FrameListener { + + //int nFiles; boost::filesystem::path mDataDir; OEngine::Render::OgreRenderer mOgre; std::string mCellName; @@ -61,12 +65,15 @@ namespace OMW bool mNewGame; bool mUseSound; bool mCompileAll; + int total; MWWorld::Environment mEnvironment; MWScript::ScriptManager *mScriptManager; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; OEngine::GUI::MyGUIManager *mGuiManager; + ESM::Region test; + boost::timer timer; int focusFrameCounter; static const int focusUpdateFrame = 10; @@ -79,6 +86,7 @@ namespace OMW /// add resources directory /// \note This function works recursively. + void addResourcesDirectory (const boost::filesystem::path& path); /// Load all BSA files in data directory. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index f9f99e58d..de8b6ffff 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -14,6 +14,7 @@ #include "../mwrender/cellimp.hpp" #include "../mwmechanics/mechanicsmanager.hpp" +#include namespace MWClass { @@ -28,32 +29,230 @@ namespace MWClass void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const { + //Ogre::SceneNode *chest; ESMS::LiveCellRef *ref = ptr.get(); + + //Store scenenodes by npc's name + bodypart [0] , npc's name + bodypart [1] + //Ex. Fargothchest , Fargothneck assert (ref->base != NULL); + std::string hairID = ref->base->hair; std::string headID = ref->base->head; + std::string npcName = ref->base->name; + std::cout << "NPC: " << npcName << "\n"; //get the part of the bodypart id which describes the race and the gender std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); std::string headModel = "meshes\\" + environment.mWorld->getStore().bodyParts.find(headID)->model; - MWRender::Rendering rendering (cellRender, ref->ref); + std::string hairModel = "meshes\\" + + environment.mWorld->getStore().bodyParts.find(hairID)->model; - cellRender.insertMesh (headModel); + MWRender::Rendering rendering (cellRender, ref->ref); + //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the // right place const ESM::BodyPart *bodyPart = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest"); - if (bodyPart) - cellRender.insertMesh("meshes\\" + bodyPart->model); + //bodyPart->model-> + Ogre::Vector3 pos = Ogre::Vector3( 20, 20, 20); + Ogre::Vector3 axis = Ogre::Vector3( 0, 0, 1); + Ogre::Radian angle = Ogre::Radian(0); + + std::string addresses[6] = {"", "", "", "","", ""}; + std::string addresses2[6] = {"", "", "", "", "", ""}; + std::string upperleft[5] = {"", "", "", "", ""}; + std::string upperright[5] = {"", "", "", "", ""}; + std::string neckandup[5] = {"", "", "","",""}; + std::string empty[6] = {"", "", "", "","", ""}; + int numbers = 0; + int uppernumbers = 0; + int neckNumbers = 0; + + if (bodyPart){ + + cellRender.insertMesh("meshes\\" + bodyPart->model, pos, axis, angle, npcName + "chest", addresses, numbers, true); //2 0 + addresses2[numbers] = npcName + "chest"; + addresses[numbers++] = npcName + "chest"; + upperleft[uppernumbers] = npcName + "chest"; + upperright[uppernumbers++] = npcName + "chest"; + neckandup[neckNumbers++] = npcName + "chest"; + } + //std::cout << "GETTING NPC PART"; + //Orgre::SceneNode test = cellRender.getNpcPart(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); - } + const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); + const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); + const ESM::BodyPart *arm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); + const ESM::BodyPart *neck = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck"); + const ESM::BodyPart *knee = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee"); + const ESM::BodyPart *ankle = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle"); + const ESM::BodyPart *foot = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot"); + const ESM::BodyPart *feet = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet"); + const ESM::BodyPart *tail = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail"); + const ESM::BodyPart *wrist = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); + const ESM::BodyPart *forearm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); + const ESM::BodyPart *hand = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand.1st"); + 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); + std::string upperarmpath[2] = {npcName + "chest", npcName + "upper arm"}; + + if (groin){ + cellRender.insertMesh("meshes\\" + groin->model, pos2, axis, Ogre::Radian(3.14), npcName + "groin", addresses, numbers); + addresses2[numbers] = npcName + "groin"; + addresses[numbers++] = npcName + "groin"; + } + if (tail) { + cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, Ogre::Radian(3.14), npcName + "tail", addresses, numbers, "tail"); + //std::cout << "TAIL\n"; + } + + //addresses[1] = npcName + "groin"; + if(upperleg){ + cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -14), axis, Ogre::Radian(3.14), npcName + "upper leg", addresses, numbers); //-18 + cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -14), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers); + addresses2[numbers] = npcName + "upper leg2"; + addresses[numbers++] = npcName + "upper leg"; + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); + } + if(knee) + { + cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -2, -18), axis, Ogre::Radian(0), npcName + "knee", addresses, numbers); + //cellRender.rotateMesh(Ogre::Vector3(0, 1, 0), Ogre::Radian (1), npcName + "upper arm"); + cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -2, -18), axis, Ogre::Radian(0), npcName + "knee2", addresses2, numbers); + + addresses2[numbers] = npcName + "knee2"; + addresses[numbers++] = npcName + "knee"; + } + if(ankle){ + + cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0, -1, -18), axis, Ogre::Radian(0), npcName + "ankle", addresses, numbers); //-1 + cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0, -1, -18), axis, Ogre::Radian(0), npcName + "ankle2", addresses2, numbers); //-1 + + addresses2[numbers] = npcName + "ankle2"; + addresses[numbers++] = npcName + "ankle"; + } + if(foot){ + if(bodyRaceID.compare("b_n_khajiit_m_") == 0) + { + feet = foot; + } + else + { + cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot", addresses, numbers); + + cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot2", addresses2, numbers); + addresses2[numbers] = npcName + "foot2"; + addresses[numbers++] = npcName + "foot"; + } + //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); + } + if(feet){ + + cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, Ogre::Radian(3.14), npcName + "foot", addresses, numbers); //9, 0, -14 + + cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, Ogre::Radian(3.14), npcName + "foot2", addresses2, numbers); + addresses2[numbers] = npcName + "foot2"; + addresses[numbers++] = npcName + "foot"; + //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); + } + + + if (arm){ + //010 + cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(-12.5, 0, 104), Ogre::Vector3(0, 1, 0), Ogre::Radian(-3.14 / 2), npcName + "upper arm", upperleft, uppernumbers); //1, 0,.75 + //cellRender.rotateMesh(Ogre::Vector3(1, 0, 0), Ogre::Radian (.45), upperarmpath, 2); //-.5, 0, -.75 + cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(12.5, 0, 105), Ogre::Vector3(-.5, 0, -.75), Ogre::Radian(3.14), npcName + "upper arm2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "upper arm"; + upperright[uppernumbers++] = npcName + "upper arm2"; + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); //1 -1 1 + cellRender.rotateMesh(Ogre::Vector3(0, .1, 0), Ogre::Radian(3.14/2), upperleft, uppernumbers); + } + + if (forearm) + { + //addresses[1] = npcName + "upper arm"; + cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm", upperleft, uppernumbers); + cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "forearm"; + upperright[uppernumbers++] = npcName + "forearm2"; + } + //else + // std::cout << npcName << "has no forearm"; + if (wrist) + { + if(upperleft[uppernumbers - 1].compare(npcName + "upper arm") == 0) + { + cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm", upperleft, uppernumbers); + cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "forearm2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "forearm"; + upperright[uppernumbers++] = npcName + "forearm2"; + + } + cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "wrist", upperleft, uppernumbers); + cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "wrist2", upperright, uppernumbers); + upperleft[uppernumbers] = npcName + "wrist"; + upperright[uppernumbers++] = npcName + "wrist2"; + } + + + 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"; + else + pass = hand->model; + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), npcName + "hand", upperleft, uppernumbers,false); //0, 100, -100 0,0,120 + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), Ogre::Radian(3.14), 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), Ogre::Radian(3.14), upperleft, uppernumbers); + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); + } + if(hands) + { + std::string pass; + if(hands->model.compare("b\\B_N_Redguard_F_Hands.1st.nif")==0 && bodyRaceID.compare("b_n_redguard_m_") == 0) + pass = "b\\B_N_Redguard_M_Hands.1st.nif"; + else if(hands->model.compare("b\\B_N_Imperial_M_Hands.1st.nif") == 0 && bodyRaceID.compare("b_n_nord_m_") == 0) + pass = "b\\B_N_Nord_M_Hands.1st.nif"; + else + pass =hands->model; //-50, 0, -120 + cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), Ogre::Radian(3.14), 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), Ogre::Radian(3.14), 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), Ogre::Radian(3.14), npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 + upperleft[uppernumbers] = npcName + "hand"; + upperright[uppernumbers++] = npcName + "hand2"; + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); + cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); + } + + //neck will reset chest counter + if(neck) + { + cellRender.insertMesh ("meshes\\" + neck->model, Ogre::Vector3( 0, 0, 120), axis, Ogre::Radian(3.14), npcName + "neck", neckandup, neckNumbers); + neckandup[neckNumbers++] = npcName + "neck"; + } + cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers); + neckandup[neckNumbers++] = npcName + "head"; + cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + + } void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const { diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index ab52f76c4..d030da20a 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -5,10 +5,12 @@ namespace MWClass { + static bool isChest; + //static ;bool isChest = false; class Npc : public MWWorld::Class { public: - + virtual std::string getId (const MWWorld::Ptr& ptr) const; ///< Return ID of \a ptr diff --git a/apps/openmw/mwrender/cellimp.hpp b/apps/openmw/mwrender/cellimp.hpp index bc6f2874a..e7a06ac6e 100644 --- a/apps/openmw/mwrender/cellimp.hpp +++ b/apps/openmw/mwrender/cellimp.hpp @@ -6,6 +6,13 @@ #include "components/esm_store/cell_store.hpp" #include "../mwworld/refdata.hpp" +#include + +namespace Ogre +{ + class SceneNode; + class Vector3; +} namespace ESM { @@ -16,7 +23,6 @@ namespace MWWorld { class Environment; } - namespace MWRender { /// Base class for cell render, that implements inserting references into a cell in a @@ -31,9 +37,15 @@ namespace MWRender /// start inserting a new reference. virtual void insertBegin (ESM::CellRef &ref) = 0; + virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) = 0; /// insert a mesh related to the most recent insertBegin call. + 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) = 0; + virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) = 0; virtual void insertMesh(const std::string &mesh) = 0; + virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) = 0; + + /// insert a light related to the most recent insertBegin call. virtual void insertLight(float r, float g, float b, float radius) = 0; diff --git a/apps/openmw/mwrender/exterior.cpp b/apps/openmw/mwrender/exterior.cpp index 58c783d72..28986d6d7 100644 --- a/apps/openmw/mwrender/exterior.cpp +++ b/apps/openmw/mwrender/exterior.cpp @@ -8,6 +8,9 @@ #include #include "mwscene.hpp" +#include +#include "mwscene.hpp" +#include using namespace MWRender; using namespace Ogre; @@ -57,8 +60,134 @@ void ExteriorCellRender::insertBegin (ESM::CellRef &ref) insert->setOrientation(xr*yr*zr); } + +void ExteriorCellRender::rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) +{ + assert(insert); + Ogre::SceneNode *parent = insert; + //std::cout << "ELEMENTS:" << elements; + for (int i = 0; i < elements; i++){ + if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) + parent = dynamic_cast (parent->getChild(sceneNodeName[i])); + } + parent->rotate(axis, angle); +} +/* +void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements){ + assert (insert); + //insert-> + Ogre::SceneNode *parent = insert; + for (int i = 0; i < elements; i++){ + if(sceneParent[i] != "" && parent->getChild(sceneParent[i])) + parent = dynamic_cast (parent->getChild(sceneParent[i])); + } + + npcPart = parent->createChildSceneNode(sceneNodeName); + NIFLoader::load(mesh); + MovableObject *ent = scene.getMgr()->createEntity(mesh); + + npcPart->translate(vec); + npcPart->rotate(axis, angle); + // npcPart->translate(vec); + //npcPart->rotate(axis, angle); + npcPart->attachObject(ent); + //npcPart-> + +} +*/ +void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) +{ + insertMesh(mesh, vec, axis, angle, sceneNodeName, sceneParent, elements, true); +} +void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst){ + + assert (insert); + //insert-> + Ogre::SceneNode *parent = insert; + for (int i = 0; i < elements; i++){ + if(sceneParent[i] != "" && parent->getChild(sceneParent[i])) + parent = dynamic_cast (parent->getChild(sceneParent[i])); + } + + npcPart = parent->createChildSceneNode(sceneNodeName); + MeshPtr good2 = NIFLoader::load(mesh); + + MovableObject *ent = scene.getMgr()->createEntity(mesh); + + + npcPart->translate(vec); + npcPart->rotate(axis, angle); + npcPart->attachObject(ent); + + Ogre::MeshManager *m = MeshManager::getSingletonPtr(); + 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"; + const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; + + const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif"; + const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif"; + const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif"; + const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif"; + + const std::string beastfoot1 ="foot\\b\\B_N_Khajiit_F_Skins.nif"; + const std::string beastfoot2 ="foot\\b\\B_N_Khajiit_M_Skins.nif"; + const std::string beastfoot3 ="foot\\b\\B_N_Argonian_F_Skins.nif"; + const std::string beastfoot4 ="foot\\b\\B_N_Argonian_M_Skins.nif"; + if(mesh.compare(beast1) == 0 && m->getByName(beasttail1).isNull()) + { + //std::cout << "CLONINGKHAJIITF\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail1); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot1); + good2->reload(); + } + else if(mesh.compare(beast2) == 0 && m->getByName(beasttail2).isNull()) + { + //std::cout << "CLONINGKHAJIITM\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail2); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot2); + good2->reload(); + } + else if(mesh.compare(beast3) == 0 && m->getByName(beasttail3).isNull()) + { + //std::cout << "CLONINGARGONIANF\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail3); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot3); + good2->reload(); + } + else if(mesh.compare(beast4) == 0 && m->getByName(beasttail4).isNull()) + { + //std::cout << "CLONINGARGONIANM\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail4); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot4); + good2->reload(); + } +} // insert a mesh related to the most recent insertBegin call. +void ExteriorCellRender::scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) +{ + assert(insert); + Ogre::SceneNode *parent = insert; + //std::cout << "ELEMENTS:" << elements; + for (int i = 0; i < elements; i++){ + if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) + parent = dynamic_cast (parent->getChild(sceneNodeName[i])); + } + parent->scale(axis); +} + +// insert a mesh related to the most recent insertBegin call. + + void ExteriorCellRender::insertMesh(const std::string &mesh) { assert (insert); diff --git a/apps/openmw/mwrender/exterior.hpp b/apps/openmw/mwrender/exterior.hpp index 7de027672..89cad3bb8 100644 --- a/apps/openmw/mwrender/exterior.hpp +++ b/apps/openmw/mwrender/exterior.hpp @@ -5,6 +5,7 @@ #include "cellimp.hpp" #include "OgreColourValue.h" +#include namespace Ogre { @@ -53,6 +54,7 @@ namespace MWRender Ogre::SceneNode *base; Ogre::SceneNode *insert; + Ogre::SceneNode *npcPart; // 0 normal, 1 more bright, 2 max int ambientMode; @@ -63,7 +65,12 @@ namespace MWRender virtual void insertBegin (ESM::CellRef &ref); /// insert a mesh related to the most recent insertBegin call. - virtual void insertMesh(const std::string &mesh); + virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements); + 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); /// insert a light related to the most recent insertBegin call. virtual void insertLight(float r, float g, float b, float radius); @@ -78,6 +85,7 @@ namespace MWRender void configureFog(); void setAmbientMode(); + public: diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index 1e88ecab4..1f1eac2af 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -5,9 +5,14 @@ #include #include #include +#include #include #include "mwscene.hpp" +#include +#include + +#include using namespace MWRender; using namespace Ogre; @@ -58,6 +63,120 @@ void InteriorCellRender::insertBegin (ESM::CellRef &ref) } // insert a mesh related to the most recent insertBegin call. +void InteriorCellRender::rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) +{ + assert(insert); + Ogre::SceneNode *parent = insert; + //std::cout << "ELEMENTS:" << elements; + for (int i = 0; i < elements; i++){ + if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) + parent = dynamic_cast (parent->getChild(sceneNodeName[i])); + } + parent->rotate(axis, angle); +} +// insert a mesh related to the most recent insertBegin call. + +void InteriorCellRender::scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) +{ + assert(insert); + Ogre::SceneNode *parent = insert; + //std::cout << "ELEMENTS:" << elements; + for (int i = 0; i < elements; i++){ + if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) + parent = dynamic_cast (parent->getChild(sceneNodeName[i])); + } + parent->scale(axis); +} +void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) +{ + insertMesh(mesh, vec, axis, angle, sceneNodeName, sceneParent, elements, true); +} +void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst){ + + assert (insert); + //insert-> + Ogre::SceneNode *parent = insert; + for (int i = 0; i < elements; i++){ + if(sceneParent[i] != "" && parent->getChild(sceneParent[i])) + parent = dynamic_cast (parent->getChild(sceneParent[i])); + } + + npcPart = parent->createChildSceneNode(sceneNodeName); + //npcPart->showBoundingBox(true); + + MeshPtr good2 = NIFLoader::load(mesh); + + MovableObject *ent = scene.getMgr()->createEntity(mesh); + //ent->extr + + // MovableObject *ent2 = scene.getMgr()->createEntity(bounds + // ); + //ent-> + //std::cout << mesh << bounds << "\n"; + + if(translateFirst){ + npcPart->translate(vec); + npcPart->rotate(axis, angle); + } + else{ + + npcPart->rotate(axis, angle); + npcPart->translate(vec); + } + + npcPart->attachObject(ent); + Ogre::MeshManager *m = MeshManager::getSingletonPtr(); + 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"; + const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; + + const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif"; + const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif"; + const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif"; + const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif"; + + const std::string beastfoot1 ="foot\\b\\B_N_Khajiit_F_Skins.nif"; + const std::string beastfoot2 ="foot\\b\\B_N_Khajiit_M_Skins.nif"; + const std::string beastfoot3 ="foot\\b\\B_N_Argonian_F_Skins.nif"; + const std::string beastfoot4 ="foot\\b\\B_N_Argonian_M_Skins.nif"; + if(mesh.compare(beast1) == 0 && m->getByName(beasttail1).isNull()) + { + //std::cout << "CLONINGKHAJIITF\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail1); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot1); + good2->reload(); + } + else if(mesh.compare(beast2) == 0 && m->getByName(beasttail2).isNull()) + { + //std::cout << "CLONINGKHAJIITM\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail2); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot2); + good2->reload(); + } + else if(mesh.compare(beast3) == 0 && m->getByName(beasttail3).isNull()) + { + //std::cout << "CLONINGARGONIANF\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail3); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot3); + good2->reload(); + } + else if(mesh.compare(beast4) == 0 && m->getByName(beasttail4).isNull()) + { + //std::cout << "CLONINGARGONIANM\n"; + good2->reload(); + MeshPtr tail = good2->clone(beasttail4); + good2->reload(); + MeshPtr foot = good2->clone(beastfoot4); + good2->reload(); + } +} void InteriorCellRender::insertMesh(const std::string &mesh) { diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index ba5089eb5..abb4a80c2 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -5,6 +5,7 @@ #include "cellimp.hpp" #include "OgreColourValue.h" +#include namespace Ogre { @@ -28,7 +29,7 @@ namespace MWRender class InteriorCellRender : public CellRender, private CellRenderImp { - + //static bool isChest; static bool lightConst; static float lightConstValue; @@ -53,6 +54,7 @@ namespace MWRender Ogre::SceneNode *base; Ogre::SceneNode *insert; + Ogre::SceneNode *npcPart; // 0 normal, 1 more bright, 2 max int ambientMode; @@ -61,10 +63,12 @@ namespace MWRender /// start inserting a new reference. virtual void insertBegin (ESM::CellRef &ref); - + 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); /// insert a mesh related to the most recent insertBegin call. virtual void insertMesh(const std::string &mesh); - + virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements); + 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); /// insert a light related to the most recent insertBegin call. virtual void insertLight(float r, float g, float b, float radius); @@ -79,6 +83,7 @@ namespace MWRender void setAmbientMode(); + public: InteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, @@ -88,6 +93,7 @@ namespace MWRender virtual ~InteriorCellRender() { destroy(); } /// Make the cell visible. Load the cell if necessary. + //virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements); virtual void show(); /// Remove the cell from rendering, but don't remove it from diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 88f62e112..8bdd8e2b9 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -62,6 +62,7 @@ namespace MWSound sounds based on the sound factory it is given. */ OEManagerPtr mgr; + SoundPtr music; /* This class calls update() on the sound manager each frame using and Ogre::FrameListener @@ -305,12 +306,13 @@ namespace MWSound SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &store, - const std::string &soundDir, + boost::filesystem::path dataDir, bool useSound) : mData(NULL) { + MP3Lookup(dataDir / "Music/Explore/"); if(useSound) - mData = new SoundImpl(root, camera, store, soundDir); + mData = new SoundImpl(root, camera, store, (dataDir / "Sound").file_string()); } SoundManager::~SoundManager() @@ -319,6 +321,62 @@ namespace MWSound delete mData; } + void SoundManager::MP3Lookup(boost::filesystem::path dir) +{ + boost::filesystem::directory_iterator dir_iter(dir), dir_end; + + std::string mp3extension = ".mp3"; + for(;dir_iter != dir_end; dir_iter++) + { + if(boost::filesystem::extension(*dir_iter) == mp3extension) + { + files.push_back(*dir_iter); + } + } +} + + void SoundManager::startRandomTitle() +{ + std::vector::iterator fileIter; + + if(files.size() > 0) + { + fileIter = files.begin(); + srand ( time(NULL) ); + int r = rand() % files.size() + 1; //old random code + + for(int i = 1; i < r; i++) + { + fileIter++; + } + std::string music = fileIter->file_string(); + try + { + std::cout << "Playing " << music << "\n"; + streamMusic(music); + } + catch(std::exception &e) + { + std::cout << " Music Error: " << e.what() << "\n"; + } + } +} + + + bool SoundManager::isMusicPlaying() + { + bool test = mData->music->isPlaying(); + return test; + } + + SoundManager::SoundImpl SoundManager::getMData() + { + // bool test = mData->music->isPlaying(); + return *mData; + } + + + void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) { // The range values are not tested @@ -342,16 +400,18 @@ namespace MWSound // Play the sound and tell it to stream, if possible. TODO: // Store the reference, the jukebox will need to check status, // control volume etc. - SoundPtr music = mData->mgr->load(filename); - music->setStreaming(true); - music->setVolume(0.4); - music->play(); + 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) { if(!mData) return; - // Play and forget float min, max; const std::string &file = mData->lookup(soundId, volume, min, max); diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 9f99b34b2..8717bf8dd 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -4,7 +4,9 @@ #include #include +#include #include "../mwworld/ptr.hpp" +#include namespace Ogre { @@ -19,18 +21,29 @@ namespace ESMS namespace MWSound { + //SoundPtr *music; class SoundManager { // Hide implementation details - engine.cpp is compiling // enough as it is. struct SoundImpl; + SoundImpl *mData; + std::vector files; + public: SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, - const std::string &soundDir, bool useSound); + boost::filesystem::path dataDir, bool useSound); ~SoundManager(); + void startRandomTitle(); + void MP3Lookup(boost::filesystem::path dir); + //struct SoundImpl; + bool isMusicPlaying(); + + SoundImpl getMData(); + void say (MWWorld::Ptr reference, const std::string& filename); ///< Make an actor say some text. /// \param filename name of a sound file in "Sound/Vo/" in the data directory. diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index ca29facfd..317dc2361 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -18,6 +18,10 @@ #include "environment.hpp" #include "class.hpp" + +#include "refdata.hpp" +#include "globals.hpp" + namespace { template @@ -62,6 +66,7 @@ namespace namespace MWWorld { + void World::insertInteriorScripts (ESMS::CellStore& cell) { listCellScripts (mStore, cell.activators, mLocalScripts, &cell); @@ -605,6 +610,7 @@ namespace MWWorld adjustSky(); mCellChanged = true; + //currentRegion->name = ""; } void World::changeCell (int X, int Y, const ESM::Position& position) @@ -681,7 +687,8 @@ namespace MWWorld mCellChanged = true; } - void World::changeToExteriorCell (const ESM::Position& position) + + void World::changeToExteriorCell (const ESM::Position& position) { int x = 0; int y = 0; @@ -714,7 +721,6 @@ namespace MWWorld return 0; } - void World::markCellAsUnchanged() { mCellChanged = false; @@ -794,6 +800,8 @@ namespace MWWorld } } + + void World::positionToIndex (float x, float y, int &cellX, int &cellY) const { const int cellSize = 8192; diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 832c90bf0..f774cd68e 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -39,8 +39,8 @@ namespace MWWorld class World { + public: - typedef std::list > ScriptList; private: @@ -50,7 +50,7 @@ namespace MWWorld MWRender::SkyManager* mSkyManager; MWRender::MWScene mScene; MWRender::PlayerPos *mPlayerPos; - Ptr::CellStore *mCurrentCell; // the cell, the player is in + Ptr::CellStore *mCurrentCell; // the cell, the player is in CellRenderCollection mActiveCells; CellRenderCollection mBufferedCells; // loaded, but not active (buffering not implementd yet) ESM::ESMReader mEsm; @@ -96,7 +96,7 @@ namespace MWWorld MWRender::PlayerPos& getPlayerPos(); - ESMS::ESMStore& getStore(); + ESMS::ESMStore& getStore(); const ScriptList& getLocalScripts() const; ///< Names and local variable state of all local scripts in active cells. diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 75debb8fc..ee8de7578 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -9,7 +9,12 @@ #include #include #include +#include + + +using namespace boost::algorithm; + namespace ESMS { using namespace ESM; @@ -233,6 +238,15 @@ namespace ESMS } }; + 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, is_iless()); + } +}; + + // Cells aren't simply indexed by name. Exterior cells are treated // separately. // TODO: case handling (cell names are case-insensitive, but they are also showen to the @@ -245,7 +259,7 @@ namespace ESMS int getSize() { return count; } // List of interior cells. Indexed by cell name. - typedef std::map IntCells; + typedef std::map IntCells; IntCells intCells; // List of exterior cells. Indexed as extCells[gridX][gridY]. @@ -268,6 +282,7 @@ namespace ESMS } } + const Cell* findInt(const std::string &id) const { IntCells::const_iterator it = intCells.find(id); @@ -300,7 +315,7 @@ namespace ESMS const ExtCellsCol& column = iter->second; for (ExtCellsCol::const_iterator iter = column.begin(); iter!=column.end(); ++iter) { - if (iter->second->name==id) + if ( toLower(iter->second->name) == toLower(id)) return iter->second; } } diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp index 74aa19e54..2af6fab37 100644 --- a/components/esm_store/store.hpp +++ b/components/esm_store/store.hpp @@ -115,13 +115,12 @@ namespace ESMS recLists[REC_GLOB] = &globals; recLists[REC_GMST] = &gameSettings; recLists[REC_INGR] = &ingreds; - recLists[REC_LAND] = &lands; + //recLists[REC_LAND] = &lands; recLists[REC_LEVC] = &creatureLists; recLists[REC_LEVI] = &itemLists; recLists[REC_LIGH] = &lights; recLists[REC_LOCK] = &lockpicks; recLists[REC_LTEX] = &landTexts; - //recLists[REC_MGEF] = &magicEffects; recLists[REC_MISC] = &miscItems; recLists[REC_NPC_] = &npcs; recLists[REC_NPCC] = &npcChange; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 4c0277f89..fc205d387 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -21,11 +21,14 @@ */ +//loadResource->handleNode->handleNiTriShape->createSubMesh + #include "ogre_nif_loader.hpp" #include #include #include +#include "../../apps/openmw/mwclass/npc.hpp" #include "../nif/nif_file.hpp" #include "../nif/node.hpp" #include "../nif/data.hpp" @@ -52,7 +55,6 @@ using namespace Mangle::VFS; NIFLoader& NIFLoader::getSingleton() { static NIFLoader instance; - return instance; } @@ -325,10 +327,13 @@ void NIFLoader::findRealTexture(String &texName) texName[len-1] = 's'; } +//Handle node at top + // Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given // mesh. void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std::list &vertexBoneAssignments) { + // cout << "s:" << shape << "\n"; NiTriShapeData *data = shape->data.getPtr(); SubMesh *sub = mesh->createSubMesh(shape->name.toString()); @@ -421,7 +426,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std for (std::list::iterator it = vertexBoneAssignments.begin(); it != vertexBoneAssignments.end(); it++) { - sub->addBoneAssignment(*it); + sub->addBoneAssignment(*it); } } @@ -468,8 +473,11 @@ static void vectorMul(const Matrix &A, float *C) C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2]; } + void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds) { + //if( MWClass::Npc.isChest) + //cout << "t:" << shape << "\n"; assert(shape != NULL); // Interpret flags @@ -719,6 +727,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou void NIFLoader::handleNode(Nif::Node *node, int flags, const Transformation *trafo, BoundsFinder &bounds, Bone *parentBone) { + stack++; + //if( MWClass::isChest) + // cout << "u:" << node << "\n"; // Accumulate the flags from all the child nodes. This works for all // the flags we currently use, at least. flags |= node->flags; @@ -768,6 +779,8 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, if (!skel.isNull()) //if there is a skeleton { std::string name = node->name.toString(); + //if (isBeast && isChest) + // std::cout << "NAME: " << name << "\n"; // Quick-n-dirty workaround for the fact that several // bones may have the same name. if(!skel->hasBone(name)) @@ -810,20 +823,199 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, { NodeList &list = ((NiNode*)node)->children; int n = list.length(); - for (int i=0; itrafo, bounds, bone); } } else if (node->recType == RC_NiTriShape) + { // For shapes - handleNiTriShape(dynamic_cast(node), flags, bounds); + /*For Beast Skins, Shape Bone Names + Tri Left Foot + Tri Right Foot + Tri Tail + 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"; + + if(isChest && isBeast && skincounter == 0 && name.compare("Tri Chest") == 0){ + //std::cout <<"BEASTCHEST1\n"; + handleNiTriShape(dynamic_cast(node), flags, bounds); + skincounter++; + } + else if(isChest && isBeast && skincounter == 1 && name.compare("Tri Tail") == 0){ + //std::cout <<"BEASTCHEST2\n"; + handleNiTriShape(dynamic_cast(node), flags, bounds); + skincounter++; + } + else if(isChest && isBeast && skincounter == 2 && name.compare("Tri Left Foot") == 0){ + //std::cout <<"BEASTCHEST3\n"; + handleNiTriShape(dynamic_cast(node), flags, bounds); + skincounter=1000; + } + else if (!isChest || !isBeast) + { + handleNiTriShape(dynamic_cast(node), flags, bounds); + } + //if(isBeast && isChest) + //cout << "Handling Shape, Stack " << stack <<"\n"; + + + + counter++; + } + /*if(isHands){ + //cout << "Handling Shape, Stack " << stack <<"\n"; + counter++; + }*/ + + } + + stack--; } void NIFLoader::loadResource(Resource *resource) { + if(skincounter == 1000) + skincounter = 0; + stack = 0; + counter = 0; + std::string name = resource->getName(); + if(resourceName.compare(name) != 0) + { + skincounter = 0; + resourceName = name; + } + //std::cout <<"NAME:" << name; + //if(name.length() >= 20) + // {std::string split = name.substr(name.length() - 20, 20); + //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"; + const std::string test3 ="meshes\\b\\B_N_Redguard_F_Skins.NIF"; + const std::string test4 ="meshes\\b\\B_N_Redguard_F_Skins.nif"; + const std::string test5 ="meshes\\b\\B_N_Dark Elf_F_Skins.nif"; + const std::string test6 ="meshes\\b\\B_N_Redguard_M_Skins.nif"; + const std::string test7 ="meshes\\b\\B_N_Wood Elf_F_Skins.nif"; + const std::string test8 ="meshes\\b\\B_N_Wood Elf_M_Skins.nif"; + const std::string test9 ="meshes\\b\\B_N_Imperial_F_Skins.nif"; + const std::string test10 ="meshes\\b\\B_N_Imperial_M_Skins.nif"; + const std::string test11 ="meshes\\b\\B_N_Khajiit_F_Skins.nif"; + const std::string test12 ="meshes\\b\\B_N_Khajiit_M_Skins.nif"; + const std::string test13 ="meshes\\b\\B_N_Argonian_F_Skins.nif"; + const std::string test14 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; + const std::string test15 ="meshes\\b\\B_N_Nord_F_Skins.nif"; + const std::string test16 ="meshes\\b\\B_N_Nord_M_Skins.nif"; + const std::string test17 ="meshes\\b\\B_N_Imperial_F_Skins.nif"; + const std::string test18 ="meshes\\b\\B_N_Imperial_M_Skins.nif"; + const std::string test19 ="meshes\\b\\B_N_Orc_F_Skins.nif"; + const std::string test20 ="meshes\\b\\B_N_Orc_M_Skins.nif"; + const std::string test21 ="meshes\\b\\B_N_Breton_F_Skins.nif"; + const std::string test22 ="meshes\\b\\B_N_Breton_M_Skins.nif"; + const std::string test23 ="meshes\\b\\B_N_High Elf_F_Skins.nif"; + 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; + if(name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 || name.compare(test14) == 0) + { + isBeast = true; + //std::cout << "Welcome Beast\n"; + } + else + isBeast = false; + } + else + isChest = false; + const std::string hands ="meshes\\b\\B_N_Dark Elf_M_Hands.1st.NIF"; + const std::string hands2 ="meshes\\b\\B_N_Dark Elf_F_Hands.1st.NIF"; + const std::string hands3 ="meshes\\b\\B_N_Redguard_M_Hands.1st.nif"; + const std::string hands4 ="meshes\\b\\B_N_Redguard_F_Hands.1st.nif"; + const std::string hands5 ="meshes\\b\\b_n_argonian_m_hands.1st.nif"; + const std::string hands6 ="meshes\\b\\b_n_argonian_f_hands.1st.nif"; + const std::string hands7 ="meshes\\b\\B_N_Breton_M_Hand.1st.NIF"; + const std::string hands8 ="meshes\\b\\B_N_Breton_F_Hands.1st.nif"; + const std::string hands9 ="meshes\\b\\B_N_High Elf_M_Hands.1st.nif"; + const std::string hands10 ="meshes\\b\\B_N_High Elf_F_Hands.1st.nif"; + const std::string hands11 ="meshes\\b\\B_N_Nord_M_Hands.1st.nif"; + const std::string hands12 ="meshes\\b\\B_N_Nord_F_Hands.1st.nif"; + const std::string hands13 ="meshes\\b\\b_n_khajiit_m_hands.1st.nif"; + const std::string hands14 ="meshes\\b\\b_n_khajiit_f_hands.1st.nif"; + const std::string hands15 ="meshes\\b\\B_N_Orc_M_Hands.1st.nif"; + const std::string hands16 ="meshes\\b\\B_N_Orc_F_Hands.1st.nif"; + const std::string hands17 ="meshes\\b\\B_N_Wood Elf_M_Hands.1st.nif"; + const std::string hands18 ="meshes\\b\\B_N_Wood Elf_F_Hands.1st.nif"; + const std::string hands19 ="meshes\\b\\B_N_Imperial_M_Hands.1st.nif"; + const std::string hands20 ="meshes\\b\\B_N_Imperial_F_Hands.1st.nif"; + if(name.compare(hands) == 0 || name.compare(hands2) == 0 || name.compare(hands3) == 0 || name.compare(hands4) == 0 || + name.compare(hands5) == 0 || name.compare(hands6) == 0 || name.compare(hands7) == 0 || name.compare(hands8) == 0 || + name.compare(hands9) == 0 || name.compare(hands10) == 0 || name.compare(hands11) == 0 || name.compare(hands12) == 0 || + name.compare(hands13) == 0 || name.compare(hands14) == 0 || name.compare(hands15) == 0 || name.compare(hands16) == 0 || + name.compare(hands17) == 0 || name.compare(hands18) == 0 || name.compare(hands19) == 0 || name.compare(hands20) == 0) + { + //std::cout << "Welcome Hands1st\n"; + isHands = true; + isChest = false; + } + else + isHands = false; + + + /* + else if(name.compare(test3) == 0 || name.compare(test4) == 0) + { + std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; + isChest = true; + } + else if(name.compare(test5) == 0 || name.compare(test6) == 0) + { + std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; + isChest = true; + } + else if(name.compare(test7) == 0 || name.compare(test8) == 0) + { + std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; + isChest = true; + } + else if(name.compare(test9) == 0 || name.compare(test10) == 0) + { + std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; + isChest = true; + }*/ + + //if(split== "Skins.NIF") + // std::cout << "\nSPECIAL PROPS\n"; resourceName = ""; + MeshManager *m = MeshManager::getSingletonPtr(); + // Check if the resource already exists + //MeshPtr ptr = m->load(name, "custom"); + //cout << "THISNAME: " << ptr->getName() << "\n"; + //cout << "RESOURCE:"<< resource->getName(); mesh = 0; skel.setNull(); @@ -836,6 +1028,7 @@ void NIFLoader::loadResource(Resource *resource) // Look it up resourceName = mesh->getName(); + //std::cout << resourceName << "\n"; if (!vfs->isFile(resourceName)) { @@ -887,19 +1080,58 @@ void NIFLoader::loadResource(Resource *resource) // mesh->setSkeletonName(getSkeletonName()); } -MeshPtr NIFLoader::load(const std::string &name, - const std::string &group) +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); - if (!ptr.isNull()) - return MeshPtr(ptr); + 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"; + const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; - // Nope, create a new one. - return MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr()); + const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif"; + const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif"; + 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(pieces > 1) + //cout << "It exists\n"; + resize = MeshPtr(ptr); + //resize->load(); + //resize->reload(); + } + else // Nope, create a new one. + { + 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()){ + if(pieces > 1) + cout << "It exists\n"; + resize = MeshPtr(ptr);*/ + //return resize; + } + 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 578308f0b..b2a6b50fd 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -67,19 +67,22 @@ namespace Mangle class NIFLoader : Ogre::ManualResourceLoader { public: + static int numberOfMeshes; static NIFLoader& getSingleton(); static NIFLoader* getSingletonPtr(); virtual void loadResource(Ogre::Resource *resource); - static Ogre::MeshPtr load(const std::string &name, - const std::string &group="General"); + 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); private: - NIFLoader() : resourceGroup("General") {} + NIFLoader() : resourceGroup("General") { skincounter = 0; resourceName = "";} NIFLoader(NIFLoader& n) {} void warn(std::string msg); @@ -120,6 +123,15 @@ class NIFLoader : Ogre::ManualResourceLoader std::string resourceName; std::string resourceGroup; + int skincounter; + bool isChest; + bool isBeast; + bool isHands; + bool isFeet; + int counter; + int numbers; + int stack; + // pointer to the ogre mesh which is currently build Ogre::Mesh *mesh; diff --git a/components/nifogre/oldnpccode.txt b/components/nifogre/oldnpccode.txt new file mode 100644 index 000000000..eec9ef11e --- /dev/null +++ b/components/nifogre/oldnpccode.txt @@ -0,0 +1,256 @@ +/* //This is old + if (pieces > 1){ //pieces > 1 + MeshPtr justChest = MeshManager::getSingleton().createManual("justchest", group, NIFLoader::getSingletonPtr()); + Ogre::AxisAlignedBox bounds = resize->getBounds(); + Ogre::Vector3 width2 = bounds.getCorner(bounds.NEAR_RIGHT_BOTTOM) - bounds.getCorner(bounds.NEAR_LEFT_BOTTOM); + Ogre::Vector3 depth2 = (bounds.getCorner(bounds.FAR_LEFT_BOTTOM) - bounds.getCorner(bounds.NEAR_LEFT_BOTTOM)); + Ogre::Vector3 height2 = bounds.getCorner(bounds.NEAR_LEFT_TOP) - bounds.getCorner(bounds.NEAR_LEFT_BOTTOM); + cout << "Width:" << width2; cout << "Height:" << height2; cout << "Depth:" << depth2; + /*int width = bounds.getMaximum().x - bounds.getMinimum().x; + int height = bounds.getMaximum().y - bounds.getMinimum().y; + int depth = bounds.getMaximum().z - bounds.getMinimum().z; + int xinc = width / pieces; + int yinc = height / pieces; + int zinc = depth / pieces; + int xmincorner = bounds.getMinimum().x + xinc*pieceIndex; + int ymincorner = bounds.getMinimum().y + yinc*pieceIndex; + int zmincorner = bounds.getMinimum().z + xinc*pieceIndex;*/ + //Ogre::Vector3 bottom_left = bounds.getCorner(bounds.NEAR_LEFT_BOTTOM) + (width2 / pieces) * pieceIndex; //width2 + //Ogre::Vector3 top_right = bottom_left + (width2 / pieces) + height2 + depth2; + //Ogre::AxisAlignedBox set = AxisAlignedBox ( Ogre::Vector3(xmincorner, bounds.getMinimum().y, bounds.getMinimum().z), Ogre::Vector3(xmincorner + xinc, bounds.getMaximum().y, bounds.getMaximum().z)); + //Ogre::AxisAlignedBox set = bounds;//AxisAlignedBox(bottom_left, top_right); + //bounds.setMinimumX(xmincorner); + //bounds.setMaximumX(xmincorner + xinc); + //bounds.setMinimumY(ymincorner); + //bounds.setMaximumY(ymincorner + yinc); + //bounds.setMinimumZ(zmincorner); + //bounds.setMaximumZ(zmincorner + zinc); + //bounds.setMinimumY(bounds.getMinimum().y); + //bounds.setMaximumY( bounds.getMaximum().y; + //resize->_setBounds(set, true); + //resize->reload(); + + //Ogre::Mesh::SubMeshIterator subMeshIterator = resize->getSubMeshIterator(); + /*Ogre::Vector3* point; + Ogre::SubMesh* subMesh; + + + + size_t vertex_count = 0; + Vector3* vertices; + size_t index_count = 0; + unsigned* indices; + Vector3 position = Vector3::ZERO; + Quaternion orient = Quaternion::IDENTITY; + Vector3 scale = Vector3::UNIT_SCALE; + + + // int vertex_count = 0; + //int index_count = 0; + + bool added_shared = false; + size_t current_offset = vertex_count; + size_t shared_offset = vertex_count; + size_t next_offset = vertex_count; + size_t index_offset = index_count; + size_t prev_vert = vertex_count; + size_t prev_ind = index_count; + // Calculate how many vertices and indices we're going to need + /* + std::cout <<"FIRST CYCLE\n"; + for(int i = 0;i < resize->getNumSubMeshes();i++) + { + std::cout<< "WEHAVEMESHES\n"; + SubMesh* submesh = resize->getSubMesh(i); + + // We only need to add the shared vertices once + if(submesh->useSharedVertices) + { + if(!added_shared) + { + VertexData* vertex_data = resize->sharedVertexData; + vertex_count += vertex_data->vertexCount; + added_shared = true; + } + } + else + { + VertexData* vertex_data = submesh->vertexData; + vertex_count += vertex_data->vertexCount; + } + + // Add the indices + Ogre::IndexData* index_data = submesh->indexData; + index_count += index_data->indexCount; + } + + */ +// Vector3* vertices; + // Allocate space for the vertices and indices + /*vertices = new Vector3[vertex_count]; + indices = new unsigned[index_count]; + + int meshcounter = 0; + added_shared = false; + std::cout <<"SECOND CYCLE: " << resize->getNumSubMeshes() << "\n"; + // Run through the submeshes again, adding the data into the arrays + int i; + for(i = 0;i < resize->getNumSubMeshes();i++) + { + + SubMesh* submesh = resize->getSubMesh(i); + + Ogre::VertexData* vertex_data = submesh->useSharedVertices ? resize->sharedVertexData : submesh->vertexData; + /* + if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared)) + { + if(submesh->useSharedVertices) + { + added_shared = true; + shared_offset = current_offset; + } + + const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); + unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + Ogre::Real* pReal; + + bool onepointexists = true; + Vector3 lastpoint; + for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) + { + posElem->baseVertexPointerToElement(vertex, &pReal); + + Vector3 pt; + pt.x = (*(pReal++)); + pt.y = (*(pReal++)); + pt.z = (*(pReal++)); + //cout << "X:" << pt.x << "Y:" <getMaterialName() << "\n"; + + if(meshcounter <= 2) + resize->destroySubMesh(i); + else if(meshcounter > 3 && meshcounter < 7) + resize->destroySubMesh(i); + //submesh->setMaterialName("BaseWhiteNoLighting"); //red + //submesh->updateMaterialUsingTextureAliases(); + //resize-> + meshcounter++; + //delete submesh; + //reakb; + }*/ + /* + vbuf->unlock(); + next_offset += vertex_data->vertexCount; + } + + Ogre::IndexData* index_data = submesh->indexData; + + size_t numTris = index_data->indexCount / 3; + unsigned short* pShort; + unsigned int* pInt; + Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; + bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); + if (use32bitindexes) pInt = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + else pShort = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); + + for(size_t k = 0; k < numTris; ++k) + { + size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset; + + unsigned int vindex = use32bitindexes? *pInt++ : *pShort++; + indices[index_offset + 0] = vindex + offset; + vindex = use32bitindexes? *pInt++ : *pShort++; + indices[index_offset + 1] = vindex + offset; + vindex = use32bitindexes? *pInt++ : *pShort++; + indices[index_offset + 2] = vindex + offset; + + index_offset += 3; + } + ibuf->unlock(); + current_offset = next_offset;*/ + //if (i == 3) //i!=3 i!=5 + //{ + //cout << "RETURNINGJUST\n"; + //SubMesh* test = + //test = resize->getSubMesh(i); + // cout << "s:" << shape << "\n"; + //NiTriShapeData *data = shape->data.getPtr(); + // SubMesh *sub = justChest->createSubMesh(name + "2"); + //sub = resize->getSubMesh(i); + + // int nextBuf = 0; + + // This function is just one long stream of Ogre-barf, but it works + // great. + + // Add vertices + //int numVerts = data->vertices.length / 3; + //sub->vertexData = new VertexData(); + //sub->vertexData->vertexCount = numVerts; + + //justChest->load(); + //return resize; + //} + // 0 hand thumb + // 1 hand thumb no chest on dunmer + //} + //resize->destroySubMesh(1); + /* while (subMeshIterator.hasMoreElements()) + { + resize->getNum + //resize->d + std::cout << "CHEST"; + subMesh = subMeshIterator.getNext();*/ + //std::vector::type test = + //std::vector::iterator fileIter = subMesh->extremityPoints.begin(); + + //std::vector::type test = subMesh->extremityPoints; + //void* pData = subMesh->vertexData->vertexBufferBinding->getBuffer(1)->lock(0, 1000, HardwareBuffer::HBL_DISCARD); + + + // if(set.contains( subMesh->vertexData->vertexStart)) + //delete subMesh; + //subMeshIterator.getNext(); + //delete[] subMesh; + //subMesh->extremityPoints.clear(); + //subMesh->mLodFaceList.clear(); + //resize->destroySubMesh(subMesh->indexData->indexStart); + //resize->destroySubMesh(subMesh->indexData->); + //subMesh-> + //std::cout << "THIS" << subMesh; + ///} + //subMesh->vertexData->vertexBufferBinding->getBuffer(0)->readData(subMesh->vertexData->vertexStart, sizeof Ogre::Vector3, point); + + + + //boost::filesystem::directory_iterator dir_iter(dir), dir_end; + + //return resize;