From e363d5df21664da160a5eebe23e4fca4bfce8a77 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 2 Feb 2020 17:08:17 +0300 Subject: [PATCH 1/2] Some more minor NIF support fixes --- components/nif/base.hpp | 2 +- components/nif/controlled.cpp | 21 +++++++++------------ components/nif/controlled.hpp | 6 +++--- components/nif/controller.cpp | 9 ++++++++- components/nif/controller.hpp | 3 ++- components/nif/data.cpp | 3 ++- components/nif/niffile.cpp | 2 +- components/nif/niffile.hpp | 22 ++++++---------------- components/nif/nifstream.hpp | 6 ++++++ components/nif/node.hpp | 3 ++- components/nifosg/nifloader.cpp | 7 +------ 11 files changed, 41 insertions(+), 43 deletions(-) diff --git a/components/nif/base.hpp b/components/nif/base.hpp index f67de0221..6e26f525e 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 9b7c9319b..0b5c32a10 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 - data.read(nif); - } + internal = nif->getChar(); - pixel = nif->getInt(); - mipmap = nif->getInt(); - alpha = nif->getInt(); + if (!external && internal) + data.read(nif); + + 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 00ff45eda..8396eae04 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 6de720b52..9a4c1b065 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 2fe28fe1d..364eff1cd 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 828f5c368..e46c0e84d 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 bced4d8e2..87bafa6b1 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 a85e46ea5..e63a7ce73 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 7ecd66084..62e334e01 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 71a0a93ca..de4bfb22e 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); From 0479311c25f421c9266c2d994e8a82ea65ecbcb9 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 2 Feb 2020 18:40:11 +0300 Subject: [PATCH 2/2] Correct declarations of utility methods --- components/nif/nifstream.cpp | 6 +++--- components/nif/nifstream.hpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 4ecb0e373..44be4b241 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -38,7 +38,7 @@ namespace Nif } // Convenience utility functions: get the versions of the currently read file - unsigned int NIFStream::getVersion() { return file->getVersion(); } - unsigned int NIFStream::getUserVersion() { return file->getBethVersion(); } - unsigned int NIFStream::getBethVersion() { return file->getBethVersion(); } + unsigned int NIFStream::getVersion() const { return file->getVersion(); } + unsigned int NIFStream::getUserVersion() const { return file->getBethVersion(); } + unsigned int NIFStream::getBethVersion() const { return file->getBethVersion(); } } diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 62e334e01..c78377448 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -159,12 +159,12 @@ public: std::string getString(); - unsigned int getVersion(); - unsigned int getUserVersion(); - unsigned int getBethVersion(); + unsigned int getVersion() const; + unsigned int getUserVersion() const; + unsigned int getBethVersion() const; // 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) + static constexpr uint32_t generateVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t rev) { return (major << 24) + (minor << 16) + (patch << 8) + rev; }