diff --git a/components/nif/base.hpp b/components/nif/base.hpp index f67de02216..6e26f525e5 100644 --- a/components/nif/base.hpp +++ b/components/nif/base.hpp @@ -59,7 +59,7 @@ public: controller.post(nif); } }; -typedef Named NiSequenceStreamHelper; +using NiSequenceStreamHelper = Named; } // Namespace #endif diff --git a/components/nif/controlled.cpp b/components/nif/controlled.cpp index 9b7c9319bf..0b5c32a101 100644 --- a/components/nif/controlled.cpp +++ b/components/nif/controlled.cpp @@ -10,17 +10,18 @@ namespace Nif Named::read(nif); external = nif->getChar() != 0; - if(external) + bool internal = false; + if (external) filename = nif->getString(); else - { - nif->getChar(); // always 1 + internal = nif->getChar(); + + if (!external && internal) data.read(nif); - } - pixel = nif->getInt(); - mipmap = nif->getInt(); - alpha = nif->getInt(); + pixel = nif->getUInt(); + mipmap = nif->getUInt(); + alpha = nif->getUInt(); nif->getChar(); // always 1 } @@ -113,8 +114,4 @@ namespace Nif mCenter = nif->getVector3(); } - - - - } diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 00ff45eda9..8396eae04c 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -46,13 +46,13 @@ public: 3 - Compressed 4 - Bumpmap 5 - Default */ - int pixel; + unsigned int pixel; /* Mipmap format 0 - no 1 - yes 2 - default */ - int mipmap; + unsigned int mipmap; /* Alpha 0 - none @@ -60,7 +60,7 @@ public: 2 - smooth 3 - default (use material alpha, or multiply material with texture if present) */ - int alpha; + unsigned int alpha; void read(NIFStream *nif); void post(NIFFile *nif); diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 6de720b527..9a4c1b065b 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -92,6 +92,12 @@ namespace Nif void NiMaterialColorController::read(NIFStream *nif) { Controller::read(nif); + // Two bits that correspond to the controlled material color. + // 00: Ambient + // 01: Diffuse + // 10: Specular + // 11: Emissive + targetColor = (flags >> 4) & 3; data.read(nif); } @@ -189,7 +195,8 @@ namespace Nif { Controller::read(nif); data.read(nif); - nif->getChar(); // always 0 + if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) + /*bool alwaysActive = */nif->getChar(); // Always 0 } void NiGeomMorpherController::post(NIFFile *nif) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 2fe28fe1d6..364eff1cdc 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -78,12 +78,13 @@ public: void read(NIFStream *nif); void post(NIFFile *nif); }; -typedef NiParticleSystemController NiBSPArrayController; +using NiBSPArrayController = NiParticleSystemController; class NiMaterialColorController : public Controller { public: NiPosDataPtr data; + unsigned int targetColor; void read(NIFStream *nif); void post(NIFFile *nif); diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 828f5c368a..e46c0e84d9 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -225,7 +225,8 @@ void NiSkinData::read(NIFStream *nif) trafo.scale = nif->getFloat(); int boneNum = nif->getInt(); - nif->getInt(); // -1 + if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFFile::NIFVersion::VER_GAMEBRYO) + nif->skip(4); // NiSkinPartition link bones.resize(boneNum); for (BoneInfo &bi : bones) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index bced4d8e2a..87bafa6b19 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -143,7 +143,7 @@ void NIFFile::parse(Files::IStreamPtr stream) 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 != VER_4_0_0_0 && ver != VER_MW) + if(ver != nif.generateVersion(4,0,0,0) && ver != VER_MW) fail("Unsupported NIF version: " + printVersion(ver)); // Number of records size_t recNum = nif.getInt(); diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index a85e46ea5e..e63a7ce733 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -75,26 +75,16 @@ class NIFFile final : public File void operator = (NIFFile const &); public: + // For generic versions NIFStream::generateVersion() is used instead enum NIFVersion { - // Feature-relevant - VER_4_1_0_0 = 0x04010000, // 1-byte booleans (previously 4-byte) - VER_5_0_0_1 = 0x05000001, // Optimized record type listings - VER_5_0_0_6 = 0x05000006, // Record groups - VER_10_0_1_8 = 0x0A000108, // The last version without user version - VER_20_1_0_1 = 0x14010001, // String tables - VER_20_2_0_5 = 0x14020005, // Record sizes - // Game-relevant - VER_4_0_0_0 = 0x04000000, // Freedom Force NIFs, supported by Morrowind - VER_MW = 0x04000002, // 4.0.0.2. Morrowind and Freedom Force NIFs - VER_4_2_1_0 = 0x04020100, // Used in Civ4 and Dark Age of Camelot - VER_CI = 0x04020200, // 4.2.2.0. Main Culpa Innata NIF version, also used in Civ4 - VER_ZT2 = 0x0A000100, // 10.0.1.0. Main Zoo Tycoon 2 NIF version, also used in Oblivion and Civ4 - VER_OB_OLD = 0x0A000102, // 10.0.1.2. Main older Oblivion NIF version + VER_MW = 0x04000002, // 4.0.0.2. Main Morrowind NIF version. + VER_CI = 0x04020200, // 4.2.2.0. Main Culpa Innata NIF version, also used in Civ4. + VER_ZT2 = 0x0A000100, // 10.0.1.0. Main Zoo Tycoon 2 NIF version, also used in Oblivion and Civ4. + VER_OB_OLD = 0x0A000102, // 10.0.1.2. Main older Oblivion NIF version. VER_GAMEBRYO = 0x0A010000, // 10.1.0.0. Lots of games use it. The first version that has Gamebryo File Format header. - VER_10_2_0_0 = 0x0A020000, // Lots of games use this version as well. VER_CIV4 = 0x14000004, // 20.0.0.4. Main Civilization IV NIF version. - VER_OB = 0x14000005, // 20.0.0.5. Main Oblivion NIF version + VER_OB = 0x14000005, // 20.0.0.5. Main Oblivion NIF version. VER_BGS = 0x14020007 // 20.2.0.7. Main Fallout 3/4/76/New Vegas and Skyrim/SkyrimSE NIF version. }; enum BethVersion diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 7ecd660844..62e334e015 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -163,6 +163,12 @@ public: unsigned int getUserVersion(); unsigned int getBethVersion(); + // Convert human-readable version numbers into a number that can be compared. + uint32_t generateVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t rev) + { + return (major << 24) + (minor << 16) + (patch << 8) + rev; + } + ///Read in a string of the given length std::string getSizedString(size_t length) { diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 71a0a93cac..de4bfb22eb 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -284,7 +284,8 @@ struct NiLODNode : public NiSwitchNode void read(NIFStream *nif) { NiSwitchNode::read(nif); - lodCenter = nif->getVector3(); + if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFFile::NIFVersion::VER_ZT2) + lodCenter = nif->getVector3(); unsigned int numLodLevels = nif->getUInt(); for (unsigned int i=0; i(ctrl.getPtr()); if (matctrl->data.empty()) continue; - // Two bits that correspond to the controlled material color. - // 00: Ambient - // 01: Diffuse - // 10: Specular - // 11: Emissive - MaterialColorController::TargetColor targetColor = static_cast((matctrl->flags >> 4) & 3); + auto targetColor = static_cast(matctrl->targetColor); osg::ref_ptr osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor)); setupController(matctrl, osgctrl, animflags); composite->addController(osgctrl);