Make update send only delta
This commit is contained in:
parent
6c5b5fbd59
commit
2f456fe8ba
@ -101,6 +101,8 @@ void game::Vehicle::Update()
|
|||||||
ProcessInput();
|
ProcessInput();
|
||||||
UpdateWheels();
|
UpdateWheels();
|
||||||
|
|
||||||
|
sync_current_ = 1 - sync_current_;
|
||||||
|
UpdateSyncState();
|
||||||
SendUpdateMsg();
|
SendUpdateMsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +111,12 @@ void game::Vehicle::SendInitData(Player& player, net::OutMessage& msg) const
|
|||||||
net::ModelName name(model_name_);
|
net::ModelName name(model_name_);
|
||||||
msg.Write(name);
|
msg.Write(name);
|
||||||
net::WriteRGB(msg, color_); // primary color
|
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)
|
void game::Vehicle::SetInput(VehicleInputType type, bool enable)
|
||||||
@ -120,6 +127,12 @@ void game::Vehicle::SetInput(VehicleInputType type, bool enable)
|
|||||||
in_ &= ~(1 << type);
|
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)
|
void game::Vehicle::SetPosition(const glm::vec3& pos)
|
||||||
{
|
{
|
||||||
auto t = body_->getWorldTransform();
|
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_);
|
VehicleSyncState& state = sync_[sync_current_];
|
||||||
net::WriteTransform(msg, root_.local);
|
|
||||||
|
|
||||||
// send wheel info
|
state.flags = flags_;
|
||||||
// msg.Write<uint8_t>(static_cast<uint8_t>(numwheels));
|
|
||||||
msg.Write<net::AngleQ>(steering_);
|
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)
|
for (size_t i = 0; i < num_wheels_; ++i)
|
||||||
{
|
{
|
||||||
auto& wheel = wheels_[i];
|
auto& wheel = wheels_[i];
|
||||||
msg.Write<net::WheelZOffsetQ>(wheel.z_offset);
|
state.wheels[i].z_offset.Encode(wheel.z_offset);
|
||||||
msg.Write<net::RotationSpeedQ>(wheel.speed);
|
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()
|
void game::Vehicle::SendUpdateMsg()
|
||||||
{
|
{
|
||||||
auto msg = BeginEntMsg(net::EMSG_UPDATE);
|
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 "collision/motionstate.hpp"
|
||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "vehicleflags.hpp"
|
#include "vehicle_sync.hpp"
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
|
|
||||||
static constexpr size_t MAX_WHEELS = 4;
|
|
||||||
|
|
||||||
struct VehicleWheelState
|
struct VehicleWheelState
|
||||||
{
|
{
|
||||||
float rotation = 0.0f; // [rad]
|
float rotation = 0.0f; // [rad]
|
||||||
@ -44,6 +42,7 @@ public:
|
|||||||
|
|
||||||
void SetInput(VehicleInputType type, bool enable);
|
void SetInput(VehicleInputType type, bool enable);
|
||||||
|
|
||||||
|
glm::vec3 GetPosition() const;
|
||||||
void SetPosition(const glm::vec3& pos);
|
void SetPosition(const glm::vec3& pos);
|
||||||
|
|
||||||
virtual ~Vehicle();
|
virtual ~Vehicle();
|
||||||
@ -51,7 +50,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void ProcessInput();
|
void ProcessInput();
|
||||||
void UpdateWheels();
|
void UpdateWheels();
|
||||||
void WriteState(net::OutMessage& msg) const;
|
void UpdateSyncState();
|
||||||
|
VehicleSyncFieldFlags WriteState(net::OutMessage& msg, const VehicleSyncState& base) const;
|
||||||
void SendUpdateMsg();
|
void SendUpdateMsg();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -69,7 +69,9 @@ private:
|
|||||||
size_t num_wheels_ = 0;
|
size_t num_wheels_ = 0;
|
||||||
std::array<VehicleWheelState, MAX_WHEELS> wheels_;
|
std::array<VehicleWheelState, MAX_WHEELS> wheels_;
|
||||||
|
|
||||||
VehicleFlags flags_;
|
VehicleFlags flags_ = VF_NONE;
|
||||||
|
VehicleSyncState sync_[2];
|
||||||
|
size_t sync_current_ = 0;
|
||||||
|
|
||||||
VehicleInputFlags in_ = 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);
|
color_ = glm::vec4(color, 1.0f);
|
||||||
|
|
||||||
snd_accel_ = assets::CacheManager::GetSound("data/auto.snd");
|
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)
|
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 model = assets::CacheManager::GetVehicleModel("data/" + std::string(modelname) + ".veh");
|
||||||
|
|
||||||
auto vehicle = std::make_unique<VehicleView>(world, std::move(model), color);
|
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];
|
vehicle->root_trans_[0] = vehicle->root_trans_[1];
|
||||||
|
|
||||||
return vehicle;
|
return vehicle;
|
||||||
@ -135,27 +142,73 @@ bool game::view::VehicleView::ReadState(net::InMessage& msg)
|
|||||||
auto& root_trans = root_trans_[1];
|
auto& root_trans = root_trans_[1];
|
||||||
update_time_ = world_.GetTime();
|
update_time_ = world_.GetTime();
|
||||||
|
|
||||||
if (!msg.Read(flags_))
|
// parse state delta
|
||||||
|
VehicleSyncFieldFlags fields;
|
||||||
|
if (!msg.Read(fields))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!net::ReadTransform(msg, root_trans))
|
// flags
|
||||||
return false;
|
if (fields & VSF_FLAGS)
|
||||||
|
{
|
||||||
|
if (!msg.Read(flags_))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
float steering;
|
// pos
|
||||||
if (!msg.Read<net::AngleQ>(steering))
|
if (fields & VSF_POSITION)
|
||||||
return false;
|
{
|
||||||
|
if (!net::ReadDelta(msg, sync_.pos.x) ||
|
||||||
|
!net::ReadDelta(msg, sync_.pos.y) ||
|
||||||
|
!net::ReadDelta(msg, sync_.pos.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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();
|
const auto& wheels = model_->GetWheels();
|
||||||
for (size_t i = 0; i < wheels_.size(); ++i)
|
for (size_t i = 0; i < wheels_.size(); ++i)
|
||||||
{
|
{
|
||||||
auto& wheel = wheels_[i];
|
auto& wheel = wheels_[i];
|
||||||
if (!msg.Read<net::WheelZOffsetQ>(wheel.z_offset) || !msg.Read<net::RotationSpeedQ>(wheel.speed))
|
wheel.z_offset = sync_.wheels[i].z_offset.Decode();
|
||||||
return false;
|
wheel.speed = sync_.wheels[i].speed.Decode();
|
||||||
|
|
||||||
wheel.steering = i < 2 ? steering : 0.0f;
|
wheel.steering = i < 2 ? steering : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
|
bool game::view::VehicleView::ProcessUpdateMsg(net::InMessage& msg)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
#include "entityview.hpp"
|
#include "entityview.hpp"
|
||||||
|
|
||||||
#include "assets/vehiclemdl.hpp"
|
#include "assets/vehiclemdl.hpp"
|
||||||
#include "game/vehicleflags.hpp"
|
#include "game/vehicle_sync.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@ -38,6 +38,7 @@ private:
|
|||||||
std::shared_ptr<const assets::VehicleModel> model_;
|
std::shared_ptr<const assets::VehicleModel> model_;
|
||||||
glm::vec4 color_;
|
glm::vec4 color_;
|
||||||
|
|
||||||
|
game::VehicleSyncState sync_;
|
||||||
std::vector<VehicleWheelViewInfo> wheels_;
|
std::vector<VehicleWheelViewInfo> wheels_;
|
||||||
|
|
||||||
float update_time_ = 0.0f;
|
float update_time_ = 0.0f;
|
||||||
|
|||||||
@ -74,9 +74,19 @@ enum EntMsgType : uint8_t
|
|||||||
EMSG_UPDATE,
|
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 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 WheelZOffsetQ = Quantized<uint8_t, -1, 1, 1>;
|
||||||
using RotationSpeedQ = Quantized<uint16_t, -300, 300, 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)
|
net::OutMessage net::MsgProducer::BeginMsg(net::MessageType type)
|
||||||
{
|
{
|
||||||
|
msg_start_ = message_buf_.size();
|
||||||
OutMessage msg(message_buf_);
|
OutMessage msg(message_buf_);
|
||||||
if (type != net::MSG_NONE)
|
if (type != net::MSG_NONE)
|
||||||
msg.Write(type);
|
msg.Write(type);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void net::MsgProducer::DiscardMsg()
|
||||||
|
{
|
||||||
|
message_buf_.resize(msg_start_);
|
||||||
|
}
|
||||||
|
|||||||
@ -15,10 +15,12 @@ public:
|
|||||||
|
|
||||||
void ResetMsg();
|
void ResetMsg();
|
||||||
OutMessage BeginMsg(MessageType type = MSG_NONE);
|
OutMessage BeginMsg(MessageType type = MSG_NONE);
|
||||||
|
void DiscardMsg();
|
||||||
std::span<const char> GetMsg() const { return message_buf_; };
|
std::span<const char> GetMsg() const { return message_buf_; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<char> message_buf_;
|
std::vector<char> message_buf_;
|
||||||
|
size_t msg_start_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -78,6 +78,12 @@ public:
|
|||||||
Write(q.value);
|
Write(q.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <AnyQuantized T>
|
||||||
|
// void Write(T quant)
|
||||||
|
// {
|
||||||
|
// Write(quant.value);
|
||||||
|
// }
|
||||||
|
|
||||||
void WriteVarInt(int64_t value)
|
void WriteVarInt(int64_t value)
|
||||||
{
|
{
|
||||||
const bool negative = value < 0;
|
const bool negative = value < 0;
|
||||||
|
|||||||
@ -19,11 +19,11 @@ struct Quantized
|
|||||||
static constexpr float inv_scale = range / static_cast<float>(max_int);
|
static constexpr float inv_scale = range / static_cast<float>(max_int);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
T value;
|
T value{0};
|
||||||
|
|
||||||
Quantized() = default;
|
Quantized() = default;
|
||||||
Quantized(T value) : value(value) {}
|
Quantized(T value) : value(value) {}
|
||||||
Quantized(float fvalue) { Encode(value); }
|
Quantized(float fvalue) { Encode(fvalue); }
|
||||||
|
|
||||||
void Encode(float fvalue) noexcept
|
void Encode(float fvalue) noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "defs.hpp"
|
#include "defs.hpp"
|
||||||
#include "outmessage.hpp"
|
|
||||||
#include "inmessage.hpp"
|
#include "inmessage.hpp"
|
||||||
|
#include "outmessage.hpp"
|
||||||
#include "utils/transform.hpp"
|
#include "utils/transform.hpp"
|
||||||
|
|
||||||
namespace net
|
namespace net
|
||||||
@ -10,51 +10,107 @@ namespace net
|
|||||||
|
|
||||||
/// TRANSFORMS
|
/// 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);
|
out.x.Encode(pos.x);
|
||||||
msg.Write<PositionQ>(pos.y);
|
out.y.Encode(pos.y);
|
||||||
msg.Write<PositionQ>(pos.z);
|
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);
|
auto q = glm::normalize(quat);
|
||||||
if (q.w < 0.0f)
|
if (q.w < 0.0f)
|
||||||
q = -q;
|
q = -q;
|
||||||
|
|
||||||
msg.Write<QuatQ>(q.x);
|
out.x.Encode(q.x);
|
||||||
msg.Write<QuatQ>(q.y);
|
out.y.Encode(q.y);
|
||||||
msg.Write<QuatQ>(q.z);
|
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);
|
msg.Write(rotq.x.value);
|
||||||
WriteRotation(msg, trans.rotation);
|
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;
|
out.x = posq.x.Decode();
|
||||||
if (!msg.Read<QuatQ>(v.x) || !msg.Read<QuatQ>(v.y) || !msg.Read<QuatQ>(v.z))
|
out.y = posq.y.Decode();
|
||||||
return false;
|
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)));
|
float w = glm::sqrt(glm::max(0.0f, 1.0f - glm::dot(v, v)));
|
||||||
q = glm::quat(w, v.x, v.y, v.z);
|
out = glm::quat(w, v.x, v.y, v.z);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ReadTransform(InMessage& msg, Transform& trans)
|
// inline bool ReadTransform(InMessage& msg, Transform& trans)
|
||||||
{
|
// {
|
||||||
return ReadPosition(msg, trans.position) && ReadRotation(msg, trans.rotation);
|
// return ReadPosition(msg, trans.position) && ReadRotation(msg, trans.rotation);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// COLOR
|
/// 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);
|
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