From 386ac56bdab827ef604362787d232d8278ff1d7e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Jul 2012 20:12:18 -0700 Subject: [PATCH] Remove the NIF loader and code to manually transform the vertices This currently breaks just about everything. They should come back as it's all reimplemented, though. --- apps/openmw/engine.cpp | 7 +- apps/openmw/mwrender/animation.cpp | 594 +++------ apps/openmw/mwrender/animation.hpp | 53 +- apps/openmw/mwrender/creatureanimation.cpp | 56 +- apps/openmw/mwrender/npcanimation.cpp | 1266 ++++++++------------ apps/openmw/mwrender/npcanimation.hpp | 94 +- components/bsa/bsa_archive.cpp | 58 +- components/nif/data.hpp | 20 - components/nif/node.hpp | 36 - components/nifbullet/bullet_nif_loader.cpp | 2 +- components/nifogre/ogre_nif_loader.cpp | 1112 +---------------- components/nifogre/ogre_nif_loader.hpp | 98 +- libs/openengine/bullet/physic.cpp | 2 +- 13 files changed, 828 insertions(+), 2570 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 45b4ab514..fded32560 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -75,11 +75,8 @@ void OMW::Engine::executeLocalScripts() localScripts.setIgnore (MWWorld::Ptr()); } -void OMW::Engine::setAnimationVerbose(bool animverbose){ - if(animverbose){ - NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true); - NifOgre::NIFLoader::getSingletonPtr()->setVerbosePath(mCfgMgr.getLogPath().string()); - } +void OMW::Engine::setAnimationVerbose(bool animverbose) +{ } bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index f0a6ab683..7e50706f9 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -6,498 +6,236 @@ #include #include -namespace MWRender{ - std::map Animation::mUniqueIDs; - - Animation::Animation(OEngine::Render::OgreRenderer& _rend) - : insert(NULL) - , mRend(_rend) - , vecRotPos() - , time(0.0f) - , startTime(0.0f) - , stopTime(0.0f) - , animate(0) - , rindexI() - , tindexI() - , shapeNumber(0) - , shapeIndexI() - , shapes(NULL) - , transformations(NULL) - , textmappings(NULL) - , base(NULL) - { - } - - Animation::~Animation() - { - } - - std::string Animation::getUniqueID(std::string mesh){ - int counter; - std::string copy = mesh; - std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower); - if(mUniqueIDs.find(copy) == mUniqueIDs.end()){ - counter = mUniqueIDs[copy] = 0; - } - else{ - mUniqueIDs[copy] = mUniqueIDs[copy] + 1; - counter = mUniqueIDs[copy]; - } - - std::stringstream out; - if(counter > 99 && counter < 1000) - out << "0"; - else if(counter > 9) - out << "00"; - else - out << "000"; - out << counter; - return out.str(); +namespace MWRender { + +std::map Animation::mUniqueIDs; + +Animation::Animation(OEngine::Render::OgreRenderer& _rend) + : insert(NULL) + , mRend(_rend) + , time(0.0f) + , startTime(0.0f) + , stopTime(0.0f) + , animate(0) + , rindexI() + , tindexI() + , shapeNumber(0) + , shapeIndexI() + , transformations(NULL) + , textmappings(NULL) + , base(NULL) +{ } - void Animation::startScript(std::string groupname, int mode, int loops){ - //If groupname is recognized set animate to true - //Set the start time and stop time - //How many times to loop - if(groupname == "all"){ - animate = loops; - time = startTime; - } - else if(textmappings){ - std::string startName = groupname + ": loop start"; - std::string stopName = groupname + ": loop stop"; +Animation::~Animation() +{ +} - bool first = false; +void Animation::startScript(std::string groupname, int mode, int loops) +{ + //If groupname is recognized set animate to true + //Set the start time and stop time + //How many times to loop + if(groupname == "all") + { + animate = loops; + time = startTime; + } + else if(textmappings) + { + std::string startName = groupname + ": loop start"; + std::string stopName = groupname + ": loop stop"; - if(loops > 1){ - startName = groupname + ": loop start"; - stopName = groupname + ": loop stop"; + bool first = false; - for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ + if(loops > 1) + { + startName = groupname + ": loop start"; + stopName = groupname + ": loop stop"; + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++) + { std::string current = iter->first.substr(0, startName.size()); std::transform(current.begin(), current.end(), current.begin(), ::tolower); std::string current2 = iter->first.substr(0, stopName.size()); std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); - if(current == startName){ + if(current == startName) + { startTime = iter->second; - animate = loops; - time = startTime; - first = true; + animate = loops; + time = startTime; + first = true; } - if(current2 == stopName){ + if(current2 == stopName) + { stopTime = iter->second; if(first) break; } - } } - if(!first){ - startName = groupname + ": start"; - stopName = groupname + ": stop"; + } - for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ + if(!first) + { + startName = groupname + ": start"; + stopName = groupname + ": stop"; + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++) + { std::string current = iter->first.substr(0, startName.size()); std::transform(current.begin(), current.end(), current.begin(), ::tolower); std::string current2 = iter->first.substr(0, stopName.size()); std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); - if(current == startName){ + if(current == startName) + { startTime = iter->second; - animate = loops; - time = startTime; - first = true; + animate = loops; + time = startTime; + first = true; } - if(current2 == stopName){ + if(current2 == stopName) + { stopTime = iter->second; if(first) break; } } - } - } - } - void Animation::stopScript(){ - animate = 0; } - void Animation::handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ - shapeNumber = 0; - - if (allshapes == NULL || creaturemodel == NULL || skel == NULL) - { - return; - } - - std::vector::iterator allshapesiter; - for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++) - - { - //std::map vecPosRot; - - Nif::NiTriShapeCopy& copy = *allshapesiter; - std::vector* allvertices = ©.vertices; - - - - //std::set vertices; - //std::set normals; - //std::vector boneinfovector = copy.boneinfo; - std::map >* verticesToChange = ©.vertsToWeights; - - //std::cout << "Name " << copy.sname << "\n"; - Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); - Ogre::Real* pReal = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); - - - std::vector initialVertices = copy.morph.getInitialVertices(); - //Each shape has multiple indices - if(initialVertices.size() ) - { - - if(copy.vertices.size() == initialVertices.size()) - { - //Create if it doesn't already exist - if(shapeIndexI.size() == static_cast (shapeNumber)) - { - std::vector vec; - shapeIndexI.push_back(vec); - } - if(time >= copy.morph.getStartTime() && time <= copy.morph.getStopTime()){ - float x; - for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++){ - int j = 0; - if(shapeIndexI[shapeNumber].size() <= i) - shapeIndexI[shapeNumber].push_back(0); - - - if(timeIndex(time,copy.morph.getRelevantTimes()[i],(shapeIndexI[shapeNumber])[i], j, x)){ - int indexI = (shapeIndexI[shapeNumber])[i]; - std::vector relevantData = (copy.morph.getRelevantData()[i]); - float v1 = relevantData[indexI].x; - float v2 = relevantData[j].x; - float t = v1 + (v2 - v1) * x; - if ( t < 0 ) t = 0; - if ( t > 1 ) t = 1; - if( t != 0 && initialVertices.size() == copy.morph.getAdditionalVertices()[i].size()) - { - for (unsigned int v = 0; v < initialVertices.size(); v++){ - initialVertices[v] += ((copy.morph.getAdditionalVertices()[i])[v]) * t; - } - } - - } - - - - } - - allvertices = &initialVertices; - } - shapeNumber++; - } - } - - - if(verticesToChange->size() > 0){ - - for(std::map >::iterator iter = verticesToChange->begin(); - iter != verticesToChange->end(); iter++) - { - std::vector inds = iter->second; - int verIndex = iter->first; - Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; - Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); - Ogre::Bone *bonePtr = 0; - - - - Ogre::Vector3 vecPos; - Ogre::Quaternion vecRot; - std::map::iterator result = vecRotPos.find(boneinfocopy); - - if(result == vecRotPos.end()){ - bonePtr = skel->getBone(boneinfocopy->bonename); - - vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; - vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - - - PosAndRot both; - both.vecPos = vecPos; - both.vecRot = vecRot; - vecRotPos[boneinfocopy] = both; - - } - else{ - PosAndRot both = result->second; - vecPos = both.vecPos; - vecRot = both.vecRot; - } - - Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; - - - - for(std::size_t i = 1; i < inds.size(); i++){ - boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); - result = vecRotPos.find(boneinfocopy); - - - if(result == vecRotPos.end()){ - bonePtr = skel->getBone(boneinfocopy->bonename); - vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; - vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - - PosAndRot both; - both.vecPos = vecPos; - both.vecRot = vecRot; - vecRotPos[boneinfocopy] = both; - - } - else{ - PosAndRot both = result->second; - vecPos = both.vecPos; - vecRot = both.vecRot; - } - - - absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; - - - } - Ogre::Real* addr = (pReal + 3 * verIndex); - *addr = absVertPos.x; - *(addr+1) = absVertPos.y; - *(addr+2) = absVertPos.z; - - } - - - - - } - else - { - //Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename); - Ogre::Quaternion shaperot = copy.trafo.rotation; - Ogre::Vector3 shapetrans = copy.trafo.trans; - float shapescale = copy.trafo.scale; - std::vector boneSequence = copy.boneSequence; - - Ogre::Vector3 transmult; - Ogre::Quaternion rotmult; - float scale; - if(boneSequence.size() > 0){ - std::vector::iterator boneSequenceIter = boneSequence.begin(); - if(skel->hasBone(*boneSequenceIter)){ - Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); - - - - - transmult = bonePtr->getPosition(); - rotmult = bonePtr->getOrientation(); - scale = bonePtr->getScale().x; - boneSequenceIter++; - - for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++) - { - if(skel->hasBone(*boneSequenceIter)){ - Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); - // Computes C = B + AxC*scale - transmult = transmult + rotmult * bonePtr->getPosition(); - rotmult = rotmult * bonePtr->getOrientation(); - scale = scale * bonePtr->getScale().x; - } - //std::cout << "Bone:" << *boneSequenceIter << " "; - } - transmult = transmult + rotmult * shapetrans; - rotmult = rotmult * shaperot; - scale = shapescale * scale; - - //std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n"; - } - } - else - { - transmult = shapetrans; - rotmult = shaperot; - scale = shapescale; - } - - +} - // Computes C = B + AxC*scale - // final_vector = old_vector + old_rotation*new_vector*old_scale/ +void Animation::stopScript() +{ + animate = 0; +} - for(unsigned int i = 0; i < allvertices->size(); i++){ - Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i]; - Ogre::Real* addr = pReal + i * 3; - *addr = current.x; - *(addr+1) = current.y; - *(addr + 2) = current.z; - }/* - for(int i = 0; i < allnormals.size(); i++){ - Ogre::Vector3 current =rotmult * allnormals[i]; - Ogre::Real* addr = pRealNormal + i * 3; - *addr = current.x; - *(addr+1) = current.y; - *(addr + 2) = current.z; +bool Animation::timeIndex(float time, const std::vector ×, int &i, int &j, float &x) +{ + size_t count; + if((count=times.size()) == 0) + return false; - }*/ + if(time <= times[0]) + { + i = j = 0; + x = 0.0; + return true; + } + if(time >= times[count-1]) + { + i = j = count - 1; + x = 0.0; + return true; + } - } - vbuf->unlock(); + if(i < 0 || (size_t)i >= count) + i = 0; - } + float tI = times[i]; + if(time > tI) + { + j = i + 1; + float tJ; + while(time >= (tJ=times[j])) + { + i = j++; + tI = tJ; + } + x = (time-tI) / (tJ-tI); + return true; + } + if(time < tI) + { + j = i - 1; + float tJ; + while(time <= (tJ=times[j])) + { + i = j--; + tI = tJ; + } + x = (time-tI) / (tJ-tI); + return true; } - bool Animation::timeIndex( float time, const std::vector & times, int & i, int & j, float & x ){ - int count; - if ( (count = times.size()) > 0 ) - { - if ( time <= times[0] ) - { - i = j = 0; - x = 0.0; - return true; - } - if ( time >= times[count - 1] ) - { - i = j = count - 1; - x = 0.0; - return true; - } - - if ( i < 0 || i >= count ) - i = 0; - - float tI = times[i]; - if ( time > tI ) - { - j = i + 1; - float tJ; - while ( time >= ( tJ = times[j]) ) - { - i = j++; - tI = tJ; - } - x = ( time - tI ) / ( tJ - tI ); - return true; - } - else if ( time < tI ) - { - j = i - 1; - float tJ; - while ( time <= ( tJ = times[j] ) ) - { - i = j--; - tI = tJ; - } - x = ( time - tI ) / ( tJ - tI ); - return true; - } - else - { - j = i; - x = 0.0; - return true; - } - } - else - return false; + j = i; + x = 0.0; + return true; } - void Animation::handleAnimationTransforms(){ - - +void Animation::handleAnimationTransforms() +{ Ogre::SkeletonInstance* skel = base->getSkeleton(); - Ogre::Bone* b = skel->getRootBone(); - b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick - - skel->_updateTransforms(); - //skel->_notifyManualBonesDirty(); - - base->getAllAnimationStates()->_notifyDirty(); - //base->_updateAnimation(); - //base->_notifyMoved(); - + b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick + skel->_updateTransforms(); + //skel->_notifyManualBonesDirty(); + base->getAllAnimationStates()->_notifyDirty(); + //base->_updateAnimation(); + //base->_notifyMoved(); std::vector::iterator iter; int slot = 0; - if(transformations){ - for(iter = transformations->begin(); iter != transformations->end(); iter++){ - if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) - { - slot++; - continue; - } - - float x; - float x2; - - const std::vector & quats = iter->getQuat(); - - const std::vector & ttime = iter->gettTime(); - - - const std::vector & rtime = iter->getrTime(); - int rindexJ = rindexI[slot]; - - timeIndex(time, rtime, rindexI[slot], rindexJ, x2); - int tindexJ = tindexI[slot]; - - - const std::vector & translist1 = iter->getTranslist1(); - - timeIndex(time, ttime, tindexI[slot], tindexJ, x); - - Ogre::Vector3 t; - Ogre::Quaternion r; - - bool bTrans = translist1.size() > 0; - - - bool bQuats = quats.size() > 0; - - if(skel->hasBone(iter->getBonename())){ - Ogre::Bone* bone = skel->getBone(iter->getBonename()); - if(bTrans){ - Ogre::Vector3 v1 = translist1[tindexI[slot]]; - Ogre::Vector3 v2 = translist1[tindexJ]; - t = (v1 + (v2 - v1) * x); - bone->setPosition(t); - - } - if(bQuats){ - r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); - bone->setOrientation(r); - } + if(transformations) + { + for(iter = transformations->begin(); iter != transformations->end(); iter++) + { + if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) + { + slot++; + continue; + } + float x; + float x2; + const std::vector &quats = iter->getQuat(); + const std::vector &ttime = iter->gettTime(); + const std::vector &rtime = iter->getrTime(); + const std::vector &translist1 = iter->getTranslist1(); + int rindexJ = rindexI[slot]; + timeIndex(time, rtime, rindexI[slot], rindexJ, x2); + int tindexJ = tindexI[slot]; + timeIndex(time, ttime, tindexI[slot], tindexJ, x); - } + Ogre::Vector3 t; + Ogre::Quaternion r; + bool bTrans = translist1.size() > 0; + bool bQuats = quats.size() > 0; + if(skel->hasBone(iter->getBonename())) + { + Ogre::Bone* bone = skel->getBone(iter->getBonename()); + if(bTrans) + { + Ogre::Vector3 v1 = translist1[tindexI[slot]]; + Ogre::Vector3 v2 = translist1[tindexJ]; + t = (v1 + (v2 - v1) * x); + bone->setPosition(t); + } + if(bQuats) + { + r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); + bone->setOrientation(r); + } + } - slot++; - } - skel->_updateTransforms(); + slot++; + } + skel->_updateTransforms(); base->getAllAnimationStates()->_notifyDirty(); -} + } } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 4ab60cff4..9d5404305 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -12,60 +12,47 @@ -namespace MWRender{ +namespace MWRender { -struct PosAndRot{ +struct PosAndRot { Ogre::Quaternion vecRot; Ogre::Vector3 vecPos; }; -class Animation{ - - protected: +class Animation { +protected: Ogre::SceneNode* insert; OEngine::Render::OgreRenderer &mRend; - std::map vecRotPos; static std::map mUniqueIDs; - - - - float time; - float startTime; - float stopTime; - int animate; - //Represents a rotation index for each bone - std::vectorrindexI; + float startTime; + float stopTime; + int animate; + //Represents a rotation index for each bone + std::vectorrindexI; //Represents a translation index for each bone - std::vectortindexI; - - //Only shapes with morphing data will use a shape number - int shapeNumber; - std::vector > shapeIndexI; - - //Ogre::SkeletonInstance* skel; - std::vector* shapes; //All the NiTriShapeData for a creature - + std::vectortindexI; + //Only shapes with morphing data will use a shape number + int shapeNumber; + std::vector > shapeIndexI; std::vector* transformations; std::map* textmappings; Ogre::Entity* base; - void handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel); void handleAnimationTransforms(); bool timeIndex( float time, const std::vector & times, int & i, int & j, float & x ); - std::string getUniqueID(std::string mesh); - public: - Animation(OEngine::Render::OgreRenderer& _rend); - virtual void runAnimation(float timepassed) = 0; - void startScript(std::string groupname, int mode, int loops); - void stopScript(); +public: + Animation(OEngine::Render::OgreRenderer& _rend); + virtual void runAnimation(float timepassed) = 0; + void startScript(std::string groupname, int mode, int loops); + void stopScript(); - virtual ~Animation(); - + virtual ~Animation(); }; + } #endif diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index e1fa7868c..6bdd58ac3 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -12,20 +12,22 @@ using namespace Ogre; using namespace NifOgre; namespace MWRender{ -CreatureAnimation::~CreatureAnimation(){ - +CreatureAnimation::~CreatureAnimation() +{ } -CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend): Animation(_rend){ + +CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend): Animation(_rend) +{ insert = ptr.getRefData().getBaseNode(); - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); - if(!ref->base->model.empty()){ - const std::string &mesh = "meshes\\" + ref->base->model; - std::string meshNumbered = mesh + getUniqueID(mesh) + ">|"; - NifOgre::NIFLoader::load(meshNumbered); - base = mRend.getScene()->createEntity(meshNumbered); + if(!ref->base->model.empty()) + { + std::string mesh = "meshes\\" + ref->base->model; + + NifOgre::NIFLoader::load(mesh); + base = mRend.getScene()->createEntity(mesh); base->setVisibilityFlags(RV_Actors); bool transparent = false; @@ -48,33 +50,22 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - std::string meshZero = mesh + "0000>|"; - - if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){ - - for(std::size_t init = 0; init < transformations->size(); init++){ - rindexI.push_back(0); - tindexI.push_back(0); - } - stopTime = transformations->begin()->getStopTime(); - startTime = transformations->begin()->getStartTime(); - shapes = (NIFLoader::getSingletonPtr())->getShapes(meshZero); - } - textmappings = NIFLoader::getSingletonPtr()->getTextIndices(meshZero); insert->attachObject(base); } } -void CreatureAnimation::runAnimation(float timepassed){ - vecRotPos.clear(); - if(animate > 0){ - //Add the amount of time passed to time +void CreatureAnimation::runAnimation(float timepassed) +{ + if(animate > 0) + { + //Add the amount of time passed to time - //Handle the animation transforms dependent on time + //Handle the animation transforms dependent on time - //Handle the shapes dependent on animation transforms + //Handle the shapes dependent on animation transforms time += timepassed; - if(time >= stopTime){ + if(time >= stopTime) + { animate--; //std::cout << "Stopping the animation\n"; if(animate == 0) @@ -84,8 +75,7 @@ void CreatureAnimation::runAnimation(float timepassed){ } handleAnimationTransforms(); - handleShapes(shapes, base, base->getSkeleton()); - - } + } } + } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index fa88b7277..fa33d18ff 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -13,13 +13,16 @@ using namespace Ogre; using namespace NifOgre; + namespace MWRender{ -NpcAnimation::~NpcAnimation(){ +NpcAnimation::~NpcAnimation() +{ } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv): Animation(_rend), mStateID(-1), inv(_inv), timeToChange(0), +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv) + : Animation(_rend), mStateID(-1), inv(_inv), timeToChange(0), robe(inv.end()), helmet(inv.end()), shirt(inv.end()), cuirass(inv.end()), greaves(inv.end()), leftpauldron(inv.end()), rightpauldron(inv.end()), @@ -27,98 +30,59 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere leftglove(inv.end()), rightglove(inv.end()), skirtiter(inv.end()), pants(inv.end()), lclavicle(0), - rclavicle(0), - rupperArm(0), - lupperArm(0), - rUpperLeg(0), - lUpperLeg(0), - lForearm(0), - rForearm(0), - lWrist(0), - rWrist(0), - rKnee(0), - lKnee(0), - neck(0), - rAnkle(0), - lAnkle(0), - groin(0), - lfoot(0), - rfoot(0) - { - MWWorld::LiveCellRef *ref = - ptr.get(); - Ogre::Entity* blank = 0; - std::vector* blankshape = 0; - zero = std::make_pair(blank, blankshape); - chest = std::make_pair(blank, blankshape); - tail = std::make_pair(blank, blankshape); - lFreeFoot = std::make_pair(blank, blankshape); - rFreeFoot = std::make_pair(blank, blankshape); - rhand = std::make_pair(blank, blankshape); - lhand = std::make_pair(blank, blankshape); - skirt = std::make_pair(blank, blankshape); - for (int init = 0; init < 27; init++){ - partslots[init] = -1; //each slot is empty - partpriorities[init] = 0; - } - - - //Part selection on last character of the file string - // " Tri Chest - // * Tri Tail - // : Tri Left Foot - // < Tri Right Foot - // > Tri Left Hand - // ? Tri Right Hand - // | Normal - - //Mirroring Parts on second to last character - //suffix == '*' - // vector = Ogre::Vector3(-1,1,1); - // suffix == '?' - // vector = Ogre::Vector3(1,-1,1); - // suffix == '<' - // vector = Ogre::Vector3(1,1,-1); - - - std::string hairID = ref->base->hair; - std::string headID = ref->base->head; - headModel = "meshes\\" + - MWBase::Environment::get().getWorld()->getStore().bodyParts.find(headID)->model; - - hairModel = "meshes\\" + - MWBase::Environment::get().getWorld()->getStore().bodyParts.find(hairID)->model; - npcName = ref->base->name; - - //ESMStore::Races r = - const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().races.find(ref->base->race); - - - bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); - isFemale = tolower(secondtolast) == 'f'; - std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); - isBeast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; - - /*std::cout << "Race: " << ref->base->race ; - if(female){ - std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; - } - else{ - std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; - }*/ + rclavicle(0), + rupperArm(0), + lupperArm(0), + rUpperLeg(0), + lUpperLeg(0), + lForearm(0), + rForearm(0), + lWrist(0), + rWrist(0), + rKnee(0), + lKnee(0), + neck(0), + rAnkle(0), + lAnkle(0), + groin(0), + lfoot(0), + rfoot(0) +{ + MWWorld::LiveCellRef *ref = ptr.get(); + + for (int init = 0; init < 27; init++) + { + partslots[init] = -1; //each slot is empty + partpriorities[init] = 0; + } + + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Race *race = store.races.find(ref->base->race); + std::string hairID = ref->base->hair; + std::string headID = ref->base->head; + headModel = "meshes\\" + store.bodyParts.find(headID)->model; + hairModel = "meshes\\" + store.bodyParts.find(hairID)->model; + npcName = ref->base->name; + isFemale = !!(ref->base->flags&ESM::NPC::Female); + isBeast = !!(race->data.flags&ESM::Race::Beast); - std::string smodel = "meshes\\base_anim.nif"; - if(isBeast) - smodel = "meshes\\base_animkna.nif"; + bodyRaceID = "b_n_"+race->name; + std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); - insert = ptr.getRefData().getBaseNode(); - assert(insert); + /*std::cout << "Race: " << ref->base->race ; + if(female) + std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; + else + std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; + */ - NifOgre::NIFLoader::load(smodel); + insert = ptr.getRefData().getBaseNode(); + assert(insert); + std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); + NifOgre::NIFLoader::load(smodel); base = mRend.getScene()->createEntity(smodel); base->setVisibilityFlags(RV_Actors); @@ -134,372 +98,290 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere while (passIt.hasMoreElements()) { Ogre::Pass* pass = passIt.getNext(); - if (pass->getDepthWriteEnabled() == false) transparent = true; } } } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); - - base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones //stay in the same place when we skipanim, or open a gui window - - - if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){ - - for(unsigned int init = 0; init < transformations->size(); init++){ - rindexI.push_back(0); - tindexI.push_back(0); - } - - stopTime = transformations->begin()->getStopTime(); - startTime = transformations->begin()->getStartTime(); - } - textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel); insert->attachObject(base); + if(isFemale) + insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); + else + insert->scale(race->data.height.male, race->data.height.male, race->data.height.male); - - if(isFemale) - insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); - else - insert->scale(race->data.height.male, race->data.height.male, race->data.height.male); - updateParts(); - + updateParts(); } -void NpcAnimation::updateParts(){ - - bool apparelChanged = false; - - - //inv.getSlot(MWWorld::InventoryStore::Slot_Robe); - if(robe != inv.getSlot(MWWorld::InventoryStore::Slot_Robe)){ - //A robe was added or removed - removePartGroup(MWWorld::InventoryStore::Slot_Robe); - robe = inv.getSlot(MWWorld::InventoryStore::Slot_Robe); - apparelChanged = true; - } - if(skirtiter != inv.getSlot(MWWorld::InventoryStore::Slot_Skirt)){ - //A robe was added or removed - removePartGroup(MWWorld::InventoryStore::Slot_Skirt); - skirtiter = inv.getSlot(MWWorld::InventoryStore::Slot_Skirt); - apparelChanged = true; - } - if(helmet != inv.getSlot(MWWorld::InventoryStore::Slot_Helmet)){ - apparelChanged = true; - helmet = inv.getSlot(MWWorld::InventoryStore::Slot_Helmet); - removePartGroup(MWWorld::InventoryStore::Slot_Helmet); - - } - if(cuirass != inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)){ - cuirass = inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass); - removePartGroup(MWWorld::InventoryStore::Slot_Cuirass); - apparelChanged = true; +void NpcAnimation::updateParts() +{ + bool apparelChanged = false; - } - if(greaves != inv.getSlot(MWWorld::InventoryStore::Slot_Greaves)){ - greaves = inv.getSlot(MWWorld::InventoryStore::Slot_Greaves); - removePartGroup(MWWorld::InventoryStore::Slot_Greaves); - apparelChanged = true; - } - if(leftpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)){ - leftpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron); - removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron); - apparelChanged = true; + //inv.getSlot(MWWorld::InventoryStore::Slot_Robe); + if(robe != inv.getSlot(MWWorld::InventoryStore::Slot_Robe)) + { + // A robe was added or removed + robe = inv.getSlot(MWWorld::InventoryStore::Slot_Robe); + removePartGroup(MWWorld::InventoryStore::Slot_Robe); + apparelChanged = true; + } + if(skirtiter != inv.getSlot(MWWorld::InventoryStore::Slot_Skirt)) + { + skirtiter = inv.getSlot(MWWorld::InventoryStore::Slot_Skirt); + removePartGroup(MWWorld::InventoryStore::Slot_Skirt); + apparelChanged = true; + } + if(helmet != inv.getSlot(MWWorld::InventoryStore::Slot_Helmet)) + { + helmet = inv.getSlot(MWWorld::InventoryStore::Slot_Helmet); + removePartGroup(MWWorld::InventoryStore::Slot_Helmet); + apparelChanged = true; + } + if(cuirass != inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)) + { + cuirass = inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass); + removePartGroup(MWWorld::InventoryStore::Slot_Cuirass); + apparelChanged = true; + } + if(greaves != inv.getSlot(MWWorld::InventoryStore::Slot_Greaves)) + { + greaves = inv.getSlot(MWWorld::InventoryStore::Slot_Greaves); + removePartGroup(MWWorld::InventoryStore::Slot_Greaves); + apparelChanged = true; + } + if(leftpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)) + { + leftpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron); + removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron); + apparelChanged = true; + } + if(rightpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)) + { + rightpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron); + removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron); + apparelChanged = true; + } + if(!isBeast && boots != inv.getSlot(MWWorld::InventoryStore::Slot_Boots)) + { + boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); + removePartGroup(MWWorld::InventoryStore::Slot_Boots); + apparelChanged = true; + } + if(leftglove != inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)) + { + leftglove = inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet); + removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet); + apparelChanged = true; + } + if(rightglove != inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)) + { + rightglove = inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet); + removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet); + apparelChanged = true; + } + if(shirt != inv.getSlot(MWWorld::InventoryStore::Slot_Shirt)) + { + shirt = inv.getSlot(MWWorld::InventoryStore::Slot_Shirt); + removePartGroup(MWWorld::InventoryStore::Slot_Shirt); + apparelChanged = true; + } + if(pants != inv.getSlot(MWWorld::InventoryStore::Slot_Pants)) + { + pants = inv.getSlot(MWWorld::InventoryStore::Slot_Pants); + removePartGroup(MWWorld::InventoryStore::Slot_Pants); + apparelChanged = true; + } - } - if(rightpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)){ - rightpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron); - removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron); - apparelChanged = true; + if(apparelChanged) + { + if(robe != inv.end()) + { + MWWorld::Ptr ptr = *robe; + + const ESM::Clothing *clothes = (ptr.get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts); + reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_Skirt, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RKnee, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LKnee, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RForearm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LForearm, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + } + if(skirtiter != inv.end()) + { + MWWorld::Ptr ptr = *skirtiter; + const ESM::Clothing *clothes = (ptr.get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts); + reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4); + reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Skirt, 4); + reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4); } - if(!isBeast && boots != inv.getSlot(MWWorld::InventoryStore::Slot_Boots)){ - boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); - removePartGroup(MWWorld::InventoryStore::Slot_Boots); - apparelChanged = true; + if(helmet != inv.end()) + { + removeIndividualPart(ESM::PRT_Hair); + const ESM::Armor *armor = (helmet->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts); } - if(leftglove != inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)){ - leftglove = inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet); - removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet); - apparelChanged = true; - + if(cuirass != inv.end()) + { + const ESM::Armor *armor = (cuirass->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts); } - if(rightglove != inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)){ - rightglove = inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet); - removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet); - apparelChanged = true; - + if(greaves != inv.end()) + { + const ESM::Armor *armor = (greaves->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts); } - if(shirt != inv.getSlot(MWWorld::InventoryStore::Slot_Shirt)){ - shirt = inv.getSlot(MWWorld::InventoryStore::Slot_Shirt); - removePartGroup(MWWorld::InventoryStore::Slot_Shirt); - apparelChanged = true; + if(leftpauldron != inv.end()) + { + const ESM::Armor *armor = (leftpauldron->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts); } - if(pants != inv.getSlot(MWWorld::InventoryStore::Slot_Pants)){ - pants = inv.getSlot(MWWorld::InventoryStore::Slot_Pants); - removePartGroup(MWWorld::InventoryStore::Slot_Pants); - apparelChanged = true; - + if(rightpauldron != inv.end()) + { + const ESM::Armor *armor = (rightpauldron->get())->base; + std::vector parts = armor->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); } - - if(apparelChanged){ - - if(robe != inv.end()) + if(!isBeast && boots != inv.end()) + { + if(boots->getTypeName() == typeid(ESM::Clothing).name()) { - MWWorld::Ptr ptr = *robe; - - const ESM::Clothing *clothes = (ptr.get())->base; + const ESM::Clothing *clothes = (boots->get())->base; std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts); - reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_Skirt, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LUpperarm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RKnee, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LKnee, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RForearm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LForearm, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5); - reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5); + addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts); } - if(skirtiter != inv.end()) + else if(boots->getTypeName() == typeid(ESM::Armor).name()) { - MWWorld::Ptr ptr = *skirtiter; - - const ESM::Clothing *clothes = (ptr.get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts); - reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4); - reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Skirt, 4); - reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4); - } - - if(helmet != inv.end()){ - removeIndividualPart(ESM::PRT_Hair); - const ESM::Armor *armor = (helmet->get())->base; + const ESM::Armor *armor = (boots->get())->base; std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts); - + addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts); } - if(cuirass != inv.end()){ - const ESM::Armor *armor = (cuirass->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts); - + } + if(leftglove != inv.end()) + { + if(leftglove->getTypeName() == typeid(ESM::Clothing).name()) + { + const ESM::Clothing *clothes = (leftglove->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts); } - if(greaves != inv.end()){ - const ESM::Armor *armor = (greaves->get())->base; + else + { + const ESM::Armor *armor = (leftglove->get())->base; std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts); - + addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts); } - - if(leftpauldron != inv.end()){ - const ESM::Armor *armor = (leftpauldron->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts); - + } + if(rightglove != inv.end()) + { + if(rightglove->getTypeName() == typeid(ESM::Clothing).name()) + { + const ESM::Clothing *clothes = (rightglove->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts); } - if(rightpauldron != inv.end()){ - const ESM::Armor *armor = (rightpauldron->get())->base; + else + { + const ESM::Armor *armor = (rightglove->get())->base; std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts); - - } - if(!isBeast && boots != inv.end()){ - if(boots->getTypeName() == typeid(ESM::Clothing).name()){ - const ESM::Clothing *clothes = (boots->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts); - } - else if(boots->getTypeName() == typeid(ESM::Armor).name()) - { - const ESM::Armor *armor = (boots->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts); - } - - } - if(leftglove != inv.end()){ - if(leftglove->getTypeName() == typeid(ESM::Clothing).name()){ - const ESM::Clothing *clothes = (leftglove->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts); - } - else - { - const ESM::Armor *armor = (leftglove->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts); - } - + addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts); } - if(rightglove != inv.end()){ - if(rightglove->getTypeName() == typeid(ESM::Clothing).name()){ - const ESM::Clothing *clothes = (rightglove->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts); - } - else - { - const ESM::Armor *armor = (rightglove->get())->base; - std::vector parts = armor->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts); - } - } - - if(shirt != inv.end()){ - const ESM::Clothing *clothes = (shirt->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts); - } - if(pants != inv.end()){ - const ESM::Clothing *clothes = (pants->get())->base; - std::vector parts = clothes->parts.parts; - addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts); - } } - if(partpriorities[ESM::PRT_Head] < 1){ - addOrReplaceIndividualPart(ESM::PRT_Head, -1,1,headModel); - } - if(partpriorities[ESM::PRT_Hair] < 1 && partpriorities[ESM::PRT_Head] <= 1){ - addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1,hairModel); - } - if(partpriorities[ESM::PRT_Neck] < 1){ - const ESM::BodyPart *neckPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "neck"); - if(neckPart) - addOrReplaceIndividualPart(ESM::PRT_Neck, -1,1,"meshes\\" + neckPart->model); - } - if(partpriorities[ESM::PRT_Cuirass] < 1){ - const ESM::BodyPart *chestPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "chest"); - if(chestPart) - addOrReplaceIndividualPart(ESM::PRT_Cuirass, -1,1,"meshes\\" + chestPart->model); - } - - if(partpriorities[ESM::PRT_Groin] < 1){ - const ESM::BodyPart *groinPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "groin"); - if(groinPart) - addOrReplaceIndividualPart(ESM::PRT_Groin, -1,1,"meshes\\" + groinPart->model); - } - if(partpriorities[ESM::PRT_RHand] < 1){ - const ESM::BodyPart *handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hand"); - if(!handPart) - handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hands"); - if(handPart) - addOrReplaceIndividualPart(ESM::PRT_RHand, -1,1,"meshes\\" + handPart->model); - } - if(partpriorities[ESM::PRT_LHand] < 1){ - const ESM::BodyPart *handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hand"); - if(!handPart) - handPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "hands"); - if(handPart) - addOrReplaceIndividualPart(ESM::PRT_LHand, -1,1,"meshes\\" + handPart->model); - } + if(shirt != inv.end()) + { + const ESM::Clothing *clothes = (shirt->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts); + } + if(pants != inv.end()) + { + const ESM::Clothing *clothes = (pants->get())->base; + std::vector parts = clothes->parts.parts; + addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts); + } + } - if(partpriorities[ESM::PRT_RWrist] < 1){ - const ESM::BodyPart *wristPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "wrist"); - if(wristPart) - addOrReplaceIndividualPart(ESM::PRT_RWrist, -1,1,"meshes\\" + wristPart->model); - } - if(partpriorities[ESM::PRT_LWrist] < 1){ - const ESM::BodyPart *wristPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "wrist"); - if(wristPart) - addOrReplaceIndividualPart(ESM::PRT_LWrist, -1,1,"meshes\\" + wristPart->model); - } - if(partpriorities[ESM::PRT_RForearm] < 1){ - const ESM::BodyPart *forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "forearm"); - if(bodyRaceID == "b_n_argonian_f_") - forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search ("b_n_argonian_m_forearm"); - if(forearmPart) - addOrReplaceIndividualPart(ESM::PRT_RForearm, -1,1,"meshes\\" + forearmPart->model); - } - if(partpriorities[ESM::PRT_LForearm] < 1){ - const ESM::BodyPart *forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "forearm"); - if(bodyRaceID == "b_n_argonian_f_") - forearmPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search ("b_n_argonian_m_forearm"); - if(forearmPart) - addOrReplaceIndividualPart(ESM::PRT_LForearm, -1,1,"meshes\\" + forearmPart->model); - } - if(partpriorities[ESM::PRT_RUpperarm] < 1){ - const ESM::BodyPart *armPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper arm"); - if(armPart) - addOrReplaceIndividualPart(ESM::PRT_RUpperarm, -1,1,"meshes\\" + armPart->model); - } - if(partpriorities[ESM::PRT_LUpperarm] < 1){ - const ESM::BodyPart *armPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper arm"); - if(armPart) - addOrReplaceIndividualPart(ESM::PRT_LUpperarm, -1,1,"meshes\\" + armPart->model); - } - if(partpriorities[ESM::PRT_RFoot] < 1){ - const ESM::BodyPart *footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "foot"); - if(isBeast && !footPart) - footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "feet"); - if(footPart) - addOrReplaceIndividualPart(ESM::PRT_RFoot, -1,1,"meshes\\" + footPart->model); - } - if(partpriorities[ESM::PRT_LFoot] < 1){ - const ESM::BodyPart *footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "foot"); - if(isBeast && !footPart) - footPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "feet"); - if(footPart) - addOrReplaceIndividualPart(ESM::PRT_LFoot, -1,1,"meshes\\" + footPart->model); - } - if(partpriorities[ESM::PRT_RAnkle] < 1){ - const ESM::BodyPart *anklePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "ankle"); - if(anklePart) - addOrReplaceIndividualPart(ESM::PRT_RAnkle, -1,1,"meshes\\" + anklePart->model); - } - if(partpriorities[ESM::PRT_LAnkle] < 1){ - const ESM::BodyPart *anklePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "ankle"); - if(anklePart) - addOrReplaceIndividualPart(ESM::PRT_LAnkle, -1,1,"meshes\\" + anklePart->model); - } - if(partpriorities[ESM::PRT_RKnee] < 1){ - const ESM::BodyPart *kneePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "knee"); - if(kneePart) - addOrReplaceIndividualPart(ESM::PRT_RKnee, -1,1,"meshes\\" + kneePart->model); - } - if(partpriorities[ESM::PRT_LKnee] < 1){ - const ESM::BodyPart *kneePart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "knee"); - if(kneePart) - addOrReplaceIndividualPart(ESM::PRT_LKnee, -1,1,"meshes\\" + kneePart->model); - } - if(partpriorities[ESM::PRT_RLeg] < 1){ - const ESM::BodyPart *legPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper leg"); - if(legPart) - addOrReplaceIndividualPart(ESM::PRT_RLeg, -1,1,"meshes\\" + legPart->model); - } - if(partpriorities[ESM::PRT_LLeg] < 1){ - const ESM::BodyPart *legPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "upper leg"); - if(legPart) - addOrReplaceIndividualPart(ESM::PRT_LLeg, -1,1,"meshes\\" + legPart->model); - } - if(partpriorities[ESM::PRT_Tail] < 1){ - const ESM::BodyPart *tailPart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (bodyRaceID + "tail"); - if(tailPart) - addOrReplaceIndividualPart(ESM::PRT_Tail, -1,1,"meshes\\" + tailPart->model); + if(partpriorities[ESM::PRT_Head] < 1) + addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, headModel); + if(partpriorities[ESM::PRT_Hair] < 1 && partpriorities[ESM::PRT_Head] <= 1) + addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, hairModel); + + static const struct { + ESM::PartReferenceType type; + const char name[2][12]; + } PartTypeList[] = { + { ESM::PRT_Neck, { "neck", "" } }, + { ESM::PRT_Cuirass, { "chest", "" } }, + { ESM::PRT_Groin, { "groin", "" } }, + { ESM::PRT_RHand, { "hand", "hands" } }, + { ESM::PRT_LHand, { "hand", "hands" } }, + { ESM::PRT_RWrist, { "wrist", "" } }, + { ESM::PRT_LWrist, { "wrist", "" } }, + { ESM::PRT_RForearm, { "forearm", "" } }, + { ESM::PRT_LForearm, { "forearm", "" } }, + { ESM::PRT_RUpperarm, { "upper arm", "" } }, + { ESM::PRT_LUpperarm, { "upper arm", "" } }, + { ESM::PRT_RFoot, { "foot", "feet" } }, + { ESM::PRT_LFoot, { "foot", "feet" } }, + { ESM::PRT_RAnkle, { "ankle", "" } }, + { ESM::PRT_LAnkle, { "ankle", "" } }, + { ESM::PRT_RKnee, { "knee", "" } }, + { ESM::PRT_LKnee, { "knee", "" } }, + { ESM::PRT_RLeg, { "upper leg", "" } }, + { ESM::PRT_LLeg, { "upper leg", "" } }, + { ESM::PRT_Tail, { "tail", "" } } + }; + + const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++) + { + if(partpriorities[PartTypeList[i].type] < 1) + { + const ESM::BodyPart *part = NULL; + bool tryfemale = isFemale; + int ni = 0; + do { + part = store.bodyParts.search(bodyRaceID+(tryfemale?"_f_":"_m_")+PartTypeList[i].name[ni]); + if(part) break; + + ni ^= 1; + if(ni == 0) + { + if(!tryfemale) + break; + tryfemale = false; } + } while(1); - - - - - - - + if(part) + addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->model); + } + } } -Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ +Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, const std::string &bonename) +{ NIFLoader::load(mesh); Ogre::Entity* part = mRend.getScene()->createEntity(mesh); @@ -508,361 +390,275 @@ Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::stri base->attachObjectToBone(bonename, part); return part; } -void NpcAnimation::insertFootPart(int type, const std::string &mesh){ - std::string meshAndSuffix = mesh; - if(type == ESM::PRT_LFoot) - meshAndSuffix += "*|"; - NIFLoader::load(meshAndSuffix); - Ogre::Entity* part = mRend.getScene()->createEntity(meshAndSuffix); - std::vector* shape = ((NIFLoader::getSingletonPtr())->getShapes(meshAndSuffix)); - if(shape == 0){ - if(type == ESM::PRT_LFoot){ - base->attachObjectToBone("Left Foot", part); - lfoot = part; - } - else if (type == ESM::PRT_RFoot){ - base->attachObjectToBone("Right Foot", part); - rfoot = part; - } - } - else{ - if(type == ESM::PRT_LFoot) - lFreeFoot = insertFreePart(mesh, "::"); - else if (type == ESM::PRT_RFoot) - rFreeFoot = insertFreePart(mesh, ":<"); - } - - - -} -std::pair*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string& suffix){ - std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; - NIFLoader::load(meshNumbered); - - Ogre::Entity* part = mRend.getScene()->createEntity(meshNumbered); - part->setVisibilityFlags(RV_Actors); - - insert->attachObject(part); - - std::vector* shape = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix)); - if(shape){ - handleShapes(shape, part, base->getSkeleton()); +void NpcAnimation::runAnimation(float timepassed) +{ + if(timeToChange > .2) + { + timeToChange = 0; + updateParts(); } - std::pair*> pair = std::make_pair(part, shape); - return pair; -} - - - -void NpcAnimation::runAnimation(float timepassed){ - - if(timeToChange > .2){ - - timeToChange = 0; - - updateParts(); - } - - timeToChange += timepassed; + timeToChange += timepassed; //1. Add the amount of time passed to time - //2. Handle the animation transforms dependent on time + //2. Handle the animation transforms dependent on time - //3. Handle the shapes dependent on animation transforms - if(animate > 0){ + //3. Handle the shapes dependent on animation transforms + if(animate > 0) + { time += timepassed; - - if(time > stopTime){ + if(time > stopTime) + { animate--; - if(animate == 0) time = stopTime; else time = startTime + (time - stopTime); } - handleAnimationTransforms(); - - - vecRotPos.clear(); - - - if(lFreeFoot.first) - handleShapes(lFreeFoot.second, lFreeFoot.first, base->getSkeleton()); - if(rFreeFoot.first) - handleShapes(rFreeFoot.second, rFreeFoot.first, base->getSkeleton()); - - if(chest.first) - handleShapes(chest.second, chest.first, base->getSkeleton()); - if(tail.first) - handleShapes(tail.second, tail.first, base->getSkeleton()); - if(skirt.first){ - handleShapes(skirt.second, skirt.first, base->getSkeleton()); - } - if(lhand.first) - handleShapes(lhand.second, lhand.first, base->getSkeleton()); - if(rhand.first) - handleShapes(rhand.second, rhand.first, base->getSkeleton()); - -} + handleAnimationTransforms(); + } } -void NpcAnimation::removeIndividualPart(int type){ +void NpcAnimation::removeIndividualPart(int type) +{ partpriorities[type] = 0; partslots[type] = -1; - if(type == ESM::PRT_Head && head){ //0 - base->detachObjectFromBone(head); - head = 0; - } - else if(type == ESM::PRT_Hair && hair){//1 - base->detachObjectFromBone(hair); - hair = 0; - } - else if(type == ESM::PRT_Neck && neck){//2 - base->detachObjectFromBone(neck); - neck = 0; - } - else if(type == ESM::PRT_Cuirass && chest.first){//3 - insert->detachObject(chest.first); - chest = zero; - } - else if(type == ESM::PRT_Groin && groin){//4 - base->detachObjectFromBone(groin); - groin = 0; - } - else if(type == ESM::PRT_Skirt && skirt.first){//5 - insert->detachObject(skirt.first); - skirt = zero; - } - else if(type == ESM::PRT_RHand && rhand.first){//6 - insert->detachObject(rhand.first); - rhand = zero; - } - else if(type == ESM::PRT_LHand && lhand.first){//7 - insert->detachObject(lhand.first); - lhand = zero; - } - else if(type == ESM::PRT_RWrist && rWrist){//8 - base->detachObjectFromBone(rWrist); - rWrist = 0; - } - else if(type == ESM::PRT_LWrist && lWrist){//9 - base->detachObjectFromBone(lWrist); - lWrist = 0; - } - else if(type == ESM::PRT_Shield){//10 - - } - else if(type == ESM::PRT_RForearm && rForearm){//11 - base->detachObjectFromBone(rForearm); - rForearm = 0; - } - else if(type == ESM::PRT_LForearm && lForearm){//12 - base->detachObjectFromBone(lForearm); - lForearm = 0; - } - else if(type == ESM::PRT_RUpperarm && rupperArm){//13 - base->detachObjectFromBone(rupperArm); - rupperArm = 0; - } - else if(type == ESM::PRT_LUpperarm && lupperArm){//14 - base->detachObjectFromBone(lupperArm); - lupperArm = 0; - } - else if(type == ESM::PRT_RFoot){ //15 - if(rfoot){ - base->detachObjectFromBone(rfoot); - rfoot = 0; - } - else if(rFreeFoot.first){ - insert->detachObject(rFreeFoot.first); - rFreeFoot = zero; - } - } - else if(type == ESM::PRT_LFoot){ //16 - if(lfoot){ - base->detachObjectFromBone(lfoot); - lfoot = 0; - } - else if(lFreeFoot.first){ - insert->detachObject(lFreeFoot.first); - lFreeFoot = zero; - } - } - else if(type == ESM::PRT_RAnkle && rAnkle){ //17 - base->detachObjectFromBone(rAnkle); - rAnkle = 0; - } - else if(type == ESM::PRT_LAnkle && lAnkle){ //18 - base->detachObjectFromBone(lAnkle); - lAnkle = 0; - } - else if(type == ESM::PRT_RKnee && rKnee){ //19 - base->detachObjectFromBone(rKnee); - rKnee = 0; - } - else if(type == ESM::PRT_LKnee && lKnee){ //20 - base->detachObjectFromBone(lKnee); - lKnee = 0; - } - else if(type == ESM::PRT_RLeg && rUpperLeg){ //21 - base->detachObjectFromBone(rUpperLeg); - rUpperLeg = 0; - } - else if(type == ESM::PRT_LLeg && lUpperLeg){ //22 - base->detachObjectFromBone(lUpperLeg); - lUpperLeg = 0; - } - else if(type == ESM::PRT_RPauldron && rclavicle){ //23 - base->detachObjectFromBone(rclavicle); - rclavicle = 0; - } - else if(type == ESM::PRT_LPauldron && lclavicle){ //24 - base->detachObjectFromBone(lclavicle); - lclavicle = 0; - } - else if(type == ESM::PRT_Weapon){ //25 - - } - else if(type == ESM::PRT_Tail && tail.first){ //26 - insert->detachObject(tail.first); - tail = zero; - } - - - - + if(type == ESM::PRT_Head && head) //0 + { + base->detachObjectFromBone(head); + head = 0; } - - void NpcAnimation::reserveIndividualPart(int type, int group, int priority){ - if(priority > partpriorities[type]){ - removeIndividualPart(type); - partpriorities[type] = priority; - partslots[type] = group; - } + else if(type == ESM::PRT_Hair && hair) //1 + { + base->detachObjectFromBone(hair); + hair = 0; + } + else if(type == ESM::PRT_Neck && neck) //2 + { + base->detachObjectFromBone(neck); + neck = 0; + } + else if(type == ESM::PRT_Groin && groin)//4 + { + base->detachObjectFromBone(groin); + groin = 0; + } + else if(type == ESM::PRT_RWrist && rWrist)//8 + { + base->detachObjectFromBone(rWrist); + rWrist = 0; + } + else if(type == ESM::PRT_LWrist && lWrist) //9 + { + base->detachObjectFromBone(lWrist); + lWrist = 0; + } + else if(type == ESM::PRT_Shield) //10 + { + } + else if(type == ESM::PRT_RForearm && rForearm) //11 + { + base->detachObjectFromBone(rForearm); + rForearm = 0; + } + else if(type == ESM::PRT_LForearm && lForearm) //12 + { + base->detachObjectFromBone(lForearm); + lForearm = 0; + } + else if(type == ESM::PRT_RUpperarm && rupperArm) //13 + { + base->detachObjectFromBone(rupperArm); + rupperArm = 0; + } + else if(type == ESM::PRT_LUpperarm && lupperArm) //14 + { + base->detachObjectFromBone(lupperArm); + lupperArm = 0; + } + else if(type == ESM::PRT_RFoot && rfoot) //15 + { + base->detachObjectFromBone(rfoot); + rfoot = 0; + } + else if(type == ESM::PRT_LFoot && lfoot) //16 + { + base->detachObjectFromBone(lfoot); + lfoot = 0; + } + else if(type == ESM::PRT_RAnkle && rAnkle) //17 + { + base->detachObjectFromBone(rAnkle); + rAnkle = 0; + } + else if(type == ESM::PRT_LAnkle && lAnkle) //18 + { + base->detachObjectFromBone(lAnkle); + lAnkle = 0; + } + else if(type == ESM::PRT_RKnee && rKnee) //19 + { + base->detachObjectFromBone(rKnee); + rKnee = 0; + } + else if(type == ESM::PRT_LKnee && lKnee) //20 + { + base->detachObjectFromBone(lKnee); + lKnee = 0; + } + else if(type == ESM::PRT_RLeg && rUpperLeg) //21 + { + base->detachObjectFromBone(rUpperLeg); + rUpperLeg = 0; + } + else if(type == ESM::PRT_LLeg && lUpperLeg) //22 + { + base->detachObjectFromBone(lUpperLeg); + lUpperLeg = 0; + } + else if(type == ESM::PRT_RPauldron && rclavicle) //23 + { + base->detachObjectFromBone(rclavicle); + rclavicle = 0; } + else if(type == ESM::PRT_LPauldron && lclavicle) //24 + { + base->detachObjectFromBone(lclavicle); + lclavicle = 0; + } + else if(type == ESM::PRT_Weapon) //25 + { + } +} - void NpcAnimation::removePartGroup(int group){ - for(int i = 0; i < 27; i++){ - if(partslots[i] == group){ - removeIndividualPart(i); - } - } +void NpcAnimation::reserveIndividualPart(int type, int group, int priority) +{ + if(priority > partpriorities[type]) + { + removeIndividualPart(type); + partpriorities[type] = priority; + partslots[type] = group; } - bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh){ - if(priority > partpriorities[type]){ - removeIndividualPart(type); - partslots[type] = group; - partpriorities[type] = priority; - switch(type){ - case ESM::PRT_Head: //0 - head = insertBoundedPart(mesh, "Head"); - break; - case ESM::PRT_Hair: //1 - hair = insertBoundedPart(mesh, "Head"); - break; - case ESM::PRT_Neck: //2 - neck = insertBoundedPart(mesh, "Neck"); - break; - case ESM::PRT_Cuirass: //3 - chest = insertFreePart(mesh, ":\""); - break; - case ESM::PRT_Groin: //4 - groin = insertBoundedPart(mesh, "Groin"); - break; - case ESM::PRT_Skirt: //5 - skirt = insertFreePart(mesh, ":|"); - break; - case ESM::PRT_RHand: //6 - rhand = insertFreePart(mesh, ":?"); - break; - case ESM::PRT_LHand: //7 - lhand = insertFreePart(mesh, ":>"); - break; - case ESM::PRT_RWrist: //8 - rWrist = insertBoundedPart(mesh, "Right Wrist"); - break; - case ESM::PRT_LWrist: //9 - lWrist = insertBoundedPart(mesh + "*|", "Left Wrist"); - break; - case ESM::PRT_Shield: //10 - break; - case ESM::PRT_RForearm: //11 - rForearm = insertBoundedPart(mesh, "Right Forearm"); - break; - case ESM::PRT_LForearm: //12 - lForearm = insertBoundedPart(mesh + "*|", "Left Forearm"); - break; - case ESM::PRT_RUpperarm: //13 - rupperArm = insertBoundedPart(mesh, "Right Upper Arm"); - break; - case ESM::PRT_LUpperarm: //14 - lupperArm = insertBoundedPart(mesh + "*|", "Left Upper Arm"); - break; - case ESM::PRT_RFoot: //15 - insertFootPart(type, mesh); - break; - case ESM::PRT_LFoot: //16 - insertFootPart(type, mesh); - break; - case ESM::PRT_RAnkle: //17 - rAnkle = insertBoundedPart(mesh , "Right Ankle"); - break; - case ESM::PRT_LAnkle: //18 - lAnkle = insertBoundedPart(mesh + "*|", "Left Ankle"); - break; - case ESM::PRT_RKnee: //19 - rKnee = insertBoundedPart(mesh , "Right Knee"); - break; - case ESM::PRT_LKnee: //20 - lKnee = insertBoundedPart(mesh + "*|", "Left Knee"); - break; - case ESM::PRT_RLeg: //21 - rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg"); - break; - case ESM::PRT_LLeg: //22 - lUpperLeg = insertBoundedPart(mesh + "*|", "Left Upper Leg"); - break; - case ESM::PRT_RPauldron: //23 - rclavicle = insertBoundedPart(mesh , "Right Clavicle"); - break; - case ESM::PRT_LPauldron: //24 - lclavicle = insertBoundedPart(mesh + "*|", "Left Clavicle"); - break; - case ESM::PRT_Weapon: //25 - break; - case ESM::PRT_Tail: //26 - tail = insertFreePart(mesh, ":*"); - break; +} +void NpcAnimation::removePartGroup(int group) +{ + for(int i = 0; i < 27; i++) + { + if(partslots[i] == group) + removeIndividualPart(i); + } +} - } - return true; - } +bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh) +{ + if(priority <= partpriorities[type]) return false; - } - void NpcAnimation::addPartGroup(int group, int priority, std::vector& parts){ - for(std::size_t i = 0; i < parts.size(); i++) - { - ESM::PartReference part = parts[i]; + removeIndividualPart(type); + partslots[type] = group; + partpriorities[type] = priority; + switch(type) + { + case ESM::PRT_Head: //0 + head = insertBoundedPart(mesh, "Head"); + break; + case ESM::PRT_Hair: //1 + hair = insertBoundedPart(mesh, "Head"); + break; + case ESM::PRT_Neck: //2 + neck = insertBoundedPart(mesh, "Neck"); + break; + case ESM::PRT_Cuirass: //3 + break; + case ESM::PRT_Groin: //4 + groin = insertBoundedPart(mesh, "Groin"); + break; + case ESM::PRT_Skirt: //5 + break; + case ESM::PRT_RHand: //6 + break; + case ESM::PRT_LHand: //7 + break; + case ESM::PRT_RWrist: //8 + rWrist = insertBoundedPart(mesh, "Right Wrist"); + break; + case ESM::PRT_LWrist: //9 + lWrist = insertBoundedPart(mesh, "Left Wrist"); + break; + case ESM::PRT_Shield: //10 + break; + case ESM::PRT_RForearm: //11 + rForearm = insertBoundedPart(mesh, "Right Forearm"); + break; + case ESM::PRT_LForearm: //12 + lForearm = insertBoundedPart(mesh, "Left Forearm"); + break; + case ESM::PRT_RUpperarm: //13 + rupperArm = insertBoundedPart(mesh, "Right Upper Arm"); + break; + case ESM::PRT_LUpperarm: //14 + lupperArm = insertBoundedPart(mesh, "Left Upper Arm"); + break; + case ESM::PRT_RFoot: //15 + lupperArm = insertBoundedPart(mesh, "Right Foot"); + break; + case ESM::PRT_LFoot: //16 + lupperArm = insertBoundedPart(mesh, "Left Foot"); + break; + case ESM::PRT_RAnkle: //17 + rAnkle = insertBoundedPart(mesh, "Right Ankle"); + break; + case ESM::PRT_LAnkle: //18 + lAnkle = insertBoundedPart(mesh, "Left Ankle"); + break; + case ESM::PRT_RKnee: //19 + rKnee = insertBoundedPart(mesh, "Right Knee"); + break; + case ESM::PRT_LKnee: //20 + lKnee = insertBoundedPart(mesh, "Left Knee"); + break; + case ESM::PRT_RLeg: //21 + rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg"); + break; + case ESM::PRT_LLeg: //22 + lUpperLeg = insertBoundedPart(mesh, "Left Upper Leg"); + break; + case ESM::PRT_RPauldron: //23 + rclavicle = insertBoundedPart(mesh , "Right Clavicle"); + break; + case ESM::PRT_LPauldron: //24 + lclavicle = insertBoundedPart(mesh, "Left Clavicle"); + break; + case ESM::PRT_Weapon: //25 + break; + case ESM::PRT_Tail: //26 + break; + } + return true; +} - const ESM::BodyPart *bodypart = 0; +void NpcAnimation::addPartGroup(int group, int priority, std::vector &parts) +{ + for(std::size_t i = 0; i < parts.size(); i++) + { + ESM::PartReference &part = parts[i]; - if(isFemale) - bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (part.female); - if(!bodypart) - bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search (part.male); - if(bodypart){ - addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model); - } - else - reserveIndividualPart(part.part, group, priority); + const ESM::BodyPart *bodypart = 0; + if(isFemale) + bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.female); + if(!bodypart) + bodypart = MWBase::Environment::get().getWorld()->getStore().bodyParts.search(part.male); - } + if(bodypart) + addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model); + else + reserveIndividualPart(part.part, group, priority); } } + +} diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 8f4f8181d..151af4163 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -20,54 +20,43 @@ namespace MWRender{ class NpcAnimation: public Animation{ private: - MWWorld::InventoryStore& inv; - int mStateID; - //Free Parts - std::pair*> chest; - std::pair*> skirt; - std::pair*> lhand; - std::pair*> rhand; - std::pair*> tail; - std::pair*> lFreeFoot; - std::pair*> rFreeFoot; + MWWorld::InventoryStore& inv; + int mStateID; - int partslots[27]; //Each part slot is taken by clothing, armor, or is empty - int partpriorities[27]; - std::pair*> zero; + int partslots[27]; //Each part slot is taken by clothing, armor, or is empty + int partpriorities[27]; + //Bounded Parts + Ogre::Entity* lclavicle; + Ogre::Entity* rclavicle; + Ogre::Entity* rupperArm; + Ogre::Entity* lupperArm; + Ogre::Entity* rUpperLeg; + Ogre::Entity* lUpperLeg; + Ogre::Entity* lForearm; + Ogre::Entity* rForearm; + Ogre::Entity* lWrist; + Ogre::Entity* rWrist; + Ogre::Entity* rKnee; + Ogre::Entity* lKnee; + Ogre::Entity* neck; + Ogre::Entity* rAnkle; + Ogre::Entity* lAnkle; + Ogre::Entity* groin; + Ogre::Entity* lfoot; + Ogre::Entity* rfoot; + Ogre::Entity* hair; + Ogre::Entity* head; - - //Bounded Parts - Ogre::Entity* lclavicle; - Ogre::Entity* rclavicle; - Ogre::Entity* rupperArm; - Ogre::Entity* lupperArm; - Ogre::Entity* rUpperLeg; - Ogre::Entity* lUpperLeg; - Ogre::Entity* lForearm; - Ogre::Entity* rForearm; - Ogre::Entity* lWrist; - Ogre::Entity* rWrist; - Ogre::Entity* rKnee; - Ogre::Entity* lKnee; - Ogre::Entity* neck; - Ogre::Entity* rAnkle; - Ogre::Entity* lAnkle; - Ogre::Entity* groin; - Ogre::Entity* lfoot; - Ogre::Entity* rfoot; - Ogre::Entity* hair; - Ogre::Entity* head; - - Ogre::SceneNode* insert; + Ogre::SceneNode* insert; bool isBeast; bool isFemale; - std::string headModel; - std::string hairModel; - std::string npcName; - std::string bodyRaceID; - float timeToChange; - MWWorld::ContainerStoreIterator robe; + std::string headModel; + std::string hairModel; + std::string npcName; + std::string bodyRaceID; + float timeToChange; + MWWorld::ContainerStoreIterator robe; MWWorld::ContainerStoreIterator helmet; MWWorld::ContainerStoreIterator shirt; MWWorld::ContainerStoreIterator cuirass; @@ -80,22 +69,19 @@ private: MWWorld::ContainerStoreIterator rightglove; MWWorld::ContainerStoreIterator skirtiter; - public: - NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); - virtual ~NpcAnimation(); - Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); - std::pair*> insertFreePart(const std::string &mesh, const std::string& suffix); - void insertFootPart(int type, const std::string &mesh); - virtual void runAnimation(float timepassed); - void updateParts(); +public: + NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); + virtual ~NpcAnimation(); + Ogre::Entity* insertBoundedPart(const std::string &mesh, const std::string &bonename); + virtual void runAnimation(float timepassed); + void updateParts(); void removeIndividualPart(int type); void reserveIndividualPart(int type, int group, int priority); bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh); - void removePartGroup(int group); + void removePartGroup(int group); void addPartGroup(int group, int priority, std::vector& parts); - - }; + } #endif diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index e9ce3f615..dd12a53ff 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -64,28 +64,13 @@ static bool fsstrict = false; /// An OGRE Archive wrapping a BSAFile archive class DirArchive: public Ogre::FileSystemArchive { - boost::filesystem::path currentdir; std::map, ciLessBoost> m; unsigned int cutoff; bool findFile(const String& filename, std::string& copy) const { - { - String passed = filename; - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); - else if(filename.at(filename.length() - 2) == '"') - passed = filename.substr(0, filename.length() - 9); - else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' - || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' - || filename.at(filename.length() - 1) == '|') - passed = filename.substr(0, filename.length() - 2); - - - copy = passed; - } - + copy = filename; std::replace(copy.begin(), copy.end(), '\\', '/'); if(copy.at(0) == '/') @@ -225,46 +210,23 @@ public: // OGRE's fault. You should NOT expect an open() command not to // have any side effects on the archive, and hence this function // should not have been declared const in the first place. - BSAFile *narc = (BSAFile*)&arc; - - String passed = filename; - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); - else if(filename.at(filename.length() - 2) == '"') - passed = filename.substr(0, filename.length() - 9); - else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' - || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' - || filename.at(filename.length() - 1) == '|') - passed = filename.substr(0, filename.length() - 2); - - + BSAFile *narc = const_cast(&arc); + // Open the file - StreamPtr strm = narc->getFile(passed.c_str()); + StreamPtr strm = narc->getFile(filename.c_str()); // Wrap it into an Ogre::DataStream. return DataStreamPtr(new Mangle2OgreStream(strm)); } -bool exists(const String& filename) { - return cexists(filename); -} + bool exists(const String& filename) { + return arc.exists(filename.c_str()); + } - // Check if the file exists. bool cexists(const String& filename) const { - String passed = filename; - if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':') - passed = filename.substr(0, filename.length() - 6); - else if(filename.at(filename.length() - 2) == '"') - passed = filename.substr(0, filename.length() - 9); - else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' - || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' - || filename.at(filename.length() - 1) == '|') - passed = filename.substr(0, filename.length() - 2); - - - -return arc.exists(passed.c_str()); -} + return arc.exists(filename.c_str()); + } + time_t getModifiedTime(const String&) { return 0; } // This is never called as far as I can see. diff --git a/components/nif/data.hpp b/components/nif/data.hpp index b7e2f172f..2d1e8bd3b 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -326,12 +326,6 @@ public: Ogre::Vector3 trans; // Translation float scale; // Probably scale (always 1) }; - struct BoneTrafoCopy - { - Ogre::Quaternion rotation; - Ogre::Vector3 trans; - float scale; - }; struct VertWeight { @@ -339,26 +333,12 @@ public: float weight; }; - struct BoneInfo { BoneTrafo trafo; Ogre::Vector4 unknown; std::vector weights; }; - struct BoneInfoCopy - { - std::string bonename; - unsigned short bonehandle; - BoneTrafoCopy trafo; - Ogre::Vector4 unknown; - //std::vector weights; - }; - struct IndividualWeight - { - float weight; - unsigned int boneinfocopyindex; - }; BoneTrafo trafo; std::vector bones; diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 293793009..1f1b91a46 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -110,20 +110,6 @@ public: } }; -struct NiTriShapeCopy -{ - std::string sname; - std::vector boneSequence; - Nif::NiSkinData::BoneTrafoCopy trafo; - //Ogre::Quaternion initialBoneRotation; - //Ogre::Vector3 initialBoneTranslation; - std::vector vertices; - std::vector normals; - std::vector boneinfo; - std::map > vertsToWeights; - Nif::NiMorphData morph; -}; - struct NiNode : Node { NodeList children; @@ -184,28 +170,6 @@ struct NiTriShape : Node data.post(nif); skin.post(nif); } - - NiTriShapeCopy clone() - { - NiTriShapeCopy copy; - copy.sname = name; - float *ptr = (float*)&data->vertices[0]; - float *ptrNormals = (float*)&data->normals[0]; - int numVerts = data->vertices.size() / 3; - for(int i = 0; i < numVerts; i++) - { - float *current = (float*) (ptr + i * 3); - copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2))); - - if(ptrNormals) - { - float *currentNormals = (float*) (ptrNormals + i * 3); - copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2))); - } - } - - return copy; - } }; struct NiCamera : Node diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index c3b34e039..5f562504b 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -79,7 +79,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) // of the early stages of development. Right now we WANT to catch // every error as early and intrusively as possible, as it's most // likely a sign of incomplete code rather than faulty input. - Nif::NIFFile nif(resourceName); + Nif::NIFFile nif(resourceName.substr(0, resourceName.length()-7)); if (nif.numRecords() < 1) { warn("Found no records in NIF."); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 014384dd4..883cf7fce 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -42,28 +42,6 @@ using namespace std; using namespace Nif; using namespace NifOgre; -NIFLoader& NIFLoader::getSingleton() -{ - static NIFLoader instance; - return instance; -} - -NIFLoader* NIFLoader::getSingletonPtr() -{ - return &getSingleton(); -} - -void NIFLoader::warn(string msg) -{ - std::cerr << "NIFLoader: Warn:" << msg << "\n"; -} - -void NIFLoader::fail(string msg) -{ - std::cerr << "NIFLoader: Fail: "<< msg << std::endl; - assert(1); -} - // Helper class that computes the bounding box and of a mesh class BoundsFinder @@ -149,6 +127,19 @@ public: } }; + +void NIFLoader::warn(const std::string &msg) +{ + std::cerr << "NIFLoader: Warn:" << msg << "\n"; +} + +void NIFLoader::fail(const std::string &msg) +{ + std::cerr << "NIFLoader: Fail: "<< msg << std::endl; + assert(1); +} + + // Conversion of blend / test mode from NIF -> OGRE. // Not in use yet, so let's comment it out. /* @@ -193,12 +184,7 @@ static CompareFunction getTestMode(int mode) } */ -void NIFLoader::setOutputAnimFiles(bool output){ - mOutputAnimFiles = output; -} -void NIFLoader::setVerbosePath(std::string path){ - verbosePath = path; -} +#if 0 void NIFLoader::createMaterial(const Ogre::String &name, const Ogre::Vector3 &ambient, const Ogre::Vector3 &diffuse, @@ -211,17 +197,6 @@ void NIFLoader::createMaterial(const Ogre::String &name, Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(name, resourceGroup); - //Hardware Skinning code, textures may be the wrong color if enabled - - /* if(!mSkel.isNull()){ - material->removeAllTechniques(); - - Ogre::Technique* tech = material->createTechnique(); - //tech->setSchemeName("blahblah"); - Pass* pass = tech->createPass(); - pass->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTexture");*/ - - // This assigns the texture to this material. If the texture name is // a file name, and this file exists (in a resource directory), it // will automatically be loaded when needed. If not (such as for @@ -302,14 +277,14 @@ void NIFLoader::createMaterial(const Ogre::String &name, { bool split = Settings::Manager::getBool("split", "Shadows"); const int numsplits = 3; - for (int i = 0; i < (split ? numsplits : 1); ++i) - { + for (int i = 0; i < (split ? numsplits : 1); ++i) + { Ogre::TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState(); tu->setName("shadowMap" + Ogre::StringConverter::toString(i)); tu->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW); tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER); tu->setTextureBorderColour(Ogre::ColourValue::White); - } + } } if (Settings::Manager::getBool("shaders", "Objects")) @@ -340,1067 +315,28 @@ void NIFLoader::createMaterial(const Ogre::String &name, material->setSelfIllumination(emissive[0], emissive[1], emissive[2]); material->setShininess(glossiness); } +#endif -// Takes a name and adds a unique part to it. This is just used to -// make sure that all materials are given unique names. -Ogre::String NIFLoader::getUniqueName(const Ogre::String &input) -{ - static int addon = 0; - static char buf[8]; - snprintf(buf, 8, "_%d", addon++); - - // Don't overflow the buffer - if (addon > 999999) addon = 0; - - return input + buf; -} - -// Check if the given texture name exists in the real world. If it -// does not, change the string IN PLACE to say .dds instead and try -// that. The texture may still not exist, but no information of value -// is lost in that case. -void NIFLoader::findRealTexture(Ogre::String &texName) -{ - if(Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName)) - return; - - // Change texture extension to .dds - Ogre::String::size_type pos = texName.rfind('.'); - texName.replace(pos, texName.length(), ".dds"); -} - -//Handle node at top - -// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given -// mesh. -void NIFLoader::createOgreSubMesh(NiTriShape *shape, const Ogre::String &material, std::list &vertexBoneAssignments) -{ - // cout << "s:" << shape << "\n"; - NiTriShapeData *data = shape->data.getPtr(); - Ogre::SubMesh *sub = mesh->createSubMesh(shape->name); - - int nextBuf = 0; - - // This function is just one long stream of Ogre-barf, but it works - // great. - - // Add vertices - int numVerts = data->vertices.size() / 3; - sub->vertexData = new Ogre::VertexData(); - sub->vertexData->vertexCount = numVerts; - sub->useSharedVertices = false; - - Ogre::VertexDeclaration *decl = sub->vertexData->vertexDeclaration; - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - - Ogre::HardwareVertexBufferSharedPtr vbuf = - Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - numVerts, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false); - - if(flip) - { - float *datamod = new float[data->vertices.size()]; - //std::cout << "Shape" << shape->name.toString() << "\n"; - for(int i = 0; i < numVerts; i++) - { - int index = i * 3; - const float *pos = &data->vertices[index]; - Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); - original = mTransform * original; - mBoundingBox.merge(original); - datamod[index] = original.x; - datamod[index+1] = original.y; - datamod[index+2] = original.z; - } - vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); - delete [] datamod; - } - else - { - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->vertices[0], false); - } - - - Ogre::VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; - bind->setBinding(nextBuf++, vbuf); - - if (data->normals.size()) - { - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - - if(flip) - { - Ogre::Quaternion rotation = mTransform.extractQuaternion(); - rotation.normalise(); - - float *datamod = new float[data->normals.size()]; - for(int i = 0; i < numVerts; i++) - { - int index = i * 3; - const float *pos = &data->normals[index]; - Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); - original = rotation * original; - if (mNormaliseNormals) - { - original.normalise(); - } - - - datamod[index] = original.x; - datamod[index+1] = original.y; - datamod[index+2] = original.z; - } - vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); - delete [] datamod; - } - else - { - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->normals[0], false); - } - bind->setBinding(nextBuf++, vbuf); - } - - - // Vertex colors - if (data->colors.size()) - { - const float *colors = &data->colors[0]; - Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); - std::vector colorsRGB(numVerts); - Ogre::RGBA *pColour = &colorsRGB.front(); - for (int i=0; iconvertColourValue(Ogre::ColourValue(colors[0],colors[1],colors[2], - colors[3]),pColour++); - colors += 4; - } - decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); - vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), - numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true); - bind->setBinding(nextBuf++, vbuf); - } - - if (data->uvlist.size()) - { - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); - vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( - Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2), - numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,false); - - if(flip) - { - float *datamod = new float[data->uvlist.size()]; - - for(unsigned int i = 0; i < data->uvlist.size(); i+=2){ - float x = data->uvlist[i]; - - float y = data->uvlist[i + 1]; - - datamod[i] =x; - datamod[i + 1] =y; - } - vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); - delete [] datamod; - } - else - vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[0], false); - bind->setBinding(nextBuf++, vbuf); - } - - // Triangle faces - The total number of triangle points - int numFaces = data->triangles.size(); - if (numFaces) - { - - sub->indexData->indexCount = numFaces; - sub->indexData->indexStart = 0; - Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton(). - createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, numFaces, - Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); - - if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){ - - sub->indexData->indexBuffer = ibuf; - - uint16_t *datamod = new uint16_t[numFaces]; - int index = 0; - for (size_t i = 0; i < sub->indexData->indexCount; i+=3) - { - - const short *pos = &data->triangles[index]; - uint16_t i0 = (uint16_t) *(pos+0); - uint16_t i1 = (uint16_t) *(pos+1); - uint16_t i2 = (uint16_t) *(pos+2); - - //std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n"; - - - datamod[index] = i2; - datamod[index+1] = i1; - datamod[index+2] = i0; - - index += 3; - } - - ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false); - delete [] datamod; - - } - else - ibuf->writeData(0, ibuf->getSizeInBytes(), &data->triangles[0], false); - sub->indexData->indexBuffer = ibuf; - } - - // Set material if one was given - if (!material.empty()) sub->setMaterialName(material); - - //add vertex bone assignments - - for (std::list::iterator it = vertexBoneAssignments.begin(); - it != vertexBoneAssignments.end(); it++) - { - sub->addBoneAssignment(*it); - } - if(mSkel.isNull()) - needBoneAssignments.push_back(sub); -} - -// Helper math functions. Reinventing linear algebra for the win! - -// Computes C = B + AxC*scale -static void vectorMulAdd(const Ogre::Matrix3 &A, const Ogre::Vector3 &B, float *C, float scale) -{ - // Keep the original values - float a = C[0]; - float b = C[1]; - float c = C[2]; - - // Perform matrix multiplication, scaling and addition - for (int i=0;i<3;i++) - C[i] = B[i] + (a*A[i][0] + b*A[i][1] + c*A[i][2])*scale; -} - -// Computes B = AxB (matrix*vector) -static void vectorMul(const Ogre::Matrix3 &A, float *C) -{ - // Keep the original values - float a = C[0]; - float b = C[1]; - float c = C[2]; - - // Perform matrix multiplication, scaling and addition - for (int i=0;i<3;i++) - C[i] = a*A[i][0] + b*A[i][1] + c*A[i][2]; -} - - -void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds, Transformation original, std::vector boneSequence) -{ - assert(shape != NULL); - - bool saveTheShape = inTheSkeletonTree; - // Interpret flags - bool hidden = (flags & 0x01) != 0; // Not displayed - bool collide = (flags & 0x02) != 0; // Use mesh for collision - bool bbcollide = (flags & 0x04) != 0; // Use bounding box for collision - - // Bounding box collision isn't implemented, always use mesh for now. - if (bbcollide) - { - collide = true; - bbcollide = false; - } - - // If the object was marked "NCO" earlier, it shouldn't collide with - // anything. - if (flags & 0x800) - { - collide = false; - bbcollide = false; - } - - if (!collide && !bbcollide && hidden) - // This mesh apparently isn't being used for anything, so don't - // bother setting it up. - return; - - // Material name for this submesh, if any - Ogre::String material; - - // Skip the entire material phase for hidden nodes - if (!hidden) - { - // These are set below if present - NiTexturingProperty *t = NULL; - NiMaterialProperty *m = NULL; - NiAlphaProperty *a = NULL; - - // Scan the property list for material information - PropertyList &list = shape->props; - int n = list.length(); - for (int i=0; irecType == RC_NiTexturingProperty) - t = static_cast(pr); - else if (pr->recType == RC_NiMaterialProperty) - m = static_cast(pr); - else if (pr->recType == RC_NiAlphaProperty) - a = static_cast(pr); - } - - // Texture - Ogre::String texName; - if (t && t->textures[0].inUse) - { - NiSourceTexture *st = t->textures[0].texture.getPtr(); - if (st->external) - { - /* findRealTexture checks if the file actually - exists. If it doesn't, and the name ends in .tga, it - will try replacing the extension with .dds instead - and search for that. Bethesda at some at some point - converted all their BSA textures from tga to dds for - increased load speed, but all texture file name - references were kept as .tga. - - The function replaces the name in place (that's why - we cast away the const modifier), but this is no - problem since all the nif data is stored in a local - throwaway buffer. - */ - texName = "textures\\" + st->filename; - findRealTexture(texName); - } - else warn("Found internal texture, ignoring."); - } - - // Alpha modifiers - int alphaFlags = -1; - ubyte alphaTest = 0; - if (a) - { - alphaFlags = a->flags; - alphaTest = a->data.threshold; - } - - // Material - if (m || !texName.empty()) - { - // If we're here, then this mesh has a material. Thus we - // need to calculate a snappy material name. It should - // contain the mesh name (mesh->getName()) but also has to - // be unique. One mesh may use many materials. - material = getUniqueName(mesh->getName()); - - if (m) - { - // Use NiMaterialProperty data to create the data - const S_MaterialProperty *d = &m->data; - - std::multimap::iterator itr = MaterialMap.find(texName); - std::multimap::iterator lastElement; - lastElement = MaterialMap.upper_bound(texName); - if (itr != MaterialMap.end()) - { - for ( ; itr != lastElement; ++itr) - { - //std::cout << "OK!"; - //MaterialPtr mat = MaterialManager::getSingleton().getByName(itr->second,recourceGroup); - material = itr->second; - //if( mat->getA - } - } - else - { - //std::cout << "new"; - createMaterial(material, d->ambient, d->diffuse, d->specular, d->emissive, - d->glossiness, d->alpha, alphaFlags, alphaTest, texName); - MaterialMap.insert(std::make_pair(texName,material)); - } - } - else - { - // We only have a texture name. Create a default - // material for it. - const Ogre::Vector3 zero(0.0f), one(1.0f); - createMaterial(material, one, one, zero, zero, 0.0f, 1.0f, - alphaFlags, alphaTest, texName); - } - } - } // End of material block, if(!hidden) ... - - /* Do in-place transformation of all the vertices and normals. This - is pretty messy stuff, but we need it to make the sub-meshes - appear in the correct place. Neither Ogre nor Bullet support - nested levels of sub-meshes with transformations applied to each - level. - */ - NiTriShapeData *data = shape->data.getPtr(); - int numVerts = data->vertices.size() / 3; - - float *ptr = (float*)&data->vertices[0]; - float *optr = ptr; - - std::list vertexBoneAssignments; - - Nif::NiTriShapeCopy copy = shape->clone(); - - if(!shape->controller.empty()) - { - Nif::Controller* cont = shape->controller.getPtr(); - if(cont->recType == RC_NiGeomMorpherController) - { - Nif::NiGeomMorpherController* morph = dynamic_cast (cont); - copy.morph = morph->data.get(); - copy.morph.setStartTime(morph->timeStart); - copy.morph.setStopTime(morph->timeStop); - saveTheShape = true; - } - - } - //use niskindata for the position of vertices. - if (!shape->skin.empty()) - { - - - - // vector that stores if the position of a vertex is absolute - std::vector vertexPosAbsolut(numVerts,false); - std::vector vertexPosOriginal(numVerts, Ogre::Vector3::ZERO); - std::vector vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO); - - float *ptrNormals = (float*)&data->normals[0]; - //the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex] - //the first one contains a link to the bone, the second vertex transformation - //relative to the bone - int boneIndex = 0; - Ogre::Bone *bonePtr; - Ogre::Vector3 vecPos; - Ogre::Quaternion vecRot; - - std::vector boneList = shape->skin->data->bones; - - /* - Iterate through the boneList which contains what vertices are linked to - the bone (it->weights array) and at what position (it->trafo) - That position is added to every vertex. - */ - for (std::vector::iterator it = boneList.begin(); - it != boneList.end(); it++) - { - if(mSkel.isNull()) - { - std::cout << "No skeleton for :" << shape->skin->bones[boneIndex]->name << std::endl; - break; - } - //get the bone from bones array of skindata - if(!mSkel->hasBone(shape->skin->bones[boneIndex]->name)) - std::cout << "We don't have this bone"; - bonePtr = mSkel->getBone(shape->skin->bones[boneIndex]->name); - - // final_vector = old_vector + old_rotation*new_vector*old_scale - - - Nif::NiSkinData::BoneInfoCopy boneinfocopy; - boneinfocopy.trafo.rotation = it->trafo.rotation; - boneinfocopy.trafo.trans = it->trafo.trans; - boneinfocopy.bonename = shape->skin->bones[boneIndex]->name; - boneinfocopy.bonehandle = bonePtr->getHandle(); - copy.boneinfo.push_back(boneinfocopy); - for (unsigned int i=0; iweights.size(); i++) - { - vecPos = bonePtr->_getDerivedPosition() + - bonePtr->_getDerivedOrientation() * it->trafo.trans; - - vecRot = bonePtr->_getDerivedOrientation() * it->trafo.rotation; - unsigned int verIndex = it->weights[i].vertex; - //boneinfo.weights.push_back(*(it->weights.ptr + i)); - Nif::NiSkinData::IndividualWeight ind; - ind.weight = it->weights[i].weight; - ind.boneinfocopyindex = copy.boneinfo.size() - 1; - if(copy.vertsToWeights.find(verIndex) == copy.vertsToWeights.end()) - { - std::vector blank; - blank.push_back(ind); - copy.vertsToWeights[verIndex] = blank; - } - else - { - copy.vertsToWeights[verIndex].push_back(ind); - } - - //Check if the vertex is relativ, FIXME: Is there a better solution? - if (vertexPosAbsolut[verIndex] == false) - { - //apply transformation to the vertices - Ogre::Vector3 absVertPos = vecPos + vecRot * Ogre::Vector3(ptr + verIndex *3); - absVertPos = absVertPos * it->weights[i].weight; - vertexPosOriginal[verIndex] = Ogre::Vector3(ptr + verIndex *3); - - mBoundingBox.merge(absVertPos); - //convert it back to float * - for (int j=0; j<3; j++) - (ptr + verIndex*3)[j] = absVertPos[j]; - - //apply rotation to the normals (not every vertex has a normal) - //FIXME: I guessed that vertex[i] = normal[i], is that true? - if (verIndex < data->normals.size()) - { - Ogre::Vector3 absNormalsPos = vecRot * Ogre::Vector3(ptrNormals + verIndex *3); - absNormalsPos = absNormalsPos * it->weights[i].weight; - vertexNormalOriginal[verIndex] = Ogre::Vector3(ptrNormals + verIndex *3); - - for (int j=0; j<3; j++) - (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; - } - - vertexPosAbsolut[verIndex] = true; - } - else - { - Ogre::Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex]; - absVertPos = absVertPos * it->weights[i].weight; - Ogre::Vector3 old = Ogre::Vector3(ptr + verIndex *3); - absVertPos = absVertPos + old; - - mBoundingBox.merge(absVertPos); - //convert it back to float * - for (int j=0; j<3; j++) - (ptr + verIndex*3)[j] = absVertPos[j]; - - //apply rotation to the normals (not every vertex has a normal) - //FIXME: I guessed that vertex[i] = normal[i], is that true? - if (verIndex < data->normals.size()) - { - Ogre::Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex]; - absNormalsPos = absNormalsPos * it->weights[i].weight; - Ogre::Vector3 oldNormal = Ogre::Vector3(ptrNormals + verIndex *3); - absNormalsPos = absNormalsPos + oldNormal; - - for (int j=0; j<3; j++) - (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; - } - } - - - Ogre::VertexBoneAssignment vba; - vba.boneIndex = bonePtr->getHandle(); - vba.vertexIndex = verIndex; - vba.weight = it->weights[i].weight; - - - vertexBoneAssignments.push_back(vba); - } - - - boneIndex++; - } - - - } - else - { - - copy.boneSequence = boneSequence; - // Rotate, scale and translate all the vertices, - const Ogre::Matrix3 &rot = shape->trafo.rotation; - const Ogre::Vector3 &pos = shape->trafo.pos; - float scale = shape->trafo.scale; - - copy.trafo.trans = original.pos; - copy.trafo.rotation = original.rotation; - copy.trafo.scale = original.scale; - //We don't use velocity for anything yet, so it does not need to be saved - - // Computes C = B + AxC*scale - for (int i=0; inormals.size()) - { - ptr = (float*)&data->normals[0]; - for (int i=0; igetNumBones() - 1; - for(int i = 0; i < numVerts; i++){ - Ogre::VertexBoneAssignment vba; - vba.boneIndex = boneIndex; - vba.vertexIndex = i; - vba.weight = 1; - vertexBoneAssignments.push_back(vba); - } - } - } - - if (!hidden) - { - // Add this vertex set to the bounding box - bounds.add(optr, numVerts); - if(saveTheShape) - shapes.push_back(copy); - - // Create the submesh - createOgreSubMesh(shape, material, vertexBoneAssignments); - } -} - -void NIFLoader::calculateTransform() -{ - // Calculate transform - Ogre::Matrix4 transform = Ogre::Matrix4::IDENTITY; - transform = Ogre::Matrix4::getScale(vector) * transform; - - // Check whether we have to flip vertex winding. - // We do have to, if we changed our right hand base. - // We can test it by using the cross product from X and Y and see, if it is a non-negative - // projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet, - // but the test is cheap either way. - Ogre::Matrix3 m3; - transform.extract3x3Matrix(m3); - - if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0) - { - mFlipVertexWinding = true; - } - - mTransform = transform; -} -void NIFLoader::handleNode(Nif::Node *node, int flags, - const Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence) -{ - // Accumulate the flags from all the child nodes. This works for all - // the flags we currently use, at least. - flags |= node->flags; - - // Check for extra data - Extra *e = node; - while (!e->extra.empty()) - { - // Get the next extra data in the list - e = e->extra.getPtr(); - assert(e != NULL); - - if (e->recType == RC_NiStringExtraData) - { - // String markers may contain important information - // affecting the entire subtree of this node - NiStringExtraData *sd = (NiStringExtraData*)e; - - if (sd->string == "NCO") - // No collision. Use an internal flag setting to mark this. - flags |= 0x800; - else if (sd->string == "MRK") - // Marker objects. These are only visible in the - // editor. Until and unless we add an editor component to - // the engine, just skip this entire node. - return; - } - - if (e->recType == RC_NiTextKeyExtraData){ - Nif::NiTextKeyExtraData* extra = dynamic_cast (e); - - std::ofstream file; - - if(mOutputAnimFiles){ - std::string cut = ""; - for(unsigned int i = 0; i < name.length(); i++) - { - if(!(name.at(i) == '\\' || name.at(i) == '/' || name.at(i) == '>' || name.at(i) == '<' || name.at(i) == '?' || name.at(i) == '*' || name.at(i) == '|' || name.at(i) == ':' || name.at(i) == '"')) - { - cut += name.at(i); - } - } - - std::cout << "Outputting " << cut << "\n"; - - file.open((verbosePath + "/Indices" + cut + ".txt").c_str()); - } - - for(std::vector::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++) - { - std::string text = textiter->text; - - replace(text.begin(), text.end(), '\n', '/'); - - text.erase(std::remove(text.begin(), text.end(), '\r'), text.end()); - std::size_t i = 0; - while(i < text.length()){ - while(i < text.length() && text.at(i) == '/' ){ - i++; - } - std::size_t first = i; - int length = 0; - while(i < text.length() && text.at(i) != '/' ){ - i++; - length++; - } - if(first < text.length()){ - //length = text.length() - first; - std::string sub = text.substr(first, length); - - if(mOutputAnimFiles) - file << "Time: " << textiter->time << "|" << sub << "\n"; - - textmappings[sub] = textiter->time; - } - } - } - file.close(); - } - } - - Ogre::Bone *bone = 0; - - // create skeleton or add bones - if (node->recType == RC_NiNode) - { - //FIXME: "Bip01" isn't every time the root bone - if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton - { - inTheSkeletonTree = true; - - mSkel = Ogre::SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true); - } - else if (!mSkel.isNull() && !parentBone) - inTheSkeletonTree = false; - - if (!mSkel.isNull()) //if there is a skeleton - { - std::string name = node->name; - - // Quick-n-dirty workaround for the fact that several - // bones may have the same name. - if(!mSkel->hasBone(name)) - { - boneSequence.push_back(name); - bone = mSkel->createBone(name); - - if (parentBone) - parentBone->addChild(bone); - - bone->setInheritOrientation(true); - bone->setPosition(node->trafo.pos); - bone->setOrientation(node->trafo.rotation); - } - } - } - Transformation original = node->trafo; - // Apply the parent transformation to this node. We overwrite the - // existing data with the final transformation. - if (trafo) - { - // Get a non-const reference to the node's data, since we're - // overwriting it. TODO: Is this necessary? - Transformation &final = node->trafo; - - // For both position and rotation we have that: - // final_vector = old_vector + old_rotation*new_vector*old_scale - final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale; - - // Merge the rotations together - final.rotation = trafo->rotation * final.rotation; - - // Scale - final.scale *= trafo->scale; - } - - // For NiNodes, loop through children - if (node->recType == RC_NiNode) - { - NodeList &list = ((NiNode*)node)->children; - int n = list.length(); - for (int i = 0; itrafo, bounds, bone, boneSequence); - } - } - else if (node->recType == RC_NiTriShape && bNiTri) - { - std::string nodename = node->name; - - if (triname == "") - { - handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); - } - else if(nodename.length() >= triname.length()) - { - std::transform(nodename.begin(), nodename.end(), nodename.begin(), ::tolower); - if(triname == nodename.substr(0, triname.length())) - handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); - } - } -} void NIFLoader::loadResource(Ogre::Resource *resource) { - inTheSkeletonTree = false; - allanim.clear(); - shapes.clear(); - needBoneAssignments.clear(); - // needBoneAssignments.clear(); - mBoundingBox.setNull(); - mesh = 0; - mSkel.setNull(); - flip = false; - name = resource->getName(); - char suffix = name.at(name.length() - 2); - bool addAnim = true; - bool hasAnim = false; - bool linkSkeleton = true; - //bool baddin = false; - bNiTri = true; - if(name == "meshes\\base_anim.nif" || name == "meshes\\base_animkna.nif") - { - bNiTri = false; - } - - if(suffix == '*') - { - vector = Ogre::Vector3(-1,1,1); - flip = true; - } - else if(suffix == '?'){ - vector = Ogre::Vector3(1,-1,1); - flip = true; - } - else if(suffix == '<'){ - vector = Ogre::Vector3(1,1,-1); - flip = true; - } - else if(suffix == '>') - { - //baddin = true; - bNiTri = true; - std::string sub = name.substr(name.length() - 6, 4); - - if(sub.compare("0000") != 0) - addAnim = false; - - } - else if(suffix == ':') - { - //baddin = true; - linkSkeleton = false; - bNiTri = true; - std::string sub = name.substr(name.length() - 6, 4); - - if(sub.compare("0000") != 0) - addAnim = false; - - } - - switch(name.at(name.length() - 1)) - { - case '"': - triname = "tri chest"; - break; - case '*': - triname = "tri tail"; - break; - case ':': - triname = "tri left foot"; - break; - case '<': - triname = "tri right foot"; - break; - case '>': - triname = "tri left hand"; - break; - case '?': - triname = "tri right hand"; - break; - default: - triname = ""; - break; - } - if(flip) - { - calculateTransform(); - } - // Get the mesh - mesh = dynamic_cast(resource); - assert(mesh); - - // Look it up - resourceName = mesh->getName(); - - - // Helper that computes bounding boxes for us. - BoundsFinder bounds; - - // Load the NIF. TODO: Wrap this in a try-catch block once we're out - // of the early stages of development. Right now we WANT to catch - // every error as early and intrusively as possible, as it's most - // likely a sign of incomplete code rather than faulty input. - NIFFile nif(resourceName); - if (nif.numRecords() < 1) - { - warn("Found no records in NIF."); - return; - } - - // The first record is assumed to be the root node - Record *r = nif.getRecord(0); - assert(r != NULL); - - Nif::Node *node = dynamic_cast(r); - - if (node == NULL) - { - warn("First record in file was not a node, but a " + - r->recName + ". Skipping file."); - return; - } - - // Handle the node - std::vector boneSequence; - - - - handleNode(node, 0, NULL, bounds, 0, boneSequence); - if(addAnim) - { - for(int i = 0; i < nif.numRecords(); i++) - { - Nif::NiKeyframeController *f = dynamic_cast(nif.getRecord(i)); - - if(f != NULL) - { - hasAnim = true; - Nif::Node *o = dynamic_cast(f->target.getPtr()); - Nif::NiKeyframeDataPtr data = f->data; - - if (f->timeStart >= 10000000000000000.0f) - continue; - data->setBonename(o->name); - data->setStartTime(f->timeStart); - data->setStopTime(f->timeStop); - - allanim.push_back(data.get()); - } - } - } - // set the bounding value. - if (bounds.isValid()) - { - mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX(), bounds.minY(), bounds.minZ(), - bounds.maxX(), bounds.maxY(), bounds.maxZ())); - mesh->_setBoundingSphereRadius(bounds.getRadius()); - } - if(hasAnim && addAnim){ - allanimmap[name] = allanim; - alltextmappings[name] = textmappings; - } - if(!mSkel.isNull() && shapes.size() > 0 && addAnim) - { - allshapesmap[name] = shapes; - - } - - if(flip){ - mesh->_setBounds(mBoundingBox, false); - } - - if (!mSkel.isNull() ) - { - for(std::vector::iterator iter = needBoneAssignments.begin(); iter != needBoneAssignments.end(); iter++) - { - int boneIndex = mSkel->getNumBones() - 1; - Ogre::VertexBoneAssignment vba; - vba.boneIndex = boneIndex; - vba.vertexIndex = 0; - vba.weight = 1; - - - (*iter)->addBoneAssignment(vba); - } - //Don't link on npc parts to eliminate redundant skeletons - //Will have to be changed later slightly for robes/skirts - if(linkSkeleton) - mesh->_notifySkeleton(mSkel); - } + warn("Found no records in NIF."); } - - - - Ogre::MeshPtr NIFLoader::load(const std::string &name, const std::string &group) { + Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - Ogre::MeshManager *m = Ogre::MeshManager::getSingletonPtr(); // Check if the resource already exists - Ogre::ResourcePtr ptr = m->getByName(name, group); - Ogre::MeshPtr themesh; - if (!ptr.isNull()){ - themesh = Ogre::MeshPtr(ptr); - } - else // Nope, create a new one. + Ogre::MeshPtr themesh = meshMgr.getByName(name, group); + if(themesh.isNull()) { - themesh = Ogre::MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr()); + static NIFLoader loader; + themesh = meshMgr.createManual(name, group, &loader); } return themesh; } -/* -This function shares much of the same code handleShapes() in MWRender::Animation -This function also creates new position and normal buffers for submeshes. -This function points to existing texture and IndexData buffers -*/ - -std::vector* NIFLoader::getAnim(std::string lowername){ - - std::map,ciLessBoost>::iterator iter = allanimmap.find(lowername); - std::vector* pass = 0; - if(iter != allanimmap.end()) - pass = &(iter->second); - return pass; - -} -std::vector* NIFLoader::getShapes(std::string lowername){ - - std::map,ciLessBoost>::iterator iter = allshapesmap.find(lowername); - std::vector* pass = 0; - if(iter != allshapesmap.end()) - pass = &(iter->second); - return pass; -} - -std::map* NIFLoader::getTextIndices(std::string lowername){ - std::map, ciLessBoost>::iterator iter = alltextmappings.find(lowername); - std::map* pass = 0; - if(iter != alltextmappings.end()) - pass = &(iter->second); - return pass; -} - - - /* More code currently not in use, from the old D source. This was used in the first attempt at loading NIF meshes, where each submesh diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 64efc70c7..bc1ef304c 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -67,12 +67,9 @@ namespace Nif namespace NifOgre { - - /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into - something Ogre can use. Later it will also handle the insertion of - collision meshes into Bullet / OgreBullet. + something Ogre can use. You have to insert meshes manually into Ogre like this: @@ -86,93 +83,18 @@ namespace NifOgre */ class NIFLoader : Ogre::ManualResourceLoader { - public: - static int numberOfMeshes; - static NIFLoader& getSingleton(); - static NIFLoader* getSingletonPtr(); - - virtual void loadResource(Ogre::Resource *resource); - - static Ogre::MeshPtr load(const std::string &name, - const std::string &group="General"); - //void insertMeshInsideBase(Ogre::Mesh* mesh); - std::vector* getAnim(std::string name); - std::vector* getShapes(std::string name); - std::map* getTextIndices(std::string name); - - - void setOutputAnimFiles(bool output); - void setVerbosePath(std::string path); - - private: - - NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false), - mFlipVertexWinding(false), mOutputAnimFiles(false), inTheSkeletonTree(false) {} - NIFLoader(NIFLoader& n) {} - - void calculateTransform(); - - - void warn(std::string msg); - void fail(std::string msg); - - void handleNode( Nif::Node *node, int flags, - const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence); - - void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds, Nif::Transformation original, std::vector boneSequence); - - void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list &vertexBoneAssignments); - - void createMaterial(const Ogre::String &name, - const Ogre::Vector3 &ambient, - const Ogre::Vector3 &diffuse, - const Ogre::Vector3 &specular, - const Ogre::Vector3 &emissive, - float glossiness, float alpha, - int alphaFlags, float alphaTest, - const Ogre::String &texName); - - void findRealTexture(Ogre::String &texName); - - Ogre::String getUniqueName(const Ogre::String &input); - - //returns the skeleton name of this mesh - std::string getSkeletonName() - { - return resourceName + ".skel"; - } - - std::string verbosePath; - std::string resourceName; - std::string resourceGroup; - Ogre::Matrix4 mTransform; - Ogre::AxisAlignedBox mBoundingBox; - bool flip; - bool mNormaliseNormals; - bool mFlipVertexWinding; - bool bNiTri; - bool mOutputAnimFiles; - std::multimap MaterialMap; - - // pointer to the ogre mesh which is currently build - Ogre::Mesh *mesh; - Ogre::SkeletonPtr mSkel; - Ogre::Vector3 vector; - std::vector shapes; - std::string name; - std::string triname; - std::vector allanim; +public: + virtual void loadResource(Ogre::Resource *resource); - std::map textmappings; - std::map,ciLessBoost> alltextmappings; - std::map,ciLessBoost> allanimmap; - std::map,ciLessBoost> allshapesmap; - std::vector mAnim; - std::vector mS; - std::vector needBoneAssignments; - bool inTheSkeletonTree; + static Ogre::MeshPtr load(const std::string &name, + const std::string &group="General"); +private: + NIFLoader() {} + NIFLoader(NIFLoader& n) {} + void warn(const std::string &msg); + void fail(const std::string &msg); }; } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 11c18010e..61d0c7b0e 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -336,7 +336,7 @@ namespace Physic char uniqueID[8]; sprintf( uniqueID, "%07.3f", scale ); std::string sid = uniqueID; - std::string outputstring = mesh + uniqueID + "\"|"; + std::string outputstring = mesh + uniqueID; //std::cout << "The string" << outputstring << "\n"; //get the shape from the .nif