mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-23 07:46:36 +08:00
feat(gltf): gltf view raycasting and 3d point to screen point conversion (#9143)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Install LVGL using CMake / build-examples (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#if LV_USE_GLTF
|
||||
|
||||
#include "../../../misc/lv_types.h"
|
||||
#include "../../../misc/lv_area.h"
|
||||
#include "../../../misc/lv_color.h"
|
||||
#include "../gltf_data/lv_gltf_model.h"
|
||||
|
||||
@@ -43,6 +44,19 @@ typedef enum {
|
||||
LV_GLTF_BG_MODE_ENVIRONMENT = 1, /** Environnement background*/
|
||||
} lv_gltf_bg_mode_t;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} lv_3dpoint_t;
|
||||
|
||||
typedef struct {
|
||||
lv_3dpoint_t origin;
|
||||
lv_3dpoint_t direction;
|
||||
} lv_3dplane_t;
|
||||
|
||||
typedef lv_3dplane_t lv_3dray_t;
|
||||
|
||||
#define LV_GLTF_ANIM_SPEED_TENTH 100
|
||||
#define LV_GLTF_ANIM_SPEED_QUARTER 250
|
||||
#define LV_GLTF_ANIM_SPEED_HALF 500
|
||||
@@ -130,12 +144,19 @@ float lv_gltf_get_pitch(const lv_obj_t * obj);
|
||||
void lv_gltf_set_distance(lv_obj_t * obj, float value);
|
||||
|
||||
/**
|
||||
* Get the camera distance from the focal point
|
||||
* Get the camera distance scale factor from the focal point
|
||||
* @param obj pointer to a GLTF viewer object
|
||||
* @return distance value
|
||||
* @return distance scaling factor value
|
||||
*/
|
||||
float lv_gltf_get_distance(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the camera distance from the focal point in world units
|
||||
* @param obj pointer to a GLTF viewer object
|
||||
* @return world unit distance value
|
||||
*/
|
||||
float lv_gltf_get_world_distance(const lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* Viewport Functions
|
||||
**********************/
|
||||
@@ -340,6 +361,54 @@ void lv_gltf_set_antialiasing_mode(lv_obj_t * obj, lv_gltf_aa_mode_t value);
|
||||
*/
|
||||
lv_gltf_aa_mode_t lv_gltf_get_antialiasing_mode(const lv_obj_t * obj);
|
||||
|
||||
/***********************
|
||||
* Raycasting Functions
|
||||
***********************/
|
||||
|
||||
/**
|
||||
* Get a plane that faces the current view camera, centered some units in front of it
|
||||
* @param obj pointer to a GLTF viewer object
|
||||
* @param distance distance in front of the camera to set the plane, in world units. see lv_gltf_get_world_distance to get the auto-distance
|
||||
* @return camera facing plane
|
||||
*/
|
||||
lv_3dplane_t lv_gltf_get_current_view_plane(lv_obj_t * obj, float distance);
|
||||
|
||||
/**
|
||||
* Get a plane that faces upward, centered at a given height
|
||||
* @param obj pointer to a GLTF viewer object
|
||||
* @param elevation elevation of the ground plane, in world units. this is usually zero
|
||||
* @return ground plane
|
||||
*/
|
||||
lv_3dplane_t lv_gltf_get_ground_plane(float elevation);
|
||||
|
||||
/**
|
||||
* Calculates a ray originating from the camera and passing through the specified mouse position on the screen.
|
||||
* @param obj pointer to a GLTF viewer object
|
||||
* @param screen_pos screen co-ordinate, in pixels
|
||||
* @return mouse point ray
|
||||
*/
|
||||
lv_3dray_t lv_gltf_get_ray_from_2d_coordinate(lv_obj_t * obj, const lv_point_t * screen_pos);
|
||||
|
||||
/**
|
||||
* Get the point that a given ray intersects with a specified plane at, if any
|
||||
* @param ray the intersection test ray
|
||||
* @param screen_y the plane to test ray intersection with
|
||||
* @param collision_point output lv_3dpoint_t holder, values are only valid if true is the return value
|
||||
* @return LV_RESULT_OK if intersection, LV_RESULT_INVALID if no intersection
|
||||
*/
|
||||
lv_result_t lv_gltf_intersect_ray_with_plane(const lv_3dray_t * ray, const lv_3dplane_t * plane,
|
||||
lv_3dpoint_t * collision_point);
|
||||
|
||||
/**
|
||||
* Get the screen position of a 3d point
|
||||
* @param obj pointer to a GLTF viewer object
|
||||
* @param world_pos world position to convert
|
||||
* @param lv_point_t the resulting point, in pixels. only valid if return value is true
|
||||
* @return LV_RESULT_OK if conversion valid, LV_RESULT_INVALID if no valid conversion
|
||||
*/
|
||||
lv_result_t lv_gltf_world_to_screen(lv_obj_t * obj, const lv_3dpoint_t world_pos, lv_point_t * screen_pos);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -209,6 +209,19 @@ float lv_gltf_get_distance(const lv_obj_t * obj)
|
||||
return viewer->desc.distance;
|
||||
}
|
||||
|
||||
float lv_gltf_get_world_distance(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
lv_gltf_view_desc_t * view_desc = &viewer->desc;
|
||||
if(viewer->models.size == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
lv_gltf_model_t * model = *(lv_gltf_model_t **)lv_array_at(&viewer->models, 0);
|
||||
return (lv_gltf_data_get_radius(model) * LV_GLTF_DISTANCE_SCALE_FACTOR) * view_desc->distance;
|
||||
}
|
||||
|
||||
void lv_gltf_set_animation_speed(lv_obj_t * obj, uint32_t value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
@@ -427,6 +440,116 @@ void lv_gltf_recenter(lv_obj_t * obj, lv_gltf_model_t * model)
|
||||
viewer->desc.focal_z = center_position[2];
|
||||
}
|
||||
|
||||
lv_3dray_t lv_gltf_get_ray_from_2d_coordinate(lv_obj_t * obj, const lv_point_t * screen_pos)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
|
||||
float norm_mouse_x = (float)screen_pos->x / (float)(lv_obj_get_width(obj));
|
||||
float norm_mouse_y = (float)screen_pos->y / (float)(lv_obj_get_height(obj));
|
||||
|
||||
lv_3dray_t outray = {0};
|
||||
|
||||
fastgltf::math::fmat4x4 proj_mat = fastgltf::math::invert(fastgltf::math::fmat4x4(viewer->projection_matrix));
|
||||
|
||||
/* Convert mouse coordinates to NDC */
|
||||
float x = norm_mouse_x * 2.0f - 1.0f;
|
||||
float y = 1.0f - (norm_mouse_y * 2.0f);
|
||||
float z = -1.0f; /* Clip space z */
|
||||
|
||||
fastgltf::math::fvec4 clip_space_pos = fastgltf::math::fvec4(x, y, z, 1.f);
|
||||
auto ray_eye = (proj_mat) * clip_space_pos;
|
||||
ray_eye[2] = -1.0f;
|
||||
ray_eye[3] = 0.0f;
|
||||
|
||||
/* Calculate ray world direction */
|
||||
fastgltf::math::fvec4 ray_world = fastgltf::math::invert(viewer->view_matrix) * ray_eye;
|
||||
auto ray_direction = fastgltf::math::normalize(fastgltf::math::fvec3(ray_world[0], ray_world[1], ray_world[2]));
|
||||
|
||||
outray.direction = {ray_direction[0], ray_direction[1], ray_direction[2]};
|
||||
outray.origin = {viewer->camera_pos[0], viewer->camera_pos[1], viewer->camera_pos[2]};
|
||||
|
||||
return outray;
|
||||
}
|
||||
|
||||
lv_result_t lv_gltf_intersect_ray_with_plane(const lv_3dray_t * ray, const lv_3dplane_t * plane,
|
||||
lv_3dpoint_t * collision_point)
|
||||
{
|
||||
fastgltf::math::fvec3 plane_center = fastgltf::math::fvec3(plane->origin.x, plane->origin.y, plane->origin.z);
|
||||
fastgltf::math::fvec3 plane_normal = fastgltf::math::fvec3(plane->direction.x, plane->direction.y, plane->direction.z);
|
||||
fastgltf::math::fvec3 ray_start = fastgltf::math::fvec3(ray->origin.x, ray->origin.y, ray->origin.z);
|
||||
fastgltf::math::fvec3 ray_direction = fastgltf::math::fvec3(ray->direction.x, ray->direction.y, ray->direction.z);
|
||||
|
||||
float denom = fastgltf::math::dot(plane_normal, ray_direction);
|
||||
if(fabs(denom) > 1e-6) { /* Check if the ray is not parallel to the plane */
|
||||
fastgltf::math::fvec3 diff = plane_center - ray_start;
|
||||
float t = fastgltf::math::dot(diff, plane_normal) / denom;
|
||||
|
||||
if(t >= 0) { /* Intersection occurs ahead of the ray origin */
|
||||
/* Calculate the collision point */
|
||||
(*collision_point).x = ray_start[0] + t * ray_direction[0];
|
||||
(*collision_point).y = ray_start[1] + t * ray_direction[1];
|
||||
(*collision_point).z = ray_start[2] + t * ray_direction[2];
|
||||
return LV_RESULT_OK; /* Collision point found */
|
||||
}
|
||||
}
|
||||
return LV_RESULT_INVALID; /* No intersection */
|
||||
}
|
||||
|
||||
lv_3dplane_t lv_gltf_get_ground_plane(float elevation)
|
||||
{
|
||||
lv_3dplane_t outplane = {0};
|
||||
outplane.origin = {0.0f, elevation, 0.0f};
|
||||
outplane.direction = {0.0f, 1.0f, 0.0f};
|
||||
return outplane;
|
||||
}
|
||||
|
||||
lv_3dplane_t lv_gltf_get_current_view_plane(lv_obj_t * obj, float distance)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
lv_3dplane_t outplane = {0};
|
||||
|
||||
/* Forward vector is the third column of the matrix */
|
||||
auto forward = fastgltf::math::fvec3(viewer->view_matrix[0][2], viewer->view_matrix[1][2], viewer->view_matrix[2][2]);
|
||||
forward = fastgltf::math::normalize(forward);
|
||||
|
||||
/* Calculate the plane center */
|
||||
const auto & camera_pos = viewer->camera_pos;
|
||||
auto plane_pos = fastgltf::math::fvec3(camera_pos[0], camera_pos[1], camera_pos[2]) - forward * distance;
|
||||
outplane.origin = {plane_pos[0], plane_pos[1], plane_pos[2]};
|
||||
outplane.direction = {-forward[0], -forward[1], -forward[2]};
|
||||
return outplane;
|
||||
}
|
||||
|
||||
lv_result_t lv_gltf_world_to_screen(lv_obj_t * obj, const lv_3dpoint_t world_pos, lv_point_t * screen_pos)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
|
||||
fastgltf::math::fvec4 world_position_h = fastgltf::math::fvec4(world_pos.x, world_pos.y, world_pos.z, 1.0f);
|
||||
fastgltf::math::fvec4 clip_space_pos = viewer->projection_matrix * viewer->view_matrix * world_position_h;
|
||||
|
||||
/* Check for perspective division (w must not be zero) */
|
||||
if(clip_space_pos[3] == 0.0f) {
|
||||
screen_pos->x = -1;
|
||||
screen_pos->y = -1;
|
||||
return LV_RESULT_INVALID; /* Position is not valid for screen mapping */
|
||||
}
|
||||
|
||||
clip_space_pos /= clip_space_pos[3];
|
||||
float norm_screen_x = clip_space_pos[0] * 0.5f + 0.5f;
|
||||
float norm_screen_y = 0.5f - (clip_space_pos[1] * 0.5f);
|
||||
int32_t win_width = lv_obj_get_width(obj);
|
||||
int32_t win_height = lv_obj_get_height(obj);
|
||||
screen_pos->x = norm_screen_x * win_width;
|
||||
screen_pos->y = norm_screen_y * win_height;
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_GLTF_DISTANCE_SCALE_FACTOR 2.5f
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
|
||||
@@ -1035,7 +1035,7 @@ static void setup_view_proj_matrix(lv_gltf_t * viewer, lv_gltf_view_desc_t * vie
|
||||
bool transmission_pass)
|
||||
{
|
||||
auto b_radius = lv_gltf_data_get_radius(gltf_data);
|
||||
float radius = b_radius * 2.5;
|
||||
float radius = b_radius * LV_GLTF_DISTANCE_SCALE_FACTOR;
|
||||
radius *= view_desc->distance;
|
||||
|
||||
fastgltf::math::fvec3 rcam_dir = fastgltf::math::fvec3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
Reference in New Issue
Block a user