diff --git a/.clang-format b/.clang-format
index 2573430fb..6ed326e11 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,5 +1,5 @@
---
-IndentWidth: 4
+BasedOnStyle: LLVM
ColumnLimit: 120
UseTab: Never
---
@@ -8,7 +8,6 @@ DerivePointerAlignment: false
PointerAlignment: Left
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
-BreakBeforeBraces: Allman
IndentCaseLabels: false
AllowShortBlocksOnASingleLine: true
AlignOperands: true
@@ -24,6 +23,6 @@ NamespaceIndentation: None
BinPackArguments: true
BinPackParameters: true
SortIncludes: false
-AccessModifierOffset: -4
+AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 7743f54aa..e288eb80f 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -10,7 +10,6 @@
-
diff --git a/DataSpec/AssetNameMap.cpp b/DataSpec/AssetNameMap.cpp
index 1a22d08e0..0fc2c0dc7 100644
--- a/DataSpec/AssetNameMap.cpp
+++ b/DataSpec/AssetNameMap.cpp
@@ -6,79 +6,70 @@ extern "C" const size_t ASSET_NAME_MP32_SZ;
extern "C" const uint8_t ASSET_NAME_MP64[];
extern "C" const size_t ASSET_NAME_MP64_SZ;
-namespace DataSpec::AssetNameMap
-{
+namespace DataSpec::AssetNameMap {
logvisor::Module Log("AssetNameMap");
-struct SAsset
-{
- std::string name;
- std::string directory;
- hecl::FourCC type;
- SAsset() = default;
- SAsset(const hecl::FourCC& typeIn, athena::io::IStreamReader& in)
- : type(typeIn)
- {
- uint32_t nameLen = in.readUint32Big();
- name = in.readString(nameLen);
- uint32_t dirLen = in.readUint32Big();
- directory = in.readString(dirLen);
- }
+struct SAsset {
+ std::string name;
+ std::string directory;
+ hecl::FourCC type;
+ SAsset() = default;
+ SAsset(const hecl::FourCC& typeIn, athena::io::IStreamReader& in) : type(typeIn) {
+ uint32_t nameLen = in.readUint32Big();
+ name = in.readString(nameLen);
+ uint32_t dirLen = in.readUint32Big();
+ directory = in.readString(dirLen);
+ }
};
static std::unordered_map g_AssetNameMap;
static bool g_AssetNameMapInit = false;
-void LoadAssetMap(athena::io::MemoryReader& ar)
-{
- if (!ar.hasError())
- {
- hecl::FourCC magic;
- if (ar.length() >= 4)
- ar.readBytesToBuf(&magic, 4);
- if (magic != FOURCC('AIDM'))
- Log.report(logvisor::Warning, _SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files."));
- else
- {
- uint32_t assetCount = ar.readUint32Big();
- g_AssetNameMap.reserve(assetCount);
- for (uint32_t i = 0 ; i= 4)
+ ar.readBytesToBuf(&magic, 4);
+ if (magic != FOURCC('AIDM'))
+ Log.report(logvisor::Warning,
+ _SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files."));
+ else {
+ uint32_t assetCount = ar.readUint32Big();
+ g_AssetNameMap.reserve(assetCount);
+ for (uint32_t i = 0; i < assetCount; ++i) {
+ hecl::FourCC type;
+ ar.readBytesToBuf(&type, 4);
+ uint64_t id = ar.readUint64Big();
+ g_AssetNameMap[id] = SAsset(type, ar);
+ }
}
+ }
}
-void InitAssetNameMap()
-{
- if (g_AssetNameMapInit)
- return;
+void InitAssetNameMap() {
+ if (g_AssetNameMapInit)
+ return;
- Log.report(logvisor::Info, "Initializing asset name database...");
+ Log.report(logvisor::Info, "Initializing asset name database...");
- /* First load the 32bit map for MP1/2 */
- {
- athena::io::MemoryReader ar(ASSET_NAME_MP32, ASSET_NAME_MP32_SZ);
- LoadAssetMap(ar);
- }
- /* Now load the 64bit map for MP3 */
- {
- athena::io::MemoryReader ar(ASSET_NAME_MP64, ASSET_NAME_MP64_SZ);
- LoadAssetMap(ar);
- }
- g_AssetNameMapInit = true;
+ /* First load the 32bit map for MP1/2 */
+ {
+ athena::io::MemoryReader ar(ASSET_NAME_MP32, ASSET_NAME_MP32_SZ);
+ LoadAssetMap(ar);
+ }
+ /* Now load the 64bit map for MP3 */
+ {
+ athena::io::MemoryReader ar(ASSET_NAME_MP64, ASSET_NAME_MP64_SZ);
+ LoadAssetMap(ar);
+ }
+ g_AssetNameMapInit = true;
}
-const std::string* TranslateIdToName(const UniqueID32& id)
-{
- if (g_AssetNameMap.find(id.toUint64()) == g_AssetNameMap.end())
- return nullptr;
+const std::string* TranslateIdToName(const UniqueID32& id) {
+ if (g_AssetNameMap.find(id.toUint64()) == g_AssetNameMap.end())
+ return nullptr;
- return &g_AssetNameMap[id.toUint64()].name;
+ return &g_AssetNameMap[id.toUint64()].name;
}
-}
+} // namespace DataSpec::AssetNameMap
diff --git a/DataSpec/AssetNameMap.hpp b/DataSpec/AssetNameMap.hpp
index e73bcdc46..fb3e5c49c 100644
--- a/DataSpec/AssetNameMap.hpp
+++ b/DataSpec/AssetNameMap.hpp
@@ -4,9 +4,8 @@
#include
#include "DNACommon/DNACommon.hpp"
-namespace DataSpec::AssetNameMap
-{
+namespace DataSpec::AssetNameMap {
void InitAssetNameMap();
const std::string* TranslateIdToName(const UniqueID32&);
const std::string* TranslateIdToName(const UniqueID64&);
-}
+} // namespace DataSpec::AssetNameMap
diff --git a/DataSpec/Blender/BlenderSupport.cpp b/DataSpec/Blender/BlenderSupport.cpp
index 276ef7315..032638071 100644
--- a/DataSpec/Blender/BlenderSupport.cpp
+++ b/DataSpec/Blender/BlenderSupport.cpp
@@ -5,20 +5,18 @@
extern "C" uint8_t RETRO_MASTER_SHADER[];
extern "C" size_t RETRO_MASTER_SHADER_SZ;
-namespace DataSpec::Blender
-{
+namespace DataSpec::Blender {
-bool BuildMasterShader(const hecl::ProjectPath& path)
-{
- hecl::blender::Connection& conn = hecl::blender::Connection::SharedConnection();
- if (!conn.createBlend(path, hecl::blender::BlendType::None))
- return false;
- {
- hecl::blender::PyOutStream os = conn.beginPythonOut(true);
- os << RETRO_MASTER_SHADER;
- os << "make_master_shader_library()\n";
- }
- return conn.saveBlend();
+bool BuildMasterShader(const hecl::ProjectPath& path) {
+ hecl::blender::Connection& conn = hecl::blender::Connection::SharedConnection();
+ if (!conn.createBlend(path, hecl::blender::BlendType::None))
+ return false;
+ {
+ hecl::blender::PyOutStream os = conn.beginPythonOut(true);
+ os << RETRO_MASTER_SHADER;
+ os << "make_master_shader_library()\n";
+ }
+ return conn.saveBlend();
}
-}
+} // namespace DataSpec::Blender
diff --git a/DataSpec/Blender/BlenderSupport.hpp b/DataSpec/Blender/BlenderSupport.hpp
index 8a52bc0e4..8a5cd7eca 100644
--- a/DataSpec/Blender/BlenderSupport.hpp
+++ b/DataSpec/Blender/BlenderSupport.hpp
@@ -2,10 +2,8 @@
#include
-namespace DataSpec::Blender
-{
+namespace DataSpec::Blender {
bool BuildMasterShader(const hecl::ProjectPath& path);
}
-
diff --git a/DataSpec/DNACommon/ANCS.cpp b/DataSpec/DNACommon/ANCS.cpp
index 5981c402b..0b1ed8e7d 100644
--- a/DataSpec/DNACommon/ANCS.cpp
+++ b/DataSpec/DNACommon/ANCS.cpp
@@ -7,302 +7,259 @@
#include "DataSpec/DNAMP3/CHAR.hpp"
#include "hecl/Blender/Connection.hpp"
-namespace DataSpec::DNAANCS
-{
+namespace DataSpec::DNAANCS {
template
-bool ReadANCSToBlender(hecl::blender::Connection& conn,
- const ANCSDNA& ancs,
- const hecl::ProjectPath& outPath,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- std::function fileChanged,
- bool force)
-{
- /* Extract character CMDL/CSKR first */
- std::vector> chResInfo;
- ancs.getCharacterResInfo(chResInfo);
- for (const auto& info : chResInfo)
- {
- const nod::Node* node;
- const typename PAKRouter::EntryType* cmdlE =
- pakRouter.lookupEntry(info.cmdl, &node, true, false);
- if (cmdlE)
- {
- hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
- if (force || cmdlPath.isNone())
- {
- cmdlPath.makeDirChain(false);
- if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
- return false;
+bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
+ PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
+ std::function fileChanged, bool force) {
+ /* Extract character CMDL/CSKR first */
+ std::vector> chResInfo;
+ ancs.getCharacterResInfo(chResInfo);
+ for (const auto& info : chResInfo) {
+ const nod::Node* node;
+ const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, false);
+ if (cmdlE) {
+ hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
+ if (force || cmdlPath.isNone()) {
+ cmdlPath.makeDirChain(false);
+ if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
+ return false;
- std::string bestName = pakRouter.getBestEntryName(*cmdlE);
- hecl::SystemStringConv bestNameView(bestName);
- fileChanged(bestNameView.c_str());
+ std::string bestName = pakRouter.getBestEntryName(*cmdlE);
+ hecl::SystemStringConv bestNameView(bestName);
+ fileChanged(bestNameView.c_str());
- typename ANCSDNA::CSKRType cskr;
- pakRouter.lookupAndReadDNA(info.cskr, cskr);
- typename ANCSDNA::CINFType cinf;
- pakRouter.lookupAndReadDNA(info.cinf, cinf);
- using RigPair = std::pair;
- RigPair rigPair(&cskr, &cinf);
+ typename ANCSDNA::CSKRType cskr;
+ pakRouter.lookupAndReadDNA(info.cskr, cskr);
+ typename ANCSDNA::CINFType cinf;
+ pakRouter.lookupAndReadDNA(info.cinf, cinf);
+ using RigPair = std::pair;
+ RigPair rigPair(&cskr, &cinf);
- PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
- DNACMDL::ReadCMDLToBlender
- (conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
+ PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
+ DNACMDL::ReadCMDLToBlender(
+ conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
- conn.saveBlend();
- }
+ conn.saveBlend();
+ }
+ }
+ }
+
+ /* Extract attachment CMDL/CSKRs first */
+ auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
+ for (auto it = attRange.first; it != attRange.second; ++it) {
+ auto cmdlid = it->second.first.second;
+
+ const nod::Node* node;
+ const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, &node, true, false);
+ if (cmdlE) {
+ hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
+ if (force || cmdlPath.isNone()) {
+ cmdlPath.makeDirChain(false);
+ if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
+ return false;
+
+ std::string bestName = pakRouter.getBestEntryName(*cmdlE);
+ hecl::SystemStringConv bestNameView(bestName);
+ fileChanged(bestNameView.c_str());
+
+ const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid);
+ typename ANCSDNA::CSKRType cskr;
+ pakRouter.lookupAndReadDNA(rp->first, cskr);
+ typename ANCSDNA::CINFType cinf;
+ pakRouter.lookupAndReadDNA(rp->second, cinf);
+ using RigPair = std::pair;
+ RigPair rigPair(&cskr, &cinf);
+
+ PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
+ DNACMDL::ReadCMDLToBlender(
+ conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
+
+ conn.saveBlend();
+ }
+ }
+ }
+
+ std::string bestName = pakRouter.getBestEntryName(entry);
+ hecl::SystemStringConv bestNameView(bestName);
+ fileChanged(bestNameView.c_str());
+
+ /* Establish ANCS blend */
+ if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor))
+ return false;
+
+ std::string firstName;
+ typename ANCSDNA::CINFType firstCinf;
+ {
+ hecl::blender::PyOutStream os = conn.beginPythonOut(true);
+
+ os.format(
+ "import bpy\n"
+ "from mathutils import Vector\n"
+ "bpy.context.scene.name = '%s'\n"
+ "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
+ "\n"
+ "# Using 'Blender Game'\n"
+ "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
+ "\n"
+ "# Clear Scene\n"
+ "for ob in bpy.data.objects:\n"
+ " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
+ " bpy.context.scene.objects.unlink(ob)\n"
+ " bpy.data.objects.remove(ob)\n"
+ "\n"
+ "actor_data = bpy.context.scene.hecl_sact_data\n"
+ "arm_obj = None\n",
+ pakRouter.getBestEntryName(entry).c_str());
+
+ std::unordered_set cinfsDone;
+ for (const auto& info : chResInfo) {
+ /* Provide data to add-on */
+ os.format(
+ "actor_subtype = actor_data.subtypes.add()\n"
+ "actor_subtype.name = '%s'\n\n",
+ info.name.c_str());
+
+ /* Build CINF if needed */
+ if (cinfsDone.find(info.cinf) == cinfsDone.end()) {
+ typename ANCSDNA::CINFType cinf;
+ pakRouter.lookupAndReadDNA(info.cinf, cinf);
+ cinf.sendCINFToBlender(os, info.cinf);
+ if (cinfsDone.empty()) {
+ firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf);
+ firstCinf = cinf;
}
+ cinfsDone.insert(info.cinf);
+ } else
+ os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
+ os << "actor_subtype.linked_armature = arm_obj.name\n";
+
+ /* Link CMDL */
+ const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, false);
+ if (cmdlE) {
+ hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
+ os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);
+
+ /* Attach CMDL to CINF */
+ os << "if obj.name not in bpy.context.scene.objects:\n"
+ " bpy.context.scene.objects.link(obj)\n"
+ "obj.parent = arm_obj\n"
+ "obj.parent_type = 'ARMATURE'\n"
+ "actor_subtype.linked_mesh = obj.name\n\n";
+ }
+
+ /* Link overlays */
+ for (const auto& overlay : info.overlays) {
+ os << "overlay = actor_subtype.overlays.add()\n";
+ os.format("overlay.name = '%s'\n", overlay.first.c_str());
+
+ /* Link CMDL */
+ const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, false);
+ if (cmdlE) {
+ hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
+ os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);
+
+ /* Attach CMDL to CINF */
+ os << "if obj.name not in bpy.context.scene.objects:\n"
+ " bpy.context.scene.objects.link(obj)\n"
+ "obj.parent = arm_obj\n"
+ "obj.parent_type = 'ARMATURE'\n"
+ "overlay.linked_mesh = obj.name\n\n";
+ }
+ }
}
- /* Extract attachment CMDL/CSKRs first */
- auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
- for (auto it = attRange.first; it != attRange.second; ++it)
- {
- auto cmdlid = it->second.first.second;
+ /* Link attachments */
+ for (auto it = attRange.first; it != attRange.second; ++it) {
+ os << "attachment = actor_data.attachments.add()\n";
+ os.format("attachment.name = '%s'\n", it->second.second.c_str());
- const nod::Node* node;
- const typename PAKRouter::EntryType* cmdlE =
- pakRouter.lookupEntry(cmdlid, &node, true, false);
- if (cmdlE)
- {
- hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
- if (force || cmdlPath.isNone())
- {
- cmdlPath.makeDirChain(false);
- if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
- return false;
+ auto cinfid = it->second.first.first;
+ auto cmdlid = it->second.first.second;
- std::string bestName = pakRouter.getBestEntryName(*cmdlE);
- hecl::SystemStringConv bestNameView(bestName);
- fileChanged(bestNameView.c_str());
+ if (cinfid) {
+ /* Build CINF if needed */
+ if (cinfsDone.find(cinfid) == cinfsDone.end()) {
+ typename ANCSDNA::CINFType cinf;
+ pakRouter.lookupAndReadDNA(cinfid, cinf);
+ cinf.sendCINFToBlender(os, cinfid);
+ if (cinfsDone.empty()) {
+ firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid);
+ firstCinf = cinf;
+ }
+ cinfsDone.insert(cinfid);
+ } else
+ os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str());
+ os << "attachment.linked_armature = arm_obj.name\n";
+ }
- const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid);
- typename ANCSDNA::CSKRType cskr;
- pakRouter.lookupAndReadDNA(rp->first, cskr);
- typename ANCSDNA::CINFType cinf;
- pakRouter.lookupAndReadDNA(rp->second, cinf);
- using RigPair = std::pair;
- RigPair rigPair(&cskr, &cinf);
+ /* Link CMDL */
+ const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, nullptr, true, false);
+ if (cmdlE) {
+ hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
+ os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);
- PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
- DNACMDL::ReadCMDLToBlender
- (conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
-
- conn.saveBlend();
- }
- }
+ /* Attach CMDL to CINF */
+ os << "if obj.name not in bpy.context.scene.objects:\n"
+ " bpy.context.scene.objects.link(obj)\n"
+ "obj.parent = arm_obj\n"
+ "obj.parent_type = 'ARMATURE'\n"
+ "attachment.linked_mesh = obj.name\n\n";
+ }
}
+ }
- std::string bestName = pakRouter.getBestEntryName(entry);
- hecl::SystemStringConv bestNameView(bestName);
- fileChanged(bestNameView.c_str());
+ {
+ hecl::blender::DataStream ds = conn.beginData();
+ std::unordered_map matrices = ds.getBoneMatrices(firstName);
+ ds.close();
+ DNAANIM::RigInverter inverter(firstCinf, matrices);
- /* Establish ANCS blend */
- if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor))
- return false;
+ hecl::blender::PyOutStream os = conn.beginPythonOut(true);
+ os << "import bpy\n"
+ "actor_data = bpy.context.scene.hecl_sact_data\n";
- std::string firstName;
- typename ANCSDNA::CINFType firstCinf;
- {
- hecl::blender::PyOutStream os = conn.beginPythonOut(true);
+ /* Get animation primitives */
+ std::map> animResInfo;
+ ancs.getAnimationResInfo(&pakRouter, animResInfo);
+ for (const auto& id : animResInfo) {
+ typename ANCSDNA::ANIMType anim;
+ if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) {
+ os.format(
+ "act = bpy.data.actions.new('%s')\n"
+ "act.use_fake_user = True\n",
+ id.second.name.c_str());
+ anim.sendANIMToBlender(os, inverter, id.second.additive);
+ }
- os.format("import bpy\n"
- "from mathutils import Vector\n"
- "bpy.context.scene.name = '%s'\n"
- "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
- "\n"
- "# Using 'Blender Game'\n"
- "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
- "\n"
- "# Clear Scene\n"
- "for ob in bpy.data.objects:\n"
- " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
- " bpy.context.scene.objects.unlink(ob)\n"
- " bpy.data.objects.remove(ob)\n"
- "\n"
- "actor_data = bpy.context.scene.hecl_sact_data\n"
- "arm_obj = None\n",
- pakRouter.getBestEntryName(entry).c_str());
+ os.format(
+ "actor_action = actor_data.actions.add()\n"
+ "actor_action.name = '%s'\n",
+ id.second.name.c_str());
- std::unordered_set cinfsDone;
- for (const auto& info : chResInfo)
- {
- /* Provide data to add-on */
- os.format("actor_subtype = actor_data.subtypes.add()\n"
- "actor_subtype.name = '%s'\n\n",
- info.name.c_str());
-
- /* Build CINF if needed */
- if (cinfsDone.find(info.cinf) == cinfsDone.end())
- {
- typename ANCSDNA::CINFType cinf;
- pakRouter.lookupAndReadDNA(info.cinf, cinf);
- cinf.sendCINFToBlender(os, info.cinf);
- if (cinfsDone.empty())
- {
- firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf);
- firstCinf = cinf;
- }
- cinfsDone.insert(info.cinf);
- }
- else
- os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
- os << "actor_subtype.linked_armature = arm_obj.name\n";
-
- /* Link CMDL */
- const typename PAKRouter::EntryType* cmdlE =
- pakRouter.lookupEntry(info.cmdl, nullptr, true, false);
- if (cmdlE)
- {
- hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
- os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(),
- pakRouter.getBestEntryName(*cmdlE).data(), true);
-
- /* Attach CMDL to CINF */
- os << "if obj.name not in bpy.context.scene.objects:\n"
- " bpy.context.scene.objects.link(obj)\n"
- "obj.parent = arm_obj\n"
- "obj.parent_type = 'ARMATURE'\n"
- "actor_subtype.linked_mesh = obj.name\n\n";
- }
-
- /* Link overlays */
- for (const auto& overlay : info.overlays)
- {
- os << "overlay = actor_subtype.overlays.add()\n";
- os.format("overlay.name = '%s'\n", overlay.first.c_str());
-
- /* Link CMDL */
- const typename PAKRouter::EntryType* cmdlE =
- pakRouter.lookupEntry(overlay.second.first, nullptr, true, false);
- if (cmdlE)
- {
- hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
- os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(),
- pakRouter.getBestEntryName(*cmdlE).data(), true);
-
- /* Attach CMDL to CINF */
- os << "if obj.name not in bpy.context.scene.objects:\n"
- " bpy.context.scene.objects.link(obj)\n"
- "obj.parent = arm_obj\n"
- "obj.parent_type = 'ARMATURE'\n"
- "overlay.linked_mesh = obj.name\n\n";
- }
- }
- }
-
- /* Link attachments */
- for (auto it = attRange.first; it != attRange.second; ++it)
- {
- os << "attachment = actor_data.attachments.add()\n";
- os.format("attachment.name = '%s'\n", it->second.second.c_str());
-
- auto cinfid = it->second.first.first;
- auto cmdlid = it->second.first.second;
-
- if (cinfid)
- {
- /* Build CINF if needed */
- if (cinfsDone.find(cinfid) == cinfsDone.end())
- {
- typename ANCSDNA::CINFType cinf;
- pakRouter.lookupAndReadDNA(cinfid, cinf);
- cinf.sendCINFToBlender(os, cinfid);
- if (cinfsDone.empty())
- {
- firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid);
- firstCinf = cinf;
- }
- cinfsDone.insert(cinfid);
- }
- else
- os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str());
- os << "attachment.linked_armature = arm_obj.name\n";
- }
-
- /* Link CMDL */
- const typename PAKRouter::EntryType* cmdlE =
- pakRouter.lookupEntry(cmdlid, nullptr, true, false);
- if (cmdlE)
- {
- hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
- os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(),
- pakRouter.getBestEntryName(*cmdlE).data(), true);
-
- /* Attach CMDL to CINF */
- os << "if obj.name not in bpy.context.scene.objects:\n"
- " bpy.context.scene.objects.link(obj)\n"
- "obj.parent = arm_obj\n"
- "obj.parent_type = 'ARMATURE'\n"
- "attachment.linked_mesh = obj.name\n\n";
- }
- }
+ /* Extract EVNT if present */
+ anim.extractEVNT(id.second, outPath, pakRouter, force);
}
-
- {
- hecl::blender::DataStream ds = conn.beginData();
- std::unordered_map matrices = ds.getBoneMatrices(firstName);
- ds.close();
- DNAANIM::RigInverter inverter(firstCinf, matrices);
-
- hecl::blender::PyOutStream os = conn.beginPythonOut(true);
- os << "import bpy\n"
- "actor_data = bpy.context.scene.hecl_sact_data\n";
-
- /* Get animation primitives */
- std::map> animResInfo;
- ancs.getAnimationResInfo(&pakRouter, animResInfo);
- for (const auto& id : animResInfo)
- {
- typename ANCSDNA::ANIMType anim;
- if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true))
- {
- os.format("act = bpy.data.actions.new('%s')\n"
- "act.use_fake_user = True\n", id.second.name.c_str());
- anim.sendANIMToBlender(os, inverter, id.second.additive);
- }
-
- os.format("actor_action = actor_data.actions.add()\n"
- "actor_action.name = '%s'\n", id.second.name.c_str());
-
- /* Extract EVNT if present */
- anim.extractEVNT(id.second, outPath, pakRouter, force);
- }
- }
- conn.saveBlend();
- return true;
+ }
+ conn.saveBlend();
+ return true;
}
-template bool ReadANCSToBlender, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>
- (hecl::blender::Connection& conn,
- const DNAMP1::ANCS& ancs,
- const hecl::ProjectPath& outPath,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- std::function fileChanged,
- bool force);
-template bool ReadANCSToBlender, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>
- (hecl::blender::Connection& conn,
- const DNAMP2::ANCS& ancs,
- const hecl::ProjectPath& outPath,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- std::function fileChanged,
- bool force);
-template bool ReadANCSToBlender, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>
- (hecl::blender::Connection& conn,
- const DNAMP3::CHAR& ancs,
- const hecl::ProjectPath& outPath,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- std::function fileChanged,
- bool force);
+template bool
+ReadANCSToBlender, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>(
+ hecl::blender::Connection& conn, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath,
+ PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry,
+ const SpecBase& dataspec, std::function fileChanged, bool force);
+template bool
+ReadANCSToBlender, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>(
+ hecl::blender::Connection& conn, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath,
+ PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry,
+ const SpecBase& dataspec, std::function fileChanged, bool force);
+template bool
+ReadANCSToBlender, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>(
+ hecl::blender::Connection& conn, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath,
+ PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry,
+ const SpecBase& dataspec, std::function fileChanged, bool force);
-}
+} // namespace DataSpec::DNAANCS
diff --git a/DataSpec/DNACommon/ANCS.hpp b/DataSpec/DNACommon/ANCS.hpp
index 52ec8bbfa..8ad77a9cb 100644
--- a/DataSpec/DNACommon/ANCS.hpp
+++ b/DataSpec/DNACommon/ANCS.hpp
@@ -5,41 +5,32 @@
#include "CMDL.hpp"
#include "RigInverter.hpp"
-namespace DataSpec::DNAANCS
-{
+namespace DataSpec::DNAANCS {
using Actor = hecl::blender::Actor;
using Armature = hecl::blender::Armature;
using Action = hecl::blender::Action;
template
-struct CharacterResInfo
-{
- std::string name;
- IDTYPE cmdl;
- IDTYPE cskr;
- IDTYPE cinf;
- std::vector>> overlays;
+struct CharacterResInfo {
+ std::string name;
+ IDTYPE cmdl;
+ IDTYPE cskr;
+ IDTYPE cinf;
+ std::vector>> overlays;
};
template
-struct AnimationResInfo
-{
- std::string name;
- IDTYPE animId;
- IDTYPE evntId;
- bool additive;
+struct AnimationResInfo {
+ std::string name;
+ IDTYPE animId;
+ IDTYPE evntId;
+ bool additive;
};
template
-bool ReadANCSToBlender(hecl::blender::Connection& conn,
- const ANCSDNA& ancs,
- const hecl::ProjectPath& outPath,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- std::function fileChanged,
- bool force=false);
-
-}
+bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
+ PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
+ std::function fileChanged, bool force = false);
+} // namespace DataSpec::DNAANCS
diff --git a/DataSpec/DNACommon/ANIM.cpp b/DataSpec/DNACommon/ANIM.cpp
index 64888baa8..0f9177734 100644
--- a/DataSpec/DNACommon/ANIM.cpp
+++ b/DataSpec/DNACommon/ANIM.cpp
@@ -3,529 +3,439 @@
#define DUMP_KEYS 0
-namespace DataSpec::DNAANIM
-{
+namespace DataSpec::DNAANIM {
-size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& channels)
-{
- size_t bitsPerKeyFrame = 0;
- for (const Channel& chan : channels)
- {
- switch (chan.type)
- {
- case Channel::Type::Rotation:
- bitsPerKeyFrame += 1;
- case Channel::Type::Translation:
- case Channel::Type::Scale:
- bitsPerKeyFrame += chan.q[0];
- bitsPerKeyFrame += chan.q[1];
- bitsPerKeyFrame += chan.q[2];
- break;
- case Channel::Type::KfHead:
- bitsPerKeyFrame += 1;
- break;
- case Channel::Type::RotationMP3:
- bitsPerKeyFrame += chan.q[0];
- bitsPerKeyFrame += chan.q[1];
- bitsPerKeyFrame += chan.q[2];
- bitsPerKeyFrame += chan.q[3];
- break;
- default: break;
- }
+size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& channels) {
+ size_t bitsPerKeyFrame = 0;
+ for (const Channel& chan : channels) {
+ switch (chan.type) {
+ case Channel::Type::Rotation:
+ bitsPerKeyFrame += 1;
+ case Channel::Type::Translation:
+ case Channel::Type::Scale:
+ bitsPerKeyFrame += chan.q[0];
+ bitsPerKeyFrame += chan.q[1];
+ bitsPerKeyFrame += chan.q[2];
+ break;
+ case Channel::Type::KfHead:
+ bitsPerKeyFrame += 1;
+ break;
+ case Channel::Type::RotationMP3:
+ bitsPerKeyFrame += chan.q[0];
+ bitsPerKeyFrame += chan.q[1];
+ bitsPerKeyFrame += chan.q[2];
+ bitsPerKeyFrame += chan.q[3];
+ break;
+ default:
+ break;
}
- return (bitsPerKeyFrame * keyFrameCount + 31) / 32 * 4;
+ }
+ return (bitsPerKeyFrame * keyFrameCount + 31) / 32 * 4;
}
-static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
-{
- float q = M_PIF / 2.0f / float(div);
- zeus::simd_floats f(quat.simd);
- return
- {
- {
- atInt32(std::asin(f[1]) / q),
- atInt32(std::asin(f[2]) / q),
- atInt32(std::asin(f[3]) / q),
- },
- (f[0] < 0.f)
- };
+static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div) {
+ float q = M_PIF / 2.0f / float(div);
+ zeus::simd_floats f(quat.simd);
+ return {{
+ atInt32(std::asin(f[1]) / q),
+ atInt32(std::asin(f[2]) / q),
+ atInt32(std::asin(f[3]) / q),
+ },
+ (f[0] < 0.f)};
}
-static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
-{
- float q = M_PIF / 2.0f / float(div);
- athena::simd_floats f = {
- 0.0f,
- std::sin(v.v[0] * q),
- std::sin(v.v[1] * q),
- std::sin(v.v[2] * q),
- };
- f[0] = std::sqrt(std::max((1.0f -
- (f[1] * f[1] +
- f[2] * f[2] +
- f[3] * f[3])), 0.0f));
- f[0] = v.w ? -f[0] : f[0];
- Value retval;
- retval.simd.copy_from(f);
- return retval;
+static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) {
+ float q = M_PIF / 2.0f / float(div);
+ athena::simd_floats f = {
+ 0.0f,
+ std::sin(v.v[0] * q),
+ std::sin(v.v[1] * q),
+ std::sin(v.v[2] * q),
+ };
+ f[0] = std::sqrt(std::max((1.0f - (f[1] * f[1] + f[2] * f[2] + f[3] * f[3])), 0.0f));
+ f[0] = v.w ? -f[0] : f[0];
+ Value retval;
+ retval.simd.copy_from(f);
+ return retval;
}
-static inline Value DequantizeRotation_3(const QuantizedRot& v, atUint32 div)
-{
- float q = 1.0f / float(div);
- athena::simd_floats f = {
- 0.0f,
- v.v[0] * q,
- v.v[1] * q,
- v.v[2] * q,
- };
- f[0] = std::sqrt(std::max((1.0f -
- (f[1] * f[1] +
- f[2] * f[2] +
- f[3] * f[3])), 0.0f));
- f[0] = v.w ? -f[0] : f[0];
- Value retval;
- retval.simd.copy_from(f);
- return retval;
+static inline Value DequantizeRotation_3(const QuantizedRot& v, atUint32 div) {
+ float q = 1.0f / float(div);
+ athena::simd_floats f = {
+ 0.0f,
+ v.v[0] * q,
+ v.v[1] * q,
+ v.v[2] * q,
+ };
+ f[0] = std::sqrt(std::max((1.0f - (f[1] * f[1] + f[2] * f[2] + f[3] * f[3])), 0.0f));
+ f[0] = v.w ? -f[0] : f[0];
+ Value retval;
+ retval.simd.copy_from(f);
+ return retval;
}
-bool BitstreamReader::dequantizeBit(const atUint8* data)
-{
- atUint32 byteCur = (m_bitCur / 32) * 4;
- atUint32 bitRem = m_bitCur % 32;
+bool BitstreamReader::dequantizeBit(const atUint8* data) {
+ atUint32 byteCur = (m_bitCur / 32) * 4;
+ atUint32 bitRem = m_bitCur % 32;
- /* Fill 32 bit buffer with region containing bits */
- /* Make them least significant */
- atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem;
+ /* Fill 32 bit buffer with region containing bits */
+ /* Make them least significant */
+ atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem;
- /* That's it */
- m_bitCur += 1;
- return tempBuf & 0x1;
+ /* That's it */
+ m_bitCur += 1;
+ return tempBuf & 0x1;
}
-atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q)
-{
- atUint32 byteCur = (m_bitCur / 32) * 4;
- atUint32 bitRem = m_bitCur % 32;
+atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q) {
+ atUint32 byteCur = (m_bitCur / 32) * 4;
+ atUint32 bitRem = m_bitCur % 32;
- /* Fill 32 bit buffer with region containing bits */
- /* Make them least significant */
- atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem;
+ /* Fill 32 bit buffer with region containing bits */
+ /* Make them least significant */
+ atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem;
- /* If this shift underflows the value, buffer the next 32 bits */
- /* And tack onto shifted buffer */
- if ((bitRem + q) > 32)
- {
- atUint32 tempBuf2 = hecl::SBig(*reinterpret_cast(data + byteCur + 4));
- tempBuf |= (tempBuf2 << (32 - bitRem));
+ /* If this shift underflows the value, buffer the next 32 bits */
+ /* And tack onto shifted buffer */
+ if ((bitRem + q) > 32) {
+ atUint32 tempBuf2 = hecl::SBig(*reinterpret_cast(data + byteCur + 4));
+ tempBuf |= (tempBuf2 << (32 - bitRem));
+ }
+
+ /* Mask it */
+ atUint32 mask = (1 << q) - 1;
+ tempBuf &= mask;
+
+ /* Sign extend */
+ atUint32 sign = (tempBuf >> (q - 1)) & 0x1;
+ if (sign)
+ tempBuf |= ~0u << q;
+
+ /* Return delta value */
+ m_bitCur += q;
+ return atInt32(tempBuf);
+}
+
+std::vector> BitstreamReader::read(const atUint8* data, size_t keyFrameCount,
+ const std::vector& channels, atUint32 rotDiv,
+ float transMult, float scaleMult) {
+ m_bitCur = 0;
+ std::vector> chanKeys;
+ std::vector chanAccum;
+ chanKeys.reserve(channels.size());
+ chanAccum.reserve(channels.size());
+ for (const Channel& chan : channels) {
+ chanAccum.push_back(chan.i);
+
+ chanKeys.emplace_back();
+ std::vector& keys = chanKeys.back();
+ keys.reserve(keyFrameCount);
+ switch (chan.type) {
+ case Channel::Type::Rotation: {
+ QuantizedRot qr = {{chan.i[0], chan.i[1], chan.i[2]}, false};
+ keys.emplace_back(DequantizeRotation(qr, rotDiv));
+ break;
}
-
- /* Mask it */
- atUint32 mask = (1 << q) - 1;
- tempBuf &= mask;
-
- /* Sign extend */
- atUint32 sign = (tempBuf >> (q - 1)) & 0x1;
- if (sign)
- tempBuf |= ~0u << q;
-
- /* Return delta value */
- m_bitCur += q;
- return atInt32(tempBuf);
-}
-
-std::vector>
-BitstreamReader::read(const atUint8* data,
- size_t keyFrameCount,
- const std::vector& channels,
- atUint32 rotDiv,
- float transMult,
- float scaleMult)
-{
- m_bitCur = 0;
- std::vector> chanKeys;
- std::vector chanAccum;
- chanKeys.reserve(channels.size());
- chanAccum.reserve(channels.size());
- for (const Channel& chan : channels)
- {
- chanAccum.push_back(chan.i);
-
- chanKeys.emplace_back();
- std::vector& keys = chanKeys.back();
- keys.reserve(keyFrameCount);
- switch (chan.type)
- {
- case Channel::Type::Rotation:
- {
- QuantizedRot qr = {{chan.i[0], chan.i[1], chan.i[2]}, false};
- keys.emplace_back(DequantizeRotation(qr, rotDiv));
- break;
- }
- case Channel::Type::Translation:
- {
- keys.push_back({chan.i[0] * transMult, chan.i[1] * transMult, chan.i[2] * transMult});
- break;
- }
- case Channel::Type::Scale:
- {
- keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult});
- break;
- }
- case Channel::Type::KfHead:
- {
- break;
- }
- case Channel::Type::RotationMP3:
- {
- QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, bool(chan.i[0] & 0x1)};
- keys.emplace_back(DequantizeRotation_3(qr, rotDiv));
- break;
- }
- default: break;
- }
+ case Channel::Type::Translation: {
+ keys.push_back({chan.i[0] * transMult, chan.i[1] * transMult, chan.i[2] * transMult});
+ break;
}
-
- for (size_t f=0 ; femplace_back(DequantizeRotation(qr, rotDiv));
-#if DUMP_KEYS
- fprintf(stderr, "%d R: %d %d %d %d\t", chan.id, wBit, p[0], p[1], p[2]);
-#endif
- break;
- }
- case Channel::Type::Translation:
- {
- atInt32 val1 = dequantize(data, chan.q[0]);
- p[0] += val1;
- atInt32 val2 = dequantize(data, chan.q[1]);
- p[1] += val2;
- atInt32 val3 = dequantize(data, chan.q[2]);
- p[2] += val3;
- kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
-#if DUMP_KEYS
- fprintf(stderr, "%d T: %d %d %d\t", chan.id, p[0], p[1], p[2]);
-#endif
- break;
- }
- case Channel::Type::Scale:
- {
- p[0] += dequantize(data, chan.q[0]);
- p[1] += dequantize(data, chan.q[1]);
- p[2] += dequantize(data, chan.q[2]);
- kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult});
-#if DUMP_KEYS
- fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]);
-#endif
- break;
- }
- case Channel::Type::KfHead:
- {
- dequantizeBit(data);
- break;
- }
- case Channel::Type::RotationMP3:
- {
- atInt32 val1 = dequantize(data, chan.q[0]);
- p[0] += val1;
- atInt32 val2 = dequantize(data, chan.q[1]);
- p[1] += val2;
- atInt32 val3 = dequantize(data, chan.q[2]);
- p[2] += val3;
- atInt32 val4 = dequantize(data, chan.q[3]);
- p[3] += val4;
- QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)};
- kit->emplace_back(DequantizeRotation_3(qr, rotDiv));
- break;
- }
- default: break;
- }
- ++kit;
- ++ait;
- }
-#if DUMP_KEYS
- fprintf(stderr, "\n");
-#endif
+ case Channel::Type::Scale: {
+ keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult});
+ break;
}
-
- return chanKeys;
-}
-
-void BitstreamWriter::quantizeBit(atUint8* data, bool val)
-{
- atUint32 byteCur = (m_bitCur / 32) * 4;
- atUint32 bitRem = m_bitCur % 32;
-
- /* Fill 32 bit buffer with region containing bits */
- /* Make them least significant */
- *(atUint32*)(data + byteCur) =
- hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (val << bitRem));
-
- m_bitCur += 1;
-}
-
-void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val)
-{
- atUint32 byteCur = (m_bitCur / 32) * 4;
- atUint32 bitRem = m_bitCur % 32;
-
- atUint32 masked = val & ((1 << q) - 1);
-
- /* Fill 32 bit buffer with region containing bits */
- /* Make them least significant */
- *(atUint32*)(data + byteCur) =
- hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (masked << bitRem));
-
- /* If this shift underflows the value, buffer the next 32 bits */
- /* And tack onto shifted buffer */
- if ((bitRem + q) > 32)
- {
- *(atUint32*)(data + byteCur + 4) =
- hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur + 4)) | (masked >> (32 - bitRem)));
+ case Channel::Type::KfHead: {
+ break;
}
+ case Channel::Type::RotationMP3: {
+ QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, bool(chan.i[0] & 0x1)};
+ keys.emplace_back(DequantizeRotation_3(qr, rotDiv));
+ break;
+ }
+ default:
+ break;
+ }
+ }
- m_bitCur += q;
-}
-
-std::unique_ptr
-BitstreamWriter::write(const std::vector>& chanKeys,
- size_t keyFrameCount, std::vector& channels,
- atUint32 quantRange,
- atUint32& rotDivOut,
- float& transMultOut,
- float& scaleMultOut,
- size_t& sizeOut)
-{
- m_bitCur = 0;
- rotDivOut = quantRange; /* Normalized range of values */
- float quantRangeF = float(quantRange);
-
- /* Pre-pass to calculate translation multiplier */
- float maxTransVal = 0.0f;
- float maxScaleVal = 0.0f;
+ for (size_t f = 0; f < keyFrameCount; ++f) {
+#if DUMP_KEYS
+ fprintf(stderr, "\nFRAME %" PRISize " %u %u\n", f, (m_bitCur / 32) * 4, m_bitCur % 32);
+ int lastId = -1;
+#endif
auto kit = chanKeys.begin();
- for (Channel& chan : channels)
- {
- switch (chan.type)
- {
- case Channel::Type::Translation:
- {
- for (auto it=kit->begin();
- it != kit->end();
- ++it)
- {
- const Value* key = &*it;
- zeus::simd_floats f(key->simd);
- maxTransVal = std::max(maxTransVal, std::fabs(f[0]));
- maxTransVal = std::max(maxTransVal, std::fabs(f[1]));
- maxTransVal = std::max(maxTransVal, std::fabs(f[2]));
- }
- break;
- }
- case Channel::Type::Scale:
- {
- for (auto it=kit->begin();
- it != kit->end();
- ++it)
- {
- const Value* key = &*it;
- zeus::simd_floats f(key->simd);
- maxScaleVal = std::max(maxScaleVal, std::fabs(f[0]));
- maxScaleVal = std::max(maxScaleVal, std::fabs(f[1]));
- maxScaleVal = std::max(maxScaleVal, std::fabs(f[2]));
- }
- break;
- }
- default: break;
- }
- ++kit;
+ auto ait = chanAccum.begin();
+ for (const Channel& chan : channels) {
+#if DUMP_KEYS
+ if (chan.id != lastId) {
+ lastId = chan.id;
+ fprintf(stderr, "\n");
+ }
+#endif
+ QuantizedValue& p = *ait;
+ switch (chan.type) {
+ case Channel::Type::Rotation: {
+ bool wBit = dequantizeBit(data);
+ p[0] += dequantize(data, chan.q[0]);
+ p[1] += dequantize(data, chan.q[1]);
+ p[2] += dequantize(data, chan.q[2]);
+ QuantizedRot qr = {{p[0], p[1], p[2]}, wBit};
+ kit->emplace_back(DequantizeRotation(qr, rotDiv));
+#if DUMP_KEYS
+ fprintf(stderr, "%d R: %d %d %d %d\t", chan.id, wBit, p[0], p[1], p[2]);
+#endif
+ break;
+ }
+ case Channel::Type::Translation: {
+ atInt32 val1 = dequantize(data, chan.q[0]);
+ p[0] += val1;
+ atInt32 val2 = dequantize(data, chan.q[1]);
+ p[1] += val2;
+ atInt32 val3 = dequantize(data, chan.q[2]);
+ p[2] += val3;
+ kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
+#if DUMP_KEYS
+ fprintf(stderr, "%d T: %d %d %d\t", chan.id, p[0], p[1], p[2]);
+#endif
+ break;
+ }
+ case Channel::Type::Scale: {
+ p[0] += dequantize(data, chan.q[0]);
+ p[1] += dequantize(data, chan.q[1]);
+ p[2] += dequantize(data, chan.q[2]);
+ kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult});
+#if DUMP_KEYS
+ fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]);
+#endif
+ break;
+ }
+ case Channel::Type::KfHead: {
+ dequantizeBit(data);
+ break;
+ }
+ case Channel::Type::RotationMP3: {
+ atInt32 val1 = dequantize(data, chan.q[0]);
+ p[0] += val1;
+ atInt32 val2 = dequantize(data, chan.q[1]);
+ p[1] += val2;
+ atInt32 val3 = dequantize(data, chan.q[2]);
+ p[2] += val3;
+ atInt32 val4 = dequantize(data, chan.q[3]);
+ p[3] += val4;
+ QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)};
+ kit->emplace_back(DequantizeRotation_3(qr, rotDiv));
+ break;
+ }
+ default:
+ break;
+ }
+ ++kit;
+ ++ait;
}
- transMultOut = maxTransVal / quantRangeF;
- scaleMultOut = maxScaleVal / quantRangeF;
+#if DUMP_KEYS
+ fprintf(stderr, "\n");
+#endif
+ }
- /* Output channel inits */
- std::vector initVals;
- initVals.reserve(channels.size());
- kit = chanKeys.begin();
- for (Channel& chan : channels)
- {
- chan.q[0] = 1;
- chan.q[1] = 1;
- chan.q[2] = 1;
- switch (chan.type)
- {
- case Channel::Type::Rotation:
- {
- QuantizedRot qr = QuantizeRotation((*kit)[0], rotDivOut);
- chan.i = qr.v;
- initVals.push_back(chan.i);
- break;
- }
- case Channel::Type::Translation:
- {
- zeus::simd_floats f((*kit)[0].simd);
- chan.i = {atInt32(f[0] / transMultOut),
- atInt32(f[1] / transMultOut),
- atInt32(f[2] / transMultOut)};
- initVals.push_back(chan.i);
- break;
- }
- case Channel::Type::Scale:
- {
- zeus::simd_floats f((*kit)[0].simd);
- chan.i = {atInt32(f[0] / scaleMultOut),
- atInt32(f[1] / scaleMultOut),
- atInt32(f[2] / scaleMultOut)};
- initVals.push_back(chan.i);
- break;
- }
- default: break;
- }
- ++kit;
- }
-
- /* Pre-pass to analyze quantization factors for channels */
- std::vector lastVals = initVals;
- kit = chanKeys.begin();
- auto vit = lastVals.begin();
- for (Channel& chan : channels)
- {
- QuantizedValue& last = *vit++;
- switch (chan.type)
- {
- case Channel::Type::Rotation:
- {
- for (auto it=kit->begin() + 1;
- it != kit->end();
- ++it)
- {
- QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
- chan.q[0] = std::max(chan.q[0], atUint8(qrCur.v.qFrom(last, 0)));
- chan.q[1] = std::max(chan.q[1], atUint8(qrCur.v.qFrom(last, 1)));
- chan.q[2] = std::max(chan.q[2], atUint8(qrCur.v.qFrom(last, 2)));
- last = qrCur.v;
- }
- break;
- }
- case Channel::Type::Translation:
- {
- for (auto it=kit->begin() + 1;
- it != kit->end();
- ++it)
- {
- zeus::simd_floats f(it->simd);
- QuantizedValue cur = {atInt32(f[0] / transMultOut),
- atInt32(f[1] / transMultOut),
- atInt32(f[2] / transMultOut)};
- chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
- chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
- chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
- last = cur;
- }
- break;
- }
- case Channel::Type::Scale:
- {
- for (auto it=kit->begin() + 1;
- it != kit->end();
- ++it)
- {
- zeus::simd_floats f(it->simd);
- QuantizedValue cur = {atInt32(f[0] / scaleMultOut),
- atInt32(f[1] / scaleMultOut),
- atInt32(f[2] / scaleMultOut)};
- chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
- chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
- chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
- last = cur;
- }
- break;
- }
- default: break;
- }
- ++kit;
- }
-
- /* Generate Bitstream */
- sizeOut = ComputeBitstreamSize(keyFrameCount, channels);
- std::unique_ptr newData(new atUint8[sizeOut]);
- memset(newData.get(), 0, sizeOut);
-
- lastVals = initVals;
- for (size_t f=0 ; f 32) {
+ *(atUint32*)(data + byteCur + 4) =
+ hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur + 4)) | (masked >> (32 - bitRem)));
+ }
+
+ m_bitCur += q;
+}
+
+std::unique_ptr BitstreamWriter::write(const std::vector>& chanKeys, size_t keyFrameCount,
+ std::vector& channels, atUint32 quantRange,
+ atUint32& rotDivOut, float& transMultOut, float& scaleMultOut,
+ size_t& sizeOut) {
+ m_bitCur = 0;
+ rotDivOut = quantRange; /* Normalized range of values */
+ float quantRangeF = float(quantRange);
+
+ /* Pre-pass to calculate translation multiplier */
+ float maxTransVal = 0.0f;
+ float maxScaleVal = 0.0f;
+ auto kit = chanKeys.begin();
+ for (Channel& chan : channels) {
+ switch (chan.type) {
+ case Channel::Type::Translation: {
+ for (auto it = kit->begin(); it != kit->end(); ++it) {
+ const Value* key = &*it;
+ zeus::simd_floats f(key->simd);
+ maxTransVal = std::max(maxTransVal, std::fabs(f[0]));
+ maxTransVal = std::max(maxTransVal, std::fabs(f[1]));
+ maxTransVal = std::max(maxTransVal, std::fabs(f[2]));
+ }
+ break;
+ }
+ case Channel::Type::Scale: {
+ for (auto it = kit->begin(); it != kit->end(); ++it) {
+ const Value* key = &*it;
+ zeus::simd_floats f(key->simd);
+ maxScaleVal = std::max(maxScaleVal, std::fabs(f[0]));
+ maxScaleVal = std::max(maxScaleVal, std::fabs(f[1]));
+ maxScaleVal = std::max(maxScaleVal, std::fabs(f[2]));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ ++kit;
+ }
+ transMultOut = maxTransVal / quantRangeF;
+ scaleMultOut = maxScaleVal / quantRangeF;
+
+ /* Output channel inits */
+ std::vector initVals;
+ initVals.reserve(channels.size());
+ kit = chanKeys.begin();
+ for (Channel& chan : channels) {
+ chan.q[0] = 1;
+ chan.q[1] = 1;
+ chan.q[2] = 1;
+ switch (chan.type) {
+ case Channel::Type::Rotation: {
+ QuantizedRot qr = QuantizeRotation((*kit)[0], rotDivOut);
+ chan.i = qr.v;
+ initVals.push_back(chan.i);
+ break;
+ }
+ case Channel::Type::Translation: {
+ zeus::simd_floats f((*kit)[0].simd);
+ chan.i = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)};
+ initVals.push_back(chan.i);
+ break;
+ }
+ case Channel::Type::Scale: {
+ zeus::simd_floats f((*kit)[0].simd);
+ chan.i = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)};
+ initVals.push_back(chan.i);
+ break;
+ }
+ default:
+ break;
+ }
+ ++kit;
+ }
+
+ /* Pre-pass to analyze quantization factors for channels */
+ std::vector lastVals = initVals;
+ kit = chanKeys.begin();
+ auto vit = lastVals.begin();
+ for (Channel& chan : channels) {
+ QuantizedValue& last = *vit++;
+ switch (chan.type) {
+ case Channel::Type::Rotation: {
+ for (auto it = kit->begin() + 1; it != kit->end(); ++it) {
+ QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
+ chan.q[0] = std::max(chan.q[0], atUint8(qrCur.v.qFrom(last, 0)));
+ chan.q[1] = std::max(chan.q[1], atUint8(qrCur.v.qFrom(last, 1)));
+ chan.q[2] = std::max(chan.q[2], atUint8(qrCur.v.qFrom(last, 2)));
+ last = qrCur.v;
+ }
+ break;
+ }
+ case Channel::Type::Translation: {
+ for (auto it = kit->begin() + 1; it != kit->end(); ++it) {
+ zeus::simd_floats f(it->simd);
+ QuantizedValue cur = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)};
+ chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
+ chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
+ chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
+ last = cur;
+ }
+ break;
+ }
+ case Channel::Type::Scale: {
+ for (auto it = kit->begin() + 1; it != kit->end(); ++it) {
+ zeus::simd_floats f(it->simd);
+ QuantizedValue cur = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)};
+ chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
+ chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
+ chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
+ last = cur;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ ++kit;
+ }
+
+ /* Generate Bitstream */
+ sizeOut = ComputeBitstreamSize(keyFrameCount, channels);
+ std::unique_ptr newData(new atUint8[sizeOut]);
+ memset(newData.get(), 0, sizeOut);
+
+ lastVals = initVals;
+ for (size_t f = 0; f < keyFrameCount; ++f) {
+ kit = chanKeys.begin();
+ vit = lastVals.begin();
+ for (const Channel& chan : channels) {
+ const Value& val = (*kit++)[f + 1];
+ QuantizedValue& last = *vit++;
+ switch (chan.type) {
+ case Channel::Type::Rotation: {
+ QuantizedRot qrCur = QuantizeRotation(val, rotDivOut);
+ quantizeBit(newData.get(), qrCur.w);
+ quantize(newData.get(), chan.q[0], qrCur.v[0] - last.v[0]);
+ quantize(newData.get(), chan.q[1], qrCur.v[1] - last.v[1]);
+ quantize(newData.get(), chan.q[2], qrCur.v[2] - last.v[2]);
+ last = qrCur.v;
+ break;
+ }
+ case Channel::Type::Translation: {
+ zeus::simd_floats f(val.simd);
+ QuantizedValue cur = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)};
+ quantize(newData.get(), chan.q[0], cur[0] - last[0]);
+ quantize(newData.get(), chan.q[1], cur[1] - last[1]);
+ quantize(newData.get(), chan.q[2], cur[2] - last[2]);
+ last = cur;
+ break;
+ }
+ case Channel::Type::Scale: {
+ zeus::simd_floats f(val.simd);
+ QuantizedValue cur = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)};
+ quantize(newData.get(), chan.q[0], cur[0] - last[0]);
+ quantize(newData.get(), chan.q[1], cur[1] - last[1]);
+ quantize(newData.get(), chan.q[2], cur[2] - last[2]);
+ last = cur;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return newData;
+}
+
+} // namespace DataSpec::DNAANIM
diff --git a/DataSpec/DNACommon/ANIM.hpp b/DataSpec/DNACommon/ANIM.hpp
index 93bab6450..268971bb2 100644
--- a/DataSpec/DNACommon/ANIM.hpp
+++ b/DataSpec/DNACommon/ANIM.hpp
@@ -3,87 +3,61 @@
#include "DNACommon.hpp"
#include
-namespace DataSpec::DNAANIM
-{
+namespace DataSpec::DNAANIM {
-struct Value
-{
- athena::simd simd;
- Value() = default;
- Value(const athena::simd& s) : simd(s) {}
- Value(const atVec3f& v) : simd(v.simd) {}
- Value(const atVec4f& v) : simd(v.simd) {}
- Value(float x, float y, float z) : simd(x, y, z, 0.f) {}
- Value(float w, float x, float y, float z) : simd(w, x, y, z) {}
+struct Value {
+ athena::simd simd;
+ Value() = default;
+ Value(const athena::simd& s) : simd(s) {}
+ Value(const atVec3f& v) : simd(v.simd) {}
+ Value(const atVec4f& v) : simd(v.simd) {}
+ Value(float x, float y, float z) : simd(x, y, z, 0.f) {}
+ Value(float w, float x, float y, float z) : simd(w, x, y, z) {}
};
-struct QuantizedValue
-{
- atInt32 v[4];
- atInt32& operator[] (size_t idx)
- {return v[idx];}
- atInt32 operator[] (size_t idx) const
- {return v[idx];}
+struct QuantizedValue {
+ atInt32 v[4];
+ atInt32& operator[](size_t idx) { return v[idx]; }
+ atInt32 operator[](size_t idx) const { return v[idx]; }
- int qFrom(const QuantizedValue& other, size_t idx) const
- {
- atInt32 delta = std::abs(v[idx] - other.v[idx]);
- if (delta == 0)
- return 1;
- return int(std::ceil(std::log2(delta))) + 1;
- }
+ int qFrom(const QuantizedValue& other, size_t idx) const {
+ atInt32 delta = std::abs(v[idx] - other.v[idx]);
+ if (delta == 0)
+ return 1;
+ return int(std::ceil(std::log2(delta))) + 1;
+ }
};
-struct QuantizedRot
-{
- QuantizedValue v;
- bool w;
+struct QuantizedRot {
+ QuantizedValue v;
+ bool w;
};
-struct Channel
-{
- enum class Type
- {
- Rotation,
- Translation,
- Scale,
- KfHead,
- RotationMP3
- } type;
- atInt32 id = -1;
- QuantizedValue i = {};
- atUint8 q[4] = {};
+struct Channel {
+ enum class Type { Rotation, Translation, Scale, KfHead, RotationMP3 } type;
+ atInt32 id = -1;
+ QuantizedValue i = {};
+ atUint8 q[4] = {};
};
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& channels);
-class BitstreamReader
-{
- size_t m_bitCur;
- atInt32 dequantize(const atUint8* data, atUint8 q);
- bool dequantizeBit(const atUint8* data);
+class BitstreamReader {
+ size_t m_bitCur;
+ atInt32 dequantize(const atUint8* data, atUint8 q);
+ bool dequantizeBit(const atUint8* data);
+
public:
- std::vector>
- read(const atUint8* data,
- size_t keyFrameCount,
- const std::vector& channels,
- atUint32 rotDiv,
- float transMult,
- float scaleMult);
+ std::vector> read(const atUint8* data, size_t keyFrameCount, const std::vector& channels,
+ atUint32 rotDiv, float transMult, float scaleMult);
};
-class BitstreamWriter
-{
- size_t m_bitCur;
- void quantize(atUint8* data, atUint8 q, atInt32 val);
- void quantizeBit(atUint8* data, bool val);
+class BitstreamWriter {
+ size_t m_bitCur;
+ void quantize(atUint8* data, atUint8 q, atInt32 val);
+ void quantizeBit(atUint8* data, bool val);
+
public:
- std::unique_ptr
- write(const std::vector>& chanKeys,
- size_t keyFrameCount, std::vector& channels,
- atUint32 quantRange,
- atUint32& rotDivOut,
- float& transMultOut,
- float& scaleMultOut,
- size_t& sizeOut);
+ std::unique_ptr write(const std::vector>& chanKeys, size_t keyFrameCount,
+ std::vector& channels, atUint32 quantRange, atUint32& rotDivOut,
+ float& transMultOut, float& scaleMultOut, size_t& sizeOut);
};
-}
-
+} // namespace DataSpec::DNAANIM
diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp
index 9f76a12e1..6c917b870 100644
--- a/DataSpec/DNACommon/AROTBuilder.cpp
+++ b/DataSpec/DNACommon/AROTBuilder.cpp
@@ -2,8 +2,7 @@
#include "hecl/Blender/Connection.hpp"
#include "../DNAMP1/PATH.hpp"
-namespace DataSpec
-{
+namespace DataSpec {
logvisor::Module Log("AROTBuilder");
#define AROT_MAX_LEVEL 10
@@ -12,505 +11,419 @@ logvisor::Module Log("AROTBuilder");
#define COLLISION_MIN_NODE_TRIANGLES 8
#define PATH_MIN_NODE_REGIONS 16
-static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i)
-{
- zeus::CAABox pos, neg;
- aabb.splitZ(neg, pos);
- if (i & 4)
- {
- zeus::CAABox(pos).splitY(neg, pos);
- if (i & 2)
- {
- zeus::CAABox(pos).splitX(neg, pos);
- if (i & 1)
- return pos;
- else
- return neg;
- }
- else
- {
- zeus::CAABox(neg).splitX(neg, pos);
- if (i & 1)
- return pos;
- else
- return neg;
- }
+static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i) {
+ zeus::CAABox pos, neg;
+ aabb.splitZ(neg, pos);
+ if (i & 4) {
+ zeus::CAABox(pos).splitY(neg, pos);
+ if (i & 2) {
+ zeus::CAABox(pos).splitX(neg, pos);
+ if (i & 1)
+ return pos;
+ else
+ return neg;
+ } else {
+ zeus::CAABox(neg).splitX(neg, pos);
+ if (i & 1)
+ return pos;
+ else
+ return neg;
}
- else
- {
- zeus::CAABox(neg).splitY(neg, pos);
- if (i & 2)
- {
- zeus::CAABox(pos).splitX(neg, pos);
- if (i & 1)
- return pos;
- else
- return neg;
- }
- else
- {
- zeus::CAABox(neg).splitX(neg, pos);
- if (i & 1)
- return pos;
- else
- return neg;
- }
+ } else {
+ zeus::CAABox(neg).splitY(neg, pos);
+ if (i & 2) {
+ zeus::CAABox(pos).splitX(neg, pos);
+ if (i & 1)
+ return pos;
+ else
+ return neg;
+ } else {
+ zeus::CAABox(neg).splitX(neg, pos);
+ if (i & 1)
+ return pos;
+ else
+ return neg;
}
+ }
}
-void AROTBuilder::Node::mergeSets(int a, int b)
-{
- childNodes[a].childIndices.insert(childNodes[b].childIndices.cbegin(), childNodes[b].childIndices.cend());
- childNodes[b].childIndices = childNodes[a].childIndices;
+void AROTBuilder::Node::mergeSets(int a, int b) {
+ childNodes[a].childIndices.insert(childNodes[b].childIndices.cbegin(), childNodes[b].childIndices.cend());
+ childNodes[b].childIndices = childNodes[a].childIndices;
}
-bool AROTBuilder::Node::compareSets(int a, int b) const
-{
- return childNodes[a].childIndices != childNodes[b].childIndices;
+bool AROTBuilder::Node::compareSets(int a, int b) const {
+ return childNodes[a].childIndices != childNodes[b].childIndices;
}
void AROTBuilder::Node::addChild(int level, int minChildren, const std::vector& triBoxes,
- const zeus::CAABox& curAABB, BspNodeType& typeOut)
-{
- /* Gather intersecting faces */
- for (int i=0 ; i();
- flags = 0;
- }
+ if (!compSubdivs) {
+ typeOut = BspNodeType::Leaf;
+ childNodes = std::vector();
+ flags = 0;
+ }
}
-size_t AROTBuilder::BitmapPool::addIndices(const std::set& indices)
-{
- for (size_t i=0 ; i& indices) {
+ for (size_t i = 0; i < m_pool.size(); ++i)
+ if (m_pool[i] == indices)
+ return i;
+ m_pool.push_back(indices);
+ return m_pool.size() - 1;
}
-static const uint32_t AROTChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 };
+static const uint32_t AROTChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8};
-void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff)
-{
- sz += 1;
- poolIdx = bmpPool.addIndices(childIndices);
- if (poolIdx > 65535)
- Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex");
+void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff) {
+ sz += 1;
+ poolIdx = bmpPool.addIndices(childIndices);
+ if (poolIdx > 65535)
+ Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex");
- uint32_t childCount = AROTChildCounts[compSubdivs];
- nodeOff = curOff;
- nodeSz = childCount * 2 + 4;
- curOff += nodeSz;
- if (childNodes.size())
- {
- for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
- {
- for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
- {
- for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
- {
- int idx = k*4 + j*2 + i;
- childNodes[idx].nodeCount(sz, idxRefs, bmpPool, curOff);
- }
- }
+ uint32_t childCount = AROTChildCounts[compSubdivs];
+ nodeOff = curOff;
+ nodeSz = childCount * 2 + 4;
+ curOff += nodeSz;
+ if (childNodes.size()) {
+ for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
+ for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
+ for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
+ int idx = k * 4 + j * 2 + i;
+ childNodes[idx].nodeCount(sz, idxRefs, bmpPool, curOff);
}
- idxRefs += childCount;
+ }
}
+ idxRefs += childCount;
+ }
}
-void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w)
-{
- w.writeUint32Big(nodeOff);
- if (childNodes.size())
- {
- for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
- {
- for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
- {
- for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
- {
- int idx = k*4 + j*2 + i;
- childNodes[idx].writeIndirectionTable(w);
- }
- }
+void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w) {
+ w.writeUint32Big(nodeOff);
+ if (childNodes.size()) {
+ for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
+ for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
+ for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
+ int idx = k * 4 + j * 2 + i;
+ childNodes[idx].writeIndirectionTable(w);
}
+ }
}
+ }
}
-void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx)
-{
- w.writeUint16Big(poolIdx);
- w.writeUint16Big(compSubdivs);
+void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) {
+ w.writeUint16Big(poolIdx);
+ w.writeUint16Big(compSubdivs);
- if (childNodes.size())
- {
- int curIdx = nodeIdx + 1;
- if (curIdx > 65535)
- Log.report(logvisor::Fatal, "AROT node exceeds 16-bit node addressing; area too complex");
+ if (childNodes.size()) {
+ int curIdx = nodeIdx + 1;
+ if (curIdx > 65535)
+ Log.report(logvisor::Fatal, "AROT node exceeds 16-bit node addressing; area too complex");
- int childIndices[8];
+ int childIndices[8];
- for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
- {
- for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
- {
- for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
- {
- int idx = k*4 + j*2 + i;
- w.writeUint16Big(curIdx);
- childIndices[idx] = curIdx;
- childNodes[idx].advanceIndex(curIdx);
- }
- }
- }
-
- for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
- {
- for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
- {
- for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
- {
- int idx = k*4 + j*2 + i;
- childNodes[idx].writeNodes(w, childIndices[idx]);
- }
- }
+ for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
+ for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
+ for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
+ int idx = k * 4 + j * 2 + i;
+ w.writeUint16Big(curIdx);
+ childIndices[idx] = curIdx;
+ childNodes[idx].advanceIndex(curIdx);
}
+ }
}
+
+ for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
+ for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
+ for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
+ int idx = k * 4 + j * 2 + i;
+ childNodes[idx].writeNodes(w, childIndices[idx]);
+ }
+ }
+ }
+ }
}
-void AROTBuilder::Node::advanceIndex(int& nodeIdx)
-{
- ++nodeIdx;
- if (childNodes.size())
- {
- for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
- {
- for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
- {
- for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
- {
- int idx = k*4 + j*2 + i;
- childNodes[idx].advanceIndex(nodeIdx);
- }
- }
+void AROTBuilder::Node::advanceIndex(int& nodeIdx) {
+ ++nodeIdx;
+ if (childNodes.size()) {
+ for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
+ for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
+ for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
+ int idx = k * 4 + j * 2 + i;
+ childNodes[idx].advanceIndex(nodeIdx);
}
+ }
}
+ }
}
-void AROTBuilder::Node::colSize(size_t& totalSz)
-{
- if (childIndices.size())
- {
- nodeOff = totalSz;
- if (childNodes.empty())
- {
- totalSz += 26 + childIndices.size() * 2;
- }
- else
- {
- totalSz += 36;
- for (int i=0 ; i<8 ; ++i)
- childNodes[i].colSize(totalSz);
- }
+void AROTBuilder::Node::colSize(size_t& totalSz) {
+ if (childIndices.size()) {
+ nodeOff = totalSz;
+ if (childNodes.empty()) {
+ totalSz += 26 + childIndices.size() * 2;
+ } else {
+ totalSz += 36;
+ for (int i = 0; i < 8; ++i)
+ childNodes[i].colSize(totalSz);
}
+ }
}
-void AROTBuilder::Node::writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB)
-{
- if (childIndices.size())
- {
- if (childNodes.empty())
- {
- float* aabbOut = reinterpret_cast(ptr);
- aabbOut[0] = hecl::SBig(curAABB.min[0]);
- aabbOut[1] = hecl::SBig(curAABB.min[1]);
- aabbOut[2] = hecl::SBig(curAABB.min[2]);
- aabbOut[3] = hecl::SBig(curAABB.max[0]);
- aabbOut[4] = hecl::SBig(curAABB.max[1]);
- aabbOut[5] = hecl::SBig(curAABB.max[2]);
- athena::io::MemoryWriter w(ptr + 24, INT32_MAX);
- w.writeUint16Big(childIndices.size());
- for (int idx : childIndices)
- w.writeUint16Big(idx);
- ptr += 26 + childIndices.size() * 2;
- }
- else
- {
- uint16_t* pflags = reinterpret_cast(ptr);
- uint32_t* offsets = reinterpret_cast(ptr + 4);
- memset(pflags, 0, sizeof(uint32_t) * 9);
- for (int i=0 ; i<8 ; ++i)
- {
- const Node& chNode = childNodes[i];
- BspNodeType type = BspNodeType((flags >> (i * 2)) & 0x3);
- if (type != BspNodeType::Invalid)
- offsets[i] = hecl::SBig(uint32_t(chNode.nodeOff - nodeOff - 36));
- }
+void AROTBuilder::Node::writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB) {
+ if (childIndices.size()) {
+ if (childNodes.empty()) {
+ float* aabbOut = reinterpret_cast(ptr);
+ aabbOut[0] = hecl::SBig(curAABB.min[0]);
+ aabbOut[1] = hecl::SBig(curAABB.min[1]);
+ aabbOut[2] = hecl::SBig(curAABB.min[2]);
+ aabbOut[3] = hecl::SBig(curAABB.max[0]);
+ aabbOut[4] = hecl::SBig(curAABB.max[1]);
+ aabbOut[5] = hecl::SBig(curAABB.max[2]);
+ athena::io::MemoryWriter w(ptr + 24, INT32_MAX);
+ w.writeUint16Big(childIndices.size());
+ for (int idx : childIndices)
+ w.writeUint16Big(idx);
+ ptr += 26 + childIndices.size() * 2;
+ } else {
+ uint16_t* pflags = reinterpret_cast(ptr);
+ uint32_t* offsets = reinterpret_cast(ptr + 4);
+ memset(pflags, 0, sizeof(uint32_t) * 9);
+ for (int i = 0; i < 8; ++i) {
+ const Node& chNode = childNodes[i];
+ BspNodeType type = BspNodeType((flags >> (i * 2)) & 0x3);
+ if (type != BspNodeType::Invalid)
+ offsets[i] = hecl::SBig(uint32_t(chNode.nodeOff - nodeOff - 36));
+ }
- *pflags = hecl::SBig(flags);
- ptr += 36;
+ *pflags = hecl::SBig(flags);
+ ptr += 36;
- for (int i=0 ; i<8 ; ++i)
- childNodes[i].writeColNodes(ptr, SplitAABB(curAABB, i));
- }
+ for (int i = 0; i < 8; ++i)
+ childNodes[i].writeColNodes(ptr, SplitAABB(curAABB, i));
}
+ }
}
-void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount)
-{
- ++nodeCount;
- if (childNodes.empty())
- {
- lookupCount += childIndices.size();
- }
- else
- {
- for (int i=0 ; i<8 ; ++i)
- childNodes[i].pathCountNodesAndLookups(nodeCount, lookupCount);
- }
+void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount) {
+ ++nodeCount;
+ if (childNodes.empty()) {
+ lookupCount += childIndices.size();
+ } else {
+ for (int i = 0; i < 8; ++i)
+ childNodes[i].pathCountNodesAndLookups(nodeCount, lookupCount);
+ }
}
-void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB)
-{
- if (childNodes.empty())
- {
- path.octree.emplace_back();
- DNAMP1::PATH::OctreeNode& n = path.octree.back();
- n.isLeaf = 1;
- n.aabb[0] = curAABB.min;
- n.aabb[1] = curAABB.max;
- n.centroid = curAABB.center();
- for (int i=0 ; i<8 ; ++i)
- n.children[i] = 0xffffffff;
- n.regionCount = childIndices.size();
- n.regionStart = path.octreeRegionLookup.size();
- for (int r : childIndices)
- path.octreeRegionLookup.push_back(r);
+void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) {
+ if (childNodes.empty()) {
+ path.octree.emplace_back();
+ DNAMP1::PATH::OctreeNode& n = path.octree.back();
+ n.isLeaf = 1;
+ n.aabb[0] = curAABB.min;
+ n.aabb[1] = curAABB.max;
+ n.centroid = curAABB.center();
+ for (int i = 0; i < 8; ++i)
+ n.children[i] = 0xffffffff;
+ n.regionCount = childIndices.size();
+ n.regionStart = path.octreeRegionLookup.size();
+ for (int r : childIndices)
+ path.octreeRegionLookup.push_back(r);
+ } else {
+ atUint32 children[8];
+ for (int i = 0; i < 8; ++i) {
+ /* Head recursion (first node will be a leaf) */
+ children[i] = path.octree.size();
+ childNodes[i].pathWrite(path, SplitAABB(curAABB, i));
}
- else
- {
- atUint32 children[8];
- for (int i=0 ; i<8 ; ++i)
- {
- /* Head recursion (first node will be a leaf) */
- children[i] = path.octree.size();
- childNodes[i].pathWrite(path, SplitAABB(curAABB, i));
- }
- path.octree.emplace_back();
- DNAMP1::PATH::OctreeNode& n = path.octree.back();
- n.isLeaf = 0;
- n.aabb[0] = curAABB.min;
- n.aabb[1] = curAABB.max;
- n.centroid = curAABB.center();
- for (int i=0 ; i<8 ; ++i)
- n.children[i] = children[i];
- n.regionCount = 0;
- n.regionStart = 0;
- }
+ path.octree.emplace_back();
+ DNAMP1::PATH::OctreeNode& n = path.octree.back();
+ n.isLeaf = 0;
+ n.aabb[0] = curAABB.min;
+ n.aabb[1] = curAABB.max;
+ n.centroid = curAABB.center();
+ for (int i = 0; i < 8; ++i)
+ n.children[i] = children[i];
+ n.regionCount = 0;
+ n.regionStart = 0;
+ }
}
void AROTBuilder::build(std::vector>& secs, const zeus::CAABox& fullAabb,
- const std::vector& meshAabbs, const std::vector& meshes)
-{
- /* Recursively split */
- BspNodeType rootType;
- rootNode.addChild(0, AROT_MIN_MODELS, meshAabbs, fullAabb, rootType);
+ const std::vector& meshAabbs, const std::vector& meshes) {
+ /* Recursively split */
+ BspNodeType rootType;
+ rootNode.addChild(0, AROT_MIN_MODELS, meshAabbs, fullAabb, rootType);
- /* Calculate indexing metrics */
- size_t totalNodeCount = 0;
- size_t idxRefCount = 0;
- size_t curOff = 0;
- rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff);
- size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32;
- size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2;
+ /* Calculate indexing metrics */
+ size_t totalNodeCount = 0;
+ size_t idxRefCount = 0;
+ size_t curOff = 0;
+ rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff);
+ size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32;
+ size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2;
- /* Write header */
- secs.emplace_back(arotSz, 0);
- athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
- w.writeUint32Big('AROT');
- w.writeUint32Big(1);
- w.writeUint32Big(bmpPool.m_pool.size());
- w.writeUint32Big(meshes.size());
- w.writeUint32Big(totalNodeCount);
- w.writeVec3fBig(fullAabb.min);
- w.writeVec3fBig(fullAabb.max);
- w.seekAlign32();
+ /* Write header */
+ secs.emplace_back(arotSz, 0);
+ athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
+ w.writeUint32Big('AROT');
+ w.writeUint32Big(1);
+ w.writeUint32Big(bmpPool.m_pool.size());
+ w.writeUint32Big(meshes.size());
+ w.writeUint32Big(totalNodeCount);
+ w.writeVec3fBig(fullAabb.min);
+ w.writeVec3fBig(fullAabb.max);
+ w.seekAlign32();
- /* Write bitmap */
- std::vector bmpWords;
- bmpWords.reserve(bmpWordCount);
- for (const std::set& bmp : bmpPool.m_pool)
- {
- bmpWords.clear();
- bmpWords.resize(bmpWordCount);
+ /* Write bitmap */
+ std::vector bmpWords;
+ bmpWords.reserve(bmpWordCount);
+ for (const std::set& bmp : bmpPool.m_pool) {
+ bmpWords.clear();
+ bmpWords.resize(bmpWordCount);
- auto bmpIt = bmp.cbegin();
- if (bmpIt != bmp.cend())
- {
- int curIdx = 0;
- for (int w=0 ; w, uint32_t> AROTBuilder::buildCol(const ColMesh& mesh, BspNodeType& rootOut)
-{
- /* Accumulate total AABB */
- zeus::CAABox fullAABB;
- for (const auto& vert : mesh.verts)
- fullAABB.accumulateBounds(zeus::CVector3f(vert));
+std::pair, uint32_t> AROTBuilder::buildCol(const ColMesh& mesh, BspNodeType& rootOut) {
+ /* Accumulate total AABB */
+ zeus::CAABox fullAABB;
+ for (const auto& vert : mesh.verts)
+ fullAABB.accumulateBounds(zeus::CVector3f(vert));
- /* Predetermine triangle AABBs */
- std::vector triBoxes;
- triBoxes.reserve(mesh.trianges.size());
- for (const ColMesh::Triangle& tri : mesh.trianges)
- {
- triBoxes.emplace_back();
- zeus::CAABox& aabb = triBoxes.back();
- for (int e=0 ; e<3 ; ++e)
- {
- const ColMesh::Edge& edge = mesh.edges[tri.edges[e]];
- for (int v=0 ; v<2 ; ++v)
- {
- const auto& vert = mesh.verts[edge.verts[v]];
- aabb.accumulateBounds(zeus::CVector3f(vert));
- }
- }
+ /* Predetermine triangle AABBs */
+ std::vector triBoxes;
+ triBoxes.reserve(mesh.trianges.size());
+ for (const ColMesh::Triangle& tri : mesh.trianges) {
+ triBoxes.emplace_back();
+ zeus::CAABox& aabb = triBoxes.back();
+ for (int e = 0; e < 3; ++e) {
+ const ColMesh::Edge& edge = mesh.edges[tri.edges[e]];
+ for (int v = 0; v < 2; ++v) {
+ const auto& vert = mesh.verts[edge.verts[v]];
+ aabb.accumulateBounds(zeus::CVector3f(vert));
+ }
}
+ }
- /* Recursively split */
- rootNode.addChild(0, COLLISION_MIN_NODE_TRIANGLES, triBoxes, fullAABB, rootOut);
+ /* Recursively split */
+ rootNode.addChild(0, COLLISION_MIN_NODE_TRIANGLES, triBoxes, fullAABB, rootOut);
- /* Calculate offsets and write out */
- size_t totalSize = 0;
- rootNode.colSize(totalSize);
- std::unique_ptr ret(new uint8_t[totalSize]);
- uint8_t* ptr = ret.get();
- rootNode.writeColNodes(ptr, fullAABB);
+ /* Calculate offsets and write out */
+ size_t totalSize = 0;
+ rootNode.colSize(totalSize);
+ std::unique_ptr ret(new uint8_t[totalSize]);
+ uint8_t* ptr = ret.get();
+ rootNode.writeColNodes(ptr, fullAABB);
- return {std::move(ret), totalSize};
+ return {std::move(ret), totalSize};
}
-void AROTBuilder::buildPath(DNAMP1::PATH& path)
-{
- /* Accumulate total AABB and gather region boxes */
- std::vector regionBoxes;
- regionBoxes.reserve(path.regions.size());
- zeus::CAABox fullAABB;
- for (const DNAMP1::PATH::Region& r : path.regions)
- {
- regionBoxes.emplace_back(r.aabb[0], r.aabb[1]);
- fullAABB.accumulateBounds(regionBoxes.back());
- }
+void AROTBuilder::buildPath(DNAMP1::PATH& path) {
+ /* Accumulate total AABB and gather region boxes */
+ std::vector regionBoxes;
+ regionBoxes.reserve(path.regions.size());
+ zeus::CAABox fullAABB;
+ for (const DNAMP1::PATH::Region& r : path.regions) {
+ regionBoxes.emplace_back(r.aabb[0], r.aabb[1]);
+ fullAABB.accumulateBounds(regionBoxes.back());
+ }
- /* Recursively split */
- BspNodeType dontCare;
- rootNode.addChild(0, PATH_MIN_NODE_REGIONS, regionBoxes, fullAABB, dontCare);
+ /* Recursively split */
+ BspNodeType dontCare;
+ rootNode.addChild(0, PATH_MIN_NODE_REGIONS, regionBoxes, fullAABB, dontCare);
- /* Write out */
- size_t nodeCount = 0;
- size_t lookupCount = 0;
- rootNode.pathCountNodesAndLookups(nodeCount, lookupCount);
- path.octreeNodeCount = nodeCount;
- path.octree.reserve(nodeCount);
- path.octreeRegionLookupCount = lookupCount;
- path.octreeRegionLookup.reserve(lookupCount);
- rootNode.pathWrite(path, fullAABB);
+ /* Write out */
+ size_t nodeCount = 0;
+ size_t lookupCount = 0;
+ rootNode.pathCountNodesAndLookups(nodeCount, lookupCount);
+ path.octreeNodeCount = nodeCount;
+ path.octree.reserve(nodeCount);
+ path.octreeRegionLookupCount = lookupCount;
+ path.octreeRegionLookup.reserve(lookupCount);
+ rootNode.pathWrite(path, fullAABB);
}
-}
+} // namespace DataSpec
diff --git a/DataSpec/DNACommon/AROTBuilder.hpp b/DataSpec/DNACommon/AROTBuilder.hpp
index da8bac3e5..1ecabbce7 100644
--- a/DataSpec/DNACommon/AROTBuilder.hpp
+++ b/DataSpec/DNACommon/AROTBuilder.hpp
@@ -6,55 +6,49 @@
#include "CMDL.hpp"
#include
-namespace DataSpec
-{
-namespace DNAMP1
-{
+namespace DataSpec {
+namespace DNAMP1 {
struct PATH;
}
-struct AROTBuilder
-{
- using ColMesh = hecl::blender::ColMesh;
+struct AROTBuilder {
+ using ColMesh = hecl::blender::ColMesh;
- struct BitmapPool
- {
- std::vector> m_pool;
- size_t addIndices(const std::set& indices);
- } bmpPool;
+ struct BitmapPool {
+ std::vector> m_pool;
+ size_t addIndices(const std::set& indices);
+ } bmpPool;
- struct Node
- {
- std::vector childNodes;
- std::set childIndices;
- size_t poolIdx = 0;
- uint16_t flags = 0;
- uint16_t compSubdivs = 0;
+ struct Node {
+ std::vector childNodes;
+ std::set childIndices;
+ size_t poolIdx = 0;
+ uint16_t flags = 0;
+ uint16_t compSubdivs = 0;
- size_t nodeOff = 0;
- size_t nodeSz = 4;
+ size_t nodeOff = 0;
+ size_t nodeSz = 4;
- void addChild(int level, int minChildren, const std::vector& triBoxes,
- const zeus::CAABox& curAABB, BspNodeType& typeOut);
- void mergeSets(int a, int b);
- bool compareSets(int a, int b) const;
- void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff);
- void writeIndirectionTable(athena::io::MemoryWriter& w);
- void writeNodes(athena::io::MemoryWriter& w, int nodeIdx);
- void advanceIndex(int& nodeIdx);
+ void addChild(int level, int minChildren, const std::vector& triBoxes, const zeus::CAABox& curAABB,
+ BspNodeType& typeOut);
+ void mergeSets(int a, int b);
+ bool compareSets(int a, int b) const;
+ void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff);
+ void writeIndirectionTable(athena::io::MemoryWriter& w);
+ void writeNodes(athena::io::MemoryWriter& w, int nodeIdx);
+ void advanceIndex(int& nodeIdx);
- void colSize(size_t& totalSz);
- void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB);
+ void colSize(size_t& totalSz);
+ void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB);
- void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount);
- void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB);
- } rootNode;
+ void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount);
+ void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB);
+ } rootNode;
- void build(std::vector>& secs, const zeus::CAABox& fullAabb,
- const std::vector& meshAabbs, const std::vector& meshes);
- std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut);
- void buildPath(DNAMP1::PATH& path);
+ void build(std::vector>& secs, const zeus::CAABox& fullAabb,
+ const std::vector& meshAabbs, const std::vector& meshes);
+ std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut);
+ void buildPath(DNAMP1::PATH& path);
};
-}
-
+} // namespace DataSpec
diff --git a/DataSpec/DNACommon/ATBL.cpp b/DataSpec/DNACommon/ATBL.cpp
index 94e83f7f7..49e0fa459 100644
--- a/DataSpec/DNACommon/ATBL.cpp
+++ b/DataSpec/DNACommon/ATBL.cpp
@@ -1,61 +1,55 @@
#include "ATBL.hpp"
-namespace DataSpec::DNAAudio
-{
+namespace DataSpec::DNAAudio {
-bool ATBL::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
-{
- uint32_t idxCount = rs.readUint32Big();
- athena::io::YAMLDocWriter w("ATBL");
- for (uint32_t i=0 ; im_mapChildren)
- {
- unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
- maxI = std::max(maxI, i);
- }
+ unsigned long maxI = 0;
+ for (const auto& pair : dr.getRootNode()->m_mapChildren) {
+ unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
+ maxI = std::max(maxI, i);
+ }
- std::vector vecOut;
- vecOut.resize(maxI + 1, 0xffff);
+ std::vector vecOut;
+ vecOut.resize(maxI + 1, 0xffff);
- for (const auto& pair : dr.getRootNode()->m_mapChildren)
- {
- unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
- vecOut[i] = hecl::SBig(uint16_t(strtoul(pair.second->m_scalarString.c_str(), nullptr, 0)));
- }
+ for (const auto& pair : dr.getRootNode()->m_mapChildren) {
+ unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
+ vecOut[i] = hecl::SBig(uint16_t(strtoul(pair.second->m_scalarString.c_str(), nullptr, 0)));
+ }
- athena::io::FileWriter w(outPath.getAbsolutePath());
- if (w.hasError())
- return false;
- w.writeUint32Big(uint32_t(vecOut.size()));
- w.writeBytes(vecOut.data(), vecOut.size() * 2);
+ athena::io::FileWriter w(outPath.getAbsolutePath());
+ if (w.hasError())
+ return false;
+ w.writeUint32Big(uint32_t(vecOut.size()));
+ w.writeBytes(vecOut.data(), vecOut.size() * 2);
- return true;
+ return true;
}
-}
+} // namespace DataSpec::DNAAudio
diff --git a/DataSpec/DNACommon/ATBL.hpp b/DataSpec/DNACommon/ATBL.hpp
index 42bdf1863..406e3869c 100644
--- a/DataSpec/DNACommon/ATBL.hpp
+++ b/DataSpec/DNACommon/ATBL.hpp
@@ -3,15 +3,12 @@
#include "DNACommon.hpp"
#include "PAK.hpp"
-namespace DataSpec::DNAAudio
-{
+namespace DataSpec::DNAAudio {
-class ATBL
-{
+class ATBL {
public:
- static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
- static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
+ static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
+ static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
};
-}
-
+} // namespace DataSpec::DNAAudio
diff --git a/DataSpec/DNACommon/BabeDead.cpp b/DataSpec/DNACommon/BabeDead.cpp
index 12c8b9976..b804470cb 100644
--- a/DataSpec/DNACommon/BabeDead.cpp
+++ b/DataSpec/DNACommon/BabeDead.cpp
@@ -4,163 +4,156 @@
#include "zeus/CTransform.hpp"
#include "hecl/Blender/Connection.hpp"
-namespace DataSpec
-{
+namespace DataSpec {
-template
-void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os,
- const BabeDeadLight& light, unsigned s, unsigned l)
-{
- switch (light.lightType)
- {
- case BabeDeadLight::LightType::LocalAmbient:
- case BabeDeadLight::LightType::LocalAmbient2:
- os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n"
- "bg_node.inputs[1].default_value = %f\n",
- light.color.simd[0], light.color.simd[1], light.color.simd[2],
- light.q / 8.f);
- return;
- case BabeDeadLight::LightType::Directional:
- os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n"
- "lamp.color = (%f,%f,%f)\n"
- "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
- "lamp_obj.rotation_mode = 'QUATERNION'\n"
- "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
- "lamp.shadow_method = '%s'\n"
- "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
- light.direction.simd[0], light.direction.simd[1], light.direction.simd[2],
- light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
- return;
- case BabeDeadLight::LightType::Custom:
- os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n"
- "lamp.color = (%f,%f,%f)\n"
- "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
- "lamp.shadow_soft_size = 1.0\n"
- "lamp.shadow_method = '%s'\n"
- "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
- light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
- break;
- case BabeDeadLight::LightType::Spot:
- case BabeDeadLight::LightType::Spot2:
- os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
- "lamp.color = (%f,%f,%f)\n"
- "lamp.spot_size = %.6g\n"
- "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
- "lamp_obj.rotation_mode = 'QUATERNION'\n"
- "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
- "lamp.shadow_soft_size = 0.5\n"
- "lamp.shadow_method = '%s'\n"
- "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
- zeus::degToRad(light.spotCutoff),
- light.direction.simd[0], light.direction.simd[1], light.direction.simd[2],
- light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
- break;
- default: return;
- }
+template
+void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLight& light, unsigned s, unsigned l) {
+ switch (light.lightType) {
+ case BabeDeadLight::LightType::LocalAmbient:
+ case BabeDeadLight::LightType::LocalAmbient2:
+ os.format(
+ "bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n"
+ "bg_node.inputs[1].default_value = %f\n",
+ light.color.simd[0], light.color.simd[1], light.color.simd[2], light.q / 8.f);
+ return;
+ case BabeDeadLight::LightType::Directional:
+ os.format(
+ "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n"
+ "lamp.color = (%f,%f,%f)\n"
+ "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
+ "lamp_obj.rotation_mode = 'QUATERNION'\n"
+ "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
+ "lamp.shadow_method = '%s'\n"
+ "\n",
+ s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], light.direction.simd[0],
+ light.direction.simd[1], light.direction.simd[2], light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
+ return;
+ case BabeDeadLight::LightType::Custom:
+ os.format(
+ "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n"
+ "lamp.color = (%f,%f,%f)\n"
+ "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
+ "lamp.shadow_soft_size = 1.0\n"
+ "lamp.shadow_method = '%s'\n"
+ "\n",
+ s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
+ light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
+ break;
+ case BabeDeadLight::LightType::Spot:
+ case BabeDeadLight::LightType::Spot2:
+ os.format(
+ "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
+ "lamp.color = (%f,%f,%f)\n"
+ "lamp.spot_size = %.6g\n"
+ "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
+ "lamp_obj.rotation_mode = 'QUATERNION'\n"
+ "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
+ "lamp.shadow_soft_size = 0.5\n"
+ "lamp.shadow_method = '%s'\n"
+ "\n",
+ s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], zeus::degToRad(light.spotCutoff),
+ light.direction.simd[0], light.direction.simd[1], light.direction.simd[2],
+ light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
+ break;
+ default:
+ return;
+ }
- os.format("lamp.retro_layer = %u\n"
- "lamp.retro_origtype = %u\n"
- "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n"
- "lamp.constant_coefficient = 0\n"
- "lamp.use_nodes = True\n"
- "falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n"
- "lamp.energy = 0.0\n"
- "falloff_node.inputs[0].default_value = %f\n"
- "hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n"
- "hue_sat_node.inputs[1].default_value = 1.25\n"
- "hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n"
- "lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n"
- "lamp_obj.location = (%f,%f,%f)\n"
- "bpy.context.scene.objects.link(lamp_obj)\n"
- "\n", s, light.lightType, light.q / 8.f,
- light.color.simd[0], light.color.simd[1], light.color.simd[2],
- light.position.simd[0], light.position.simd[1], light.position.simd[2]);
+ os.format(
+ "lamp.retro_layer = %u\n"
+ "lamp.retro_origtype = %u\n"
+ "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n"
+ "lamp.constant_coefficient = 0\n"
+ "lamp.use_nodes = True\n"
+ "falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n"
+ "lamp.energy = 0.0\n"
+ "falloff_node.inputs[0].default_value = %f\n"
+ "hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n"
+ "hue_sat_node.inputs[1].default_value = 1.25\n"
+ "hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n"
+ "lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n"
+ "lamp_obj.location = (%f,%f,%f)\n"
+ "bpy.context.scene.objects.link(lamp_obj)\n"
+ "\n",
+ s, light.lightType, light.q / 8.f, light.color.simd[0], light.color.simd[1], light.color.simd[2],
+ light.position.simd[0], light.position.simd[1], light.position.simd[2]);
- switch (light.falloff)
- {
- case BabeDeadLight::Falloff::Constant:
- os << "falloff_node.inputs[0].default_value *= 150.0\n"
- "lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
- if (light.q > FLT_EPSILON)
- os.format("lamp.constant_coefficient = 2.0 / %f\n", light.q);
- break;
- case BabeDeadLight::Falloff::Linear:
- os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n";
- if (light.q > FLT_EPSILON)
- os.format("lamp.linear_coefficient = 250 / %f\n", light.q);
- break;
- case BabeDeadLight::Falloff::Quadratic:
- os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n";
- if (light.q > FLT_EPSILON)
- os.format("lamp.quadratic_coefficient = 25000 / %f\n", light.q);
- break;
- default: break;
- }
+ switch (light.falloff) {
+ case BabeDeadLight::Falloff::Constant:
+ os << "falloff_node.inputs[0].default_value *= 150.0\n"
+ "lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
+ if (light.q > FLT_EPSILON)
+ os.format("lamp.constant_coefficient = 2.0 / %f\n", light.q);
+ break;
+ case BabeDeadLight::Falloff::Linear:
+ os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n";
+ if (light.q > FLT_EPSILON)
+ os.format("lamp.linear_coefficient = 250 / %f\n", light.q);
+ break;
+ case BabeDeadLight::Falloff::Quadratic:
+ os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n";
+ if (light.q > FLT_EPSILON)
+ os.format("lamp.quadratic_coefficient = 25000 / %f\n", light.q);
+ break;
+ default:
+ break;
+ }
}
-template void ReadBabeDeadLightToBlender
-(hecl::blender::PyOutStream& os, const DNAMP1::MREA::BabeDeadLight& light, unsigned s, unsigned l);
-template void ReadBabeDeadLightToBlender
-(hecl::blender::PyOutStream& os, const DNAMP3::MREA::BabeDeadLight& light, unsigned s, unsigned l);
+template void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os,
+ const DNAMP1::MREA::BabeDeadLight& light,
+ unsigned s, unsigned l);
+template void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os,
+ const DNAMP3::MREA::BabeDeadLight& light,
+ unsigned s, unsigned l);
-template
-void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn)
-{
- using InterType = hecl::blender::Light::Type;
- switch (lightIn.type)
- {
- case InterType::Ambient:
- lightOut.lightType = BabeDeadLight::LightType::LocalAmbient;
- break;
- case InterType::Directional:
- lightOut.lightType = BabeDeadLight::LightType::Directional;
- break;
- case InterType::Custom:
- default:
- lightOut.lightType = BabeDeadLight::LightType::Custom;
- break;
- case InterType::Spot:
- lightOut.lightType = BabeDeadLight::LightType::Spot;
- break;
- }
+template
+void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn) {
+ using InterType = hecl::blender::Light::Type;
+ switch (lightIn.type) {
+ case InterType::Ambient:
+ lightOut.lightType = BabeDeadLight::LightType::LocalAmbient;
+ break;
+ case InterType::Directional:
+ lightOut.lightType = BabeDeadLight::LightType::Directional;
+ break;
+ case InterType::Custom:
+ default:
+ lightOut.lightType = BabeDeadLight::LightType::Custom;
+ break;
+ case InterType::Spot:
+ lightOut.lightType = BabeDeadLight::LightType::Spot;
+ break;
+ }
- if (lightIn.type == InterType::Ambient)
- {
- lightOut.falloff = BabeDeadLight::Falloff::Constant;
- lightOut.q = lightIn.energy * 8.f;
- }
- else if (lightIn.linear > lightIn.constant &&
- lightIn.linear > lightIn.quadratic)
- {
- lightOut.falloff = BabeDeadLight::Falloff::Linear;
- lightOut.q = 250.f / lightIn.linear;
- }
- else if (lightIn.quadratic > lightIn.constant &&
- lightIn.quadratic > lightIn.linear)
- {
- lightOut.falloff = BabeDeadLight::Falloff::Quadratic;
- lightOut.q = 25000.f / lightIn.quadratic;
- }
- else
- {
- lightOut.falloff = BabeDeadLight::Falloff::Constant;
- lightOut.q = 2.f / lightIn.constant;
- }
+ if (lightIn.type == InterType::Ambient) {
+ lightOut.falloff = BabeDeadLight::Falloff::Constant;
+ lightOut.q = lightIn.energy * 8.f;
+ } else if (lightIn.linear > lightIn.constant && lightIn.linear > lightIn.quadratic) {
+ lightOut.falloff = BabeDeadLight::Falloff::Linear;
+ lightOut.q = 250.f / lightIn.linear;
+ } else if (lightIn.quadratic > lightIn.constant && lightIn.quadratic > lightIn.linear) {
+ lightOut.falloff = BabeDeadLight::Falloff::Quadratic;
+ lightOut.q = 25000.f / lightIn.quadratic;
+ } else {
+ lightOut.falloff = BabeDeadLight::Falloff::Constant;
+ lightOut.q = 2.f / lightIn.constant;
+ }
- lightOut.color = lightIn.color;
- lightOut.spotCutoff = zeus::radToDeg(lightIn.spotCutoff);
- lightOut.castShadows = lightIn.shadow;
- lightOut.position.simd[0] = lightIn.sceneXf[0].simd[3];
- lightOut.position.simd[1] = lightIn.sceneXf[1].simd[3];
- lightOut.position.simd[2] = lightIn.sceneXf[2].simd[3];
+ lightOut.color = lightIn.color;
+ lightOut.spotCutoff = zeus::radToDeg(lightIn.spotCutoff);
+ lightOut.castShadows = lightIn.shadow;
+ lightOut.position.simd[0] = lightIn.sceneXf[0].simd[3];
+ lightOut.position.simd[1] = lightIn.sceneXf[1].simd[3];
+ lightOut.position.simd[2] = lightIn.sceneXf[2].simd[3];
- zeus::CTransform lightXf(&lightIn.sceneXf[0]);
- lightOut.direction = (lightXf.basis.transposed() * zeus::CVector3f(0.f, 0.f, -1.f)).normalized();
+ zeus::CTransform lightXf(&lightIn.sceneXf[0]);
+ lightOut.direction = (lightXf.basis.transposed() * zeus::CVector3f(0.f, 0.f, -1.f)).normalized();
}
-template void WriteBabeDeadLightFromBlender
-(DNAMP1::MREA::BabeDeadLight& lightOut, const hecl::blender::Light& lightIn);
-template void WriteBabeDeadLightFromBlender
-(DNAMP3::MREA::BabeDeadLight& lightOut, const hecl::blender::Light& lightIn);
+template void WriteBabeDeadLightFromBlender(DNAMP1::MREA::BabeDeadLight& lightOut,
+ const hecl::blender::Light& lightIn);
+template void WriteBabeDeadLightFromBlender(DNAMP3::MREA::BabeDeadLight& lightOut,
+ const hecl::blender::Light& lightIn);
-}
+} // namespace DataSpec
diff --git a/DataSpec/DNACommon/BabeDead.hpp b/DataSpec/DNACommon/BabeDead.hpp
index 49e00ffa1..7ef2662b0 100644
--- a/DataSpec/DNACommon/BabeDead.hpp
+++ b/DataSpec/DNACommon/BabeDead.hpp
@@ -4,15 +4,12 @@
#include "hecl/hecl.hpp"
#include
-namespace DataSpec
-{
+namespace DataSpec {
-template
-void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os,
- const BabeDeadLight& light, unsigned s, unsigned l);
+template
+void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLight& light, unsigned s, unsigned l);
-template
+template
void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn);
-}
-
+} // namespace DataSpec
diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp
index f70b14c47..5fde36861 100644
--- a/DataSpec/DNACommon/CMDL.cpp
+++ b/DataSpec/DNACommon/CMDL.cpp
@@ -9,2494 +9,2261 @@
#include "zeus/CAABox.hpp"
#include "hecl/Blender/Connection.hpp"
-namespace DataSpec::DNACMDL
-{
+namespace DataSpec::DNACMDL {
template
-void GetVertexAttributes(const MaterialSet& matSet,
- std::vector& attributesOut)
-{
- attributesOut.clear();
- attributesOut.reserve(matSet.materials.size());
+void GetVertexAttributes(const MaterialSet& matSet, std::vector& attributesOut) {
+ attributesOut.clear();
+ attributesOut.reserve(matSet.materials.size());
- for (const typename MaterialSet::Material& mat : matSet.materials)
- {
- const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags();
- attributesOut.emplace_back();
- VertexAttributes& va = attributesOut.back();
+ for (const typename MaterialSet::Material& mat : matSet.materials) {
+ const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags();
+ attributesOut.emplace_back();
+ VertexAttributes& va = attributesOut.back();
- va.pos = vaFlags.position();
- va.norm = vaFlags.normal();
- va.color0 = vaFlags.color0();
- va.color1 = vaFlags.color1();
+ va.pos = vaFlags.position();
+ va.norm = vaFlags.normal();
+ va.color0 = vaFlags.color0();
+ va.color1 = vaFlags.color1();
- if ((va.uvs[0] = vaFlags.tex0()))
- ++va.uvCount;
- if ((va.uvs[1] = vaFlags.tex1()))
- ++va.uvCount;
- if ((va.uvs[2] = vaFlags.tex2()))
- ++va.uvCount;
- if ((va.uvs[3] = vaFlags.tex3()))
- ++va.uvCount;
- if ((va.uvs[4] = vaFlags.tex4()))
- ++va.uvCount;
- if ((va.uvs[5] = vaFlags.tex5()))
- ++va.uvCount;
- if ((va.uvs[6] = vaFlags.tex6()))
- ++va.uvCount;
+ if ((va.uvs[0] = vaFlags.tex0()))
+ ++va.uvCount;
+ if ((va.uvs[1] = vaFlags.tex1()))
+ ++va.uvCount;
+ if ((va.uvs[2] = vaFlags.tex2()))
+ ++va.uvCount;
+ if ((va.uvs[3] = vaFlags.tex3()))
+ ++va.uvCount;
+ if ((va.uvs[4] = vaFlags.tex4()))
+ ++va.uvCount;
+ if ((va.uvs[5] = vaFlags.tex5()))
+ ++va.uvCount;
+ if ((va.uvs[6] = vaFlags.tex6()))
+ ++va.uvCount;
- va.pnMtxIdx = vaFlags.pnMatIdx();
+ va.pnMtxIdx = vaFlags.pnMatIdx();
- if ((va.texMtxIdx[0] = vaFlags.tex0MatIdx()))
- ++va.texMtxIdxCount;
- if ((va.texMtxIdx[1] = vaFlags.tex1MatIdx()))
- ++va.texMtxIdxCount;
- if ((va.texMtxIdx[2] = vaFlags.tex2MatIdx()))
- ++va.texMtxIdxCount;
- if ((va.texMtxIdx[3] = vaFlags.tex3MatIdx()))
- ++va.texMtxIdxCount;
- if ((va.texMtxIdx[4] = vaFlags.tex4MatIdx()))
- ++va.texMtxIdxCount;
- if ((va.texMtxIdx[5] = vaFlags.tex5MatIdx()))
- ++va.texMtxIdxCount;
- if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx()))
- ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[0] = vaFlags.tex0MatIdx()))
+ ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[1] = vaFlags.tex1MatIdx()))
+ ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[2] = vaFlags.tex2MatIdx()))
+ ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[3] = vaFlags.tex3MatIdx()))
+ ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[4] = vaFlags.tex4MatIdx()))
+ ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[5] = vaFlags.tex5MatIdx()))
+ ++va.texMtxIdxCount;
+ if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx()))
+ ++va.texMtxIdxCount;
- va.shortUVs = mat.getFlags().lightmapUVArray();
- }
+ va.shortUVs = mat.getFlags().lightmapUVArray();
+ }
}
template
-void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os,
- const MaterialSet& matSet,
- const PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- unsigned setIdx)
-{
- /* Texmaps */
- os << "texmap_list = []\n";
- for (const UniqueID32& tex : matSet.head.textureIDs)
- {
- std::string texName = pakRouter.getBestEntryName(tex);
- const nod::Node* node;
- const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node);
- hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
- if (!txtrPath.isNone())
- {
- txtrPath.makeDirChain(false);
- PAKEntryReadStream rs = texEntry->beginReadStream(*node);
- TXTR::Extract(rs, txtrPath);
- }
- hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
- hecl::SystemUTF8Conv resPathView(resPath);
- os.format("if '%s' in bpy.data.textures:\n"
- " image = bpy.data.images['%s']\n"
- " texture = bpy.data.textures[image.name]\n"
- "else:\n"
- " image = bpy.data.images.load('''//%s''')\n"
- " image.name = '%s'\n"
- " texture = bpy.data.textures.new(image.name, 'IMAGE')\n"
- " texture.image = image\n"
- "texmap_list.append(texture)\n"
- "\n", texName.c_str(), texName.c_str(),
- resPathView.c_str(), texName.c_str());
+void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter,
+ const typename PAKRouter::EntryType& entry, unsigned setIdx) {
+ /* Texmaps */
+ os << "texmap_list = []\n";
+ for (const UniqueID32& tex : matSet.head.textureIDs) {
+ std::string texName = pakRouter.getBestEntryName(tex);
+ const nod::Node* node;
+ const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node);
+ hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
+ if (!txtrPath.isNone()) {
+ txtrPath.makeDirChain(false);
+ PAKEntryReadStream rs = texEntry->beginReadStream(*node);
+ TXTR::Extract(rs, txtrPath);
}
+ hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
+ hecl::SystemUTF8Conv resPathView(resPath);
+ os.format(
+ "if '%s' in bpy.data.textures:\n"
+ " image = bpy.data.images['%s']\n"
+ " texture = bpy.data.textures[image.name]\n"
+ "else:\n"
+ " image = bpy.data.images.load('''//%s''')\n"
+ " image.name = '%s'\n"
+ " texture = bpy.data.textures.new(image.name, 'IMAGE')\n"
+ " texture.image = image\n"
+ "texmap_list.append(texture)\n"
+ "\n",
+ texName.c_str(), texName.c_str(), resPathView.c_str(), texName.c_str());
+ }
- unsigned m=0;
- for (const typename MaterialSet::Material& mat : matSet.materials)
- {
- MaterialSet::ConstructMaterial(os, mat, setIdx, m++);
- os << "materials.append(new_material)\n";
- }
+ unsigned m = 0;
+ for (const typename MaterialSet::Material& mat : matSet.materials) {
+ MaterialSet::ConstructMaterial(os, mat, setIdx, m++);
+ os << "materials.append(new_material)\n";
+ }
}
template
-void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os,
- const MaterialSet& matSet,
- const PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- unsigned setIdx)
-{
- unsigned m=0;
- for (const typename MaterialSet::Material& mat : matSet.materials)
- {
- MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++);
- os << "materials.append(new_material)\n";
- }
+void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter,
+ const typename PAKRouter::EntryType& entry, unsigned setIdx) {
+ unsigned m = 0;
+ for (const typename MaterialSet::Material& mat : matSet.materials) {
+ MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++);
+ os << "materials.append(new_material)\n";
+ }
}
-template void ReadMaterialSetToBlender_3, DNAMP3::MaterialSet>
-(hecl::blender::PyOutStream& os,
- const DNAMP3::MaterialSet& matSet,
- const PAKRouter& pakRouter,
- const PAKRouter::EntryType& entry,
- unsigned setIdx);
+template void ReadMaterialSetToBlender_3, DNAMP3::MaterialSet>(
+ hecl::blender::PyOutStream& os, const DNAMP3::MaterialSet& matSet, const PAKRouter& pakRouter,
+ const PAKRouter::EntryType& entry, unsigned setIdx);
-class DLReader
-{
+class DLReader {
public:
- /* Class used for splitting verts with shared positions but different skinning matrices */
- class ExtraVertTracker
- {
- std::map>> m_extraVerts;
- atUint16 m_maxBasePos = 0;
- atUint16 m_nextOverPos = 1;
- public:
- atInt16 addPosSkinPair(atUint16 pos, atInt16 skin)
- {
- m_maxBasePos = std::max(m_maxBasePos, pos);
- auto search = m_extraVerts.find(pos);
- if (search == m_extraVerts.end())
- {
- m_extraVerts[pos] = {std::make_pair(skin, 0)};
- return skin;
- }
- std::vector>& vertTrack = search->second;
- for (const std::pair& s : vertTrack)
- if (s.first == skin)
- return vertTrack.front().first;
- vertTrack.push_back(std::make_pair(skin, m_nextOverPos++));
- return vertTrack.front().first;
- }
+ /* Class used for splitting verts with shared positions but different skinning matrices */
+ class ExtraVertTracker {
+ std::map>> m_extraVerts;
+ atUint16 m_maxBasePos = 0;
+ atUint16 m_nextOverPos = 1;
- template
- atUint32 sendAdditionalVertsToBlender(hecl::blender::PyOutStream& os,
- const RigPair& rp, atUint32 baseVert) const
- {
- atUint32 addedVerts = 0;
- atUint32 nextVert = 1;
- while (nextVert < m_nextOverPos)
- {
- for (const std::pair>>& ev : m_extraVerts)
- {
- for (const std::pair& se : ev.second)
- {
- if (se.second == nextVert)
- {
- os.format("bm.verts.ensure_lookup_table()\n"
- "orig_vert = bm.verts[%u]\n"
- "vert = bm.verts.new(orig_vert.co)\n",
- ev.first + baseVert);
- rp.first->weightVertex(os, *rp.second, se.first);
- ++nextVert;
- ++addedVerts;
- }
- }
- }
- }
- return addedVerts;
- }
+ public:
+ atInt16 addPosSkinPair(atUint16 pos, atInt16 skin) {
+ m_maxBasePos = std::max(m_maxBasePos, pos);
+ auto search = m_extraVerts.find(pos);
+ if (search == m_extraVerts.end()) {
+ m_extraVerts[pos] = {std::make_pair(skin, 0)};
+ return skin;
+ }
+ std::vector>& vertTrack = search->second;
+ for (const std::pair& s : vertTrack)
+ if (s.first == skin)
+ return vertTrack.front().first;
+ vertTrack.push_back(std::make_pair(skin, m_nextOverPos++));
+ return vertTrack.front().first;
+ }
- atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const
- {
- auto search = m_extraVerts.find(pos);
- if (search == m_extraVerts.end())
- return -1;
- const std::vector>& vertTrack = search->second;
- if (vertTrack.front().first == skin)
- return pos;
- for (auto it=vertTrack.begin()+1 ; it!=vertTrack.end() ; ++it)
- if (it->first == skin)
- return m_maxBasePos + it->second;
- return -1;
+ template
+ atUint32 sendAdditionalVertsToBlender(hecl::blender::PyOutStream& os, const RigPair& rp, atUint32 baseVert) const {
+ atUint32 addedVerts = 0;
+ atUint32 nextVert = 1;
+ while (nextVert < m_nextOverPos) {
+ for (const std::pair>>& ev : m_extraVerts) {
+ for (const std::pair& se : ev.second) {
+ if (se.second == nextVert) {
+ os.format(
+ "bm.verts.ensure_lookup_table()\n"
+ "orig_vert = bm.verts[%u]\n"
+ "vert = bm.verts.new(orig_vert.co)\n",
+ ev.first + baseVert);
+ rp.first->weightVertex(os, *rp.second, se.first);
+ ++nextVert;
+ ++addedVerts;
+ }
+ }
}
- };
+ }
+ return addedVerts;
+ }
+
+ atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const {
+ auto search = m_extraVerts.find(pos);
+ if (search == m_extraVerts.end())
+ return -1;
+ const std::vector>& vertTrack = search->second;
+ if (vertTrack.front().first == skin)
+ return pos;
+ for (auto it = vertTrack.begin() + 1; it != vertTrack.end(); ++it)
+ if (it->first == skin)
+ return m_maxBasePos + it->second;
+ return -1;
+ }
+ };
private:
- const VertexAttributes& m_va;
- std::unique_ptr m_dl;
- size_t m_dlSize;
- ExtraVertTracker& m_evt;
- const atInt16* m_bankIn;
- atUint8* m_cur;
- atUint16 readVal(GX::AttrType type)
- {
- atUint16 retval = 0;
- switch (type)
- {
- case GX::DIRECT:
- case GX::INDEX8:
- if ((m_cur - m_dl.get()) >= intptr_t(m_dlSize))
- return 0;
- retval = *m_cur;
- ++m_cur;
- break;
- case GX::INDEX16:
- if ((m_cur - m_dl.get() + 1) >= intptr_t(m_dlSize))
- return 0;
- retval = hecl::SBig(*(atUint16*)m_cur);
- m_cur += 2;
- break;
- default: break;
- }
- return retval;
+ const VertexAttributes& m_va;
+ std::unique_ptr m_dl;
+ size_t m_dlSize;
+ ExtraVertTracker& m_evt;
+ const atInt16* m_bankIn;
+ atUint8* m_cur;
+ atUint16 readVal(GX::AttrType type) {
+ atUint16 retval = 0;
+ switch (type) {
+ case GX::DIRECT:
+ case GX::INDEX8:
+ if ((m_cur - m_dl.get()) >= intptr_t(m_dlSize))
+ return 0;
+ retval = *m_cur;
+ ++m_cur;
+ break;
+ case GX::INDEX16:
+ if ((m_cur - m_dl.get() + 1) >= intptr_t(m_dlSize))
+ return 0;
+ retval = hecl::SBig(*(atUint16*)m_cur);
+ m_cur += 2;
+ break;
+ default:
+ break;
}
+ return retval;
+ }
+
public:
- DLReader(const VertexAttributes& va, std::unique_ptr&& dl,
- size_t dlSize, ExtraVertTracker& evt, const atInt16* bankIn=nullptr)
- : m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize), m_evt(evt), m_bankIn(bankIn)
- {
- m_cur = m_dl.get();
+ DLReader(const VertexAttributes& va, std::unique_ptr&& dl, size_t dlSize, ExtraVertTracker& evt,
+ const atInt16* bankIn = nullptr)
+ : m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize), m_evt(evt), m_bankIn(bankIn) {
+ m_cur = m_dl.get();
+ }
+
+ operator bool() { return ((m_cur - m_dl.get()) < intptr_t(m_dlSize)) && *m_cur; }
+
+ GX::Primitive readPrimitive() { return GX::Primitive(*m_cur++ & 0xf8); }
+
+ GX::Primitive readPrimitiveAndVat(unsigned& vatOut) {
+ atUint8 val = *m_cur++;
+ vatOut = val & 0x7;
+ return GX::Primitive(val & 0xf8);
+ }
+
+ atUint16 readVertCount() {
+ atUint16 retval = hecl::SBig(*(atUint16*)m_cur);
+ m_cur += 2;
+ return retval;
+ }
+
+ struct DLPrimVert {
+ atUint16 pos = 0;
+ atUint16 norm = 0;
+ atUint16 color[2] = {0};
+ atUint16 uvs[7] = {0};
+ atUint8 pnMtxIdx = 0;
+ atUint8 texMtxIdx[7] = {0};
+ };
+
+ DLPrimVert readVert(bool peek = false) {
+ atUint8* bakCur = m_cur;
+ DLPrimVert retval;
+ retval.pnMtxIdx = readVal(m_va.pnMtxIdx);
+ retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]);
+ retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]);
+ retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]);
+ retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]);
+ retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]);
+ retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]);
+ retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]);
+ if (m_bankIn) {
+ atUint16 posIdx = readVal(m_va.pos);
+ atUint8 mtxIdx = retval.pnMtxIdx / 3;
+ atInt16 skinIdx = -1;
+ if (mtxIdx < 10)
+ skinIdx = m_bankIn[mtxIdx];
+ retval.pos = m_evt.lookupVertIdx(posIdx, skinIdx);
+ } else
+ retval.pos = readVal(m_va.pos);
+ retval.norm = readVal(m_va.norm);
+ retval.color[0] = readVal(m_va.color0);
+ retval.color[1] = readVal(m_va.color1);
+ retval.uvs[0] = readVal(m_va.uvs[0]);
+ retval.uvs[1] = readVal(m_va.uvs[1]);
+ retval.uvs[2] = readVal(m_va.uvs[2]);
+ retval.uvs[3] = readVal(m_va.uvs[3]);
+ retval.uvs[4] = readVal(m_va.uvs[4]);
+ retval.uvs[5] = readVal(m_va.uvs[5]);
+ retval.uvs[6] = readVal(m_va.uvs[6]);
+ if (peek)
+ m_cur = bakCur;
+ return retval;
+ }
+
+ void preReadMaxIdxs(DLPrimVert& out) {
+ atUint8* bakCur = m_cur;
+ while (*this) {
+ readPrimitive();
+ atUint16 vc = readVertCount();
+ for (atUint16 v = 0; v < vc; ++v) {
+ atUint16 val;
+ val = readVal(m_va.pnMtxIdx);
+ out.pnMtxIdx = std::max(out.pnMtxIdx, atUint8(val));
+ val = readVal(m_va.texMtxIdx[0]);
+ out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
+ val = readVal(m_va.texMtxIdx[1]);
+ out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val));
+ val = readVal(m_va.texMtxIdx[2]);
+ out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
+ val = readVal(m_va.texMtxIdx[3]);
+ out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val));
+ val = readVal(m_va.texMtxIdx[4]);
+ out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
+ val = readVal(m_va.texMtxIdx[5]);
+ out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val));
+ val = readVal(m_va.texMtxIdx[6]);
+ out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
+ val = readVal(m_va.pos);
+ out.pos = std::max(out.pos, val);
+ val = readVal(m_va.norm);
+ out.norm = std::max(out.norm, val);
+ val = readVal(m_va.color0);
+ out.color[0] = std::max(out.color[0], val);
+ val = readVal(m_va.color1);
+ out.color[1] = std::max(out.color[1], val);
+ val = readVal(m_va.uvs[0]);
+ out.uvs[0] = std::max(out.uvs[0], val);
+ val = readVal(m_va.uvs[1]);
+ out.uvs[1] = std::max(out.uvs[1], val);
+ val = readVal(m_va.uvs[2]);
+ out.uvs[2] = std::max(out.uvs[2], val);
+ val = readVal(m_va.uvs[3]);
+ out.uvs[3] = std::max(out.uvs[3], val);
+ val = readVal(m_va.uvs[4]);
+ out.uvs[4] = std::max(out.uvs[4], val);
+ val = readVal(m_va.uvs[5]);
+ out.uvs[5] = std::max(out.uvs[5], val);
+ val = readVal(m_va.uvs[6]);
+ out.uvs[6] = std::max(out.uvs[6], val);
+ }
}
+ m_cur = bakCur;
+ }
- operator bool()
- {
- return ((m_cur - m_dl.get()) < intptr_t(m_dlSize)) && *m_cur;
- }
-
- GX::Primitive readPrimitive()
- {
- return GX::Primitive(*m_cur++ & 0xf8);
- }
-
- GX::Primitive readPrimitiveAndVat(unsigned& vatOut)
- {
- atUint8 val = *m_cur++;
- vatOut = val & 0x7;
- return GX::Primitive(val & 0xf8);
- }
-
- atUint16 readVertCount()
- {
- atUint16 retval = hecl::SBig(*(atUint16*)m_cur);
- m_cur += 2;
- return retval;
- }
-
- struct DLPrimVert
- {
- atUint16 pos = 0;
- atUint16 norm = 0;
- atUint16 color[2] = {0};
- atUint16 uvs[7] = {0};
- atUint8 pnMtxIdx = 0;
- atUint8 texMtxIdx[7] = {0};
- };
-
- DLPrimVert readVert(bool peek=false)
- {
- atUint8* bakCur = m_cur;
- DLPrimVert retval;
- retval.pnMtxIdx = readVal(m_va.pnMtxIdx);
- retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]);
- retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]);
- retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]);
- retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]);
- retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]);
- retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]);
- retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]);
- if (m_bankIn)
- {
- atUint16 posIdx = readVal(m_va.pos);
- atUint8 mtxIdx = retval.pnMtxIdx / 3;
- atInt16 skinIdx = -1;
- if (mtxIdx < 10)
- skinIdx = m_bankIn[mtxIdx];
- retval.pos = m_evt.lookupVertIdx(posIdx, skinIdx);
- }
- else
- retval.pos = readVal(m_va.pos);
- retval.norm = readVal(m_va.norm);
- retval.color[0] = readVal(m_va.color0);
- retval.color[1] = readVal(m_va.color1);
- retval.uvs[0] = readVal(m_va.uvs[0]);
- retval.uvs[1] = readVal(m_va.uvs[1]);
- retval.uvs[2] = readVal(m_va.uvs[2]);
- retval.uvs[3] = readVal(m_va.uvs[3]);
- retval.uvs[4] = readVal(m_va.uvs[4]);
- retval.uvs[5] = readVal(m_va.uvs[5]);
- retval.uvs[6] = readVal(m_va.uvs[6]);
- if (peek)
- m_cur = bakCur;
- return retval;
- }
-
- void preReadMaxIdxs(DLPrimVert& out)
- {
- atUint8* bakCur = m_cur;
- while (*this)
- {
- readPrimitive();
- atUint16 vc = readVertCount();
- for (atUint16 v=0 ; v& skinOut)
- {
- atUint8* bakCur = m_cur;
- while (*this)
- {
- readPrimitive();
- atUint16 vc = readVertCount();
- for (atUint16 v=0 ; v& skinOut) {
+ atUint8* bakCur = m_cur;
+ while (*this) {
+ readPrimitive();
+ atUint16 vc = readVertCount();
+ for (atUint16 v = 0; v < vc; ++v) {
+ atUint16 val;
+ atUint8 pnMtxVal = readVal(m_va.pnMtxIdx);
+ out.pnMtxIdx = std::max(out.pnMtxIdx, pnMtxVal);
+ val = readVal(m_va.texMtxIdx[0]);
+ out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val));
+ val = readVal(m_va.texMtxIdx[1]);
+ out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val));
+ val = readVal(m_va.texMtxIdx[2]);
+ out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val));
+ val = readVal(m_va.texMtxIdx[3]);
+ out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val));
+ val = readVal(m_va.texMtxIdx[4]);
+ out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val));
+ val = readVal(m_va.texMtxIdx[5]);
+ out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val));
+ val = readVal(m_va.texMtxIdx[6]);
+ out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val));
+ atUint16 posVal = readVal(m_va.pos);
+ out.pos = std::max(out.pos, posVal);
+ val = readVal(m_va.norm);
+ out.norm = std::max(out.norm, val);
+ val = readVal(m_va.color0);
+ out.color[0] = std::max(out.color[0], val);
+ val = readVal(m_va.color1);
+ out.color[1] = std::max(out.color[1], val);
+ val = readVal(m_va.uvs[0]);
+ out.uvs[0] = std::max(out.uvs[0], val);
+ val = readVal(m_va.uvs[1]);
+ out.uvs[1] = std::max(out.uvs[1], val);
+ val = readVal(m_va.uvs[2]);
+ out.uvs[2] = std::max(out.uvs[2], val);
+ val = readVal(m_va.uvs[3]);
+ out.uvs[3] = std::max(out.uvs[3], val);
+ val = readVal(m_va.uvs[4]);
+ out.uvs[4] = std::max(out.uvs[4], val);
+ val = readVal(m_va.uvs[5]);
+ out.uvs[5] = std::max(out.uvs[5], val);
+ val = readVal(m_va.uvs[6]);
+ out.uvs[6] = std::max(out.uvs[6], val);
+
+ atInt16 skinIdx = m_bankIn[pnMtxVal / 3];
+ skinOut[posVal] = m_evt.addPosSkinPair(posVal, skinIdx);
+ }
}
+ m_cur = bakCur;
+ }
};
-void InitGeomBlenderContext(hecl::blender::PyOutStream& os,
- const hecl::ProjectPath& masterShaderPath,
- bool solidShading)
-{
- os << "import math\n"
- "from mathutils import Vector\n"
- "\n"
- "# Using 'Blender Game'\n"
- "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
- "\n"
- "# Clear Scene\n"
- "for ob in bpy.data.objects:\n"
- " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
- " bpy.context.scene.objects.unlink(ob)\n"
- " bpy.data.objects.remove(ob)\n"
- "\n"
- "def loop_from_facevert(bm, face, vert_idx):\n"
- " for loop in face.loops:\n"
- " if loop.vert[bm.verts.layers.int['CMDLOriginalPosIdxs']] == vert_idx:\n"
- " return loop\n"
- "\n"
- "def loops_from_edgevert(bm, edge, vert):\n"
- " ret = []\n"
- " for face in edge.link_faces:\n"
- " for loop in face.loops:\n"
- " if loop.vert == vert:\n"
- " ret.append(loop)\n"
- " return ret\n"
- "\n"
- "def add_triangle(bm, vert_seq, vert_indices, norm_seq, norm_indices, mat_nr, od_list, two_face_vert):\n"
- " if len(set(vert_indices)) != 3:\n"
- " return None, None\n"
- "\n"
- " ret_mesh = bm\n"
- " vert_seq.ensure_lookup_table()\n"
- " verts = [vert_seq[i] for i in vert_indices]\n"
- "\n"
- " # Try getting existing face\n"
- " face = bm.faces.get(verts)\n"
- "\n"
- " if face is not None and face.material_index != mat_nr: # Same poly, new material\n"
- " # Overdraw detected; track copy\n"
- " od_entry = None\n"
- " for entry in od_list:\n"
- " if entry['material'] == mat_nr:\n"
- " od_entry = entry\n"
- " if od_entry is None:\n"
- " bm_cpy = bm.copy()\n"
- " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n"
- " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n"
- " od_list.append(od_entry)\n"
- " od_entry['bm'].verts.ensure_lookup_table()\n"
- " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n"
- " face = od_entry['bm'].faces.get(verts)\n"
- " if face is None:\n"
- " face = od_entry['bm'].faces.new(verts)\n"
- " else: # Probably a double-sided surface\n"
- " verts = [od_entry['bm'].verts[i + two_face_vert] for i in vert_indices]\n"
- " face = od_entry['bm'].faces.get(verts)\n"
- " if face is None:\n"
- " face = od_entry['bm'].faces.new(verts)\n"
- " ret_mesh = od_entry['bm']\n"
- "\n"
- " elif face is not None: # Same material, probably double-sided\n"
- " verts = [vert_seq[i + two_face_vert] for i in vert_indices]\n"
- " face = bm.faces.get(verts)\n"
- " if face is None:\n"
- " face = bm.faces.new(verts)\n"
- "\n"
- " else: # Make totally new face\n"
- " face = bm.faces.new(verts)\n"
- "\n"
- " for i in range(3):\n"
- " face.verts[i][ret_mesh.verts.layers.int['CMDLOriginalPosIdxs']] = vert_indices[i]\n"
- " face.loops[i][ret_mesh.loops.layers.int['CMDLOriginalNormIdxs']] = norm_indices[i]\n"
- " face.material_index = mat_nr\n"
- " face.smooth = True\n"
- "\n"
- " return face, ret_mesh\n"
- "\n"
- "def expand_lightmap_triangle(lightmap_tri_tracker, uva, uvb, uvc):\n"
- " result = ([uva[0],uva[1]], [uvb[0],uvb[1]], [uvc[0],uvc[1]])\n"
- " inst = 0\n"
- " if uva in lightmap_tri_tracker:\n"
- " inst = lightmap_tri_tracker[uva]\n"
- " lightmap_tri_tracker[uva] = inst + 1\n"
- " if uva == uvb:\n"
- " result[1][0] += 0.005\n"
- " if uva == uvc:\n"
- " result[2][1] -= 0.005\n"
- " if inst & 0x1 and uva == uvb and uva == uvc:\n"
- " result[0][0] += 0.005\n"
- " result[0][1] -= 0.005\n"
- " return result\n"
- "\n";
+void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath,
+ bool solidShading) {
+ os << "import math\n"
+ "from mathutils import Vector\n"
+ "\n"
+ "# Using 'Blender Game'\n"
+ "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
+ "\n"
+ "# Clear Scene\n"
+ "for ob in bpy.data.objects:\n"
+ " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
+ " bpy.context.scene.objects.unlink(ob)\n"
+ " bpy.data.objects.remove(ob)\n"
+ "\n"
+ "def loop_from_facevert(bm, face, vert_idx):\n"
+ " for loop in face.loops:\n"
+ " if loop.vert[bm.verts.layers.int['CMDLOriginalPosIdxs']] == vert_idx:\n"
+ " return loop\n"
+ "\n"
+ "def loops_from_edgevert(bm, edge, vert):\n"
+ " ret = []\n"
+ " for face in edge.link_faces:\n"
+ " for loop in face.loops:\n"
+ " if loop.vert == vert:\n"
+ " ret.append(loop)\n"
+ " return ret\n"
+ "\n"
+ "def add_triangle(bm, vert_seq, vert_indices, norm_seq, norm_indices, mat_nr, od_list, two_face_vert):\n"
+ " if len(set(vert_indices)) != 3:\n"
+ " return None, None\n"
+ "\n"
+ " ret_mesh = bm\n"
+ " vert_seq.ensure_lookup_table()\n"
+ " verts = [vert_seq[i] for i in vert_indices]\n"
+ "\n"
+ " # Try getting existing face\n"
+ " face = bm.faces.get(verts)\n"
+ "\n"
+ " if face is not None and face.material_index != mat_nr: # Same poly, new material\n"
+ " # Overdraw detected; track copy\n"
+ " od_entry = None\n"
+ " for entry in od_list:\n"
+ " if entry['material'] == mat_nr:\n"
+ " od_entry = entry\n"
+ " if od_entry is None:\n"
+ " bm_cpy = bm.copy()\n"
+ " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n"
+ " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n"
+ " od_list.append(od_entry)\n"
+ " od_entry['bm'].verts.ensure_lookup_table()\n"
+ " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n"
+ " face = od_entry['bm'].faces.get(verts)\n"
+ " if face is None:\n"
+ " face = od_entry['bm'].faces.new(verts)\n"
+ " else: # Probably a double-sided surface\n"
+ " verts = [od_entry['bm'].verts[i + two_face_vert] for i in vert_indices]\n"
+ " face = od_entry['bm'].faces.get(verts)\n"
+ " if face is None:\n"
+ " face = od_entry['bm'].faces.new(verts)\n"
+ " ret_mesh = od_entry['bm']\n"
+ "\n"
+ " elif face is not None: # Same material, probably double-sided\n"
+ " verts = [vert_seq[i + two_face_vert] for i in vert_indices]\n"
+ " face = bm.faces.get(verts)\n"
+ " if face is None:\n"
+ " face = bm.faces.new(verts)\n"
+ "\n"
+ " else: # Make totally new face\n"
+ " face = bm.faces.new(verts)\n"
+ "\n"
+ " for i in range(3):\n"
+ " face.verts[i][ret_mesh.verts.layers.int['CMDLOriginalPosIdxs']] = vert_indices[i]\n"
+ " face.loops[i][ret_mesh.loops.layers.int['CMDLOriginalNormIdxs']] = norm_indices[i]\n"
+ " face.material_index = mat_nr\n"
+ " face.smooth = True\n"
+ "\n"
+ " return face, ret_mesh\n"
+ "\n"
+ "def expand_lightmap_triangle(lightmap_tri_tracker, uva, uvb, uvc):\n"
+ " result = ([uva[0],uva[1]], [uvb[0],uvb[1]], [uvc[0],uvc[1]])\n"
+ " inst = 0\n"
+ " if uva in lightmap_tri_tracker:\n"
+ " inst = lightmap_tri_tracker[uva]\n"
+ " lightmap_tri_tracker[uva] = inst + 1\n"
+ " if uva == uvb:\n"
+ " result[1][0] += 0.005\n"
+ " if uva == uvc:\n"
+ " result[2][1] -= 0.005\n"
+ " if inst & 0x1 and uva == uvb and uva == uvc:\n"
+ " result[0][0] += 0.005\n"
+ " result[0][1] -= 0.005\n"
+ " return result\n"
+ "\n";
- if (solidShading)
- {
- os << "for ar in bpy.context.screen.areas:\n"
- " for sp in ar.spaces:\n"
- " if sp.type == 'VIEW_3D':\n"
- " sp.viewport_shade = 'SOLID'\n";
- }
+ if (solidShading) {
+ os << "for ar in bpy.context.screen.areas:\n"
+ " for sp in ar.spaces:\n"
+ " if sp.type == 'VIEW_3D':\n"
+ " sp.viewport_shade = 'SOLID'\n";
+ }
- /* Link master shader library */
- os.format("# Master shader library\n"
- "with bpy.data.libraries.load('%s', link=True, relative=True) as (data_from, data_to):\n"
- " data_to.node_groups = data_from.node_groups\n"
- "\n", masterShaderPath.getAbsolutePathUTF8().data());
+ /* Link master shader library */
+ os.format(
+ "# Master shader library\n"
+ "with bpy.data.libraries.load('%s', link=True, relative=True) as (data_from, data_to):\n"
+ " data_to.node_groups = data_from.node_groups\n"
+ "\n",
+ masterShaderPath.getAbsolutePathUTF8().data());
}
-void FinishBlenderMesh(hecl::blender::PyOutStream& os,
- unsigned matSetCount, int meshIdx)
-{
- if (meshIdx < 0)
- os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name)\n"
- "obj = bpy.data.objects.new(mesh.name, mesh)\n"
- "obj.show_transparent = True\n"
- "bpy.context.scene.objects.link(obj)\n"
- "mesh.hecl_material_count = %u\n", matSetCount);
- else
- os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n"
- "obj = bpy.data.objects.new(mesh.name, mesh)\n"
- "obj.show_transparent = True\n"
- "bpy.context.scene.objects.link(obj)\n"
- "mesh.hecl_material_count = %u\n", meshIdx, matSetCount);
+void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx) {
+ if (meshIdx < 0)
+ os.format(
+ "mesh = bpy.data.meshes.new(bpy.context.scene.name)\n"
+ "obj = bpy.data.objects.new(mesh.name, mesh)\n"
+ "obj.show_transparent = True\n"
+ "bpy.context.scene.objects.link(obj)\n"
+ "mesh.hecl_material_count = %u\n",
+ matSetCount);
+ else
+ os.format(
+ "mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n"
+ "obj = bpy.data.objects.new(mesh.name, mesh)\n"
+ "obj.show_transparent = True\n"
+ "bpy.context.scene.objects.link(obj)\n"
+ "mesh.hecl_material_count = %u\n",
+ meshIdx, matSetCount);
- os << "mesh.use_auto_smooth = True\n"
- "mesh.auto_smooth_angle = math.pi\n"
- "mesh.show_edge_sharp = True\n"
- "\n"
- "for material in materials:\n"
- " mesh.materials.append(material)\n"
- "\n"
- "# Merge OD meshes\n"
- "for od_entry in od_list:\n"
- " vert_dict = [{},{}]\n"
- "\n"
- " for vert in od_entry['bm'].verts:\n"
- " if len(vert.link_faces):\n"
- " if vert.index >= two_face_vert:\n"
- " use_vert_dict = vert_dict[1]\n"
- " else:\n"
- " use_vert_dict = vert_dict[0]\n"
- " copy_vert = bm.verts.new(vert.co, vert)\n"
- " use_vert_dict[vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] = copy_vert\n"
- " copy_vert[orig_pidx_lay] = vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]\n"
- "\n"
- " for face in od_entry['bm'].faces:\n"
- " if face.verts[0].index >= two_face_vert:\n"
- " use_vert_dict = vert_dict[1]\n"
- " else:\n"
- " use_vert_dict = vert_dict[0]\n"
- " merge_verts = [use_vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in face.verts]\n"
- " if bm.faces.get(merge_verts) is not None:\n"
- " continue\n"
- " merge_face = bm.faces.new(merge_verts)\n"
- " for i in range(len(face.loops)):\n"
- " old = face.loops[i]\n"
- " new = merge_face.loops[i]\n"
- " for j in range(len(od_entry['bm'].loops.layers.uv)):\n"
- " new[bm.loops.layers.uv[j]] = old[od_entry['bm'].loops.layers.uv[j]]\n"
- " new[orig_nidx_lay] = old[od_entry['bm'].loops.layers.int['CMDLOriginalNormIdxs']]\n"
- " merge_face.smooth = True\n"
- " merge_face.material_index = face.material_index\n"
- "\n"
- " od_entry['bm'].free()\n"
- "\n"
- "verts_to_del = []\n"
- "for v in bm.verts:\n"
- " if len(v.link_faces) == 0:\n"
- " verts_to_del.append(v)\n"
- "bmesh.ops.delete(bm, geom=verts_to_del, context=1)\n"
- "\n"
- "for edge in bm.edges:\n"
- " if edge.is_manifold:\n"
- " pass_count = 0\n"
- " for vert in edge.verts:\n"
- " loops = loops_from_edgevert(bm, edge, vert)\n"
- " norm0 = Vector(norm_list[loops[0][orig_nidx_lay]])\n"
- " norm1 = Vector(norm_list[loops[1][orig_nidx_lay]])\n"
- " if norm0.dot(norm1) < 0.9:\n"
- " pass_count += 1\n"
- " if pass_count > 0:\n"
- " edge.smooth = False\n"
- "\n"
- "bm.to_mesh(mesh)\n"
- "bm.free()\n"
- "\n"
- "# Remove redundant materials\n"
- "present_mats = set()\n"
- "for poly in mesh.polygons:\n"
- " present_mats.add(poly.material_index)\n"
- "for mat_idx in reversed(range(len(mesh.materials))):\n"
- " if mat_idx not in present_mats:\n"
- " mesh.materials.pop(index=mat_idx, update_data=True)\n"
- "\n"
- "mesh.update()\n"
- "\n";
+ os << "mesh.use_auto_smooth = True\n"
+ "mesh.auto_smooth_angle = math.pi\n"
+ "mesh.show_edge_sharp = True\n"
+ "\n"
+ "for material in materials:\n"
+ " mesh.materials.append(material)\n"
+ "\n"
+ "# Merge OD meshes\n"
+ "for od_entry in od_list:\n"
+ " vert_dict = [{},{}]\n"
+ "\n"
+ " for vert in od_entry['bm'].verts:\n"
+ " if len(vert.link_faces):\n"
+ " if vert.index >= two_face_vert:\n"
+ " use_vert_dict = vert_dict[1]\n"
+ " else:\n"
+ " use_vert_dict = vert_dict[0]\n"
+ " copy_vert = bm.verts.new(vert.co, vert)\n"
+ " use_vert_dict[vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] = copy_vert\n"
+ " copy_vert[orig_pidx_lay] = vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]\n"
+ "\n"
+ " for face in od_entry['bm'].faces:\n"
+ " if face.verts[0].index >= two_face_vert:\n"
+ " use_vert_dict = vert_dict[1]\n"
+ " else:\n"
+ " use_vert_dict = vert_dict[0]\n"
+ " merge_verts = [use_vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in "
+ "face.verts]\n"
+ " if bm.faces.get(merge_verts) is not None:\n"
+ " continue\n"
+ " merge_face = bm.faces.new(merge_verts)\n"
+ " for i in range(len(face.loops)):\n"
+ " old = face.loops[i]\n"
+ " new = merge_face.loops[i]\n"
+ " for j in range(len(od_entry['bm'].loops.layers.uv)):\n"
+ " new[bm.loops.layers.uv[j]] = old[od_entry['bm'].loops.layers.uv[j]]\n"
+ " new[orig_nidx_lay] = old[od_entry['bm'].loops.layers.int['CMDLOriginalNormIdxs']]\n"
+ " merge_face.smooth = True\n"
+ " merge_face.material_index = face.material_index\n"
+ "\n"
+ " od_entry['bm'].free()\n"
+ "\n"
+ "verts_to_del = []\n"
+ "for v in bm.verts:\n"
+ " if len(v.link_faces) == 0:\n"
+ " verts_to_del.append(v)\n"
+ "bmesh.ops.delete(bm, geom=verts_to_del, context=1)\n"
+ "\n"
+ "for edge in bm.edges:\n"
+ " if edge.is_manifold:\n"
+ " pass_count = 0\n"
+ " for vert in edge.verts:\n"
+ " loops = loops_from_edgevert(bm, edge, vert)\n"
+ " norm0 = Vector(norm_list[loops[0][orig_nidx_lay]])\n"
+ " norm1 = Vector(norm_list[loops[1][orig_nidx_lay]])\n"
+ " if norm0.dot(norm1) < 0.9:\n"
+ " pass_count += 1\n"
+ " if pass_count > 0:\n"
+ " edge.smooth = False\n"
+ "\n"
+ "bm.to_mesh(mesh)\n"
+ "bm.free()\n"
+ "\n"
+ "# Remove redundant materials\n"
+ "present_mats = set()\n"
+ "for poly in mesh.polygons:\n"
+ " present_mats.add(poly.material_index)\n"
+ "for mat_idx in reversed(range(len(mesh.materials))):\n"
+ " if mat_idx not in present_mats:\n"
+ " mesh.materials.pop(index=mat_idx, update_data=True)\n"
+ "\n"
+ "mesh.update()\n"
+ "\n";
}
template
-atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os,
- athena::io::IStreamReader& reader,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const RigPair& rp,
- bool shortNormals,
- bool shortUVs,
- std::vector& vertAttribs,
- int meshIdx,
- atUint32 secCount,
- atUint32 matSetCount,
- const atUint32* secSizes,
- atUint32 surfaceCount)
-{
- os << "# Begin bmesh\n"
- "bm = bmesh.new()\n"
- "\n"
- "# Overdraw-tracking\n"
- "od_list = []\n"
- "\n"
- "orig_pidx_lay = bm.verts.layers.int.new('CMDLOriginalPosIdxs')\n"
- "orig_nidx_lay = bm.loops.layers.int.new('CMDLOriginalNormIdxs')\n"
- "\n"
- "lightmap_tri_tracker = {}\n";
+atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::IStreamReader& reader,
+ PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const RigPair& rp,
+ bool shortNormals, bool shortUVs, std::vector& vertAttribs,
+ int meshIdx, atUint32 secCount, atUint32 matSetCount, const atUint32* secSizes,
+ atUint32 surfaceCount) {
+ os << "# Begin bmesh\n"
+ "bm = bmesh.new()\n"
+ "\n"
+ "# Overdraw-tracking\n"
+ "od_list = []\n"
+ "\n"
+ "orig_pidx_lay = bm.verts.layers.int.new('CMDLOriginalPosIdxs')\n"
+ "orig_nidx_lay = bm.loops.layers.int.new('CMDLOriginalNormIdxs')\n"
+ "\n"
+ "lightmap_tri_tracker = {}\n";
- if (rp.first)
- os << "dvert_lay = bm.verts.layers.deform.verify()\n";
+ if (rp.first)
+ os << "dvert_lay = bm.verts.layers.deform.verify()\n";
- /* Pre-read pass to determine maximum used vert indices */
- atUint32 matSecCount = 0;
- if (matSetCount)
- matSecCount = MaterialSet::OneSection() ? 1 : matSetCount;
- bool visitedDLOffsets = false;
- atUint32 lastDlSec = secCount;
- atUint64 afterHeaderPos = reader.position();
- DLReader::DLPrimVert maxIdxs;
- std::vector skinIndices;
- DLReader::ExtraVertTracker extraTracker;
- for (size_t s=0 ; s skinIndices;
+ DLReader::ExtraVertTracker extraTracker;
+ for (size_t s = 0; s < lastDlSec; ++s) {
+ atUint64 secStart = reader.position();
+ if (s < matSecCount) {
+ if (!s) {
+ MaterialSet matSet;
+ matSet.read(reader);
+ matSet.ensureTexturesExtracted(pakRouter);
+ GetVertexAttributes(matSet, vertAttribs);
+ }
+ } else {
+ switch (s - matSecCount) {
+ case 0: {
+ /* Positions */
+ if (SurfaceHeader::UseMatrixSkinning() && rp.first)
+ skinIndices.assign(secSizes[s] / 12, -1);
+ break;
+ }
+ case 1: {
+ /* Normals */
+ break;
+ }
+ case 2: {
+ /* Colors */
+ break;
+ }
+ case 3: {
+ /* Float UVs */
+ break;
+ }
+ case 4: {
+ if (surfaceCount) {
+ /* MP3 MREA case */
+ visitedDLOffsets = true;
+ lastDlSec = 4 + surfaceCount;
+ } else {
+ /* Short UVs */
+ if (shortUVs)
+ break;
+
+ /* DL Offsets (here or next section) */
+ visitedDLOffsets = true;
+ lastDlSec = s + reader.readUint32Big() + 1;
+ break;
}
+ }
+ default: {
+ if (!visitedDLOffsets) {
+ visitedDLOffsets = true;
+ lastDlSec = s + reader.readUint32Big() + 1;
+ break;
+ }
+
+ /* GX Display List (surface) */
+ SurfaceHeader sHead;
+ sHead.read(reader);
+ const atInt16* bankIn = nullptr;
+ if (SurfaceHeader::UseMatrixSkinning() && rp.first)
+ bankIn = rp.first->getMatrixBank(sHead.skinMatrixBankIdx());
+
+ /* Do max index pre-read */
+ atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
+ DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize, extraTracker, bankIn);
+ if (SurfaceHeader::UseMatrixSkinning() && rp.first)
+ dl.preReadMaxIdxs(maxIdxs, skinIndices);
else
- {
- switch (s-matSecCount)
- {
- case 0:
- {
- /* Positions */
- if (SurfaceHeader::UseMatrixSkinning() && rp.first)
- skinIndices.assign(secSizes[s] / 12, -1);
- break;
- }
- case 1:
- {
- /* Normals */
- break;
- }
- case 2:
- {
- /* Colors */
- break;
- }
- case 3:
- {
- /* Float UVs */
- break;
- }
- case 4:
- {
- if (surfaceCount)
- {
- /* MP3 MREA case */
- visitedDLOffsets = true;
- lastDlSec = 4 + surfaceCount;
- }
- else
- {
- /* Short UVs */
- if (shortUVs)
- break;
-
- /* DL Offsets (here or next section) */
- visitedDLOffsets = true;
- lastDlSec = s + reader.readUint32Big() + 1;
- break;
- }
- }
- default:
- {
- if (!visitedDLOffsets)
- {
- visitedDLOffsets = true;
- lastDlSec = s + reader.readUint32Big() + 1;
- break;
- }
-
- /* GX Display List (surface) */
- SurfaceHeader sHead;
- sHead.read(reader);
- const atInt16* bankIn = nullptr;
- if (SurfaceHeader::UseMatrixSkinning() && rp.first)
- bankIn = rp.first->getMatrixBank(sHead.skinMatrixBankIdx());
-
- /* Do max index pre-read */
- atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
- DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize),
- realDlSize, extraTracker, bankIn);
- if (SurfaceHeader::UseMatrixSkinning() && rp.first)
- dl.preReadMaxIdxs(maxIdxs, skinIndices);
- else
- dl.preReadMaxIdxs(maxIdxs);
-
- }
- }
- }
-
- if (s < secCount - 1)
- reader.seek(secStart + secSizes[s], athena::Begin);
+ dl.preReadMaxIdxs(maxIdxs);
+ }
+ }
}
- reader.seek(afterHeaderPos, athena::Begin);
+ if (s < secCount - 1)
+ reader.seek(secStart + secSizes[s], athena::Begin);
+ }
- visitedDLOffsets = false;
- unsigned createdUVLayers = 0;
- unsigned surfIdx = 0;
+ reader.seek(afterHeaderPos, athena::Begin);
- for (size_t s=0 ; s positions;
+ positions.reserve(vertCount);
+ for (size_t i = 0; i <= maxIdxs.pos; ++i) {
+ positions.push_back(reader.readVec3fBig());
+ const atVec3f& pos = positions.back();
+ os.format("vert = bm.verts.new((%f,%f,%f))\n", pos.simd[0], pos.simd[1], pos.simd[2]);
+ if (rp.first) {
+ if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
+ rp.first->weightVertex(os, *rp.second, skinIndices[i]);
+ else if (!SurfaceHeader::UseMatrixSkinning())
+ rp.first->weightVertex(os, *rp.second, i);
+ }
}
- else
- {
- switch (s-matSecCount)
- {
- case 0:
- {
- /* Positions */
- atUint32 vertCount = maxIdxs.pos + 1;
- std::vector positions;
- positions.reserve(vertCount);
- for (size_t i=0 ; i<=maxIdxs.pos ; ++i)
- {
- positions.push_back(reader.readVec3fBig());
- const atVec3f& pos = positions.back();
- os.format("vert = bm.verts.new((%f,%f,%f))\n",
- pos.simd[0], pos.simd[1], pos.simd[2]);
- if (rp.first)
- {
- if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
- rp.first->weightVertex(os, *rp.second, skinIndices[i]);
- else if (!SurfaceHeader::UseMatrixSkinning())
- rp.first->weightVertex(os, *rp.second, i);
- }
- }
- if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
- vertCount += extraTracker.sendAdditionalVertsToBlender(os, rp, 0);
- os.format("two_face_vert = %u\n", vertCount);
- for (size_t i=0 ; i<=maxIdxs.pos ; ++i)
- {
- const atVec3f& pos = positions[i];
- os.format("vert = bm.verts.new((%f,%f,%f))\n",
- pos.simd[0], pos.simd[1], pos.simd[2]);
- if (rp.first)
- {
- if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
- rp.first->weightVertex(os, *rp.second, skinIndices[i]);
- else if (!SurfaceHeader::UseMatrixSkinning())
- rp.first->weightVertex(os, *rp.second, i);
- }
- }
- if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
- extraTracker.sendAdditionalVertsToBlender(os, rp, vertCount);
- break;
+ if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
+ vertCount += extraTracker.sendAdditionalVertsToBlender(os, rp, 0);
+ os.format("two_face_vert = %u\n", vertCount);
+ for (size_t i = 0; i <= maxIdxs.pos; ++i) {
+ const atVec3f& pos = positions[i];
+ os.format("vert = bm.verts.new((%f,%f,%f))\n", pos.simd[0], pos.simd[1], pos.simd[2]);
+ if (rp.first) {
+ if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
+ rp.first->weightVertex(os, *rp.second, skinIndices[i]);
+ else if (!SurfaceHeader::UseMatrixSkinning())
+ rp.first->weightVertex(os, *rp.second, i);
+ }
+ }
+ if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
+ extraTracker.sendAdditionalVertsToBlender(os, rp, vertCount);
+ break;
+ }
+ case 1: {
+ /* Normals */
+ os << "norm_list = []\n";
+ if (shortNormals) {
+ size_t normCount = secSizes[s] / 6;
+ for (size_t i = 0; i < normCount; ++i) {
+ float x = reader.readInt16Big() / 16384.0f;
+ float y = reader.readInt16Big() / 16384.0f;
+ float z = reader.readInt16Big() / 16384.0f;
+ os.format("norm_list.append((%f,%f,%f))\n", x, y, z);
+ }
+ } else {
+ size_t normCount = secSizes[s] / 12;
+ for (size_t i = 0; i < normCount; ++i) {
+ const atVec3f norm = reader.readVec3fBig();
+ os.format("norm_list.append((%f,%f,%f))\n", norm.simd[0], norm.simd[1], norm.simd[2]);
+ }
+ }
+ break;
+ }
+ case 2: {
+ /* Colors */
+ break;
+ }
+ case 3: {
+ /* Float UVs */
+ os << "uv_list = []\n";
+ size_t uvCount = secSizes[s] / 8;
+ for (size_t i = 0; i < uvCount; ++i) {
+ const atVec2f uv = reader.readVec2fBig();
+ os.format("uv_list.append((%f,%f))\n", uv.simd[0], uv.simd[1]);
+ }
+ break;
+ }
+ case 4: {
+ if (surfaceCount) {
+ /* MP3 MREA case */
+ visitedDLOffsets = true;
+ } else {
+ /* Short UVs */
+ os << "suv_list = []\n";
+ if (shortUVs) {
+ size_t uvCount = secSizes[s] / 4;
+ for (size_t i = 0; i < uvCount; ++i) {
+ float x = reader.readInt16Big() / 32768.0f;
+ float y = reader.readInt16Big() / 32768.0f;
+ os.format("suv_list.append((%f,%f))\n", x, y);
}
- case 1:
- {
- /* Normals */
- os << "norm_list = []\n";
- if (shortNormals)
- {
- size_t normCount = secSizes[s] / 6;
- for (size_t i=0 ; igetMatrixBank(sHead.skinMatrixBankIdx());
-
- os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++);
- if (matUVCount > createdUVLayers)
- {
- for (unsigned l=createdUVLayers ; l= vertCount - 3);
-
- /* Advance one prim vert */
- primVerts[c%3] = dl.readVert(peek);
- ++c;
- }
- }
- else if (ptype == GX::TRIANGLES)
- {
- for (int v=0 ; v= vertCount)
- break;
-
- /* Advance 3 Prim Verts */
- for (int pv=0 ; pv<3 ; ++pv)
- primVerts[pv] = dl.readVert();
- }
- }
- else if (ptype == GX::TRIANGLEFAN)
- {
- ++c;
- for (int v=0 ; v= vertCount)
- break;
-
- /* Advance one prim vert */
- primVerts[(c+2)%3] = dl.readVert();
- ++c;
- }
- }
- os << "\n";
- }
- }
- }
+ /* DL Offsets (here or next section) */
+ visitedDLOffsets = true;
+ break;
+ }
+ }
+ default: {
+ if (!visitedDLOffsets) {
+ visitedDLOffsets = true;
+ break;
}
- if (s < secCount - 1)
- reader.seek(secStart + secSizes[s], athena::Begin);
+ /* GX Display List (surface) */
+ SurfaceHeader sHead;
+ sHead.read(reader);
+ VertexAttributes& curVA = vertAttribs[sHead.matIdx];
+ unsigned matUVCount = curVA.uvCount;
+ bool matShortUVs = curVA.shortUVs;
+ const atInt16* bankIn = nullptr;
+ if (SurfaceHeader::UseMatrixSkinning() && rp.first)
+ bankIn = rp.first->getMatrixBank(sHead.skinMatrixBankIdx());
+
+ os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++);
+ if (matUVCount > createdUVLayers) {
+ for (unsigned l = createdUVLayers; l < matUVCount; ++l)
+ os.format("bm.loops.layers.uv.new('UV_%u')\n", l);
+ createdUVLayers = matUVCount;
+ }
+
+ atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
+ DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize, extraTracker, bankIn);
+
+ while (dl) {
+ GX::Primitive ptype = dl.readPrimitive();
+ atUint16 vertCount = dl.readVertCount();
+
+ /* First vert */
+ DLReader::DLPrimVert firstPrimVert = dl.readVert(true);
+
+ /* 3 Prim Verts to start */
+ int c = 0;
+ DLReader::DLPrimVert primVerts[3] = {dl.readVert(), dl.readVert(), dl.readVert()};
+
+ if (ptype == GX::TRIANGLESTRIP) {
+ atUint8 flip = 0;
+ for (int v = 0; v < vertCount - 2; ++v) {
+ if (flip) {
+ os.format(
+ "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, "
+ "two_face_vert)\n",
+ primVerts[c % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[c % 3].norm,
+ primVerts[(c + 2) % 3].norm, primVerts[(c + 1) % 3].norm, sHead.matIdx);
+ if (matUVCount) {
+ os << "if last_face is not None:\n";
+ for (unsigned j = 0; j < matUVCount; ++j) {
+ if (j == 0 && matShortUVs)
+ os.format(
+ " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], "
+ "suv_list[%u])\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[0]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[1]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[2]\n",
+ primVerts[c % 3].uvs[j], primVerts[(c + 2) % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j],
+ primVerts[c % 3].pos, j, primVerts[(c + 2) % 3].pos, j, primVerts[(c + 1) % 3].pos, j);
+ else
+ os.format(
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n",
+ primVerts[c % 3].pos, j, primVerts[c % 3].uvs[j], primVerts[(c + 2) % 3].pos, j,
+ primVerts[(c + 2) % 3].uvs[j], primVerts[(c + 1) % 3].pos, j, primVerts[(c + 1) % 3].uvs[j]);
+ }
+ }
+ } else {
+ os.format(
+ "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, "
+ "two_face_vert)\n",
+ primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[c % 3].norm,
+ primVerts[(c + 1) % 3].norm, primVerts[(c + 2) % 3].norm, sHead.matIdx);
+ if (matUVCount) {
+ os << "if last_face is not None:\n";
+ for (unsigned j = 0; j < matUVCount; ++j) {
+ if (j == 0 && matShortUVs)
+ os.format(
+ " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], "
+ "suv_list[%u])\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[0]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[1]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[2]\n",
+ primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], primVerts[(c + 2) % 3].uvs[j],
+ primVerts[c % 3].pos, j, primVerts[(c + 1) % 3].pos, j, primVerts[(c + 2) % 3].pos, j);
+ else
+ os.format(
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n",
+ primVerts[c % 3].pos, j, primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].pos, j,
+ primVerts[(c + 1) % 3].uvs[j], primVerts[(c + 2) % 3].pos, j, primVerts[(c + 2) % 3].uvs[j]);
+ }
+ }
+ }
+ flip ^= 1;
+
+ bool peek = (v >= vertCount - 3);
+
+ /* Advance one prim vert */
+ primVerts[c % 3] = dl.readVert(peek);
+ ++c;
+ }
+ } else if (ptype == GX::TRIANGLES) {
+ for (int v = 0; v < vertCount; v += 3) {
+
+ os.format(
+ "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, "
+ "two_face_vert)\n",
+ primVerts[0].pos, primVerts[1].pos, primVerts[2].pos, primVerts[0].norm, primVerts[1].norm,
+ primVerts[2].norm, sHead.matIdx);
+ if (matUVCount) {
+ os << "if last_face is not None:\n";
+ for (unsigned j = 0; j < matUVCount; ++j) {
+ if (j == 0 && matShortUVs)
+ os.format(
+ " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], "
+ "suv_list[%u])\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[0]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[1]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[2]\n",
+ primVerts[0].uvs[j], primVerts[1].uvs[j], primVerts[2].uvs[j], primVerts[0].pos, j,
+ primVerts[1].pos, j, primVerts[2].pos, j);
+ else
+ os.format(
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n",
+ primVerts[0].pos, j, primVerts[0].uvs[j], primVerts[1].pos, j, primVerts[1].uvs[j],
+ primVerts[2].pos, j, primVerts[2].uvs[j]);
+ }
+ }
+
+ /* Break if done */
+ if (v + 3 >= vertCount)
+ break;
+
+ /* Advance 3 Prim Verts */
+ for (int pv = 0; pv < 3; ++pv)
+ primVerts[pv] = dl.readVert();
+ }
+ } else if (ptype == GX::TRIANGLEFAN) {
+ ++c;
+ for (int v = 0; v < vertCount - 2; ++v) {
+ os.format(
+ "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, "
+ "two_face_vert)\n",
+ firstPrimVert.pos, primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, firstPrimVert.norm,
+ primVerts[c % 3].norm, primVerts[(c + 1) % 3].norm, sHead.matIdx);
+ if (matUVCount) {
+ os << "if last_face is not None:\n";
+ for (unsigned j = 0; j < matUVCount; ++j) {
+ if (j == 0 && matShortUVs)
+ os.format(
+ " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], "
+ "suv_list[%u])\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[0]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[1]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_tri[2]\n",
+ firstPrimVert.uvs[j], primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], firstPrimVert.pos,
+ j, primVerts[c % 3].pos, j, primVerts[(c + 1) % 3].pos, j);
+ else
+ os.format(
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n"
+ " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = "
+ "uv_list[%u]\n",
+ firstPrimVert.pos, j, firstPrimVert.uvs[j], primVerts[c % 3].pos, j, primVerts[c % 3].uvs[j],
+ primVerts[(c + 1) % 3].pos, j, primVerts[(c + 1) % 3].uvs[j]);
+ }
+ }
+
+ /* Break if done */
+ if (v + 3 >= vertCount)
+ break;
+
+ /* Advance one prim vert */
+ primVerts[(c + 2) % 3] = dl.readVert();
+ ++c;
+ }
+ }
+ os << "\n";
+ }
+ }
+ }
}
- /* Finish Mesh */
- FinishBlenderMesh(os, matSetCount, meshIdx);
+ if (s < secCount - 1)
+ reader.seek(secStart + secSizes[s], athena::Begin);
+ }
- if (rp.first)
- rp.second->sendVertexGroupsToBlender(os);
+ /* Finish Mesh */
+ FinishBlenderMesh(os, matSetCount, meshIdx);
- return lastDlSec;
+ if (rp.first)
+ rp.second->sendVertexGroupsToBlender(os);
+
+ return lastDlSec;
}
template
-bool ReadCMDLToBlender(hecl::blender::Connection& conn,
- athena::io::IStreamReader& reader,
- PAKRouter& pakRouter,
- const typename PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- const RigPair& rp)
-{
- Header head;
- head.read(reader);
+bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter,
+ const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, const RigPair& rp) {
+ Header head;
+ head.read(reader);
- if (head.magic != 0xDEADBABE)
- {
- LogDNACommon.report(logvisor::Error, "invalid CMDL magic");
- return false;
- }
+ if (head.magic != 0xDEADBABE) {
+ LogDNACommon.report(logvisor::Error, "invalid CMDL magic");
+ return false;
+ }
- if (head.version != Version)
- {
- LogDNACommon.report(logvisor::Error, "invalid CMDL version");
- return false;
- }
+ if (head.version != Version) {
+ LogDNACommon.report(logvisor::Error, "invalid CMDL version");
+ return false;
+ }
- /* Open Py Stream and read sections */
- hecl::blender::PyOutStream os = conn.beginPythonOut(true);
- os.format("import bpy\n"
- "import bmesh\n"
- "\n"
- "bpy.context.scene.name = '%s'\n"
- "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n",
- pakRouter.getBestEntryName(entry).c_str());
- InitGeomBlenderContext(os, dataspec.getMasterShaderPath(), false);
- MaterialSet::RegisterMaterialProps(os);
+ /* Open Py Stream and read sections */
+ hecl::blender::PyOutStream os = conn.beginPythonOut(true);
+ os.format(
+ "import bpy\n"
+ "import bmesh\n"
+ "\n"
+ "bpy.context.scene.name = '%s'\n"
+ "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n",
+ pakRouter.getBestEntryName(entry).c_str());
+ InitGeomBlenderContext(os, dataspec.getMasterShaderPath(), false);
+ MaterialSet::RegisterMaterialProps(os);
- os << "# Materials\n"
- "materials = []\n"
- "\n";
+ os << "# Materials\n"
+ "materials = []\n"
+ "\n";
- std::vector vertAttribs;
- ReadGeomSectionsToBlender
- (os, reader, pakRouter, entry, rp, head.flags.shortNormals(),
- head.flags.shortUVs(), vertAttribs, -1,
- head.secCount, head.matSetCount, head.secSizes.data());
+ std::vector vertAttribs;
+ ReadGeomSectionsToBlender(
+ os, reader, pakRouter, entry, rp, head.flags.shortNormals(), head.flags.shortUVs(), vertAttribs, -1,
+ head.secCount, head.matSetCount, head.secSizes.data());
- return true;
+ return true;
}
template bool ReadCMDLToBlender, DNAMP1::MaterialSet,
- std::pair, DNACMDL::SurfaceHeader_1, 2>
-(hecl::blender::Connection& conn,
- athena::io::IStreamReader& reader,
- PAKRouter& pakRouter,
- const PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- const std::pair& rp);
+ std::pair, DNACMDL::SurfaceHeader_1, 2>(
+ hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter,
+ const PAKRouter::EntryType& entry, const SpecBase& dataspec,
+ const std::pair& rp);
template bool ReadCMDLToBlender, DNAMP2::MaterialSet,
- std::pair, DNACMDL::SurfaceHeader_2, 4>
-(hecl::blender::Connection& conn,
- athena::io::IStreamReader& reader,
- PAKRouter& pakRouter,
- const PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- const std::pair& rp);
+ std::pair, DNACMDL::SurfaceHeader_2, 4>(
+ hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter,
+ const PAKRouter::EntryType& entry, const SpecBase& dataspec,
+ const std::pair& rp);
template bool ReadCMDLToBlender, DNAMP3::MaterialSet,
- std::pair, DNACMDL::SurfaceHeader_3, 4>
-(hecl::blender::Connection& conn,
- athena::io::IStreamReader& reader,
- PAKRouter& pakRouter,
- const PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- const std::pair& rp);
+ std::pair, DNACMDL::SurfaceHeader_3, 4>(
+ hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter,
+ const PAKRouter::EntryType& entry, const SpecBase& dataspec,
+ const std::pair& rp);
template bool ReadCMDLToBlender, DNAMP3::MaterialSet,
- std::pair, DNACMDL::SurfaceHeader_3, 5>
-(hecl::blender::Connection& conn,
- athena::io::IStreamReader& reader,
- PAKRouter& pakRouter,
- const PAKRouter::EntryType& entry,
- const SpecBase& dataspec,
- const std::pair& rp);
+ std::pair, DNACMDL::SurfaceHeader_3, 5>(
+ hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter,
+ const PAKRouter::EntryType& entry, const SpecBase& dataspec,
+ const std::pair& rp);
template