godot-module-template/engine/thirdparty/jolt_physics/Jolt/Physics/DeterminismLog.h

160 lines
3.9 KiB
C++

// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2022 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#pragma once
//#define JPH_ENABLE_DETERMINISM_LOG
#ifdef JPH_ENABLE_DETERMINISM_LOG
#include <Jolt/Physics/Body/BodyID.h>
#include <Jolt/Physics/Collision/Shape/SubShapeID.h>
JPH_SUPPRESS_WARNINGS_STD_BEGIN
#include <iomanip>
#include <fstream>
JPH_SUPPRESS_WARNINGS_STD_END
JPH_NAMESPACE_BEGIN
/// A simple class that logs the state of the simulation. The resulting text file can be used to diff between platforms and find issues in determinism.
class DeterminismLog
{
private:
JPH_INLINE uint32 Convert(float inValue) const
{
return *(uint32 *)&inValue;
}
JPH_INLINE uint64 Convert(double inValue) const
{
return *(uint64 *)&inValue;
}
public:
DeterminismLog()
{
mLog.open("detlog.txt", std::ios::out | std::ios::trunc | std::ios::binary); // Binary because we don't want a difference between Unix and Windows line endings.
mLog.fill('0');
}
DeterminismLog & operator << (char inValue)
{
mLog << inValue;
return *this;
}
DeterminismLog & operator << (const char *inValue)
{
mLog << std::dec << inValue;
return *this;
}
DeterminismLog & operator << (const string &inValue)
{
mLog << std::dec << inValue;
return *this;
}
DeterminismLog & operator << (const BodyID &inValue)
{
mLog << std::hex << std::setw(8) << inValue.GetIndexAndSequenceNumber();
return *this;
}
DeterminismLog & operator << (const SubShapeID &inValue)
{
mLog << std::hex << std::setw(8) << inValue.GetValue();
return *this;
}
DeterminismLog & operator << (float inValue)
{
mLog << std::hex << std::setw(8) << Convert(inValue);
return *this;
}
DeterminismLog & operator << (int inValue)
{
mLog << inValue;
return *this;
}
DeterminismLog & operator << (uint32 inValue)
{
mLog << std::hex << std::setw(8) << inValue;
return *this;
}
DeterminismLog & operator << (uint64 inValue)
{
mLog << std::hex << std::setw(16) << inValue;
return *this;
}
DeterminismLog & operator << (Vec3Arg inValue)
{
mLog << std::hex << std::setw(8) << Convert(inValue.GetX()) << " " << std::setw(8) << Convert(inValue.GetY()) << " " << std::setw(8) << Convert(inValue.GetZ());
return *this;
}
DeterminismLog & operator << (DVec3Arg inValue)
{
mLog << std::hex << std::setw(16) << Convert(inValue.GetX()) << " " << std::setw(16) << Convert(inValue.GetY()) << " " << std::setw(16) << Convert(inValue.GetZ());
return *this;
}
DeterminismLog & operator << (Vec4Arg inValue)
{
mLog << std::hex << std::setw(8) << Convert(inValue.GetX()) << " " << std::setw(8) << Convert(inValue.GetY()) << " " << std::setw(8) << Convert(inValue.GetZ()) << " " << std::setw(8) << Convert(inValue.GetW());
return *this;
}
DeterminismLog & operator << (const Float3 &inValue)
{
mLog << std::hex << std::setw(8) << Convert(inValue.x) << " " << std::setw(8) << Convert(inValue.y) << " " << std::setw(8) << Convert(inValue.z);
return *this;
}
DeterminismLog & operator << (Mat44Arg inValue)
{
*this << inValue.GetColumn4(0) << " " << inValue.GetColumn4(1) << " " << inValue.GetColumn4(2) << " " << inValue.GetColumn4(3);
return *this;
}
DeterminismLog & operator << (DMat44Arg inValue)
{
*this << inValue.GetColumn4(0) << " " << inValue.GetColumn4(1) << " " << inValue.GetColumn4(2) << " " << inValue.GetTranslation();
return *this;
}
DeterminismLog & operator << (QuatArg inValue)
{
*this << inValue.GetXYZW();
return *this;
}
// Singleton instance
static DeterminismLog sLog;
private:
std::ofstream mLog;
};
/// Will log something to the determinism log, usage: JPH_DET_LOG("label " << value);
#define JPH_DET_LOG(...) DeterminismLog::sLog << __VA_ARGS__ << '\n'
JPH_NAMESPACE_END
#else
JPH_SUPPRESS_WARNING_PUSH
JPH_SUPPRESS_WARNINGS
/// By default we log nothing
#define JPH_DET_LOG(...)
JPH_SUPPRESS_WARNING_POP
#endif // JPH_ENABLE_DETERMINISM_LOG