MetaCore/Source/MetaCorePhysics/Private/MetaCorePhysicsSettings.cpp
2026-07-17 09:42:32 +08:00

83 lines
5.2 KiB
C++

#include "MetaCorePhysics/MetaCorePhysics.h"
#include "MetaCoreFoundation/MetaCoreArchive.h"
#include <algorithm>
#include <cmath>
#include <fstream>
namespace MetaCore {
MetaCorePhysicsSettingsDocument MetaCoreBuildDefaultPhysicsSettings() {
MetaCorePhysicsSettingsDocument result;
result.LayerNames.resize(32U);
result.CollisionMasks.assign(32U, 0xFFFFFFFFU);
result.LayerNames[0] = "Default";
for (std::size_t index = 1; index < result.LayerNames.size(); ++index) result.LayerNames[index] = "Layer " + std::to_string(index);
return result;
}
bool MetaCoreValidatePhysicsSettings(MetaCorePhysicsSettingsDocument& document, std::vector<std::string>* issues) {
bool valid = true;
const auto report = [&](std::string value) { valid = false; if (issues) issues->push_back(std::move(value)); };
if (!std::isfinite(document.Gravity.x) || !std::isfinite(document.Gravity.y) || !std::isfinite(document.Gravity.z)) {
report("Gravity 必须为有限值"); document.Gravity = glm::vec3(0.0F, 0.0F, -9.81F);
}
if (!std::isfinite(document.FixedTimeStep) || document.FixedTimeStep < 0.001 || document.FixedTimeStep > 1.0) {
report("FixedTimeStep 必须位于 [0.001, 1.0]"); document.FixedTimeStep = 1.0 / 60.0;
}
if (!std::isfinite(document.MaxFrameDelta) || document.MaxFrameDelta < document.FixedTimeStep || document.MaxFrameDelta > 1.0) {
report("MaxFrameDelta 无效"); document.MaxFrameDelta = 0.25;
}
if (document.MaxFixedStepsPerFrame == 0U || document.MaxFixedStepsPerFrame > 32U) {
report("MaxFixedStepsPerFrame 必须位于 [1, 32]"); document.MaxFixedStepsPerFrame = 4U;
}
if (document.LayerNames.size() != 32U) { report("碰撞层名称必须恰好为 32 项"); document.LayerNames.resize(32U); }
if (document.CollisionMasks.size() != 32U) { report("碰撞矩阵必须恰好为 32 项"); document.CollisionMasks.resize(32U, 0xFFFFFFFFU); }
for (std::uint32_t lhs = 0; lhs < 32U; ++lhs) for (std::uint32_t rhs = lhs + 1U; rhs < 32U; ++rhs) {
const bool enabled = ((document.CollisionMasks[lhs] >> rhs) & 1U) != 0U && ((document.CollisionMasks[rhs] >> lhs) & 1U) != 0U;
if (enabled) { document.CollisionMasks[lhs] |= 1U << rhs; document.CollisionMasks[rhs] |= 1U << lhs; }
else { document.CollisionMasks[lhs] &= ~(1U << rhs); document.CollisionMasks[rhs] &= ~(1U << lhs); }
}
return valid;
}
bool MetaCoreWritePhysicsSettings(const std::filesystem::path& path, const MetaCorePhysicsSettingsDocument& document,
const MetaCoreTypeRegistry& registry) {
const auto bytes = MetaCoreSerializeToBytes(document, registry); if (!bytes) return false;
std::error_code error; std::filesystem::create_directories(path.parent_path(), error);
std::ofstream output(path, std::ios::binary | std::ios::trunc);
if (!output) return false;
output.write(reinterpret_cast<const char*>(bytes->data()), static_cast<std::streamsize>(bytes->size())); return output.good();
}
std::optional<MetaCorePhysicsSettingsDocument> MetaCoreReadPhysicsSettings(const std::filesystem::path& path,
const MetaCoreTypeRegistry& registry) {
std::ifstream input(path, std::ios::binary | std::ios::ate); if (!input) return std::nullopt;
const auto size = static_cast<std::size_t>(input.tellg()); input.seekg(0); std::vector<std::byte> bytes(size);
if (size && !input.read(reinterpret_cast<char*>(bytes.data()), static_cast<std::streamsize>(size))) return std::nullopt;
MetaCorePhysicsSettingsDocument result;
if (!MetaCoreDeserializeFromBytes(std::span<const std::byte>(bytes.data(), bytes.size()), result, registry)) return std::nullopt;
// Version 1 used Bullet's Y-up convention. MetaCore is Z-up, so migrate the
// complete gravity vector instead of only replacing the old default value.
if (result.Version < 2U) {
result.Gravity = glm::vec3(result.Gravity.x, result.Gravity.z, result.Gravity.y);
result.Version = 2U;
}
(void)MetaCoreValidatePhysicsSettings(result); return result;
}
bool MetaCoreWritePhysicsMaterial(const std::filesystem::path& path, const MetaCorePhysicsMaterialDocument& document,
const MetaCoreTypeRegistry& registry) {
const auto bytes=MetaCoreSerializeToBytes(document,registry);if(!bytes)return false;std::error_code error;std::filesystem::create_directories(path.parent_path(),error);
std::ofstream output(path,std::ios::binary|std::ios::trunc);if(!output)return false;output.write(reinterpret_cast<const char*>(bytes->data()),static_cast<std::streamsize>(bytes->size()));return output.good();
}
std::optional<MetaCorePhysicsMaterialDocument> MetaCoreReadPhysicsMaterial(const std::filesystem::path& path,
const MetaCoreTypeRegistry& registry) {
std::ifstream input(path,std::ios::binary|std::ios::ate);if(!input)return std::nullopt;const auto size=static_cast<std::size_t>(input.tellg());input.seekg(0);std::vector<std::byte> bytes(size);
if(size&&!input.read(reinterpret_cast<char*>(bytes.data()),static_cast<std::streamsize>(size)))return std::nullopt;MetaCorePhysicsMaterialDocument result;if(!MetaCoreDeserializeFromBytes(std::span<const std::byte>(bytes.data(),bytes.size()),result,registry))return std::nullopt;return result;
}
} // namespace MetaCore