Add better movement and teleporting
This commit is contained in:
parent
e4ee01de2e
commit
b81cee948d
@ -19,6 +19,9 @@ add_executable(PortalGame
|
|||||||
"src/collision/trianglemesh.cpp"
|
"src/collision/trianglemesh.cpp"
|
||||||
"src/game/entity.hpp"
|
"src/game/entity.hpp"
|
||||||
"src/game/entity.cpp"
|
"src/game/entity.cpp"
|
||||||
|
"src/game/player_input.hpp"
|
||||||
|
"src/game/player.hpp"
|
||||||
|
"src/game/player.cpp"
|
||||||
"src/game/sector.hpp"
|
"src/game/sector.hpp"
|
||||||
"src/game/sector.cpp"
|
"src/game/sector.cpp"
|
||||||
"src/game/world.hpp"
|
"src/game/world.hpp"
|
||||||
|
|||||||
95
src/app.cpp
95
src/app.cpp
@ -22,11 +22,7 @@ App::App()
|
|||||||
world_.LinkPortals(s1, "NDoor", s2, "WDoor");
|
world_.LinkPortals(s1, "NDoor", s2, "WDoor");
|
||||||
world_.LinkPortals(s2, "NDoor", s2, "SDoor");
|
world_.LinkPortals(s2, "NDoor", s2, "SDoor");
|
||||||
|
|
||||||
game::CapsuleShape capsule_shape;
|
player_ = world_.Spawn<game::Player>(s1, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
capsule_shape.radius = 0.2f; // 20cm radius
|
|
||||||
capsule_shape.height = 0.3f; // 1.8m height
|
|
||||||
|
|
||||||
player_ = world_.Spawn<game::Entity>(s1, capsule_shape, glm::vec3(0.0f, 0.0f, 1.0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::Frame()
|
void App::Frame()
|
||||||
@ -47,85 +43,34 @@ void App::Frame()
|
|||||||
|
|
||||||
renderer_.Begin(viewport_size_.x, viewport_size_.y);
|
renderer_.Begin(viewport_size_.x, viewport_size_.y);
|
||||||
|
|
||||||
//float cameraDistance = 2.0f;
|
player_->SetInput(input_);
|
||||||
//float angle = time_ * 0.1f; // Rotate over time
|
|
||||||
//
|
|
||||||
//glm::vec3 cameraPos = glm::vec3(
|
|
||||||
// cameraDistance * cos(angle),
|
|
||||||
// cameraDistance * sin(angle),
|
|
||||||
// cameraDistance * 0.13f
|
|
||||||
//);
|
|
||||||
|
|
||||||
//glm::vec3 center(0.0f, 0.0f, 1.5f);
|
|
||||||
//glm::vec3 up(0.0f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
//renderer_.DrawWorld(world_, 1, center + cameraPos, -cameraPos, up, aspect, 60.0f);
|
|
||||||
|
|
||||||
glm::vec3 velocity(0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
if (input_ & game::PI_FORWARD)
|
|
||||||
velocity.y += 1.0f;
|
|
||||||
|
|
||||||
if (input_ & game::PI_BACKWARD)
|
|
||||||
velocity.y -= 1.0f;
|
|
||||||
|
|
||||||
if (input_ & game::PI_LEFT)
|
|
||||||
velocity.x -= 1.0f;
|
|
||||||
|
|
||||||
if (input_ & game::PI_RIGHT)
|
|
||||||
velocity.x += 1.0f;
|
|
||||||
|
|
||||||
if (input_ & game::PI_JUMP)
|
|
||||||
velocity.z += 1.0f;
|
|
||||||
|
|
||||||
if (input_ & game::PI_CROUCH)
|
|
||||||
velocity.z -= 1.0f;
|
|
||||||
|
|
||||||
glm::vec3 forward = glm::vec3(
|
|
||||||
cos(angles_.x) * cos(angles_.y),
|
|
||||||
sin(angles_.x) * cos(angles_.y),
|
|
||||||
sin(angles_.y)
|
|
||||||
);
|
|
||||||
|
|
||||||
velocity.z -= 0.1f * delta_time; // Apply gravity
|
|
||||||
|
|
||||||
glm::vec3 forward_xy = glm::normalize(glm::vec3(forward.x, forward.y, 0.0f));
|
|
||||||
glm::vec3 right = glm::normalize(glm::vec3(forward.y, -forward.x, 0.0f));
|
|
||||||
velocity = glm::normalize(velocity.x * right + velocity.y * forward_xy + velocity.z * glm::vec3(0.0f, 0.0f, 1.0f));
|
|
||||||
|
|
||||||
//if (glm::length(velocity) > 0.1f)
|
|
||||||
//{
|
|
||||||
// velocity = glm::normalize(velocity); // Normalize to prevent faster diagonal movement
|
|
||||||
|
|
||||||
// glm::vec3 u = velocity * delta_time * 2.0f;
|
|
||||||
// //bool hit = world_.GetSector(0).SweepCapsule(position, position + u);
|
|
||||||
|
|
||||||
// //if (!hit)
|
|
||||||
// //{
|
|
||||||
// // position += u;
|
|
||||||
// //}
|
|
||||||
//}
|
|
||||||
|
|
||||||
player_->SetVelocity(velocity);
|
|
||||||
player_->Update(delta_time);
|
player_->Update(delta_time);
|
||||||
|
|
||||||
const auto& position = player_->GetOccurrence().GetPosition();
|
//const auto& position = player_->GetOccurrence().GetPosition();
|
||||||
|
size_t sector_idx;
|
||||||
|
glm::vec3 position, forward, up;
|
||||||
|
player_->GetPOV(sector_idx, position, forward, up);
|
||||||
|
|
||||||
renderer_.DrawWorld(world_, 0, position, forward, glm::vec3(0.0f, 0.0f, 1.0f), aspect, 60.0f);
|
renderer_.DrawWorld(world_, sector_idx, position, forward, up, aspect, 60.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::MouseMove(const glm::vec2& delta)
|
void App::MouseMove(const glm::vec2& delta)
|
||||||
{
|
{
|
||||||
float sensitivity = 0.002f; // Sensitivity factor for mouse movement
|
float sensitivity = 0.002f; // Sensitivity factor for mouse movement
|
||||||
angles_.x -= delta.x * sensitivity; // Yaw
|
//angles_.x -= delta.x * sensitivity; // Yaw
|
||||||
angles_.y -= delta.y * sensitivity; // Pitch
|
//angles_.y -= delta.y * sensitivity; // Pitch
|
||||||
|
|
||||||
// Clamp pitch to avoid gimbal lock
|
//// Clamp pitch to avoid gimbal lock
|
||||||
if (angles_.y > glm::radians(89.0f)) {
|
//if (angles_.y > glm::radians(89.0f)) {
|
||||||
angles_.y = glm::radians(89.0f);
|
// angles_.y = glm::radians(89.0f);
|
||||||
} else if (angles_.y < glm::radians(-89.0f)) {
|
//} else if (angles_.y < glm::radians(-89.0f)) {
|
||||||
angles_.y = glm::radians(-89.0f);
|
// angles_.y = glm::radians(-89.0f);
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
float delta_yaw = delta.x * sensitivity;
|
||||||
|
float delta_pitch = -delta.y * sensitivity;
|
||||||
|
|
||||||
|
player_->Rotate(delta_yaw, delta_pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
App::~App()
|
App::~App()
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "game/world.hpp"
|
#include "game/world.hpp"
|
||||||
#include "game/player_input.hpp"
|
#include "game/player_input.hpp"
|
||||||
|
#include "game/player.hpp"
|
||||||
#include "gfx/renderer.hpp"
|
#include "gfx/renderer.hpp"
|
||||||
|
|
||||||
class App
|
class App
|
||||||
@ -15,9 +16,7 @@ class App
|
|||||||
float prev_time_ = 0.0f;
|
float prev_time_ = 0.0f;
|
||||||
|
|
||||||
game::World world_;
|
game::World world_;
|
||||||
game::Entity* player_ = nullptr;
|
game::Player* player_ = nullptr;
|
||||||
|
|
||||||
glm::vec2 angles_ = { 0.0f, 0.0f }; // Pitch and yaw angles in radians
|
|
||||||
|
|
||||||
gfx::Renderer renderer_;
|
gfx::Renderer renderer_;
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
game::Entity::Entity(World* world, size_t sector_idx, const CapsuleShape& capsule_shape, const glm::vec3& position) :
|
game::Entity::Entity(World* world, size_t sector_idx, const CapsuleShape& capsule_shape, const glm::vec3& position) :
|
||||||
world_(world),
|
world_(world),
|
||||||
capsule_(capsule_shape),
|
capsule_(capsule_shape),
|
||||||
velocity_(0.0f)
|
velocity_(0.0f),
|
||||||
|
touching_portal_(nullptr)
|
||||||
{
|
{
|
||||||
CreateOccurrenceParams occu_params;
|
CreateOccurrenceParams occu_params;
|
||||||
occu_params.sector = &world->GetSector(sector_idx);
|
occu_params.sector = &world->GetSector(sector_idx);
|
||||||
@ -23,7 +24,7 @@ void game::Entity::Move(glm::vec3& velocity, float dt)
|
|||||||
const int MAX_ITERS = 4;
|
const int MAX_ITERS = 4;
|
||||||
for (size_t i = 0; i < MAX_ITERS && glm::dot(u, u) > 0.0f; ++i)
|
for (size_t i = 0; i < MAX_ITERS && glm::dot(u, u) > 0.0f; ++i)
|
||||||
{
|
{
|
||||||
printf("Entity::Move: Iteration %zu, u = (%f, %f, %f)\n", i, u.x, u.y, u.z);
|
//printf("Entity::Move: Iteration %zu, u = (%f, %f, %f)\n", i, u.x, u.y, u.z);
|
||||||
|
|
||||||
// offset in occu's sector space
|
// offset in occu's sector space
|
||||||
glm::vec3 occu_offset = occu_->basis_ * u;
|
glm::vec3 occu_offset = occu_->basis_ * u;
|
||||||
@ -37,6 +38,7 @@ void game::Entity::Move(glm::vec3& velocity, float dt)
|
|||||||
|
|
||||||
if (hit_portal != touching_portal_)
|
if (hit_portal != touching_portal_)
|
||||||
{
|
{
|
||||||
|
printf("Entity::Move: Touching portal changed from %p to %p\n", touching_portal_, hit_portal);
|
||||||
touching_portal_ = hit_portal;
|
touching_portal_ = hit_portal;
|
||||||
|
|
||||||
if (hit_portal)
|
if (hit_portal)
|
||||||
@ -85,15 +87,21 @@ void game::Entity::Move(glm::vec3& velocity, float dt)
|
|||||||
// Update the position based on the hit fraction
|
// Update the position based on the hit fraction
|
||||||
occu_->position_ += hit_fraction * occu_offset;
|
occu_->position_ += hit_fraction * occu_offset;
|
||||||
|
|
||||||
if (any_hit)
|
//if (any_hit)
|
||||||
{
|
//{
|
||||||
occu_->position_ += hit_normal * 0.00001f;
|
// occu_->position_ += hit_normal * 0.00001f;
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
if (other_occu_ && touching_portal_)
|
if (other_occu_ && touching_portal_)
|
||||||
{
|
{
|
||||||
other_occu_->position_ = touching_portal_->tr_position * glm::vec4(occu_->position_, 1.0f);
|
other_occu_->position_ = touching_portal_->tr_position * glm::vec4(occu_->position_, 1.0f);
|
||||||
|
|
||||||
|
// TELEPORT
|
||||||
|
float sd = glm::dot(glm::vec3(touching_portal_->plane), occu_->position_) + touching_portal_->plane.w;
|
||||||
|
if (sd < 0.0f)
|
||||||
|
{
|
||||||
|
std::swap(occu_, other_occu_); // Swap occurrences
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!any_hit)
|
if (!any_hit)
|
||||||
@ -102,7 +110,7 @@ void game::Entity::Move(glm::vec3& velocity, float dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//hit_normal *= -1.0f; // Invert the normal to point outwards
|
//hit_normal *= -1.0f; // Invert the normal to point outwards
|
||||||
printf("Entity::Move: Hit detected, hit_fraction = %f, hit_normal = (%f, %f, %f)\n", hit_fraction, hit_normal.x, hit_normal.y, hit_normal.z);
|
//printf("Entity::Move: Hit detected, hit_fraction = %f, hit_normal = (%f, %f, %f)\n", hit_fraction, hit_normal.x, hit_normal.y, hit_normal.z);
|
||||||
|
|
||||||
u -= hit_fraction * u; // Reduce the movement vector by the hit fraction
|
u -= hit_fraction * u; // Reduce the movement vector by the hit fraction
|
||||||
u -= glm::dot(u, hit_normal) * hit_normal; // Reflect the velocity along the hit normal
|
u -= glm::dot(u, hit_normal) * hit_normal; // Reflect the velocity along the hit normal
|
||||||
@ -118,6 +126,14 @@ void game::Entity::Update(float dt)
|
|||||||
|
|
||||||
void game::Entity::CreateOtherOccurence(const Portal& portal)
|
void game::Entity::CreateOtherOccurence(const Portal& portal)
|
||||||
{
|
{
|
||||||
|
other_occu_.reset();
|
||||||
|
|
||||||
|
if (!portal.link)
|
||||||
|
{
|
||||||
|
// No linked sector, no occurence :(
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CreateOccurrenceParams other_occu_params;
|
CreateOccurrenceParams other_occu_params;
|
||||||
other_occu_params.sector = portal.link->sector;
|
other_occu_params.sector = portal.link->sector;
|
||||||
other_occu_params.position = portal.tr_position * glm::vec4(occu_->position_, 1.0f);
|
other_occu_params.position = portal.tr_position * glm::vec4(occu_->position_, 1.0f);
|
||||||
@ -141,13 +157,22 @@ game::EntityOccurrence::EntityOccurrence(Entity* entity, const CreateOccurrenceP
|
|||||||
|
|
||||||
bool game::EntityOccurrence::Sweep(const glm::vec3& target_position, float& hit_fraction, glm::vec3& hit_normal, const Portal** hit_portal)
|
bool game::EntityOccurrence::Sweep(const glm::vec3& target_position, float& hit_fraction, glm::vec3& hit_normal, const Portal** hit_portal)
|
||||||
{
|
{
|
||||||
|
if (hit_portal)
|
||||||
|
{
|
||||||
|
*hit_portal = sector_->TestPortalContact(bt_capsule_, basis_, position_);
|
||||||
|
|
||||||
|
if (!*hit_portal)
|
||||||
|
{
|
||||||
|
*hit_portal = sector_->TestPortalContact(bt_capsule_, basis_, target_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return sector_->SweepCapsule(
|
return sector_->SweepCapsule(
|
||||||
bt_capsule_,
|
bt_capsule_,
|
||||||
basis_,
|
basis_,
|
||||||
position_,
|
position_,
|
||||||
target_position,
|
target_position,
|
||||||
hit_fraction,
|
hit_fraction,
|
||||||
hit_normal,
|
hit_normal
|
||||||
hit_portal
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,10 +45,14 @@ namespace game
|
|||||||
|
|
||||||
const Sector& GetSector() const { return *sector_; }
|
const Sector& GetSector() const { return *sector_; }
|
||||||
const glm::vec3& GetPosition() const { return position_; }
|
const glm::vec3& GetPosition() const { return position_; }
|
||||||
|
|
||||||
|
const glm::mat3& GetBasis() const { return basis_; }
|
||||||
|
const glm::mat3& GetInvBasis() const { return inv_basis_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Entity
|
class Entity
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
World* world_;
|
World* world_;
|
||||||
|
|
||||||
CapsuleShape capsule_;
|
CapsuleShape capsule_;
|
||||||
@ -65,7 +69,7 @@ namespace game
|
|||||||
// offset in entity space
|
// offset in entity space
|
||||||
void Move(glm::vec3& velocity, float dt);
|
void Move(glm::vec3& velocity, float dt);
|
||||||
|
|
||||||
void Update(float dt);
|
virtual void Update(float dt);
|
||||||
|
|
||||||
void SetVelocity(const glm::vec3& velocity) { velocity_ = velocity; }
|
void SetVelocity(const glm::vec3& velocity) { velocity_ = velocity; }
|
||||||
|
|
||||||
|
|||||||
88
src/game/player.cpp
Normal file
88
src/game/player.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "player.hpp"
|
||||||
|
#include "world.hpp"
|
||||||
|
#include "sector.hpp"
|
||||||
|
|
||||||
|
game::Player::Player(World* world, size_t sector_idx, const glm::vec3& position) :
|
||||||
|
Super(world, sector_idx, { 0.3f, 1.2f }, position),
|
||||||
|
yaw_(0.0f),
|
||||||
|
pitch_(0.0f),
|
||||||
|
input_(0),
|
||||||
|
cam_forward_(0.0f),
|
||||||
|
cam_up_(0.0f)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Player::Rotate(float delta_yaw, float delta_pitch)
|
||||||
|
{
|
||||||
|
yaw_ += delta_yaw;
|
||||||
|
pitch_ += delta_pitch;
|
||||||
|
// Clamp pitch to avoid gimbal lock
|
||||||
|
if (pitch_ > glm::radians(89.0f)) {
|
||||||
|
pitch_ = glm::radians(89.0f);
|
||||||
|
} else if (pitch_ < glm::radians(-89.0f)) {
|
||||||
|
pitch_ = glm::radians(-89.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Player::Update(float dt)
|
||||||
|
{
|
||||||
|
const glm::mat3& occu_basis = occu_->GetBasis();
|
||||||
|
|
||||||
|
float yaw_cos = glm::cos(yaw_);
|
||||||
|
float yaw_sin = glm::sin(yaw_);
|
||||||
|
float pitch_cos = glm::cos(pitch_);
|
||||||
|
float pitch_sin = glm::sin(pitch_);
|
||||||
|
|
||||||
|
// MOVEMENT
|
||||||
|
glm::vec2 velocity_xy(0.0f);
|
||||||
|
if (input_ & PI_FORWARD)
|
||||||
|
velocity_xy.y += 1.0f;
|
||||||
|
|
||||||
|
if (input_ & PI_BACKWARD)
|
||||||
|
velocity_xy.y -= 1.0f;
|
||||||
|
|
||||||
|
if (input_ & PI_LEFT)
|
||||||
|
velocity_xy.x -= 1.0f;
|
||||||
|
|
||||||
|
if (input_ & PI_RIGHT)
|
||||||
|
velocity_xy.x += 1.0f;
|
||||||
|
|
||||||
|
glm::mat2 movement_basis(
|
||||||
|
yaw_cos, -yaw_sin,
|
||||||
|
yaw_sin, yaw_cos
|
||||||
|
);
|
||||||
|
|
||||||
|
float speed = 3.0f; // Base speed
|
||||||
|
|
||||||
|
glm::vec2 normalized_velocity_xy(0.0f);
|
||||||
|
if (glm::length(velocity_xy) > 0.01f)
|
||||||
|
{
|
||||||
|
normalized_velocity_xy = glm::normalize(movement_basis * velocity_xy);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 velocity = glm::vec3(
|
||||||
|
normalized_velocity_xy * speed,
|
||||||
|
-1.0f // No vertical movement for now
|
||||||
|
);
|
||||||
|
|
||||||
|
velocity_ = velocity;
|
||||||
|
|
||||||
|
Super::Update(dt);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Occurrence could have changed during update !!!!1!1!
|
||||||
|
const glm::mat3& occu_basis = occu_->GetBasis();
|
||||||
|
cam_forward_ = occu_basis * glm::vec3(yaw_sin * pitch_cos, yaw_cos * pitch_cos, pitch_sin);
|
||||||
|
cam_up_ = occu_basis[2]; // Up vector is always the Z axis in sector space
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Player::GetPOV(size_t& sector_idx, glm::vec3& position, glm::vec3& forward, glm::vec3& up) const
|
||||||
|
{
|
||||||
|
sector_idx = occu_->GetSector().GetIndex();
|
||||||
|
position = occu_->GetPosition() + cam_up_ * 0.7f;
|
||||||
|
|
||||||
|
forward = cam_forward_;
|
||||||
|
up = cam_up_;
|
||||||
|
}
|
||||||
36
src/game/player.hpp
Normal file
36
src/game/player.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entity.hpp"
|
||||||
|
#include "player_input.hpp"
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
class Player : public Entity
|
||||||
|
{
|
||||||
|
using Super = Entity;
|
||||||
|
|
||||||
|
float yaw_, pitch_;
|
||||||
|
PlayerInputFlags input_;
|
||||||
|
|
||||||
|
// in occu's sector space
|
||||||
|
glm::vec3 cam_forward_;
|
||||||
|
glm::vec3 cam_up_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Player(World* world, size_t sector_idx, const glm::vec3& position);
|
||||||
|
|
||||||
|
// angles in radians
|
||||||
|
void Rotate(float delta_yaw, float delta_pitch);
|
||||||
|
|
||||||
|
void SetInput(PlayerInputFlags input) { input_ = input; }
|
||||||
|
|
||||||
|
virtual void Update(float dt) override;
|
||||||
|
|
||||||
|
void GetPOV(size_t& sector_idx, glm::vec3& position, glm::vec3& forward, glm::vec3& up) const;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,6 +14,10 @@ game::Sector::Sector(World* world, size_t idx, std::shared_ptr<assets::SectorDef
|
|||||||
bt_col_dispatcher_(&bt_col_cfg_),
|
bt_col_dispatcher_(&bt_col_cfg_),
|
||||||
bt_world_(&bt_col_dispatcher_, &bt_broad_phase_, &bt_col_cfg_)
|
bt_world_(&bt_col_dispatcher_, &bt_broad_phase_, &bt_col_cfg_)
|
||||||
{
|
{
|
||||||
|
// Create Bullet collision mesh
|
||||||
|
bt_mesh_col_obj_.setCollisionShape(mesh_->GetCollisionMesh()->GetShape());
|
||||||
|
bt_world_.addCollisionObject(&bt_mesh_col_obj_);
|
||||||
|
|
||||||
auto def_portals = def_->GetPortals();
|
auto def_portals = def_->GetPortals();
|
||||||
size_t num_portals = def_portals.size();
|
size_t num_portals = def_portals.size();
|
||||||
|
|
||||||
@ -26,7 +30,9 @@ game::Sector::Sector(World* world, size_t idx, std::shared_ptr<assets::SectorDef
|
|||||||
portal.sector = this;
|
portal.sector = this;
|
||||||
portal.def = &assets::PortalDef::portal_defs[def_portal.def_name];
|
portal.def = &assets::PortalDef::portal_defs[def_portal.def_name];
|
||||||
|
|
||||||
glm::mat4 rotation(glm::quat(glm::radians(def_portal.angles)));
|
glm::vec3 angles_rad = glm::radians(def_portal.angles);
|
||||||
|
|
||||||
|
glm::mat4 rotation = glm::mat4((glm::quat(angles_rad)));
|
||||||
glm::mat4 translation = glm::translate(glm::mat4(1.0f), def_portal.origin);
|
glm::mat4 translation = glm::translate(glm::mat4(1.0f), def_portal.origin);
|
||||||
glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(def_portal.scale));
|
glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(def_portal.scale));
|
||||||
|
|
||||||
@ -43,10 +49,26 @@ game::Sector::Sector(World* world, size_t idx, std::shared_ptr<assets::SectorDef
|
|||||||
portal.link = nullptr;
|
portal.link = nullptr;
|
||||||
|
|
||||||
portal_map_[def_portal.name] = i;
|
portal_map_[def_portal.name] = i;
|
||||||
|
|
||||||
|
// create portal collision object
|
||||||
|
portal.bt_col_shape = std::make_unique<btBoxShape>(
|
||||||
|
btVector3(portal.def->size.x * portal.scale * 0.5f, 0.1f, portal.def->size.y * portal.scale * 0.5f)
|
||||||
|
);
|
||||||
|
|
||||||
|
portal.bt_col_obj = std::make_unique<btCollisionObject>();
|
||||||
|
portal.bt_col_obj->setCollisionShape(portal.bt_col_shape.get());
|
||||||
|
|
||||||
|
btQuaternion bt_rotation(angles_rad.x, angles_rad.y, angles_rad.z);
|
||||||
|
btVector3 bt_position(def_portal.origin.x, def_portal.origin.y, def_portal.origin.z);
|
||||||
|
btTransform bt_transform(bt_rotation, bt_position);
|
||||||
|
portal.bt_col_obj->setWorldTransform(bt_transform);
|
||||||
|
|
||||||
|
portal.col_data.type = CO_PORTAL;
|
||||||
|
portal.col_data.portal = &portal;
|
||||||
|
portal.bt_col_obj->setUserPointer(&portal.col_data);
|
||||||
|
|
||||||
|
bt_world_.addCollisionObject(portal.bt_col_obj.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_col_obj_.setCollisionShape(mesh_->GetCollisionMesh()->GetShape());
|
|
||||||
bt_world_.addCollisionObject(&bt_mesh_col_obj_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Sector::ComputePortalVertex(Portal& portal, size_t idx, const glm::vec2& base_vert)
|
void game::Sector::ComputePortalVertex(Portal& portal, size_t idx, const glm::vec2& base_vert)
|
||||||
@ -82,7 +104,7 @@ static void LinkPortal(game::Portal& p1, game::Portal& p2) {
|
|||||||
|
|
||||||
// get rid of scale
|
// get rid of scale
|
||||||
for (size_t i = 0; i < 3 ; i++)
|
for (size_t i = 0; i < 3 ; i++)
|
||||||
p1.tr_orientation[i] = glm::normalize(p1.tr_basis[i]);
|
p1.tr_basis[i] = glm::normalize(p1.tr_basis[i]);
|
||||||
|
|
||||||
p1.tr_scale = p2.scale / p1.scale;
|
p1.tr_scale = p2.scale / p1.scale;
|
||||||
}
|
}
|
||||||
@ -108,18 +130,15 @@ void game::Sector::LinkPortals(Sector& s1, size_t idx1, Sector& s2, size_t idx2)
|
|||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
struct PortalDetectingClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
struct PortalIgnoringClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
||||||
{
|
{
|
||||||
using Super = btCollisionWorld::ClosestConvexResultCallback;
|
using Super = btCollisionWorld::ClosestConvexResultCallback;
|
||||||
|
|
||||||
PortalDetectingClosestConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld) :
|
PortalIgnoringClosestConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld) :
|
||||||
Super(convexFromWorld, convexToWorld)
|
Super(convexFromWorld, convexToWorld)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const Portal* hit_portal = nullptr;
|
|
||||||
float hit_portal_fraction = std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace) override
|
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace) override
|
||||||
{
|
{
|
||||||
void* ptr = convexResult.m_hitCollisionObject->getUserPointer();
|
void* ptr = convexResult.m_hitCollisionObject->getUserPointer();
|
||||||
@ -127,21 +146,13 @@ namespace game
|
|||||||
|
|
||||||
if (data && data->type == CO_PORTAL)
|
if (data && data->type == CO_PORTAL)
|
||||||
{
|
{
|
||||||
if (convexResult.m_hitFraction < hit_portal_fraction)
|
// Ignore portal hits
|
||||||
{
|
return m_closestHitFraction;
|
||||||
hit_portal = data->portal;
|
|
||||||
hit_portal_fraction = convexResult.m_hitFraction;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return Super::addSingleResult(convexResult, normalInWorldSpace);
|
||||||
Super::addSingleResult(convexResult, normalInWorldSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1.0f; // Continue processing other results
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game::Sector::SweepCapsule(
|
bool game::Sector::SweepCapsule(
|
||||||
@ -150,8 +161,7 @@ bool game::Sector::SweepCapsule(
|
|||||||
const glm::vec3& start,
|
const glm::vec3& start,
|
||||||
const glm::vec3& end,
|
const glm::vec3& end,
|
||||||
float& hit_fraction,
|
float& hit_fraction,
|
||||||
glm::vec3& hit_normal,
|
glm::vec3& hit_normal)
|
||||||
const Portal** hit_portal)
|
|
||||||
{
|
{
|
||||||
//const btVector3* bt_start = reinterpret_cast<const btVector3*>(&start);
|
//const btVector3* bt_start = reinterpret_cast<const btVector3*>(&start);
|
||||||
//const btVector3* bt_end = reinterpret_cast<const btVector3*>(&end);
|
//const btVector3* bt_end = reinterpret_cast<const btVector3*>(&end);
|
||||||
@ -168,14 +178,9 @@ bool game::Sector::SweepCapsule(
|
|||||||
btTransform start_transform(bt_basis, bt_start);
|
btTransform start_transform(bt_basis, bt_start);
|
||||||
btTransform end_transform(bt_basis, bt_end);
|
btTransform end_transform(bt_basis, bt_end);
|
||||||
|
|
||||||
PortalDetectingClosestConvexResultCallback result_callback(bt_start, bt_end);
|
PortalIgnoringClosestConvexResultCallback result_callback(bt_start, bt_end);
|
||||||
|
|
||||||
bt_world_.convexSweepTest(&capsule, start_transform, end_transform, result_callback);
|
bt_world_.convexSweepTest(&capsule, start_transform, end_transform, result_callback, 0.0f);
|
||||||
|
|
||||||
if (hit_portal)
|
|
||||||
{
|
|
||||||
*hit_portal = result_callback.hit_portal;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result_callback.hasHit())
|
if (result_callback.hasHit())
|
||||||
{
|
{
|
||||||
@ -191,3 +196,55 @@ bool game::Sector::SweepCapsule(
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
struct PortalContactResultCallback : public btCollisionWorld::ContactResultCallback
|
||||||
|
{
|
||||||
|
const game::Portal* portal = nullptr;
|
||||||
|
|
||||||
|
PortalContactResultCallback()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0,
|
||||||
|
const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) override
|
||||||
|
{
|
||||||
|
void* ptr0 = colObj0Wrap->getCollisionObject()->getUserPointer();
|
||||||
|
void* ptr1 = colObj1Wrap->getCollisionObject()->getUserPointer();
|
||||||
|
void* ptr = ptr0 ? ptr0 : ptr1;
|
||||||
|
CollisionObjectData* data = static_cast<CollisionObjectData*>(ptr);
|
||||||
|
|
||||||
|
if (data && data->type == CO_PORTAL)
|
||||||
|
{
|
||||||
|
// We hit a portal, store it
|
||||||
|
portal = data->portal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f; // No specific action needed for contact results
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const game::Portal* game::Sector::TestPortalContact(btCapsuleShapeZ& capsule, const glm::mat3& basis, const glm::vec3& pos)
|
||||||
|
{
|
||||||
|
btCollisionObject capsule_obj;
|
||||||
|
capsule_obj.setCollisionShape(&capsule);
|
||||||
|
btTransform capsule_transform;
|
||||||
|
|
||||||
|
btVector3 bt_pos(pos.x, pos.y, pos.z);
|
||||||
|
btMatrix3x3 bt_basis(
|
||||||
|
basis[0][0], basis[0][1], basis[0][2],
|
||||||
|
basis[1][0], basis[1][1], basis[1][2],
|
||||||
|
basis[2][0], basis[2][1], basis[2][2]
|
||||||
|
);
|
||||||
|
|
||||||
|
btTransform bt_transform(bt_basis, bt_pos);
|
||||||
|
|
||||||
|
capsule_obj.setWorldTransform(bt_transform);
|
||||||
|
|
||||||
|
PortalContactResultCallback result_callback;
|
||||||
|
bt_world_.contactTest(&capsule_obj, result_callback);
|
||||||
|
|
||||||
|
return result_callback.portal;
|
||||||
|
}
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
|
class World;
|
||||||
class Sector;
|
class Sector;
|
||||||
class Portal;
|
class Portal;
|
||||||
class World;
|
|
||||||
|
|
||||||
enum CollisionObjectType
|
enum CollisionObjectType
|
||||||
{
|
{
|
||||||
@ -41,8 +41,11 @@ namespace game
|
|||||||
|
|
||||||
glm::mat4 tr_position; // this sector space to other sector space
|
glm::mat4 tr_position; // this sector space to other sector space
|
||||||
glm::mat3 tr_basis;
|
glm::mat3 tr_basis;
|
||||||
glm::mat3 tr_orientation;
|
|
||||||
float tr_scale;
|
float tr_scale;
|
||||||
|
|
||||||
|
std::unique_ptr<btCollisionShape> bt_col_shape; // Bullet collision shape
|
||||||
|
std::unique_ptr<btCollisionObject> bt_col_obj; // Bullet collision object
|
||||||
|
CollisionObjectData col_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sector
|
class Sector
|
||||||
@ -56,13 +59,13 @@ namespace game
|
|||||||
std::vector<Portal> portals_;
|
std::vector<Portal> portals_;
|
||||||
std::map<std::string, size_t> portal_map_; // Maps portal name to index in portals_
|
std::map<std::string, size_t> portal_map_; // Maps portal name to index in portals_
|
||||||
|
|
||||||
|
btCollisionObject bt_mesh_col_obj_;
|
||||||
|
|
||||||
btDefaultCollisionConfiguration bt_col_cfg_;
|
btDefaultCollisionConfiguration bt_col_cfg_;
|
||||||
btCollisionDispatcher bt_col_dispatcher_;
|
btCollisionDispatcher bt_col_dispatcher_;
|
||||||
btDbvtBroadphase bt_broad_phase_;
|
btDbvtBroadphase bt_broad_phase_;
|
||||||
btCollisionWorld bt_world_;
|
btCollisionWorld bt_world_;
|
||||||
|
|
||||||
btCollisionObject bt_mesh_col_obj_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sector(World* world, size_t idx, std::shared_ptr<assets::SectorDef> def);
|
Sector(World* world, size_t idx, std::shared_ptr<assets::SectorDef> def);
|
||||||
|
|
||||||
@ -70,6 +73,7 @@ namespace game
|
|||||||
void ComputePortalVertex(Portal& portal, size_t idx, const glm::vec2& base_vert);
|
void ComputePortalVertex(Portal& portal, size_t idx, const glm::vec2& base_vert);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
size_t GetIndex() const { return idx_; }
|
||||||
const std::shared_ptr<assets::Mesh>& GetMesh() const { return mesh_; }
|
const std::shared_ptr<assets::Mesh>& GetMesh() const { return mesh_; }
|
||||||
|
|
||||||
int GetPortalIndex(const std::string& name) const;
|
int GetPortalIndex(const std::string& name) const;
|
||||||
@ -84,8 +88,10 @@ namespace game
|
|||||||
const glm::vec3& start,
|
const glm::vec3& start,
|
||||||
const glm::vec3& end,
|
const glm::vec3& end,
|
||||||
float& hit_fraction,
|
float& hit_fraction,
|
||||||
glm::vec3& hit_normal,
|
glm::vec3& hit_normal);
|
||||||
const Portal** hit_portal);
|
|
||||||
|
const Portal* TestPortalContact(btCapsuleShapeZ& capsule, const glm::mat3& basis, const glm::vec3& pos);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -25,8 +25,10 @@ namespace game
|
|||||||
template<class T, class... TArgs>
|
template<class T, class... TArgs>
|
||||||
T* Spawn(TArgs&&... args)
|
T* Spawn(TArgs&&... args)
|
||||||
{
|
{
|
||||||
auto& entity = entities_.emplace_back(std::make_unique<T>(this, std::forward<TArgs>(args)...));
|
auto entity = std::make_unique<T>(this, std::forward<TArgs>(args)...);
|
||||||
return entity.get();
|
T* entity_ptr = entity.get();
|
||||||
|
entities_.push_back(std::move(entity));
|
||||||
|
return entity_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sector& GetSector(size_t idx) { return *sectors_[idx]; }
|
Sector& GetSector(size_t idx) { return *sectors_[idx]; }
|
||||||
|
|||||||
@ -45,11 +45,14 @@ void gfx::Renderer::DrawWorld(
|
|||||||
float aspect,
|
float aspect,
|
||||||
float fov)
|
float fov)
|
||||||
{
|
{
|
||||||
|
float near_plane = 0.001f; // Near plane distance
|
||||||
|
float far_plane = 500.0f; // Far plane distance
|
||||||
|
|
||||||
proj_ = glm::perspective(
|
proj_ = glm::perspective(
|
||||||
glm::radians(fov), // FOV
|
glm::radians(fov), // FOV
|
||||||
aspect, // Aspect ratio
|
aspect, // Aspect ratio
|
||||||
0.01f, // Near plane
|
near_plane, // Near plane
|
||||||
1000.0f // Far plane
|
far_plane // Far plane
|
||||||
);
|
);
|
||||||
|
|
||||||
glm::mat4 view = glm::lookAt(
|
glm::mat4 view = glm::lookAt(
|
||||||
@ -58,6 +61,8 @@ void gfx::Renderer::DrawWorld(
|
|||||||
up // Up vector
|
up // Up vector
|
||||||
);
|
);
|
||||||
|
|
||||||
|
min_portal_distance_ = near_plane * 2.0f;
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
@ -166,25 +171,39 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta
|
|||||||
return; // Portal AABB does not intersect with the screen AABB, skip
|
return; // Portal AABB does not intersect with the screen AABB, skip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const game::Portal& other_portal = *portal.link;
|
||||||
|
const game::Sector& other_sector = *other_portal.sector;
|
||||||
|
|
||||||
|
glm::mat4 portal_mesh_trans = portal.trans;
|
||||||
|
glm::vec4 new_clip_plane = other_portal.plane;
|
||||||
|
|
||||||
|
if (eye_plane_sd < min_portal_distance_)
|
||||||
|
{
|
||||||
|
float how_much_shift = min_portal_distance_ - eye_plane_sd;
|
||||||
|
|
||||||
|
portal_mesh_trans = glm::translate(portal_mesh_trans,
|
||||||
|
glm::vec3(0.0f, how_much_shift, 0.0f)); // Shift portal mesh to avoid clipping
|
||||||
|
|
||||||
|
new_clip_plane.w += how_much_shift; // Shift the clip plane as well
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Open portal
|
// Open portal
|
||||||
glStencilFunc(GL_EQUAL, params.recursion, 0xFF);
|
glStencilFunc(GL_EQUAL, params.recursion, 0xFF);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
DrawPortalPlane(params, portal, false); // Mark the portal plane in stencil buffer
|
DrawPortalPlane(params, portal, portal_mesh_trans, false); // Mark the portal plane in stencil buffer
|
||||||
glStencilFunc(GL_EQUAL, params.recursion + 1, 0xFF);
|
glStencilFunc(GL_EQUAL, params.recursion + 1, 0xFF);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
glDepthFunc(GL_ALWAYS);
|
glDepthFunc(GL_ALWAYS);
|
||||||
DrawPortalPlane(params, portal, true); // Clear the depth buffer for nested sector
|
DrawPortalPlane(params, portal, portal_mesh_trans, true); // Clear the depth buffer for nested sector
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
const game::Portal& other_portal = *portal.link;
|
|
||||||
const game::Sector& other_sector = *other_portal.sector;
|
|
||||||
|
|
||||||
DrawSectorParams new_params;
|
DrawSectorParams new_params;
|
||||||
new_params.sector = &other_sector;
|
new_params.sector = &other_sector;
|
||||||
new_params.entry_portal = &other_portal;
|
new_params.entry_portal = &other_portal;
|
||||||
new_params.clip_plane = other_portal.plane; // Use the portal plane as the clip plane
|
new_params.clip_plane = new_clip_plane; // Use the portal plane as the clip plane
|
||||||
|
|
||||||
// Compute the new screen AABB based on the portal AABB and the current screen AABB
|
// Compute the new screen AABB based on the portal AABB and the current screen AABB
|
||||||
new_params.screen_aabb = params.screen_aabb.Intersection(portal_aabb);
|
new_params.screen_aabb = params.screen_aabb.Intersection(portal_aabb);
|
||||||
@ -201,7 +220,7 @@ void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Porta
|
|||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
glStencilFunc(GL_EQUAL, params.recursion + 1, 0xFF);
|
glStencilFunc(GL_EQUAL, params.recursion + 1, 0xFF);
|
||||||
DrawPortalPlane(params, portal, false);
|
DrawPortalPlane(params, portal, portal_mesh_trans, false);
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,13 +259,13 @@ bool gfx::Renderer::ComputePortalScreenAABB(const game::Portal& portal, const gl
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::Renderer::DrawPortalPlane(const DrawSectorParams& params, const game::Portal& portal, bool clear_depth)
|
void gfx::Renderer::DrawPortalPlane(const DrawSectorParams& params, const game::Portal& portal, const glm::mat4& trans, bool clear_depth)
|
||||||
{
|
{
|
||||||
if (!clear_depth) // first draw
|
if (!clear_depth) // first draw
|
||||||
{
|
{
|
||||||
glUseProgram(portal_shader_->GetId());
|
glUseProgram(portal_shader_->GetId());
|
||||||
glUniformMatrix4fv(portal_shader_->U(gfx::SU_VIEW_PROJ), 1, GL_FALSE, ¶ms.view_proj[0][0]);
|
glUniformMatrix4fv(portal_shader_->U(gfx::SU_VIEW_PROJ), 1, GL_FALSE, ¶ms.view_proj[0][0]);
|
||||||
glUniformMatrix4fv(portal_shader_->U(gfx::SU_MODEL), 1, GL_FALSE, &portal.trans[0][0]);
|
glUniformMatrix4fv(portal_shader_->U(gfx::SU_MODEL), 1, GL_FALSE, &trans[0][0]);
|
||||||
glUniform4fv(portal_shader_->U(gfx::SU_CLIP_PLANE), 1, ¶ms.clip_plane[0]);
|
glUniform4fv(portal_shader_->U(gfx::SU_CLIP_PLANE), 1, ¶ms.clip_plane[0]);
|
||||||
glUniform2fv(portal_shader_->U(gfx::SU_PORTAL_SIZE), 1, &portal.def->size[0]);
|
glUniform2fv(portal_shader_->U(gfx::SU_PORTAL_SIZE), 1, &portal.def->size[0]);
|
||||||
glUniform1i(portal_shader_->U(gfx::SU_CLEAR_DEPTH), 0);
|
glUniform1i(portal_shader_->U(gfx::SU_CLEAR_DEPTH), 0);
|
||||||
|
|||||||
@ -44,13 +44,17 @@ namespace gfx
|
|||||||
|
|
||||||
size_t max_portal_recursion_ = 24;
|
size_t max_portal_recursion_ = 24;
|
||||||
|
|
||||||
|
// Minimum distance to portal mesh from eye
|
||||||
|
// If the distance is smaller, portal plane is shifted to avoid clipping by near plane
|
||||||
|
float min_portal_distance_ = 0.01f;
|
||||||
|
|
||||||
glm::mat4 proj_;
|
glm::mat4 proj_;
|
||||||
|
|
||||||
void DrawSector(const DrawSectorParams& params);
|
void DrawSector(const DrawSectorParams& params);
|
||||||
void DrawPortal(const DrawSectorParams& params, const game::Portal& portal);
|
void DrawPortal(const DrawSectorParams& params, const game::Portal& portal);
|
||||||
|
|
||||||
static bool ComputePortalScreenAABB(const game::Portal& portal, const glm::mat4 view_proj, collision::AABB2& aabb);
|
static bool ComputePortalScreenAABB(const game::Portal& portal, const glm::mat4 view_proj, collision::AABB2& aabb);
|
||||||
void DrawPortalPlane(const DrawSectorParams& params, const game::Portal& portal, bool clear_depth);
|
void DrawPortalPlane(const DrawSectorParams& params, const game::Portal& portal, const glm::mat4& trans, bool clear_depth);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user