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,43 +426,214 @@ 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();
int magic = nif->getInt();
int type = nif->getInt();
for(int i = 0; i < vertCount; i++){
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));
}
for(int i=1; i<morphCount; i++)
{
int magic = nif->getInt();
nif->getInt();
if(magic)
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
nif->getFloatLen(4*magic);
nif->getFloatLen(vertCount*3);
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:
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)
{
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)
//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++)
{
@ -467,20 +652,69 @@ class NiKeyframeData : public Record
}
else nif->fail("Unknown rotation type in NiKeyframeData");
}
//first = false;
// 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
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");
}
@ -488,16 +722,101 @@ class NiKeyframeData : public Record
count = nif->getInt();
if(count)
{
int type = nif->getInt();
stype = 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
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");
nif->getFloatLen(count*size);
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,6 +822,8 @@ 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];
@ -809,27 +831,67 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
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;
}
@ -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;
@ -52,6 +81,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
something Ogre can use. Later it will also handle the insertion of
@ -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