Skip to content

Commit

Permalink
Simplify camera event handlers
Browse files Browse the repository at this point in the history
Event handlers now infer camera distance from zoom controls which are
no longer an optional input.

Other changes
- Implements pan support in the camera touch event handler
- Add touch event handler to hello-tetra example
- Fixes world axes transform in hello-tetra example
  • Loading branch information
davreev committed Sep 1, 2024
1 parent 70dc9f2 commit 937dc12
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 39 deletions.
27 changes: 21 additions & 6 deletions example/hello-tetra/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ struct {

struct {
bool mouse_down[3];
Vec2<f32> last_touch_points[2];
i8 last_num_touches;
} input;

struct {
Expand Down Expand Up @@ -178,14 +180,17 @@ void draw_mesh(Mat4<f32> const& local_to_view, Mat4<f32> const& view_to_clip)
sg_draw(0, 12, 1);
}

void debug_draw(Mat4<f32> const& local_to_view, Mat4<f32> const& view_to_clip)
void debug_draw(
Mat4<f32> const& local_to_view,
Mat4<f32> const& world_to_view,
Mat4<f32> const& view_to_clip)
{
sgl_defaults();

sgl_matrix_mode_projection();
sgl_load_matrix(view_to_clip.data());

debug_draw_axes(local_to_view, 0.1f);
debug_draw_axes(world_to_view, 0.25f);
debug_draw_unit_cube_edges(local_to_view);

sgl_draw();
Expand Down Expand Up @@ -229,21 +234,31 @@ void draw(void* /*context*/)
state.view.clip_far);

draw_mesh(local_to_view, view_to_clip);
debug_draw(local_to_view, view_to_clip);
debug_draw(local_to_view, world_to_view, view_to_clip);
draw_ui();
}

void handle_event(void* /*context*/, App::Event const& event)
{
f32 const screen_to_view = dr::screen_to_view(state.view.fov_y, sapp_heightf());

camera_handle_mouse_event(
event,
state.camera.offset.z(),
screen_to_view(state.view.fov_y, sapp_heightf()),
state.zoom.target,
&state.orbit.target,
&state.zoom.target,
&state.pan.target,
screen_to_view,
state.input.mouse_down);

camera_handle_touch_event(
event,
state.zoom.target,
&state.orbit.target,
&state.pan.target,
screen_to_view,
state.input.last_touch_points,
state.input.last_num_touches);

constexpr auto center_camera = []() {
state.zoom.target.distance = 4.0f;
state.pan.target.offset = {};
Expand Down
12 changes: 5 additions & 7 deletions include/dr/app/event_handlers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,25 @@ struct Pan;
/// True if the mouse is over the app window
bool is_mouse_over(App::Event const& event);

/// Scale factor for taking screen space distances to view space (at z = -1).
/// Scale factor for taking screen space displacements to view space (at z = -1).
f32 screen_to_view(f32 fov, f32 size);

/// Handles mouse events for camera control
void camera_handle_mouse_event(
App::Event const& event,
f32 camera_distance,
f32 screen_to_view,
Zoom& zoom,
Orbit* orbit,
Zoom* zoom,
Pan* pan,
f32 screen_to_view,
bool mouse_down[3]);

/// Handles touch events for camera control
void camera_handle_touch_event(
App::Event const& event,
f32 camera_distance,
f32 screen_to_view,
Zoom& zoom,
Orbit* orbit,
Zoom* zoom,
Pan* pan,
f32 screen_to_view,
Vec2<f32> last_touch_points[2],
i8& last_num_touches);

Expand Down
57 changes: 31 additions & 26 deletions src/event_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cmath>

#include <dr/math.hpp>
#include <dr/app/app.hpp>
#include <dr/app/camera.hpp>

Expand All @@ -14,20 +15,18 @@ bool is_mouse_over(App::Event const& event)
&& event.mouse_y < event.window_height;
}

f32 screen_to_view(f32 const fov, f32 const size)
{
return std::tan(fov * 0.5f) / (size * 0.5f);
}
f32 screen_to_view(f32 const fov, f32 const size) { return std::tan(fov * 0.5f) / (size * 0.5f); }

void camera_handle_mouse_event(
App::Event const& event,
f32 const camera_distance,
f32 const screen_to_view,
Zoom& zoom,
Orbit* const orbit,
Zoom* const zoom,
Pan* const pan,
f32 const screen_to_view,
bool mouse_down[3])
{
f32 const cam_offset = zoom.distance;

switch (event.type)
{
case SAPP_EVENTTYPE_MOUSE_DOWN:
Expand Down Expand Up @@ -65,30 +64,25 @@ void camera_handle_mouse_event(
}
case SAPP_EVENTTYPE_MOUSE_MOVE:
{
if (mouse_down[0] && orbit != nullptr)
if (mouse_down[0] && orbit)
{
Vec2<f32> const d{event.mouse_dx, event.mouse_dy};
orbit->handle_drag(d * screen_to_view);
}

if (mouse_down[1] && pan != nullptr)
if (mouse_down[1] && pan)
{
Vec2<f32> const d{event.mouse_dx, event.mouse_dy};
pan->handle_drag(d * (camera_distance * screen_to_view));
pan->handle_drag(d * (cam_offset * screen_to_view));
}

break;
}
case SAPP_EVENTTYPE_MOUSE_SCROLL:
{
constexpr f32 scroll_scale = 0.1f;

if (zoom != nullptr)
{
f32 const d = scroll_scale * sign(event.scroll_y);
zoom->handle_scroll(d * camera_distance);
}

constexpr f32 scroll_scale = 0.1f; // TODO(dr): Expose as parameter
f32 const d = scroll_scale * sign(event.scroll_y);
zoom.handle_scroll(d * cam_offset);
break;
}
default:
Expand All @@ -100,14 +94,15 @@ void camera_handle_mouse_event(

void camera_handle_touch_event(
App::Event const& event,
f32 const camera_distance,
f32 const screen_to_view,
Zoom& zoom,
Orbit* const orbit,
Zoom* const zoom,
Pan* const /*pan*/,
Pan* const pan,
f32 const screen_to_view,
Vec2<f32> last_touch_points[2],
i8& last_num_touches)
{
f32 const cam_offset = zoom.distance;

switch (event.type)
{
case SAPP_EVENTTYPE_TOUCHES_BEGAN:
Expand All @@ -133,7 +128,7 @@ void camera_handle_touch_event(
{
case 1:
{
if (orbit != nullptr)
if (orbit)
{
Vec2<f32> const d = p0 - last_touch_points[0];
orbit->handle_drag(d * screen_to_view);
Expand All @@ -142,12 +137,22 @@ void camera_handle_touch_event(
}
case 2:
{
// TODO: Handle as pan if deltas for each point are nearly parallel
if (zoom != nullptr)
// Handle drag pan
if(pan)
{
Vec2<f32> const d0 = screen_to_view * (p0 - last_touch_points[0]);
Vec2<f32> const d1 = screen_to_view * (p1 - last_touch_points[1]);

constexpr f32 abs_tol = 1.0e-3; // TODO(dr): Test this
if(near_equal(d0, d1, abs_tol))
pan->handle_drag((d0 + d1) * (0.5f * cam_offset));
}

// Handle pinch zoom
{
f32 const d0 = (last_touch_points[0] - last_touch_points[1]).norm();
f32 const d1 = (p0 - p1).norm();
zoom->handle_scroll((d1 - d0) * (camera_distance * screen_to_view));
zoom.handle_scroll((d1 - d0) * (cam_offset * screen_to_view));
}
break;
}
Expand Down

0 comments on commit 937dc12

Please sign in to comment.