Vehicle deform
This commit is contained in:
parent
8369181e9a
commit
3e284af672
@ -27,6 +27,8 @@ set(COMMON_SOURCES
|
|||||||
"src/collision/trianglemesh.cpp"
|
"src/collision/trianglemesh.cpp"
|
||||||
"src/game/character_anim_state.hpp"
|
"src/game/character_anim_state.hpp"
|
||||||
"src/game/character_anim_state.cpp"
|
"src/game/character_anim_state.cpp"
|
||||||
|
"src/game/deform_grid.hpp"
|
||||||
|
"src/game/deform_grid.cpp"
|
||||||
"src/game/player_input.hpp"
|
"src/game/player_input.hpp"
|
||||||
"src/game/simple_entity_sync.hpp"
|
"src/game/simple_entity_sync.hpp"
|
||||||
"src/game/skeletoninstance.hpp"
|
"src/game/skeletoninstance.hpp"
|
||||||
@ -90,6 +92,8 @@ set(CLIENT_ONLY_SOURCES
|
|||||||
"src/gameview/worldview.cpp"
|
"src/gameview/worldview.cpp"
|
||||||
"src/gfx/buffer_object.cpp"
|
"src/gfx/buffer_object.cpp"
|
||||||
"src/gfx/buffer_object.hpp"
|
"src/gfx/buffer_object.hpp"
|
||||||
|
"src/gfx/deform_texture.hpp"
|
||||||
|
"src/gfx/deform_texture.cpp"
|
||||||
"src/gfx/draw_list.hpp"
|
"src/gfx/draw_list.hpp"
|
||||||
"src/gfx/frustum.hpp"
|
"src/gfx/frustum.hpp"
|
||||||
"src/gfx/frustum.cpp"
|
"src/gfx/frustum.cpp"
|
||||||
|
|||||||
@ -21,12 +21,19 @@ enum ObjectFlag : ObjectFlags
|
|||||||
OF_NOTIFY_CONTACT = 0x02,
|
OF_NOTIFY_CONTACT = 0x02,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ContactInfo
|
||||||
|
{
|
||||||
|
glm::vec3 pos;
|
||||||
|
glm::vec3 normal;
|
||||||
|
float impulse;
|
||||||
|
};
|
||||||
|
|
||||||
class ObjectCallback
|
class ObjectCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObjectCallback() = default;
|
ObjectCallback() = default;
|
||||||
|
|
||||||
virtual void OnContact(float impulse) {}
|
virtual void OnContact(const ContactInfo& info) {}
|
||||||
|
|
||||||
virtual ~ObjectCallback() = default;
|
virtual ~ObjectCallback() = default;
|
||||||
};
|
};
|
||||||
|
|||||||
46
src/game/deform_grid.cpp
Normal file
46
src/game/deform_grid.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "deform_grid.hpp"
|
||||||
|
|
||||||
|
game::DeformGrid::DeformGrid(const gfx::DeformGridInfo& info)
|
||||||
|
: info_(info), data_(info_.res.x * info_.res.y * info_.res.z, glm::i8vec3(0))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::DeformGrid::ApplyImpulse(const glm::vec3& pos, const glm::vec3& impulse, float radius)
|
||||||
|
{
|
||||||
|
glm::vec3 step = (info_.max - info_.min) / glm::vec3(info_.res);
|
||||||
|
|
||||||
|
glm::ivec3 ipos;
|
||||||
|
|
||||||
|
// TODO: make more efficient
|
||||||
|
for (ipos.z = 0; ipos.z < info_.res.z; ++ipos.z)
|
||||||
|
{
|
||||||
|
for (ipos.y = 0; ipos.y < info_.res.y; ++ipos.y)
|
||||||
|
{
|
||||||
|
for (ipos.x = 0; ipos.x < info_.res.x; ++ipos.x)
|
||||||
|
{
|
||||||
|
glm::vec3 texel_pos = info_.min + glm::vec3(ipos) * step;
|
||||||
|
|
||||||
|
if (glm::distance2(pos, texel_pos) < radius * radius)
|
||||||
|
{
|
||||||
|
size_t idx = GetTexelIndex(ipos);
|
||||||
|
glm::vec3 offset = UnpackOffset(data_[idx]);
|
||||||
|
offset += impulse;
|
||||||
|
data_[idx] = PackOffset(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::i8vec3 game::DeformGrid::PackOffset(const glm::vec3& offset)
|
||||||
|
{
|
||||||
|
return glm::i8vec3(glm::round(glm::clamp(offset / info_.max_offset, -1.0f, 1.0f) * 127.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 game::DeformGrid::UnpackOffset(const glm::i8vec3& packed)
|
||||||
|
{
|
||||||
|
return glm::clamp(glm::vec3(packed) * 0.0078740157480315f, -1.0f, 1.0f) * info_.max_offset;
|
||||||
|
}
|
||||||
41
src/game/deform_grid.hpp
Normal file
41
src/game/deform_grid.hpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
|
|
||||||
|
#include "gfx/deform_grid_info.hpp"
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
|
||||||
|
class DeformGrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeformGrid(const gfx::DeformGridInfo& info);
|
||||||
|
|
||||||
|
void ApplyImpulse(const glm::vec3& pos, const glm::vec3& impulse, float radius);
|
||||||
|
|
||||||
|
const gfx::DeformGridInfo& GetInfo() const { return info_; }
|
||||||
|
|
||||||
|
std::span<glm::i8vec3> GetData() { return data_; }
|
||||||
|
std::span<const glm::i8vec3> GetData() const { return data_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::i8vec3 PackOffset(const glm::vec3& offset);
|
||||||
|
glm::vec3 UnpackOffset(const glm::i8vec3& packed);
|
||||||
|
|
||||||
|
size_t GetTexelIndex(const glm::ivec3& pos) const { return static_cast<size_t>(pos.x + (pos.y + pos.z * info_.res.y) * info_.res.x); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const gfx::DeformGridInfo info_;
|
||||||
|
std::vector<glm::i8vec3> data_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -47,12 +47,12 @@ game::OpenWorld::OpenWorld() : World("openworld")
|
|||||||
SpawnBot();
|
SpawnBot();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& veh = Spawn<game::DrivableVehicle>("twingo", glm::vec3{0.8f, 0.1f, 0.1f});
|
auto& veh = Spawn<game::DrivableVehicle>("twingo", glm::vec3{1.0f, 0.8f, 0.1f});
|
||||||
veh.SetPosition({110.0f, 100.0f, 5.0f});
|
veh.SetPosition({110.0f, 100.0f, 5.0f});
|
||||||
|
|
||||||
constexpr size_t in_row = 20;
|
constexpr size_t in_row = 20;
|
||||||
|
|
||||||
for (size_t i = 0; i < 3000; ++i)
|
for (size_t i = 0; i < 1500; ++i)
|
||||||
{
|
{
|
||||||
Schedule(i * 40, [this, i] {
|
Schedule(i * 40, [this, i] {
|
||||||
size_t col = i % in_row;
|
size_t col = i % in_row;
|
||||||
|
|||||||
@ -95,6 +95,14 @@ game::Vehicle::Vehicle(World& world, std::string model_name, const glm::vec3& co
|
|||||||
bt_world.addRigidBody(body_.get(), btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::AllFilter);
|
bt_world.addRigidBody(body_.get(), btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::AllFilter);
|
||||||
bt_world.addAction(vehicle_.get());
|
bt_world.addAction(vehicle_.get());
|
||||||
|
|
||||||
|
// init deform
|
||||||
|
gfx::DeformGridInfo info{};
|
||||||
|
info.min = glm::vec3(-1.0f, -2.5f, 0.10f);
|
||||||
|
info.max = glm::vec3(1.0f, 2.0f, 1.8f);
|
||||||
|
info.res = glm::ivec3(8, 16, 8);
|
||||||
|
info.max_offset = 0.1f;
|
||||||
|
deformgrid_ = std::make_unique<DeformGrid>(info);
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,20 +135,22 @@ void game::Vehicle::SendInitData(Player& player, net::OutMessage& msg) const
|
|||||||
size_t fields_pos = msg.Reserve<VehicleSyncFieldFlags>();
|
size_t fields_pos = msg.Reserve<VehicleSyncFieldFlags>();
|
||||||
auto fields = WriteState(msg, default_state);
|
auto fields = WriteState(msg, default_state);
|
||||||
msg.WriteAt(fields_pos, fields);
|
msg.WriteAt(fields_pos, fields);
|
||||||
|
|
||||||
|
WriteDeformSync(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Vehicle::OnContact(float impulse)
|
void game::Vehicle::OnContact(const collision::ContactInfo& info)
|
||||||
{
|
{
|
||||||
Super::OnContact(impulse);
|
Super::OnContact(info);
|
||||||
|
|
||||||
crash_intensity_ += impulse;
|
crash_intensity_ += info.impulse;
|
||||||
|
|
||||||
if (impulse < 1000.0f)
|
if (info.impulse < 1000.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (window_health_ > 0.0f)
|
if (window_health_ > 0.0f)
|
||||||
{
|
{
|
||||||
window_health_ -= impulse;
|
window_health_ -= info.impulse;
|
||||||
|
|
||||||
if (window_health_ <= 0.0f) // just broken
|
if (window_health_ <= 0.0f) // just broken
|
||||||
{
|
{
|
||||||
@ -148,6 +158,11 @@ void game::Vehicle::OnContact(float impulse)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window_health_ <= 0.0f)
|
||||||
|
{
|
||||||
|
Deform(info.pos, -glm::normalize(info.normal) * 0.1f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Vehicle::SetInput(VehicleInputType type, bool enable)
|
void game::Vehicle::SetInput(VehicleInputType type, bool enable)
|
||||||
@ -485,3 +500,56 @@ void game::Vehicle::SendUpdateMsg()
|
|||||||
|
|
||||||
msg.WriteAt(fields_pos, fields);
|
msg.WriteAt(fields_pos, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::Vehicle::WriteDeformSync(net::OutMessage& msg) const
|
||||||
|
{
|
||||||
|
const auto texels = deformgrid_->GetData();
|
||||||
|
|
||||||
|
auto numtexels_pos = msg.Reserve<net::NumTexels>();
|
||||||
|
net::NumTexels numtexels = 0;
|
||||||
|
|
||||||
|
size_t last = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < texels.size(); ++i)
|
||||||
|
{
|
||||||
|
if (texels[i] == glm::i8vec3(0))
|
||||||
|
continue; // unchanged, no write
|
||||||
|
|
||||||
|
auto diff = i - last;
|
||||||
|
msg.WriteVarInt(diff);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
msg.Write(texels[i][j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
last = i;
|
||||||
|
++numtexels;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.WriteAt(numtexels_pos, numtexels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Vehicle::Deform(const glm::vec3& pos, const glm::vec3& deform, float radius)
|
||||||
|
{
|
||||||
|
net::PositionQ pos_q;
|
||||||
|
net::PositionQ deform_q;
|
||||||
|
net::EncodePosition(pos, pos_q);
|
||||||
|
net::EncodePosition(deform, deform_q);
|
||||||
|
|
||||||
|
SendDeformMsg(pos_q, deform_q);
|
||||||
|
|
||||||
|
// defeorm locally
|
||||||
|
glm::vec3 new_pos, new_deform;
|
||||||
|
net::DecodePosition(pos_q, new_pos);
|
||||||
|
net::DecodePosition(deform_q, new_deform);
|
||||||
|
|
||||||
|
deformgrid_->ApplyImpulse(new_pos, new_deform, 0.3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Vehicle::SendDeformMsg(const net::PositionQ& pos, const net::PositionQ& deform)
|
||||||
|
{
|
||||||
|
auto msg = BeginEntMsg(net::EMSG_DEFORM);
|
||||||
|
net::WritePositionQ(msg, pos);
|
||||||
|
net::WritePositionQ(msg, deform);
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "vehicle_sync.hpp"
|
#include "vehicle_sync.hpp"
|
||||||
|
#include "deform_grid.hpp"
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
@ -41,7 +42,7 @@ public:
|
|||||||
virtual void Update() override;
|
virtual void Update() override;
|
||||||
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
|
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
|
||||||
|
|
||||||
virtual void OnContact(float impulse) override;
|
virtual void OnContact(const collision::ContactInfo& info) override;
|
||||||
|
|
||||||
void SetInput(VehicleInputType type, bool enable);
|
void SetInput(VehicleInputType type, bool enable);
|
||||||
void SetInputs(VehicleInputFlags inputs) { in_ = inputs; }
|
void SetInputs(VehicleInputFlags inputs) { in_ = inputs; }
|
||||||
@ -65,9 +66,14 @@ private:
|
|||||||
void UpdateCrash();
|
void UpdateCrash();
|
||||||
void UpdateWheels();
|
void UpdateWheels();
|
||||||
void UpdateSyncState();
|
void UpdateSyncState();
|
||||||
|
|
||||||
VehicleSyncFieldFlags WriteState(net::OutMessage& msg, const VehicleSyncState& base) const;
|
VehicleSyncFieldFlags WriteState(net::OutMessage& msg, const VehicleSyncState& base) const;
|
||||||
void SendUpdateMsg();
|
void SendUpdateMsg();
|
||||||
|
|
||||||
|
void WriteDeformSync(net::OutMessage& msg) const;
|
||||||
|
void Deform(const glm::vec3& pos, const glm::vec3& deform, float radius);
|
||||||
|
void SendDeformMsg(const net::PositionQ& pos, const net::PositionQ& deform);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string model_name_;
|
std::string model_name_;
|
||||||
std::shared_ptr<const assets::VehicleModel> model_;
|
std::shared_ptr<const assets::VehicleModel> model_;
|
||||||
@ -95,6 +101,8 @@ private:
|
|||||||
|
|
||||||
float crash_intensity_ = 0.0f;
|
float crash_intensity_ = 0.0f;
|
||||||
size_t no_crash_frames_ = 0;
|
size_t no_crash_frames_ = 0;
|
||||||
|
|
||||||
|
std::unique_ptr<DeformGrid> deformgrid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
@ -105,7 +105,7 @@ void game::World::HandleContacts()
|
|||||||
static std::vector<net::ObjNum> to_destroy;
|
static std::vector<net::ObjNum> to_destroy;
|
||||||
to_destroy.clear();
|
to_destroy.clear();
|
||||||
|
|
||||||
auto ProcessContact = [&](btRigidBody* body, btRigidBody* other_body, btManifoldPoint& pt) {
|
auto ProcessContact = [&](btRigidBody* body, btRigidBody* other_body, const btVector3& pos, const btVector3& normal, float impulse) {
|
||||||
collision::ObjectType type;
|
collision::ObjectType type;
|
||||||
collision::ObjectFlags flags;
|
collision::ObjectFlags flags;
|
||||||
collision::ObjectCallback* cb;
|
collision::ObjectCallback* cb;
|
||||||
@ -113,7 +113,11 @@ void game::World::HandleContacts()
|
|||||||
|
|
||||||
if (cb && (flags & collision::OF_NOTIFY_CONTACT))
|
if (cb && (flags & collision::OF_NOTIFY_CONTACT))
|
||||||
{
|
{
|
||||||
cb->OnContact(pt.getAppliedImpulse());
|
collision::ContactInfo info;
|
||||||
|
info.pos = glm::vec3(pos.x(), pos.y(), pos.z());
|
||||||
|
info.normal = glm::vec3(normal.x(), normal.y(), normal.z());
|
||||||
|
info.impulse = impulse;
|
||||||
|
cb->OnContact(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == collision::OT_MAP_OBJECT && (flags & collision::OF_DESTRUCTIBLE))
|
if (type == collision::OT_MAP_OBJECT && (flags & collision::OF_DESTRUCTIBLE))
|
||||||
@ -122,10 +126,10 @@ void game::World::HandleContacts()
|
|||||||
if (!col)
|
if (!col)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pt.getAppliedImpulse() > col->GetDestroyThreshold())
|
if (impulse > col->GetDestroyThreshold())
|
||||||
{
|
{
|
||||||
to_destroy.push_back(col->GetNum());
|
to_destroy.push_back(col->GetNum());
|
||||||
other_body->applyCentralImpulse(pt.m_normalWorldOnB * pt.getAppliedImpulse() * 0.5f);
|
other_body->applyCentralImpulse(-normal * impulse * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -143,8 +147,8 @@ void game::World::HandleContacts()
|
|||||||
for (int j = 0; j < contactManifold->getNumContacts(); j++)
|
for (int j = 0; j < contactManifold->getNumContacts(); j++)
|
||||||
{
|
{
|
||||||
btManifoldPoint& pt = contactManifold->getContactPoint(j);
|
btManifoldPoint& pt = contactManifold->getContactPoint(j);
|
||||||
ProcessContact(body0, body1, pt);
|
ProcessContact(body0, body1, pt.m_localPointA, -pt.m_normalWorldOnB, pt.getAppliedImpulse());
|
||||||
ProcessContact(body1, body0, pt);
|
ProcessContact(body1, body0, pt.m_localPointB, pt.m_normalWorldOnB, pt.getAppliedImpulse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,10 @@
|
|||||||
#include "assets/cache.hpp"
|
#include "assets/cache.hpp"
|
||||||
#include "net/utils.hpp"
|
#include "net/utils.hpp"
|
||||||
#include "worldview.hpp"
|
#include "worldview.hpp"
|
||||||
|
#include "utils/random.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
game::view::VehicleView::VehicleView(WorldView& world, net::InMessage& msg)
|
game::view::VehicleView::VehicleView(WorldView& world, net::InMessage& msg)
|
||||||
: EntityView(world, msg)
|
: EntityView(world, msg)
|
||||||
@ -16,6 +18,7 @@ game::view::VehicleView::VehicleView(WorldView& world, net::InMessage& msg)
|
|||||||
|
|
||||||
model_ = assets::CacheManager::GetVehicleModel("data/" + std::string(modelname) + ".veh");
|
model_ = assets::CacheManager::GetVehicleModel("data/" + std::string(modelname) + ".veh");
|
||||||
mesh_ = *model_->GetModel()->GetMesh();
|
mesh_ = *model_->GetModel()->GetMesh();
|
||||||
|
InitMesh();
|
||||||
|
|
||||||
auto& modelwheels = model_->GetWheels();
|
auto& modelwheels = model_->GetWheels();
|
||||||
wheels_.resize(modelwheels.size());
|
wheels_.resize(modelwheels.size());
|
||||||
@ -30,6 +33,9 @@ game::view::VehicleView::VehicleView(WorldView& world, net::InMessage& msg)
|
|||||||
if (!ReadState(&msg))
|
if (!ReadState(&msg))
|
||||||
throw EntityInitError();
|
throw EntityInitError();
|
||||||
|
|
||||||
|
if (!ReadDeformSync(msg))
|
||||||
|
throw EntityInitError();
|
||||||
|
|
||||||
// init the other transform to identical
|
// init the other transform to identical
|
||||||
root_trans_[0] = root_trans_[1];
|
root_trans_[0] = root_trans_[1];
|
||||||
root_.local = root_trans_[0];
|
root_.local = root_trans_[0];
|
||||||
@ -43,6 +49,8 @@ bool game::view::VehicleView::ProcessMsg(net::EntMsgType type, net::InMessage& m
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case net::EMSG_DEFORM:
|
||||||
|
return ProcessDeformMsg(msg);
|
||||||
default:
|
default:
|
||||||
return Super::ProcessMsg(type, msg);
|
return Super::ProcessMsg(type, msg);
|
||||||
}
|
}
|
||||||
@ -141,6 +149,44 @@ void game::view::VehicleView::Draw(const DrawArgs& args)
|
|||||||
args.dlist.AddSurface(cmd);
|
args.dlist.AddSurface(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// temp deforms
|
||||||
|
for (const auto& [pos, deform] : debug_deforms_)
|
||||||
|
{
|
||||||
|
glm::vec3 start = root_.matrix * glm::vec4(pos, 1.0f);
|
||||||
|
glm::vec3 end = root_.matrix * glm::vec4(pos + deform, 1.0f);
|
||||||
|
glm::vec3 end2 = end + glm::vec3(0.0f, 0.0f, 0.1f);
|
||||||
|
|
||||||
|
args.dlist.AddBeam(start, end, 0xFFFFFF00, 0.01f);
|
||||||
|
args.dlist.AddBeam(end, end2, 0xFFFF00FF, 0.01f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::view::VehicleView::InitMesh()
|
||||||
|
{
|
||||||
|
gfx::DeformGridInfo info{};
|
||||||
|
info.min = glm::vec3(-1.0f, -2.5f, 0.10f);
|
||||||
|
info.max = glm::vec3(1.0f, 2.0f, 1.8f);
|
||||||
|
info.res = glm::ivec3(8, 16, 8);
|
||||||
|
info.max_offset = 0.1f;
|
||||||
|
deform_ = std::make_unique<VehicleDeformView>(info);
|
||||||
|
|
||||||
|
for (auto& surface : mesh_.surfaces)
|
||||||
|
{
|
||||||
|
surface.deform_tex = deform_->tex;
|
||||||
|
surface.sflags |= gfx::SF_DEFORM_GRID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (size_t i = 0; i < 20; ++i)
|
||||||
|
// {
|
||||||
|
// glm::vec3 pos(RandomFloat(-1.0f, 1.0f), RandomFloat(-2.0f, 2.0f), RandomFloat(0.0f, 2.0f));
|
||||||
|
// glm::vec3 impulse(RandomFloat(-1.0f, 1.0f), RandomFloat(-1.0f, 1.0f), RandomFloat(-1.0f, 1.0f));
|
||||||
|
// impulse *= 0.05f;
|
||||||
|
|
||||||
|
// deform_->grid.ApplyImpulse(pos, impulse, 1.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
deform_->tex->SetData(deform_->grid.GetData());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::view::VehicleView::ReadState(net::InMessage* msg)
|
bool game::view::VehicleView::ReadState(net::InMessage* msg)
|
||||||
@ -218,3 +264,58 @@ bool game::view::VehicleView::ReadState(net::InMessage* msg)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::VehicleView::ReadDeformSync(net::InMessage& msg)
|
||||||
|
{
|
||||||
|
net::NumTexels numtexels;
|
||||||
|
if (!msg.Read(numtexels))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto texels = deform_->grid.GetData();
|
||||||
|
std::ranges::fill(texels, glm::i8vec3(0));
|
||||||
|
|
||||||
|
size_t current = 0;
|
||||||
|
for (size_t i = 0; i < numtexels; ++i)
|
||||||
|
{
|
||||||
|
int64_t diff;
|
||||||
|
if (!msg.ReadVarInt(diff))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
current += static_cast<size_t>(diff);
|
||||||
|
|
||||||
|
if (current >= texels.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto& texel = texels[current];
|
||||||
|
for (size_t j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
if (!msg.Read(texel[j]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deform_->tex->SetData(deform_->grid.GetData());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game::view::VehicleView::ProcessDeformMsg(net::InMessage& msg)
|
||||||
|
{
|
||||||
|
net::PositionQ pos_q, deform_q;
|
||||||
|
if (!net::ReadPositionQ(msg, pos_q) || !net::ReadPositionQ(msg, deform_q))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
glm::vec3 pos, deform;
|
||||||
|
net::DecodePosition(pos_q, pos);
|
||||||
|
net::DecodePosition(deform_q, deform);
|
||||||
|
|
||||||
|
deform_->grid.ApplyImpulse(pos, deform, 0.3f);
|
||||||
|
deform_->tex->SetData(deform_->grid.GetData());
|
||||||
|
|
||||||
|
//debug_deforms_.emplace_back(std::make_tuple(pos, deform));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "assets/vehiclemdl.hpp"
|
#include "assets/vehiclemdl.hpp"
|
||||||
#include "game/vehicle_sync.hpp"
|
#include "game/vehicle_sync.hpp"
|
||||||
|
#include "game/deform_grid.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@ -19,6 +20,14 @@ struct VehicleWheelViewInfo
|
|||||||
float rotation = 0.0f;
|
float rotation = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VehicleDeformView
|
||||||
|
{
|
||||||
|
DeformGrid grid;
|
||||||
|
std::shared_ptr<gfx::DeformTexture> tex;
|
||||||
|
|
||||||
|
VehicleDeformView(const gfx::DeformGridInfo& info) : grid(info), tex(std::make_shared<gfx::DeformTexture>(info)) {}
|
||||||
|
};
|
||||||
|
|
||||||
class VehicleView : public EntityView
|
class VehicleView : public EntityView
|
||||||
{
|
{
|
||||||
using Super = EntityView;
|
using Super = EntityView;
|
||||||
@ -32,8 +41,13 @@ public:
|
|||||||
virtual void Draw(const DrawArgs& args) override;
|
virtual void Draw(const DrawArgs& args) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void InitMesh();
|
||||||
|
|
||||||
bool ReadState(net::InMessage* msg);
|
bool ReadState(net::InMessage* msg);
|
||||||
|
|
||||||
|
bool ReadDeformSync(net::InMessage& msg);
|
||||||
|
bool ProcessDeformMsg(net::InMessage& msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<const assets::VehicleModel> model_;
|
std::shared_ptr<const assets::VehicleModel> model_;
|
||||||
assets::Mesh mesh_;
|
assets::Mesh mesh_;
|
||||||
@ -51,6 +65,8 @@ private:
|
|||||||
audio::SoundSource* snd_accel_src_ = nullptr;
|
audio::SoundSource* snd_accel_src_ = nullptr;
|
||||||
|
|
||||||
bool windows_broken_ = false;
|
bool windows_broken_ = false;
|
||||||
|
std::unique_ptr<VehicleDeformView> deform_;
|
||||||
|
std::vector<std::tuple<glm::vec3, glm::vec3>> debug_deforms_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
17
src/gfx/deform_grid_info.hpp
Normal file
17
src/gfx/deform_grid_info.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace gfx
|
||||||
|
{
|
||||||
|
|
||||||
|
struct DeformGridInfo
|
||||||
|
{
|
||||||
|
glm::vec3 min;
|
||||||
|
glm::vec3 max;
|
||||||
|
glm::ivec3 res;
|
||||||
|
float max_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
32
src/gfx/deform_texture.cpp
Normal file
32
src/gfx/deform_texture.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "deform_texture.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
gfx::DeformTexture::DeformTexture(const DeformGridInfo& info) : info_(info)
|
||||||
|
{
|
||||||
|
glGenTextures(1, &id_);
|
||||||
|
|
||||||
|
if (!id_)
|
||||||
|
throw std::runtime_error("Nelze vytvorit texturu!");
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_3D, id_);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_3D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx::DeformTexture::SetData(std::span<const glm::i8vec3> data)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_3D, id_);
|
||||||
|
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8_SNORM, info_.res.x, info_.res.y, info_.res.z, 0, GL_RGB, GL_BYTE, data.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::DeformTexture::~DeformTexture()
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &id_);
|
||||||
|
}
|
||||||
34
src/gfx/deform_texture.hpp
Normal file
34
src/gfx/deform_texture.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include "client/gl.hpp"
|
||||||
|
#include "utils/defs.hpp"
|
||||||
|
#include "deform_grid_info.hpp"
|
||||||
|
|
||||||
|
namespace gfx
|
||||||
|
{
|
||||||
|
|
||||||
|
class DeformTexture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeformTexture(const DeformGridInfo& info);
|
||||||
|
DELETE_COPY_MOVE(DeformTexture)
|
||||||
|
|
||||||
|
void SetData(std::span<const glm::i8vec3> data);
|
||||||
|
|
||||||
|
const DeformGridInfo& GetInfo() const { return info_; }
|
||||||
|
GLuint GetId() const { return id_; }
|
||||||
|
|
||||||
|
~DeformTexture();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const DeformGridInfo info_;
|
||||||
|
GLuint id_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,6 +16,7 @@ gfx::Renderer::Renderer()
|
|||||||
{
|
{
|
||||||
ShaderSources::MakeShader(mesh_shader_.shader, SS_MESH_VERT, SS_MESH_FRAG);
|
ShaderSources::MakeShader(mesh_shader_.shader, SS_MESH_VERT, SS_MESH_FRAG);
|
||||||
ShaderSources::MakeShader(skel_mesh_shader_.shader, SS_SKEL_MESH_VERT, SS_SKEL_MESH_FRAG);
|
ShaderSources::MakeShader(skel_mesh_shader_.shader, SS_SKEL_MESH_VERT, SS_SKEL_MESH_FRAG);
|
||||||
|
ShaderSources::MakeShader(deform_mesh_shader_.shader, SS_DEFORM_MESH_VERT, SS_DEFORM_MESH_FRAG);
|
||||||
ShaderSources::MakeShader(solid_shader_, SS_SOLID_VERT, SS_SOLID_FRAG);
|
ShaderSources::MakeShader(solid_shader_, SS_SOLID_VERT, SS_SOLID_FRAG);
|
||||||
ShaderSources::MakeShader(hud_shader_, SS_HUD_VERT, SS_HUD_FRAG);
|
ShaderSources::MakeShader(hud_shader_, SS_HUD_VERT, SS_HUD_FRAG);
|
||||||
ShaderSources::MakeShader(beam_shader_, SS_BEAM_VERT, SS_BEAM_FRAG);
|
ShaderSources::MakeShader(beam_shader_, SS_BEAM_VERT, SS_BEAM_FRAG);
|
||||||
@ -104,6 +105,7 @@ void gfx::Renderer::InvalidateShaders()
|
|||||||
{
|
{
|
||||||
InvalidateMeshShader(mesh_shader_);
|
InvalidateMeshShader(mesh_shader_);
|
||||||
InvalidateMeshShader(skel_mesh_shader_);
|
InvalidateMeshShader(skel_mesh_shader_);
|
||||||
|
InvalidateMeshShader(deform_mesh_shader_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::Renderer::InvalidateMeshShader(MeshShader& mshader)
|
void gfx::Renderer::InvalidateMeshShader(MeshShader& mshader)
|
||||||
@ -171,6 +173,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
const gfx::Texture* last_texture = nullptr;
|
const gfx::Texture* last_texture = nullptr;
|
||||||
const gfx::VertexArray* last_vao = nullptr;
|
const gfx::VertexArray* last_vao = nullptr;
|
||||||
const gfx::UniformBuffer<glm::mat4>* last_skin = nullptr;
|
const gfx::UniformBuffer<glm::mat4>* last_skin = nullptr;
|
||||||
|
const DeformTexture* last_deform = nullptr;
|
||||||
InvalidateShaders();
|
InvalidateShaders();
|
||||||
|
|
||||||
// enable depth test
|
// enable depth test
|
||||||
@ -199,6 +202,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
const bool twosided_flag = surface->sflags & SF_2SIDED;
|
const bool twosided_flag = surface->sflags & SF_2SIDED;
|
||||||
const bool blend_flag = surface->sflags & SF_BLEND;
|
const bool blend_flag = surface->sflags & SF_BLEND;
|
||||||
const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR;
|
const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR;
|
||||||
|
const bool deform_flag = surface->sflags & SF_DEFORM_GRID;
|
||||||
|
|
||||||
// sync 2sided
|
// sync 2sided
|
||||||
if (last_twosided != twosided_flag)
|
if (last_twosided != twosided_flag)
|
||||||
@ -212,7 +216,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// select shader
|
// select shader
|
||||||
MeshShader& mshader = skeletal_flag ? skel_mesh_shader_ : mesh_shader_;
|
MeshShader& mshader = skeletal_flag ? skel_mesh_shader_ : (deform_flag ? deform_mesh_shader_ : mesh_shader_);
|
||||||
SetupMeshShader(mshader, params);
|
SetupMeshShader(mshader, params);
|
||||||
|
|
||||||
// set model matrix
|
// set model matrix
|
||||||
@ -290,6 +294,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
if (last_texture != surface->texture.get())
|
if (last_texture != surface->texture.get())
|
||||||
{
|
{
|
||||||
GLuint tex_id = surface->texture ? surface->texture->GetId() : 0;
|
GLuint tex_id = surface->texture ? surface->texture->GetId() : 0;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, tex_id);
|
glBindTexture(GL_TEXTURE_2D, tex_id);
|
||||||
last_texture = surface->texture.get();
|
last_texture = surface->texture.get();
|
||||||
}
|
}
|
||||||
@ -297,10 +302,28 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
// bind skinning UBO
|
// bind skinning UBO
|
||||||
if (cmd.skinning && last_skin != cmd.skinning)
|
if (cmd.skinning && last_skin != cmd.skinning)
|
||||||
{
|
{
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cmd.skinning->GetId());
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cmd.skinning->GetId());
|
||||||
last_skin = cmd.skinning;
|
last_skin = cmd.skinning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind deform texture
|
||||||
|
if (deform_flag && surface->deform_tex.get() != last_deform)
|
||||||
|
{
|
||||||
|
const auto& deform_tex = *surface->deform_tex;
|
||||||
|
GLuint tex_id = deform_tex.GetId();
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_3D, tex_id);
|
||||||
|
last_deform = &deform_tex;
|
||||||
|
|
||||||
|
// update deform tex info
|
||||||
|
const auto& deform_info = deform_tex.GetInfo();
|
||||||
|
glm::mat3 deform_info_mat;
|
||||||
|
deform_info_mat[0] = deform_info.min;
|
||||||
|
deform_info_mat[1] = deform_info.max;
|
||||||
|
deform_info_mat[2] = glm::vec3(deform_info.max_offset, 0.0f, 0.0f);
|
||||||
|
glUniformMatrix3fv(mshader.shader->U(SU_DEFORM_INFO), 1, GL_FALSE, &deform_info_mat[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
// bind VAO
|
// bind VAO
|
||||||
if (last_vao != surface->va.get())
|
if (last_vao != surface->va.get())
|
||||||
{
|
{
|
||||||
@ -428,6 +451,8 @@ void gfx::Renderer::DrawHudList(std::span<DrawHudCmd> queue, const DrawListParam
|
|||||||
const gfx::Texture* last_texture = nullptr;
|
const gfx::Texture* last_texture = nullptr;
|
||||||
const gfx::VertexArray* last_vao = nullptr;
|
const gfx::VertexArray* last_vao = nullptr;
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
for (const auto& cmd : queue)
|
for (const auto& cmd : queue)
|
||||||
{
|
{
|
||||||
if (!cmd.va || !cmd.texture)
|
if (!cmd.va || !cmd.texture)
|
||||||
|
|||||||
@ -52,6 +52,7 @@ namespace gfx
|
|||||||
private:
|
private:
|
||||||
MeshShader mesh_shader_;
|
MeshShader mesh_shader_;
|
||||||
MeshShader skel_mesh_shader_;
|
MeshShader skel_mesh_shader_;
|
||||||
|
MeshShader deform_mesh_shader_;
|
||||||
std::unique_ptr<Shader> solid_shader_;
|
std::unique_ptr<Shader> solid_shader_;
|
||||||
|
|
||||||
std::unique_ptr<BufferObject> beam_segments_vbo_;
|
std::unique_ptr<BufferObject> beam_segments_vbo_;
|
||||||
|
|||||||
@ -11,6 +11,8 @@ static const char* const s_uni_names[] = {
|
|||||||
"u_color", // SU_COLOR
|
"u_color", // SU_COLOR
|
||||||
"u_flags", // SU_FLAGS
|
"u_flags", // SU_FLAGS
|
||||||
"u_camera", // SU_CAMERA
|
"u_camera", // SU_CAMERA
|
||||||
|
"u_deform_tex", // SU_DEFORM_TEX
|
||||||
|
"u_deform_info", // SU_DEFORM_INFO
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vytvori shader z daneho zdroje
|
// Vytvori shader z daneho zdroje
|
||||||
@ -93,6 +95,7 @@ void gfx::Shader::SetupBindings()
|
|||||||
glUseProgram(m_id);
|
glUseProgram(m_id);
|
||||||
|
|
||||||
glUniform1i(m_uni[SU_TEX], 0);
|
glUniform1i(m_uni[SU_TEX], 0);
|
||||||
|
glUniform1i(m_uni[SU_DEFORM_TEX], 1);
|
||||||
|
|
||||||
// Bones UBO
|
// Bones UBO
|
||||||
int ubo_index = glGetUniformBlockIndex(m_id, "Bones");
|
int ubo_index = glGetUniformBlockIndex(m_id, "Bones");
|
||||||
|
|||||||
@ -16,6 +16,8 @@ namespace gfx
|
|||||||
SU_COLOR,
|
SU_COLOR,
|
||||||
SU_FLAGS,
|
SU_FLAGS,
|
||||||
SU_CAMERA,
|
SU_CAMERA,
|
||||||
|
SU_DEFORM_TEX,
|
||||||
|
SU_DEFORM_INFO,
|
||||||
|
|
||||||
SU_COUNT
|
SU_COUNT
|
||||||
};
|
};
|
||||||
|
|||||||
@ -212,6 +212,76 @@ void main() {
|
|||||||
|
|
||||||
)GLSL",
|
)GLSL",
|
||||||
|
|
||||||
|
// SS_DEFORM_MESH_VERT
|
||||||
|
SHADER_HEADER
|
||||||
|
R"GLSL(
|
||||||
|
layout (location = 0) in vec3 a_pos;
|
||||||
|
layout (location = 1) in vec3 a_normal;
|
||||||
|
layout (location = 2) in vec4 a_color;
|
||||||
|
layout (location = 3) in vec2 a_uv;
|
||||||
|
|
||||||
|
)GLSL"
|
||||||
|
MESH_MATRICES_GLSL
|
||||||
|
LIGHT_MATRICES_GLSL
|
||||||
|
COMPUTE_LIGHTS_GLSL
|
||||||
|
R"GLSL(
|
||||||
|
|
||||||
|
uniform sampler3D u_deform_tex;
|
||||||
|
uniform mat3 u_deform_info;
|
||||||
|
|
||||||
|
out vec2 v_uv;
|
||||||
|
out vec3 v_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 deform_pos = (a_pos - u_deform_info[0]) / (u_deform_info[1] - u_deform_info[0]);
|
||||||
|
vec3 pos = a_pos + texture(u_deform_tex, deform_pos).xyz * u_deform_info[2].x;
|
||||||
|
//vec3 pos = a_pos + u_deform_info[0] * u_deform_info[2].x;
|
||||||
|
//vec3 pos = a_pos + vec3(0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
vec4 world_pos = u_model * vec4(pos, 1.0);
|
||||||
|
vec3 world_normal = normalize(mat3(u_model) * a_normal);
|
||||||
|
gl_Position = u_view_proj * world_pos;
|
||||||
|
|
||||||
|
v_uv = a_uv;
|
||||||
|
v_color = ComputeLights(world_pos.xyz, world_normal) * a_color.rgb;
|
||||||
|
}
|
||||||
|
)GLSL",
|
||||||
|
|
||||||
|
// SS_DEFORM_MESH_FRAG
|
||||||
|
SHADER_HEADER
|
||||||
|
R"GLSL(
|
||||||
|
in vec2 v_uv;
|
||||||
|
in vec3 v_color;
|
||||||
|
|
||||||
|
#define SHF_CULL_ALPHA 1
|
||||||
|
#define SHF_BACKGROUND 2
|
||||||
|
|
||||||
|
uniform sampler2D u_tex;
|
||||||
|
uniform vec4 u_color;
|
||||||
|
uniform int u_flags;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 o_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
o_color = vec4(texture(u_tex, v_uv));
|
||||||
|
|
||||||
|
if ((u_flags & SHF_CULL_ALPHA) > 0)
|
||||||
|
{
|
||||||
|
if (o_color.a < 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
else if ((u_flags & SHF_BACKGROUND) > 0)
|
||||||
|
{
|
||||||
|
// blend with bg
|
||||||
|
o_color = mix(u_color, o_color, o_color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
o_color.rgb *= v_color; // Apply vertex color
|
||||||
|
//o_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
)GLSL",
|
||||||
|
|
||||||
// SS_SOLID_VERT
|
// SS_SOLID_VERT
|
||||||
SHADER_HEADER
|
SHADER_HEADER
|
||||||
R"GLSL(
|
R"GLSL(
|
||||||
|
|||||||
@ -13,6 +13,9 @@ namespace gfx
|
|||||||
SS_SKEL_MESH_VERT,
|
SS_SKEL_MESH_VERT,
|
||||||
SS_SKEL_MESH_FRAG,
|
SS_SKEL_MESH_FRAG,
|
||||||
|
|
||||||
|
SS_DEFORM_MESH_VERT,
|
||||||
|
SS_DEFORM_MESH_FRAG,
|
||||||
|
|
||||||
SS_SOLID_VERT,
|
SS_SOLID_VERT,
|
||||||
SS_SOLID_FRAG,
|
SS_SOLID_FRAG,
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "texture.hpp"
|
#include "texture.hpp"
|
||||||
#include "vertex_array.hpp"
|
#include "vertex_array.hpp"
|
||||||
|
#include "deform_texture.hpp"
|
||||||
|
|
||||||
namespace gfx
|
namespace gfx
|
||||||
{
|
{
|
||||||
@ -24,16 +25,18 @@ enum SurfaceFlag : SurfaceFlags
|
|||||||
SF_BLEND = 0x02, // enable blending, disable depth write
|
SF_BLEND = 0x02, // enable blending, disable depth write
|
||||||
SF_BLEND_ADDITIVE = 0x04, // use additive blending instead of opacity
|
SF_BLEND_ADDITIVE = 0x04, // use additive blending instead of opacity
|
||||||
SF_OBJECT_COLOR = 0x08, // use object color for background instead of alpha culling
|
SF_OBJECT_COLOR = 0x08, // use object color for background instead of alpha culling
|
||||||
|
SF_DEFORM_GRID = 0x10, // use deform grid
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Surface
|
struct Surface
|
||||||
{
|
{
|
||||||
std::shared_ptr<const gfx::Texture> texture;
|
std::shared_ptr<const Texture> texture;
|
||||||
std::shared_ptr<const gfx::VertexArray> va;
|
std::shared_ptr<const VertexArray> va;
|
||||||
size_t first = 0; // first triangle VA EBO
|
size_t first = 0; // first triangle VA EBO
|
||||||
size_t count = 0; // number of triangles
|
size_t count = 0; // number of triangles
|
||||||
MeshFlags mflags = MF_NONE;
|
MeshFlags mflags = MF_NONE;
|
||||||
SurfaceFlags sflags = SF_NONE;
|
SurfaceFlags sflags = SF_NONE;
|
||||||
|
std::shared_ptr<const DeformTexture> deform_tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
@ -90,6 +90,7 @@ enum EntMsgType : uint8_t
|
|||||||
EMSG_ATTACH,
|
EMSG_ATTACH,
|
||||||
// EMSG_UPDATE, // deprecated
|
// EMSG_UPDATE, // deprecated
|
||||||
EMSG_PLAYSOUND,
|
EMSG_PLAYSOUND,
|
||||||
|
EMSG_DEFORM,
|
||||||
};
|
};
|
||||||
|
|
||||||
using PositionElemQ = Quantized<uint32_t, -10000, 10000, 1>;
|
using PositionElemQ = Quantized<uint32_t, -10000, 10000, 1>;
|
||||||
@ -128,4 +129,6 @@ using ClothesName = FixedStr<32>;
|
|||||||
using ObjNum = uint16_t;
|
using ObjNum = uint16_t;
|
||||||
using ObjCount = ObjNum;
|
using ObjCount = ObjNum;
|
||||||
|
|
||||||
|
using NumTexels = uint16_t;
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
Loading…
x
Reference in New Issue
Block a user