diff --git a/components/nif/data.hpp b/components/nif/data.hpp index c483b4873..f4c907edb 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -26,6 +26,7 @@ #include "controlled.hpp" #include +#include namespace Nif { @@ -366,6 +367,12 @@ public: Vector trans; // Translation float scale; // Probably scale (always 1) }; + struct BoneTrafoCopy + { + Ogre::Quaternion rotation; + Ogre::Vector3 trans; + float scale; + }; struct VertWeight { @@ -380,6 +387,13 @@ public: const Vector4 *unknown; Misc::SliceArray weights; }; + struct BoneInfoCopy + { + std::string bonename; + BoneTrafoCopy trafo; + Vector4 unknown; + std::vector weights; + }; const BoneTrafo *trafo; std::vector bones; @@ -412,92 +426,397 @@ public: class NiMorphData : public Record { + float startTime; + float stopTime; + std::vector initialVertices; + std::vector> relevantTimes; + std::vector> relevantData; + std::vector> additionalVertices; + + public: - void read(NIFFile *nif) + float getStartTime(){ + return startTime; + } + float getStopTime(){ + return stopTime; + } + void setStartTime(float time){ + startTime = time; + } + + void setStopTime(float time){ + stopTime = time; + } + std::vector getInitialVertices(){ + return initialVertices; + } + std::vector> getRelevantData(){ + return relevantData; + } + std::vector> getRelevantTimes(){ + return relevantTimes; + } + std::vector> getAdditionalVertices(){ + return additionalVertices; + } + +void read(NIFFile *nif) { int morphCount = nif->getInt(); int vertCount = nif->getInt(); nif->getByte(); - - for(int i=0; igetInt(); - nif->getInt(); - if(magic) - // Time, data, forward, backward tangents - nif->getFloatLen(4*magic); - - nif->getFloatLen(vertCount*3); + int magic = nif->getInt(); + int type = nif->getInt(); + for(int i = 0; i < vertCount; i++){ + + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + initialVertices.push_back(Ogre::Vector3(x, y, z)); + } + + for(int i=1; igetInt(); + type = nif->getInt(); + std::vector current; + std::vector currentTime; + for(int i = 0; i < magic; i++){ + // Time, data, forward, backward tangents + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + current.push_back(Ogre::Vector3(x,y,z)); + currentTime.push_back(time); + //nif->getFloatLen(4*magic); + } + if(magic){ + relevantData.push_back(current); + relevantTimes.push_back(currentTime); + } + std::vector verts; + for(int i = 0; i < vertCount; i++){ + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + verts.push_back(Ogre::Vector3(x, y, z)); + } + additionalVertices.push_back(verts); } } }; + class NiKeyframeData : public Record { - public: - - void read(NIFFile *nif) - { - // Rotations first - int count = nif->getInt(); - if(count) - { - int type = nif->getInt(); - - if(type == 1) - nif->skip(count*4*5); // time + quaternion - else if(type == 3) - nif->skip(count*4*8); // rot1 + tension+bias+continuity - else if(type == 4) - { - for(int j=0;jgetFloat(); // time - for(int i=0; i<3; i++) - { - int cnt = nif->getInt(); - int type = nif->getInt(); - if(type == 1) - nif->skip(cnt*4*2); // time + unknown - else if(type == 2) - nif->skip(cnt*4*4); // time + unknown vector - else nif->fail("Unknown sub-rotation type"); - } - } - } - else nif->fail("Unknown rotation type in NiKeyframeData"); - } - - // Then translation - count = nif->getInt(); - - if(count) - { - int type = nif->getInt(); - - if(type == 1) - nif->getFloatLen(count*4); // time + translation - else if(type == 2) - nif->getFloatLen(count*10); // trans1 + forward + backward - else if(type == 3) - nif->getFloatLen(count*7); // trans1 + tension,bias,continuity - else nif->fail("Unknown translation type"); - } - - // Finally, scalings - count = nif->getInt(); - if(count) - { - int type = nif->getInt(); - - int size = 0; - if(type == 1) size = 2; // time+scale - else if(type == 2) size = 4; // 1 + forward + backward (floats) - else if(type == 3) size = 5; // 1 + tbc - else nif->fail("Unknown scaling type"); - nif->getFloatLen(count*size); - } - } + std::string bonename; + //Rotations + std::vector quats; + std::vector tbc; + std::vector rottime; + float startTime; + float stopTime; + int rtype; + + //Translations + std::vector translist1; + std::vector translist2; + std::vector translist3; + std::vector transtbc; + std::vector transtime; + int ttype; + + //Scalings + + std::vector scalefactor; + std::vector scaletime; + std::vector forwards; + std::vector backwards; + std::vector tbcscale; + int stype; + + + +public: + void clone(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; + } + void read(NIFFile *nif) + { + // Rotations first + int count = nif->getInt(); + //std::vector quat(count); + //std::vector rottime(count); + std::cout << "r"; + 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"; + } + + //nif->skip(count*4*8); // rot1 + tension+bias+continuity + } + else if(rtype == 4) + { + for(int j=0;jgetFloat(); // time + for(int i=0; i<3; i++) + { + int cnt = nif->getInt(); + int type = nif->getInt(); + if(type == 1) + nif->skip(cnt*4*2); // time + unknown + else if(type == 2) + nif->skip(cnt*4*4); // time + unknown vector + else nif->fail("Unknown sub-rotation type"); + } + } + } + else nif->fail("Unknown rotation type in NiKeyframeData"); + } + //first = false; + + // Then translation + count = nif->getInt(); + + if(count) + { + ttype = nif->getInt(); + + //std::cout << "TransCount:" << count << " Type: " << type << "\n"; + if(ttype == 1) { + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + Ogre::Vector3 trans = Ogre::Vector3(x, y, z); + translist1.push_back(trans); + transtime.push_back(time); + } + //nif->getFloatLen(count*4); // time + translation + } + else if(ttype == 2) + { //Example - node 116 in base_anim.nif + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + float x2 = nif->getFloat(); + float y2 = nif->getFloat(); + float z2 = nif->getFloat(); + float x3 = nif->getFloat(); + float y3 = nif->getFloat(); + float z3 = nif->getFloat(); + Ogre::Vector3 trans = Ogre::Vector3(x, y, z); + Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2); + Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3); + transtime.push_back(time); + translist1.push_back(trans); + translist2.push_back(trans2); + translist3.push_back(trans3); + } + + //nif->getFloatLen(count*10); // trans1 + forward + backward + } + else if(ttype == 3){ + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + float t = nif->getFloat(); + float b = nif->getFloat(); + float c = nif->getFloat(); + Ogre::Vector3 trans = Ogre::Vector3(x, y, z); + Ogre::Vector3 tbc = Ogre::Vector3(t, b, c); + translist1.push_back(trans); + transtbc.push_back(tbc); + transtime.push_back(time); + } + //nif->getFloatLen(count*7); // trans1 + tension,bias,continuity + } + else nif->fail("Unknown translation type"); + } + + // Finally, scalings + count = nif->getInt(); + if(count) + { + stype = nif->getInt(); + + + for(int i = 0; i < count; i++){ + + + //int size = 0; + if(stype >= 1 && stype < 4) + { + float time = nif->getFloat(); + float scale = nif->getFloat(); + scaletime.push_back(time); + scalefactor.push_back(scale); + //size = 2; // time+scale + } + else nif->fail("Unknown scaling type"); + if(stype == 2){ + //size = 4; // 1 + forward + backward (floats) + float forward = nif->getFloat(); + float backward = nif->getFloat(); + forwards.push_back(forward); + backwards.push_back(backward); + } + else if(stype == 3){ + float tbcx = nif->getFloat(); + float tbcy = nif->getFloat(); + float tbcz = nif->getFloat(); + Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz); + tbcscale.push_back(vec); + + //size = 5; // 1 + tbc + } + + } + } + else + stype = 0; + } + int getRtype(){ + return rtype; + } + int getStype(){ + return stype; + } + int getTtype(){ + return ttype; + } + float getStartTime(){ + return startTime; + } + float getStopTime(){ + return stopTime; + } + std::vector getQuat(){ + return quats; + } + std::vector getrTbc(){ + return tbc; + } + std::vector getrTime(){ + return rottime; + } + + std::vector getTranslist1(){ + return translist1; + } + std::vector getTranslist2(){ + return translist2; + } + std::vector getTranslist3(){ + return translist3; + } + std::vector gettTime(){ + return transtime; + } + std::vector getScalefactor(){ + return scalefactor; + } + std::vector getForwards(){ + return forwards; + } + std::vector getBackwards(){ + return backwards; + } + std::vector getScaleTbc(){ + return tbcscale; + } + + std::vector getsTime(){ + return scaletime; + } + std::string getBonename(){ return bonename; + } + + }; } // Namespace diff --git a/components/nif/node.hpp b/components/nif/node.hpp index f0ad54655..02387d219 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -93,6 +93,19 @@ 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; + Nif::NiMorphData morph; +}; + struct NiNode : Node { NodeList children; @@ -133,6 +146,27 @@ struct NiTriShape : Node data.read(nif); skin.read(nif); } + + NiTriShapeCopy clone(){ + NiTriShapeCopy copy; + copy.sname = name.toString(); + float *ptr = (float*)data->vertices.ptr; + float *ptrNormals = (float*)data->normals.ptr; + int numVerts = data->vertices.length / 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 @@ -186,5 +220,7 @@ struct NiRotatingParticles : Node } }; + + } // Namespace #endif diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 9f98c98d8..b8596d3c5 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -24,25 +24,7 @@ //loadResource->handleNode->handleNiTriShape->createSubMesh #include "ogre_nif_loader.hpp" -#include -#include - -#include -#include "../nif/nif_file.hpp" -#include "../nif/node.hpp" -#include "../nif/data.hpp" -#include "../nif/property.hpp" -#include "../nif/controller.hpp" -#include "../nif/extra.hpp" -#include - -#include -#include -// For warning messages -#include - -// float infinity -#include + typedef unsigned char ubyte; @@ -583,7 +565,7 @@ static void vectorMul(const Matrix &A, float *C) } -void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds) +void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds, Transformation original, std::vector boneSequence) { assert(shape != NULL); @@ -744,11 +726,39 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou std::list vertexBoneAssignments; + Nif::NiTriShapeCopy copy = shape->clone(); + if(!shape->controller.empty()) + { + //Nif::NiGeomMorpherController* cont = dynamic_cast (shape->controller.getPtr()); + 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); + //std::cout << "Size" << morph->data->getInitialVertices().size() << "\n"; + + } + + //std::cout << "We have a controller"; + } //use niskindata for the position of vertices. if (!shape->skin.empty()) { + + //std::cout << "Skin is not empty\n"; + //Bone assignments are stored in submeshes, so we don't need to copy them + //std::string triname + //std::vector vertices; + //std::vector normals; + //std::vector boneinfo; + + // vector that stores if the position if 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.ptr; //the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex] @@ -775,24 +785,34 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou break; } //get the bone from bones array of skindata + if(!mSkel->hasBone(shape->skin->bones[boneIndex].name.toString())) + std::cout << "We don't have this bone"; bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString()); // final_vector = old_vector + old_rotation*new_vector*old_scale - vecPos = bonePtr->_getDerivedPosition() + - bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans); - - vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation); + + Nif::NiSkinData::BoneInfoCopy boneinfo; + boneinfo.trafo.rotation = convertRotation(it->trafo->rotation); + boneinfo.trafo.trans = convertVector3(it->trafo->trans); + boneinfo.bonename = shape->skin->bones[boneIndex].name.toString(); for (unsigned int i=0; iweights.length; i++) { - unsigned int verIndex = (it->weights.ptr + i)->vertex; + vecPos = bonePtr->_getDerivedPosition() + + bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans); + vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation); + unsigned int verIndex = (it->weights.ptr + i)->vertex; + boneinfo.weights.push_back(*(it->weights.ptr + i)); //Check if the vertex is relativ, FIXME: Is there a better solution? if (vertexPosAbsolut[verIndex] == false) { //apply transformation to the vertices Vector3 absVertPos = vecPos + vecRot * Vector3(ptr + verIndex *3); + absVertPos = absVertPos * (it->weights.ptr + i)->weight; + vertexPosOriginal[verIndex] = 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]; @@ -802,37 +822,79 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou if (verIndex < data->normals.length) { Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3); - + absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; + vertexNormalOriginal[verIndex] = Vector3(ptrNormals + verIndex *3); + for (int j=0; j<3; j++) (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; } vertexPosAbsolut[verIndex] = true; } + else + { + Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex]; + absVertPos = absVertPos * (it->weights.ptr + i)->weight; + Vector3 old = 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.length) + { + Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex]; + absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; + Vector3 oldNormal = Vector3(ptrNormals + verIndex *3); + absNormalsPos = absNormalsPos + oldNormal; + + for (int j=0; j<3; j++) + (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; + } + } + VertexBoneAssignment vba; vba.boneIndex = bonePtr->getHandle(); vba.vertexIndex = verIndex; vba.weight = (it->weights.ptr + i)->weight; + vertexBoneAssignments.push_back(vba); } + copy.boneinfo.push_back(boneinfo); boneIndex++; } + } else { + + copy.boneSequence = boneSequence; // Rotate, scale and translate all the vertices, const Matrix &rot = shape->trafo->rotation; const Vector &pos = shape->trafo->pos; float scale = shape->trafo->scale; + + copy.trafo.trans = convertVector3(original.pos); + copy.trafo.rotation = convertRotation(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.length) { @@ -843,12 +905,28 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou ptr += 3; } } + if(!mSkel.isNull() ){ + int boneIndex; + Ogre::Bone *parentBone = mSkel->getBone(boneSequence[boneSequence.size() - 1]); + if(parentBone) + boneIndex = parentBone->getHandle(); + else + boneIndex = mSkel->getNumBones() - 1; + for(int i = 0; i < numVerts; i++){ + 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); + shapes.push_back(copy); // Create the submesh createOgreSubMesh(shape, material, vertexBoneAssignments); @@ -877,7 +955,7 @@ void NIFLoader::calculateTransform() } void NIFLoader::handleNode(Nif::Node *node, int flags, - const Transformation *trafo, BoundsFinder &bounds, Bone *parentBone) + const Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence) { //if( MWClass::isChest) // cout << "u:" << node << "\n"; @@ -908,6 +986,48 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, // the engine, just skip this entire node. return; } + + if (e->recType == RC_NiTextKeyExtraData){ + Nif::NiTextKeyExtraData* extra = dynamic_cast (e); + + std::vector::iterator textiter = extra->list.begin(); + //std::ofstream File("Indices" + name + ".txt"); + + //std::string sample = "uy"; + + std::string cut = ""; + for(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 << "End" << end; + + std::cout << "Outputting " << cut << "\n"; + + std::ofstream File("Indices" + cut + ".txt"); + + /*if(File.is_open()) + std::cout << "We could open\n"; + else + std::cout << "We could not\n";*/ + for(; textiter != extra->list.end(); textiter++) + { + //if(textiter->text.toString().find("Torch") < textiter->text.toString().length()) + //std::cout << "Time: " << textiter->time << " " << textiter->text.toString() << "\n"; + std::string text = textiter->text.toString(); + + replace(text.begin(), text.end(), '\n', '/'); + + text.erase(std::remove(text.begin(), text.end(), '\r'), text.end()); + File << "Time: " << textiter->time << "|" << text << "\n"; + + textmappings[text] = textiter->time; + } + File.close(); + } } Bone *bone = 0; @@ -930,6 +1050,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, if (!mSkel.isNull()) //if there is a skeleton { std::string name = node->name.toString(); + boneSequence.push_back(name); //if (isBeast && isChest) // std::cout << "NAME: " << name << "\n"; // Quick-n-dirty workaround for the fact that several @@ -947,7 +1068,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, } } } - + Transformation original = *(node->trafo); // Apply the parent transformation to this node. We overwrite the // existing data with the final transformation. if (trafo) @@ -978,12 +1099,23 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, { if (list.has(i)) - handleNode(&list[i], flags, node->trafo, bounds, bone); + handleNode(&list[i], flags, node->trafo, bounds, bone, boneSequence); } } else if (node->recType == RC_NiTriShape) { - handleNiTriShape(dynamic_cast(node), flags, bounds); + std::string nodename = node->name.toString(); + + if (triname == "") + { + handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); + } + else if(name.length() >= triname.length()) + { + std::transform(nodename.begin(), nodename.end(), nodename.begin(), std::tolower); + if(triname == name.substr(0, triname.length())) + handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); + } } } @@ -993,7 +1125,7 @@ void NIFLoader::loadResource(Resource *resource) mesh = 0; mSkel.setNull(); flip = false; - std::string name = resource->getName(); + name = resource->getName(); char suffix = name.at(name.length() - 2); if(suffix == '*') @@ -1019,6 +1151,31 @@ void NIFLoader::loadResource(Resource *resource) // 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) { //std::cout << "Flipping"; @@ -1070,7 +1227,11 @@ void NIFLoader::loadResource(Resource *resource) } // Handle the node - handleNode(node, 0, NULL, bounds, 0); + std::vector boneSequence; + + + + handleNode(node, 0, NULL, bounds, 0, boneSequence); // set the bounding value. if (bounds.isValid()) diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index b721fedf4..a110e7e4f 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -28,10 +28,39 @@ #include #include #include +#include +#include +#include + +#include +#include "../nif/nif_file.hpp" +#include "../nif/node.hpp" +#include "../nif/data.hpp" +#include "../nif/property.hpp" +#include "../nif/controller.hpp" +#include "../nif/extra.hpp" +#include + +#include +#include +// For warning messages +#include + +// float infinity +#include +using namespace boost::algorithm; class BoundsFinder; +struct ciLessBoost : std::binary_function +{ + bool operator() (const std::string & s1, const std::string & s2) const { + //case insensitive version of is_less + return lexicographical_compare(s1, s2, is_iless()); + } +}; + namespace Nif { class Node; @@ -51,6 +80,7 @@ namespace Mangle namespace NifOgre { + /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into @@ -94,9 +124,9 @@ class NIFLoader : Ogre::ManualResourceLoader void fail(std::string msg); void handleNode( Nif::Node *node, int flags, - const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone); + const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence); - void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds); + 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); @@ -139,6 +169,14 @@ class NIFLoader : Ogre::ManualResourceLoader Ogre::Mesh *mesh; Ogre::SkeletonPtr mSkel; Ogre::Vector3 vector; + std::vector shapes; + std::string name; + std::string triname; + std::vector allanim; + std::map textmappings; + std::map,ciLessBoost> alltextmappings; + std::map,ciLessBoost> allanimmap; + std::map,ciLessBoost> allshapesmap; }; }