Make update send only delta
This commit is contained in:
parent
6c5b5fbd59
commit
2f456fe8ba
@ -101,6 +101,8 @@ void game::Vehicle::Update()
|
||||
ProcessInput();
|
||||
UpdateWheels();
|
||||
|
||||
sync_current_ = 1 - sync_current_;
|
||||
UpdateSyncState();
|
||||
SendUpdateMsg();
|
||||
}
|
||||
|
||||
@ -109,7 +111,12 @@ void game::Vehicle::SendInitData(Player& player, net::OutMessage& msg) const
|
||||
net::ModelName name(model_name_);
|
||||
msg.Write(name);
|
||||
net::WriteRGB(msg, color_); // primary color
|
||||
WriteState(msg);
|
||||
|
||||
// write state against default
|
||||
static const VehicleSyncState default_state;
|
||||
size_t fields_pos = msg.Reserve<VehicleSyncFieldFlags>();
|
||||
auto fields = WriteState(msg, default_state);
|
||||
msg.WriteAt(fields_pos, fields);
|
||||
}
|
||||
|
||||
void game::Vehicle::SetInput(VehicleInputType type, bool enable)
|
||||
@ -120,6 +127,12 @@ void game::Vehicle::SetInput(VehicleInputType type, bool enable)
|
||||
in_ &= ~(1 << type);
|
||||
}
|
||||
|
||||
glm::vec3 game::Vehicle::GetPosition() const
|
||||
{
|
||||
btVector3 pos = body_->getWorldTransform().getOrigin();
|
||||
return glm::vec3(pos.x(), pos.y(), pos.z());
|
||||
}
|
||||
|
||||
void game::Vehicle::SetPosition(const glm::vec3& pos)
|
||||
{
|
||||
auto t = body_->getWorldTransform();
|
||||
@ -240,25 +253,102 @@ void game::Vehicle::UpdateWheels()
|
||||
}
|
||||
}
|
||||
|
||||
void game::Vehicle::WriteState(net::OutMessage& msg) const
|
||||
void game::Vehicle::UpdateSyncState()
|
||||
{
|
||||
msg.Write(flags_);
|
||||
net::WriteTransform(msg, root_.local);
|
||||
VehicleSyncState& state = sync_[sync_current_];
|
||||
|
||||
// send wheel info
|
||||
// msg.Write<uint8_t>(static_cast<uint8_t>(numwheels));
|
||||
msg.Write<net::AngleQ>(steering_);
|
||||
state.flags = flags_;
|
||||
|
||||
net::EncodePosition(root_.local.position, state.pos);
|
||||
net::EncodeRotation(root_.local.rotation, state.rot);
|
||||
|
||||
state.steering.Encode(steering_);
|
||||
|
||||
for (size_t i = 0; i < num_wheels_; ++i)
|
||||
{
|
||||
auto& wheel = wheels_[i];
|
||||
msg.Write<net::WheelZOffsetQ>(wheel.z_offset);
|
||||
msg.Write<net::RotationSpeedQ>(wheel.speed);
|
||||
state.wheels[i].z_offset.Encode(wheel.z_offset);
|
||||
state.wheels[i].speed.Encode(wheel.speed);
|
||||
}
|
||||
}
|
||||
|
||||
game::VehicleSyncFieldFlags game::Vehicle::WriteState(net::OutMessage& msg, const VehicleSyncState& base) const
|
||||
{
|
||||
VehicleSyncFieldFlags fields = 0;
|
||||
const VehicleSyncState& curr = sync_[sync_current_];
|
||||
|
||||
if (curr.flags != base.flags)
|
||||
{
|
||||
fields |= VSF_FLAGS;
|
||||
msg.Write(curr.flags);
|
||||
}
|
||||
|
||||
if (curr.pos.x.value != base.pos.x.value ||
|
||||
curr.pos.y.value != base.pos.y.value ||
|
||||
curr.pos.z.value != base.pos.z.value)
|
||||
{
|
||||
fields |= VSF_POSITION;
|
||||
|
||||
net::WriteDelta(msg, curr.pos.x, base.pos.x);
|
||||
net::WriteDelta(msg, curr.pos.y, base.pos.y);
|
||||
net::WriteDelta(msg, curr.pos.z, base.pos.z);
|
||||
}
|
||||
|
||||
if (curr.rot.x.value != base.rot.x.value ||
|
||||
curr.rot.y.value != base.rot.y.value ||
|
||||
curr.rot.z.value != base.rot.z.value)
|
||||
{
|
||||
fields |= VSF_ROTATION;
|
||||
|
||||
net::WriteDelta(msg, curr.rot.x, base.rot.x);
|
||||
net::WriteDelta(msg, curr.rot.y, base.rot.y);
|
||||
net::WriteDelta(msg, curr.rot.z, base.rot.z);
|
||||
}
|
||||
|
||||
if (curr.steering.value != base.steering.value)
|
||||
{
|
||||
fields |= VSF_STEERING;
|
||||
|
||||
net::WriteDelta(msg, curr.steering, base.steering);
|
||||
}
|
||||
|
||||
bool wheels_changed = false;
|
||||
for (size_t i = 0; i < num_wheels_; ++i)
|
||||
{
|
||||
if (curr.wheels[i].z_offset.value != base.wheels[i].z_offset.value ||
|
||||
curr.wheels[i].speed.value != base.wheels[i].speed.value)
|
||||
{
|
||||
wheels_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (wheels_changed)
|
||||
{
|
||||
fields |= VSF_WHEELS;
|
||||
|
||||
for (size_t i = 0; i < num_wheels_; ++i)
|
||||
{
|
||||
net::WriteDelta(msg, curr.wheels[i].z_offset, base.wheels[i].z_offset);
|
||||
net::WriteDelta(msg, curr.wheels[i].speed, base.wheels[i].speed);
|
||||
}
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
void game::Vehicle::SendUpdateMsg()
|
||||
{
|
||||
auto msg = BeginEntMsg(net::EMSG_UPDATE);
|
||||
WriteState(msg);
|
||||
auto fields_pos = msg.Reserve<VehicleSyncFieldFlags>();
|
||||
auto fields = WriteState(msg, sync_[1 - sync_current_]);
|
||||
|
||||
// TODO: allow this
|
||||
// if (fields == 0)
|
||||
// {
|
||||
// DiscardMsg();
|
||||
// return;
|
||||
// }
|
||||
|
||||
msg.WriteAt(fields_pos, fields);
|
||||
}
|
||||
|
||||
@ -7,13 +7,11 @@
|
||||
#include "collision/motionstate.hpp"
|
||||
#include "entity.hpp"
|
||||
#include "world.hpp"
|
||||
#include "vehicleflags.hpp"
|
||||
#include "vehicle_sync.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
static constexpr size_t MAX_WHEELS = 4;
|
||||
|
||||
struct VehicleWheelState
|
||||
{
|
||||
float rotation = 0.0f; // [rad]
|
||||
@ -44,6 +42,7 @@ public:
|
||||
|
||||
void SetInput(VehicleInputType type, bool enable);
|
||||
|
||||
glm::vec3 GetPosition() const;
|
||||
void SetPosition(const glm::vec3& pos);
|
||||
|
||||
virtual ~Vehicle();
|
||||
@ -51,7 +50,8 @@ public:
|
||||
private:
|
||||
void ProcessInput();
|
||||
void UpdateWheels();
|
||||
void WriteState(net::OutMessage& msg) const;
|
||||
void UpdateSyncState();
|
||||
VehicleSyncFieldFlags WriteState(net::OutMessage& msg, const VehicleSyncState& base) const;
|
||||
void SendUpdateMsg();
|
||||
|
||||
private:
|
||||
@ -69,7 +69,9 @@ private:
|
||||
size_t num_wheels_ = 0;
|
||||
std::array<VehicleWheelState, MAX_WHEELS> wheels_;
|
||||
|
||||
VehicleFlags flags_;
|
||||
VehicleFlags flags_ = VF_NONE;
|
||||
VehicleSyncState sync_[2];
|
||||
size_t sync_current_ = 0;
|
||||
|
||||
VehicleInputFlags in_ = 0;
|
||||
};
|
||||
|
||||
49
src/game/vehicle_sync.hpp
Normal file
49
src/game/vehicle_sync.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "net/defs.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
constexpr size_t MAX_WHEELS = 4;
|
||||
|
||||
using VehicleFlags = uint8_t;
|
||||
|
||||
enum VehicleFlag : VehicleFlags
|
||||
{
|
||||
VF_NONE,
|
||||
VF_ACCELERATING = 1,
|
||||
VF_BREAKING = 2,
|
||||
};
|
||||
|
||||
struct VehicleSyncState
|
||||
{
|
||||
VehicleFlags flags = VF_NONE;
|
||||
|
||||
net::PositionQ pos;
|
||||
net::QuatQ rot;
|
||||
|
||||
net::AngleQ steering;
|
||||
|
||||
struct
|
||||
{
|
||||
net::WheelZOffsetQ z_offset; // how much compressed
|
||||
net::RotationSpeedQ speed; // rad/s
|
||||
} wheels[MAX_WHEELS];
|
||||
};
|
||||
|
||||
using VehicleSyncFieldFlags = uint8_t;
|
||||
|
||||
enum VehicleSyncFieldFlag
|
||||
{
|
||||
VSF_FLAGS = 0x01,
|
||||
VSF_POSITION = 0x02,
|
||||
VSF_ROTATION = 0x04,
|
||||
VSF_STEERING = 0x08,
|
||||
VSF_WHEELS = 0x10,
|
||||
};
|
||||
|
||||
|
||||
} // namespace game
|
||||
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace game
|
||||
{
|
||||
|
||||
using VehicleFlags = uint8_t;
|
||||
|
||||
enum VehicleFlag : VehicleFlags
|
||||
{
|
||||
VF_NONE,
|
||||
VF_ACCELERATING = 1,
|
||||
VF_BREAKING = 2,
|
||||
};
|
||||
|
||||
}
|
||||
@ -20,6 +20,11 @@ game::view::VehicleView::VehicleView(WorldView& world, std::shared_ptr<const ass
|
||||
color_ = glm::vec4(color, 1.0f);
|
||||
|
||||
snd_accel_ = assets::CacheManager::GetSound("data/auto.snd");
|
||||
|
||||
// sync state
|
||||
net::DecodePosition(sync_.pos, root_.local.position);
|
||||
net::DecodeRotation(sync_.rot, root_.local.rotation);
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<game::view::VehicleView> game::view::VehicleView::InitFromMsg(WorldView& world, net::InMessage& msg)
|
||||
@ -32,7 +37,9 @@ std::unique_ptr<game::view::VehicleView> game::view::VehicleView::InitFromMsg(Wo
|
||||
auto model = assets::CacheManager::GetVehicleModel("data/" + std::string(modelname) + ".veh");
|
||||
|
||||
auto vehicle = std::make_unique<VehicleView>(world, std::move(model), color);
|
||||
vehicle->ReadState(msg);
|
||||
if (!vehicle->ReadState(msg))
|
||||
return nullptr;
|
||||
|
||||
vehicle->root_trans_[0] = vehicle->root_trans_[1];
|
||||
|
||||
return vehicle;
|
||||
@ -135,27 +142,73 @@ bool game::view::VehicleView::ReadState(net::InMessage& msg)
|
||||
auto& root_trans = root_trans_[1];
|
||||
update_time_ = world_.GetTime();
|
||||
|
||||
// parse state delta
|
||||
VehicleSyncFieldFlags fields;
|
||||
if (!msg.Read(fields))
|
||||
return false;
|
||||
|
||||
// flags
|
||||
if (fields & VSF_FLAGS)
|
||||
{
|
||||
if (!msg.Read(flags_))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!net::ReadTransform(msg, root_trans))
|
||||
// pos
|
||||
if (fields & VSF_POSITION)
|
||||
{
|
||||
if (!net::ReadDelta(msg, sync_.pos.x) ||
|
||||
!net::ReadDelta(msg, sync_.pos.y) ||
|
||||
!net::ReadDelta(msg, sync_.pos.z))
|
||||
return false;
|
||||
|
||||
float steering;
|
||||
if (!msg.Read<net::AngleQ>(steering))
|
||||
net::DecodePosition(sync_.pos, root_trans.position);
|
||||
}
|
||||
|
||||
// rot
|
||||
if (fields & VSF_ROTATION)
|
||||
{
|
||||
if (!net::ReadDelta(msg, sync_.rot.x) ||
|
||||
!net::ReadDelta(msg, sync_.rot.y) ||
|
||||
!net::ReadDelta(msg, sync_.rot.z))
|
||||
return false;
|
||||
|
||||
net::DecodeRotation(sync_.rot, root_trans.rotation);
|
||||
}
|
||||
|
||||
// steering
|
||||
if (fields & VSF_STEERING)
|
||||
{
|
||||
if (!net::ReadDelta(msg, sync_.steering))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
float steering = sync_.steering.Decode();
|
||||
|
||||
// wheels
|
||||
if (fields & VSF_WHEELS)
|
||||
{
|
||||
for (size_t i = 0; i < wheels_.size(); ++i)
|
||||
{
|
||||
if (!net::ReadDelta(msg, sync_.wheels[i].z_offset) ||
|
||||
!net::ReadDelta(msg, sync_.wheels[i].speed))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& wheels = model_->GetWheels();
|
||||
for (size_t i = 0; i < wheels_.size(); ++i)
|
||||
{
|
||||
auto& wheel = wheels_[i];
|
||||
if (!msg.Read<net::WheelZOffsetQ>(wheel.z_offset) || !msg.Read<net::RotationSpeedQ>(wheel.speed))
|
||||
return false;
|
||||
wheel.z_offset = sync_.wheels[i].z_offset.Decode();
|
||||
wheel.speed = sync_.wheels[i].speed.Decode();
|
||||
|
||||
wheel.steering = i < 2 ? steering : 0.0f;
|
||||
}
|
||||
|
||||
return true;}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
|
||||
{
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include "entityview.hpp"
|
||||
|
||||
#include "assets/vehiclemdl.hpp"
|
||||
#include "game/vehicleflags.hpp"
|
||||
#include "game/vehicle_sync.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@ -38,6 +38,7 @@ private:
|
||||
std::shared_ptr<const assets::VehicleModel> model_;
|
||||
glm::vec4 color_;
|
||||
|
||||
game::VehicleSyncState sync_;
|
||||
std::vector<VehicleWheelViewInfo> wheels_;
|
||||
|
||||
float update_time_ = 0.0f;
|
||||
|
||||
@ -74,9 +74,19 @@ enum EntMsgType : uint8_t
|
||||
EMSG_UPDATE,
|
||||
};
|
||||
|
||||
using PositionQ = Quantized<uint32_t, -10000, 10000, 1>;
|
||||
using PositionElemQ = Quantized<uint32_t, -10000, 10000, 1>;
|
||||
struct PositionQ
|
||||
{
|
||||
PositionElemQ x, y, z;
|
||||
};
|
||||
|
||||
using AngleQ = Quantized<uint16_t, -PI_N, PI_N, PI_D>;
|
||||
using QuatQ = Quantized<uint16_t, -1, 1, 1>;
|
||||
|
||||
using QuatElemQ = Quantized<uint16_t, -1, 1, 1>;
|
||||
struct QuatQ
|
||||
{
|
||||
QuatElemQ x, y, z;
|
||||
};
|
||||
|
||||
using WheelZOffsetQ = Quantized<uint8_t, -1, 1, 1>;
|
||||
using RotationSpeedQ = Quantized<uint16_t, -300, 300, 1>;
|
||||
|
||||
@ -9,8 +9,14 @@ void net::MsgProducer::ResetMsg()
|
||||
|
||||
net::OutMessage net::MsgProducer::BeginMsg(net::MessageType type)
|
||||
{
|
||||
msg_start_ = message_buf_.size();
|
||||
OutMessage msg(message_buf_);
|
||||
if (type != net::MSG_NONE)
|
||||
msg.Write(type);
|
||||
return msg;
|
||||
}
|
||||
|
||||
void net::MsgProducer::DiscardMsg()
|
||||
{
|
||||
message_buf_.resize(msg_start_);
|
||||
}
|
||||
|
||||
@ -15,10 +15,12 @@ public:
|
||||
|
||||
void ResetMsg();
|
||||
OutMessage BeginMsg(MessageType type = MSG_NONE);
|
||||
void DiscardMsg();
|
||||
std::span<const char> GetMsg() const { return message_buf_; };
|
||||
|
||||
private:
|
||||
std::vector<char> message_buf_;
|
||||
size_t msg_start_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
@ -78,6 +78,12 @@ public:
|
||||
Write(q.value);
|
||||
}
|
||||
|
||||
// template <AnyQuantized T>
|
||||
// void Write(T quant)
|
||||
// {
|
||||
// Write(quant.value);
|
||||
// }
|
||||
|
||||
void WriteVarInt(int64_t value)
|
||||
{
|
||||
const bool negative = value < 0;
|
||||
|
||||
@ -19,11 +19,11 @@ struct Quantized
|
||||
static constexpr float inv_scale = range / static_cast<float>(max_int);
|
||||
|
||||
public:
|
||||
T value;
|
||||
T value{0};
|
||||
|
||||
Quantized() = default;
|
||||
Quantized(T value) : value(value) {}
|
||||
Quantized(float fvalue) { Encode(value); }
|
||||
Quantized(float fvalue) { Encode(fvalue); }
|
||||
|
||||
void Encode(float fvalue) noexcept
|
||||
{
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "defs.hpp"
|
||||
#include "outmessage.hpp"
|
||||
#include "inmessage.hpp"
|
||||
#include "outmessage.hpp"
|
||||
#include "utils/transform.hpp"
|
||||
|
||||
namespace net
|
||||
@ -10,51 +10,107 @@ namespace net
|
||||
|
||||
/// TRANSFORMS
|
||||
|
||||
inline void WritePosition(OutMessage& msg, const glm::vec3& pos)
|
||||
// inline void WritePosition(OutMessage& msg, const glm::vec3& pos)
|
||||
// {
|
||||
// msg.Write<PositionQ>(pos.x);
|
||||
// msg.Write<PositionQ>(pos.y);
|
||||
// msg.Write<PositionQ>(pos.z);
|
||||
// }
|
||||
|
||||
inline void EncodePosition(const glm::vec3& pos, PositionQ& out)
|
||||
{
|
||||
msg.Write<PositionQ>(pos.x);
|
||||
msg.Write<PositionQ>(pos.y);
|
||||
msg.Write<PositionQ>(pos.z);
|
||||
out.x.Encode(pos.x);
|
||||
out.y.Encode(pos.y);
|
||||
out.z.Encode(pos.z);
|
||||
}
|
||||
|
||||
inline void WriteRotation(OutMessage& msg, const glm::quat& quat)
|
||||
inline void WritePositionQ(OutMessage& msg, const PositionQ& posq)
|
||||
{
|
||||
msg.Write(posq.x.value);
|
||||
msg.Write(posq.y.value);
|
||||
msg.Write(posq.z.value);
|
||||
}
|
||||
|
||||
// inline void WriteRotation(OutMessage& msg, const glm::quat& quat)
|
||||
// {
|
||||
// auto q = glm::normalize(quat);
|
||||
// if (q.w < 0.0f)
|
||||
// q = -q;
|
||||
|
||||
// msg.Write<QuatQ>(q.x);
|
||||
// msg.Write<QuatQ>(q.y);
|
||||
// msg.Write<QuatQ>(q.z);
|
||||
// }
|
||||
|
||||
inline void EncodeRotation(const glm::quat& quat, QuatQ& out)
|
||||
{
|
||||
auto q = glm::normalize(quat);
|
||||
if (q.w < 0.0f)
|
||||
q = -q;
|
||||
|
||||
msg.Write<QuatQ>(q.x);
|
||||
msg.Write<QuatQ>(q.y);
|
||||
msg.Write<QuatQ>(q.z);
|
||||
out.x.Encode(q.x);
|
||||
out.y.Encode(q.y);
|
||||
out.z.Encode(q.z);
|
||||
}
|
||||
|
||||
inline void WriteTransform(OutMessage& msg, const Transform& trans)
|
||||
inline void WriteRotationQ(OutMessage& msg, const QuatQ& rotq)
|
||||
{
|
||||
WritePosition(msg, trans.position);
|
||||
WriteRotation(msg, trans.rotation);
|
||||
msg.Write(rotq.x.value);
|
||||
msg.Write(rotq.y.value);
|
||||
msg.Write(rotq.z.value);
|
||||
}
|
||||
|
||||
inline bool ReadPosition(InMessage& msg, glm::vec3& pos)
|
||||
// inline void WriteTransform(OutMessage& msg, const Transform& trans)
|
||||
// {
|
||||
// WritePosition(msg, trans.position);
|
||||
// WriteRotation(msg, trans.rotation);
|
||||
// }
|
||||
|
||||
// inline bool ReadPosition(InMessage& msg, glm::vec3& pos)
|
||||
// {
|
||||
// return msg.Read<PositionQ>(pos.x) && msg.Read<PositionQ>(pos.y) && msg.Read<PositionQ>(pos.z);
|
||||
// }
|
||||
|
||||
inline bool ReadPositionQ(InMessage& msg, PositionQ& posq)
|
||||
{
|
||||
return msg.Read<PositionQ>(pos.x) && msg.Read<PositionQ>(pos.y) && msg.Read<PositionQ>(pos.z);
|
||||
return msg.Read(posq.x.value) && msg.Read(posq.y.value) && msg.Read(posq.z.value);
|
||||
}
|
||||
|
||||
inline bool ReadRotation(InMessage& msg, glm::quat& q)
|
||||
inline void DecodePosition(const PositionQ& posq, glm::vec3& out)
|
||||
{
|
||||
glm::vec3 v;
|
||||
if (!msg.Read<QuatQ>(v.x) || !msg.Read<QuatQ>(v.y) || !msg.Read<QuatQ>(v.z))
|
||||
return false;
|
||||
out.x = posq.x.Decode();
|
||||
out.y = posq.y.Decode();
|
||||
out.z = posq.z.Decode();
|
||||
}
|
||||
|
||||
// inline bool ReadRotation(InMessage& msg, glm::quat& q)
|
||||
// {
|
||||
// glm::vec3 v;
|
||||
// if (!msg.Read<QuatQ>(v.x) || !msg.Read<QuatQ>(v.y) || !msg.Read<QuatQ>(v.z))
|
||||
// return false;
|
||||
|
||||
// float w = glm::sqrt(glm::max(0.0f, 1.0f - glm::dot(v, v)));
|
||||
// q = glm::quat(w, v.x, v.y, v.z);
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
inline bool ReadRotationQ(InMessage& msg, QuatQ& rotq)
|
||||
{
|
||||
return msg.Read(rotq.x.value) && msg.Read(rotq.y.value) && msg.Read(rotq.z.value);
|
||||
}
|
||||
|
||||
inline void DecodeRotation(const QuatQ& rotq, glm::quat& out)
|
||||
{
|
||||
glm::vec3 v(rotq.x.Decode(), rotq.y.Decode(), rotq.z.Decode());
|
||||
float w = glm::sqrt(glm::max(0.0f, 1.0f - glm::dot(v, v)));
|
||||
q = glm::quat(w, v.x, v.y, v.z);
|
||||
|
||||
return true;
|
||||
out = glm::quat(w, v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
inline bool ReadTransform(InMessage& msg, Transform& trans)
|
||||
{
|
||||
return ReadPosition(msg, trans.position) && ReadRotation(msg, trans.rotation);
|
||||
}
|
||||
// inline bool ReadTransform(InMessage& msg, Transform& trans)
|
||||
// {
|
||||
// return ReadPosition(msg, trans.position) && ReadRotation(msg, trans.rotation);
|
||||
// }
|
||||
|
||||
/// COLOR
|
||||
|
||||
@ -70,4 +126,50 @@ inline bool ReadRGB(InMessage& msg, glm::vec3& color)
|
||||
return msg.Read<ColorQ>(color.r) && msg.Read<ColorQ>(color.g) && msg.Read<ColorQ>(color.b);
|
||||
}
|
||||
|
||||
// DELTA
|
||||
template <std::unsigned_integral T>
|
||||
inline void WriteDelta(OutMessage& msg, T previous, T current)
|
||||
{
|
||||
static_assert(sizeof(T) <= 4);
|
||||
|
||||
int64_t delta = static_cast<int64_t>(current) - static_cast<int64_t>(previous);
|
||||
|
||||
constexpr int64_t wrap = 1LL << (sizeof(T) * 8);
|
||||
delta = (delta + wrap / 2) % wrap - wrap / 2;
|
||||
|
||||
msg.WriteVarInt(delta);
|
||||
}
|
||||
|
||||
template <AnyQuantized T>
|
||||
inline void WriteDelta(OutMessage& msg, T current, T previous)
|
||||
{
|
||||
WriteDelta(msg, previous.value, current.value);
|
||||
}
|
||||
|
||||
template <std::unsigned_integral T>
|
||||
inline bool ReadDelta(InMessage& msg, T previous, T& current)
|
||||
{
|
||||
static_assert(sizeof(T) <= 4);
|
||||
|
||||
int64_t encoded;
|
||||
if (!msg.ReadVarInt(encoded))
|
||||
return false;
|
||||
|
||||
constexpr uint64_t mask = (1ULL << (sizeof(T) * 8)) - 1;
|
||||
current = static_cast<T>((static_cast<uint64_t>(previous) + static_cast<uint64_t>(encoded)) & mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <std::unsigned_integral T>
|
||||
inline bool ReadDelta(InMessage& msg, T& value)
|
||||
{
|
||||
return ReadDelta<T>(msg, value, value);
|
||||
}
|
||||
|
||||
template <AnyQuantized T>
|
||||
inline bool ReadDelta(InMessage& msg, T& quant)
|
||||
{
|
||||
return ReadDelta(msg, quant.value, quant.value);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
Loading…
x
Reference in New Issue
Block a user