83 lines
5.2 KiB
C++
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
|