Allow loading arbitrary NIF files

pull/3030/head
Alexei Dobrohotov 4 years ago
parent f6b43b9321
commit 7e63afdecf

@ -1,9 +1,12 @@
#include "niffile.hpp"
#include "effect.hpp"
#include <array>
#include <map>
#include <sstream>
#include <components/settings/settings.hpp>
namespace Nif
{
@ -137,15 +140,46 @@ void NIFFile::parse(Files::IStreamPtr stream)
// Check the header string
std::string head = nif.getVersionString();
if(head.compare(0, 22, "NetImmerse File Format") != 0)
static const std::array<std::string, 2> verStrings =
{
"NetImmerse File Format",
"Gamebryo File Format"
};
bool supported = false;
for (const std::string& verString : verStrings)
{
supported = (head.compare(0, verString.size(), verString) == 0);
if (supported)
break;
}
if (!supported)
fail("Invalid NIF header: " + head);
supported = false;
// Get BCD version
ver = nif.getUInt();
// 4.0.0.0 is an older, practically identical version of the format.
// It's not used by Morrowind assets but Morrowind supports it.
if(ver != NIFStream::generateVersion(4,0,0,0) && ver != VER_MW)
fail("Unsupported NIF version: " + printVersion(ver));
static const std::array<uint32_t, 2> supportedVers =
{
NIFStream::generateVersion(4,0,0,0),
VER_MW
};
for (uint32_t supportedVer : supportedVers)
{
supported = (ver == supportedVer);
if (supported)
break;
}
if (!supported)
{
static const bool ignoreUnsupported = Settings::Manager::getBool("load unsupported nif files", "Models");
if (ignoreUnsupported)
warn("Unsupported NIF version: " + printVersion(ver) + ". Proceed with caution!");
else
fail("Unsupported NIF version: " + printVersion(ver));
}
// NIF data endianness
if (ver >= NIFStream::generateVersion(20,0,0,4))
@ -245,6 +279,9 @@ void NIFFile::parse(Files::IStreamPtr stream)
else
fail("Unknown record type " + rec);
if (!supported)
Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" << filename << ")";
assert(r != nullptr);
assert(r->recType != RC_MISSING);
r->recName = rec;

@ -58,3 +58,4 @@ The ranges included with each setting are the physically possible ranges, not re
windows
navigator
physics
models

@ -0,0 +1,27 @@
Models Settings
###############
load unsupported nif files
--------------------------
:Type: boolean
:Range: True/False
:Default: False
At the moment OpenMW's NIF loader is only tailored to load models
that can also load in Morrowind.
However, you can enable its limited and experimental support for updates in
the definitions of record types from later NIF revisions by toggling on
this setting.
You must keep in mind that loading unsupported NIF files may fail,
and the degree of this failure may vary. In milder cases, OpenMW will reject
the file anyway because it lacks a definition for a certain record type
that the file may use. In more severe cases OpenMW's
incomplete understanding of a record type can lead to memory corruption,
crashes or even freezes. Don't enable this if you're not sure that
you know what you're doing.
To help debug possible issues OpenMW will log its progress in loading
every file that uses an unsupported NIF version.

@ -945,3 +945,8 @@ lineofsight keep inactive cache = 0
# Defer bounding boxes update until collision detection.
defer aabb update = true
[Models]
# Attempt to load any valid NIF file regardless of its version and track the progress.
# Loading arbitrary meshes is not advised and may cause instability.
load unsupported nif files = false

Loading…
Cancel
Save