mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
More NIFLoader code
This commit is contained in:
parent
828a3904a5
commit
e8ec9093f8
4 changed files with 655 additions and 101 deletions
|
@ -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();
|
||||
int magic = nif->getInt();
|
||||
int type = nif->getInt();
|
||||
for(int i = 0; i < vertCount; i++){
|
||||
|
||||
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);
|
||||
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:
|
||||
std::string bonename;
|
||||
//Rotations
|
||||
std::vector<Ogre::Quaternion> quats;
|
||||
std::vector<Ogre::Vector3> tbc;
|
||||
std::vector<float> rottime;
|
||||
float startTime;
|
||||
float stopTime;
|
||||
int rtype;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
// Rotations first
|
||||
int count = nif->getInt();
|
||||
if(count)
|
||||
{
|
||||
int type = nif->getInt();
|
||||
//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;
|
||||
|
||||
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");
|
||||
}
|
||||
//Scalings
|
||||
|
||||
// Then translation
|
||||
count = nif->getInt();
|
||||
std::vector<float> scalefactor;
|
||||
std::vector<float> scaletime;
|
||||
std::vector<float> forwards;
|
||||
std::vector<float> backwards;
|
||||
std::vector<Ogre::Vector3> tbcscale;
|
||||
int stype;
|
||||
|
||||
if(count)
|
||||
{
|
||||
int type = nif->getInt();
|
||||
|
||||
|
||||
public:
|
||||
void clone(NiKeyframeData c)
|
||||
{
|
||||
quats = c.getQuat();
|
||||
tbc = c.getrTbc();
|
||||
rottime = c.getrTime();
|
||||
|
||||
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");
|
||||
}
|
||||
//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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // 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() +
|
||||
|
||||
|
||||
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++)
|
||||
{
|
||||
vecPos = bonePtr->_getDerivedPosition() +
|
||||
bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans);
|
||||
|
||||
vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation);
|
||||
|
||||
for (unsigned int i=0; i<it->weights.length; i++)
|
||||
{
|
||||
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…
Reference in a new issue