Cleanup RecordPtrT

This moves the index resolution into a separate post method instead of always
checking when access. As a result, it reduces the size of it down to the size
of a pointer, as opposed to 2 pointers + 1 int. The appropriate methods are
added to the various node types to make sure they're resolved.
actorid
Chris Robinson 13 years ago
parent efb95e2f83
commit 046e9686f9

@ -25,6 +25,7 @@
#define _NIF_CONTROLLED_H_
#include "extra.hpp"
#include "controller.hpp"
namespace Nif
{
@ -40,6 +41,12 @@ public:
Extra::read(nif);
controller.read(nif);
}
void post(NIFFile *nif)
{
Extra::post(nif);
controller.post(nif);
}
};
/// Has name, extra-data and controller
@ -78,6 +85,12 @@ public:
Controlled::read(nif);
data.read(nif);
}
void post(NIFFile *nif)
{
Controlled::post(nif);
data.post(nif);
}
};
class NiGravity : public Controlled

@ -53,6 +53,13 @@ public:
target.read(nif);
}
void post(NIFFile *nif)
{
Record::post(nif);
next.post(nif);
target.post(nif);
}
};
class NiBSPArrayController : public Controller
@ -80,6 +87,12 @@ public:
Controller::read(nif);
data.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
};
class NiPathController : public Controller
@ -101,6 +114,14 @@ public:
posData.read(nif);
floatData.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
posData.post(nif);
floatData.post(nif);
}
};
class NiUVController : public Controller
@ -115,6 +136,12 @@ public:
nif->getShort(); // always 0
data.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
};
class NiKeyframeController : public Controller
@ -127,6 +154,12 @@ public:
Controller::read(nif);
data.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
};
class NiAlphaController : public Controller
@ -139,6 +172,12 @@ public:
Controller::read(nif);
data.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
};
class NiGeomMorpherController : public Controller
@ -152,6 +191,12 @@ public:
data.read(nif);
nif->getByte(); // always 0
}
void post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
};
class NiVisController : public Controller
@ -164,6 +209,12 @@ public:
Controller::read(nif);
data.read(nif);
}
void post(NIFFile *nif)
{
Controller::post(nif);
data.post(nif);
}
};
} // Namespace

@ -34,7 +34,6 @@ namespace Nif
class NiSourceTexture : public Named
{
public:
// Is this an external (references a separate texture file) or
// internal (data is inside the nif itself) texture?
bool external;
@ -70,8 +69,8 @@ public:
Named::read(nif);
external = !!nif->getByte();
if(external) filename = nif->getString();
if(external)
filename = nif->getString();
else
{
nif->getByte(); // always 1
@ -84,6 +83,12 @@ public:
nif->getByte(); // always 1
}
void post(NIFFile *nif)
{
Named::post(nif);
data.post(nif);
}
};
// Common ancestor for several data classes
@ -173,9 +178,11 @@ public:
nif->getShort(); // Number of valid entries in the following arrays ?
if(nif->getInt())
{
// Particle sizes
nif->getFloatLen(activeCount);
}
}
};
class NiRotatingParticlesData : public NiAutoNormalParticlesData
@ -186,11 +193,13 @@ public:
NiAutoNormalParticlesData::read(nif);
if(nif->getInt())
{
// Rotation quaternions. I THINK activeCount is correct here,
// but verts (vertex number) might also be correct, if there is
// any case where the two don't match.
nif->getArrayLen<Vector4>(activeCount);
}
}
};
class NiPosData : public Record
@ -228,11 +237,9 @@ public:
// also used in FloatData and KeyframeData. We could probably
// reuse and refactor a lot of this if we actually use it at some
// point.
for(int i=0; i<2; i++)
{
int count = nif->getInt();
if(count)
{
nif->getInt(); // always 2
@ -345,9 +352,6 @@ public:
data.read(nif);
root.read(nif);
bones.read(nif);
if(data.empty() || root.empty())
nif->fail("NiSkinInstance missing root or data");
}
void post(NIFFile *nif);
@ -415,7 +419,6 @@ public:
nif->getInt(); // -1
bones.resize(boneNum);
for(int i=0;i<boneNum;i++)
{
BoneInfo &bi = bones[i];
@ -439,33 +442,25 @@ class NiMorphData : public Record
std::vector<std::vector<Ogre::Vector3> > relevantData;
std::vector<std::vector<Ogre::Vector3> > additionalVertices;
public:
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;
}
float getStartTime() const
{ return startTime; }
float getStopTime() const
{ return stopTime; }
void setStartTime(float time)
{ startTime = time; }
void setStopTime(float time)
{ stopTime = time; }
const std::vector<Ogre::Vector3>& getInitialVertices() const
{ return initialVertices; }
const std::vector<std::vector<Ogre::Vector3> >& getRelevantData() const
{ return relevantData; }
const std::vector<std::vector<float> >& getRelevantTimes() const
{ return relevantTimes; }
const std::vector<std::vector<Ogre::Vector3> >& getAdditionalVertices() const
{ return additionalVertices; }
void read(NIFFile *nif)
{
@ -474,8 +469,9 @@ void read(NIFFile *nif)
nif->getByte();
int magic = nif->getInt();
/*int type =*/ nif->getInt();
for(int i = 0; i < vertCount; i++){
for(int i = 0; i < vertCount; i++)
{
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
@ -488,7 +484,8 @@ void read(NIFFile *nif)
/*type =*/ nif->getInt();
std::vector<Ogre::Vector3> current;
std::vector<float> currentTime;
for(int i = 0; i < magic; i++){
for(int i = 0; i < magic; i++)
{
// Time, data, forward, backward tangents
float time = nif->getFloat();
float x = nif->getFloat();
@ -498,12 +495,16 @@ void read(NIFFile *nif)
currentTime.push_back(time);
//nif->getFloatLen(4*magic);
}
if(magic){
if(magic)
{
relevantData.push_back(current);
relevantTimes.push_back(currentTime);
}
std::vector<Ogre::Vector3> verts;
for(int i = 0; i < vertCount; i++){
for(int i = 0; i < vertCount; i++)
{
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
@ -535,7 +536,6 @@ class NiKeyframeData : public Record
int ttype;
//Scalings
std::vector<float> scalefactor;
std::vector<float> scaletime;
std::vector<float> forwards;
@ -543,10 +543,8 @@ class NiKeyframeData : public Record
std::vector<Ogre::Vector3> tbcscale;
int stype;
public:
void clone(NiKeyframeData c)
void clone(const NiKeyframeData &c)
{
quats = c.getQuat();
tbc = c.getrTbc();
@ -565,22 +563,15 @@ public:
transtime = c.gettTime();
bonename = c.getBonename();
}
void setBonename(std::string bone)
{
bonename = bone;
}
{ bonename = bone; }
void setStartTime(float start)
{
startTime = start;
}
{ startTime = start; }
void setStopTime(float end)
{
stopTime = end;
}
{ stopTime = end; }
void read(NIFFile *nif)
{
// Rotations first
@ -589,7 +580,6 @@ public:
//std::vector<float> rottime(count);
if(count)
{
//TYPE1 LINEAR_KEY
//TYPE2 QUADRATIC_KEY
//TYPE3 TBC_KEY
@ -602,7 +592,8 @@ public:
{
//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++) {
for (int i = 0; i < count; i++)
{
float time = nif->getFloat();
float w = nif->getFloat();
float x = nif->getFloat();
@ -616,8 +607,10 @@ public:
}
}
else if(rtype == 3)
{ //Example - node 116 in base_anim.nif
for (int i = 0; i < count; i++) {
{
//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();
@ -627,6 +620,7 @@ public:
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);
@ -635,8 +629,6 @@ public:
//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)
{
@ -651,28 +643,32 @@ public:
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 sub-rotation type");
}
}
}
else nif->fail("Unknown rotation type in NiKeyframeData");
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++) {
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);
@ -680,8 +676,10 @@ public:
//nif->getFloatLen(count*4); // time + translation
}
else if(ttype == 2)
{ //Example - node 116 in base_anim.nif
for (int i = 0; i < count; i++) {
{
//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();
@ -692,6 +690,7 @@ public:
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);
@ -703,8 +702,10 @@ public:
//nif->getFloatLen(count*10); // trans1 + forward + backward
}
else if(ttype == 3){
for (int i = 0; i < count; i++) {
else if(ttype == 3)
{
for(int i = 0; i < count; i++)
{
float time = nif->getFloat();
float x = nif->getFloat();
float y = nif->getFloat();
@ -729,10 +730,8 @@ public:
{
stype = nif->getInt();
for(int i = 0; i < count; i++){
for(int i = 0; i < count; i++)
{
//int size = 0;
if(stype >= 1 && stype < 4)
{
@ -742,86 +741,70 @@ public:
scalefactor.push_back(scale);
//size = 2; // time+scale
}
else nif->fail("Unknown scaling type");
if(stype == 2){
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){
else if(stype == 3)
{
//size = 5; // 1 + tbc
float tbcx = nif->getFloat();
float tbcy = nif->getFloat();
float tbcz = nif->getFloat();
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
tbcscale.push_back(vec);
//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;
}
int getRtype() const
{ return rtype; }
int getStype() const
{ return stype; }
int getTtype() const
{ return ttype; }
float getStartTime() const
{ return startTime; }
float getStopTime() const
{ return stopTime; }
const std::vector<Ogre::Quaternion>& getQuat() const
{ return quats; }
const std::vector<Ogre::Vector3>& getrTbc() const
{ return tbc; }
const std::vector<float>& getrTime() const
{ return rottime; }
const std::vector<Ogre::Vector3>& getTranslist1() const
{ return translist1; }
const std::vector<Ogre::Vector3>& getTranslist2() const
{ return translist2; }
const std::vector<Ogre::Vector3>& getTranslist3() const
{ return translist3; }
const std::vector<float>& gettTime() const
{ return transtime; }
const std::vector<float>& getScalefactor() const
{ return scalefactor; }
const std::vector<float>& getForwards() const
{ return forwards; }
const std::vector<float>& getBackwards() const
{ return backwards; }
const std::vector<Ogre::Vector3>& getScaleTbc() const
{ return tbcscale; }
const std::vector<float>& getsTime() const
{ return scaletime; }
const std::string& getBonename() const
{ return bonename; }
};
} // Namespace

@ -42,7 +42,6 @@ struct NiLight : Effect
Vector diffuse;
Vector specular;
};
const SLight *light;
void read(NIFFile *nif)
@ -86,6 +85,12 @@ struct NiTextureEffect : Effect
*/
nif->skip(23);
}
void post(NIFFile *nif)
{
Effect::post(nif);
texture.post(nif);
}
};
} // Namespace

@ -41,6 +41,7 @@ public:
ExtraPtr extra;
void read(NIFFile *nif) { extra.read(nif); }
void post(NIFFile *nif) { extra.post(nif); }
};
class NiVertWeightsExtraData : public Extra
@ -67,7 +68,6 @@ public:
float time;
Misc::SString text;
};
std::vector<TextKey> list;
void read(NIFFile *nif)

@ -190,8 +190,15 @@ void NIFFile::parse()
void NiSkinInstance::post(NIFFile *nif)
{
int bnum = bones.length();
if(bnum != static_cast<int> (data->bones.size()))
data.post(nif);
root.post(nif);
bones.post(nif);
if(data.empty() || root.empty())
nif->fail("NiSkinInstance missing root or data");
size_t bnum = bones.length();
if(bnum != data->bones.size())
nif->fail("Mismatch in NiSkinData bone count");
root->makeRootBone(data->trafo);
@ -200,7 +207,6 @@ void NiSkinInstance::post(NIFFile *nif)
{
if(!bones.has(i))
nif->fail("Oops: Missing bone! Don't know how to handle this.");
bones[i].makeBone(i, data->bones[i]);
}
}

@ -43,8 +43,7 @@ namespace Nif
class NIFFile
{
enum NIFVersion
{
enum NIFVersion {
VER_MW = 0x04000002 // Morrowind NIFs
};
@ -95,16 +94,13 @@ class NIFFile
~NIFFile()
{
for(std::size_t i=0; i<records.size(); i++)
{
delete records[i];
}
}
/// Get a given record
Record *getRecord(int index)
Record *getRecord(size_t index)
{
assert(index >= 0 && index < static_cast<int> (records.size()));
Record *res = records[index];
Record *res = records.at(index);
assert(res != NULL);
return res;
}
@ -113,9 +109,7 @@ class NIFFile
int numRecords() { return records.size(); }
/*************************************************
Parser functions
****************************************************/
void skip(size_t size) { inp->getPtr(size); }

@ -26,6 +26,7 @@
#include "controlled.hpp"
#include "data.hpp"
#include "property.hpp"
namespace Nif
{
@ -69,6 +70,12 @@ public:
boneIndex = -1;
}
void post(NIFFile *nif)
{
Named::post(nif);
props.post(nif);
}
// Bone transformation. If set, node is a part of a skeleton.
const NiSkinData::BoneTrafo *boneTrafo;
@ -113,7 +120,6 @@ struct NiNode : Node
NodeList effects;
/* Known NiNode flags:
0x01 hidden
0x02 use mesh for collision
0x04 use bounding box for collision (?)
@ -127,6 +133,13 @@ struct NiNode : Node
children.read(nif);
effects.read(nif);
}
void post(NIFFile *nif)
{
Node::post(nif);
children.post(nif);
effects.post(nif);
}
};
struct NiTriShape : Node
@ -148,7 +161,15 @@ struct NiTriShape : Node
skin.read(nif);
}
NiTriShapeCopy clone(){
void post(NIFFile *nif)
{
Node::post(nif);
data.post(nif);
skin.post(nif);
}
NiTriShapeCopy clone()
{
NiTriShapeCopy copy;
copy.sname = name.toString();
float *ptr = (float*)data->vertices.ptr;
@ -159,13 +180,13 @@ struct NiTriShape : Node
float *current = (float*) (ptr + i * 3);
copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2)));
if(ptrNormals){
if(ptrNormals)
{
float *currentNormals = (float*) (ptrNormals + i * 3);
copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2)));
}
}
return copy;
}
};
@ -183,7 +204,6 @@ struct NiCamera : Node
// Level of detail modifier
float LOD;
};
const Camera *cam;
void read(NIFFile *nif)
@ -207,6 +227,12 @@ struct NiAutoNormalParticles : Node
data.read(nif);
nif->getInt(); // -1
}
void post(NIFFile *nif)
{
Node::post(nif);
data.post(nif);
}
};
struct NiRotatingParticles : Node
@ -219,9 +245,13 @@ struct NiRotatingParticles : Node
data.read(nif);
nif->getInt(); // -1
}
};
void post(NIFFile *nif)
{
Node::post(nif);
data.post(nif);
}
};
} // Namespace
#endif

@ -82,6 +82,11 @@ public:
// short.
nif->skip(6);
}
void post(NIFFile *nif)
{
texture.post(nif);
}
};
/* Apply mode:
@ -130,6 +135,13 @@ public:
}
textures[6].read(nif); // Decal
}
void post(NIFFile *nif)
{
Property::post(nif);
for(int i = 0;i < 7;i++)
textures[i].post(nif);
}
};
// These contain no other data than the 'flags' field in Property
@ -140,15 +152,15 @@ typedef Property NiSpecularProperty;
typedef Property NiWireframeProperty;
// The rest are all struct-based
template <typename Struct>
template <typename T>
struct StructPropT : Property
{
const Struct* data;
const T* data;
void read(NIFFile *nif)
{
Property::read(nif);
data = nif->getPtr<Struct>();
data = nif->getPtr<T>();
}
};

@ -104,7 +104,6 @@ struct Record
/*
Use these later if you want custom allocation of all NIF objects
static void* operator new(size_t size);
static void operator delete(void *p);
*/

@ -37,61 +37,51 @@ namespace Nif
template <class X>
class RecordPtrT
{
int index;
union {
intptr_t index;
X* ptr;
NIFFile *nif;
};
public:
RecordPtrT() : index(-2), ptr(NULL) {}
RecordPtrT() : index(-2) {}
/// Read the index from the nif
void read(NIFFile *_nif)
void read(NIFFile *nif)
{
// Can only read the index once
assert(index == -2);
// Store the NIFFile pointer for later
nif = _nif;
// And the index, of course
// Store the index for later
index = nif->getInt();
}
/** Set the pointer explicitly. May be used when you are pointing to
records in another file, eg. when you have a .nif / .kf pair.
*/
void set(X *p)
{
ptr = p;
index = -1;
}
/// Look up the actual object from the index
X* getPtr()
/// Resolve index to pointer
void post(NIFFile *nif)
{
// Have we found the pointer already?
if(ptr == NULL)
if(index < 0)
ptr = NULL;
else
{
// Get the record
assert(index >= 0);
Record *r = nif->getRecord(index);
// And cast it
ptr = dynamic_cast<X*>(r);
assert(ptr != NULL);
}
}
/// Look up the actual object from the index
X* getPtr()
{
assert(ptr != NULL);
return ptr;
}
X& get() { return *getPtr(); }
/// Syntactic sugar
X* operator->() { return getPtr(); }
X& get() { return *getPtr(); }
/// Pointers are allowed to be empty
bool empty() { return index == -1 && ptr == NULL; }
int getIndex() { return index; }
bool empty() { return ptr == NULL; }
};
/** A list of references to other records. These are read as a list,
@ -105,36 +95,34 @@ class RecordListT
std::vector<Ptr> list;
public:
void read(NIFFile *nif)
{
int len = nif->getInt();
list.resize(len);
assert(len >= 0 && len < 1000);
for(int i=0;i<len;i++)
for(size_t i=0;i < list.size();i++)
list[i].read(nif);
}
X& operator[](int index)
void post(NIFFile *nif)
{
assert(index >= 0 && index < static_cast<int> (list.size()));
return list[index].get();
for(size_t i=0;i < list.size();i++)
list[i].post(nif);
}
bool has(int index)
X& operator[](size_t index)
{
assert(index >= 0 && index < static_cast<int> (list.size()));
return !list[index].empty();
return list.at(index).get();
}
int getIndex(int index)
bool has(size_t index)
{
if(has(index)) return list[index].getIndex();
else return -1;
assert(index >= 0 && index < static_cast<int> (list.size()));
return !list.at(index).empty();
}
int length() { return list.size(); }
int length()
{ return list.size(); }
};

Loading…
Cancel
Save