Files
2025-09-18 17:55:52 -04:00

124 lines
4.0 KiB
C++

/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include <boost/circular_buffer.hpp>
#include "G3DCore.h"
#include "rbx/rbxTime.h"
#include "boost/thread/mutex.hpp"
#include "Math.h"
namespace RBX {
#define MH_NUM_MAX_NODES 80
#define MH_MIN_PRECISION 0.01f
#define MH_TOLERABLE_COMPRESSION_ERROR 1.f
typedef unsigned char uint8_t;
typedef signed char int8_t;
class MovementHistory
{
public:
struct DeltaCompressedTranslation
{
// in terms of MIN_PRECISION
uint8_t precisionLevel;
int8_t dX;
int8_t dY;
int8_t dZ;
};
struct MovementNode
{
DeltaCompressedTranslation translation;
uint8_t delta2Ms;
MovementNode()
{
setZero();
}
MovementNode(const CoordinateFrame& newCFrame, const CoordinateFrame& oldCFrame, float deltaSecs)
{
Vector3 delta = newCFrame.translation - oldCFrame.translation;
compress(delta, *this);
if (deltaSecs < 0.f)
{
delta2Ms = 0;
}
else if (deltaSecs > 0.510f)
{
delta2Ms = 255; // overflow, use 255 to indicate the long gap
}
else
{
delta2Ms = (uint8_t)(deltaSecs*500.f);
}
}
bool isZero() const
{
return translation.dX == 0 && translation.dY == 0 && translation.dZ == 0;
}
void setZero()
{
translation.precisionLevel = 0;
translation.dX = 0;
translation.dY = 0;
translation.dZ = 0;
delta2Ms = 0;
}
// rotation will be estimated by interpolation
};
static const MovementHistory& getDefaultHistory()
{
static CoordinateFrame zeroCFrame;
static Velocity zeroVelocity;
static MovementHistory defaultMovementHistory(zeroCFrame, zeroVelocity, Time());
return defaultMovementHistory;
}
MovementHistory(const CoordinateFrame& cFrame, const Velocity& velocity, const Time& timeStamp);
~MovementHistory()
{}
void clearNodeHistory();
void addNode(const CoordinateFrame& cFrame, const Velocity& velocity, const Time& timeStamp);
size_t getNumNodes() const {return size;}
bool hasHistory(float accumulatedError) const;
void getMovementNodeList(const Time& lastCutOffTime, const Time& currentCutOffTime, std::deque<MovementNode>& result, bool crossPacketCompression, const CoordinateFrame& lastSentCFrame, CoordinateFrame& outCalculatedBaselineCFrame, Vector3& outCalculatedLinearVelocity) const;
const CoordinateFrame& getBaselineCFrame() const {return baselineCFrame;}
const Velocity& getBaselineVelocity() const {return baselineVelocity;}
static float decompress(int8_t v, uint8_t precisionLevel);
static void decompress(MovementNode node, Vector3& outTranslation);
const Time& getLastUpdateTime() const {return lastUpdateTime;}
float getTimeSpan() const {return timeSpanSec;}
static float getSecFrom2Ms(uint8_t delta2MS)
{
return ((float)delta2MS)/500.f;
}
private:
CoordinateFrame baselineCFrame;
Velocity baselineVelocity;
Time lastUpdateTime;
float timeSpanSec;
int checksum;
MovementNode movementNodes[MH_NUM_MAX_NODES];
size_t startIndex;
size_t size;
void popFront();
void pushBack(MovementNode node);
MovementNode concatNode(size_t lastIndex, size_t numNodesToConcat) const;
static int8_t compress(float v, uint8_t precisionLevel);
static void compress(Vector3 translation, MovementNode& outMovementNode);
};
} // namespace