110 lines
2.7 KiB
C++
110 lines
2.7 KiB
C++
#include "simple_entity_view.hpp"
|
|
#include "net/defs.hpp"
|
|
#include "assets/cache.hpp"
|
|
#include "worldview.hpp"
|
|
#include "net/utils.hpp"
|
|
|
|
game::view::SimpleEntityView::SimpleEntityView(WorldView& world, net::InMessage& msg) : Super(world, msg)
|
|
{
|
|
net::ModelName modelname;
|
|
if (!msg.Read(modelname))
|
|
throw EntityInitError();
|
|
|
|
if (modelname.len > 0)
|
|
{
|
|
model_ = assets::CacheManager::GetModel(std::string(modelname));
|
|
if (!model_)
|
|
throw EntityInitError();
|
|
}
|
|
|
|
if (!ReadState(&msg))
|
|
throw EntityInitError();
|
|
|
|
states_[0] = states_[1]; // lerp from the read state to avoid jump
|
|
root_.local = states_[0].trans;
|
|
|
|
radius_ = 20.0f;
|
|
}
|
|
|
|
bool game::view::SimpleEntityView::ProcessMsg(net::EntMsgType type, net::InMessage& msg)
|
|
{
|
|
switch (type)
|
|
{
|
|
default:
|
|
return Super::ProcessMsg(type, msg);
|
|
}
|
|
}
|
|
|
|
bool game::view::SimpleEntityView::ProcessUpdateMsg(net::InMessage* msg)
|
|
{
|
|
return ReadState(msg);
|
|
}
|
|
|
|
void game::view::SimpleEntityView::Update(const UpdateInfo& info)
|
|
{
|
|
Super::Update(info);
|
|
|
|
// interpolate states
|
|
float tps = 25.0f;
|
|
float t = (info.time - update_time_) * tps * 0.8f; // assume some jitter, interpolate for longer
|
|
t = glm::clamp(t, 0.0f, 2.0f);
|
|
|
|
root_.local = Transform::Lerp(states_[0].trans, states_[1].trans, t);
|
|
root_.UpdateMatrix();
|
|
}
|
|
|
|
void game::view::SimpleEntityView::Draw(const DrawArgs& args)
|
|
{
|
|
Super::Draw(args);
|
|
|
|
if (!model_)
|
|
return;
|
|
|
|
const auto& mesh = *model_->GetMesh();
|
|
for (const auto& surface : mesh.surfaces)
|
|
{
|
|
gfx::DrawSurfaceCmd cmd;
|
|
cmd.surface = &surface;
|
|
cmd.matrices = &root_.matrix;
|
|
args.dlist.AddSurface(cmd);
|
|
}
|
|
}
|
|
|
|
bool game::view::SimpleEntityView::ReadState(net::InMessage* msg)
|
|
{
|
|
update_time_ = world_.GetTime();
|
|
|
|
// init lerp start state
|
|
states_[0].trans = root_.local;
|
|
|
|
auto& new_state = states_[1];
|
|
|
|
if (msg)
|
|
{
|
|
// parse state delta
|
|
SimpleEntitySyncFieldFlags fields;
|
|
if (!msg->Read(fields))
|
|
return false;
|
|
|
|
// pos
|
|
if (fields & SESF_POSITION)
|
|
{
|
|
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, new_state.trans.position);
|
|
}
|
|
|
|
// rot
|
|
if (fields & SESF_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, new_state.trans.rotation);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|