forked from mirror/openmw-tes3mp
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.
This commit is contained in:
parent
efb95e2f83
commit
046e9686f9
11 changed files with 1364 additions and 1283 deletions
|
@ -25,6 +25,7 @@
|
|||
#define _NIF_CONTROLLED_H_
|
||||
|
||||
#include "extra.hpp"
|
||||
#include "controller.hpp"
|
||||
|
||||
namespace Nif
|
||||
{
|
||||
|
@ -33,92 +34,104 @@ namespace Nif
|
|||
class Controlled : public Extra
|
||||
{
|
||||
public:
|
||||
ControllerPtr controller;
|
||||
ControllerPtr controller;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
controller.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
controller.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Extra::post(nif);
|
||||
controller.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
/// Has name, extra-data and controller
|
||||
class Named : public Controlled
|
||||
{
|
||||
public:
|
||||
Misc::SString name;
|
||||
Misc::SString name;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
name = nif->getString();
|
||||
Controlled::read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
name = nif->getString();
|
||||
Controlled::read(nif);
|
||||
}
|
||||
};
|
||||
typedef Named NiSequenceStreamHelper;
|
||||
|
||||
class NiParticleGrowFade : public Controlled
|
||||
{
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
|
||||
// Two floats.
|
||||
nif->skip(8);
|
||||
}
|
||||
// Two floats.
|
||||
nif->skip(8);
|
||||
}
|
||||
};
|
||||
|
||||
class NiParticleColorModifier : public Controlled
|
||||
{
|
||||
public:
|
||||
NiColorDataPtr data;
|
||||
NiColorDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controlled::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiGravity : public Controlled
|
||||
{
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
|
||||
// two floats, one int, six floats
|
||||
nif->skip(9*4);
|
||||
}
|
||||
// two floats, one int, six floats
|
||||
nif->skip(9*4);
|
||||
}
|
||||
};
|
||||
|
||||
// NiPinaColada
|
||||
class NiPlanarCollider : public Controlled
|
||||
{
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
|
||||
// (I think) 4 floats + 4 vectors
|
||||
nif->skip(4*16);
|
||||
}
|
||||
// (I think) 4 floats + 4 vectors
|
||||
nif->skip(4*16);
|
||||
}
|
||||
};
|
||||
|
||||
class NiParticleRotation : public Controlled
|
||||
{
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controlled::read(nif);
|
||||
|
||||
/*
|
||||
byte (0 or 1)
|
||||
float (1)
|
||||
float*3
|
||||
*/
|
||||
nif->skip(17);
|
||||
}
|
||||
/*
|
||||
byte (0 or 1)
|
||||
float (1)
|
||||
float*3
|
||||
*/
|
||||
nif->skip(17);
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
|
|
|
@ -34,136 +34,187 @@ namespace Nif
|
|||
class Controller : public Record
|
||||
{
|
||||
public:
|
||||
ControllerPtr next;
|
||||
int flags;
|
||||
float frequency, phase;
|
||||
float timeStart, timeStop;
|
||||
ControlledPtr target;
|
||||
ControllerPtr next;
|
||||
int flags;
|
||||
float frequency, phase;
|
||||
float timeStart, timeStop;
|
||||
ControlledPtr target;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
next.read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
next.read(nif);
|
||||
|
||||
flags = nif->getShort();
|
||||
flags = nif->getShort();
|
||||
|
||||
frequency = nif->getFloat();
|
||||
phase = nif->getFloat();
|
||||
timeStart = nif->getFloat();
|
||||
timeStop = nif->getFloat();
|
||||
frequency = nif->getFloat();
|
||||
phase = nif->getFloat();
|
||||
timeStart = nif->getFloat();
|
||||
timeStop = nif->getFloat();
|
||||
|
||||
target.read(nif);
|
||||
}
|
||||
target.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Record::post(nif);
|
||||
next.post(nif);
|
||||
target.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiBSPArrayController : public Controller
|
||||
{
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
|
||||
// At the moment, just skip it all
|
||||
nif->skip(111);
|
||||
int s = nif->getShort();
|
||||
nif->skip(15 + s*40);
|
||||
}
|
||||
// At the moment, just skip it all
|
||||
nif->skip(111);
|
||||
int s = nif->getShort();
|
||||
nif->skip(15 + s*40);
|
||||
}
|
||||
};
|
||||
typedef NiBSPArrayController NiParticleSystemController;
|
||||
|
||||
class NiMaterialColorController : public Controller
|
||||
{
|
||||
public:
|
||||
NiPosDataPtr data;
|
||||
NiPosDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiPathController : public Controller
|
||||
{
|
||||
public:
|
||||
NiPosDataPtr posData;
|
||||
NiFloatDataPtr floatData;
|
||||
NiPosDataPtr posData;
|
||||
NiFloatDataPtr floatData;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
|
||||
/*
|
||||
int = 1
|
||||
2xfloat
|
||||
short = 0 or 1
|
||||
*/
|
||||
nif->skip(14);
|
||||
posData.read(nif);
|
||||
floatData.read(nif);
|
||||
}
|
||||
/*
|
||||
int = 1
|
||||
2xfloat
|
||||
short = 0 or 1
|
||||
*/
|
||||
nif->skip(14);
|
||||
posData.read(nif);
|
||||
floatData.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
|
||||
posData.post(nif);
|
||||
floatData.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiUVController : public Controller
|
||||
{
|
||||
public:
|
||||
NiUVDataPtr data;
|
||||
NiUVDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
|
||||
nif->getShort(); // always 0
|
||||
data.read(nif);
|
||||
}
|
||||
nif->getShort(); // always 0
|
||||
data.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiKeyframeController : public Controller
|
||||
{
|
||||
public:
|
||||
NiKeyframeDataPtr data;
|
||||
NiKeyframeDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiAlphaController : public Controller
|
||||
{
|
||||
public:
|
||||
NiFloatDataPtr data;
|
||||
NiFloatDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiGeomMorpherController : public Controller
|
||||
{
|
||||
public:
|
||||
NiMorphDataPtr data;
|
||||
NiMorphDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
nif->getByte(); // always 0
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
nif->getByte(); // always 0
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
class NiVisController : public Controller
|
||||
{
|
||||
public:
|
||||
NiVisDataPtr data;
|
||||
NiVisDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Controller::read(nif);
|
||||
data.read(nif);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Controller::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,57 +35,62 @@ typedef Node Effect;
|
|||
// NiPointLight and NiSpotLight?
|
||||
struct NiLight : Effect
|
||||
{
|
||||
struct SLight
|
||||
{
|
||||
float dimmer;
|
||||
Vector ambient;
|
||||
Vector diffuse;
|
||||
Vector specular;
|
||||
};
|
||||
struct SLight
|
||||
{
|
||||
float dimmer;
|
||||
Vector ambient;
|
||||
Vector diffuse;
|
||||
Vector specular;
|
||||
};
|
||||
const SLight *light;
|
||||
|
||||
const SLight *light;
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Effect::read(nif);
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Effect::read(nif);
|
||||
|
||||
nif->getInt(); // 1
|
||||
nif->getInt(); // 1?
|
||||
light = nif->getPtr<SLight>();
|
||||
}
|
||||
nif->getInt(); // 1
|
||||
nif->getInt(); // 1?
|
||||
light = nif->getPtr<SLight>();
|
||||
}
|
||||
};
|
||||
|
||||
struct NiTextureEffect : Effect
|
||||
{
|
||||
NiSourceTexturePtr texture;
|
||||
NiSourceTexturePtr texture;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Effect::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Effect::read(nif);
|
||||
|
||||
int tmp = nif->getInt();
|
||||
if(tmp) nif->getInt(); // always 1?
|
||||
int tmp = nif->getInt();
|
||||
if(tmp) nif->getInt(); // always 1?
|
||||
|
||||
/*
|
||||
3 x Vector4 = [1,0,0,0]
|
||||
int = 2
|
||||
int = 0 or 3
|
||||
int = 2
|
||||
int = 2
|
||||
*/
|
||||
nif->skip(16*4);
|
||||
/*
|
||||
3 x Vector4 = [1,0,0,0]
|
||||
int = 2
|
||||
int = 0 or 3
|
||||
int = 2
|
||||
int = 2
|
||||
*/
|
||||
nif->skip(16*4);
|
||||
|
||||
texture.read(nif);
|
||||
texture.read(nif);
|
||||
|
||||
/*
|
||||
byte = 0
|
||||
vector4 = [1,0,0,0]
|
||||
short = 0
|
||||
short = -75
|
||||
short = 0
|
||||
*/
|
||||
nif->skip(23);
|
||||
}
|
||||
/*
|
||||
byte = 0
|
||||
vector4 = [1,0,0,0]
|
||||
short = 0
|
||||
short = -75
|
||||
short = 0
|
||||
*/
|
||||
nif->skip(23);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Effect::post(nif);
|
||||
texture.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
|
|
|
@ -38,70 +38,70 @@ namespace Nif
|
|||
class Extra : public Record
|
||||
{
|
||||
public:
|
||||
ExtraPtr extra;
|
||||
ExtraPtr extra;
|
||||
|
||||
void read(NIFFile *nif) { extra.read(nif); }
|
||||
void read(NIFFile *nif) { extra.read(nif); }
|
||||
void post(NIFFile *nif) { extra.post(nif); }
|
||||
};
|
||||
|
||||
class NiVertWeightsExtraData : public Extra
|
||||
{
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
|
||||
// We should have s*4+2 == i, for some reason. Might simply be the
|
||||
// size of the rest of the record, unhelpful as that may be.
|
||||
/*int i =*/ nif->getInt();
|
||||
int s = nif->getShort(); // number of vertices
|
||||
// We should have s*4+2 == i, for some reason. Might simply be the
|
||||
// size of the rest of the record, unhelpful as that may be.
|
||||
/*int i =*/ nif->getInt();
|
||||
int s = nif->getShort(); // number of vertices
|
||||
|
||||
nif->getFloatLen(s); // vertex weights I guess
|
||||
}
|
||||
nif->getFloatLen(s); // vertex weights I guess
|
||||
}
|
||||
};
|
||||
|
||||
class NiTextKeyExtraData : public Extra
|
||||
{
|
||||
public:
|
||||
struct TextKey
|
||||
{
|
||||
float time;
|
||||
Misc::SString text;
|
||||
};
|
||||
struct TextKey
|
||||
{
|
||||
float time;
|
||||
Misc::SString text;
|
||||
};
|
||||
std::vector<TextKey> list;
|
||||
|
||||
std::vector<TextKey> list;
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
nif->getInt(); // 0
|
||||
|
||||
nif->getInt(); // 0
|
||||
|
||||
int keynum = nif->getInt();
|
||||
list.resize(keynum);
|
||||
for(int i=0; i<keynum; i++)
|
||||
{
|
||||
list[i].time = nif->getFloat();
|
||||
list[i].text = nif->getString();
|
||||
}
|
||||
}
|
||||
int keynum = nif->getInt();
|
||||
list.resize(keynum);
|
||||
for(int i=0; i<keynum; i++)
|
||||
{
|
||||
list[i].time = nif->getFloat();
|
||||
list[i].text = nif->getString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class NiStringExtraData : public Extra
|
||||
{
|
||||
public:
|
||||
/* Two known meanings:
|
||||
"MRK" - marker, only visible in the editor, not rendered in-game
|
||||
"NCO" - no collision
|
||||
*/
|
||||
Misc::SString string;
|
||||
/* Two known meanings:
|
||||
"MRK" - marker, only visible in the editor, not rendered in-game
|
||||
"NCO" - no collision
|
||||
*/
|
||||
Misc::SString string;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Extra::read(nif);
|
||||
|
||||
nif->getInt(); // size of string + 4. Really useful...
|
||||
string = nif->getString();
|
||||
}
|
||||
nif->getInt(); // size of string + 4. Really useful...
|
||||
string = nif->getString();
|
||||
}
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
|
|
|
@ -190,17 +190,23 @@ void NIFFile::parse()
|
|||
|
||||
void NiSkinInstance::post(NIFFile *nif)
|
||||
{
|
||||
int bnum = bones.length();
|
||||
if(bnum != static_cast<int> (data->bones.size()))
|
||||
nif->fail("Mismatch in NiSkinData bone count");
|
||||
data.post(nif);
|
||||
root.post(nif);
|
||||
bones.post(nif);
|
||||
|
||||
root->makeRootBone(data->trafo);
|
||||
if(data.empty() || root.empty())
|
||||
nif->fail("NiSkinInstance missing root or data");
|
||||
|
||||
for(int i=0; i<bnum; i++)
|
||||
size_t bnum = bones.length();
|
||||
if(bnum != data->bones.size())
|
||||
nif->fail("Mismatch in NiSkinData bone count");
|
||||
|
||||
root->makeRootBone(data->trafo);
|
||||
|
||||
for(int i=0; i<bnum; i++)
|
||||
{
|
||||
if(!bones.has(i))
|
||||
nif->fail("Oops: Missing bone! Don't know how to handle this.");
|
||||
|
||||
bones[i].makeBone(i, data->bones[i]);
|
||||
if(!bones.has(i))
|
||||
nif->fail("Oops: Missing bone! Don't know how to handle this.");
|
||||
bones[i].makeBone(i, data->bones[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,113 +43,107 @@ namespace Nif
|
|||
|
||||
class NIFFile
|
||||
{
|
||||
enum NIFVersion
|
||||
{
|
||||
VER_MW = 0x04000002 // Morrowind NIFs
|
||||
enum NIFVersion {
|
||||
VER_MW = 0x04000002 // Morrowind NIFs
|
||||
};
|
||||
|
||||
/// Nif file version
|
||||
int ver;
|
||||
/// Nif file version
|
||||
int ver;
|
||||
|
||||
/// Input stream
|
||||
StreamPtr inp;
|
||||
/// Input stream
|
||||
StreamPtr inp;
|
||||
|
||||
/// File name, used for error messages
|
||||
std::string filename;
|
||||
/// File name, used for error messages
|
||||
std::string filename;
|
||||
|
||||
/// Record list
|
||||
std::vector<Record*> records;
|
||||
/// Record list
|
||||
std::vector<Record*> records;
|
||||
|
||||
/// Parse the file
|
||||
void parse();
|
||||
/// Parse the file
|
||||
void parse();
|
||||
|
||||
public:
|
||||
/// Used for error handling
|
||||
void fail(const std::string &msg)
|
||||
public:
|
||||
/// Used for error handling
|
||||
void fail(const std::string &msg)
|
||||
{
|
||||
std::string err = "NIFFile Error: " + msg;
|
||||
err += "\nFile: " + filename;
|
||||
throw std::runtime_error(err);
|
||||
std::string err = "NIFFile Error: " + msg;
|
||||
err += "\nFile: " + filename;
|
||||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
/// Open a NIF stream. The name is used for error messages.
|
||||
NIFFile(StreamPtr nif, const std::string &name)
|
||||
: filename(name)
|
||||
/// Open a NIF stream. The name is used for error messages.
|
||||
NIFFile(StreamPtr nif, const std::string &name)
|
||||
: filename(name)
|
||||
{
|
||||
/* Load the entire file into memory. This allows us to use
|
||||
direct pointers to the data arrays in the NIF, instead of
|
||||
individually allocating and copying each one.
|
||||
/* Load the entire file into memory. This allows us to use
|
||||
direct pointers to the data arrays in the NIF, instead of
|
||||
individually allocating and copying each one.
|
||||
|
||||
The NIF data is only stored temporarily in memory, since once
|
||||
the mesh data is loaded it is siphoned into OGRE and
|
||||
deleted. For that reason, we might improve this further and
|
||||
use a shared region/pool based allocation scheme in the
|
||||
future, especially since only one NIFFile will ever be loaded
|
||||
at any given time.
|
||||
*/
|
||||
inp = StreamPtr(new BufferStream(nif));
|
||||
The NIF data is only stored temporarily in memory, since once
|
||||
the mesh data is loaded it is siphoned into OGRE and
|
||||
deleted. For that reason, we might improve this further and
|
||||
use a shared region/pool based allocation scheme in the
|
||||
future, especially since only one NIFFile will ever be loaded
|
||||
at any given time.
|
||||
*/
|
||||
inp = StreamPtr(new BufferStream(nif));
|
||||
|
||||
parse();
|
||||
parse();
|
||||
}
|
||||
|
||||
~NIFFile()
|
||||
~NIFFile()
|
||||
{
|
||||
for(std::size_t i=0; i<records.size(); i++)
|
||||
{
|
||||
delete records[i];
|
||||
}
|
||||
for(std::size_t i=0; i<records.size(); i++)
|
||||
delete records[i];
|
||||
}
|
||||
|
||||
/// Get a given record
|
||||
Record *getRecord(int index)
|
||||
{
|
||||
assert(index >= 0 && index < static_cast<int> (records.size()));
|
||||
Record *res = records[index];
|
||||
assert(res != NULL);
|
||||
return res;
|
||||
}
|
||||
/// Get a given record
|
||||
Record *getRecord(size_t index)
|
||||
{
|
||||
Record *res = records.at(index);
|
||||
assert(res != NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Number of records
|
||||
int numRecords() { return records.size(); }
|
||||
|
||||
/* ************************************************
|
||||
/// Number of records
|
||||
int numRecords() { return records.size(); }
|
||||
|
||||
/*************************************************
|
||||
Parser functions
|
||||
****************************************************/
|
||||
|
||||
****************************************************/
|
||||
void skip(size_t size) { inp->getPtr(size); }
|
||||
|
||||
void skip(size_t size) { inp->getPtr(size); }
|
||||
template<class X> const X* getPtr() { return (const X*)inp->getPtr(sizeof(X)); }
|
||||
template<class X> X getType() { return *getPtr<X>(); }
|
||||
unsigned short getShort() { return getType<unsigned short>(); }
|
||||
int getInt() { return getType<int>(); }
|
||||
float getFloat() { return getType<float>(); }
|
||||
char getByte() { return getType<char>(); }
|
||||
|
||||
template<class X> const X* getPtr() { return (const X*)inp->getPtr(sizeof(X)); }
|
||||
template<class X> X getType() { return *getPtr<X>(); }
|
||||
unsigned short getShort() { return getType<unsigned short>(); }
|
||||
int getInt() { return getType<int>(); }
|
||||
float getFloat() { return getType<float>(); }
|
||||
char getByte() { return getType<char>(); }
|
||||
|
||||
template<class X>
|
||||
Misc::SliceArray<X> getArrayLen(int num)
|
||||
template<class X>
|
||||
Misc::SliceArray<X> getArrayLen(int num)
|
||||
{ return Misc::SliceArray<X>((const X*)inp->getPtr(num*sizeof(X)),num); }
|
||||
|
||||
template<class X>
|
||||
Misc::SliceArray<X> getArray()
|
||||
template<class X>
|
||||
Misc::SliceArray<X> getArray()
|
||||
{
|
||||
int len = getInt();
|
||||
return getArrayLen<X>(len);
|
||||
int len = getInt();
|
||||
return getArrayLen<X>(len);
|
||||
}
|
||||
|
||||
Misc::SString getString() { return getArray<char>(); }
|
||||
Misc::SString getString() { return getArray<char>(); }
|
||||
|
||||
const Vector *getVector() { return getPtr<Vector>(); }
|
||||
const Matrix *getMatrix() { return getPtr<Matrix>(); }
|
||||
const Transformation *getTrafo() { return getPtr<Transformation>(); }
|
||||
const Vector4 *getVector4() { return getPtr<Vector4>(); }
|
||||
const Vector *getVector() { return getPtr<Vector>(); }
|
||||
const Matrix *getMatrix() { return getPtr<Matrix>(); }
|
||||
const Transformation *getTrafo() { return getPtr<Transformation>(); }
|
||||
const Vector4 *getVector4() { return getPtr<Vector4>(); }
|
||||
|
||||
Misc::FloatArray getFloatLen(int num)
|
||||
Misc::FloatArray getFloatLen(int num)
|
||||
{ return getArrayLen<float>(num); }
|
||||
|
||||
// For fixed-size strings where you already know the size
|
||||
const char *getString(int size)
|
||||
// For fixed-size strings where you already know the size
|
||||
const char *getString(int size)
|
||||
{ return (const char*)inp->getPtr(size); }
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "controlled.hpp"
|
||||
#include "data.hpp"
|
||||
#include "property.hpp"
|
||||
|
||||
namespace Nif
|
||||
{
|
||||
|
@ -37,191 +38,220 @@ namespace Nif
|
|||
class Node : public Named
|
||||
{
|
||||
public:
|
||||
// Node flags. Interpretation depends somewhat on the type of node.
|
||||
int flags;
|
||||
const Transformation *trafo;
|
||||
PropertyList props;
|
||||
// Node flags. Interpretation depends somewhat on the type of node.
|
||||
int flags;
|
||||
const Transformation *trafo;
|
||||
PropertyList props;
|
||||
|
||||
// Bounding box info
|
||||
bool hasBounds;
|
||||
const Vector *boundPos;
|
||||
const Matrix *boundRot;
|
||||
const Vector *boundXYZ; // Box size
|
||||
// Bounding box info
|
||||
bool hasBounds;
|
||||
const Vector *boundPos;
|
||||
const Matrix *boundRot;
|
||||
const Vector *boundXYZ; // Box size
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Named::read(nif);
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Named::read(nif);
|
||||
|
||||
flags = nif->getShort();
|
||||
trafo = nif->getTrafo();
|
||||
props.read(nif);
|
||||
flags = nif->getShort();
|
||||
trafo = nif->getTrafo();
|
||||
props.read(nif);
|
||||
|
||||
hasBounds = !!nif->getInt();
|
||||
if(hasBounds)
|
||||
{
|
||||
nif->getInt(); // always 1
|
||||
boundPos = nif->getVector();
|
||||
boundRot = nif->getMatrix();
|
||||
boundXYZ = nif->getVector();
|
||||
}
|
||||
hasBounds = !!nif->getInt();
|
||||
if(hasBounds)
|
||||
{
|
||||
nif->getInt(); // always 1
|
||||
boundPos = nif->getVector();
|
||||
boundRot = nif->getMatrix();
|
||||
boundXYZ = nif->getVector();
|
||||
}
|
||||
|
||||
boneTrafo = NULL;
|
||||
boneIndex = -1;
|
||||
}
|
||||
boneTrafo = NULL;
|
||||
boneIndex = -1;
|
||||
}
|
||||
|
||||
// Bone transformation. If set, node is a part of a skeleton.
|
||||
const NiSkinData::BoneTrafo *boneTrafo;
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Named::post(nif);
|
||||
props.post(nif);
|
||||
}
|
||||
|
||||
// Bone weight info, from NiSkinData
|
||||
const NiSkinData::BoneInfo *boneInfo;
|
||||
// Bone transformation. If set, node is a part of a skeleton.
|
||||
const NiSkinData::BoneTrafo *boneTrafo;
|
||||
|
||||
// Bone index. If -1, this node is either not a bone, or if
|
||||
// boneTrafo is set it is the root bone in the skeleton.
|
||||
short boneIndex;
|
||||
// Bone weight info, from NiSkinData
|
||||
const NiSkinData::BoneInfo *boneInfo;
|
||||
|
||||
void makeRootBone(const NiSkinData::BoneTrafo *tr)
|
||||
{
|
||||
boneTrafo = tr;
|
||||
boneIndex = -1;
|
||||
}
|
||||
// Bone index. If -1, this node is either not a bone, or if
|
||||
// boneTrafo is set it is the root bone in the skeleton.
|
||||
short boneIndex;
|
||||
|
||||
void makeBone(short ind, const NiSkinData::BoneInfo &bi)
|
||||
{
|
||||
boneInfo = &bi;
|
||||
boneTrafo = bi.trafo;
|
||||
boneIndex = ind;
|
||||
}
|
||||
void makeRootBone(const NiSkinData::BoneTrafo *tr)
|
||||
{
|
||||
boneTrafo = tr;
|
||||
boneIndex = -1;
|
||||
}
|
||||
|
||||
void makeBone(short ind, const NiSkinData::BoneInfo &bi)
|
||||
{
|
||||
boneInfo = &bi;
|
||||
boneTrafo = bi.trafo;
|
||||
boneIndex = ind;
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> > vertsToWeights;
|
||||
Nif::NiMorphData morph;
|
||||
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;
|
||||
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> > vertsToWeights;
|
||||
Nif::NiMorphData morph;
|
||||
};
|
||||
|
||||
struct NiNode : Node
|
||||
{
|
||||
NodeList children;
|
||||
NodeList effects;
|
||||
NodeList children;
|
||||
NodeList effects;
|
||||
|
||||
/* Known NiNode flags:
|
||||
/* Known NiNode flags:
|
||||
0x01 hidden
|
||||
0x02 use mesh for collision
|
||||
0x04 use bounding box for collision (?)
|
||||
0x08 unknown, but common
|
||||
0x20, 0x40, 0x80 unknown
|
||||
*/
|
||||
|
||||
0x01 hidden
|
||||
0x02 use mesh for collision
|
||||
0x04 use bounding box for collision (?)
|
||||
0x08 unknown, but common
|
||||
0x20, 0x40, 0x80 unknown
|
||||
*/
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
children.read(nif);
|
||||
effects.read(nif);
|
||||
}
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
children.read(nif);
|
||||
effects.read(nif);
|
||||
}
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Node::post(nif);
|
||||
children.post(nif);
|
||||
effects.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
struct NiTriShape : Node
|
||||
{
|
||||
/* Possible flags:
|
||||
0x40 - mesh has no vertex normals ?
|
||||
/* Possible flags:
|
||||
0x40 - mesh has no vertex normals ?
|
||||
|
||||
Only flags included in 0x47 (ie. 0x01, 0x02, 0x04 and 0x40) have
|
||||
been observed so far.
|
||||
*/
|
||||
Only flags included in 0x47 (ie. 0x01, 0x02, 0x04 and 0x40) have
|
||||
been observed so far.
|
||||
*/
|
||||
|
||||
NiTriShapeDataPtr data;
|
||||
NiSkinInstancePtr skin;
|
||||
NiTriShapeDataPtr data;
|
||||
NiSkinInstancePtr skin;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
data.read(nif);
|
||||
skin.read(nif);
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
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)));
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Node::post(nif);
|
||||
data.post(nif);
|
||||
skin.post(nif);
|
||||
}
|
||||
|
||||
if(ptrNormals){
|
||||
float *currentNormals = (float*) (ptrNormals + i * 3);
|
||||
copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2)));
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
};
|
||||
|
||||
struct NiCamera : Node
|
||||
{
|
||||
struct Camera
|
||||
{
|
||||
// Camera frustrum
|
||||
float left, right, top, bottom, nearDist, farDist;
|
||||
struct Camera
|
||||
{
|
||||
// Camera frustrum
|
||||
float left, right, top, bottom, nearDist, farDist;
|
||||
|
||||
// Viewport
|
||||
float vleft, vright, vtop, vbottom;
|
||||
// Viewport
|
||||
float vleft, vright, vtop, vbottom;
|
||||
|
||||
// Level of detail modifier
|
||||
float LOD;
|
||||
};
|
||||
// Level of detail modifier
|
||||
float LOD;
|
||||
};
|
||||
const Camera *cam;
|
||||
|
||||
const Camera *cam;
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
nif->getPtr<Camera>();
|
||||
|
||||
nif->getPtr<Camera>();
|
||||
|
||||
nif->getInt(); // -1
|
||||
nif->getInt(); // 0
|
||||
}
|
||||
nif->getInt(); // -1
|
||||
nif->getInt(); // 0
|
||||
}
|
||||
};
|
||||
|
||||
struct NiAutoNormalParticles : Node
|
||||
{
|
||||
NiAutoNormalParticlesDataPtr data;
|
||||
NiAutoNormalParticlesDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
data.read(nif);
|
||||
nif->getInt(); // -1
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
data.read(nif);
|
||||
nif->getInt(); // -1
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Node::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
struct NiRotatingParticles : Node
|
||||
{
|
||||
NiRotatingParticlesDataPtr data;
|
||||
NiRotatingParticlesDataPtr data;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
data.read(nif);
|
||||
nif->getInt(); // -1
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Node::read(nif);
|
||||
data.read(nif);
|
||||
nif->getInt(); // -1
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
Node::post(nif);
|
||||
data.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // Namespace
|
||||
#endif
|
||||
|
|
|
@ -32,104 +32,116 @@ namespace Nif
|
|||
class Property : public Named
|
||||
{
|
||||
public:
|
||||
// The meaning of these depends on the actual property type.
|
||||
int flags;
|
||||
// The meaning of these depends on the actual property type.
|
||||
int flags;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Named::read(nif);
|
||||
flags = nif->getShort();
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Named::read(nif);
|
||||
flags = nif->getShort();
|
||||
}
|
||||
};
|
||||
|
||||
class NiTexturingProperty : public Property
|
||||
{
|
||||
public:
|
||||
// A sub-texture
|
||||
struct Texture
|
||||
{
|
||||
/* Clamp mode
|
||||
0 - clampS clampT
|
||||
1 - clampS wrapT
|
||||
2 - wrapS clampT
|
||||
3 - wrapS wrapT
|
||||
*/
|
||||
// A sub-texture
|
||||
struct Texture
|
||||
{
|
||||
/* Clamp mode
|
||||
0 - clampS clampT
|
||||
1 - clampS wrapT
|
||||
2 - wrapS clampT
|
||||
3 - wrapS wrapT
|
||||
*/
|
||||
|
||||
/* Filter:
|
||||
0 - nearest
|
||||
1 - bilinear
|
||||
2 - trilinear
|
||||
3, 4, 5 - who knows
|
||||
*/
|
||||
bool inUse;
|
||||
NiSourceTexturePtr texture;
|
||||
/* Filter:
|
||||
0 - nearest
|
||||
1 - bilinear
|
||||
2 - trilinear
|
||||
3, 4, 5 - who knows
|
||||
*/
|
||||
bool inUse;
|
||||
NiSourceTexturePtr texture;
|
||||
|
||||
int clamp, set, filter;
|
||||
short unknown2;
|
||||
int clamp, set, filter;
|
||||
short unknown2;
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
inUse = !!nif->getInt();
|
||||
if(!inUse) return;
|
||||
|
||||
texture.read(nif);
|
||||
clamp = nif->getInt();
|
||||
filter = nif->getInt();
|
||||
set = nif->getInt();
|
||||
|
||||
// I have no idea, but I think these are actually two
|
||||
// PS2-specific shorts (ps2L and ps2K), followed by an unknown
|
||||
// short.
|
||||
nif->skip(6);
|
||||
}
|
||||
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
texture.post(nif);
|
||||
}
|
||||
};
|
||||
|
||||
/* Apply mode:
|
||||
0 - replace
|
||||
1 - decal
|
||||
2 - modulate
|
||||
3 - hilight // These two are for PS2 only?
|
||||
4 - hilight2
|
||||
*/
|
||||
int apply;
|
||||
|
||||
/*
|
||||
* The textures in this list are as follows:
|
||||
*
|
||||
* 0 - Base texture
|
||||
* 1 - Dark texture
|
||||
* 2 - Detail texture
|
||||
* 3 - Gloss texture (never used?)
|
||||
* 4 - Glow texture
|
||||
* 5 - Bump map texture
|
||||
* 6 - Decal texture
|
||||
*/
|
||||
Texture textures[7];
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
inUse = !!nif->getInt();
|
||||
if(!inUse) return;
|
||||
Property::read(nif);
|
||||
apply = nif->getInt();
|
||||
|
||||
texture.read(nif);
|
||||
clamp = nif->getInt();
|
||||
filter = nif->getInt();
|
||||
set = nif->getInt();
|
||||
// Unknown, always 7. Probably the number of textures to read
|
||||
// below
|
||||
nif->getInt();
|
||||
|
||||
// I have no idea, but I think these are actually two
|
||||
// PS2-specific shorts (ps2L and ps2K), followed by an unknown
|
||||
// short.
|
||||
nif->skip(6);
|
||||
textures[0].read(nif); // Base
|
||||
textures[1].read(nif); // Dark
|
||||
textures[2].read(nif); // Detail
|
||||
textures[3].read(nif); // Gloss (never present)
|
||||
textures[4].read(nif); // Glow
|
||||
textures[5].read(nif); // Bump map
|
||||
if(textures[5].inUse)
|
||||
{
|
||||
// Ignore these at the moment
|
||||
/*float lumaScale =*/ nif->getFloat();
|
||||
/*float lumaOffset =*/ nif->getFloat();
|
||||
/*const Vector4 *lumaMatrix =*/ nif->getVector4();
|
||||
}
|
||||
textures[6].read(nif); // Decal
|
||||
}
|
||||
};
|
||||
|
||||
/* Apply mode:
|
||||
0 - replace
|
||||
1 - decal
|
||||
2 - modulate
|
||||
3 - hilight // These two are for PS2 only?
|
||||
4 - hilight2
|
||||
*/
|
||||
int apply;
|
||||
|
||||
/*
|
||||
* The textures in this list are as follows:
|
||||
*
|
||||
* 0 - Base texture
|
||||
* 1 - Dark texture
|
||||
* 2 - Detail texture
|
||||
* 3 - Gloss texture (never used?)
|
||||
* 4 - Glow texture
|
||||
* 5 - Bump map texture
|
||||
* 6 - Decal texture
|
||||
*/
|
||||
Texture textures[7];
|
||||
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Property::read(nif);
|
||||
apply = nif->getInt();
|
||||
|
||||
// Unknown, always 7. Probably the number of textures to read
|
||||
// below
|
||||
nif->getInt();
|
||||
|
||||
textures[0].read(nif); // Base
|
||||
textures[1].read(nif); // Dark
|
||||
textures[2].read(nif); // Detail
|
||||
textures[3].read(nif); // Gloss (never present)
|
||||
textures[4].read(nif); // Glow
|
||||
textures[5].read(nif); // Bump map
|
||||
if(textures[5].inUse)
|
||||
{
|
||||
// Ignore these at the moment
|
||||
/*float lumaScale =*/ nif->getFloat();
|
||||
/*float lumaOffset =*/ nif->getFloat();
|
||||
/*const Vector4 *lumaMatrix =*/ nif->getVector4();
|
||||
}
|
||||
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,88 +152,88 @@ 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>();
|
||||
}
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
Property::read(nif);
|
||||
data = nif->getPtr<T>();
|
||||
}
|
||||
};
|
||||
|
||||
struct S_MaterialProperty
|
||||
{
|
||||
// The vector components are R,G,B
|
||||
Vector ambient, diffuse, specular, emissive;
|
||||
float glossiness, alpha;
|
||||
// The vector components are R,G,B
|
||||
Vector ambient, diffuse, specular, emissive;
|
||||
float glossiness, alpha;
|
||||
};
|
||||
|
||||
struct S_VertexColorProperty
|
||||
{
|
||||
/* Vertex mode:
|
||||
0 - source ignore
|
||||
1 - source emmisive
|
||||
2 - source amb diff
|
||||
/* Vertex mode:
|
||||
0 - source ignore
|
||||
1 - source emmisive
|
||||
2 - source amb diff
|
||||
|
||||
Lighting mode
|
||||
0 - lighting emmisive
|
||||
1 - lighting emmisive ambient/diffuse
|
||||
*/
|
||||
int vertmode, lightmode;
|
||||
Lighting mode
|
||||
0 - lighting emmisive
|
||||
1 - lighting emmisive ambient/diffuse
|
||||
*/
|
||||
int vertmode, lightmode;
|
||||
};
|
||||
|
||||
struct S_AlphaProperty
|
||||
{
|
||||
/*
|
||||
In NiAlphaProperty, the flags have the following meaning:
|
||||
/*
|
||||
In NiAlphaProperty, the flags have the following meaning:
|
||||
|
||||
Bit 0 : alpha blending enable
|
||||
Bits 1-4 : source blend mode
|
||||
Bits 5-8 : destination blend mode
|
||||
Bit 9 : alpha test enable
|
||||
Bit 10-12 : alpha test mode
|
||||
Bit 13 : no sorter flag ( disables triangle sorting )
|
||||
Bit 0 : alpha blending enable
|
||||
Bits 1-4 : source blend mode
|
||||
Bits 5-8 : destination blend mode
|
||||
Bit 9 : alpha test enable
|
||||
Bit 10-12 : alpha test mode
|
||||
Bit 13 : no sorter flag ( disables triangle sorting )
|
||||
|
||||
blend modes (glBlendFunc):
|
||||
0000 GL_ONE
|
||||
0001 GL_ZERO
|
||||
0010 GL_SRC_COLOR
|
||||
0011 GL_ONE_MINUS_SRC_COLOR
|
||||
0100 GL_DST_COLOR
|
||||
0101 GL_ONE_MINUS_DST_COLOR
|
||||
0110 GL_SRC_ALPHA
|
||||
0111 GL_ONE_MINUS_SRC_ALPHA
|
||||
1000 GL_DST_ALPHA
|
||||
1001 GL_ONE_MINUS_DST_ALPHA
|
||||
1010 GL_SRC_ALPHA_SATURATE
|
||||
blend modes (glBlendFunc):
|
||||
0000 GL_ONE
|
||||
0001 GL_ZERO
|
||||
0010 GL_SRC_COLOR
|
||||
0011 GL_ONE_MINUS_SRC_COLOR
|
||||
0100 GL_DST_COLOR
|
||||
0101 GL_ONE_MINUS_DST_COLOR
|
||||
0110 GL_SRC_ALPHA
|
||||
0111 GL_ONE_MINUS_SRC_ALPHA
|
||||
1000 GL_DST_ALPHA
|
||||
1001 GL_ONE_MINUS_DST_ALPHA
|
||||
1010 GL_SRC_ALPHA_SATURATE
|
||||
|
||||
test modes (glAlphaFunc):
|
||||
000 GL_ALWAYS
|
||||
001 GL_LESS
|
||||
010 GL_EQUAL
|
||||
011 GL_LEQUAL
|
||||
100 GL_GREATER
|
||||
101 GL_NOTEQUAL
|
||||
110 GL_GEQUAL
|
||||
111 GL_NEVER
|
||||
test modes (glAlphaFunc):
|
||||
000 GL_ALWAYS
|
||||
001 GL_LESS
|
||||
010 GL_EQUAL
|
||||
011 GL_LEQUAL
|
||||
100 GL_GREATER
|
||||
101 GL_NOTEQUAL
|
||||
110 GL_GEQUAL
|
||||
111 GL_NEVER
|
||||
|
||||
Taken from:
|
||||
http://niftools.sourceforge.net/doc/nif/NiAlphaProperty.html
|
||||
Taken from:
|
||||
http://niftools.sourceforge.net/doc/nif/NiAlphaProperty.html
|
||||
|
||||
Right now we only use standard alpha blending (see the Ogre code
|
||||
that sets it up) and it appears that this is the only blending
|
||||
used in the original game. Bloodmoon (along with several mods) do
|
||||
however use other settings, such as discarding pixel values with
|
||||
alpha < 1.0. This is faster because we don't have to mess with the
|
||||
depth stuff like we did for blending. And OGRE has settings for
|
||||
this too.
|
||||
*/
|
||||
Right now we only use standard alpha blending (see the Ogre code
|
||||
that sets it up) and it appears that this is the only blending
|
||||
used in the original game. Bloodmoon (along with several mods) do
|
||||
however use other settings, such as discarding pixel values with
|
||||
alpha < 1.0. This is faster because we don't have to mess with the
|
||||
depth stuff like we did for blending. And OGRE has settings for
|
||||
this too.
|
||||
*/
|
||||
|
||||
// Tested against when certain flags are set (see above.)
|
||||
unsigned char threshold;
|
||||
// Tested against when certain flags are set (see above.)
|
||||
unsigned char threshold;
|
||||
};
|
||||
|
||||
typedef StructPropT<S_AlphaProperty> NiAlphaProperty;
|
||||
|
|
|
@ -88,26 +88,25 @@ enum RecordType
|
|||
/// Base class for all records
|
||||
struct Record
|
||||
{
|
||||
// Record type and type name
|
||||
int recType;
|
||||
Misc::SString recName;
|
||||
// Record type and type name
|
||||
int recType;
|
||||
Misc::SString recName;
|
||||
|
||||
Record() : recType(RC_MISSING) {}
|
||||
Record() : recType(RC_MISSING) {}
|
||||
|
||||
/// Parses the record from file
|
||||
virtual void read(NIFFile *nif) = 0;
|
||||
/// Parses the record from file
|
||||
virtual void read(NIFFile *nif) = 0;
|
||||
|
||||
/// Does post-processing, after the entire tree is loaded
|
||||
virtual void post(NIFFile *nif) {}
|
||||
/// Does post-processing, after the entire tree is loaded
|
||||
virtual void post(NIFFile *nif) {}
|
||||
|
||||
virtual ~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);
|
||||
*/
|
||||
/*
|
||||
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);
|
||||
*/
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
|
|
|
@ -37,61 +37,51 @@ namespace Nif
|
|||
template <class X>
|
||||
class RecordPtrT
|
||||
{
|
||||
int index;
|
||||
X* ptr;
|
||||
NIFFile *nif;
|
||||
union {
|
||||
intptr_t index;
|
||||
X* ptr;
|
||||
};
|
||||
|
||||
public:
|
||||
public:
|
||||
RecordPtrT() : index(-2) {}
|
||||
|
||||
RecordPtrT() : index(-2), ptr(NULL) {}
|
||||
/// Read the index from the nif
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
// Can only read the index once
|
||||
assert(index == -2);
|
||||
|
||||
/// Read the index from the nif
|
||||
void read(NIFFile *_nif)
|
||||
{
|
||||
// Can only read the index once
|
||||
assert(index == -2);
|
||||
// Store the index for later
|
||||
index = nif->getInt();
|
||||
}
|
||||
|
||||
// Store the NIFFile pointer for later
|
||||
nif = _nif;
|
||||
/// Resolve index to pointer
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
if(index < 0)
|
||||
ptr = NULL;
|
||||
else
|
||||
{
|
||||
Record *r = nif->getRecord(index);
|
||||
// And cast it
|
||||
ptr = dynamic_cast<X*>(r);
|
||||
assert(ptr != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// And the index, of course
|
||||
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()
|
||||
{
|
||||
// Have we found the pointer already?
|
||||
if(ptr == NULL)
|
||||
{
|
||||
// Get the record
|
||||
assert(index >= 0);
|
||||
Record *r = nif->getRecord(index);
|
||||
|
||||
// And cast it
|
||||
ptr = dynamic_cast<X*>(r);
|
||||
/// Look up the actual object from the index
|
||||
X* getPtr()
|
||||
{
|
||||
assert(ptr != NULL);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
X& get() { return *getPtr(); }
|
||||
|
||||
/// Syntactic sugar
|
||||
X* operator->() { return getPtr(); }
|
||||
X& get() { return *getPtr(); }
|
||||
/// Syntactic sugar
|
||||
X* operator->() { return getPtr(); }
|
||||
|
||||
/// Pointers are allowed to be empty
|
||||
bool empty() { return index == -1 && ptr == NULL; }
|
||||
|
||||
int getIndex() { return index; }
|
||||
/// Pointers are allowed to be empty
|
||||
bool empty() { return ptr == NULL; }
|
||||
};
|
||||
|
||||
/** A list of references to other records. These are read as a list,
|
||||
|
@ -101,40 +91,38 @@ class RecordPtrT
|
|||
template <class X>
|
||||
class RecordListT
|
||||
{
|
||||
typedef RecordPtrT<X> Ptr;
|
||||
std::vector<Ptr> list;
|
||||
typedef RecordPtrT<X> Ptr;
|
||||
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++)
|
||||
list[i].read(nif);
|
||||
}
|
||||
|
||||
X& operator[](int index)
|
||||
public:
|
||||
void read(NIFFile *nif)
|
||||
{
|
||||
assert(index >= 0 && index < static_cast<int> (list.size()));
|
||||
return list[index].get();
|
||||
int len = nif->getInt();
|
||||
list.resize(len);
|
||||
|
||||
for(size_t i=0;i < list.size();i++)
|
||||
list[i].read(nif);
|
||||
}
|
||||
|
||||
bool has(int index)
|
||||
{
|
||||
assert(index >= 0 && index < static_cast<int> (list.size()));
|
||||
return !list[index].empty();
|
||||
}
|
||||
|
||||
int getIndex(int index)
|
||||
void post(NIFFile *nif)
|
||||
{
|
||||
if(has(index)) return list[index].getIndex();
|
||||
else return -1;
|
||||
for(size_t i=0;i < list.size();i++)
|
||||
list[i].post(nif);
|
||||
}
|
||||
|
||||
int length() { return list.size(); }
|
||||
X& operator[](size_t index)
|
||||
{
|
||||
return list.at(index).get();
|
||||
}
|
||||
|
||||
bool has(size_t index)
|
||||
{
|
||||
assert(index >= 0 && index < static_cast<int> (list.size()));
|
||||
return !list.at(index).empty();
|
||||
}
|
||||
|
||||
int length()
|
||||
{ return list.size(); }
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue