Correct handling of empty skinned models

This commit is contained in:
Jack Andersen 2018-11-08 20:57:16 -10:00
parent 3f7431286c
commit 87e5aea6f5
1 changed files with 82 additions and 76 deletions

View File

@ -1345,43 +1345,45 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath,
if (!modelCookFunc(*modelPath)) if (!modelCookFunc(*modelPath))
Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data()); Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data());
athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false);
if (skinIO.hasError())
Log.report(logvisor::Fatal, _SYS_STR("unable to open '%s'"), skinIntPath.getRelativePath().data());
std::vector<std::string> boneNames;
uint32_t boneNameCount = skinIO.readUint32Big();
boneNames.reserve(boneNameCount);
for (uint32_t i=0 ; i<boneNameCount ; ++i)
boneNames.push_back(skinIO.readString());
std::vector<std::pair<std::vector<std::pair<uint32_t, float>>, uint32_t>> skins; std::vector<std::pair<std::vector<std::pair<uint32_t, float>>, uint32_t>> skins;
uint32_t skinCount = skinIO.readUint32Big(); uint32_t posCount = 0;
skins.resize(skinCount); uint32_t normCount = 0;
for (uint32_t i=0 ; i<skinCount ; ++i) athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false);
if (!skinIO.hasError())
{ {
std::pair<std::vector<std::pair<uint32_t, float>>, uint32_t>& virtualBone = skins[i]; std::vector<std::string> boneNames;
uint32_t bindCount = skinIO.readUint32Big(); uint32_t boneNameCount = skinIO.readUint32Big();
virtualBone.first.reserve(bindCount); boneNames.reserve(boneNameCount);
for (uint32_t j=0 ; j<bindCount ; ++j) for (uint32_t i=0 ; i<boneNameCount ; ++i)
boneNames.push_back(skinIO.readString());
uint32_t skinCount = skinIO.readUint32Big();
skins.resize(skinCount);
for (uint32_t i=0 ; i<skinCount ; ++i)
{ {
uint32_t bIdx = skinIO.readUint32Big(); std::pair<std::vector<std::pair<uint32_t, float>>, uint32_t>& virtualBone = skins[i];
float weight = skinIO.readFloatBig(); uint32_t bindCount = skinIO.readUint32Big();
const std::string& name = boneNames[bIdx]; virtualBone.first.reserve(bindCount);
auto search = boneIdMap.find(name); for (uint32_t j=0 ; j<bindCount ; ++j)
if (search == boneIdMap.cend()) {
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s", uint32_t bIdx = skinIO.readUint32Big();
name.c_str(), inPath.getRelativePathUTF8().data()); float weight = skinIO.readFloatBig();
virtualBone.first.emplace_back(search->second, weight); const std::string& name = boneNames[bIdx];
auto search = boneIdMap.find(name);
if (search == boneIdMap.cend())
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s",
name.c_str(), inPath.getRelativePathUTF8().data());
virtualBone.first.emplace_back(search->second, weight);
}
virtualBone.second = skinIO.readUint32Big();
} }
virtualBone.second = skinIO.readUint32Big();
posCount = skinIO.readUint32Big();
normCount = skinIO.readUint32Big();
skinIO.close();
} }
uint32_t posCount = skinIO.readUint32Big();
uint32_t normCount = skinIO.readUint32Big();
skinIO.close();
athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath());
skinOut.writeUint32Big(skins.size()); skinOut.writeUint32Big(skins.size());
@ -1483,58 +1485,61 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath,
if (!modelCookFunc(*modelPath)) if (!modelCookFunc(*modelPath))
Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data()); Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data());
athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false); uint32_t bankCount = 0;
if (skinIO.hasError())
Log.report(logvisor::Fatal, _SYS_STR("unable to open '%s'"), skinIntPath.getRelativePath().data());
std::vector<std::vector<uint32_t>> skinBanks; std::vector<std::vector<uint32_t>> skinBanks;
uint32_t bankCount = skinIO.readUint32Big();
skinBanks.reserve(bankCount);
for (uint32_t i=0 ; i<bankCount ; ++i)
{
skinBanks.emplace_back();
std::vector<uint32_t>& bonesOut = skinBanks.back();
uint32_t boneCount = skinIO.readUint32Big();
bonesOut.reserve(boneCount);
for (uint32_t j=0 ; j<boneCount ; ++j)
{
uint32_t idx = skinIO.readUint32Big();
bonesOut.push_back(idx);
}
}
std::vector<std::string> boneNames; std::vector<std::string> boneNames;
uint32_t boneNameCount = skinIO.readUint32Big();
boneNames.reserve(boneNameCount);
for (uint32_t i=0 ; i<boneNameCount ; ++i)
boneNames.push_back(skinIO.readString());
std::vector<std::vector<std::pair<uint32_t, float>>> skins; std::vector<std::vector<std::pair<uint32_t, float>>> skins;
uint32_t skinCount = skinIO.readUint32Big(); atUint64 uniquePoolIndexLen = 0;
skins.resize(skinCount); std::unique_ptr<atUint8[]> uniquePoolIndexData;
for (uint32_t i=0 ; i<skinCount ; ++i) athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false);
if (!skinIO.hasError())
{ {
std::vector<std::pair<uint32_t, float>>& virtualBone = skins[i]; bankCount = skinIO.readUint32Big();
uint32_t bindCount = skinIO.readUint32Big(); skinBanks.reserve(bankCount);
virtualBone.reserve(bindCount); for (uint32_t i=0 ; i<bankCount ; ++i)
for (uint32_t j=0 ; j<bindCount ; ++j)
{ {
uint32_t bIdx = skinIO.readUint32Big(); skinBanks.emplace_back();
float weight = skinIO.readFloatBig(); std::vector<uint32_t>& bonesOut = skinBanks.back();
const std::string& name = boneNames[bIdx]; uint32_t boneCount = skinIO.readUint32Big();
auto search = boneIdMap.find(name); bonesOut.reserve(boneCount);
if (search == boneIdMap.cend()) for (uint32_t j=0 ; j<boneCount ; ++j)
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s", {
name.c_str(), inPath.getRelativePathUTF8().data()); uint32_t idx = skinIO.readUint32Big();
virtualBone.emplace_back(search->second, weight); bonesOut.push_back(idx);
}
} }
uint32_t boneNameCount = skinIO.readUint32Big();
boneNames.reserve(boneNameCount);
for (uint32_t i=0 ; i<boneNameCount ; ++i)
boneNames.push_back(skinIO.readString());
uint32_t skinCount = skinIO.readUint32Big();
skins.resize(skinCount);
for (uint32_t i=0 ; i<skinCount ; ++i)
{
std::vector<std::pair<uint32_t, float>>& virtualBone = skins[i];
uint32_t bindCount = skinIO.readUint32Big();
virtualBone.reserve(bindCount);
for (uint32_t j=0 ; j<bindCount ; ++j)
{
uint32_t bIdx = skinIO.readUint32Big();
float weight = skinIO.readFloatBig();
const std::string& name = boneNames[bIdx];
auto search = boneIdMap.find(name);
if (search == boneIdMap.cend())
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s",
name.c_str(), inPath.getRelativePathUTF8().data());
virtualBone.emplace_back(search->second, weight);
}
}
uniquePoolIndexLen = skinIO.length() - skinIO.position();
uniquePoolIndexData = skinIO.readUBytes(uniquePoolIndexLen);
skinIO.close();
} }
atUint64 uniquePoolIndexLen = skinIO.length() - skinIO.position();
auto uniquePoolIndexData = skinIO.readUBytes(uniquePoolIndexLen);
skinIO.close();
athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath());
skinOut.writeUint32Big(bankCount); skinOut.writeUint32Big(bankCount);
@ -1563,7 +1568,8 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath,
} }
} }
skinOut.writeUBytes(uniquePoolIndexData.get(), uniquePoolIndexLen); if (uniquePoolIndexLen)
skinOut.writeUBytes(uniquePoolIndexData.get(), uniquePoolIndexLen);
return true; return true;
} }