Handling for additive ANIMs and MP3 skinning fix

This commit is contained in:
Jack Andersen 2015-09-28 16:00:28 -10:00
parent d59c649f2f
commit d075225c31
11 changed files with 162 additions and 48 deletions

View File

@ -21,6 +21,14 @@ struct CharacterResInfo
std::vector<std::pair<HECL::FourCC, std::pair<IDTYPE, IDTYPE>>> overlays;
};
template <typename IDTYPE>
struct AnimationResInfo
{
std::string name;
IDTYPE animId;
bool additive;
};
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
bool ReadANCSToBlender(HECL::BlenderConnection& conn,
const ANCSDNA& ancs,
@ -150,20 +158,20 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
}
/* Get animation primitives */
std::map<atUint32, std::pair<std::string, typename PAKRouter::IDType>> animResInfo;
std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
ancs.getAnimationResInfo(animResInfo);
for (const auto& id : animResInfo)
{
typename ANCSDNA::ANIMType anim;
if (pakRouter.lookupAndReadDNA(id.second.second, anim, true))
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.first.c_str());
anim.sendANIMToBlender(os, cinf);
"act.use_fake_user = True\n", id.second.name.c_str());
anim.sendANIMToBlender(os, cinf, id.second.additive);
}
os.format("actor_action = actor_data.actions.add()\n"
"actor_action.name = '%s'\n", id.second.first.c_str());
"actor_action.name = '%s'\n", id.second.name.c_str());
}
os.close();

View File

@ -29,7 +29,6 @@ void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os,
" ret_mesh = bm\n"
" vert_seq.ensure_lookup_table()\n"
" verts = [vert_seq[i] for i in vert_indices]\n"
" #norms = [norm_seq[i] for i in norm_indices]\n"
"\n"
" # Make the face\n"
" face = bm.faces.get(verts)\n"

View File

@ -20,10 +20,10 @@ struct Header : BigDNA
{
DECL_DNA
Value<atUint32> flags;
inline bool shortNormals() const {return (flags & 0x2) != 0;}
inline void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;}
inline bool shortUVs() const {return (flags & 0x4) != 0;}
inline void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;}
bool shortNormals() const {return (flags & 0x2) != 0;}
void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;}
bool shortUVs() const {return (flags & 0x4) != 0;}
void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;}
} flags;
Value<atVec3f> aabbMin;
Value<atVec3f> aabbMax;
@ -199,9 +199,77 @@ void ReadMaterialSetToBlender_3(HECL::BlenderConnection::PyOutStream& os,
class DLReader
{
public:
/* Class used for splitting verts with shared positions but different skinning matrices */
class ExtraVertTracker
{
std::map<atUint16, std::vector<std::pair<atInt16, atUint16>>> 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<std::pair<atInt16, atUint16>>& vertTrack = search->second;
for (const std::pair<atInt16, atUint16>& s : vertTrack)
if (s.first == skin)
return vertTrack.front().first;
vertTrack.push_back(std::make_pair(skin, m_nextOverPos++));
return vertTrack.front().first;
}
template<class RigPair>
void sendAdditionalVertsToBlender(HECL::BlenderConnection::PyOutStream& os,
const RigPair& rp) const
{
atUint32 nextVert = 1;
while (nextVert < m_nextOverPos)
{
for (const std::pair<atUint16, std::vector<std::pair<atInt16, atUint16>>>& ev : m_extraVerts)
{
for (const std::pair<atInt16, atUint16>& 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);
rp.first->weightVertex(os, *rp.second, se.first);
++nextVert;
}
}
}
}
}
atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const
{
auto search = m_extraVerts.find(pos);
if (search == m_extraVerts.end())
return -1;
const std::vector<std::pair<atInt16, atUint16>>& 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<atUint8[]> m_dl;
size_t m_dlSize;
ExtraVertTracker& m_evt;
const atInt16* m_bankIn;
atUint8* m_cur;
atUint16 readVal(GX::AttrType type)
{
@ -226,31 +294,37 @@ class DLReader
return retval;
}
public:
DLReader(const VertexAttributes& va, std::unique_ptr<atUint8[]>&& dl, size_t dlSize)
: m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize)
DLReader(const VertexAttributes& va, std::unique_ptr<atUint8[]>&& 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;
@ -260,6 +334,7 @@ public:
atUint8 pnMtxIdx = 0;
atUint8 texMtxIdx[7] = {0};
};
DLPrimVert readVert(bool peek=false)
{
atUint8* bakCur = m_cur;
@ -272,6 +347,16 @@ public:
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);
@ -287,6 +372,7 @@ public:
m_cur = bakCur;
return retval;
}
void preReadMaxIdxs(DLPrimVert& out)
{
atUint8* bakCur = m_cur;
@ -339,8 +425,9 @@ public:
}
m_cur = bakCur;
}
void preReadMaxIdxs(DLPrimVert& out, std::vector<atInt16>& skinOut,
const atInt16 bankIn[10])
void preReadMaxIdxs(DLPrimVert& out,
std::vector<atInt16>& skinOut)
{
atUint8* bakCur = m_cur;
while (*this)
@ -389,7 +476,8 @@ public:
val = readVal(m_va.uvs[6]);
out.uvs[6] = std::max(out.uvs[6], val);
skinOut[posVal] = bankIn[pnMtxVal/3];
atInt16 skinIdx = m_bankIn[pnMtxVal/3];
skinOut[posVal] = m_evt.addPosSkinPair(posVal, skinIdx);
}
}
m_cur = bakCur;
@ -437,6 +525,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
atUint64 afterHeaderPos = reader.position();
DLReader::DLPrimVert maxIdxs;
std::vector<atInt16> skinIndices;
DLReader::ExtraVertTracker extraTracker;
for (size_t s=0 ; s<lastDlSec ; ++s)
{
atUint64 secStart = reader.position();
@ -507,12 +596,16 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
/* 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);
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize),
realDlSize, extraTracker, bankIn);
if (SurfaceHeader::UseMatrixSkinning() && rp.first)
dl.preReadMaxIdxs(maxIdxs, skinIndices, rp.first->getMatrixBank(sHead.skinMatrixBankIdx()));
dl.preReadMaxIdxs(maxIdxs, skinIndices);
else
dl.preReadMaxIdxs(maxIdxs);
@ -561,6 +654,8 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
rp.first->weightVertex(os, *rp.second, i);
}
}
if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
extraTracker.sendAdditionalVertsToBlender(os, rp);
break;
}
case 1:
@ -652,6 +747,9 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
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)
@ -662,7 +760,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
}
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize, extraTracker, bankIn);
while (dl)
{

View File

@ -168,7 +168,7 @@ struct ANCS : BigYAML
const char* m_typeStr;
IMetaAnim(Type type, const char* typeStr)
: m_type(type), m_typeStr(typeStr) {}
virtual void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)=0;
virtual void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)=0;
};
struct MetaAnimFactory : BigYAML
{
@ -186,9 +186,9 @@ struct ANCS : BigYAML
Value<float> unk1;
Value<atUint32> unk2;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
{
out[animIdx] = std::make_pair(animName, animId);
out[animIdx] = {animName, animId, false};
}
};
struct MetaAnimBlend : IMetaAnim
@ -200,7 +200,7 @@ struct ANCS : BigYAML
Value<float> unkFloat;
Value<atUint8> unk;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
{
animA.m_anim->gatherPrimitives(out);
animB.m_anim->gatherPrimitives(out);
@ -215,7 +215,7 @@ struct ANCS : BigYAML
Value<float> unkFloat;
Value<atUint8> unk;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
{
animA.m_anim->gatherPrimitives(out);
animB.m_anim->gatherPrimitives(out);
@ -234,7 +234,7 @@ struct ANCS : BigYAML
};
Vector<Child, DNA_COUNT(animCount)> children;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
{
for (const auto& child : children)
child.anim.m_anim->gatherPrimitives(out);
@ -247,7 +247,7 @@ struct ANCS : BigYAML
Value<atUint32> animCount;
Vector<MetaAnimFactory, DNA_COUNT(animCount)> children;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID32>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
{
for (const auto& child : children)
child.m_anim->gatherPrimitives(out);
@ -367,7 +367,7 @@ struct ANCS : BigYAML
}
}
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID32>>& out) const
void getAnimationResInfo(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) const
{
out.clear();
for (const AnimationSet::Animation& ai : animationSet.animations)

View File

@ -161,7 +161,7 @@ struct ANIM : BigDNA
m_anim->write(writer);
}
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, bool) const
{
m_anim->sendANIMToBlender(os, cinf);
}

View File

@ -204,7 +204,7 @@ struct ANCS : BigYAML
}
}
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID32>>& out) const
void getAnimationResInfo(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) const
{
out.clear();
for (const DNAMP1::ANCS::AnimationSet::Animation& ai : animationSet.animations)

View File

@ -194,7 +194,7 @@ struct ANIM : BigDNA
m_anim->write(writer);
}
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, bool) const
{
m_anim->sendANIMToBlender(os, cinf);
}

View File

@ -9,9 +9,11 @@ namespace DNAMP3
using ANIMOutStream = HECL::BlenderConnection::PyOutStream::ANIMOutStream;
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, bool additive) const
{
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
os.format("act.hecl_fps = round(%f)\n"
"act.hecl_additive = %s\n",
1.0f / mainInterval, additive ? "True" : "False");
auto kit = chanKeys.begin() + 1;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
@ -41,14 +43,19 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
"\n";
if (std::get<1>(bone.second))
{
if (!additive)
os << "bone_trans_head = (0.0,0.0,0.0)\n"
"if arm_obj.data.bones[bone_string].parent is not None:\n"
" bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
"transCurves = []\n"
" bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n";
else
os << "bone_trans_head = (0.0,0.0,0.0)\n";
os << "transCurves = []\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
"\n";
}
if (std::get<2>(bone.second))
os << "scaleCurves = []\n"

View File

@ -27,7 +27,7 @@ struct ANIM : BigDNA
std::vector<std::vector<DNAANIM::Value>> chanKeys;
float mainInterval = 0.0;
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const;
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&, bool additive) const;
};
struct ANIM0 : IANIM
@ -105,9 +105,9 @@ struct ANIM : BigDNA
m_anim->write(writer);
}
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf, bool additive) const
{
m_anim->sendANIMToBlender(os, cinf);
m_anim->sendANIMToBlender(os, cinf, additive);
}
};

View File

@ -141,7 +141,7 @@ struct CHAR : BigYAML
const char* m_typeStr;
IMetaAnim(Type type, const char* typeStr)
: m_type(type), m_typeStr(typeStr) {}
virtual void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID64>>& out)=0;
virtual void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out)=0;
};
struct MetaAnimFactory : BigYAML
{
@ -159,9 +159,9 @@ struct CHAR : BigYAML
Value<float> unk1;
Value<atUint32> unk2;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID64>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out)
{
out[animIdx] = std::make_pair(animName, animId);
out[animIdx] = {animName, animId, false};
}
};
struct MetaAnimBlend : IMetaAnim
@ -173,7 +173,7 @@ struct CHAR : BigYAML
Value<float> unkFloat;
Value<atUint8> unk;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID64>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out)
{
animA.m_anim->gatherPrimitives(out);
animB.m_anim->gatherPrimitives(out);
@ -188,7 +188,7 @@ struct CHAR : BigYAML
Value<float> unkFloat;
Value<atUint8> unk;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID64>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out)
{
animA.m_anim->gatherPrimitives(out);
animB.m_anim->gatherPrimitives(out);
@ -207,7 +207,7 @@ struct CHAR : BigYAML
};
Vector<Child, DNA_COUNT(animCount)> children;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID64>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out)
{
for (const auto& child : children)
child.anim.m_anim->gatherPrimitives(out);
@ -220,7 +220,7 @@ struct CHAR : BigYAML
Value<atUint32> animCount;
Vector<MetaAnimFactory, DNA_COUNT(animCount)> children;
void gatherPrimitives(std::map<atUint32, std::pair<std::string, UniqueID64>>& out)
void gatherPrimitives(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out)
{
for (const auto& child : children)
child.m_anim->gatherPrimitives(out);
@ -296,11 +296,13 @@ struct CHAR : BigYAML
chOut.overlays.emplace_back(overlay.type, std::make_pair(overlay.cmdl, overlay.cskr));
}
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID64>>& out) const
void getAnimationResInfo(std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID64>>& out) const
{
out.clear();
for (const AnimationInfo::Animation& ai : animationInfo.animations)
ai.metaAnim.m_anim->gatherPrimitives(out);
for (auto& animRes : out)
animRes.second.additive = animationInfo.additiveMap.at(animRes.first);
}
static bool Extract(const SpecBase& dataSpec,

2
hecl

@ -1 +1 @@
Subproject commit daec614e8af7aaebc9c81be2ac3eda97f50daa0d
Subproject commit 5c36b9e5bb0bc051e320477720eb3847154adfa5