2013-02-24 21:51:56 +00:00
|
|
|
#ifndef OPENMW_COMPONENTS_NIF_NODE_HPP
|
|
|
|
#define OPENMW_COMPONENTS_NIF_NODE_HPP
|
2010-01-06 11:28:37 +00:00
|
|
|
|
2010-06-03 18:44:55 +00:00
|
|
|
#include "controlled.hpp"
|
2014-10-19 06:26:44 +00:00
|
|
|
#include "extra.hpp"
|
2010-06-03 18:44:55 +00:00
|
|
|
#include "data.hpp"
|
2012-07-03 04:41:21 +00:00
|
|
|
#include "property.hpp"
|
2014-08-24 17:27:09 +00:00
|
|
|
#include "niftypes.hpp"
|
2014-10-19 06:26:44 +00:00
|
|
|
#include "controller.hpp"
|
|
|
|
#include "base.hpp"
|
2010-01-06 11:28:37 +00:00
|
|
|
|
2016-01-02 00:12:44 +00:00
|
|
|
#include <components/misc/stringops.hpp>
|
|
|
|
|
2010-01-06 11:28:37 +00:00
|
|
|
namespace Nif
|
|
|
|
{
|
|
|
|
|
2015-03-06 08:36:42 +00:00
|
|
|
struct NiNode;
|
2012-07-03 05:49:44 +00:00
|
|
|
|
2010-01-06 11:28:37 +00:00
|
|
|
/** A Node is an object that's part of the main NIF tree. It has
|
|
|
|
parent node (unless it's the root), and transformation (location
|
|
|
|
and rotation) relative to it's parent.
|
|
|
|
*/
|
2010-06-28 01:05:01 +00:00
|
|
|
class Node : public Named
|
2010-01-06 11:28:37 +00:00
|
|
|
{
|
2010-06-28 01:05:01 +00:00
|
|
|
public:
|
2012-07-03 04:41:21 +00:00
|
|
|
// Node flags. Interpretation depends somewhat on the type of node.
|
2019-12-29 12:53:44 +00:00
|
|
|
unsigned int flags;
|
2012-07-10 04:35:36 +00:00
|
|
|
Transformation trafo;
|
2015-02-17 16:08:55 +00:00
|
|
|
osg::Vec3f velocity; // Unused? Might be a run-time game state
|
2012-07-03 04:41:21 +00:00
|
|
|
PropertyList props;
|
|
|
|
|
|
|
|
// Bounding box info
|
|
|
|
bool hasBounds;
|
2015-02-17 16:08:55 +00:00
|
|
|
osg::Vec3f boundPos;
|
|
|
|
Matrix3 boundRot;
|
|
|
|
osg::Vec3f boundXYZ; // Box size
|
2012-07-03 04:41:21 +00:00
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
|
|
|
Named::read(nif);
|
|
|
|
|
2012-07-10 10:52:01 +00:00
|
|
|
flags = nif->getUShort();
|
2012-07-03 04:41:21 +00:00
|
|
|
trafo = nif->getTrafo();
|
2012-07-12 18:21:52 +00:00
|
|
|
velocity = nif->getVector3();
|
2012-07-03 04:41:21 +00:00
|
|
|
props.read(nif);
|
|
|
|
|
2020-01-02 10:09:54 +00:00
|
|
|
hasBounds = nif->getBoolean();
|
2012-07-03 04:41:21 +00:00
|
|
|
if(hasBounds)
|
|
|
|
{
|
|
|
|
nif->getInt(); // always 1
|
2012-07-10 11:45:14 +00:00
|
|
|
boundPos = nif->getVector3();
|
|
|
|
boundRot = nif->getMatrix3();
|
|
|
|
boundXYZ = nif->getVector3();
|
2012-07-03 04:41:21 +00:00
|
|
|
}
|
|
|
|
|
2018-10-09 06:21:12 +00:00
|
|
|
parent = nullptr;
|
2012-07-03 05:49:44 +00:00
|
|
|
|
2017-02-26 21:39:23 +00:00
|
|
|
isBone = false;
|
2012-07-03 04:41:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Named::post(nif);
|
|
|
|
props.post(nif);
|
|
|
|
}
|
|
|
|
|
2018-10-09 06:21:12 +00:00
|
|
|
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
2012-07-03 05:49:44 +00:00
|
|
|
// NiNodes (or types derived from NiNodes) can be parents.
|
|
|
|
NiNode *parent;
|
|
|
|
|
2017-02-26 21:39:23 +00:00
|
|
|
bool isBone;
|
2012-07-03 04:41:21 +00:00
|
|
|
|
2017-02-26 21:39:23 +00:00
|
|
|
void setBone()
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
2017-02-26 21:39:23 +00:00
|
|
|
isBone = true;
|
2012-07-03 04:41:21 +00:00
|
|
|
}
|
2010-01-06 14:00:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct NiNode : Node
|
|
|
|
{
|
2012-07-03 04:41:21 +00:00
|
|
|
NodeList children;
|
|
|
|
NodeList effects;
|
|
|
|
|
2013-04-16 08:20:32 +00:00
|
|
|
enum Flags {
|
|
|
|
Flag_Hidden = 0x0001,
|
|
|
|
Flag_MeshCollision = 0x0002,
|
2020-02-19 08:14:21 +00:00
|
|
|
Flag_BBoxCollision = 0x0004,
|
|
|
|
Flag_ActiveCollision = 0x0020
|
2013-04-16 08:20:32 +00:00
|
|
|
};
|
|
|
|
enum BSAnimFlags {
|
|
|
|
AnimFlag_AutoPlay = 0x0020
|
|
|
|
};
|
|
|
|
enum BSParticleFlags {
|
2013-11-25 12:50:33 +00:00
|
|
|
ParticleFlag_AutoPlay = 0x0020,
|
|
|
|
ParticleFlag_LocalSpace = 0x0080
|
2013-04-16 08:20:32 +00:00
|
|
|
};
|
2014-01-31 04:59:58 +00:00
|
|
|
enum ControllerFlags {
|
|
|
|
ControllerFlag_Active = 0x8
|
|
|
|
};
|
2012-07-03 04:41:21 +00:00
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
|
|
|
Node::read(nif);
|
|
|
|
children.read(nif);
|
|
|
|
effects.read(nif);
|
2014-08-24 17:27:09 +00:00
|
|
|
|
2016-01-02 00:12:44 +00:00
|
|
|
// Discard transformations for the root node, otherwise some meshes
|
2014-08-24 17:27:09 +00:00
|
|
|
// occasionally get wrong orientation. Only for NiNode-s for now, but
|
|
|
|
// can be expanded if needed.
|
2016-01-02 00:12:44 +00:00
|
|
|
if (0 == recIndex && !Misc::StringUtils::ciEqual(name, "bip01"))
|
2014-08-24 17:27:09 +00:00
|
|
|
{
|
|
|
|
static_cast<Nif::Node*>(this)->trafo = Nif::Transformation::getIdentity();
|
|
|
|
}
|
2012-07-03 04:41:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Node::post(nif);
|
|
|
|
children.post(nif);
|
|
|
|
effects.post(nif);
|
2012-07-03 05:49:44 +00:00
|
|
|
|
|
|
|
for(size_t i = 0;i < children.length();i++)
|
2012-07-04 01:37:04 +00:00
|
|
|
{
|
|
|
|
// Why would a unique list of children contain empty refs?
|
2012-07-12 12:37:56 +00:00
|
|
|
if(!children[i].empty())
|
|
|
|
children[i]->parent = this;
|
2012-07-04 01:37:04 +00:00
|
|
|
}
|
2012-07-03 04:41:21 +00:00
|
|
|
}
|
2010-01-06 14:00:08 +00:00
|
|
|
};
|
|
|
|
|
2020-05-14 07:52:27 +00:00
|
|
|
struct NiGeometry : Node
|
|
|
|
{
|
|
|
|
NiSkinInstancePtr skin;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NiTriShape : NiGeometry
|
2010-01-06 14:00:08 +00:00
|
|
|
{
|
2012-07-03 04:41:21 +00:00
|
|
|
/* Possible flags:
|
|
|
|
0x40 - mesh has no vertex normals ?
|
|
|
|
|
|
|
|
Only flags included in 0x47 (ie. 0x01, 0x02, 0x04 and 0x40) have
|
|
|
|
been observed so far.
|
|
|
|
*/
|
|
|
|
|
|
|
|
NiTriShapeDataPtr data;
|
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
|
|
|
Node::read(nif);
|
|
|
|
data.read(nif);
|
|
|
|
skin.read(nif);
|
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Node::post(nif);
|
|
|
|
data.post(nif);
|
|
|
|
skin.post(nif);
|
2015-03-25 14:39:41 +00:00
|
|
|
if (!skin.empty())
|
|
|
|
nif->setUseSkinning(true);
|
2012-07-03 04:41:21 +00:00
|
|
|
}
|
2010-01-06 11:28:37 +00:00
|
|
|
};
|
|
|
|
|
2020-05-14 07:52:27 +00:00
|
|
|
struct NiTriStrips : NiGeometry
|
2019-08-08 10:11:24 +00:00
|
|
|
{
|
|
|
|
NiTriStripsDataPtr data;
|
|
|
|
|
|
|
|
void read(NIFStream *nif)
|
|
|
|
{
|
|
|
|
Node::read(nif);
|
|
|
|
data.read(nif);
|
|
|
|
skin.read(nif);
|
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Node::post(nif);
|
|
|
|
data.post(nif);
|
|
|
|
skin.post(nif);
|
|
|
|
if (!skin.empty())
|
|
|
|
nif->setUseSkinning(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-30 14:59:36 +00:00
|
|
|
struct NiLines : NiGeometry
|
|
|
|
{
|
|
|
|
NiLinesDataPtr data;
|
|
|
|
|
|
|
|
void read(NIFStream *nif)
|
|
|
|
{
|
|
|
|
Node::read(nif);
|
|
|
|
data.read(nif);
|
|
|
|
skin.read(nif);
|
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Node::post(nif);
|
|
|
|
data.post(nif);
|
|
|
|
skin.post(nif);
|
|
|
|
if (!skin.empty())
|
|
|
|
nif->setUseSkinning(true);
|
|
|
|
}
|
|
|
|
};
|
2019-08-08 10:11:24 +00:00
|
|
|
|
2010-01-07 18:11:03 +00:00
|
|
|
struct NiCamera : Node
|
|
|
|
{
|
2012-07-03 04:41:21 +00:00
|
|
|
struct Camera
|
|
|
|
{
|
|
|
|
// Camera frustrum
|
|
|
|
float left, right, top, bottom, nearDist, farDist;
|
2010-01-07 18:11:03 +00:00
|
|
|
|
2012-07-03 04:41:21 +00:00
|
|
|
// Viewport
|
|
|
|
float vleft, vright, vtop, vbottom;
|
2010-01-07 18:11:03 +00:00
|
|
|
|
2012-07-03 04:41:21 +00:00
|
|
|
// Level of detail modifier
|
|
|
|
float LOD;
|
2012-07-10 07:27:13 +00:00
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-10 07:27:13 +00:00
|
|
|
{
|
2012-07-10 11:21:47 +00:00
|
|
|
left = nif->getFloat();
|
|
|
|
right = nif->getFloat();
|
|
|
|
top = nif->getFloat();
|
|
|
|
bottom = nif->getFloat();
|
|
|
|
nearDist = nif->getFloat();
|
|
|
|
farDist = nif->getFloat();
|
|
|
|
|
|
|
|
vleft = nif->getFloat();
|
|
|
|
vright = nif->getFloat();
|
|
|
|
vtop = nif->getFloat();
|
|
|
|
vbottom = nif->getFloat();
|
|
|
|
|
|
|
|
LOD = nif->getFloat();
|
2012-07-10 07:27:13 +00:00
|
|
|
}
|
2012-07-03 04:41:21 +00:00
|
|
|
};
|
2012-07-10 04:35:36 +00:00
|
|
|
Camera cam;
|
2010-01-07 18:11:03 +00:00
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
|
|
|
Node::read(nif);
|
2010-01-07 18:11:03 +00:00
|
|
|
|
2012-07-10 07:27:13 +00:00
|
|
|
cam.read(nif);
|
2010-01-07 18:11:03 +00:00
|
|
|
|
2012-07-03 04:41:21 +00:00
|
|
|
nif->getInt(); // -1
|
|
|
|
nif->getInt(); // 0
|
|
|
|
}
|
2010-01-07 18:11:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct NiAutoNormalParticles : Node
|
|
|
|
{
|
2012-07-03 04:41:21 +00:00
|
|
|
NiAutoNormalParticlesDataPtr data;
|
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
|
|
|
Node::read(nif);
|
|
|
|
data.read(nif);
|
|
|
|
nif->getInt(); // -1
|
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Node::post(nif);
|
|
|
|
data.post(nif);
|
|
|
|
}
|
2010-01-07 18:11:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct NiRotatingParticles : Node
|
|
|
|
{
|
2012-07-03 04:41:21 +00:00
|
|
|
NiRotatingParticlesDataPtr data;
|
|
|
|
|
2013-01-05 21:03:05 +00:00
|
|
|
void read(NIFStream *nif)
|
2012-07-03 04:41:21 +00:00
|
|
|
{
|
|
|
|
Node::read(nif);
|
|
|
|
data.read(nif);
|
|
|
|
nif->getInt(); // -1
|
|
|
|
}
|
|
|
|
|
|
|
|
void post(NIFFile *nif)
|
|
|
|
{
|
|
|
|
Node::post(nif);
|
|
|
|
data.post(nif);
|
|
|
|
}
|
2010-01-07 18:11:03 +00:00
|
|
|
};
|
|
|
|
|
2015-11-12 18:40:31 +00:00
|
|
|
// A node used as the base to switch between child nodes, such as for LOD levels.
|
|
|
|
struct NiSwitchNode : public NiNode
|
|
|
|
{
|
2019-06-08 22:58:02 +00:00
|
|
|
unsigned int initialIndex;
|
|
|
|
|
2015-11-12 18:40:31 +00:00
|
|
|
void read(NIFStream *nif)
|
|
|
|
{
|
|
|
|
NiNode::read(nif);
|
2019-06-08 22:58:02 +00:00
|
|
|
initialIndex = nif->getUInt();
|
2015-11-12 18:40:31 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NiLODNode : public NiSwitchNode
|
|
|
|
{
|
|
|
|
osg::Vec3f lodCenter;
|
|
|
|
|
|
|
|
struct LODRange
|
|
|
|
{
|
|
|
|
float minRange;
|
|
|
|
float maxRange;
|
|
|
|
};
|
|
|
|
std::vector<LODRange> lodLevels;
|
|
|
|
|
|
|
|
void read(NIFStream *nif)
|
|
|
|
{
|
|
|
|
NiSwitchNode::read(nif);
|
2020-05-12 22:06:38 +00:00
|
|
|
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFStream::generateVersion(10,0,1,0))
|
2020-02-02 14:08:17 +00:00
|
|
|
lodCenter = nif->getVector3();
|
2015-11-12 18:40:31 +00:00
|
|
|
unsigned int numLodLevels = nif->getUInt();
|
|
|
|
for (unsigned int i=0; i<numLodLevels; ++i)
|
|
|
|
{
|
|
|
|
LODRange r;
|
|
|
|
r.minRange = nif->getFloat();
|
|
|
|
r.maxRange = nif->getFloat();
|
|
|
|
lodLevels.push_back(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-01-06 11:28:37 +00:00
|
|
|
} // Namespace
|
|
|
|
#endif
|