More NIFLoader code

actorid
Jason Hooks 13 years ago
parent 828a3904a5
commit e8ec9093f8

@ -26,6 +26,7 @@
#include "controlled.hpp"
#include <iostream>
#include <Ogre.h>
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<VertWeight> weights;
};
struct BoneInfoCopy
{
std::string bonename;
BoneTrafoCopy trafo;
Vector4 unknown;
std::vector<VertWeight> weights;
};
const BoneTrafo *trafo;
std::vector<BoneInfo> bones;
@ -412,92 +426,397 @@ public:
class 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:
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<Ogre::Vector3> getInitialVertices(){
return initialVertices;
}
std::vector<std::vector<Ogre::Vector3>> getRelevantData(){
return relevantData;
}
std::vector<std::vector<float>> getRelevantTimes(){
return relevantTimes;
}
std::vector<std::vector<Ogre::Vector3>> getAdditionalVertices(){
return additionalVertices;
}
void read(NIFFile *nif)
{
int morphCount = nif->getInt();
int vertCount = nif->getInt();
nif->getByte();
for(int i=0; i<morphCount; i++)
{
int magic = nif->getInt();
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; 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);
}
}
};
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;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");
}
// 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<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(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<Ogre::Quaternion> quat(count);
//std::vector<float> 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;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){
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<Ogre::Quaternion> getQuat(){
return quats;
}
std::vector<Ogre::Vector3> getrTbc(){
return tbc;
}
std::vector<float> getrTime(){
return rottime;
}
std::vector<Ogre::Vector3> getTranslist1(){
return translist1;
}
std::vector<Ogre::Vector3> getTranslist2(){
return translist2;
}
std::vector<Ogre::Vector3> getTranslist3(){
return translist3;
}
std::vector<float> gettTime(){
return transtime;
}
std::vector<float> getScalefactor(){
return scalefactor;
}
std::vector<float> getForwards(){
return forwards;
}
std::vector<float> getBackwards(){
return backwards;
}
std::vector<Ogre::Vector3> getScaleTbc(){
return tbcscale;
}
std::vector<float> getsTime(){
return scaletime;
}
std::string getBonename(){ return bonename;
}
};
} // Namespace

@ -93,6 +93,19 @@ public:
}
};
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;
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

@ -24,25 +24,7 @@
//loadResource->handleNode->handleNiTriShape->createSubMesh
#include "ogre_nif_loader.hpp"
#include <Ogre.h>
#include <stdio.h>
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
#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 <libs/platform/strings.h>
#include <vector>
#include <list>
// For warning messages
#include <iostream>
// float infinity
#include <limits>
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<std::string> boneSequence)
{
assert(shape != NULL);
@ -744,11 +726,39 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
std::list<VertexBoneAssignment> vertexBoneAssignments;
Nif::NiTriShapeCopy copy = shape->clone();
if(!shape->controller.empty())
{
//Nif::NiGeomMorpherController* cont = dynamic_cast<Nif::NiGeomMorpherController*> (shape->controller.getPtr());
Nif::Controller* cont = shape->controller.getPtr();
if(cont->recType == RC_NiGeomMorpherController)
{
Nif::NiGeomMorpherController* morph = dynamic_cast<Nif::NiGeomMorpherController*> (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<Ogre::Vector3> vertices;
//std::vector<Ogre::Vector3> normals;
//std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfo;
// vector that stores if the position if a vertex is absolute
std::vector<bool> vertexPosAbsolut(numVerts,false);
std::vector<Ogre::Vector3> vertexPosOriginal(numVerts, Ogre::Vector3::ZERO);
std::vector<Ogre::Vector3> 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; i<it->weights.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; i<numVerts; i++)
{
vectorMulAdd(rot, pos, ptr, scale);
Ogre::Vector3 absVertPos = Ogre::Vector3(*(ptr + 3 * i), *(ptr + 3 * i + 1), *(ptr + 3 * i + 2));
mBoundingBox.merge(absVertPos);
ptr += 3;
}
// Remember to rotate all the vertex normals as well
if (data->normals.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<std::string> 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<Nif::NiTextKeyExtraData*> (e);
std::vector<Nif::NiTextKeyExtraData::TextKey>::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<NiTriShape*>(node), flags, bounds);
std::string nodename = node->name.toString();
if (triname == "")
{
handleNiTriShape(dynamic_cast<NiTriShape*>(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<NiTriShape*>(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<std::string> boneSequence;
handleNode(node, 0, NULL, bounds, 0, boneSequence);
// set the bounding value.
if (bounds.isValid())

@ -28,10 +28,39 @@
#include <OgreMesh.h>
#include <assert.h>
#include <string>
#include <boost/algorithm/string.hpp>
#include <Ogre.h>
#include <stdio.h>
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
#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 <libs/platform/strings.h>
#include <vector>
#include <list>
// For warning messages
#include <iostream>
// float infinity
#include <limits>
using namespace boost::algorithm;
class BoundsFinder;
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
{
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<std::string> boneSequence);
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
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);
@ -139,6 +169,14 @@ class NIFLoader : Ogre::ManualResourceLoader
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;
};
}

Loading…
Cancel
Save