forked from teamnwah/openmw-tes3coop
Merge branch 'master' into shadersystem
This commit is contained in:
commit
06bd2cd919
23 changed files with 1742 additions and 3056 deletions
|
@ -186,6 +186,9 @@ if (UNIX AND NOT APPLE)
|
|||
find_package (Threads)
|
||||
endif()
|
||||
|
||||
# find boost without components so we can use Boost_VERSION
|
||||
find_package(Boost REQUIRED)
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread)
|
||||
|
||||
if (Boost_VERSION LESS 104900)
|
||||
|
|
|
@ -56,11 +56,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)
|
||||
|
|
|
@ -122,15 +122,13 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store){
|
|||
|
||||
void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){
|
||||
if(mAllActors.find(ptr) != mAllActors.end())
|
||||
mAllActors[ptr]->startScript(groupName, mode, number);
|
||||
mAllActors[ptr]->playGroup(groupName, mode, number);
|
||||
}
|
||||
void Actors::skipAnimation (const MWWorld::Ptr& ptr){
|
||||
if(mAllActors.find(ptr) != mAllActors.end())
|
||||
mAllActors[ptr]->stopScript();
|
||||
mAllActors[ptr]->skipAnim();
|
||||
}
|
||||
void Actors::update (float duration){
|
||||
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++)
|
||||
{
|
||||
(iter->second)->runAnimation(duration);
|
||||
}
|
||||
iter->second->runAnimation(duration);
|
||||
}
|
||||
|
|
|
@ -5,498 +5,171 @@
|
|||
#include <OgreEntity.h>
|
||||
#include <OgreBone.h>
|
||||
#include <OgreSubMesh.h>
|
||||
#include <OgreSceneManager.h>
|
||||
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
std::map<std::string, int> Animation::sUniqueIDs;
|
||||
|
||||
Animation::Animation(OEngine::Render::OgreRenderer& _rend)
|
||||
: mInsert(NULL)
|
||||
, mRend(_rend)
|
||||
, mVecRotPos()
|
||||
, mTime(0.0f)
|
||||
, mStartTime(0.0f)
|
||||
, mStopTime(0.0f)
|
||||
, mAnimate(0)
|
||||
, mRindexI()
|
||||
, mTindexI()
|
||||
, mShapeNumber(0)
|
||||
, mShapeIndexI()
|
||||
, mShapes(NULL)
|
||||
, mTransformations(NULL)
|
||||
, mTextmappings(NULL)
|
||||
, mBase(NULL)
|
||||
Animation::Animation(OEngine::Render::OgreRenderer& _rend)
|
||||
: mInsert(NULL)
|
||||
, mRend(_rend)
|
||||
, mTime(0.0f)
|
||||
, mSkipFrame(false)
|
||||
{
|
||||
}
|
||||
|
||||
Animation::~Animation()
|
||||
{
|
||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
||||
for(size_t i = 0;i < mEntityList.mEntities.size();i++)
|
||||
sceneMgr->destroyEntity(mEntityList.mEntities[i]);
|
||||
mEntityList.mEntities.clear();
|
||||
}
|
||||
|
||||
|
||||
struct checklow {
|
||||
bool operator()(const char &a, const char &b) const
|
||||
{
|
||||
return ::tolower(a) == ::tolower(b);
|
||||
}
|
||||
};
|
||||
|
||||
Animation::~Animation()
|
||||
bool Animation::findGroupTimes(const std::string &groupname, Animation::GroupTimes *times)
|
||||
{
|
||||
const std::string &start = groupname+": start";
|
||||
const std::string &startloop = groupname+": loop start";
|
||||
const std::string &stop = groupname+": stop";
|
||||
const std::string &stoploop = groupname+": loop stop";
|
||||
|
||||
NifOgre::TextKeyMap::const_iterator iter;
|
||||
for(iter = mTextKeys.begin();iter != mTextKeys.end();iter++)
|
||||
{
|
||||
}
|
||||
if(times->mStart >= 0.0f && times->mLoopStart >= 0.0f && times->mLoopStop >= 0.0f && times->mStop >= 0.0f)
|
||||
return true;
|
||||
|
||||
std::string Animation::getUniqueID(std::string mesh)
|
||||
{
|
||||
int counter;
|
||||
std::string copy = mesh;
|
||||
std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
|
||||
std::string::const_iterator strpos = iter->second.begin();
|
||||
std::string::const_iterator strend = iter->second.end();
|
||||
|
||||
if(sUniqueIDs.find(copy) == sUniqueIDs.end())
|
||||
while(strpos != strend)
|
||||
{
|
||||
counter = sUniqueIDs[copy] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sUniqueIDs[copy] = sUniqueIDs[copy] + 1;
|
||||
counter = sUniqueIDs[copy];
|
||||
}
|
||||
size_t strlen = strend-strpos;
|
||||
std::string::const_iterator striter;
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
if(counter > 99 && counter < 1000)
|
||||
out << "0";
|
||||
else if(counter > 9)
|
||||
out << "00";
|
||||
else
|
||||
out << "000";
|
||||
out << counter;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
void Animation::startScript(std::string groupname, int mode, int loops)
|
||||
{
|
||||
//If groupname is recognized set animate to true
|
||||
//Set the start time and stop time
|
||||
//How many times to loop
|
||||
if(groupname == "all")
|
||||
{
|
||||
mAnimate = loops;
|
||||
mTime = mStartTime;
|
||||
}
|
||||
else if(mTextmappings)
|
||||
{
|
||||
|
||||
std::string startName = groupname + ": loop start";
|
||||
std::string stopName = groupname + ": loop stop";
|
||||
|
||||
bool first = false;
|
||||
|
||||
if(loops > 1)
|
||||
if(start.size() <= strlen &&
|
||||
((striter=std::mismatch(strpos, strend, start.begin(), checklow()).first) == strend ||
|
||||
*striter == '\r' || *striter == '\n'))
|
||||
{
|
||||
startName = groupname + ": loop start";
|
||||
stopName = groupname + ": loop stop";
|
||||
|
||||
for(std::map<std::string, float>::iterator iter = mTextmappings->begin(); iter != mTextmappings->end(); iter++)
|
||||
{
|
||||
|
||||
std::string current = iter->first.substr(0, startName.size());
|
||||
std::transform(current.begin(), current.end(), current.begin(), ::tolower);
|
||||
std::string current2 = iter->first.substr(0, stopName.size());
|
||||
std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower);
|
||||
|
||||
if(current == startName)
|
||||
{
|
||||
mStartTime = iter->second;
|
||||
mAnimate = loops;
|
||||
mTime = mStartTime;
|
||||
first = true;
|
||||
}
|
||||
if(current2 == stopName)
|
||||
{
|
||||
mStopTime = iter->second;
|
||||
if(first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
times->mStart = iter->first;
|
||||
times->mLoopStart = iter->first;
|
||||
}
|
||||
if(!first)
|
||||
else if(startloop.size() <= strlen &&
|
||||
((striter=std::mismatch(strpos, strend, startloop.begin(), checklow()).first) == strend ||
|
||||
*striter == '\r' || *striter == '\n'))
|
||||
{
|
||||
startName = groupname + ": start";
|
||||
stopName = groupname + ": stop";
|
||||
|
||||
for(std::map<std::string, float>::iterator iter = mTextmappings->begin(); iter != mTextmappings->end(); iter++)
|
||||
{
|
||||
|
||||
std::string current = iter->first.substr(0, startName.size());
|
||||
std::transform(current.begin(), current.end(), current.begin(), ::tolower);
|
||||
std::string current2 = iter->first.substr(0, stopName.size());
|
||||
std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower);
|
||||
|
||||
if(current == startName)
|
||||
{
|
||||
mStartTime = iter->second;
|
||||
mAnimate = loops;
|
||||
mTime = mStartTime;
|
||||
first = true;
|
||||
}
|
||||
if(current2 == stopName)
|
||||
{
|
||||
mStopTime = iter->second;
|
||||
if(first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
times->mLoopStart = iter->first;
|
||||
}
|
||||
else if(stoploop.size() <= strlen &&
|
||||
((striter=std::mismatch(strpos, strend, stoploop.begin(), checklow()).first) == strend ||
|
||||
*striter == '\r' || *striter == '\n'))
|
||||
{
|
||||
times->mLoopStop = iter->first;
|
||||
}
|
||||
else if(stop.size() <= strlen &&
|
||||
((striter=std::mismatch(strpos, strend, stop.begin(), checklow()).first) == strend ||
|
||||
*striter == '\r' || *striter == '\n'))
|
||||
{
|
||||
times->mStop = iter->first;
|
||||
if(times->mLoopStop < 0.0f)
|
||||
times->mLoopStop = iter->first;
|
||||
break;
|
||||
}
|
||||
|
||||
strpos = std::find(strpos+1, strend, '\n');
|
||||
while(strpos != strend && *strpos == '\n')
|
||||
strpos++;
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::stopScript()
|
||||
return (times->mStart >= 0.0f && times->mLoopStart >= 0.0f && times->mLoopStop >= 0.0f && times->mStop >= 0.0f);
|
||||
}
|
||||
|
||||
|
||||
void Animation::playGroup(std::string groupname, int mode, int loops)
|
||||
{
|
||||
GroupTimes times;
|
||||
times.mLoops = loops;
|
||||
|
||||
if(groupname == "all")
|
||||
{
|
||||
mAnimate = 0;
|
||||
}
|
||||
times.mStart = times.mLoopStart = 0.0f;
|
||||
times.mLoopStop = times.mStop = 0.0f;
|
||||
|
||||
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel)
|
||||
{
|
||||
mShapeNumber = 0;
|
||||
|
||||
if (allshapes == NULL || creaturemodel == NULL || skel == NULL)
|
||||
return;
|
||||
|
||||
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
|
||||
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)
|
||||
if(mEntityList.mSkelBase)
|
||||
{
|
||||
//std::map<unsigned short, PosAndRot> vecPosRot;
|
||||
|
||||
Nif::NiTriShapeCopy& copy = *allshapesiter;
|
||||
std::vector<Ogre::Vector3>* allvertices = ©.vertices;
|
||||
|
||||
//std::set<unsigned int> vertices;
|
||||
//std::set<unsigned int> normals;
|
||||
//std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfovector = copy.boneinfo;
|
||||
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >* 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<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||
|
||||
|
||||
std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices();
|
||||
//Each shape has multiple indices
|
||||
if(initialVertices.size() )
|
||||
Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates();
|
||||
Ogre::AnimationStateIterator as = aset->getAnimationStateIterator();
|
||||
while(as.hasMoreElements())
|
||||
{
|
||||
if(copy.vertices.size() == initialVertices.size())
|
||||
{
|
||||
//Create if it doesn't already exist
|
||||
if(mShapeIndexI.size() == static_cast<std::size_t> (mShapeNumber))
|
||||
{
|
||||
std::vector<int> vec;
|
||||
mShapeIndexI.push_back(vec);
|
||||
}
|
||||
if(mTime >= copy.morph.getStartTime() && mTime <= copy.morph.getStopTime())
|
||||
{
|
||||
float x;
|
||||
for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++)
|
||||
{
|
||||
int j = 0;
|
||||
if(mShapeIndexI[mShapeNumber].size() <= i)
|
||||
mShapeIndexI[mShapeNumber].push_back(0);
|
||||
|
||||
if(timeIndex(mTime,copy.morph.getRelevantTimes()[i],(mShapeIndexI[mShapeNumber])[i], j, x))
|
||||
{
|
||||
int indexI = (mShapeIndexI[mShapeNumber])[i];
|
||||
std::vector<Ogre::Vector3> 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;
|
||||
}
|
||||
mShapeNumber++;
|
||||
}
|
||||
Ogre::AnimationState *state = as.getNext();
|
||||
times.mLoopStop = times.mStop = state->getLength();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!findGroupTimes(groupname, ×))
|
||||
throw std::runtime_error("Failed to find animation group "+groupname);
|
||||
|
||||
if(mode == 0 && mCurGroup.mLoops > 0)
|
||||
mNextGroup = times;
|
||||
else
|
||||
{
|
||||
mCurGroup = times;
|
||||
mNextGroup = GroupTimes();
|
||||
mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart);
|
||||
}
|
||||
}
|
||||
|
||||
if(verticesToChange->size() > 0)
|
||||
void Animation::skipAnim()
|
||||
{
|
||||
mSkipFrame = true;
|
||||
}
|
||||
|
||||
void Animation::runAnimation(float timepassed)
|
||||
{
|
||||
if(mCurGroup.mLoops > 0 && !mSkipFrame)
|
||||
{
|
||||
mTime += timepassed;
|
||||
if(mTime >= mCurGroup.mLoopStop)
|
||||
{
|
||||
if(mCurGroup.mLoops > 1)
|
||||
{
|
||||
|
||||
for(std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >::iterator iter = verticesToChange->begin();
|
||||
iter != verticesToChange->end(); iter++)
|
||||
{
|
||||
std::vector<Nif::NiSkinData::IndividualWeight> 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<Nif::NiSkinData::BoneInfoCopy*, PosAndRot>::iterator result = mVecRotPos.find(boneinfocopy);
|
||||
|
||||
if(result == mVecRotPos.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;
|
||||
mVecRotPos[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 = mVecRotPos.find(boneinfocopy);
|
||||
|
||||
if(result == mVecRotPos.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;
|
||||
mVecRotPos[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;
|
||||
|
||||
}
|
||||
mCurGroup.mLoops--;
|
||||
mTime = mTime - mCurGroup.mLoopStop + mCurGroup.mLoopStart;
|
||||
}
|
||||
else
|
||||
else if(mTime >= mCurGroup.mStop)
|
||||
{
|
||||
//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<std::string> boneSequence = copy.boneSequence;
|
||||
|
||||
Ogre::Vector3 transmult;
|
||||
Ogre::Quaternion rotmult;
|
||||
float scale;
|
||||
if(boneSequence.size() > 0)
|
||||
{
|
||||
std::vector<std::string>::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";
|
||||
}
|
||||
}
|
||||
if(mNextGroup.mLoops > 0)
|
||||
mTime = mTime - mCurGroup.mStop + mNextGroup.mStart;
|
||||
else
|
||||
{
|
||||
transmult = shapetrans;
|
||||
rotmult = shaperot;
|
||||
scale = shapescale;
|
||||
}
|
||||
|
||||
// Computes C = B + AxC*scale
|
||||
// final_vector = old_vector + old_rotation*new_vector*old_scale/
|
||||
|
||||
for(unsigned int i = 0; i < allvertices->size(); i++)
|
||||
{
|
||||
Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i];
|
||||
Ogre::Real* addr = pReal + i * 3;
|
||||
*addr = current.x;
|
||||
*(addr+1) = current.y;
|
||||
*(addr + 2) = current.z;
|
||||
|
||||
}/*
|
||||
for(int i = 0; i < allnormals.size(); i++){
|
||||
Ogre::Vector3 current =rotmult * allnormals[i];
|
||||
Ogre::Real* addr = pRealNormal + i * 3;
|
||||
*addr = current.x;
|
||||
*(addr+1) = current.y;
|
||||
*(addr + 2) = current.z;
|
||||
|
||||
}*/
|
||||
|
||||
mTime = mCurGroup.mStop;
|
||||
mCurGroup = mNextGroup;
|
||||
mNextGroup = GroupTimes();
|
||||
}
|
||||
vbuf->unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Animation::timeIndex( float time, const std::vector<float> & times, int & i, int & j, float & x )
|
||||
{
|
||||
int count;
|
||||
if ( (count = times.size()) > 0 )
|
||||
if(mEntityList.mSkelBase)
|
||||
{
|
||||
if ( time <= times[0] )
|
||||
Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates();
|
||||
Ogre::AnimationStateIterator as = aset->getAnimationStateIterator();
|
||||
while(as.hasMoreElements())
|
||||
{
|
||||
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;
|
||||
Ogre::AnimationState *state = as.getNext();
|
||||
state->setTimePosition(mTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void Animation::handleAnimationTransforms()
|
||||
{
|
||||
Ogre::SkeletonInstance* skel = mBase->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();
|
||||
|
||||
mBase->getAllAnimationStates()->_notifyDirty();
|
||||
//mBase->_updateAnimation();
|
||||
//mBase->_notifyMoved();
|
||||
|
||||
std::vector<Nif::NiKeyframeData>::iterator iter;
|
||||
int slot = 0;
|
||||
if(mTransformations)
|
||||
{
|
||||
for(iter = mTransformations->begin(); iter != mTransformations->end(); iter++)
|
||||
{
|
||||
if(mTime < iter->getStartTime() || mTime < mStartTime || mTime > iter->getStopTime())
|
||||
{
|
||||
slot++;
|
||||
continue;
|
||||
}
|
||||
|
||||
float x;
|
||||
float x2;
|
||||
|
||||
const std::vector<Ogre::Quaternion> & quats = iter->getQuat();
|
||||
|
||||
const std::vector<float> & ttime = iter->gettTime();
|
||||
const std::vector<float> & rtime = iter->getrTime();
|
||||
int rindexJ = mRindexI[slot];
|
||||
|
||||
timeIndex(mTime, rtime, mRindexI[slot], rindexJ, x2);
|
||||
int tindexJ = mTindexI[slot];
|
||||
|
||||
const std::vector<Ogre::Vector3> & translist1 = iter->getTranslist1();
|
||||
|
||||
timeIndex(mTime, ttime, mTindexI[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[mTindexI[slot]];
|
||||
Ogre::Vector3 v2 = translist1[tindexJ];
|
||||
t = (v1 + (v2 - v1) * x);
|
||||
bone->setPosition(t);
|
||||
|
||||
}
|
||||
|
||||
if(bQuats)
|
||||
{
|
||||
r = Ogre::Quaternion::Slerp(x2, quats[mRindexI[slot]], quats[rindexJ], true);
|
||||
bone->setOrientation(r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
slot++;
|
||||
}
|
||||
skel->_updateTransforms();
|
||||
mBase->getAllAnimationStates()->_notifyDirty();
|
||||
}
|
||||
}
|
||||
mSkipFrame = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef _GAME_RENDER_ANIMATION_H
|
||||
#define _GAME_RENDER_ANIMATION_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
#include <components/nif/node.hpp>
|
||||
|
@ -8,53 +11,47 @@
|
|||
|
||||
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
struct PosAndRot{
|
||||
Ogre::Quaternion vecRot;
|
||||
Ogre::Vector3 vecPos;
|
||||
};
|
||||
namespace MWRender {
|
||||
|
||||
class Animation{
|
||||
class Animation {
|
||||
struct GroupTimes {
|
||||
float mStart;
|
||||
float mStop;
|
||||
float mLoopStart;
|
||||
float mLoopStop;
|
||||
|
||||
protected:
|
||||
size_t mLoops;
|
||||
|
||||
GroupTimes()
|
||||
: mStart(-1.0f), mStop(-1.0f), mLoopStart(-1.0f), mLoopStop(-1.0f),
|
||||
mLoops(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
protected:
|
||||
Ogre::SceneNode* mInsert;
|
||||
OEngine::Render::OgreRenderer &mRend;
|
||||
std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot> mVecRotPos;
|
||||
static std::map<std::string, int> sUniqueIDs;
|
||||
|
||||
float mTime;
|
||||
float mStartTime;
|
||||
float mStopTime;
|
||||
int mAnimate;
|
||||
//Represents a rotation index for each bone
|
||||
std::vector<int>mRindexI;
|
||||
//Represents a translation index for each bone
|
||||
std::vector<int>mTindexI;
|
||||
GroupTimes mCurGroup;
|
||||
GroupTimes mNextGroup;
|
||||
|
||||
//Only shapes with morphing data will use a shape number
|
||||
int mShapeNumber;
|
||||
std::vector<std::vector<int> > mShapeIndexI;
|
||||
bool mSkipFrame;
|
||||
|
||||
//Ogre::SkeletonInstance* skel;
|
||||
std::vector<Nif::NiTriShapeCopy>* mShapes; //All the NiTriShapeData for a creature
|
||||
NifOgre::EntityList mEntityList;
|
||||
NifOgre::TextKeyMap mTextKeys;
|
||||
|
||||
std::vector<Nif::NiKeyframeData>* mTransformations;
|
||||
std::map<std::string,float>* mTextmappings;
|
||||
Ogre::Entity* mBase;
|
||||
void handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel);
|
||||
void handleAnimationTransforms();
|
||||
bool timeIndex( float time, const std::vector<float> & times, int & i, int & j, float & x );
|
||||
std::string getUniqueID(std::string mesh);
|
||||
bool findGroupTimes(const std::string &groupname, GroupTimes *times);
|
||||
|
||||
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();
|
||||
public:
|
||||
Animation(OEngine::Render::OgreRenderer& _rend);
|
||||
virtual ~Animation();
|
||||
|
||||
void playGroup(std::string groupname, int mode, int loops);
|
||||
void skipAnim();
|
||||
virtual void runAnimation(float timepassed);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,75 +24,54 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, OEngine::Render::O
|
|||
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);
|
||||
mBase = mRend.getScene()->createEntity(meshNumbered);
|
||||
mBase->setVisibilityFlags(RV_Actors);
|
||||
std::string mesh = "meshes\\" + ref->base->model;
|
||||
|
||||
bool transparent = false;
|
||||
for (unsigned int i=0; i < mBase->getNumSubEntities(); ++i)
|
||||
mEntityList = NifOgre::NIFLoader::createEntities(mInsert, &mTextKeys, mesh);
|
||||
for(size_t i = 0;i < mEntityList.mEntities.size();i++)
|
||||
{
|
||||
Ogre::MaterialPtr mat = mBase->getSubEntity(i)->getMaterial();
|
||||
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||
while (techIt.hasMoreElements())
|
||||
{
|
||||
Ogre::Technique* tech = techIt.getNext();
|
||||
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||
while (passIt.hasMoreElements())
|
||||
{
|
||||
Ogre::Pass* pass = passIt.getNext();
|
||||
Ogre::Entity *ent = mEntityList.mEntities[i];
|
||||
ent->setVisibilityFlags(RV_Actors);
|
||||
|
||||
if (pass->getDepthWriteEnabled() == false)
|
||||
transparent = true;
|
||||
bool transparent = false;
|
||||
for (unsigned int j=0;j < ent->getNumSubEntities() && !transparent; ++j)
|
||||
{
|
||||
Ogre::MaterialPtr mat = ent->getSubEntity(j)->getMaterial();
|
||||
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||
while (techIt.hasMoreElements() && !transparent)
|
||||
{
|
||||
Ogre::Technique* tech = techIt.getNext();
|
||||
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||
while (passIt.hasMoreElements() && !transparent)
|
||||
{
|
||||
Ogre::Pass* pass = passIt.getNext();
|
||||
|
||||
if (pass->getDepthWriteEnabled() == false)
|
||||
transparent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
}
|
||||
mBase->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
|
||||
std::string meshZero = mesh + "0000>|";
|
||||
|
||||
if((mTransformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero)))
|
||||
if(mEntityList.mSkelBase)
|
||||
{
|
||||
for(std::size_t init = 0; init < mTransformations->size(); init++)
|
||||
Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates();
|
||||
Ogre::AnimationStateIterator as = aset->getAnimationStateIterator();
|
||||
while(as.hasMoreElements())
|
||||
{
|
||||
mRindexI.push_back(0);
|
||||
mTindexI.push_back(0);
|
||||
Ogre::AnimationState *state = as.getNext();
|
||||
state->setEnabled(true);
|
||||
state->setLoop(false);
|
||||
}
|
||||
mStopTime = mTransformations->begin()->getStopTime();
|
||||
mStartTime = mTransformations->begin()->getStartTime();
|
||||
mShapes = (NIFLoader::getSingletonPtr())->getShapes(meshZero);
|
||||
}
|
||||
mTextmappings = NIFLoader::getSingletonPtr()->getTextIndices(meshZero);
|
||||
mInsert->attachObject(mBase);
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureAnimation::runAnimation(float timepassed)
|
||||
{
|
||||
mVecRotPos.clear();
|
||||
if(mAnimate > 0)
|
||||
{
|
||||
//Add the amount of time passed to time
|
||||
// Placeholder
|
||||
|
||||
//Handle the animation transforms dependent on time
|
||||
|
||||
//Handle the shapes dependent on animation transforms
|
||||
mTime += timepassed;
|
||||
if(mTime >= mStopTime)
|
||||
{
|
||||
mAnimate--;
|
||||
//std::cout << "Stopping the animation\n";
|
||||
if(mAnimate == 0)
|
||||
mTime = mStopTime;
|
||||
else
|
||||
mTime = mStartTime + (mTime - mStopTime);
|
||||
}
|
||||
|
||||
handleAnimationTransforms();
|
||||
handleShapes(mShapes, mBase, mBase->getSkeleton());
|
||||
|
||||
}
|
||||
Animation::runAnimation(timepassed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,42 +14,37 @@ class NpcAnimation: public Animation{
|
|||
private:
|
||||
MWWorld::InventoryStore& mInv;
|
||||
int mStateID;
|
||||
//Free Parts
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mChest;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mSkirt;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mLhand;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mRhand;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mTail;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mLFreeFoot;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mRFreeFoot;
|
||||
|
||||
int mPartslots[27]; //Each part slot is taken by clothing, armor, or is empty
|
||||
int mPartPriorities[27];
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> mZero;
|
||||
int mPartslots[27]; //Each part slot is taken by clothing, armor, or is empty
|
||||
int mPartPriorities[27];
|
||||
|
||||
//Bounded Parts
|
||||
Ogre::Entity* lclavicle;
|
||||
Ogre::Entity* rclavicle;
|
||||
Ogre::Entity* rupperArm;
|
||||
Ogre::Entity* lupperArm;
|
||||
Ogre::Entity* rUpperLeg;
|
||||
Ogre::Entity* lUpperLeg;
|
||||
Ogre::Entity* lForearm;
|
||||
Ogre::Entity* rForearm;
|
||||
Ogre::Entity* lWrist;
|
||||
Ogre::Entity* rWrist;
|
||||
Ogre::Entity* rKnee;
|
||||
Ogre::Entity* lKnee;
|
||||
Ogre::Entity* neck;
|
||||
Ogre::Entity* rAnkle;
|
||||
Ogre::Entity* lAnkle;
|
||||
Ogre::Entity* groin;
|
||||
Ogre::Entity* lfoot;
|
||||
Ogre::Entity* rfoot;
|
||||
Ogre::Entity* hair;
|
||||
Ogre::Entity* head;
|
||||
NifOgre::EntityList lclavicle;
|
||||
NifOgre::EntityList rclavicle;
|
||||
NifOgre::EntityList rupperArm;
|
||||
NifOgre::EntityList lupperArm;
|
||||
NifOgre::EntityList rUpperLeg;
|
||||
NifOgre::EntityList lUpperLeg;
|
||||
NifOgre::EntityList lForearm;
|
||||
NifOgre::EntityList rForearm;
|
||||
NifOgre::EntityList lWrist;
|
||||
NifOgre::EntityList rWrist;
|
||||
NifOgre::EntityList rKnee;
|
||||
NifOgre::EntityList lKnee;
|
||||
NifOgre::EntityList neck;
|
||||
NifOgre::EntityList rAnkle;
|
||||
NifOgre::EntityList lAnkle;
|
||||
NifOgre::EntityList groin;
|
||||
NifOgre::EntityList skirt;
|
||||
NifOgre::EntityList lfoot;
|
||||
NifOgre::EntityList rfoot;
|
||||
NifOgre::EntityList hair;
|
||||
NifOgre::EntityList rHand;
|
||||
NifOgre::EntityList lHand;
|
||||
NifOgre::EntityList head;
|
||||
NifOgre::EntityList chest;
|
||||
NifOgre::EntityList tail;
|
||||
|
||||
Ogre::SceneNode* insert;
|
||||
bool isBeast;
|
||||
bool isFemale;
|
||||
std::string headModel;
|
||||
|
@ -73,18 +68,17 @@ private:
|
|||
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<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> insertFreePart(const std::string &mesh, const std::string& suffix);
|
||||
void insertFootPart(int type, const std::string &mesh);
|
||||
NifOgre::EntityList insertBoundedPart(const std::string &mesh, const std::string &bonename);
|
||||
virtual void runAnimation(float timepassed);
|
||||
void updateParts();
|
||||
void removeEntities(NifOgre::EntityList &entities);
|
||||
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 addPartGroup(int group, int priority, std::vector<ESM::PartReference>& parts);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -92,11 +92,16 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
|||
Ogre::SceneNode* insert = ptr.getRefData().getBaseNode();
|
||||
assert(insert);
|
||||
|
||||
NifOgre::NIFLoader::load(mesh);
|
||||
Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh);
|
||||
|
||||
|
||||
Ogre::Vector3 extents = ent->getBoundingBox().getSize();
|
||||
Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL;
|
||||
NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, NULL, mesh);
|
||||
for(size_t i = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
const Ogre::AxisAlignedBox &tmp = entities.mEntities[i]->getBoundingBox();
|
||||
bounds.merge(Ogre::AxisAlignedBox(insert->_getDerivedPosition() + tmp.getMinimum(),
|
||||
insert->_getDerivedPosition() + tmp.getMaximum())
|
||||
);
|
||||
}
|
||||
Ogre::Vector3 extents = bounds.getSize();
|
||||
extents *= insert->getScale();
|
||||
float size = std::max(std::max(extents.x, extents.y), extents.z);
|
||||
|
||||
|
@ -108,42 +113,41 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
|||
|
||||
if (mBounds.find(ptr.getCell()) == mBounds.end())
|
||||
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL;
|
||||
|
||||
Ogre::AxisAlignedBox bounds = ent->getBoundingBox();
|
||||
bounds = Ogre::AxisAlignedBox(
|
||||
insert->_getDerivedPosition() + bounds.getMinimum(),
|
||||
insert->_getDerivedPosition() + bounds.getMaximum()
|
||||
);
|
||||
|
||||
bounds.scale(insert->getScale());
|
||||
mBounds[ptr.getCell()].merge(bounds);
|
||||
|
||||
bool transparent = false;
|
||||
for (unsigned int i=0; i<ent->getNumSubEntities(); ++i)
|
||||
for(size_t i = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial();
|
||||
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||
while (techIt.hasMoreElements())
|
||||
Ogre::Entity *ent = entities.mEntities[i];
|
||||
for (unsigned int i=0; i<ent->getNumSubEntities(); ++i)
|
||||
{
|
||||
Ogre::Technique* tech = techIt.getNext();
|
||||
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||
while (passIt.hasMoreElements())
|
||||
Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial();
|
||||
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||
while (techIt.hasMoreElements())
|
||||
{
|
||||
Ogre::Pass* pass = passIt.getNext();
|
||||
Ogre::Technique* tech = techIt.getNext();
|
||||
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||
while (passIt.hasMoreElements())
|
||||
{
|
||||
Ogre::Pass* pass = passIt.getNext();
|
||||
|
||||
if (pass->getDepthWriteEnabled() == false)
|
||||
transparent = true;
|
||||
if (pass->getDepthWriteEnabled() == false)
|
||||
transparent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent)
|
||||
{
|
||||
insert->attachObject(ent);
|
||||
for(size_t i = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
Ogre::Entity *ent = entities.mEntities[i];
|
||||
|
||||
ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0);
|
||||
ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc);
|
||||
ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0);
|
||||
ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc);
|
||||
ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -183,15 +187,20 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
|||
// - there will be too many batches.
|
||||
sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500));
|
||||
|
||||
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
||||
|
||||
sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics);
|
||||
|
||||
sg->setCastShadows(true);
|
||||
|
||||
sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
|
||||
mRenderer.getScene()->destroyEntity(ent);
|
||||
for(size_t i = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
Ogre::Entity *ent = entities.mEntities[i];
|
||||
insert->detachObject(ent);
|
||||
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
||||
|
||||
mRenderer.getScene()->destroyEntity(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
|
|||
|
||||
void SkyManager::create()
|
||||
{
|
||||
assert(!mCreated);
|
||||
|
||||
sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
|
||||
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
|
||||
sh::Factory::getInstance().setSharedParameter ("cloudOpacity",
|
||||
|
@ -302,7 +304,7 @@ void SkyManager::create()
|
|||
sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", "");
|
||||
sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", "");
|
||||
|
||||
// Create overlay used for thunderstorm
|
||||
// Create light used for thunderstorm
|
||||
mLightning = mSceneMgr->createLight();
|
||||
mLightning->setType (Ogre::Light::LT_DIRECTIONAL);
|
||||
mLightning->setDirection (Ogre::Vector3(0.3, -0.7, 0.3));
|
||||
|
@ -324,52 +326,57 @@ void SkyManager::create()
|
|||
mSunGlare->setVisibilityFlags(RV_NoReflection);
|
||||
|
||||
// Stars
|
||||
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
|
||||
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
||||
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
|
||||
night1_ent->setVisibilityFlags(RV_Sky);
|
||||
night1_ent->setCastShadows(false);
|
||||
|
||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||
mAtmosphereNight->attachObject(night1_ent);
|
||||
|
||||
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
|
||||
NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(mAtmosphereNight, NULL, "meshes\\sky_night_01.nif");
|
||||
for(size_t i = 0, matidx = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
std::string matName = "openmw_stars_" + boost::lexical_cast<std::string>(i);
|
||||
sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars");
|
||||
Entity* night1_ent = entities.mEntities[i];
|
||||
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
|
||||
night1_ent->setVisibilityFlags(RV_Sky);
|
||||
night1_ent->setCastShadows(false);
|
||||
|
||||
std::string textureName = sh::retrieveValue<sh::StringValue>(
|
||||
sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (i)->getMaterialName ())->getProperty("diffuseMap"), NULL).get();
|
||||
for (unsigned int j=0; j<night1_ent->getNumSubEntities(); ++j)
|
||||
{
|
||||
std::string matName = "openmw_stars_" + boost::lexical_cast<std::string>(matidx++);
|
||||
sh::MaterialInstance* m = sh::Factory::getInstance().createMaterialInstance(matName, "openmw_stars");
|
||||
|
||||
m->setProperty ("texture", sh::makeProperty<sh::StringValue>(new sh::StringValue(textureName)));
|
||||
std::string textureName = sh::retrieveValue<sh::StringValue>(
|
||||
sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity(j)->getMaterialName())->getProperty("diffuseMap"), NULL).get();
|
||||
|
||||
night1_ent->getSubEntity(i)->setMaterialName (matName);
|
||||
m->setProperty("texture", sh::makeProperty<sh::StringValue>(new sh::StringValue(textureName)));
|
||||
|
||||
night1_ent->getSubEntity(j)->setMaterialName(matName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Atmosphere (day)
|
||||
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
||||
atmosphere_ent->setCastShadows(false);
|
||||
|
||||
ModVertexAlpha(atmosphere_ent, 0);
|
||||
|
||||
atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly);
|
||||
atmosphere_ent->setVisibilityFlags(RV_Sky);
|
||||
mAtmosphereDay = mRootNode->createChildSceneNode();
|
||||
mAtmosphereDay->attachObject(atmosphere_ent);
|
||||
atmosphere_ent->getSubEntity (0)->setMaterialName ("openmw_atmosphere");
|
||||
entities = NifOgre::NIFLoader::createEntities(mAtmosphereDay, NULL, "meshes\\sky_atmosphere.nif");
|
||||
for(size_t i = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
Entity* atmosphere_ent = entities.mEntities[i];
|
||||
atmosphere_ent->setCastShadows(false);
|
||||
atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly);
|
||||
atmosphere_ent->setVisibilityFlags(RV_Sky);
|
||||
atmosphere_ent->getSubEntity (0)->setMaterialName ("openmw_atmosphere");
|
||||
ModVertexAlpha(atmosphere_ent, 0);
|
||||
}
|
||||
|
||||
|
||||
// Clouds
|
||||
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
||||
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
||||
clouds_ent->setVisibilityFlags(RV_Sky);
|
||||
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
|
||||
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||
clouds_node->attachObject(clouds_ent);
|
||||
clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds");
|
||||
clouds_ent->setCastShadows(false);
|
||||
entities = NifOgre::NIFLoader::createEntities(clouds_node, NULL, "meshes\\sky_clouds_01.nif");
|
||||
for(size_t i = 0;i < entities.mEntities.size();i++)
|
||||
{
|
||||
Entity* clouds_ent = entities.mEntities[i];
|
||||
clouds_ent->setVisibilityFlags(RV_Sky);
|
||||
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
|
||||
clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds");
|
||||
clouds_ent->setCastShadows(false);
|
||||
|
||||
ModVertexAlpha(clouds_ent, 1);
|
||||
ModVertexAlpha(clouds_ent, 1);
|
||||
}
|
||||
|
||||
mCreated = true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _GAME_RENDER_SKY_H
|
||||
#define _GAME_RENDER_SKY_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <OgreVector3.h>
|
||||
#include <OgreString.h>
|
||||
#include <OgreMaterial.h>
|
||||
|
@ -9,7 +11,7 @@
|
|||
|
||||
#include <extern/shiny/Main/Factory.hpp>
|
||||
|
||||
#include "sky.hpp"
|
||||
|
||||
#include "../mwworld/weather.hpp"
|
||||
|
||||
namespace Ogre
|
||||
|
|
|
@ -62,28 +62,13 @@ static bool fsstrict = false;
|
|||
/// An OGRE Archive wrapping a BSAFile archive
|
||||
class DirArchive: public Ogre::FileSystemArchive
|
||||
{
|
||||
|
||||
boost::filesystem::path currentdir;
|
||||
std::map<std::string, std::vector<std::string>, 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) == '/')
|
||||
|
@ -223,43 +208,20 @@ 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<BSAFile*>(&arc);
|
||||
|
||||
// Open the file
|
||||
return narc->getFile(passed.c_str());
|
||||
return narc->getFile(filename.c_str());
|
||||
}
|
||||
|
||||
bool exists(const String& filename) {
|
||||
return cexists(filename);
|
||||
}
|
||||
bool exists(const String& filename) {
|
||||
return arc.exists(filename.c_str());
|
||||
}
|
||||
|
||||
// Check if the file exists.
|
||||
bool cexists(const String& filename) const {
|
||||
String passed = filename;
|
||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||
passed = filename.substr(0, filename.length() - 6);
|
||||
else if(filename.at(filename.length() - 2) == '"')
|
||||
passed = filename.substr(0, filename.length() - 9);
|
||||
else if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
||||
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
||||
|| filename.at(filename.length() - 1) == '|')
|
||||
passed = filename.substr(0, filename.length() - 2);
|
||||
return arc.exists(filename.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
return arc.exists(passed.c_str());
|
||||
}
|
||||
time_t getModifiedTime(const String&) { return 0; }
|
||||
|
||||
// This is never called as far as I can see.
|
||||
|
|
|
@ -96,7 +96,9 @@ public:
|
|||
class ShapeData : public Record
|
||||
{
|
||||
public:
|
||||
std::vector<float> vertices, normals, colors, uvlist;
|
||||
std::vector<Ogre::Vector3> vertices, normals;
|
||||
std::vector<Ogre::Vector4> colors;
|
||||
std::vector< std::vector<Ogre::Vector2> > uvlist;
|
||||
Ogre::Vector3 center;
|
||||
float radius;
|
||||
|
||||
|
@ -105,16 +107,16 @@ public:
|
|||
int verts = nif->getUShort();
|
||||
|
||||
if(nif->getInt())
|
||||
nif->getFloats(vertices, verts*3);
|
||||
nif->getVector3s(vertices, verts);
|
||||
|
||||
if(nif->getInt())
|
||||
nif->getFloats(normals, verts*3);
|
||||
nif->getVector3s(normals, verts);
|
||||
|
||||
center = nif->getVector3();
|
||||
radius = nif->getFloat();
|
||||
|
||||
if(nif->getInt())
|
||||
nif->getFloats(colors, verts*4);
|
||||
nif->getVector4s(colors, verts);
|
||||
|
||||
// Only the first 6 bits are used as a count. I think the rest are
|
||||
// flags of some sort.
|
||||
|
@ -122,7 +124,11 @@ public:
|
|||
uvs &= 0x3f;
|
||||
|
||||
if(nif->getInt())
|
||||
nif->getFloats(uvlist, uvs*verts*2);
|
||||
{
|
||||
uvlist.resize(uvs);
|
||||
for(int i = 0;i < uvs;i++)
|
||||
nif->getVector2s(uvlist[i], verts);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -202,61 +208,34 @@ public:
|
|||
class NiPosData : public Record
|
||||
{
|
||||
public:
|
||||
Vector3KeyList mKeyList;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
int count = nif->getInt();
|
||||
int type = nif->getInt();
|
||||
if(type != 1 && type != 2)
|
||||
nif->fail("Cannot handle NiPosData type");
|
||||
|
||||
// TODO: Could make structs of these. Seems to be identical to
|
||||
// translation in NiKeyframeData.
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
/*float time =*/ nif->getFloat();
|
||||
nif->getVector3(); // This isn't really shared between type 1
|
||||
// and type 2, most likely
|
||||
if(type == 2)
|
||||
{
|
||||
nif->getVector3();
|
||||
nif->getVector3();
|
||||
}
|
||||
}
|
||||
mKeyList.read(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiUVData : public Record
|
||||
{
|
||||
public:
|
||||
FloatKeyList mKeyList[4];
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
// TODO: This is claimed to be a "float animation key", which is
|
||||
// also used in FloatData and KeyframeData. We could probably
|
||||
// reuse and refactor a lot of this if we actually use it at some
|
||||
// point.
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
int count = nif->getInt();
|
||||
if(count)
|
||||
{
|
||||
nif->getInt(); // always 2
|
||||
nif->skip(count * (sizeof(float) + 3*sizeof(float))); // Really one time float + one vector
|
||||
}
|
||||
}
|
||||
// Always 0
|
||||
nif->getInt();
|
||||
nif->getInt();
|
||||
for(int i = 0;i < 4;i++)
|
||||
mKeyList[i].read(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiFloatData : public Record
|
||||
{
|
||||
public:
|
||||
FloatKeyList mKeyList;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
int count = nif->getInt();
|
||||
nif->getInt(); // always 2
|
||||
nif->skip(count * (sizeof(float) + 3*sizeof(float))); // Really one time float + one vector
|
||||
mKeyList.read(nif);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -302,19 +281,11 @@ public:
|
|||
class NiColorData : public Record
|
||||
{
|
||||
public:
|
||||
struct ColorData
|
||||
{
|
||||
float time;
|
||||
Ogre::Vector4 rgba;
|
||||
};
|
||||
Vector4KeyList mKeyList;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
int count = nif->getInt();
|
||||
nif->getInt(); // always 1
|
||||
|
||||
// Skip the data
|
||||
nif->skip(count * 5*sizeof(float));
|
||||
mKeyList.read(nif);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -361,12 +332,6 @@ public:
|
|||
Ogre::Vector3 trans; // Translation
|
||||
float scale; // Probably scale (always 1)
|
||||
};
|
||||
struct BoneTrafoCopy
|
||||
{
|
||||
Ogre::Quaternion rotation;
|
||||
Ogre::Vector3 trans;
|
||||
float scale;
|
||||
};
|
||||
|
||||
struct VertWeight
|
||||
{
|
||||
|
@ -374,26 +339,12 @@ public:
|
|||
float weight;
|
||||
};
|
||||
|
||||
|
||||
struct BoneInfo
|
||||
{
|
||||
BoneTrafo trafo;
|
||||
Ogre::Vector4 unknown;
|
||||
std::vector<VertWeight> weights;
|
||||
};
|
||||
struct BoneInfoCopy
|
||||
{
|
||||
std::string bonename;
|
||||
unsigned short bonehandle;
|
||||
BoneTrafoCopy trafo;
|
||||
Ogre::Vector4 unknown;
|
||||
//std::vector<VertWeight> weights;
|
||||
};
|
||||
struct IndividualWeight
|
||||
{
|
||||
float weight;
|
||||
unsigned int boneinfocopyindex;
|
||||
};
|
||||
|
||||
BoneTrafo trafo;
|
||||
std::vector<BoneInfo> bones;
|
||||
|
@ -428,378 +379,45 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class NiMorphData : public Record
|
||||
struct NiMorphData : public Record
|
||||
{
|
||||
float startTime;
|
||||
float stopTime;
|
||||
std::vector<Ogre::Vector3> initialVertices;
|
||||
std::vector<std::vector<float> > relevantTimes;
|
||||
std::vector<std::vector<Ogre::Vector3> > relevantData;
|
||||
std::vector<std::vector<Ogre::Vector3> > additionalVertices;
|
||||
|
||||
public:
|
||||
float getStartTime() const
|
||||
{ return startTime; }
|
||||
float getStopTime() const
|
||||
{ return stopTime; }
|
||||
|
||||
void setStartTime(float time)
|
||||
{ startTime = time; }
|
||||
void setStopTime(float time)
|
||||
{ stopTime = time; }
|
||||
|
||||
const std::vector<Ogre::Vector3>& getInitialVertices() const
|
||||
{ return initialVertices; }
|
||||
const std::vector<std::vector<Ogre::Vector3> >& getRelevantData() const
|
||||
{ return relevantData; }
|
||||
const std::vector<std::vector<float> >& getRelevantTimes() const
|
||||
{ return relevantTimes; }
|
||||
const std::vector<std::vector<Ogre::Vector3> >& getAdditionalVertices() const
|
||||
{ return additionalVertices; }
|
||||
struct MorphData {
|
||||
FloatKeyList mData;
|
||||
std::vector<Ogre::Vector3> mVertices;
|
||||
};
|
||||
std::vector<MorphData> mMorphs;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
int morphCount = nif->getInt();
|
||||
int vertCount = nif->getInt();
|
||||
nif->getChar();
|
||||
int magic = nif->getInt();
|
||||
/*int type =*/ nif->getInt();
|
||||
|
||||
for(int i = 0; i < vertCount; i++)
|
||||
mMorphs.resize(morphCount);
|
||||
for(int i = 0;i < morphCount;i++)
|
||||
{
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
initialVertices.push_back(Ogre::Vector3(x, y, z));
|
||||
}
|
||||
mMorphs[i].mData.read(nif, true);
|
||||
|
||||
for(int i=1; i<morphCount; i++)
|
||||
{
|
||||
magic = nif->getInt();
|
||||
/*type =*/ nif->getInt();
|
||||
std::vector<Ogre::Vector3> current;
|
||||
std::vector<float> currentTime;
|
||||
for(int i = 0; i < magic; i++)
|
||||
{
|
||||
// Time, data, forward, backward tangents
|
||||
float time = nif->getFloat();
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
current.push_back(Ogre::Vector3(x,y,z));
|
||||
currentTime.push_back(time);
|
||||
//nif->getFloatLen(4*magic);
|
||||
}
|
||||
|
||||
if(magic)
|
||||
{
|
||||
relevantData.push_back(current);
|
||||
relevantTimes.push_back(currentTime);
|
||||
}
|
||||
|
||||
std::vector<Ogre::Vector3> verts;
|
||||
for(int i = 0; i < vertCount; i++)
|
||||
{
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
verts.push_back(Ogre::Vector3(x, y, z));
|
||||
}
|
||||
additionalVertices.push_back(verts);
|
||||
mMorphs[i].mVertices.resize(vertCount);
|
||||
for(int j = 0;j < vertCount;j++)
|
||||
mMorphs[i].mVertices[j] = nif->getVector3();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class NiKeyframeData : public Record
|
||||
struct NiKeyframeData : public Record
|
||||
{
|
||||
std::string bonename;
|
||||
//Rotations
|
||||
std::vector<Ogre::Quaternion> quats;
|
||||
std::vector<Ogre::Vector3> tbc;
|
||||
std::vector<float> rottime;
|
||||
float startTime;
|
||||
float stopTime;
|
||||
int rtype;
|
||||
|
||||
//Translations
|
||||
std::vector<Ogre::Vector3> translist1;
|
||||
std::vector<Ogre::Vector3> translist2;
|
||||
std::vector<Ogre::Vector3> translist3;
|
||||
std::vector<Ogre::Vector3> transtbc;
|
||||
std::vector<float> transtime;
|
||||
int ttype;
|
||||
|
||||
//Scalings
|
||||
std::vector<float> scalefactor;
|
||||
std::vector<float> scaletime;
|
||||
std::vector<float> forwards;
|
||||
std::vector<float> backwards;
|
||||
std::vector<Ogre::Vector3> tbcscale;
|
||||
int stype;
|
||||
|
||||
public:
|
||||
void clone(const NiKeyframeData &c)
|
||||
{
|
||||
quats = c.getQuat();
|
||||
tbc = c.getrTbc();
|
||||
rottime = c.getrTime();
|
||||
|
||||
//types
|
||||
ttype = c.getTtype();
|
||||
rtype = c.getRtype();
|
||||
stype = c.getStype();
|
||||
|
||||
|
||||
translist1 = c.getTranslist1();
|
||||
translist2 = c.getTranslist2();
|
||||
translist3 = c.getTranslist3();
|
||||
|
||||
transtime = c.gettTime();
|
||||
|
||||
bonename = c.getBonename();
|
||||
}
|
||||
|
||||
void setBonename(std::string bone)
|
||||
{ bonename = bone; }
|
||||
void setStartTime(float start)
|
||||
{ startTime = start; }
|
||||
void setStopTime(float end)
|
||||
{ stopTime = end; }
|
||||
QuaternionKeyList mRotations;
|
||||
Vector3KeyList mTranslations;
|
||||
FloatKeyList mScales;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
// Rotations first
|
||||
int count = nif->getInt();
|
||||
//std::vector<Ogre::Quaternion> quat(count);
|
||||
//std::vector<float> rottime(count);
|
||||
if(count)
|
||||
{
|
||||
//TYPE1 LINEAR_KEY
|
||||
//TYPE2 QUADRATIC_KEY
|
||||
//TYPE3 TBC_KEY
|
||||
//TYPE4 XYZ_ROTATION_KEY
|
||||
//TYPE5 UNKNOWN_KEY
|
||||
rtype = nif->getInt();
|
||||
//std::cout << "Count: " << count << "Type: " << type << "\n";
|
||||
|
||||
if(rtype == 1)
|
||||
{
|
||||
//We need to actually read in these values instead of skipping them
|
||||
//nif->skip(count*4*5); // time + quaternion
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
float time = nif->getFloat();
|
||||
float w = nif->getFloat();
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
|
||||
quats.push_back(quat);
|
||||
rottime.push_back(time);
|
||||
//if(time == 0.0 || time > 355.5)
|
||||
// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
|
||||
}
|
||||
}
|
||||
else if(rtype == 3)
|
||||
{
|
||||
//Example - node 116 in base_anim.nif
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
float time = nif->getFloat();
|
||||
float w = nif->getFloat();
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
|
||||
float tbcx = nif->getFloat();
|
||||
float tbcy = nif->getFloat();
|
||||
float tbcz = nif->getFloat();
|
||||
|
||||
Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
|
||||
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
|
||||
quats.push_back(quat);
|
||||
rottime.push_back(time);
|
||||
tbc.push_back(vec);
|
||||
//if(time == 0.0 || time > 355.5)
|
||||
// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
|
||||
}
|
||||
}
|
||||
else if(rtype == 4)
|
||||
{
|
||||
for(int j=0;j<count;j++)
|
||||
{
|
||||
nif->getFloat(); // time
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
int cnt = nif->getInt();
|
||||
int type = nif->getInt();
|
||||
if(type == 1)
|
||||
nif->skip(cnt*4*2); // time + unknown
|
||||
else if(type == 2)
|
||||
nif->skip(cnt*4*4); // time + unknown vector
|
||||
else
|
||||
nif->fail("Unknown sub-rotation type");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
nif->fail("Unknown rotation type in NiKeyframeData");
|
||||
}
|
||||
//first = false;
|
||||
|
||||
// Then translation
|
||||
count = nif->getInt();
|
||||
if(count)
|
||||
{
|
||||
ttype = nif->getInt();
|
||||
|
||||
//std::cout << "TransCount:" << count << " Type: " << type << "\n";
|
||||
if(ttype == 1)
|
||||
{
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
float time = nif->getFloat();
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
|
||||
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
||||
translist1.push_back(trans);
|
||||
transtime.push_back(time);
|
||||
}
|
||||
//nif->getFloatLen(count*4); // time + translation
|
||||
}
|
||||
else if(ttype == 2)
|
||||
{
|
||||
//Example - node 116 in base_anim.nif
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
float time = nif->getFloat();
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
float x2 = nif->getFloat();
|
||||
float y2 = nif->getFloat();
|
||||
float z2 = nif->getFloat();
|
||||
float x3 = nif->getFloat();
|
||||
float y3 = nif->getFloat();
|
||||
float z3 = nif->getFloat();
|
||||
|
||||
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
||||
Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2);
|
||||
Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3);
|
||||
transtime.push_back(time);
|
||||
translist1.push_back(trans);
|
||||
translist2.push_back(trans2);
|
||||
translist3.push_back(trans3);
|
||||
}
|
||||
|
||||
//nif->getFloatLen(count*10); // trans1 + forward + backward
|
||||
}
|
||||
else if(ttype == 3)
|
||||
{
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
float time = nif->getFloat();
|
||||
float x = nif->getFloat();
|
||||
float y = nif->getFloat();
|
||||
float z = nif->getFloat();
|
||||
float t = nif->getFloat();
|
||||
float b = nif->getFloat();
|
||||
float c = nif->getFloat();
|
||||
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
|
||||
Ogre::Vector3 tbc = Ogre::Vector3(t, b, c);
|
||||
translist1.push_back(trans);
|
||||
transtbc.push_back(tbc);
|
||||
transtime.push_back(time);
|
||||
}
|
||||
//nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
|
||||
}
|
||||
else nif->fail("Unknown translation type");
|
||||
}
|
||||
|
||||
// Finally, scalings
|
||||
count = nif->getInt();
|
||||
if(count)
|
||||
{
|
||||
stype = nif->getInt();
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
//int size = 0;
|
||||
if(stype >= 1 && stype < 4)
|
||||
{
|
||||
float time = nif->getFloat();
|
||||
float scale = nif->getFloat();
|
||||
scaletime.push_back(time);
|
||||
scalefactor.push_back(scale);
|
||||
//size = 2; // time+scale
|
||||
}
|
||||
else
|
||||
nif->fail("Unknown scaling type");
|
||||
|
||||
if(stype == 2)
|
||||
{
|
||||
//size = 4; // 1 + forward + backward (floats)
|
||||
float forward = nif->getFloat();
|
||||
float backward = nif->getFloat();
|
||||
forwards.push_back(forward);
|
||||
backwards.push_back(backward);
|
||||
}
|
||||
else if(stype == 3)
|
||||
{
|
||||
//size = 5; // 1 + tbc
|
||||
float tbcx = nif->getFloat();
|
||||
float tbcy = nif->getFloat();
|
||||
float tbcz = nif->getFloat();
|
||||
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
|
||||
tbcscale.push_back(vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
stype = 0;
|
||||
mRotations.read(nif);
|
||||
mTranslations.read(nif);
|
||||
mScales.read(nif);
|
||||
}
|
||||
|
||||
int getRtype() const
|
||||
{ return rtype; }
|
||||
int getStype() const
|
||||
{ return stype; }
|
||||
int getTtype() const
|
||||
{ return ttype; }
|
||||
float getStartTime() const
|
||||
{ return startTime; }
|
||||
float getStopTime() const
|
||||
{ return stopTime; }
|
||||
const std::vector<Ogre::Quaternion>& getQuat() const
|
||||
{ return quats; }
|
||||
const std::vector<Ogre::Vector3>& getrTbc() const
|
||||
{ return tbc; }
|
||||
const std::vector<float>& getrTime() const
|
||||
{ return rottime; }
|
||||
|
||||
const std::vector<Ogre::Vector3>& getTranslist1() const
|
||||
{ return translist1; }
|
||||
const std::vector<Ogre::Vector3>& getTranslist2() const
|
||||
{ return translist2; }
|
||||
const std::vector<Ogre::Vector3>& getTranslist3() const
|
||||
{ return translist3; }
|
||||
const std::vector<float>& gettTime() const
|
||||
{ return transtime; }
|
||||
const std::vector<float>& getScalefactor() const
|
||||
{ return scalefactor; }
|
||||
const std::vector<float>& getForwards() const
|
||||
{ return forwards; }
|
||||
const std::vector<float>& getBackwards() const
|
||||
{ return backwards; }
|
||||
const std::vector<Ogre::Vector3>& getScaleTbc() const
|
||||
{ return tbcscale; }
|
||||
|
||||
const std::vector<float>& getsTime() const
|
||||
{ return scaletime; }
|
||||
const std::string& getBonename() const
|
||||
{ return bonename; }
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
|
|
|
@ -205,8 +205,22 @@ void NiSkinInstance::post(NIFFile *nif)
|
|||
|
||||
for(size_t i=0; i<bnum; i++)
|
||||
{
|
||||
if(!bones.has(i))
|
||||
if(bones[i].empty())
|
||||
nif->fail("Oops: Missing bone! Don't know how to handle this.");
|
||||
bones[i].makeBone(i, data->bones[i]);
|
||||
bones[i]->makeBone(i, data->bones[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Ogre::Matrix4 Node::getLocalTransform()
|
||||
{
|
||||
Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY);
|
||||
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
|
||||
return mat4;
|
||||
}
|
||||
|
||||
Ogre::Matrix4 Node::getWorldTransform()
|
||||
{
|
||||
if(parent != NULL)
|
||||
return parent->getWorldTransform() * getLocalTransform();
|
||||
return getLocalTransform();
|
||||
}
|
||||
|
|
|
@ -26,9 +26,12 @@
|
|||
|
||||
#include <OgreResourceGroupManager.h>
|
||||
#include <OgreDataStream.h>
|
||||
#include <OgreVector2.h>
|
||||
#include <OgreVector3.h>
|
||||
#include <OgreVector4.h>
|
||||
#include <OgreMatrix3.h>
|
||||
#include <OgreQuaternion.h>
|
||||
#include <OgreStringConverter.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
@ -97,6 +100,12 @@ public:
|
|||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
void warn(const std::string &msg)
|
||||
{
|
||||
std::cerr<< "NIFFile Warning: "<<msg <<std::endl
|
||||
<< "File: "<<filename <<std::endl;
|
||||
}
|
||||
|
||||
/// Open a NIF stream. The name is used for error messages.
|
||||
NIFFile(const std::string &name)
|
||||
: filename(name)
|
||||
|
@ -133,6 +142,13 @@ public:
|
|||
unsigned short getUShort() { return read_le16(); }
|
||||
int getInt() { return read_le32(); }
|
||||
float getFloat() { return read_le32f(); }
|
||||
Ogre::Vector2 getVector2()
|
||||
{
|
||||
float a[2];
|
||||
for(size_t i = 0;i < 2;i++)
|
||||
a[i] = getFloat();
|
||||
return Ogre::Vector2(a);
|
||||
}
|
||||
Ogre::Vector3 getVector3()
|
||||
{
|
||||
float a[3];
|
||||
|
@ -157,13 +173,19 @@ public:
|
|||
}
|
||||
return Ogre::Matrix3(a);
|
||||
}
|
||||
Ogre::Quaternion getQuaternion()
|
||||
{
|
||||
float a[4];
|
||||
for(size_t i = 0;i < 4;i++)
|
||||
a[i] = getFloat();
|
||||
return Ogre::Quaternion(a);
|
||||
}
|
||||
Transformation getTrafo()
|
||||
{
|
||||
Transformation t;
|
||||
t.pos = getVector3();
|
||||
t.rotation = getMatrix3();
|
||||
t.scale = getFloat();
|
||||
t.velocity = getVector3();
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -193,7 +215,101 @@ public:
|
|||
for(size_t i = 0;i < vec.size();i++)
|
||||
vec[i] = getFloat();
|
||||
}
|
||||
void getVector2s(std::vector<Ogre::Vector2> &vec, size_t size)
|
||||
{
|
||||
vec.resize(size);
|
||||
for(size_t i = 0;i < vec.size();i++)
|
||||
vec[i] = getVector2();
|
||||
}
|
||||
void getVector3s(std::vector<Ogre::Vector3> &vec, size_t size)
|
||||
{
|
||||
vec.resize(size);
|
||||
for(size_t i = 0;i < vec.size();i++)
|
||||
vec[i] = getVector3();
|
||||
}
|
||||
void getVector4s(std::vector<Ogre::Vector4> &vec, size_t size)
|
||||
{
|
||||
vec.resize(size);
|
||||
for(size_t i = 0;i < vec.size();i++)
|
||||
vec[i] = getVector4();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct KeyT {
|
||||
float mTime;
|
||||
T mValue;
|
||||
T mForwardValue; // Only for Quadratic interpolation
|
||||
T mBackwardValue; // Only for Quadratic interpolation
|
||||
float mTension; // Only for TBC interpolation
|
||||
float mBias; // Only for TBC interpolation
|
||||
float mContinuity; // Only for TBC interpolation
|
||||
};
|
||||
typedef KeyT<float> FloatKey;
|
||||
typedef KeyT<Ogre::Vector3> Vector3Key;
|
||||
typedef KeyT<Ogre::Vector4> Vector4Key;
|
||||
typedef KeyT<Ogre::Quaternion> QuaternionKey;
|
||||
|
||||
template<typename T, T (NIFFile::*getValue)()>
|
||||
struct KeyListT {
|
||||
typedef std::vector< KeyT<T> > VecType;
|
||||
|
||||
static const int sLinearInterpolation = 1;
|
||||
static const int sQuadraticInterpolation = 2;
|
||||
static const int sTBCInterpolation = 3;
|
||||
|
||||
int mInterpolationType;
|
||||
VecType mKeys;
|
||||
|
||||
void read(NIFFile *nif, bool force=false)
|
||||
{
|
||||
size_t count = nif->getInt();
|
||||
if(count == 0 && !force)
|
||||
return;
|
||||
|
||||
mInterpolationType = nif->getInt();
|
||||
mKeys.resize(count);
|
||||
if(mInterpolationType == sLinearInterpolation)
|
||||
{
|
||||
for(size_t i = 0;i < count;i++)
|
||||
{
|
||||
KeyT<T> &key = mKeys[i];
|
||||
key.mTime = nif->getFloat();
|
||||
key.mValue = (nif->*getValue)();
|
||||
}
|
||||
}
|
||||
else if(mInterpolationType == sQuadraticInterpolation)
|
||||
{
|
||||
for(size_t i = 0;i < count;i++)
|
||||
{
|
||||
KeyT<T> &key = mKeys[i];
|
||||
key.mTime = nif->getFloat();
|
||||
key.mValue = (nif->*getValue)();
|
||||
key.mForwardValue = (nif->*getValue)();
|
||||
key.mBackwardValue = (nif->*getValue)();
|
||||
}
|
||||
}
|
||||
else if(mInterpolationType == sTBCInterpolation)
|
||||
{
|
||||
for(size_t i = 0;i < count;i++)
|
||||
{
|
||||
KeyT<T> &key = mKeys[i];
|
||||
key.mTime = nif->getFloat();
|
||||
key.mValue = (nif->*getValue)();
|
||||
key.mTension = nif->getFloat();
|
||||
key.mBias = nif->getFloat();
|
||||
key.mContinuity = nif->getFloat();
|
||||
}
|
||||
}
|
||||
else
|
||||
nif->warn("Unhandled interpolation type: "+Ogre::StringConverter::toString(mInterpolationType));
|
||||
}
|
||||
};
|
||||
typedef KeyListT<float,&NIFFile::getFloat> FloatKeyList;
|
||||
typedef KeyListT<Ogre::Vector3,&NIFFile::getVector3> Vector3KeyList;
|
||||
typedef KeyListT<Ogre::Vector4,&NIFFile::getVector4> Vector4KeyList;
|
||||
typedef KeyListT<Ogre::Quaternion,&NIFFile::getQuaternion> QuaternionKeyList;
|
||||
|
||||
} // Namespace
|
||||
#endif
|
||||
|
|
|
@ -37,21 +37,12 @@ struct Transformation
|
|||
Ogre::Vector3 pos;
|
||||
Ogre::Matrix3 rotation;
|
||||
float scale;
|
||||
Ogre::Vector3 velocity;
|
||||
|
||||
static const Transformation& getIdentity()
|
||||
{
|
||||
static Transformation identity;
|
||||
static bool iset = false;
|
||||
if (!iset)
|
||||
{
|
||||
identity.scale = 1.0f;
|
||||
identity.rotation[0][0] = 1.0f;
|
||||
identity.rotation[1][1] = 1.0f;
|
||||
identity.rotation[2][2] = 1.0f;
|
||||
iset = true;
|
||||
}
|
||||
|
||||
static const Transformation identity = {
|
||||
Ogre::Vector3::ZERO, Ogre::Matrix3::IDENTITY, 1.0f
|
||||
};
|
||||
return identity;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef _NIF_NODE_H_
|
||||
#define _NIF_NODE_H_
|
||||
|
||||
#include <OgreMatrix4.h>
|
||||
|
||||
#include "controlled.hpp"
|
||||
#include "data.hpp"
|
||||
#include "property.hpp"
|
||||
|
@ -43,6 +45,7 @@ public:
|
|||
// Node flags. Interpretation depends somewhat on the type of node.
|
||||
int flags;
|
||||
Transformation trafo;
|
||||
Ogre::Vector3 velocity; // Unused? Might be a run-time game state
|
||||
PropertyList props;
|
||||
|
||||
// Bounding box info
|
||||
|
@ -57,6 +60,7 @@ public:
|
|||
|
||||
flags = nif->getUShort();
|
||||
trafo = nif->getTrafo();
|
||||
velocity = nif->getVector3();
|
||||
props.read(nif);
|
||||
|
||||
hasBounds = !!nif->getInt();
|
||||
|
@ -106,20 +110,9 @@ public:
|
|||
boneTrafo = &bi.trafo;
|
||||
boneIndex = ind;
|
||||
}
|
||||
};
|
||||
|
||||
struct NiTriShapeCopy
|
||||
{
|
||||
std::string sname;
|
||||
std::vector<std::string> boneSequence;
|
||||
Nif::NiSkinData::BoneTrafoCopy trafo;
|
||||
//Ogre::Quaternion initialBoneRotation;
|
||||
//Ogre::Vector3 initialBoneTranslation;
|
||||
std::vector<Ogre::Vector3> vertices;
|
||||
std::vector<Ogre::Vector3> normals;
|
||||
std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfo;
|
||||
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> > vertsToWeights;
|
||||
Nif::NiMorphData morph;
|
||||
Ogre::Matrix4 getLocalTransform();
|
||||
Ogre::Matrix4 getWorldTransform();
|
||||
};
|
||||
|
||||
struct NiNode : Node
|
||||
|
@ -151,8 +144,8 @@ struct NiNode : Node
|
|||
for(size_t i = 0;i < children.length();i++)
|
||||
{
|
||||
// Why would a unique list of children contain empty refs?
|
||||
if(children.has(i))
|
||||
children[i].parent = this;
|
||||
if(!children[i].empty())
|
||||
children[i]->parent = this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -182,28 +175,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
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef _NIF_RECORD_H_
|
||||
#define _NIF_RECORD_H_
|
||||
|
||||
#include <components/misc/slice_array.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Nif
|
||||
{
|
||||
|
|
|
@ -71,18 +71,21 @@ public:
|
|||
}
|
||||
|
||||
/// Look up the actual object from the index
|
||||
X* getPtr()
|
||||
X* getPtr() const
|
||||
{
|
||||
assert(ptr != NULL);
|
||||
return ptr;
|
||||
}
|
||||
X& get() { return *getPtr(); }
|
||||
X& get() const
|
||||
{ return *getPtr(); }
|
||||
|
||||
/// Syntactic sugar
|
||||
X* operator->() { return getPtr(); }
|
||||
X* operator->() const
|
||||
{ return getPtr(); }
|
||||
|
||||
/// Pointers are allowed to be empty
|
||||
bool empty() { return ptr == NULL; }
|
||||
bool empty() const
|
||||
{ return ptr == NULL; }
|
||||
};
|
||||
|
||||
/** A list of references to other records. These are read as a list,
|
||||
|
@ -111,17 +114,10 @@ public:
|
|||
list[i].post(nif);
|
||||
}
|
||||
|
||||
X& operator[](size_t index)
|
||||
{
|
||||
return list.at(index).get();
|
||||
}
|
||||
const Ptr& operator[](size_t index) const
|
||||
{ return list.at(index); }
|
||||
|
||||
bool has(size_t index)
|
||||
{
|
||||
return !list.at(index).empty();
|
||||
}
|
||||
|
||||
size_t length()
|
||||
size_t length() const
|
||||
{ return list.size(); }
|
||||
};
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
@ -138,9 +138,9 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
|
|||
int n = list.length();
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
if (list.has(i))
|
||||
if (!list[i].empty())
|
||||
{
|
||||
if(hasRootCollisionNode(&list[i])) return true;;
|
||||
if(hasRootCollisionNode(list[i].getPtr())) return true;;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +204,6 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
|||
// For both position and rotation we have that:
|
||||
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
||||
final.pos = trafo->pos + trafo->rotation*final.pos*trafo->scale;
|
||||
final.velocity = trafo->velocity + trafo->rotation*final.velocity*trafo->scale;
|
||||
|
||||
// Merge the rotations together
|
||||
final.rotation = trafo->rotation * final.rotation;
|
||||
|
@ -222,9 +221,9 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
|||
int n = list.length();
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
if (list.has(i))
|
||||
if (!list[i].empty())
|
||||
{
|
||||
handleNode(&list[i], flags,&node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly);
|
||||
handleNode(list[i].getPtr(), flags,&node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,8 +238,8 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
|
|||
int n = list.length();
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
if (list.has(i))
|
||||
handleNode(&list[i], flags,&node->trafo, hasCollisionNode,true,raycastingOnly);
|
||||
if (!list[i].empty())
|
||||
handleNode(list[i].getPtr(), flags,&node->trafo, hasCollisionNode,true,raycastingOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,19 +271,16 @@ void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags
|
|||
|
||||
Nif::NiTriShapeData *data = shape->data.getPtr();
|
||||
|
||||
float* vertices = &data->vertices[0];
|
||||
short* triangles = &data->triangles[0];
|
||||
const std::vector<Ogre::Vector3> &vertices = data->vertices;
|
||||
const Ogre::Matrix3 &rot = shape->trafo.rotation;
|
||||
const Ogre::Vector3 &pos = shape->trafo.pos;
|
||||
float scale = shape->trafo.scale;
|
||||
for(unsigned int i=0; i < data->triangles.size(); i = i+3)
|
||||
float scale = shape->trafo.scale * parentScale;
|
||||
short* triangles = &data->triangles[0];
|
||||
for(size_t i = 0;i < data->triangles.size();i+=3)
|
||||
{
|
||||
Ogre::Vector3 b1(vertices[triangles[i+0]*3]*parentScale,vertices[triangles[i+0]*3+1]*parentScale,vertices[triangles[i+0]*3+2]*parentScale);
|
||||
Ogre::Vector3 b2(vertices[triangles[i+1]*3]*parentScale,vertices[triangles[i+1]*3+1]*parentScale,vertices[triangles[i+1]*3+2]*parentScale);
|
||||
Ogre::Vector3 b3(vertices[triangles[i+2]*3]*parentScale,vertices[triangles[i+2]*3+1]*parentScale,vertices[triangles[i+2]*3+2]*parentScale);
|
||||
b1 = pos + rot*b1*scale;
|
||||
b2 = pos + rot*b2*scale;
|
||||
b3 = pos + rot*b3*scale;
|
||||
Ogre::Vector3 b1 = pos + rot*vertices[triangles[i+0]]*scale;
|
||||
Ogre::Vector3 b2 = pos + rot*vertices[triangles[i+1]]*scale;
|
||||
Ogre::Vector3 b3 = pos + rot*vertices[triangles[i+2]]*scale;
|
||||
mTriMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,7 +26,10 @@
|
|||
|
||||
#include <OgreResource.h>
|
||||
#include <OgreMesh.h>
|
||||
#include <OgreSkeleton.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
|
@ -55,112 +58,47 @@ namespace Nif
|
|||
namespace NifOgre
|
||||
{
|
||||
|
||||
// FIXME: These should not be in NifOgre, it works agnostic of what model format is used
|
||||
typedef std::map<float,std::string> TextKeyMap;
|
||||
struct EntityList {
|
||||
std::vector<Ogre::Entity*> mEntities;
|
||||
Ogre::Entity *mSkelBase;
|
||||
|
||||
EntityList() : mSkelBase(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/** This holds a list of meshes along with the names of their parent nodes
|
||||
*/
|
||||
typedef std::vector< std::pair<Ogre::MeshPtr,std::string> > MeshPairList;
|
||||
|
||||
/** Manual resource loader for NIF meshes. This is the main class
|
||||
responsible for translating the internal NIF mesh structure into
|
||||
something Ogre can use. 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:
|
||||
|
||||
NIFLoader::load("somemesh.nif");
|
||||
|
||||
Afterwards, you can use the mesh name "somemesh.nif" normally to
|
||||
create entities and so on. The mesh isn't loaded from disk until
|
||||
OGRE needs it for rendering. Thus the above load() command is not
|
||||
very resource intensive, and can safely be done for a large number
|
||||
of meshes at load time.
|
||||
This returns a list of meshes used by the model, as well as the names of
|
||||
their parent nodes (as they pertain to the skeleton, which is optionally
|
||||
returned in the second argument if it exists).
|
||||
*/
|
||||
class NIFLoader : Ogre::ManualResourceLoader
|
||||
class NIFLoader
|
||||
{
|
||||
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<Nif::NiKeyframeData>* getAnim(std::string name);
|
||||
std::vector<Nif::NiTriShapeCopy>* getShapes(std::string name);
|
||||
std::map<std::string, float>* 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<std::string> boneSequence);
|
||||
|
||||
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds, Nif::Transformation original, std::vector<std::string> boneSequence);
|
||||
|
||||
void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list<Ogre::VertexBoneAssignment> &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,
|
||||
bool vertexColor);
|
||||
|
||||
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<std::string,std::string> MaterialMap;
|
||||
|
||||
// pointer to the ogre mesh which is currently build
|
||||
Ogre::Mesh *mesh;
|
||||
Ogre::SkeletonPtr mSkel;
|
||||
Ogre::Vector3 vector;
|
||||
std::vector<Nif::NiTriShapeCopy> shapes;
|
||||
std::string name;
|
||||
std::string triname;
|
||||
std::vector<Nif::NiKeyframeData> allanim;
|
||||
|
||||
std::map<std::string,float> textmappings;
|
||||
std::map<std::string,std::map<std::string,float>,ciLessBoost> alltextmappings;
|
||||
std::map<std::string,std::vector<Nif::NiKeyframeData>,ciLessBoost> allanimmap;
|
||||
std::map<std::string,std::vector<Nif::NiTriShapeCopy>,ciLessBoost> allshapesmap;
|
||||
std::vector<Nif::NiKeyframeData> mAnim;
|
||||
std::vector<Nif::NiTriShapeCopy> mS;
|
||||
std::vector<Ogre::SubMesh*> needBoneAssignments;
|
||||
bool inTheSkeletonTree;
|
||||
static MeshPairList load(std::string name, std::string skelName, TextKeyMap *textkeys, const std::string &group);
|
||||
|
||||
public:
|
||||
static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename,
|
||||
Ogre::SceneNode *parentNode,
|
||||
const std::string &name,
|
||||
const std::string &group="General");
|
||||
|
||||
static EntityList createEntities(Ogre::SceneNode *parent,
|
||||
TextKeyMap *textkeys,
|
||||
const std::string &name,
|
||||
const std::string &group="General");
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue