Browse Source

Add ping method to signal class. Remove some obsolete systems

master
C. J. Howard 1 year ago
parent
commit
870ccc2030
13 changed files with 110 additions and 596 deletions
  1. +2
    -0
      src/application.cpp
  2. +10
    -1
      src/application.hpp
  3. +70
    -22
      src/event/signal.hpp
  4. +2
    -2
      src/game/context.hpp
  5. +0
    -36
      src/game/events/tool-events.cpp
  6. +0
    -43
      src/game/events/tool-events.hpp
  7. +16
    -6
      src/game/state/boot.cpp
  8. +0
    -13
      src/game/state/main-menu.cpp
  9. +0
    -372
      src/game/system/painting.cpp
  10. +0
    -94
      src/game/system/painting.hpp
  11. +6
    -3
      src/gl/rasterizer.cpp
  12. +3
    -3
      src/gl/shader-stage.hpp
  13. +1
    -1
      src/render/stage/culling-stage.cpp

+ 2
- 0
src/application.cpp View File

@ -482,6 +482,7 @@ void application::process_events()
logger->log("Reconnected gamepad \"" + controller_name + "\""); logger->log("Reconnected gamepad \"" + controller_name + "\"");
it->second->connect(true); it->second->connect(true);
gamepad_connection_signal.emit(*it->second, true);
} }
else else
{ {
@ -506,6 +507,7 @@ void application::process_events()
// Send controller connected event // Send controller connected event
gamepad->connect(false); gamepad->connect(false);
gamepad_connection_signal.emit(*it->second, false);
} }
} }
else else

+ 10
- 1
src/application.hpp View File

@ -151,6 +151,9 @@ public:
bool was_closed() const; bool was_closed() const;
/// Returns a connector for the signal emitted when a gamepad is connected or disconnected.
connector<void(input::gamepad&, bool)>& get_gamepad_connection_signal() noexcept;
/// Returns a connector for the signal emitted when the window is requested to close. /// Returns a connector for the signal emitted when the window is requested to close.
connector<void()>& get_window_close_signal() noexcept; connector<void()>& get_window_close_signal() noexcept;
@ -165,7 +168,7 @@ public:
/// Returns a connector for the signal emitted each time the window viewport is resized. /// Returns a connector for the signal emitted each time the window viewport is resized.
connector<void(int, int)>& get_viewport_size_signal() noexcept; connector<void(int, int)>& get_viewport_size_signal() noexcept;
private: private:
void window_resized(); void window_resized();
@ -194,6 +197,7 @@ private:
std::list<input::gamepad*> gamepads; std::list<input::gamepad*> gamepads;
std::unordered_map<int, input::gamepad*> gamepad_map; std::unordered_map<int, input::gamepad*> gamepad_map;
signal<void(input::gamepad&, bool)> gamepad_connection_signal;
signal<void()> window_close_signal; signal<void()> window_close_signal;
signal<void(bool)> window_focus_signal; signal<void(bool)> window_focus_signal;
signal<void(int, int)> window_motion_signal; signal<void(int, int)> window_motion_signal;
@ -266,6 +270,11 @@ inline bool application::was_closed() const
return closed; return closed;
} }
inline connector<void(input::gamepad&, bool)>& application::get_gamepad_connection_signal() noexcept
{
return gamepad_connection_signal.connector();
}
inline connector<void()>& application::get_window_close_signal() noexcept inline connector<void()>& application::get_window_close_signal() noexcept
{ {
return window_close_signal.connector(); return window_close_signal.connector();

+ 70
- 22
src/event/signal.hpp View File

@ -25,9 +25,16 @@
#include <functional> #include <functional>
#include <list> #include <list>
#include <memory> #include <memory>
#include <type_traits>
//namespace event { //namespace event {
template <class T>
class signal;
template <class T>
class connector;
/** /**
* Manages a connection between a signal and handler. A signal will be disconnected from a handler when the connection is destructed or is disconnected manually via connection::disconnect(). * Manages a connection between a signal and handler. A signal will be disconnected from a handler when the connection is destructed or is disconnected manually via connection::disconnect().
*/ */
@ -61,26 +68,26 @@ public:
void disconnect(); void disconnect();
private: private:
template <class T>
friend class signal;
std::weak_ptr<void> handler; std::weak_ptr<void> handler;
disconnector_type disconnector; disconnector_type disconnector;
}; };
template<class T>
class signal;
template<class T>
class connector;
/** /**
* Creates connections between a signal and signal handlers. * Creates connections between a signal and signal handlers.
* *
* @tparam T Signal handler return type.
* @tparam Args Signal handler argument types.
* @tparam T Signal response type.
* @tparam Args Signal argument types.
*/ */
template <class T, class... Args> template <class T, class... Args>
class connector<T(Args...)> class connector<T(Args...)>
{ {
public: public:
/// Signal response type.
typedef T response_type;
/// Signal type. /// Signal type.
typedef signal<T(Args...)> signal_type; typedef signal<T(Args...)> signal_type;
@ -104,15 +111,18 @@ private:
}; };
/** /**
* Emits signals to connected handlers.
* Emits signals to signal handlers.
* *
* @tparam T Signal handler return type.
* @tparam Args Signal handler argument types.
* @tparam T Signal response type.
* @tparam Args Signal argument types.
*/ */
template <class T, class... Args> template <class T, class... Args>
class signal<T(Args...)> class signal<T(Args...)>
{ {
public: public:
/// Signal response type.
typedef T response_type;
/// Signal handler type. /// Signal handler type.
typedef std::function<T(Args...)> handler_type; typedef std::function<T(Args...)> handler_type;
@ -147,7 +157,7 @@ public:
std::shared_ptr<handler_type> shared_handler = std::make_shared<handler_type>(handler); std::shared_ptr<handler_type> shared_handler = std::make_shared<handler_type>(handler);
// Add handler to list of connected handlers // Add handler to list of connected handlers
handlers.push_back(shared_handler);
connections.push_back(shared_handler);
// Return a shared pointer to the connection between the signal and handler // Return a shared pointer to the connection between the signal and handler
return std::make_shared<connection> return std::make_shared<connection>
@ -155,7 +165,7 @@ public:
std::static_pointer_cast<void>(shared_handler), std::static_pointer_cast<void>(shared_handler),
[this](std::weak_ptr<void> handler) [this](std::weak_ptr<void> handler)
{ {
this->handlers.remove(std::static_pointer_cast<handler_type>(handler.lock()));
this->connections.remove(std::static_pointer_cast<handler_type>(handler.lock()));
} }
); );
} }
@ -165,7 +175,7 @@ public:
*/ */
void disconnect() void disconnect()
{ {
handlers.clear();
connections.clear();
} }
/** /**
@ -176,14 +186,15 @@ public:
* @param policy Execution policy to use. * @param policy Execution policy to use.
* @param args Signal arguments. * @param args Signal arguments.
*/ */
/// @{
template <class ExecutionPolicy> template <class ExecutionPolicy>
void emit(ExecutionPolicy&& policy, Args... args) const void emit(ExecutionPolicy&& policy, Args... args) const
{ {
std::for_each std::for_each
( (
policy, policy,
std::begin(handlers),
std::end(handlers),
std::begin(connections),
std::end(connections),
[&](const auto& handler) [&](const auto& handler)
{ {
(*handler)(args...); (*handler)(args...);
@ -191,22 +202,59 @@ public:
); );
} }
void emit(Args... args) const
{
emit(std::execution::seq, args...);
}
/// @}
/** /**
* Emits a signal to all connected handlers.
* Emits a signal to all connected handlers and relays their responses to a listener.
*
* @tparam ExecutionPolicy Execution policy type.
* @tparam UnaryFunction Listener function object type.
* *
* @param policy Execution policy to use.
* @param listener Listener function object.
* @param args Signal arguments. * @param args Signal arguments.
*/ */
void emit(Args... args) const
/// @{
template <class ExecutionPolicy, class UnaryFunction>
void ping(ExecutionPolicy&& policy, UnaryFunction listener, Args... args) const
{ {
emit(std::execution::seq, args...);
std::for_each
(
policy,
std::begin(connections),
std::end(connections),
[&](const auto& handler)
{
if constexpr(std::is_void_v<T>)
{
(*handler)(args...);
listener();
}
else
{
listener((*handler)(args...));
}
}
);
}
template <class UnaryFunction>
void ping(UnaryFunction listener, Args... args) const
{
ping(std::execution::seq, listener, args...);
} }
/// @}
private: private:
/// List of connected signal handlers.
std::list<std::shared_ptr<handler_type>> connections;
/// Signal connector. /// Signal connector.
connector_type signal_connector; connector_type signal_connector;
/// List of connected signal handlers.
std::list<std::shared_ptr<handler_type>> handlers;
}; };
//} // namespace event //} // namespace event

+ 2
- 2
src/game/context.hpp View File

@ -86,7 +86,6 @@ namespace game
class terrain; class terrain;
class vegetation; class vegetation;
class spatial; class spatial;
class painting;
class astronomy; class astronomy;
class blackbody; class blackbody;
class atmosphere; class atmosphere;
@ -296,7 +295,6 @@ struct context
game::system::vegetation* vegetation_system; game::system::vegetation* vegetation_system;
game::system::spring* spring_system; game::system::spring* spring_system;
game::system::spatial* spatial_system; game::system::spatial* spatial_system;
game::system::painting* painting_system;
game::system::blackbody* blackbody_system; game::system::blackbody* blackbody_system;
game::system::atmosphere* atmosphere_system; game::system::atmosphere* atmosphere_system;
game::system::astronomy* astronomy_system; game::system::astronomy* astronomy_system;
@ -308,6 +306,8 @@ struct context
bool bloom_enabled; bool bloom_enabled;
render::anti_aliasing_method anti_aliasing_method; render::anti_aliasing_method anti_aliasing_method;
std::shared_ptr<connection> ui_resize_connection;
}; };
} // namespace game } // namespace game

+ 0
- 36
src/game/events/tool-events.cpp View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "game/events/tool-events.hpp"
event_base* tool_pressed_event::clone() const
{
tool_pressed_event* event = new tool_pressed_event();
event->entity_id = entity_id;
event->position = position;
return event;
}
event_base* tool_released_event::clone() const
{
tool_released_event* event = new tool_released_event();
event->entity_id = entity_id;
event->position = position;
return event;
}

+ 0
- 43
src/game/events/tool-events.hpp View File

@ -1,43 +0,0 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_TOOL_EVENTS_HPP
#define ANTKEEPER_TOOL_EVENTS_HPP
#include "event/event.hpp"
#include "utility/fundamental-types.hpp"
#include "entity/id.hpp"
class tool_pressed_event: public event<tool_pressed_event>
{
public:
virtual event_base* clone() const;
entity::id entity_id;
float3 position;
};
class tool_released_event: public event<tool_released_event>
{
public:
virtual event_base* clone() const;
entity::id entity_id;
float3 position;
};
#endif // ANTKEEPER_TOOL_EVENTS_HPP

+ 16
- 6
src/game/state/boot.cpp View File

@ -67,7 +67,6 @@
#include "game/system/terrain.hpp" #include "game/system/terrain.hpp"
#include "game/system/vegetation.hpp" #include "game/system/vegetation.hpp"
#include "game/system/spatial.hpp" #include "game/system/spatial.hpp"
#include "game/system/painting.hpp"
#include "game/system/astronomy.hpp" #include "game/system/astronomy.hpp"
#include "game/system/blackbody.hpp" #include "game/system/blackbody.hpp"
#include "game/system/atmosphere.hpp" #include "game/system/atmosphere.hpp"
@ -985,10 +984,6 @@ void boot::setup_systems()
// Setup constraint system // Setup constraint system
ctx.constraint_system = new game::system::constraint(*ctx.entity_registry); ctx.constraint_system = new game::system::constraint(*ctx.entity_registry);
// Setup painting system
ctx.painting_system = new game::system::painting(*ctx.entity_registry, event_dispatcher, ctx.resource_manager);
ctx.painting_system->set_scene(ctx.surface_scene);
// Setup orbit system // Setup orbit system
ctx.orbit_system = new game::system::orbit(*ctx.entity_registry); ctx.orbit_system = new game::system::orbit(*ctx.entity_registry);
@ -1154,6 +1149,22 @@ void boot::setup_ui()
} }
ctx.logger->pop_task(EXIT_SUCCESS); ctx.logger->pop_task(EXIT_SUCCESS);
// Setup UI resize handler
ctx.ui_resize_connection = ctx.app->get_window_size_signal().connect
(
[&](int w, int h)
{
const float clip_left = static_cast<float>(w) * -0.5f;
const float clip_right = static_cast<float>(w) * 0.5f;
const float clip_top = static_cast<float>(h) * -0.5f;
const float clip_bottom = static_cast<float>(h) * 0.5f;
const float clip_near = ctx.ui_camera->get_clip_near();
const float clip_far = ctx.ui_camera->get_clip_far();
ctx.ui_camera->set_orthographic(clip_left, clip_right, clip_top, clip_bottom, clip_near, clip_far);
}
);
// Construct mouse tracker // Construct mouse tracker
ctx.menu_mouse_tracker = new ui::mouse_tracker(); ctx.menu_mouse_tracker = new ui::mouse_tracker();
ctx.app->get_event_dispatcher()->subscribe<mouse_moved_event>(ctx.menu_mouse_tracker); ctx.app->get_event_dispatcher()->subscribe<mouse_moved_event>(ctx.menu_mouse_tracker);
@ -1242,7 +1253,6 @@ void boot::setup_loop()
ctx.spring_system->update(t, dt); ctx.spring_system->update(t, dt);
ctx.spatial_system->update(t, dt); ctx.spatial_system->update(t, dt);
ctx.constraint_system->update(t, dt); ctx.constraint_system->update(t, dt);
ctx.painting_system->update(t, dt);
ctx.animator->animate(dt); ctx.animator->animate(dt);
ctx.render_system->update(t, dt); ctx.render_system->update(t, dt);
} }

+ 0
- 13
src/game/state/main-menu.cpp View File

@ -55,19 +55,6 @@ main_menu::main_menu(game::context& ctx, bool fade_in):
{ {
ctx.logger->push_task("Entering main menu state"); ctx.logger->push_task("Entering main menu state");
auto listener1 = [](int x, int y)
{
std::cout << "listener1 received " << x << std::endl;
};
auto listener2 = [](int x, int y)
{
std::cout << "listener2 received " << x << std::endl;
};
auto listener3 = [](int x, int y)
{
std::cout << "listener3 received " << x << std::endl;
};
viewport_size_connection = ctx.app->get_viewport_size_signal().connect viewport_size_connection = ctx.app->get_viewport_size_signal().connect
( (
[](int w, int h) [](int w, int h)

+ 0
- 372
src/game/system/painting.cpp View File

@ -1,372 +0,0 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "painting.hpp"
#include "game/component/transform.hpp"
#include "game/component/brush.hpp"
#include "game/component/tool.hpp"
#include "event/event-dispatcher.hpp"
#include "resources/resource-manager.hpp"
#include "render/material.hpp"
#include "render/model.hpp"
#include "utility/fundamental-types.hpp"
#include "entity/commands.hpp"
#include "game/component/collision.hpp"
#include "game/component/transform.hpp"
#include "gl/vertex-buffer.hpp"
#include "render/vertex-attribute.hpp"
#include "geom/mesh-functions.hpp"
#include <limits>
namespace game {
namespace system {
painting::painting(entity::registry& registry, ::event_dispatcher* event_dispatcher, ::resource_manager* resource_manager):
updatable(registry),
event_dispatcher(event_dispatcher),
resource_manager(resource_manager),
scene_collection(nullptr),
is_painting(false)
{
/*
event_dispatcher->subscribe<tool_pressed_event>(this);
event_dispatcher->subscribe<tool_released_event>(this);
max_miter_angle = math::radians(135.0f);
decal_offset = 0.01f;
stroke_width = 1.5f;
min_stroke_length = 1.0f;
min_stroke_length_squared = min_stroke_length * min_stroke_length;
max_stroke_segments = 4096;
current_stroke_segment = 0;
vertex_size = 13;
vertex_stride = sizeof(float) * vertex_size;
vertex_count = max_stroke_segments * 6;
// Create stroke model
stroke_model = new model();
stroke_model_group = stroke_model->add_group();
stroke_model_group->set_material(resource_manager->load<material>("brushstroke.mtl"));
// Setup stroke vbo and vao
stroke_vbo = stroke_model->get_vertex_buffer();
stroke_vbo->repurpose(gl::buffer_usage::dynamic_draw, sizeof(float) * vertex_size * vertex_count, nullptr);
stroke_model->get_vertex_array()->bind_attribute(VERTEX_POSITION_LOCATION, *stroke_vbo, 4, gl::vertex_attribute_type::float_32, vertex_stride, 0);
stroke_model->get_vertex_array()->bind_attribute(VERTEX_NORMAL_LOCATION, *stroke_vbo, 3, gl::vertex_attribute_type::float_32, vertex_stride, sizeof(float) * 4);
stroke_model->get_vertex_array()->bind_attribute(VERTEX_TEXCOORD_LOCATION, *stroke_vbo, 2, gl::vertex_attribute_type::float_32, vertex_stride, sizeof(float) * 7);
stroke_model->get_vertex_array()->bind_attribute(VERTEX_TANGENT_LOCATION, *stroke_vbo, 4, gl::vertex_attribute_type::float_32, vertex_stride, sizeof(float) * 9);
// Create stroke model instance
stroke_model_instance = new scene::model_instance();
stroke_model_instance->set_model(stroke_model);
stroke_model_instance->update_tweens();
stroke_bounds_min.x() = std::numeric_limits<float>::infinity();
stroke_bounds_min.y() = std::numeric_limits<float>::infinity();
stroke_bounds_min.z() = std::numeric_limits<float>::infinity();
stroke_bounds_max.x() = -std::numeric_limits<float>::infinity();
stroke_bounds_max.y() = -std::numeric_limits<float>::infinity();
stroke_bounds_max.z() = -std::numeric_limits<float>::infinity();
midstroke = false;
*/
}
painting::~painting()
{
/*
event_dispatcher->unsubscribe<tool_pressed_event>(this);
event_dispatcher->unsubscribe<tool_released_event>(this);
*/
}
void painting::update(double t, double dt)
{
/*
if (is_painting)
{
const component::tool& tool = registry.get<component::tool>(brush_entity);
auto cast_result = cast_ray(tool.cursor);
if (cast_result.has_value())
{
stroke_end = std::get<0>(cast_result.value());
float3 surface_normal = std::get<1>(cast_result.value());
float3 segment_difference = stroke_end - stroke_start;
float segment_length_squared = math::dot(segment_difference, segment_difference);
if (segment_length_squared >= min_stroke_length_squared)
{
float segment_length = std::sqrt(segment_length_squared);
float3 segment_forward = segment_difference / segment_length;
float3 segment_right = math::normalize(math::cross(segment_forward, surface_normal));
float3 segment_up = math::cross(segment_right, segment_forward);
float angle = std::acos(math::dot(segment_forward, float3{0, 0, -1}));
float3 cross = math::cross(segment_forward, float3{0, 0, -1});
if (math::dot(surface_normal, cross) < 0.0f)
angle = -angle;
math::quaternion<float> tangent_rotation = math::normalize(math::angle_axis(-angle, surface_normal));
float3 p1 = stroke_start;
float3 p2 = stroke_end;
// Find miter
float3 tangent = math::normalize(math::normalize(p2 - p1) + math::normalize(p1 - p0));
float2 miter = float2{-tangent.z(), tangent.x()};
float2 normal = float2{segment_right.x(), segment_right.z()};
float miter_length = stroke_width / math::dot(miter, normal);
float3 a = p0a;
float3 b = p0b;
float3 c = p1 - segment_right * stroke_width * 0.5f + segment_up * decal_offset;
float3 d = p1 + segment_right * stroke_width * 0.5f + segment_up * decal_offset;
float3 e = p2 - segment_right * stroke_width * 0.5f + segment_up * decal_offset;
float3 f = p2 + segment_right * stroke_width * 0.5f + segment_up * decal_offset;
// Adjust c and d
bool mitered = false;
if (midstroke)
{
float angle = std::acos(math::dot(math::normalize(p2 - p1), math::normalize(p1 - p0)));
if (angle < max_miter_angle)
{
mitered = true;
c = p1 - float3{miter.x(), 0.0f, miter.y()} * miter_length * 0.5f + segment_up * decal_offset;
d = p1 + float3{miter.x(), 0.0f, miter.y()} * miter_length * 0.5f + segment_up * decal_offset;
}
}
const float3 positions[] =
{
a, b, c,
c, b, d,
c, d, e,
e, d, f
};
const float w = static_cast<float>(t);
float2 texcoords[] =
{
{0, 0}, {1, 0}, {0, 1},
{0, 1}, {1, 0}, {1, 1},
{0, 0}, {1, 0}, {0, 1},
{0, 1}, {1, 0}, {1, 1},
};
float3 tangent_positions[] =
{
{0, 0, 0}, {1, 0, 0}, {0, 0, 1},
{0, 0, 1}, {1, 0, 0}, {1, 0, 1},
{0, 0, 0}, {1, 0, 0}, {0, 0, 1},
{0, 0, 1}, {1, 0, 0}, {1, 0, 1}
};
/// @TODO: smooth normals in middle of segment
float4 tangents[12];
for (int i = 0; i < 4; ++i)
{
const float3& a = tangent_positions[i * 3];
const float3& b = tangent_positions[i * 3 + 1];
const float3& c = tangent_positions[i * 3 + 2];
const float2& uva = texcoords[i * 3];
const float2& uvb = texcoords[i * 3 + 1];
const float2& uvc = texcoords[i * 3 + 2];
float3 ba = b - a;
float3 ca = c - a;
float2 uvba = uvb - uva;
float2 uvca = uvc - uva;
float f = 1.0f / (uvba.x() * uvca.y() - uvca.x() * uvba.y());
float3 tangent = math::normalize((ba * uvca.y() - ca * uvba.y()) * f);
float3 bitangent = math::normalize((ba * -uvca.x() + ca * uvba.x()) * f);
// Rotate tangent and bitangent according to segment rotation
tangent = math::normalize(tangent_rotation * tangent);
bitangent = math::normalize(tangent_rotation * bitangent);
// Calculate sign of bitangent
float bitangent_sign = (math::dot(math::cross(surface_normal, tangent), bitangent) < 0.0f) ? -1.0f : 1.0f;
tangents[i * 3] = {tangent.x(), tangent.y(), tangent.z(), bitangent_sign};
tangents[i * 3 + 1] = {tangent.x(), tangent.y(), tangent.z(), bitangent_sign};
tangents[i * 3 + 2] = {tangent.x(), tangent.y(), tangent.z(), bitangent_sign};
}
float vertex_data[13 * 12];
float* v = &vertex_data[0];
for (int i = 0; i < 12; ++i)
{
*(v++) = positions[i].x();
*(v++) = positions[i].y();
*(v++) = positions[i].z();
*(v++) = w;
*(v++) = surface_normal.x();
*(v++) = surface_normal.y();
*(v++) = surface_normal.z();
*(v++) = texcoords[i].x();
*(v++) = texcoords[i].y();
*(v++) = tangents[i].x();
*(v++) = tangents[i].y();
*(v++) = tangents[i].z();
*(v++) = tangents[i].w;
}
std::size_t segment_size = sizeof(float) * vertex_size * 6;
if (mitered)
{
stroke_vbo->update((current_stroke_segment - 1) * segment_size, segment_size * 2, &vertex_data[0]);
}
else
{
stroke_vbo->update(current_stroke_segment * segment_size, segment_size, &vertex_data[vertex_size * 6]);
}
++current_stroke_segment;
stroke_model_group->set_index_count(current_stroke_segment * 6);
// Update stroke bounds
stroke_bounds_min.x() = std::min<float>(stroke_bounds_min.x(), std::min<float>(c.x(), std::min<float>(d.x(), std::min<float>(e.x(), f.x()))));
stroke_bounds_min.y() = std::min<float>(stroke_bounds_min.y(), std::min<float>(c.y(), std::min<float>(d.y(), std::min<float>(e.y(), f.y()))));
stroke_bounds_min.z() = std::min<float>(stroke_bounds_min.z(), std::min<float>(c.z(), std::min<float>(d.z(), std::min<float>(e.z(), f.z()))));
stroke_bounds_max.x() = std::max<float>(stroke_bounds_max.x(), std::max<float>(c.x(), std::max<float>(d.x(), std::max<float>(e.x(), f.x()))));
stroke_bounds_max.y() = std::max<float>(stroke_bounds_max.y(), std::max<float>(c.y(), std::max<float>(d.y(), std::max<float>(e.y(), f.y()))));
stroke_bounds_max.z() = std::max<float>(stroke_bounds_max.z(), std::max<float>(c.z(), std::max<float>(d.z(), std::max<float>(e.z(), f.z()))));
stroke_model->set_bounds(geom::aabb<float>{stroke_bounds_min, stroke_bounds_max});
stroke_model_instance->update_bounds();
p0 = stroke_start;
p0a = c;
p0b = d;
stroke_start = stroke_end;
midstroke = true;
}
}
}
*/
}
void painting::set_scene(scene::collection* collection)
{
/*
this->scene_collection = collection;
scene_collection->add_object(stroke_model_instance);
*/
}
void painting::handle_event(const tool_pressed_event& event)
{
/*
if (registry.has<component::brush>(event.entity_id))
{
auto cast_result = cast_ray(event.position);
if (cast_result.has_value())
{
brush_entity = event.entity_id;
is_painting = true;
stroke_start = std::get<0>(cast_result.value());
stroke_end = stroke_start;
p0 = stroke_start;
p0a = p0;
p0b = p0;
midstroke = false;
}
}
*/
}
void painting::handle_event(const tool_released_event& event)
{
/*
if (registry.has<component::brush>(event.entity_id))
{
auto cast_result = cast_ray(command::get_world_transform(registry, event.entity_id).translation);
if (cast_result.has_value())
{
stroke_end = std::get<0>(cast_result.value());
}
brush_entity = entt::null;
is_painting = false;
}
*/
}
std::optional<std::tuple<float3, float3>> painting::cast_ray(const float3& position) const
{
std::optional<std::tuple<float3, float3>> result;
/*
float3 intersection;
float3 surface_normal;
geom::mesh::face* face = nullptr;
geom::ray<float> untransformed_ray = {position + float3{0.0f, 10000.0f, 0.0f}, {0, -1, 0}};
float min_distance = std::numeric_limits<float>::infinity();
registry.view<component::transform, component::collision>().each(
[&](entity::id entity_id, auto& collision_transform, auto& collision)
{
// Transform ray into local space of collision component
math::transform<float> inverse_transform = math::inverse(collision_transform.local);
float3 origin = inverse_transform * untransformed_ray.origin;
float3 direction = math::normalize(math::conjugate(collision_transform.local.rotation) * untransformed_ray.direction);
geom::ray<float> transformed_ray = {origin, direction};
// Broad phase AABB test
auto aabb_result = geom::ray_aabb_intersection(transformed_ray, collision.bounds);
if (!std::get<0>(aabb_result))
{
return;
}
// Narrow phase mesh test
auto mesh_result = collision.mesh_accelerator.query_nearest(transformed_ray);
if (mesh_result)
{
if (mesh_result->t < min_distance)
{
min_distance = mesh_result->t;
intersection = untransformed_ray.extrapolate(min_distance);
face = mesh_result->face;
}
}
});
if (face != nullptr)
{
surface_normal = calculate_face_normal(*face);
result = std::make_tuple(intersection, surface_normal);
}
*/
return result;
}
} // namespace system
} // namespace game

+ 0
- 94
src/game/system/painting.hpp View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_SYSTEM_PAINTING_HPP
#define ANTKEEPER_GAME_SYSTEM_PAINTING_HPP
#include "game/system/updatable.hpp"
#include "entity/id.hpp"
#include "event/event-handler.hpp"
#include "game/events/tool-events.hpp"
#include "utility/fundamental-types.hpp"
#include "scene/collection.hpp"
#include "scene/model-instance.hpp"
#include "gl/vertex-buffer.hpp"
#include "render/model.hpp"
#include <vector>
#include <optional>
class event_dispatcher;
class resource_manager;
namespace game {
namespace system {
class painting: public updatable,
public event_handler<tool_pressed_event>,
public event_handler<tool_released_event>
{
public:
painting(entity::registry& registry, event_dispatcher* event_dispatcher, resource_manager* resource_manager);
virtual ~painting();
virtual void update(double t, double dt);
void set_scene(scene::collection* collection);
private:
virtual void handle_event(const tool_pressed_event& event);
virtual void handle_event(const tool_released_event& event);
std::optional<std::tuple<float3, float3>> cast_ray(const float3& position) const;
event_dispatcher* event_dispatcher;
resource_manager* resource_manager;
scene::collection* scene_collection;
bool is_painting;
entity::id brush_entity;
float3 stroke_start;
float3 stroke_end;
float min_stroke_length;
float min_stroke_length_squared;
float stroke_width;
int max_stroke_segments;
int current_stroke_segment;
float max_miter_angle;
float decal_offset;
float3 stroke_bounds_min;
float3 stroke_bounds_max;
float3 p0;
float3 p0a;
float3 p0b;
std::size_t vertex_size;
std::size_t vertex_stride;
std::size_t vertex_count;
::render::model* stroke_model;
::render::model_group* stroke_model_group;
gl::vertex_buffer* stroke_vbo;
bool midstroke;
scene::model_instance* stroke_model_instance;
};
} // namespace system
} // namespace game
#endif // ANTKEEPER_GAME_SYSTEM_PAINTING_HPP

+ 6
- 3
src/gl/rasterizer.cpp View File

@ -102,9 +102,12 @@ void rasterizer::clear_framebuffer(bool color, bool depth, bool stencil)
{ {
GLbitfield mask = 0; GLbitfield mask = 0;
if (color) mask |= GL_COLOR_BUFFER_BIT;
if (depth) mask |= GL_DEPTH_BUFFER_BIT;
if (stencil) mask |= GL_STENCIL_BUFFER_BIT;
if (color)
mask |= GL_COLOR_BUFFER_BIT;
if (depth)
mask |= GL_DEPTH_BUFFER_BIT;
if (stencil)
mask |= GL_STENCIL_BUFFER_BIT;
glClear(mask); glClear(mask);
} }

+ 3
- 3
src/gl/shader-stage.hpp View File

@ -27,13 +27,13 @@ namespace gl {
*/ */
enum class shader_stage enum class shader_stage
{ {
/// Indicates a vertex shader stage.
/// Vertex shader stage.
vertex, vertex,
/// Indicates a fragment shader stage.
/// Fragment shader stage.
fragment, fragment,
/// Indicates a geometry shader stage.
/// Geometry shader stage.
geometry geometry
}; };

+ 1
- 1
src/render/stage/culling-stage.cpp View File

@ -45,7 +45,7 @@ void culling_stage::execute(render::context& ctx) const
// For each object in the scene collection // For each object in the scene collection
std::for_each std::for_each
( (
std::execution::par_unseq,
std::execution::par,
std::begin(objects), std::begin(objects),
std::end(objects), std::end(objects),
[&](scene::object_base* object) [&](scene::object_base* object)

Loading…
Cancel
Save