11#include " le_camera.h"
22#include " le_core.h"
33
4+ #include " modules/le_log/le_log.h"
45#include " private/le_renderer/le_renderer_types.h" // for le::Viewport
56#include " le_ui_event.h"
67
@@ -92,7 +93,7 @@ static void update_frustum_planes( le_camera_o* self ) {
9293 float fPL [ 6 ]{};
9394 for ( size_t i = 0 ; i != 6 ; i++ ) {
9495 // get the length (= magnitude of the .xyz part of the row), so that we can normalize later
95- fPL [ i ] = glm::vec3 ( fP [ i ].x , fP [ i ].y , fP [ i ].z ). length ( );
96+ fPL [ i ] = glm::distance ( glm:: vec3 ( fP [ i ].x , fP [ i ].y , fP [ i ].z ), glm::vec3 ( 0 ) );
9697 }
9798
9899 for ( size_t i = 0 ; i < 6 ; i++ ) {
@@ -289,6 +290,19 @@ void camera_translate_xy( le_camera_o* camera, glm::mat4 const& world_to_cam_sta
289290 camera->view_matrix = glm::inverse ( world_to_cam );
290291}
291292
293+ // ----------------------------------------------------------------------
294+ void camera_translate_xyz ( le_camera_o* camera, glm::mat4 const & world_to_cam_start, glm::vec3 const & signedNorm, float movement_speed, float pivotDistance ) {
295+
296+ float distance_to_origin = glm::distance ( glm::vec4{ 0 , 0 , 0 , 1 }, world_to_cam_start * glm::vec4 ( 0 , 0 , 0 , 1 ) );
297+ movement_speed *= distance_to_origin;
298+
299+ auto pivot = glm::translate ( world_to_cam_start, glm::vec3{ 0 , 0 , -pivotDistance } );
300+ pivot = glm::translate ( pivot, movement_speed * glm::vec3{ signedNorm.x , signedNorm.y , signedNorm.z } );
301+ auto world_to_cam = glm::translate ( pivot, glm::vec3{ 0 , 0 , pivotDistance } );
302+
303+ camera->view_matrix = glm::inverse ( world_to_cam );
304+ }
305+
292306// ----------------------------------------------------------------------
293307
294308void camera_translate_z ( le_camera_o* camera, glm::mat4 const & world_to_cam_start, glm::vec3 const & signedNorm, float movement_speed, float pivotDistance ) {
@@ -326,6 +340,8 @@ static void camera_controller_update_camera( le_camera_controller_o* controller,
326340 }
327341
328342 for ( auto const & event : events ) {
343+ glm::vec3 translationDelta{};
344+ glm::vec3 rotationDelta{};
329345
330346 // -- accumulate mouse state
331347
@@ -355,21 +371,56 @@ static void camera_controller_update_camera( le_camera_controller_o* controller,
355371 if ( e.action == LeUiEvent::ButtonAction::ePress ) {
356372 // set appropriate button flag
357373 mouse_state.buttonState |= ( 1 << e.button );
358-
359374 } else if ( e.action == LeUiEvent::ButtonAction::eRelease ) {
360375 // null appropriate button flag
361376 mouse_state.buttonState &= ~( 1 << e.button );
362377 // set camera controller into neutral state if any button was released.
363378 controller->mode = le_camera_controller_o::eNeutral;
364379 }
365380 } break ;
381+ case ( LeUiEvent::Type::eGamepad ): {
382+ auto & e = event->gamepad ;
383+
384+ // We must make sure that axes are not drifting ... if any of the values are below axes_epsilon, they shall be zero.
385+ // Therefore, we ignore any values that are within the +- drift range; we then remap the range so that we still cover -1..1
386+ auto remove_drift = []( glm::vec3 const & vec_input, glm::vec3 const & drift_tolerance = glm::vec3 ( 0 .1f ) ) -> glm::vec3 {
387+ glm::vec3 abs_val = glm::abs ( vec_input );
388+ glm::vec3 sign_val = glm::sign ( vec_input );
389+
390+ glm::vec3 test_val = abs_val - drift_tolerance;
391+ test_val = max ( glm::vec3 ( 0 .f ), test_val );
392+ test_val = test_val * sign_val;
393+ // todo: map back to original range.
394+ return test_val / ( glm::vec3 ( 1 .f ) - drift_tolerance );
395+ };
396+
397+ glm::vec3 gamepad_x_y_z = {
398+ e.axes [ uint32_t ( le::UiEvent::NamedGamepadAxis::eLeftX ) ],
399+ e.axes [ uint32_t ( le::UiEvent::NamedGamepadAxis::eLeftY ) ],
400+ ( ( e.axes [ uint32_t ( le::UiEvent::NamedGamepadAxis::eLeftTrigger ) ] + 1 ) -
401+ ( e.axes [ uint32_t ( le::UiEvent::NamedGamepadAxis::eRightTrigger ) ] + 1 ) ),
402+ };
403+
404+ translationDelta += 0 .01f * remove_drift ( gamepad_x_y_z, glm::vec3 ( 0.1 ) );
405+ ;
406+
407+ glm::vec3 gamepad_rot = {
408+ e.axes [ uint32_t ( le::UiEvent::NamedGamepadAxis::eRightX ) ],
409+ e.axes [ uint32_t ( le::UiEvent::NamedGamepadAxis::eRightY ) ],
410+ 0 .f };
411+
412+ gamepad_rot = remove_drift ( gamepad_rot, glm::vec3 ( 0.1 ) );
413+
414+ rotationDelta.x = glm::two_pi<float >() * -0 .0025f * gamepad_rot.x ;
415+ rotationDelta.y = glm::two_pi<float >() * 0 .0025f * gamepad_rot.y ;
416+
417+ break ;
418+ }
366419 default :
367420 break ;
368421 }
369422
370- glm::vec3 rotationDelta;
371- glm::vec3 translationDelta;
372- {
423+ if ( mouse_state.buttonState ) {
373424 auto mouseInitial = controller->mouse_pos_initial - controlRectCentre;
374425 float mouseInitialAngle = glm::two_pi<float >() - fmodf ( glm::two_pi<float >() + atan2f ( mouseInitial.y , mouseInitial.x ), glm::two_pi<float >() ); // Range is expected to be 0..2pi, ccw
375426
@@ -389,6 +440,18 @@ static void camera_controller_update_camera( le_camera_controller_o* controller,
389440 switch ( controller->mode ) {
390441 case le_camera_controller_o::eNeutral: {
391442
443+ if ( event->event == le::UiEvent::Type::eGamepad ) {
444+
445+ float movement_speed = 0.5 ;
446+ static auto logger = le::Log ( " le_camera" );
447+ controller->world_to_cam = glm::inverse ( camera->view_matrix );
448+ camera_translate_xyz ( camera, controller->world_to_cam , translationDelta, movement_speed, controller->pivotDistance );
449+ controller->world_to_cam = glm::inverse ( camera->view_matrix );
450+ camera_orbit_xy ( camera, controller->world_to_cam , rotationDelta, controller->pivotDistance );
451+ controller->world_to_cam = glm::inverse ( camera->view_matrix );
452+ continue ;
453+ }
454+
392455 if ( false == is_inside_rect ( mouse_state.cursor_pos , controller->controlRect ) ) {
393456 // if camera is outside the control rect, we don't care.
394457 continue ;
@@ -458,7 +521,10 @@ static void camera_controller_process_events( le_camera_controller_o* controller
458521 filtered_events.reserve ( numEvents );
459522
460523 for ( auto event = events; event != events_end; event++ ) {
461- if ( event->event == LeUiEvent::Type::eCursorPosition || event->event == LeUiEvent::Type::eMouseButton || event->event == LeUiEvent::Type::eKey ) {
524+ if ( event->event == LeUiEvent::Type::eCursorPosition ||
525+ event->event == LeUiEvent::Type::eMouseButton ||
526+ event->event == LeUiEvent::Type::eKey ||
527+ event->event == LeUiEvent::Type::eGamepad ) {
462528 filtered_events.emplace_back ( event );
463529 }
464530 }
@@ -510,7 +576,8 @@ static void camera_controller_set_pivot_distance( le_camera_controller_o* self,
510576// ----------------------------------------------------------------------
511577
512578LE_MODULE_REGISTER_IMPL ( le_camera, api ) {
513- auto & le_camera_i = static_cast <le_camera_api*>( api )->le_camera_i ;
579+ auto api_i = static_cast <le_camera_api*>( api );
580+ auto & le_camera_i = api_i->le_camera_i ;
514581
515582 le_camera_i.create = le_camera_create;
516583 le_camera_i.destroy = le_camera_destroy;
@@ -529,7 +596,7 @@ LE_MODULE_REGISTER_IMPL( le_camera, api ) {
529596 le_camera_i.get_sphere_in_frustum = camera_get_sphere_in_frustum;
530597 le_camera_i.set_is_orthographic = camera_set_is_orthographic;
531598
532- auto & le_camera_controller_i = static_cast <le_camera_api*>( api ) ->le_camera_controller_i ;
599+ auto & le_camera_controller_i = api_i ->le_camera_controller_i ;
533600
534601 le_camera_controller_i.create = camera_controller_create;
535602 le_camera_controller_i.destroy = camera_controller_destroy;
0 commit comments