Initial CCharLayoutInfo implementation

This commit is contained in:
Jack Andersen 2016-04-09 13:19:17 -10:00
parent 68c1ac8978
commit e661fa6f2b
22 changed files with 360 additions and 22 deletions

View File

@ -9,6 +9,7 @@
#include "CINF.hpp"
#include "CSKR.hpp"
#include "ANIM.hpp"
#include "EVNT.hpp"
#include "athena/FileReader.hpp"
namespace DataSpec
@ -540,16 +541,16 @@ struct ANCS : BigYAML
hecl::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
hecl::ProjectPath::Type blendType = blendPath.getPathType();
ANCS ancs;
ancs.read(rs);
if (force ||
yamlType == hecl::ProjectPath::Type::None ||
blendType == hecl::ProjectPath::Type::None)
{
ANCS ancs;
ancs.read(rs);
if (force || yamlType == hecl::ProjectPath::Type::None)
{
FILE* fp = hecl::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
FILE* fp = hecl::Fopen(yamlPath.getAbsolutePath().c_str(), _S("w"));
ancs.toYAMLFile(fp);
fclose(fp);
}
@ -562,6 +563,32 @@ struct ANCS : BigYAML
}
}
/* Extract EVNTs */
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>> animRes;
ancs.getAnimationResInfo(animRes);
for (const auto& res : animRes)
{
if (res.second.evntId)
{
hecl::SystemStringView sysStr(res.second.name);
hecl::ProjectPath evntYamlPath = outPath.getWithExtension((hecl::SystemString(_S(".")) +
sysStr.sys_str() +
_S(".evnt.yaml")).c_str());
hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType();
if (force || evntYamlType == hecl::ProjectPath::Type::None)
{
EVNT evnt;
if (pakRouter.lookupAndReadDNA(res.second.evntId, evnt, true))
{
FILE* fp = hecl::Fopen(evntYamlPath.getAbsolutePath().c_str(), _S("w"));
evnt.toYAMLFile(fp);
fclose(fp);
}
}
}
}
return true;
}
@ -612,22 +639,76 @@ struct ANCS : BigYAML
ancs.enumeratePrimitives([&](AnimationSet::MetaAnimPrimitive& prim) -> bool
{
hecl::SystemStringView sysStr(prim.animName);
prim.animId = inPath.ensureAuxInfo(sysStr.c_str());
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
prim.animId = pathOut;
return true;
});
std::unordered_map<std::string, atInt32> boneIdMap;
/* Write out CINF resources */
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
{
hecl::SystemStringView sysStr(arm.name);
hecl::ProjectPath pathOut = inPath.getWithExtension(sysStr.c_str(), true);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"), pathOut.getRelativePath().c_str());
CINF cinf(arm);
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
pathOut.getRelativePath().c_str());
CINF cinf(arm, boneIdMap);
cinf.write(w);
}
/* Write out ANIM resources */
ancs.animationSet.animResources.reserve(actor.actions.size());
for (const DNAANCS::Actor::Action& act : actor.actions)
{
hecl::SystemStringView sysStr(act.name);
hecl::ProjectPath pathOut = inPath.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
pathOut.getRelativePath().c_str());
ANIM anim(act, boneIdMap);
ancs.animationSet.animResources.emplace_back();
ancs.animationSet.animResources.back().animId = pathOut;
/* Check for associated EVNT YAML */
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) +
sysStr.sys_str() +
_S(".evnt.yaml")).c_str(), true);
if (evntYamlPath.getPathType() == hecl::ProjectPath::Type::File)
{
FILE* fp = hecl::Fopen(evntYamlPath.getAbsolutePath().c_str(), _S("r"));
if (fp)
{
EVNT evnt;
evnt.fromYAMLFile(fp);
fclose(fp);
anim.m_anim->evnt = evntYamlPath;
hecl::ProjectPath evntYamlOut = pathOut.getWithExtension(_S(".evnt"));
athena::io::FileWriter w(evntYamlOut.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
evntYamlOut.getRelativePath().c_str());
evnt.write(w);
ancs.animationSet.animResources.back().evntId = evntYamlPath;
}
}
anim.write(w);
}
/* Write out ANCS */
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
if (w.hasError())
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
outPath.getRelativePath().c_str());
ancs.write(w);
return true;
}
};

View File

@ -428,5 +428,76 @@ size_t ANIM::ANIM2::binarySize(size_t __isz) const
return __isz + DNAANIM::ComputeBitstreamSize(frames.size(), channels);
}
ANIM::ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt32>& idMap)
{
m_anim.reset(new struct ANIM0);
IANIM& newAnim = *m_anim;
newAnim.bones.reserve(act.channels.size());
size_t extChanCount = 0;
for (const BlenderAction::Channel& chan : act.channels)
{
auto search = idMap.find(chan.boneName);
if (search == idMap.cend())
{
Log.report(logvisor::Warning, "unable to find id for bone '%s'", chan.boneName.c_str());
continue;
}
extChanCount += std::max(zeus::PopCount(chan.attrMask), 2);
newAnim.bones.emplace_back(search->second, (chan.attrMask & 0x2) != 0);
}
newAnim.frames.reserve(act.frames.size());
for (int32_t frame : act.frames)
newAnim.frames.push_back(frame);
newAnim.channels.reserve(extChanCount);
newAnim.chanKeys.reserve(extChanCount);
for (const BlenderAction::Channel& chan : act.channels)
{
auto search = idMap.find(chan.boneName);
if (search == idMap.cend())
continue;
newAnim.channels.emplace_back();
DNAANIM::Channel& newChan = newAnim.channels.back();
newChan.type = DNAANIM::Channel::Type::Rotation;
newChan.id = search->second;
newAnim.chanKeys.emplace_back();
std::vector<DNAANIM::Value>& rotVals = newAnim.chanKeys.back();
rotVals.reserve(chan.keys.size());
for (const BlenderAction::Channel::Key& key : chan.keys)
{
rotVals.emplace_back(key.rotation.val.vec[0],
key.rotation.val.vec[1],
key.rotation.val.vec[2],
key.rotation.val.vec[3]);
}
if (chan.attrMask & 0x2)
{
newAnim.channels.emplace_back();
DNAANIM::Channel& newChan = newAnim.channels.back();
newChan.type = DNAANIM::Channel::Type::Translation;
newChan.id = search->second;
newAnim.chanKeys.emplace_back();
std::vector<DNAANIM::Value>& transVals = newAnim.chanKeys.back();
transVals.reserve(chan.keys.size());
for (const BlenderAction::Channel::Key& key : chan.keys)
{
transVals.emplace_back(key.position.val.vec[0],
key.position.val.vec[1],
key.position.val.vec[2]);
}
}
}
newAnim.mainInterval = act.interval;
}
}
}

View File

@ -179,6 +179,10 @@ struct ANIM : BigDNA
m_anim->sendANIMToBlender(os, rig);
}
using BlenderAction = hecl::BlenderConnection::DataStream::Actor::Action;
ANIM() = default;
ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt32>& idMap);
};
}

View File

@ -121,36 +121,49 @@ struct CINF : BigDNA
CINF() = default;
using Armature = hecl::BlenderConnection::DataStream::Actor::Armature;
int RecursiveAddArmatureBone(const Armature& armature, const Armature::Bone* bone, int parent, int& curId)
int RecursiveAddArmatureBone(const Armature& armature, const Armature::Bone* bone, int parent, int& curId,
std::unordered_map<std::string, atInt32>& idMap)
{
int selId;
auto search = idMap.find(bone->name);
if (search == idMap.end())
{
selId = curId++;
idMap.emplace(std::make_pair(bone->name, selId));
}
else
selId = search->second;
bones.emplace_back();
names.emplace_back();
Bone& boneOut = bones.back();
Name& nameOut = names.back();
nameOut.name = bone->name;
nameOut.boneId = curId;
boneOut.id = curId++;
nameOut.boneId = selId;
boneOut.id = selId;
boneOut.parentId = parent;
boneOut.origin = bone->origin;
boneOut.linkedCount = bone->children.size();
boneOut.linkedCount = bone->children.size() + 1;
boneOut.linked.reserve(boneOut.linkedCount);
const Armature::Bone* child;
boneOut.linked.push_back(parent);
for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i)
boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId));
boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, selId, idMap));
return boneOut.id;
}
CINF(const Armature& armature)
CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap)
{
idMap.reserve(armature.bones.size());
bones.reserve(armature.bones.size());
names.reserve(armature.bones.size());
const Armature::Bone* bone = armature.getRoot();
int curId = 3;
if (bone)
RecursiveAddArmatureBone(armature, bone, 2, curId);
RecursiveAddArmatureBone(armature, bone, 2, curId, idMap);
boneCount = bones.size();
nameCount = names.size();

View File

@ -261,7 +261,7 @@ struct SpecMP1 : SpecBase
for (std::pair<const std::string, DNAMP1::PAKBridge*>& pair : m_orderedPaks)
{
#if 0
const DNAMP1::PAK::Entry* ent = pair.second->getPAK().lookupEntry(UniqueID32("AF974083"));
const DNAMP1::PAK::Entry* ent = pair.second->getPAK().lookupEntry(UniqueID32("A4DFCAD6"));
if (ent)
{
DNAMP1::ANIM anim;
@ -296,6 +296,8 @@ struct SpecMP1 : SpecBase
});
}
process.waitUntilComplete();
return true;
}

View File

@ -265,6 +265,8 @@ struct SpecMP2 : SpecBase
});
}
process.waitUntilComplete();
return true;
}

View File

@ -395,6 +395,8 @@ struct SpecMP3 : SpecBase
});
});
}
process.waitUntilComplete();
}
if (doMPTFE)
@ -455,6 +457,8 @@ struct SpecMP3 : SpecBase
});
});
}
process.waitUntilComplete();
}
return true;
}

View File

@ -157,7 +157,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
for (const std::string& arm : armatureNames)
{
hecl::SystemStringView sysStr(arm);
hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.c_str());
hecl::ProjectPath subPath = path.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender);
if (pathTag)
{
@ -169,7 +169,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
for (const std::string& act : actionNames)
{
hecl::SystemStringView sysStr(act);
hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.c_str());
hecl::ProjectPath subPath = path.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true);
SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender);
if (pathTag)
{

View File

@ -9,6 +9,7 @@
#include "Runtime/GuiSys/CRasterFont.hpp"
#include "Runtime/Graphics/CModel.hpp"
#include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/Character/CCharLayoutInfo.hpp"
#include "DataSpec/DNACommon/TXTR.hpp"
@ -29,6 +30,7 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client
m_factoryMgr.AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame));
m_factoryMgr.AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory));
m_factoryMgr.AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory));
m_factoryMgr.AddFactory(FOURCC('CINF'), FFactoryFunc(FCharLayoutInfo));
}
void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj)
@ -98,6 +100,11 @@ SObjectTag ProjectResourceFactoryMP1::TagFromPath(const hecl::ProjectPath& path,
resTag.type = SBIG('FONT');
return true;
}
else if (!strcmp(className, "urde::DNAMP1::EVNT"))
{
resTag.type = SBIG('EVNT');
return true;
}
return false;
}))
{

View File

@ -11,7 +11,7 @@
#include "Runtime/Particle/CSwooshDescription.hpp"
#include "Runtime/Graphics/CModel.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/Graphics/CSkinRules.hpp"
#include "Runtime/Character/CSkinRules.hpp"
#include <cstdio>
using YAMLNode = athena::io::YAMLNode;

View File

@ -0,0 +1,51 @@
#include "CCharLayoutInfo.hpp"
#include "CToken.hpp"
namespace urde
{
void CCharLayoutNode::Bone::read(CInputStream& in)
{
x0_parentId = CSegId(in);
x4_origin.readBig(in);
u32 chCount = in.readUint32Big();
x10_children.reserve(chCount);
for (u32 i=0 ; i<chCount ; ++i)
x10_children.emplace_back(in);
}
CCharLayoutNode::CCharLayoutNode(CInputStream& in)
{
x0_boneCount = in.readUint32Big();
for (u32 i=0 ; i<x0_boneCount ; ++i)
{
u32 thisId = in.readUint32Big();
if (thisId >= 100)
{
Bone dummy;
dummy.read(in);
}
else
x108_bones[i].read(in);
}
}
CCharLayoutInfo::CCharLayoutInfo(CInputStream& in)
: x0_node(std::make_shared<CCharLayoutNode>(in)),
x8_segIdList(in)
{
atUint32 mapCount = in.readUint32Big();
for (int i=0 ; i<mapCount ; ++i)
{
std::string key = in.readString();
x18_segIdMap.emplace(key, in);
}
}
CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream& in, const CVParamTransfer&)
{
return TToken<CCharLayoutInfo>::GetIObjObjectFor(std::make_unique<CCharLayoutInfo>(in));
}
}

View File

@ -1,13 +1,43 @@
#ifndef __PSHAG_CCHARLAYOUTINFO_HPP__
#define __PSHAG_CCHARLAYOUTINFO_HPP__
#include "CFactoryMgr.hpp"
#include "IOStreams.hpp"
#include "CSegIdList.hpp"
#include "CSegId.hpp"
namespace urde
{
class CCharLayoutNode
{
public:
struct Bone
{
CSegId x0_parentId;
zeus::CVector3f x4_origin;
std::vector<CSegId> x10_children;
void read(CInputStream& in);
};
private:
u8 x0_boneCount;
CSegId x8_ids[100];
Bone x108_bones[100];
public:
CCharLayoutNode(CInputStream& in);
};
class CCharLayoutInfo
{
std::shared_ptr<CCharLayoutNode> x0_node;
CSegIdList x8_segIdList;
std::map<std::string, CSegId> x18_segIdMap;
public:
CCharLayoutInfo(CInputStream& in);
};
CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream&, const CVParamTransfer&);
}
#endif // __PSHAG_CCHARLAYOUTINFO_HPP__

View File

@ -12,4 +12,8 @@ add_library(RuntimeCommonCharacter
CHierarchyPoseBuilder.hpp CHierarchyPoseBuilder.cpp
CPoseAsTransforms.hpp CPoseAsTransforms.cpp
CVirtualBone.hpp CVirtualBone.cpp
CCharLayoutInfo.hpp CCharLayoutInfo.cpp
CSegIdList.hpp CSegIdList.cpp
CSegId.hpp CSegId.cpp
CSkinRules.hpp CSkinRules.cpp
CBodyState.hpp)

View File

@ -0,0 +1,21 @@
#ifndef __PSHAG_CSEGID_HPP__
#define __PSHAG_CSEGID_HPP__
#include "RetroTypes.hpp"
#include "IOStreams.hpp"
#include "zeus/CVector3f.hpp"
namespace urde
{
class CSegId
{
u8 x0_segId = 0xff;
public:
CSegId() = default;
CSegId(CInputStream& in) : x0_segId(in.readUint32Big()) {}
};
}
#endif // __PSHAG_CSEGID_HPP__

View File

@ -0,0 +1,14 @@
#include "CSegIdList.hpp"
namespace urde
{
CSegIdList::CSegIdList(CInputStream& in)
{
u32 count = in.readUint32Big();
x0_list.reserve(count);
for (u32 i=0 ; i<count ; ++i)
x0_list.emplace_back(in);
}
}

View File

@ -0,0 +1,19 @@
#ifndef __PSHAG_CSEGIDLIST_HPP__
#define __PSHAG_CSEGIDLIST_HPP__
#include "IOStreams.hpp"
#include "CSegId.hpp"
namespace urde
{
class CSegIdList
{
std::vector<CSegId> x0_list;
public:
CSegIdList(CInputStream& in);
};
}
#endif // __PSHAG_CSEGIDLIST_HPP__

View File

@ -0,0 +1,10 @@
#include "CSkinRules.hpp"
namespace urde
{
CSkinRules::CSkinRules(CInputStream& in)
{
}
}

View File

@ -1,11 +1,17 @@
#ifndef __PSHAG_CSKINRULES_HPP__
#define __PSHAG_CSKINRULES_HPP__
#include "RetroTypes.hpp"
#include "CVirtualBone.hpp"
namespace urde
{
class CSkinRules
{
std::vector<CVirtualBone> x0_bones;
public:
CSkinRules(CInputStream& in);
};
}

View File

@ -20,6 +20,5 @@ add_library(RuntimeCommonGraphics
CVertexMorphEffect.hpp CVertexMorphEffect.cpp
CMoviePlayer.hpp CMoviePlayer.cpp
CGraphicsPalette.hpp CGraphicsPalette.cpp
CSkinRules.hpp CSkinRules.cpp
CGraphics.hpp CGraphics.cpp
${PLAT_SRCS})

2
hecl

@ -1 +1 @@
Subproject commit 3ed5345c08fa0e93c5ab57099fc4714c41cf8457
Subproject commit d6b0f29fbce05f193822fbd4d05cd9b4d59d36f2

@ -1 +1 @@
Subproject commit dac460c4d531bd6e67ee76119d5203c3f3d4f48d
Subproject commit 5272e08fc7584dc45890707123a16eac2ed16b20