mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-03 13:39:40 +00:00
Move NIF implementation to cpp files
This commit is contained in:
parent
ebc34ea251
commit
c36c28e8f9
18 changed files with 397 additions and 326 deletions
|
@ -1,5 +1,7 @@
|
||||||
#include <components/nifbullet/bulletnifloader.hpp>
|
#include <components/nifbullet/bulletnifloader.hpp>
|
||||||
#include <components/bullethelpers/processtrianglecallback.hpp>
|
#include <components/bullethelpers/processtrianglecallback.hpp>
|
||||||
|
#include <components/nif/data.hpp>
|
||||||
|
#include <components/nif/extra.hpp>
|
||||||
#include <components/nif/node.hpp>
|
#include <components/nif/node.hpp>
|
||||||
|
|
||||||
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
||||||
|
|
32
components/nif/base.cpp
Normal file
32
components/nif/base.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
namespace Nif
|
||||||
|
{
|
||||||
|
void Extra::read(NIFStream *nif)
|
||||||
|
{
|
||||||
|
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0))
|
||||||
|
name = nif->getString();
|
||||||
|
else if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0))
|
||||||
|
{
|
||||||
|
next.read(nif);
|
||||||
|
recordSize = nif->getUInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Named::read(NIFStream *nif)
|
||||||
|
{
|
||||||
|
name = nif->getString();
|
||||||
|
if (nif->getVersion() < NIFStream::generateVersion(10,0,1,0))
|
||||||
|
extra.read(nif);
|
||||||
|
else
|
||||||
|
extralist.read(nif);
|
||||||
|
controller.read(nif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Named::post(NIFFile *nif)
|
||||||
|
{
|
||||||
|
extra.post(nif);
|
||||||
|
extralist.post(nif);
|
||||||
|
controller.post(nif);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,14 +2,14 @@
|
||||||
#ifndef OPENMW_COMPONENTS_NIF_BASE_HPP
|
#ifndef OPENMW_COMPONENTS_NIF_BASE_HPP
|
||||||
#define OPENMW_COMPONENTS_NIF_BASE_HPP
|
#define OPENMW_COMPONENTS_NIF_BASE_HPP
|
||||||
|
|
||||||
#include "record.hpp"
|
|
||||||
#include "niffile.hpp"
|
|
||||||
#include "recordptr.hpp"
|
#include "recordptr.hpp"
|
||||||
#include "nifstream.hpp"
|
|
||||||
#include "nifkey.hpp"
|
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
struct File;
|
||||||
|
struct Record;
|
||||||
|
struct Stream;
|
||||||
|
|
||||||
// An extra data record. All the extra data connected to an object form a linked list.
|
// An extra data record. All the extra data connected to an object form a linked list.
|
||||||
struct Extra : public Record
|
struct Extra : public Record
|
||||||
{
|
{
|
||||||
|
@ -17,17 +17,7 @@ struct Extra : public Record
|
||||||
ExtraPtr next; // Next extra data record in the list
|
ExtraPtr next; // Next extra data record in the list
|
||||||
unsigned int recordSize{0u};
|
unsigned int recordSize{0u};
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0))
|
|
||||||
name = nif->getString();
|
|
||||||
else if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0))
|
|
||||||
{
|
|
||||||
next.read(nif);
|
|
||||||
recordSize = nif->getUInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void post(NIFFile *nif) override { next.post(nif); }
|
void post(NIFFile *nif) override { next.post(nif); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,22 +56,8 @@ struct Named : public Record
|
||||||
ExtraList extralist;
|
ExtraList extralist;
|
||||||
ControllerPtr controller;
|
ControllerPtr controller;
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
void post(NIFFile *nif) override;
|
||||||
name = nif->getString();
|
|
||||||
if (nif->getVersion() < NIFStream::generateVersion(10,0,1,0))
|
|
||||||
extra.read(nif);
|
|
||||||
else
|
|
||||||
extralist.read(nif);
|
|
||||||
controller.read(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void post(NIFFile *nif) override
|
|
||||||
{
|
|
||||||
extra.post(nif);
|
|
||||||
extralist.post(nif);
|
|
||||||
controller.post(nif);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
using NiSequenceStreamHelper = Named;
|
using NiSequenceStreamHelper = Named;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "controller.hpp"
|
#include "controller.hpp"
|
||||||
|
|
||||||
#include "node.hpp"
|
#include "controlled.hpp"
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "node.hpp"
|
||||||
|
#include "recordptr.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "nifkey.hpp"
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
|
|
||||||
|
#include "nifkey.hpp"
|
||||||
#include "niftypes.hpp" // Transformation
|
#include "niftypes.hpp" // Transformation
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
#include "effect.hpp"
|
#include "effect.hpp"
|
||||||
|
|
||||||
|
#include "controlled.hpp"
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void NiDynamicEffect::read(NIFStream *nif)
|
||||||
|
{
|
||||||
|
Node::read(nif);
|
||||||
|
if (nif->getVersion() >= nif->generateVersion(10,1,0,106)
|
||||||
|
&& nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
|
||||||
|
nif->getBoolean(); // Switch state
|
||||||
|
unsigned int numAffectedNodes = nif->getUInt();
|
||||||
|
for (unsigned int i=0; i<numAffectedNodes; ++i)
|
||||||
|
nif->getUInt(); // ref to another Node
|
||||||
|
}
|
||||||
|
|
||||||
void NiLight::read(NIFStream *nif)
|
void NiLight::read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
NiDynamicEffect::read(nif);
|
NiDynamicEffect::read(nif);
|
||||||
|
|
|
@ -31,16 +31,7 @@ namespace Nif
|
||||||
|
|
||||||
struct NiDynamicEffect : public Node
|
struct NiDynamicEffect : public Node
|
||||||
{
|
{
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
Node::read(nif);
|
|
||||||
if (nif->getVersion() >= nif->generateVersion(10,1,0,106)
|
|
||||||
&& nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
|
|
||||||
nif->getBoolean(); // Switch state
|
|
||||||
unsigned int numAffectedNodes = nif->getUInt();
|
|
||||||
for (unsigned int i=0; i<numAffectedNodes; ++i)
|
|
||||||
nif->getUInt(); // ref to another Node
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used as base for NiAmbientLight, NiDirectionalLight, NiPointLight and NiSpotLight.
|
// Used as base for NiAmbientLight, NiDirectionalLight, NiPointLight and NiSpotLight.
|
||||||
|
|
|
@ -1,12 +1,22 @@
|
||||||
#include "niffile.hpp"
|
#include "niffile.hpp"
|
||||||
#include "effect.hpp"
|
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/files/hash.hpp>
|
#include <components/files/hash.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "controlled.hpp"
|
||||||
|
#include "controller.hpp"
|
||||||
|
#include "data.hpp"
|
||||||
|
#include "effect.hpp"
|
||||||
|
#include "extra.hpp"
|
||||||
|
#include "physics.hpp"
|
||||||
|
#include "property.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
@ -353,4 +363,21 @@ void NIFFile::setLoadUnsupportedFiles(bool load)
|
||||||
sLoadUnsupportedFiles = load;
|
sLoadUnsupportedFiles = load;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NIFFile::warn(const std::string &msg) const
|
||||||
|
{
|
||||||
|
Log(Debug::Warning) << " NIFFile Warning: " << msg << "\nFile: " << filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void NIFFile::fail(const std::string &msg) const
|
||||||
|
{
|
||||||
|
throw std::runtime_error(" NIFFile Error: " + msg + "\nFile: " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NIFFile::getString(uint32_t index) const
|
||||||
|
{
|
||||||
|
if (index == std::numeric_limits<uint32_t>::max())
|
||||||
|
return std::string();
|
||||||
|
return strings.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,9 @@
|
||||||
#ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP
|
#ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP
|
||||||
#define OPENMW_COMPONENTS_NIF_NIFFILE_HPP
|
#define OPENMW_COMPONENTS_NIF_NIFFILE_HPP
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
|
||||||
#include <components/files/istreamptr.hpp>
|
#include <components/files/istreamptr.hpp>
|
||||||
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
|
@ -97,15 +94,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Used if file parsing fails
|
/// Used if file parsing fails
|
||||||
[[noreturn]] void fail(const std::string &msg) const
|
[[noreturn]] void fail(const std::string &msg) const;
|
||||||
{
|
|
||||||
throw std::runtime_error(" NIFFile Error: " + msg + "\nFile: " + filename);
|
|
||||||
}
|
|
||||||
/// Used when something goes wrong, but not catastrophically so
|
/// Used when something goes wrong, but not catastrophically so
|
||||||
void warn(const std::string &msg) const
|
void warn(const std::string &msg) const;
|
||||||
{
|
|
||||||
Log(Debug::Warning) << " NIFFile Warning: " << msg << "\nFile: " << filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Open a NIF stream. The name is used for error messages.
|
/// Open a NIF stream. The name is used for error messages.
|
||||||
NIFFile(Files::IStreamPtr&& stream, const std::string &name);
|
NIFFile(Files::IStreamPtr&& stream, const std::string &name);
|
||||||
|
@ -128,12 +120,7 @@ public:
|
||||||
size_t numRoots() const override { return roots.size(); }
|
size_t numRoots() const override { return roots.size(); }
|
||||||
|
|
||||||
/// Get a given string from the file's string table
|
/// Get a given string from the file's string table
|
||||||
std::string getString(uint32_t index) const override
|
std::string getString(uint32_t index) const override;
|
||||||
{
|
|
||||||
if (index == std::numeric_limits<uint32_t>::max())
|
|
||||||
return std::string();
|
|
||||||
return strings.at(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether there is skinning contained in this NIF file.
|
/// Set whether there is skinning contained in this NIF file.
|
||||||
/// @note This is just a hint for users of the NIF file and has no effect on the loading procedure.
|
/// @note This is just a hint for users of the NIF file and has no effect on the loading procedure.
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
||||||
#define OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
#define OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
||||||
|
|
||||||
#include "nifstream.hpp"
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "nifstream.hpp"
|
||||||
#include "niffile.hpp"
|
#include "niffile.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <typeinfo>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,275 @@
|
||||||
|
#include "node.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include "data.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:
|
||||||
|
{
|
||||||
|
nif->file->fail("Unhandled NiBoundingVolume type: " + std::to_string(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(NIFFile *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(NIFFile *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(NIFFile *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(NIFFile *nif)
|
||||||
|
{
|
||||||
|
NiNode::post(nif);
|
||||||
|
mSubSorter.post(nif);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,16 +3,7 @@
|
||||||
|
|
||||||
#include <osg/Plane>
|
#include <osg/Plane>
|
||||||
|
|
||||||
#include "controlled.hpp"
|
|
||||||
#include "extra.hpp"
|
|
||||||
#include "data.hpp"
|
|
||||||
#include "property.hpp"
|
|
||||||
#include "niftypes.hpp"
|
|
||||||
#include "controller.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "physics.hpp"
|
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
@ -70,70 +61,8 @@ struct NiBoundingVolume
|
||||||
NiLozengeBV lozenge;
|
NiLozengeBV lozenge;
|
||||||
std::vector<NiBoundingVolume> children;
|
std::vector<NiBoundingVolume> children;
|
||||||
NiHalfSpaceBV halfSpace;
|
NiHalfSpaceBV halfSpace;
|
||||||
void read(NIFStream* nif)
|
|
||||||
{
|
void 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:
|
|
||||||
{
|
|
||||||
nif->file->fail("Unhandled NiBoundingVolume type: " + std::to_string(type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A Node is an object that's part of the main NIF tree. It has
|
/** A Node is an object that's part of the main NIF tree. It has
|
||||||
|
@ -163,36 +92,8 @@ struct Node : public Named
|
||||||
// Collision object info
|
// Collision object info
|
||||||
NiCollisionObjectPtr collision;
|
NiCollisionObjectPtr collision;
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
void post(NIFFile *nif) override;
|
||||||
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 post(NIFFile *nif) override
|
|
||||||
{
|
|
||||||
Named::post(nif);
|
|
||||||
props.post(nif);
|
|
||||||
collision.post(nif);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
// Parent node, or nullptr for the root node. As far as I'm aware, only
|
||||||
// NiNodes (or types derived from NiNodes) can be parents.
|
// NiNodes (or types derived from NiNodes) can be parents.
|
||||||
|
@ -200,10 +101,7 @@ struct Node : public Named
|
||||||
|
|
||||||
bool isBone{false};
|
bool isBone{false};
|
||||||
|
|
||||||
void setBone()
|
void setBone();
|
||||||
{
|
|
||||||
isBone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isHidden() const { return flags & Flag_Hidden; }
|
bool isHidden() const { return flags & Flag_Hidden; }
|
||||||
bool hasMeshCollision() const { return flags & Flag_MeshCollision; }
|
bool hasMeshCollision() const { return flags & Flag_MeshCollision; }
|
||||||
|
@ -224,36 +122,8 @@ struct NiNode : Node
|
||||||
ParticleFlag_LocalSpace = 0x0080
|
ParticleFlag_LocalSpace = 0x0080
|
||||||
};
|
};
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
void post(NIFFile *nif) override;
|
||||||
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 post(NIFFile *nif) override
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiGeometry : Node
|
struct NiGeometry : Node
|
||||||
|
@ -271,25 +141,7 @@ struct NiGeometry : Node
|
||||||
std::vector<int> extra;
|
std::vector<int> extra;
|
||||||
unsigned int active{0};
|
unsigned int active{0};
|
||||||
bool needsUpdate{false};
|
bool needsUpdate{false};
|
||||||
void read(NIFStream *nif)
|
void 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();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NiGeometryDataPtr data;
|
NiGeometryDataPtr data;
|
||||||
|
@ -298,42 +150,15 @@ struct NiGeometry : Node
|
||||||
BSShaderPropertyPtr shaderprop;
|
BSShaderPropertyPtr shaderprop;
|
||||||
NiAlphaPropertyPtr alphaprop;
|
NiAlphaPropertyPtr alphaprop;
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
void post(NIFFile *nif) override;
|
||||||
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 post(NIFFile *nif) override
|
|
||||||
{
|
|
||||||
Node::post(nif);
|
|
||||||
data.post(nif);
|
|
||||||
skin.post(nif);
|
|
||||||
shaderprop.post(nif);
|
|
||||||
alphaprop.post(nif);
|
|
||||||
if (recType != RC_NiParticles && !skin.empty())
|
|
||||||
nif->setUseSkinning(true);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiTriShape : NiGeometry {};
|
struct NiTriShape : NiGeometry {};
|
||||||
struct BSLODTriShape : NiTriShape
|
struct BSLODTriShape : NiTriShape
|
||||||
{
|
{
|
||||||
unsigned int lod0, lod1, lod2;
|
unsigned int lod0, lod1, lod2;
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
NiTriShape::read(nif);
|
|
||||||
lod0 = nif->getUInt();
|
|
||||||
lod1 = nif->getUInt();
|
|
||||||
lod2 = nif->getUInt();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
struct NiTriStrips : NiGeometry {};
|
struct NiTriStrips : NiGeometry {};
|
||||||
struct NiLines : NiGeometry {};
|
struct NiLines : NiGeometry {};
|
||||||
|
@ -357,39 +182,11 @@ struct NiCamera : Node
|
||||||
// Orthographic projection usage flag
|
// Orthographic projection usage flag
|
||||||
bool orthographic{false};
|
bool orthographic{false};
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void 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();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Camera cam;
|
Camera cam;
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
Node::read(nif);
|
|
||||||
|
|
||||||
cam.read(nif);
|
|
||||||
|
|
||||||
nif->getInt(); // -1
|
|
||||||
nif->getInt(); // 0
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(4,2,1,0))
|
|
||||||
nif->getInt(); // 0
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A node used as the base to switch between child nodes, such as for LOD levels.
|
// A node used as the base to switch between child nodes, such as for LOD levels.
|
||||||
|
@ -398,13 +195,7 @@ struct NiSwitchNode : public NiNode
|
||||||
unsigned int switchFlags{0};
|
unsigned int switchFlags{0};
|
||||||
unsigned int initialIndex{0};
|
unsigned int initialIndex{0};
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
NiNode::read(nif);
|
|
||||||
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
|
|
||||||
switchFlags = nif->getUShort();
|
|
||||||
initialIndex = nif->getUInt();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiLODNode : public NiSwitchNode
|
struct NiLODNode : public NiSwitchNode
|
||||||
|
@ -418,26 +209,7 @@ struct NiLODNode : public NiSwitchNode
|
||||||
};
|
};
|
||||||
std::vector<LODRange> lodLevels;
|
std::vector<LODRange> lodLevels;
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiFltAnimationNode : public NiSwitchNode
|
struct NiFltAnimationNode : public NiSwitchNode
|
||||||
|
@ -448,11 +220,7 @@ struct NiFltAnimationNode : public NiSwitchNode
|
||||||
Flag_Swing = 0x40
|
Flag_Swing = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
void read(NIFStream *nif) override
|
void read(NIFStream *nif) override;
|
||||||
{
|
|
||||||
NiSwitchNode::read(nif);
|
|
||||||
mDuration = nif->getFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool swing() const { return flags & Flag_Swing; }
|
bool swing() const { return flags & Flag_Swing; }
|
||||||
};
|
};
|
||||||
|
@ -478,18 +246,9 @@ struct NiSortAdjustNode : NiNode
|
||||||
|
|
||||||
int mMode;
|
int mMode;
|
||||||
NiAccumulatorPtr mSubSorter;
|
NiAccumulatorPtr mSubSorter;
|
||||||
void read(NIFStream *nif) override
|
|
||||||
{
|
void read(NIFStream *nif) override;
|
||||||
NiNode::read(nif);
|
void post(NIFFile *nif) override;
|
||||||
mMode = nif->getInt();
|
|
||||||
if (nif->getVersion() <= NIFStream::generateVersion(20,0,0,3))
|
|
||||||
mSubSorter.read(nif);
|
|
||||||
}
|
|
||||||
void post(NIFFile *nif) override
|
|
||||||
{
|
|
||||||
NiNode::post(nif);
|
|
||||||
mSubSorter.post(nif);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include "physics.hpp"
|
#include "physics.hpp"
|
||||||
|
|
||||||
|
#include "data.hpp"
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
|
@ -310,4 +312,4 @@ namespace Nif
|
||||||
mBodyFlags = nif->getUShort();
|
mBodyFlags = nif->getUShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -39,8 +39,11 @@
|
||||||
#include <osg/TexEnv>
|
#include <osg/TexEnv>
|
||||||
#include <osg/TexEnvCombine>
|
#include <osg/TexEnvCombine>
|
||||||
|
|
||||||
#include <components/nif/node.hpp>
|
#include <components/nif/controlled.hpp>
|
||||||
#include <components/nif/effect.hpp>
|
#include <components/nif/effect.hpp>
|
||||||
|
#include <components/nif/extra.hpp>
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
#include <components/nif/property.hpp>
|
||||||
#include <components/sceneutil/skeleton.hpp>
|
#include <components/sceneutil/skeleton.hpp>
|
||||||
#include <components/sceneutil/riggeometry.hpp>
|
#include <components/sceneutil/riggeometry.hpp>
|
||||||
#include <components/sceneutil/morphgeometry.hpp>
|
#include <components/sceneutil/morphgeometry.hpp>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <osgAnimation/BasicAnimationManager>
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
#include <osgAnimation/Channel>
|
#include <osgAnimation/Channel>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/nifosg/nifloader.hpp>
|
||||||
#include <components/sceneutil/keyframe.hpp>
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
#include <components/sceneutil/osgacontroller.hpp>
|
#include <components/sceneutil/osgacontroller.hpp>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "niffilemanager.hpp"
|
#include "niffilemanager.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <osg/Object>
|
#include <osg/Object>
|
||||||
#include <osg/Stats>
|
#include <osg/Stats>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue