mirror of https://github.com/AxioDL/metaforce.git
CINF/CSKR integration
This commit is contained in:
parent
cdd7b45394
commit
fd550702e1
|
@ -7,8 +7,3 @@ include_directories(${ATHENA_INCLUDE_DIR} ${LOG_VISOR_INCLUDE_DIR} ${ANGELSCRIPT
|
|||
set(NOD_LIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/NODLib/include)
|
||||
add_subdirectory(DataSpec)
|
||||
add_subdirectory(Runtime)
|
||||
|
||||
include_directories(include)
|
||||
add_library(RetroCommon
|
||||
src/RetroCommon.cpp include/RetroCommon.hpp
|
||||
src/MREADecompress.cpp)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _DNACOMMON_ANCS_HPP_
|
||||
#define _DNACOMMON_ANCS_HPP_
|
||||
|
||||
#include <unordered_set>
|
||||
#include "DNACommon.hpp"
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "CMDL.hpp"
|
||||
|
@ -28,7 +29,7 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
const HECL::ProjectPath& masterShader,
|
||||
bool force=false)
|
||||
{
|
||||
/* Extract characters first */
|
||||
/* Extract character CMDL/CSKR first */
|
||||
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
|
||||
ancs.getCharacterResInfo(chResInfo);
|
||||
for (const auto& info : chResInfo)
|
||||
|
@ -40,12 +41,17 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
{
|
||||
if (!conn.createBlend(cmdlPath.getAbsolutePath()))
|
||||
return false;
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, CMDLVersion>
|
||||
(conn, rs, pakRouter, entry, masterShader);
|
||||
|
||||
const typename PAKRouter::EntryType* cskrE = pakRouter.lookupEntry(info.cskr);
|
||||
const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(info.cinf);
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
using RIGPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RIGPair rigPair(&cskr, &cinf);
|
||||
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RIGPair, CMDLVersion>
|
||||
(conn, rs, pakRouter, *cmdlE, masterShader, &rigPair);
|
||||
|
||||
conn.saveBlend();
|
||||
}
|
||||
|
@ -56,14 +62,76 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
|
|||
return false;
|
||||
HECL::BlenderConnection::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_type = 'ACTOR'\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':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"actor_data = bpy.context.scene.hecl_sact_data\n",
|
||||
pakRouter.getBestEntryName(entry).c_str());
|
||||
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
std::unordered_set<typename PAKRouter::IDType> cinfsDone;
|
||||
for (const auto& info : chResInfo)
|
||||
{
|
||||
/* Build CINF if needed */
|
||||
if (cinfsDone.find(info.cinf) == cinfsDone.end())
|
||||
{
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
cinf.sendCINFToBlender(os, info.cinf);
|
||||
cinfsDone.insert(info.cinf);
|
||||
}
|
||||
else
|
||||
os.format("arm_obj = bpy.data.objects['CINF_%08X']\n", info.cinf.toUint32());
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl);
|
||||
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePath(), pakRouter.getBestEntryName(*cmdlE), 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"
|
||||
"\n";
|
||||
|
||||
/* Provide data to add-on */
|
||||
os.format("actor_subtype = actor_data.subtypes.add()\n"
|
||||
"actor_subtype.name = '%s'\n"
|
||||
"actor_subtype.linked_armature = arm_obj.name\n"
|
||||
"actor_subtype.linked_mesh = obj.name\n\n",
|
||||
info.name.c_str());
|
||||
}
|
||||
|
||||
/* Get animation primitives */
|
||||
std::unordered_set<typename PAKRouter::IDType> animResInfo;
|
||||
std::map<atUint32, std::pair<std::string, typename PAKRouter::IDType>> animResInfo;
|
||||
ancs.getAnimationResInfo(animResInfo);
|
||||
for (const auto& id : animResInfo)
|
||||
{
|
||||
const typename PAKRouter::EntryType* animE = pakRouter.lookupEntry(id);
|
||||
typename ANCSDNA::ANIMType anim;
|
||||
pakRouter.lookupAndReadDNA(id.second.second, anim);
|
||||
|
||||
os.format("act = bpy.data.actions.new('%s')\n"
|
||||
"act.use_fake_user = True\n", id.second.first.c_str());
|
||||
anim.sendANIMToBlender(os, cinf);
|
||||
|
||||
os.format("actor_action = actor_data.actions.add()\n"
|
||||
"actor_action.name = '%s'\n", id.second.first.c_str());
|
||||
}
|
||||
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -293,12 +293,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class PAKRouter, class MaterialSet, atUint32 Version>
|
||||
template <class PAKRouter, class MaterialSet, class RIGPAIR, atUint32 Version>
|
||||
bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
||||
Athena::io::IStreamReader& reader,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
const HECL::ProjectPath& masterShader)
|
||||
const HECL::ProjectPath& masterShader,
|
||||
const RIGPAIR* rp=nullptr)
|
||||
{
|
||||
reader.setEndian(Athena::BigEndian);
|
||||
|
||||
|
@ -401,6 +402,9 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
|||
"bm = bmesh.new()\n"
|
||||
"\n", pakRouter.getBestEntryName(entry).c_str());
|
||||
|
||||
if (rp)
|
||||
os << "dvert_lay = bm.verts.layers.deform.verify()\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"
|
||||
|
@ -520,8 +524,10 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
|||
for (size_t i=0 ; i<=maxIdxs.pos ; ++i)
|
||||
{
|
||||
atVec3f pos = reader.readVec3f();
|
||||
os.format("bm.verts.new((%f,%f,%f))\n",
|
||||
os.format("vert = bm.verts.new((%f,%f,%f))\n",
|
||||
pos.vec[0], pos.vec[1], pos.vec[2]);
|
||||
if (rp)
|
||||
rp->first->weightVertex(os, *rp->second, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -817,6 +823,9 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
|
|||
"bm.free()\n"
|
||||
"\n", head.matSetCount);
|
||||
|
||||
if (rp)
|
||||
rp->second->sendVertexGroupsToBlender(os);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -571,6 +571,21 @@ public:
|
|||
*nodeOut = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename DNA>
|
||||
bool lookupAndReadDNA(const typename BRIDGETYPE::PAKType::IDType& id, DNA& out)
|
||||
{
|
||||
const NOD::DiscBase::IPartition::Node* node;
|
||||
const typename BRIDGETYPE::PAKType::Entry* entry = lookupEntry(id, &node);
|
||||
if (!entry)
|
||||
{
|
||||
LogDNACommon.report(LogVisor::Error, "unable to find PAK entry %s", id.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
PAKEntryReadStream rs = entry->beginReadStream(*node);
|
||||
out.read(rs);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/* Resource cooker function */
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#ifndef _DNAMP1_ANCS_HPP_
|
||||
#define _DNAMP1_ANCS_HPP_
|
||||
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "../DNACommon/ANCS.hpp"
|
||||
#include "CMDLMaterials.hpp"
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "CINF.hpp"
|
||||
#include "CSKR.hpp"
|
||||
#include "ANIM.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -14,6 +17,10 @@ namespace DNAMP1
|
|||
|
||||
struct ANCS : BigYAML
|
||||
{
|
||||
using CINFType = CINF;
|
||||
using CSKRType = CSKR;
|
||||
using ANIMType = ANIM;
|
||||
|
||||
DECL_YAML
|
||||
Value<atUint16> version;
|
||||
|
||||
|
@ -163,7 +170,7 @@ struct ANCS : BigYAML
|
|||
const char* m_typeStr;
|
||||
IMetaAnim(Type type, const char* typeStr)
|
||||
: m_type(type), m_typeStr(typeStr) {}
|
||||
virtual void gatherPrimitives(std::unordered_set<UniqueID32>& out)=0;
|
||||
virtual void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)=0;
|
||||
};
|
||||
struct MetaAnimFactory : BigYAML
|
||||
{
|
||||
|
@ -181,9 +188,9 @@ struct ANCS : BigYAML
|
|||
Value<float> unk1;
|
||||
Value<atUint32> unk2;
|
||||
|
||||
void gatherPrimitives(std::unordered_set<UniqueID32>& out)
|
||||
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
|
||||
{
|
||||
out.insert(animId);
|
||||
out[animIdx] = std::make_pair(animName, animId);
|
||||
}
|
||||
};
|
||||
struct MetaAnimBlend : IMetaAnim
|
||||
|
@ -195,7 +202,7 @@ struct ANCS : BigYAML
|
|||
Value<float> unkFloat;
|
||||
Value<atUint8> unk;
|
||||
|
||||
void gatherPrimitives(std::unordered_set<UniqueID32>& out)
|
||||
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
|
||||
{
|
||||
animA.m_anim->gatherPrimitives(out);
|
||||
animB.m_anim->gatherPrimitives(out);
|
||||
|
@ -210,7 +217,7 @@ struct ANCS : BigYAML
|
|||
Value<float> unkFloat;
|
||||
Value<atUint8> unk;
|
||||
|
||||
void gatherPrimitives(std::unordered_set<UniqueID32>& out)
|
||||
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
|
||||
{
|
||||
animA.m_anim->gatherPrimitives(out);
|
||||
animB.m_anim->gatherPrimitives(out);
|
||||
|
@ -229,7 +236,7 @@ struct ANCS : BigYAML
|
|||
};
|
||||
Vector<Child, DNA_COUNT(animCount)> children;
|
||||
|
||||
void gatherPrimitives(std::unordered_set<UniqueID32>& out)
|
||||
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
|
||||
{
|
||||
for (const auto& child : children)
|
||||
child.anim.m_anim->gatherPrimitives(out);
|
||||
|
@ -242,7 +249,7 @@ struct ANCS : BigYAML
|
|||
Value<atUint32> animCount;
|
||||
Vector<MetaAnimFactory, DNA_COUNT(animCount)> children;
|
||||
|
||||
void gatherPrimitives(std::unordered_set<UniqueID32>& out)
|
||||
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
|
||||
{
|
||||
for (const auto& child : children)
|
||||
child.m_anim->gatherPrimitives(out);
|
||||
|
@ -359,7 +366,7 @@ struct ANCS : BigYAML
|
|||
}
|
||||
}
|
||||
|
||||
void getAnimationResInfo(std::unordered_set<UniqueID32>& out) const
|
||||
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID32>>& out) const
|
||||
{
|
||||
out.clear();
|
||||
for (const AnimationSet::Animation& ai : animationSet.animations)
|
||||
|
|
|
@ -5,6 +5,72 @@ namespace Retro
|
|||
namespace DNAMP1
|
||||
{
|
||||
|
||||
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
|
||||
{
|
||||
os.format("bone_trans_heads = []\n"
|
||||
"act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
|
||||
|
||||
auto kit = chanKeys.begin();
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
{
|
||||
os.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str());
|
||||
os << "action_group = act.groups.new(bone_string)\n"
|
||||
"\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string)\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string)\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string)\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string)\n"
|
||||
"\n";
|
||||
|
||||
if (bone.second)
|
||||
os << "bone_parent_head = (0.0,0.0,0.0)\n"
|
||||
"if arm_obj.data.bones[bone_string].parent is not None:\n"
|
||||
" bone_parent_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
|
||||
"bone_trans_heads.append(bone_parent_head)\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string)\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string)\n"
|
||||
"crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string)\n"
|
||||
"\n";
|
||||
else
|
||||
os << "bone_trans_heads.append((0,0,0))\n";
|
||||
|
||||
os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].co = (0, 0)\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"\n";
|
||||
|
||||
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
|
||||
auto timeit = times.begin();
|
||||
for (const DNAANIM::Value& val : rotKeys)
|
||||
{
|
||||
float time = *timeit++;
|
||||
for (int c=0 ; c<4 ; ++c)
|
||||
os.format("crv = act.fcurves[%d]\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"crv.keyframe_points[-1].co = (%f, %f)\n",
|
||||
c, time, val.v4.vec[c]);
|
||||
}
|
||||
|
||||
if (bone.second)
|
||||
{
|
||||
const std::vector<DNAANIM::Value>& transKeys = *kit++;
|
||||
auto timeit = times.begin();
|
||||
for (const DNAANIM::Value& val : transKeys)
|
||||
{
|
||||
float time = *timeit++;
|
||||
for (int c=0 ; c<3 ; ++c)
|
||||
os.format("crv = act.fcurves[%d+4]\n"
|
||||
"crv.keyframe_points.add()\n"
|
||||
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
|
||||
"crv.keyframe_points[-1].co = (%f, %f)\n",
|
||||
c, time, val.v4.vec[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
Header head;
|
||||
|
@ -174,6 +240,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
|
|||
times.push_back(timeAccum);
|
||||
timeAccum += head.interval;
|
||||
}
|
||||
reader.seek(8);
|
||||
|
||||
bones.clear();
|
||||
bones.reserve(head.boneChannelCount);
|
||||
|
@ -256,6 +323,8 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
|
|||
|
||||
head.write(writer);
|
||||
keyBmp.write(writer);
|
||||
writer.writeUint32(head.boneChannelCount);
|
||||
writer.writeUint32(head.boneChannelCount);
|
||||
auto cit = qChannels.begin();
|
||||
for (const std::pair<atUint32, bool>& bone : bones)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#ifndef _DNAMP1_ANIM_HPP_
|
||||
#define _DNAMP1_ANIM_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
#include "../DNACommon/ANIM.hpp"
|
||||
#include "CINF.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -25,6 +27,8 @@ struct ANIM : BigDNA
|
|||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
UniqueID32 evnt;
|
||||
|
||||
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const;
|
||||
};
|
||||
|
||||
struct ANIM0 : IANIM
|
||||
|
@ -134,6 +138,7 @@ struct ANIM : BigDNA
|
|||
std::unique_ptr<IANIM> m_anim;
|
||||
void read(Athena::io::IStreamReader& reader)
|
||||
{
|
||||
reader.setEndian(Athena::BigEndian);
|
||||
atUint32 version = reader.readUint32();
|
||||
switch (version)
|
||||
{
|
||||
|
@ -153,9 +158,16 @@ struct ANIM : BigDNA
|
|||
|
||||
void write(Athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.setEndian(Athena::BigEndian);
|
||||
writer.writeUint32(m_anim->m_version);
|
||||
m_anim->write(writer);
|
||||
}
|
||||
|
||||
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
|
||||
{
|
||||
m_anim->sendANIMToBlender(os, cinf);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _DNAMP1_CINF_HPP_
|
||||
#define _DNAMP1_CINF_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace Retro
|
||||
|
@ -34,6 +35,66 @@ struct CINF : BigDNA
|
|||
Value<atUint32> boneId;
|
||||
};
|
||||
Vector<Name, DNA_COUNT(nameCount)> names;
|
||||
|
||||
atUint32 getBoneIdxFromId(atUint32 id) const
|
||||
{
|
||||
atUint32 idx = 0;
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
if (bid == id)
|
||||
return idx;
|
||||
++idx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string* getBoneNameFromId(atUint32 id) const
|
||||
{
|
||||
for (const Name& name : names)
|
||||
if (id == name.boneId)
|
||||
return &name.name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void sendVertexGroupsToBlender(HECL::BlenderConnection::PyOutStream& os) const
|
||||
{
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
for (const Name& name : names)
|
||||
{
|
||||
if (name.boneId == bid)
|
||||
{
|
||||
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID32& cinfId) const
|
||||
{
|
||||
os.format("arm = bpy.data.armatures.new('CINF_%08X')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.objects.link(arm_obj)\n"
|
||||
"bpy.context.scene.objects.active = arm_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"arm_bone_table = {}\n",
|
||||
cinfId.toUint32());
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
os.format("bone = arm.edit_bones.new('%s')\n"
|
||||
"bone.head = (%f,%f,%f)\n"
|
||||
"bone.tail = bone.head\n"
|
||||
"bone.tail[1] += 0.5\n"
|
||||
"arm_bone_table[%u] = bone\n", getBoneNameFromId(bone.id)->c_str(),
|
||||
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "../DNACommon/CMDL.hpp"
|
||||
#include "CMDLMaterials.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
#include "CINF.hpp"
|
||||
#include "CSKR.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -23,7 +25,7 @@ struct CMDL
|
|||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||
return false;
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 2>
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 2>
|
||||
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef _DNAMP1_CSKR_HPP_
|
||||
#define _DNAMP1_CSKR_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "CINF.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -26,6 +28,20 @@ struct CSKR : BigDNA
|
|||
Value<atUint32> vertCount;
|
||||
};
|
||||
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
||||
|
||||
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
||||
{
|
||||
atUint32 accum = 0;
|
||||
for (const SkinningRule& rule : skinningRules)
|
||||
{
|
||||
if (idx >= accum && idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format("vert[dvert_lay][%u] = %f\n",
|
||||
cinf.getBoneIdxFromId(weight.boneId),
|
||||
weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -174,16 +174,16 @@ void PAKBridge::build()
|
|||
|
||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
|
||||
{
|
||||
switch (entry.type.toUint32())
|
||||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
case SBIG('CMDL'):
|
||||
return {nullptr, CMDL::Extract, ".blend", 1};
|
||||
return {nullptr, CMDL::Extract, ".blend", 2};
|
||||
case SBIG('ANCS'):
|
||||
return {nullptr, ANCS::Extract, nullptr};
|
||||
return {nullptr, ANCS::Extract, nullptr, 1};
|
||||
case SBIG('MLVL'):
|
||||
return {MLVL::Extract, nullptr, ".yaml"};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
#ifndef _DNAMP2_CINF_HPP_
|
||||
#define _DNAMP2_CINF_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP2
|
||||
{
|
||||
|
||||
struct CINF : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> boneCount;
|
||||
struct Bone : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> id;
|
||||
Value<atUint32> parentId;
|
||||
Value<atVec3f> origin;
|
||||
Value<atUint32> linkedCount;
|
||||
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
|
||||
};
|
||||
Vector<Bone, DNA_COUNT(boneCount)> bones;
|
||||
|
||||
Value<atUint32> boneIdCount;
|
||||
Vector<atUint32, DNA_COUNT(boneIdCount)> boneIds;
|
||||
|
||||
Value<atUint32> nameCount;
|
||||
struct Name : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
String<-1> name;
|
||||
Value<atUint32> boneId;
|
||||
};
|
||||
Vector<Name, DNA_COUNT(nameCount)> names;
|
||||
|
||||
atUint32 getBoneIdxFromId(atUint32 id) const
|
||||
{
|
||||
atUint32 idx = 0;
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
if (bid == id)
|
||||
return idx;
|
||||
++idx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string* getBoneNameFromId(atUint32 id) const
|
||||
{
|
||||
for (const Name& name : names)
|
||||
if (id == name.boneId)
|
||||
return &name.name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void sendVertexGroupsToBlender(HECL::BlenderConnection::PyOutStream& os) const
|
||||
{
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
for (const Name& name : names)
|
||||
{
|
||||
if (name.boneId == bid)
|
||||
{
|
||||
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID32& cinfId) const
|
||||
{
|
||||
os.format("arm = bpy.data.armatures.new('CINF_%08X')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.objects.link(arm_obj)\n"
|
||||
"bpy.context.scene.objects.active = arm_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"arm_bone_table = {}\n",
|
||||
cinfId.toUint32());
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
os.format("bone = arm.edit_bones.new('%s')\n"
|
||||
"bone.head = (%f,%f,%f)\n"
|
||||
"bone.tail = bone.head\n"
|
||||
"bone.tail[1] += 0.5\n"
|
||||
"arm_bone_table[%u] = bone\n", getBoneNameFromId(bone.id)->c_str(),
|
||||
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DNAMP2_CINF_HPP_
|
|
@ -5,6 +5,8 @@
|
|||
#include "../DNACommon/CMDL.hpp"
|
||||
#include "CMDLMaterials.hpp"
|
||||
#include "DNAMP2.hpp"
|
||||
#include "CINF.hpp"
|
||||
#include "CSKR.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -23,7 +25,7 @@ struct CMDL
|
|||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||
return false;
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 4>
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 4>
|
||||
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
make_dnalist(liblist
|
||||
MLVL
|
||||
CMDLMaterials)
|
||||
CMDLMaterials
|
||||
CINF
|
||||
CSKR)
|
||||
add_library(DNAMP2
|
||||
DNAMP2.hpp DNAMP2.cpp
|
||||
${liblist}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef _DNAMP2_CSKR_HPP_
|
||||
#define _DNAMP2_CSKR_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "CINF.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP2
|
||||
{
|
||||
|
||||
struct CSKR : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> skinningRuleCount;
|
||||
struct SkinningRule : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> weightCount;
|
||||
struct Weight : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> boneId;
|
||||
Value<float> weight;
|
||||
};
|
||||
Vector<Weight, DNA_COUNT(weightCount)> weights;
|
||||
Value<atUint32> vertCount;
|
||||
};
|
||||
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
||||
|
||||
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
||||
{
|
||||
atUint32 accum = 0;
|
||||
for (const SkinningRule& rule : skinningRules)
|
||||
{
|
||||
if (idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format("vert[dvert_lay][%u] = %f\n",
|
||||
cinf.getBoneIdxFromId(weight.boneId),
|
||||
weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DNAMP2_CSKR_HPP_
|
|
@ -181,7 +181,7 @@ void PAKBridge::build()
|
|||
|
||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& entry)
|
||||
{
|
||||
switch (entry.type.toUint32())
|
||||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
#ifndef _DNAMP3_CINF_HPP_
|
||||
#define _DNAMP3_CINF_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP3
|
||||
{
|
||||
|
||||
struct CINF : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> boneCount;
|
||||
struct Bone : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> id;
|
||||
Value<atUint32> parentId;
|
||||
Value<atVec3f> origin;
|
||||
Value<atUint32> linkedCount;
|
||||
Vector<atUint32, DNA_COUNT(linkedCount)> linked;
|
||||
};
|
||||
Vector<Bone, DNA_COUNT(boneCount)> bones;
|
||||
|
||||
Value<atUint32> boneIdCount;
|
||||
Vector<atUint32, DNA_COUNT(boneIdCount)> boneIds;
|
||||
|
||||
Value<atUint32> nameCount;
|
||||
struct Name : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
String<-1> name;
|
||||
Value<atUint32> boneId;
|
||||
};
|
||||
Vector<Name, DNA_COUNT(nameCount)> names;
|
||||
|
||||
atUint32 getBoneIdxFromId(atUint32 id) const
|
||||
{
|
||||
atUint32 idx = 0;
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
if (bid == id)
|
||||
return idx;
|
||||
++idx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string* getBoneNameFromId(atUint32 id) const
|
||||
{
|
||||
for (const Name& name : names)
|
||||
if (id == name.boneId)
|
||||
return &name.name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void sendVertexGroupsToBlender(HECL::BlenderConnection::PyOutStream& os) const
|
||||
{
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
for (const Name& name : names)
|
||||
{
|
||||
if (name.boneId == bid)
|
||||
{
|
||||
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendCINFToBlender(HECL::BlenderConnection::PyOutStream& os, const UniqueID32& cinfId) const
|
||||
{
|
||||
os.format("arm = bpy.data.armatures.new('CINF_%08X')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.objects.link(arm_obj)\n"
|
||||
"bpy.context.scene.objects.active = arm_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"arm_bone_table = {}\n",
|
||||
cinfId.toUint32());
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
os.format("bone = arm.edit_bones.new('%s')\n"
|
||||
"bone.head = (%f,%f,%f)\n"
|
||||
"bone.tail = bone.head\n"
|
||||
"bone.tail[1] += 0.5\n"
|
||||
"arm_bone_table[%u] = bone\n", getBoneNameFromId(bone.id)->c_str(),
|
||||
bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DNAMP3_CINF_HPP_
|
|
@ -5,6 +5,8 @@
|
|||
#include "../DNACommon/CMDL.hpp"
|
||||
#include "CMDLMaterials.hpp"
|
||||
#include "DNAMP3.hpp"
|
||||
#include "CINF.hpp"
|
||||
#include "CSKR.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -23,7 +25,7 @@ struct CMDL
|
|||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||
return false;
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 5>
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, 5>
|
||||
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
make_dnalist(liblist
|
||||
PAK
|
||||
MLVL
|
||||
CMDLMaterials)
|
||||
CMDLMaterials
|
||||
CINF
|
||||
CSKR)
|
||||
add_library(DNAMP3
|
||||
DNAMP3.hpp DNAMP3.cpp
|
||||
${liblist}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef _DNAMP3_CSKR_HPP_
|
||||
#define _DNAMP3_CSKR_HPP_
|
||||
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "CINF.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP3
|
||||
{
|
||||
|
||||
struct CSKR : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> skinningRuleCount;
|
||||
struct SkinningRule : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> weightCount;
|
||||
struct Weight : BigDNA
|
||||
{
|
||||
DECL_DNA
|
||||
Value<atUint32> boneId;
|
||||
Value<float> weight;
|
||||
};
|
||||
Vector<Weight, DNA_COUNT(weightCount)> weights;
|
||||
Value<atUint32> vertCount;
|
||||
};
|
||||
Vector<SkinningRule, DNA_COUNT(skinningRuleCount)> skinningRules;
|
||||
|
||||
void weightVertex(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
||||
{
|
||||
atUint32 accum = 0;
|
||||
for (const SkinningRule& rule : skinningRules)
|
||||
{
|
||||
if (idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format("vert[dvert_lay][%u] = %f\n",
|
||||
cinf.getBoneIdxFromId(weight.boneId),
|
||||
weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DNAMP3_CSKR_HPP_
|
|
@ -55,7 +55,7 @@ void PAKBridge::build()
|
|||
|
||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
|
||||
{
|
||||
switch (entry.type.toUint32())
|
||||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
|
|
Loading…
Reference in New Issue