Cleanup & store extra part bit in msurf instead of lodinfo
This commit is contained in:
parent
adddbd5ecc
commit
4a61617e88
@ -173,7 +173,7 @@ namespace Components
|
||||
Register(new Threading());
|
||||
Register(new Toast());
|
||||
Register(new UIFeeder());
|
||||
//Register(new Updater());
|
||||
Register(new Updater());
|
||||
Register(new VisionFile());
|
||||
Register(new Voice());
|
||||
Register(new Vote());
|
||||
|
@ -221,7 +221,7 @@ namespace Components
|
||||
retn
|
||||
}
|
||||
}
|
||||
#pragma optimize( "", off )
|
||||
|
||||
void AssetHandler::ModifyAsset(Game::XAssetType type, Game::XAssetHeader asset, const std::string& name)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -235,63 +235,6 @@ namespace Components
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (type == Game::XAssetType::ASSET_TYPE_XANIMPARTS)
|
||||
{
|
||||
auto anim = asset.parts;
|
||||
if (anim->name == "unarmed_cowerstand_idle"s || anim->name == "civilian_walk_cool"s || anim->name == "civilian_run_upright"s)
|
||||
{
|
||||
auto str = Game::SL_FindString("j_spinelower");
|
||||
int interestingPart = 0;
|
||||
{
|
||||
if (anim->names[i] == str)
|
||||
{
|
||||
interestingPart = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Something interesting to do there
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (type == Game::XAssetType::ASSET_TYPE_XMODEL)
|
||||
//if (name == "body_urban_civ_female_a"s || name == "mp_body_opforce_arab_assault_a"s)
|
||||
{
|
||||
|
||||
if (name == "body_urban_civ_male_aa"s)
|
||||
{
|
||||
printf("");
|
||||
}
|
||||
|
||||
const auto model = asset.model;
|
||||
|
||||
int total =
|
||||
model->noScalePartBits[0] |
|
||||
model->noScalePartBits[1] |
|
||||
model->noScalePartBits[2] |
|
||||
model->noScalePartBits[3] |
|
||||
model->noScalePartBits[4] |
|
||||
model->noScalePartBits[5];
|
||||
|
||||
if (total != 0)
|
||||
{
|
||||
printf("");
|
||||
}
|
||||
|
||||
if (!model->quats || !model->trans || model->numBones < 10)
|
||||
{
|
||||
// Unlikely candidate
|
||||
return;
|
||||
}
|
||||
static Utils::Memory::Allocator allocator{};
|
||||
|
||||
//
|
||||
//if (name == "body_urban_civ_female_a"s)
|
||||
{
|
||||
Assets::IXModel::ConvertPlayerModelFromSingleplayerToMultiplayer(model, allocator);
|
||||
printf("");
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Game::ASSET_TYPE_MATERIAL && (name == "gfx_distortion_knife_trail" || name == "gfx_distortion_heat_far" || name == "gfx_distortion_ring_light" || name == "gfx_distortion_heat") && asset.material->info.sortKey >= 43)
|
||||
{
|
||||
@ -348,7 +291,6 @@ namespace Components
|
||||
asset.gfxWorld->sortKeyDistortion = 43;
|
||||
}
|
||||
}
|
||||
#pragma optimize( "", on )
|
||||
|
||||
bool AssetHandler::IsAssetEligible(Game::XAssetType type, Game::XAssetHeader* asset)
|
||||
{
|
||||
|
@ -11,8 +11,19 @@ namespace Assets
|
||||
{
|
||||
header->model = builder->getIW4OfApi()->read<Game::XModel>(Game::XAssetType::ASSET_TYPE_XMODEL, name);
|
||||
|
||||
if (!header->model)
|
||||
{
|
||||
// In that case if we want to convert it later potentially we have to grab it now:
|
||||
header->model = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_XMODEL, name.data()).model;
|
||||
}
|
||||
|
||||
if (header->model)
|
||||
{
|
||||
if (Components::ZoneBuilder::zb_sp_to_mp.get<bool>())
|
||||
{
|
||||
Assets::IXModel::ConvertPlayerModelFromSingleplayerToMultiplayer(header->model, *builder->getAllocator());
|
||||
}
|
||||
|
||||
// ???
|
||||
if (header->model->physCollmap)
|
||||
{
|
||||
@ -305,16 +316,13 @@ namespace Assets
|
||||
uint8_t IXModel::GetHighestAffectingBoneIndex(const Game::XModelLodInfo* lod)
|
||||
{
|
||||
uint8_t highestBoneIndex = 0;
|
||||
constexpr auto LENGTH = 6;
|
||||
|
||||
{
|
||||
for (auto surfIndex = 0; surfIndex < lod->numsurfs; surfIndex++)
|
||||
{
|
||||
const auto surface = &lod->surfs[surfIndex];
|
||||
|
||||
auto vertsBlendOffset = 0;
|
||||
|
||||
int rebuiltPartBits[LENGTH]{};
|
||||
std::unordered_set<uint8_t> affectingBones{};
|
||||
|
||||
const auto registerBoneAffectingSurface = [&](unsigned int offset) {
|
||||
@ -380,7 +388,7 @@ namespace Assets
|
||||
const auto lod = &model->lodInfo[i];
|
||||
int lodPartBits[6]{};
|
||||
|
||||
for (auto surfIndex = 0; surfIndex < lod->numsurfs; surfIndex++)
|
||||
for (unsigned short surfIndex = 0; surfIndex < lod->numsurfs; surfIndex++)
|
||||
{
|
||||
const auto surface = &lod->surfs[surfIndex];
|
||||
|
||||
@ -400,7 +408,7 @@ namespace Assets
|
||||
|
||||
|
||||
// 1 bone weight
|
||||
for (auto vertIndex = 0; vertIndex < surface->vertInfo.vertCount[0]; vertIndex++)
|
||||
for (unsigned int vertIndex = 0; vertIndex < surface->vertInfo.vertCount[0]; vertIndex++)
|
||||
{
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 0);
|
||||
|
||||
@ -408,7 +416,7 @@ namespace Assets
|
||||
}
|
||||
|
||||
// 2 bone weights
|
||||
for (auto vertIndex = 0; vertIndex < surface->vertInfo.vertCount[1]; vertIndex++)
|
||||
for (unsigned int vertIndex = 0; vertIndex < surface->vertInfo.vertCount[1]; vertIndex++)
|
||||
{
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 0);
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 1);
|
||||
@ -417,7 +425,7 @@ namespace Assets
|
||||
}
|
||||
|
||||
// 3 bone weights
|
||||
for (auto vertIndex = 0; vertIndex < surface->vertInfo.vertCount[2]; vertIndex++)
|
||||
for (unsigned int vertIndex = 0; vertIndex < surface->vertInfo.vertCount[2]; vertIndex++)
|
||||
{
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 0);
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 1);
|
||||
@ -427,7 +435,7 @@ namespace Assets
|
||||
}
|
||||
|
||||
// 4 bone weights
|
||||
for (auto vertIndex = 0; vertIndex < surface->vertInfo.vertCount[3]; vertIndex++)
|
||||
for (unsigned int vertIndex = 0; vertIndex < surface->vertInfo.vertCount[3]; vertIndex++)
|
||||
{
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 0);
|
||||
registerBoneAffectingSurface(vertsBlendOffset + 1);
|
||||
@ -437,7 +445,7 @@ namespace Assets
|
||||
vertsBlendOffset += 7;
|
||||
}
|
||||
|
||||
for (auto vertListIndex = 0; vertListIndex < surface->vertListCount; vertListIndex++)
|
||||
for (unsigned int vertListIndex = 0; vertListIndex < surface->vertListCount; vertListIndex++)
|
||||
{
|
||||
affectingBones.emplace(static_cast<uint8_t>(surface->vertList[vertListIndex].boneOffset / sizeof(Game::DObjSkelMat)));
|
||||
}
|
||||
@ -481,7 +489,7 @@ namespace Assets
|
||||
// Start with backing up parent links that we will have to restore
|
||||
// We'll restore them at the end
|
||||
std::map<std::string, std::string> parentsToRestore{};
|
||||
for (int i = model->numRootBones; i < model->numBones; i++)
|
||||
for (uint8_t i = model->numRootBones; i < model->numBones; i++)
|
||||
{
|
||||
parentsToRestore[Game::SL_ConvertToString(model->boneNames[i])] = GetParentOfBone(model, i);
|
||||
}
|
||||
@ -498,8 +506,6 @@ namespace Assets
|
||||
const uint8_t newBoneIndex = atPosition;
|
||||
const uint8_t newBoneIndexMinusRoot = atPosition - model->numRootBones;
|
||||
|
||||
Components::Logger::Print("Inserting bone {} at position {} (between {} and {})\n", boneName, atPosition, Game::SL_ConvertToString(model->boneNames[atPosition - 1]), Game::SL_ConvertToString(model->boneNames[atPosition + 1]));
|
||||
|
||||
// Reallocate
|
||||
const auto newBoneNames = allocator.allocateArray<uint16_t>(newBoneCount);
|
||||
const auto newMats = allocator.allocateArray<Game::DObjAnimMat>(newBoneCount);
|
||||
@ -518,8 +524,8 @@ namespace Assets
|
||||
const uint8_t atPositionM1 = atPosition - model->numRootBones;
|
||||
|
||||
// should be equal to model->numBones
|
||||
int total = lengthOfFirstPart + lengthOfSecondPart;
|
||||
assert(total = model->numBones);
|
||||
unsigned int total = lengthOfFirstPart + lengthOfSecondPart;
|
||||
assert(total == model->numBones);
|
||||
|
||||
// should be equal to model->numBones - model->numRootBones
|
||||
int totalM1 = lengthOfFirstPartM1 + lengthOfSecondPartM1;
|
||||
@ -599,9 +605,10 @@ namespace Assets
|
||||
{
|
||||
const auto lod = &model->lodInfo[lodIndex];
|
||||
|
||||
if ((lod->partBits[5] & 0x1) == 0x1)
|
||||
if ((lod->modelSurfs->partBits[5] & 0x1) == 0x1)
|
||||
{
|
||||
// surface lod already converted (more efficient)
|
||||
std::memcpy(lod->partBits, lod->modelSurfs->partBits, 6 * sizeof(uint32_t));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -630,7 +637,7 @@ namespace Assets
|
||||
|
||||
if (index < 0 || index >= model->numBones)
|
||||
{
|
||||
Components::Logger::Print("Unexpected 'bone index' {} out of {} bones while working vertex blend of model {} lod {} surf {}\n", index, model->numBones, model->name, lodIndex, surfIndex);
|
||||
Components::Logger::Print("Unexpected 'bone index' {} out of {} bones while working vertex blend of: xmodel {} lod {} xmodelsurf {} surf #{}", index, model->numBones, model->name, lodIndex, lod->modelSurfs->name, lodIndex, surfIndex);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@ -652,7 +659,7 @@ namespace Assets
|
||||
|
||||
if (index < 0 || index >= model->numBones)
|
||||
{
|
||||
Components::Logger::Print("Unexpected 'bone index' {} out of {} bones while working list blend of model {} lod {} surf {}\n", index, model->numBones, model->name, lodIndex, surfIndex);
|
||||
Components::Logger::Print("Unexpected 'bone index' {} out of {} bones while working vertex list of: xmodel {} lod {} xmodelsurf {} surf #{}\n", index, model->numBones, model->name, lodIndex, lod->modelSurfs->name, surfIndex);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@ -711,39 +718,17 @@ namespace Assets
|
||||
const auto key = kv.first;
|
||||
const auto beforeVal = kv.second;
|
||||
|
||||
const auto parentIndex = GetIndexOfBone(model, beforeVal);
|
||||
const auto p = GetIndexOfBone(model, beforeVal);
|
||||
const auto index = GetIndexOfBone(model, key);
|
||||
SetParentIndexOfBone(model, index, parentIndex);
|
||||
SetParentIndexOfBone(model, index, p);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
// check
|
||||
for (const auto& kv : parentsToRestore)
|
||||
{
|
||||
const auto key = kv.first;
|
||||
const auto beforeVal = kv.second;
|
||||
|
||||
const auto index = GetIndexOfBone(model, key);
|
||||
const auto afterVal = GetParentOfBone(model, index);
|
||||
|
||||
if (beforeVal != afterVal)
|
||||
{
|
||||
printf("");
|
||||
}
|
||||
}
|
||||
//
|
||||
#endif
|
||||
|
||||
return atPosition; // Bone index of added bone
|
||||
};
|
||||
|
||||
|
||||
void IXModel::TransferWeights(Game::XModel* model, const uint8_t origin, const uint8_t destination)
|
||||
{
|
||||
const auto from = Game::SL_ConvertToString(model->boneNames[origin]);
|
||||
const auto to = Game::SL_ConvertToString(model->boneNames[destination]);
|
||||
Components::Logger::Print("Transferring bone weights from {} to {}\n", from, to);
|
||||
|
||||
const auto originalWeights = model->baseMat[origin].transWeight;
|
||||
model->baseMat[origin].transWeight = model->baseMat[destination].transWeight;
|
||||
model->baseMat[destination].transWeight = originalWeights;
|
||||
@ -887,15 +872,34 @@ namespace Assets
|
||||
|
||||
void IXModel::ConvertPlayerModelFromSingleplayerToMultiplayer(Game::XModel* model, Utils::Memory::Allocator& allocator)
|
||||
{
|
||||
auto indexOfSpine = GetIndexOfBone(model, "j_spinelower");
|
||||
if (indexOfSpine < UCHAR_MAX) // It has a spine so it must be some sort of humanoid
|
||||
if (model->name == "body_airport_com_a"s)
|
||||
{
|
||||
printf("");
|
||||
}
|
||||
|
||||
std::string requiredBonesForHumanoid[] = {
|
||||
"j_spinelower",
|
||||
"j_spineupper",
|
||||
"j_spine4",
|
||||
"j_mainroot"
|
||||
};
|
||||
|
||||
for (const auto& required : requiredBonesForHumanoid)
|
||||
{
|
||||
if (GetIndexOfBone(model, required) == UCHAR_MAX)
|
||||
{
|
||||
// Not humanoid - nothing to do
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto indexOfSpine = GetIndexOfBone(model, "j_spinelower");
|
||||
const auto nameOfParent = GetParentOfBone(model, indexOfSpine);
|
||||
|
||||
if (GetIndexOfBone(model, "torso_stabilizer") == UCHAR_MAX) // Singleplayer model is likely
|
||||
{
|
||||
|
||||
Components::Logger::Print("Converting {}\n", model->name);
|
||||
Components::Logger::Print("Converting {} skeleton from SP to MP...\n", model->name);
|
||||
|
||||
// No stabilizer - let's do surgery
|
||||
// We're trying to get there:
|
||||
@ -917,13 +921,8 @@ namespace Assets
|
||||
if (root < UCHAR_MAX) {
|
||||
|
||||
// Add pelvis
|
||||
#if false
|
||||
const uint8_t backLow = InsertBone(model, "back_low", "j_spinelower", allocator);
|
||||
TransferWeights(model, GetIndexOfBone(model, "j_spinelower"), backLow);
|
||||
SetParentIndexOfBone(model, GetIndexOfBone(model, "j_spineupper"), backLow);
|
||||
#else
|
||||
const uint8_t indexOfPelvis = InsertBone(model, "pelvis", "j_mainroot", allocator);
|
||||
SetBoneQuaternion(model, indexOfPelvis, true, -0.494f, -0.506f, -0.506f, 0.494);
|
||||
SetBoneQuaternion(model, indexOfPelvis, true, -0.494f, -0.506f, -0.506f, 0.494f);
|
||||
|
||||
TransferWeights(model, root, indexOfPelvis);
|
||||
|
||||
@ -968,33 +967,35 @@ namespace Assets
|
||||
// This doesn't feel like it should be necessary
|
||||
// It is, on singleplayer models unfortunately. Could we add an extra bone to compensate this?
|
||||
// Or compensate it another way?
|
||||
SetBoneTrans(model, GetIndexOfBone(model, "j_spinelower"), false, 0.07, 0.0f, 5.2f);
|
||||
SetBoneTrans(model, GetIndexOfBone(model, "j_spinelower"), false, 0.07f, 0.0f, 5.2f);
|
||||
|
||||
// These are often messed up on civilian models, but there is no obvious way to tell from code
|
||||
const auto stowedBack = GetIndexOfBone(model, "tag_stowed_back");
|
||||
if (stowedBack != UCHAR_MAX)
|
||||
auto stowedBack = GetIndexOfBone(model, "tag_stowed_back");
|
||||
if (stowedBack == UCHAR_MAX)
|
||||
{
|
||||
SetBoneTrans(model, stowedBack, false, -0.32f, -6.27f, -2.65F);
|
||||
SetBoneQuaternion(model, stowedBack, false, -0.044, 0.088, -0.995, 0.025);
|
||||
SetBoneTrans(model, stowedBack, true, -9.571f, -2.654f, 51.738f);
|
||||
SetBoneQuaternion(model, stowedBack, true, -0.071f, 0.0f, -0.997f, 0.0f);
|
||||
stowedBack = InsertBone(model, "tag_stowed_back", "j_spine4", allocator);
|
||||
}
|
||||
|
||||
if (stowedBack != UCHAR_MAX)
|
||||
SetBoneTrans(model, stowedBack, false, -0.32f, -6.27f, -2.65F);
|
||||
SetBoneQuaternion(model, stowedBack, false, -0.044f, 0.088f, -0.995f, 0.025f);
|
||||
SetBoneTrans(model, stowedBack, true, -9.571f, -2.654f, 51.738f);
|
||||
SetBoneQuaternion(model, stowedBack, true, -0.071f, 0.0f, -0.997f, 0.0f);
|
||||
|
||||
auto stowedRear = GetIndexOfBone(model, "tag_stowed_hip_rear");
|
||||
if (stowedRear == UCHAR_MAX)
|
||||
{
|
||||
const auto stowedRear = GetIndexOfBone(model, "tag_stowed_hip_rear");
|
||||
stowedBack = InsertBone(model, "tag_stowed_hip_rear", "pelvis", allocator);
|
||||
}
|
||||
|
||||
SetBoneTrans(model, stowedRear, false, -0.75f, -6.45f, -4.99f);
|
||||
SetBoneQuaternion(model, stowedRear, false, -0.553f, -0.062f, -0.049f, 0.830f);
|
||||
SetBoneTrans(model, stowedBack, true, -9.866f, -4.989f, 36.315f);
|
||||
SetBoneQuaternion(model, stowedRear, true, -0.054, -0.025f, -0.975f, 0.214f);
|
||||
}
|
||||
#endif
|
||||
SetBoneQuaternion(model, stowedRear, true, -0.054f, -0.025f, -0.975f, 0.214f);
|
||||
|
||||
|
||||
RebuildPartBits(model);
|
||||
}
|
||||
}
|
||||
printf("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -314,8 +314,6 @@ namespace Components
|
||||
|
||||
QuickPatch::QuickPatch()
|
||||
{
|
||||
|
||||
|
||||
// Filtering any mapents that is intended for Spec:Ops gamemode (CODO) and prevent them from spawning
|
||||
Utils::Hook(0x5FBD6E, QuickPatch::IsDynClassname_Stub, HOOK_CALL).install()->quick();
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <version.hpp>
|
||||
|
||||
#include "AssetInterfaces/ILocalizeEntry.hpp"
|
||||
|
||||
#include "Events.hpp"
|
||||
#include "Branding.hpp"
|
||||
|
||||
namespace Components
|
||||
@ -22,6 +24,8 @@ namespace Components
|
||||
iw4of::api ZoneBuilder::ExporterAPI(GetExporterAPIParams());
|
||||
std::string ZoneBuilder::DumpingZone{};
|
||||
|
||||
Dvar::Var ZoneBuilder::zb_sp_to_mp{};
|
||||
|
||||
ZoneBuilder::Zone::Zone(const std::string& name, const std::string& sourceName, const std::string& destination) :
|
||||
indexStart(0), externalSize(0),
|
||||
// Reserve 100MB by default.
|
||||
@ -115,7 +119,7 @@ namespace Components
|
||||
return &iw4ofApi;
|
||||
}
|
||||
|
||||
void ZoneBuilder::Zone::Zone::build()
|
||||
void ZoneBuilder::Zone::build()
|
||||
{
|
||||
if (!this->dataMap.isValid())
|
||||
{
|
||||
@ -1300,6 +1304,8 @@ namespace Components
|
||||
// don't remap techsets
|
||||
Utils::Hook::Nop(0x5BC791, 5);
|
||||
|
||||
ZoneBuilder::zb_sp_to_mp = Game::Dvar_RegisterBool("zb_sp_to_mp", false, Game::DVAR_ARCHIVE, "Attempt to convert singleplayer assets to multiplayer format whenever possible");
|
||||
|
||||
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader /* asset*/, const std::string& name, bool* /*restrict*/)
|
||||
{
|
||||
if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current())
|
||||
@ -1402,7 +1408,7 @@ namespace Components
|
||||
if (assetHeader.data)
|
||||
{
|
||||
ExporterAPI.write(type, assetHeader.data);
|
||||
const auto typeName = Game::DB_GetXAssetTypeName(type) ;
|
||||
const auto typeName = Game::DB_GetXAssetTypeName(type);
|
||||
|
||||
if (type != lastTypeEncountered)
|
||||
{
|
||||
@ -1558,7 +1564,7 @@ namespace Components
|
||||
}, &type, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZoneBuilder::~ZoneBuilder()
|
||||
|
@ -135,6 +135,8 @@ namespace Components
|
||||
static void BeginAssetTrace(const std::string& zone);
|
||||
static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace();
|
||||
|
||||
static Dvar::Var zb_sp_to_mp;
|
||||
|
||||
static Game::XAssetHeader GetEmptyAssetIfCommon(Game::XAssetType type, const std::string& name, Zone* builder);
|
||||
static std::string GetDumpingZonePath();
|
||||
static void RefreshExporterWorkDirectory();
|
||||
|
@ -1066,7 +1066,7 @@ namespace Game
|
||||
|
||||
struct XSurfaceVertexInfo
|
||||
{
|
||||
__int16 vertCount[4];
|
||||
unsigned __int16 vertCount[4];
|
||||
unsigned __int16* vertsBlend;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user