mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
f2fb3d6de8
NIFFile might not always be created from a file or stream containing NIF data. Basically there are 2 different responsibilities for this class: 1. Read NIF file 2. Provide input for nifosg and bulletnifloader. Remove no longer needed NIFFileMock since the state of NIFFfile can be initialized independently from reading NIF file.
288 lines
8.4 KiB
C++
288 lines
8.4 KiB
C++
#include "node.hpp"
|
|
|
|
#include <components/misc/algorithm.hpp>
|
|
|
|
#include "data.hpp"
|
|
#include "exception.hpp"
|
|
#include "physics.hpp"
|
|
#include "property.hpp"
|
|
|
|
namespace Nif
|
|
{
|
|
void NiBoundingVolume::read(NIFStream* nif)
|
|
{
|
|
type = nif->getUInt();
|
|
switch (type)
|
|
{
|
|
case BASE_BV:
|
|
break;
|
|
case SPHERE_BV:
|
|
{
|
|
sphere.center = nif->getVector3();
|
|
sphere.radius = nif->getFloat();
|
|
break;
|
|
}
|
|
case BOX_BV:
|
|
{
|
|
box.center = nif->getVector3();
|
|
box.axes = nif->getMatrix3();
|
|
box.extents = nif->getVector3();
|
|
break;
|
|
}
|
|
case CAPSULE_BV:
|
|
{
|
|
capsule.center = nif->getVector3();
|
|
capsule.axis = nif->getVector3();
|
|
capsule.extent = nif->getFloat();
|
|
capsule.radius = nif->getFloat();
|
|
break;
|
|
}
|
|
case LOZENGE_BV:
|
|
{
|
|
lozenge.radius = nif->getFloat();
|
|
if (nif->getVersion() >= NIFStream::generateVersion(4, 2, 1, 0))
|
|
{
|
|
lozenge.extent0 = nif->getFloat();
|
|
lozenge.extent1 = nif->getFloat();
|
|
}
|
|
lozenge.center = nif->getVector3();
|
|
lozenge.axis0 = nif->getVector3();
|
|
lozenge.axis1 = nif->getVector3();
|
|
break;
|
|
}
|
|
case UNION_BV:
|
|
{
|
|
unsigned int numChildren = nif->getUInt();
|
|
if (numChildren == 0)
|
|
break;
|
|
children.resize(numChildren);
|
|
for (NiBoundingVolume& child : children)
|
|
child.read(nif);
|
|
break;
|
|
}
|
|
case HALFSPACE_BV:
|
|
{
|
|
halfSpace.plane = osg::Plane(nif->getVector4());
|
|
if (nif->getVersion() >= NIFStream::generateVersion(4, 2, 1, 0))
|
|
halfSpace.origin = nif->getVector3();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
throw Nif::Exception(
|
|
"Unhandled NiBoundingVolume type: " + std::to_string(type), nif->getFile().getFilename());
|
|
}
|
|
}
|
|
}
|
|
|
|
void Node::read(NIFStream* nif)
|
|
{
|
|
Named::read(nif);
|
|
|
|
flags = nif->getBethVersion() <= 26 ? nif->getUShort() : nif->getUInt();
|
|
trafo = nif->getTrafo();
|
|
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
|
|
velocity = nif->getVector3();
|
|
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
|
props.read(nif);
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(4, 2, 2, 0))
|
|
hasBounds = nif->getBoolean();
|
|
if (hasBounds)
|
|
bounds.read(nif);
|
|
// Reference to the collision object in Gamebryo files.
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
|
|
collision.read(nif);
|
|
|
|
parents.clear();
|
|
|
|
isBone = false;
|
|
}
|
|
|
|
void Node::post(Reader& nif)
|
|
{
|
|
Named::post(nif);
|
|
props.post(nif);
|
|
collision.post(nif);
|
|
}
|
|
|
|
void Node::setBone()
|
|
{
|
|
isBone = true;
|
|
}
|
|
|
|
void NiNode::read(NIFStream* nif)
|
|
{
|
|
Node::read(nif);
|
|
children.read(nif);
|
|
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
|
|
effects.read(nif);
|
|
|
|
// Discard transformations for the root node, otherwise some meshes
|
|
// occasionally get wrong orientation. Only for NiNode-s for now, but
|
|
// can be expanded if needed.
|
|
// FIXME: if node 0 is *not* the only root node, this must not happen.
|
|
if (0 == recIndex && !Misc::StringUtils::ciEqual(name, "bip01"))
|
|
{
|
|
trafo = Nif::Transformation::getIdentity();
|
|
}
|
|
}
|
|
|
|
void NiNode::post(Reader& nif)
|
|
{
|
|
Node::post(nif);
|
|
children.post(nif);
|
|
effects.post(nif);
|
|
|
|
for (size_t i = 0; i < children.length(); i++)
|
|
{
|
|
// Why would a unique list of children contain empty refs?
|
|
if (!children[i].empty())
|
|
children[i]->parents.push_back(this);
|
|
}
|
|
}
|
|
|
|
void NiGeometry::MaterialData::read(NIFStream* nif)
|
|
{
|
|
if (nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 0))
|
|
return;
|
|
unsigned int num = 0;
|
|
if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 3))
|
|
num = nif->getBoolean(); // Has Shader
|
|
else if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
|
|
num = nif->getUInt();
|
|
if (num)
|
|
{
|
|
nif->getStrings(names, num);
|
|
nif->getInts(extra, num);
|
|
}
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
|
|
active = nif->getUInt();
|
|
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
|
|
needsUpdate = nif->getBoolean();
|
|
}
|
|
|
|
void NiGeometry::read(NIFStream* nif)
|
|
{
|
|
Node::read(nif);
|
|
data.read(nif);
|
|
skin.read(nif);
|
|
material.read(nif);
|
|
if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS
|
|
&& nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
|
|
{
|
|
shaderprop.read(nif);
|
|
alphaprop.read(nif);
|
|
}
|
|
}
|
|
|
|
void NiGeometry::post(Reader& nif)
|
|
{
|
|
Node::post(nif);
|
|
data.post(nif);
|
|
skin.post(nif);
|
|
shaderprop.post(nif);
|
|
alphaprop.post(nif);
|
|
if (recType != RC_NiParticles && !skin.empty())
|
|
nif.setUseSkinning(true);
|
|
}
|
|
|
|
void BSLODTriShape::read(NIFStream* nif)
|
|
{
|
|
NiTriShape::read(nif);
|
|
lod0 = nif->getUInt();
|
|
lod1 = nif->getUInt();
|
|
lod2 = nif->getUInt();
|
|
}
|
|
|
|
void NiCamera::Camera::read(NIFStream* nif)
|
|
{
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
cameraFlags = nif->getUShort();
|
|
left = nif->getFloat();
|
|
right = nif->getFloat();
|
|
top = nif->getFloat();
|
|
bottom = nif->getFloat();
|
|
nearDist = nif->getFloat();
|
|
farDist = nif->getFloat();
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
orthographic = nif->getBoolean();
|
|
vleft = nif->getFloat();
|
|
vright = nif->getFloat();
|
|
vtop = nif->getFloat();
|
|
vbottom = nif->getFloat();
|
|
|
|
LOD = nif->getFloat();
|
|
}
|
|
|
|
void NiCamera::read(NIFStream* nif)
|
|
{
|
|
Node::read(nif);
|
|
|
|
cam.read(nif);
|
|
|
|
nif->getInt(); // -1
|
|
nif->getInt(); // 0
|
|
if (nif->getVersion() >= NIFStream::generateVersion(4, 2, 1, 0))
|
|
nif->getInt(); // 0
|
|
}
|
|
|
|
void NiSwitchNode::read(NIFStream* nif)
|
|
{
|
|
NiNode::read(nif);
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
switchFlags = nif->getUShort();
|
|
initialIndex = nif->getUInt();
|
|
}
|
|
|
|
void NiLODNode::read(NIFStream* nif)
|
|
{
|
|
NiSwitchNode::read(nif);
|
|
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW
|
|
&& nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 0))
|
|
lodCenter = nif->getVector3();
|
|
else if (nif->getVersion() > NIFStream::generateVersion(10, 0, 1, 0))
|
|
{
|
|
nif->skip(4); // NiLODData, unsupported at the moment
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
void NiFltAnimationNode::read(NIFStream* nif)
|
|
{
|
|
NiSwitchNode::read(nif);
|
|
mDuration = nif->getFloat();
|
|
}
|
|
|
|
void NiSortAdjustNode::read(NIFStream* nif)
|
|
{
|
|
NiNode::read(nif);
|
|
mMode = nif->getInt();
|
|
if (nif->getVersion() <= NIFStream::generateVersion(20, 0, 0, 3))
|
|
mSubSorter.read(nif);
|
|
}
|
|
|
|
void NiSortAdjustNode::post(Reader& nif)
|
|
{
|
|
NiNode::post(nif);
|
|
mSubSorter.post(nif);
|
|
}
|
|
|
|
void NiBillboardNode::read(NIFStream* nif)
|
|
{
|
|
NiNode::read(nif);
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
|
|
mMode = nif->getUShort() & 0x7;
|
|
else
|
|
mMode = (flags >> 5) & 0x3;
|
|
}
|
|
}
|