mirror of
https://github.com/lvgl/lvgl.git
synced 2026-03-23 13:07:07 +08:00
feat(gltf): allow sharing models across gltf objects (#9681)
This commit is contained in:
@@ -40,19 +40,25 @@ typedef struct {
|
||||
lv_obj_t * label;
|
||||
} play_pause_event_data_t;
|
||||
|
||||
typedef void (*lv_gltf_set_float_fn)(lv_obj_t *, float);
|
||||
typedef void (*lv_gltf_set_int_fn)(lv_obj_t *, uint32_t);
|
||||
typedef void (*lv_gltf_set_float_cb_t)(lv_obj_t *, float);
|
||||
typedef void (*lv_gltf_set_int_cb_t)(lv_obj_t *, uint32_t);
|
||||
typedef void (*lv_gltf_model_set_int_fn)(lv_gltf_model_t *, uint32_t);
|
||||
|
||||
typedef union {
|
||||
void * ptr;
|
||||
lv_gltf_set_float_fn fn;
|
||||
lv_gltf_set_float_cb_t cb;
|
||||
} lv_gltf_set_float_fn_union_t;
|
||||
|
||||
typedef union {
|
||||
void * ptr;
|
||||
lv_gltf_set_int_fn fn;
|
||||
lv_gltf_set_int_cb_t cb;
|
||||
} lv_gltf_set_int_fn_union_t;
|
||||
|
||||
typedef union {
|
||||
void * ptr;
|
||||
lv_gltf_set_int_cb_t cb;
|
||||
} lv_gltf_model_set_int_fn_union_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
@@ -77,6 +83,7 @@ static lv_obj_t * add_dropdown_to_row(lv_obj_t * row);
|
||||
static void viewer_observer_float_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void viewer_observer_int_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void animation_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void animation_speed_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void style_dropdown(lv_obj_t * dropdown);
|
||||
static void style_slider(lv_obj_t * slider, lv_color_t accent_color);
|
||||
static void style_control_panel(lv_obj_t * panel);
|
||||
@@ -85,16 +92,15 @@ static void style_control_panel(lv_obj_t * panel);
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static lv_gltf_set_float_fn_union_t pitch_fn = { .fn = lv_gltf_set_pitch };
|
||||
static lv_gltf_set_float_fn_union_t yaw_fn = { .fn = lv_gltf_set_yaw };
|
||||
static lv_gltf_set_float_fn_union_t distance_fn = { .fn = lv_gltf_set_distance };
|
||||
static lv_gltf_set_int_fn_union_t camera_fn = { .fn = lv_gltf_set_camera };
|
||||
static lv_gltf_set_int_fn_union_t animation_speed_fn = { .fn = lv_gltf_set_animation_speed };
|
||||
static lv_gltf_set_int_fn_union_t background_mode_fn = { .fn = lv_gltf_set_background_mode };
|
||||
static lv_gltf_set_int_fn_union_t antialiasing_mode_fn = { .fn = lv_gltf_set_antialiasing_mode };
|
||||
static lv_gltf_set_float_fn_union_t pitch_fn = { .cb = lv_gltf_set_pitch };
|
||||
static lv_gltf_set_float_fn_union_t yaw_fn = { .cb = lv_gltf_set_yaw };
|
||||
static lv_gltf_set_float_fn_union_t distance_fn = { .cb = lv_gltf_set_distance };
|
||||
static lv_gltf_set_int_fn_union_t camera_fn = { .cb = lv_gltf_set_camera };
|
||||
static lv_gltf_set_int_fn_union_t background_mode_fn = { .cb = lv_gltf_set_background_mode };
|
||||
static lv_gltf_set_int_fn_union_t antialiasing_mode_fn = { .cb = lv_gltf_set_antialiasing_mode };
|
||||
|
||||
static lv_gltf_set_int_fn_union_t env_brightness_fn = { .fn = lv_gltf_set_env_brightness };
|
||||
static lv_gltf_set_int_fn_union_t bg_blur_fn = { .fn = lv_gltf_set_background_blur };
|
||||
static lv_gltf_set_int_fn_union_t env_brightness_fn = { .cb = lv_gltf_set_env_brightness };
|
||||
static lv_gltf_set_int_fn_union_t bg_blur_fn = { .cb = lv_gltf_set_background_blur };
|
||||
|
||||
static lv_subject_t yaw_subject;
|
||||
static lv_subject_t pitch_subject;
|
||||
@@ -165,7 +171,7 @@ static void init_subjects(lv_obj_t * viewer)
|
||||
lv_subject_add_observer_obj(&distance_subject, viewer_observer_float_cb, viewer, distance_fn.ptr);
|
||||
|
||||
lv_subject_add_observer(&animation_subject, animation_observer_cb, viewer);
|
||||
lv_subject_add_observer_obj(&animation_speed_subject, viewer_observer_int_cb, viewer, animation_speed_fn.ptr);
|
||||
lv_subject_add_observer(&animation_speed_subject, animation_speed_observer_cb, viewer);
|
||||
|
||||
lv_subject_add_observer_obj(&background_subject, viewer_observer_int_cb, viewer, background_mode_fn.ptr);
|
||||
lv_subject_add_observer_obj(&env_brightness_subject, viewer_observer_int_cb, viewer, env_brightness_fn.ptr);
|
||||
@@ -497,7 +503,7 @@ static void viewer_observer_float_cb(lv_observer_t * observer, lv_subject_t * su
|
||||
float value = lv_subject_get_float(subject);
|
||||
lv_gltf_set_float_fn_union_t fn_union = { .ptr = lv_observer_get_user_data(observer) };
|
||||
|
||||
fn_union.fn(viewer, value);
|
||||
fn_union.cb(viewer, value);
|
||||
}
|
||||
|
||||
static void viewer_observer_int_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
@@ -506,7 +512,7 @@ static void viewer_observer_int_cb(lv_observer_t * observer, lv_subject_t * subj
|
||||
lv_gltf_set_int_fn_union_t fn_union = { .ptr = lv_observer_get_user_data(observer) };
|
||||
|
||||
lv_obj_t * viewer = lv_observer_get_target_obj(observer);
|
||||
fn_union.fn(viewer, value);
|
||||
fn_union.cb(viewer, value);
|
||||
}
|
||||
|
||||
static void animation_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
@@ -517,6 +523,15 @@ static void animation_observer_cb(lv_observer_t * observer, lv_subject_t * subje
|
||||
|
||||
lv_gltf_model_play_animation(model, value);
|
||||
}
|
||||
|
||||
static void animation_speed_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
int value = lv_subject_get_int(subject);
|
||||
lv_obj_t * viewer = lv_observer_get_user_data(observer);
|
||||
lv_gltf_model_t * model = lv_gltf_get_primary_model(viewer);
|
||||
|
||||
lv_gltf_model_set_animation_speed(model, value);
|
||||
}
|
||||
static void style_slider(lv_obj_t * slider, lv_color_t accent_color)
|
||||
{
|
||||
lv_obj_set_style_bg_color(slider, lv_color_hex(0x1A1A1A), LV_PART_MAIN);
|
||||
|
||||
@@ -291,7 +291,7 @@ Control model animations with these functions:
|
||||
lv_gltf_model_play_animation(model, 0);
|
||||
|
||||
/* Control animation speed */
|
||||
lv_gltf_set_animation_speed(gltf, LV_GLTF_ANIM_SPEED_2X);
|
||||
lv_gltf_model_set_animation_speed(model, LV_GLTF_ANIM_SPEED_2X);
|
||||
|
||||
/* Pause/resume animation */
|
||||
lv_gltf_model_pause_animation(model);
|
||||
|
||||
@@ -19,3 +19,10 @@ Load multiple models in a single glTF object and modify their position, rotation
|
||||
|
||||
.. lv_example:: libs/gltf/lv_example_gltf_3
|
||||
:language: c
|
||||
|
||||
|
||||
Share a model across different glTF objects
|
||||
-------------------------------------------
|
||||
|
||||
.. lv_example:: libs/gltf/lv_example_gltf_4
|
||||
:language: c
|
||||
|
||||
@@ -30,6 +30,7 @@ extern "C" {
|
||||
void lv_example_gltf_1(void);
|
||||
void lv_example_gltf_2(void);
|
||||
void lv_example_gltf_3(void);
|
||||
void lv_example_gltf_4(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -14,6 +14,7 @@ static uint32_t current_speed = LV_GLTF_ANIM_SPEED_HALF;
|
||||
static void timer_cb(lv_timer_t * timer)
|
||||
{
|
||||
lv_obj_t * gltf = (lv_obj_t *) lv_timer_get_user_data(timer);
|
||||
lv_gltf_model_t * model = lv_gltf_get_primary_model(gltf);
|
||||
current_camera = (current_camera + 1) % (camera_count + 1);
|
||||
current_speed *= 2;
|
||||
|
||||
@@ -23,7 +24,7 @@ static void timer_cb(lv_timer_t * timer)
|
||||
|
||||
LV_LOG_USER("Setting camera %zu and animation speed %" PRIu32, current_camera, current_speed);
|
||||
lv_gltf_set_camera(gltf, current_camera);
|
||||
lv_gltf_set_animation_speed(gltf, current_speed);
|
||||
lv_gltf_model_set_animation_speed(model, current_speed);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +37,7 @@ void lv_example_gltf_2(void)
|
||||
"A:lvgl/examples/libs/gltf/webp_diffuse_transmission_plant.glb");
|
||||
|
||||
|
||||
lv_gltf_set_animation_speed(gltf, current_speed);
|
||||
lv_gltf_model_set_animation_speed(model, current_speed);
|
||||
lv_gltf_model_play_animation(model, 0);
|
||||
lv_obj_set_size(gltf, LV_PCT(100), LV_PCT(100));
|
||||
camera_count = lv_gltf_get_camera_count(gltf);
|
||||
|
||||
117
examples/libs/gltf/lv_example_gltf_4.c
Normal file
117
examples/libs/gltf/lv_example_gltf_4.c
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "lv_example_gltf.h"
|
||||
|
||||
#if LV_BUILD_EXAMPLES
|
||||
|
||||
#if LV_USE_GLTF
|
||||
|
||||
static lv_gltf_model_node_t * logo_root;
|
||||
|
||||
static void anim_scale_cb(void * var, int32_t v)
|
||||
{
|
||||
lv_gltf_model_node_t * node = (lv_gltf_model_node_t *)var;
|
||||
|
||||
/* Convert integer animation value to float scale (v ranges from 10 to 100, representing 0.1 to 1.0) */
|
||||
float scale = v / 100.0f;
|
||||
|
||||
/* Apply uniform scale to all axes */
|
||||
lv_gltf_model_node_set_scale_x(node, scale);
|
||||
lv_gltf_model_node_set_scale_y(node, scale);
|
||||
lv_gltf_model_node_set_scale_z(node, scale);
|
||||
}
|
||||
|
||||
static void logo_scale_cb(lv_event_t * e)
|
||||
{
|
||||
lv_3dpoint_t scale;
|
||||
|
||||
/* Read current scale values */
|
||||
lv_gltf_model_node_get_scale(e, &scale);
|
||||
|
||||
LV_LOG_USER("logo scale: %.2f, %.2f, %.2f",
|
||||
scale.x, scale.y, scale.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a logo model once and share it across four glTF viewers in a 2x2 grid.
|
||||
* Each viewer shows the logo from a different angle.
|
||||
* Animate the shared model's growth - changes affect all four viewers.
|
||||
*/
|
||||
void lv_example_gltf_4(void)
|
||||
{
|
||||
/* Load the logo model once */
|
||||
lv_gltf_model_t * logo_model = lv_gltf_data_load_from_file(
|
||||
"A:lvgl/examples/libs/gltf/lvgl_logo.glb", NULL);
|
||||
|
||||
LV_ASSERT_NULL(logo_model);
|
||||
/* Create first glTF viewer - Top Left */
|
||||
lv_obj_t * gltf1 = lv_gltf_create(lv_screen_active());
|
||||
lv_obj_set_size(gltf1, LV_PCT(50), LV_PCT(50));
|
||||
lv_obj_align(gltf1, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_gltf_set_pitch(gltf1, -30.f);
|
||||
lv_gltf_set_yaw(gltf1, -30.f);
|
||||
lv_gltf_set_distance(gltf1, 0.5f);
|
||||
lv_gltf_add_model(gltf1, logo_model);
|
||||
|
||||
/* Create second glTF viewer - Top Right */
|
||||
lv_obj_t * gltf2 = lv_gltf_create(lv_screen_active());
|
||||
lv_obj_set_size(gltf2, LV_PCT(50), LV_PCT(50));
|
||||
lv_obj_align(gltf2, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_gltf_set_pitch(gltf2, -30.f);
|
||||
lv_gltf_set_yaw(gltf2, 30.f);
|
||||
lv_gltf_set_distance(gltf2, 0.5f);
|
||||
lv_gltf_add_model(gltf2, logo_model);
|
||||
|
||||
/* Create third glTF viewer - Bottom Left */
|
||||
lv_obj_t * gltf3 = lv_gltf_create(lv_screen_active());
|
||||
lv_obj_set_size(gltf3, LV_PCT(50), LV_PCT(50));
|
||||
lv_obj_align(gltf3, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
lv_gltf_set_pitch(gltf3, 30.f);
|
||||
lv_gltf_set_yaw(gltf3, -30.f);
|
||||
lv_gltf_set_distance(gltf3, 0.5f);
|
||||
lv_gltf_add_model(gltf3, logo_model);
|
||||
|
||||
/* Create fourth glTF viewer - Bottom Right */
|
||||
lv_obj_t * gltf4 = lv_gltf_create(lv_screen_active());
|
||||
lv_obj_set_size(gltf4, LV_PCT(50), LV_PCT(50));
|
||||
lv_obj_align(gltf4, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
lv_gltf_set_pitch(gltf4, 30.f);
|
||||
lv_gltf_set_yaw(gltf4, 30.f);
|
||||
lv_gltf_set_distance(gltf4, 0.5f);
|
||||
lv_gltf_add_model(gltf4, logo_model);
|
||||
|
||||
/* Get the root node of the shared logo */
|
||||
logo_root = lv_gltf_model_node_get_by_numeric_path(logo_model, ".0");
|
||||
|
||||
/* Register event callback to monitor scale changes */
|
||||
lv_gltf_model_node_add_event_cb(logo_root, logo_scale_cb,
|
||||
LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
/* Create animation for logo growth */
|
||||
/* Since the model is shared, animating the node affects all four viewers */
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, logo_root);
|
||||
lv_anim_set_values(&a, 10, 100); /* Scale from 0.1 to 1.0 */
|
||||
lv_anim_set_duration(&a, 2000); /* 2 seconds to grow */
|
||||
lv_anim_set_reverse_delay(&a, 1000); /* Stay big for 1 second */
|
||||
lv_anim_set_reverse_duration(&a, 1500); /* 1.5 seconds to shrink */
|
||||
lv_anim_set_repeat_delay(&a, 500); /* Wait 0.5 seconds before repeating */
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);
|
||||
lv_anim_set_exec_cb(&a, anim_scale_cb);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void lv_example_gltf_4(void)
|
||||
{
|
||||
/*TODO
|
||||
*fallback for online examples*/
|
||||
|
||||
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "glTF web support is coming soon");
|
||||
lv_obj_center(label);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
BIN
examples/libs/gltf/lvgl_logo.glb
Normal file
BIN
examples/libs/gltf/lvgl_logo.glb
Normal file
Binary file not shown.
@@ -15,7 +15,6 @@
|
||||
#include "../../../misc/lv_assert.h"
|
||||
#include "../../../core/lv_obj_pos.h"
|
||||
#include "../../../misc/lv_timer.h"
|
||||
#include "../gltf_view/lv_gltf_view_internal.h"
|
||||
|
||||
|
||||
/*********************
|
||||
@@ -52,20 +51,17 @@ lv_gltf_model_t * lv_gltf_data_create_internal(const char * gltf_path,
|
||||
new(data) lv_gltf_model_t;
|
||||
new(&data->asset) fastgltf::Asset(std::move(asset));
|
||||
data->filename = gltf_path;
|
||||
data->last_camera_index = -5;
|
||||
data->last_anim_num = -5;
|
||||
data->current_animation_max_time = 0;
|
||||
data->local_timestamp = 0.0f;
|
||||
data->last_material_index = 99999;
|
||||
data->last_frame_was_antialiased = false;
|
||||
data->last_frame_no_motion = false;
|
||||
data->_last_frame_no_motion = false;
|
||||
|
||||
data->animation_speed_ratio = LV_GLTF_ANIM_SPEED_NORMAL;
|
||||
data->animation_update_timer = lv_timer_create(update_animation_cb, LV_DEF_REFR_PERIOD, data);
|
||||
lv_timer_pause(data->animation_update_timer);
|
||||
LV_ASSERT_NULL(data->animation_update_timer);
|
||||
|
||||
new(&data->node_transform_cache) NodeTransformMap();
|
||||
new(&data->transforms) NodeTransformMap();
|
||||
new(&data->opaque_nodes_by_material_index) MaterialIndexMap();
|
||||
new(&data->blended_nodes_by_material_index) MaterialIndexMap();
|
||||
new(&data->validated_skins) LongVector();
|
||||
@@ -75,40 +71,46 @@ lv_gltf_model_t * lv_gltf_data_create_internal(const char * gltf_path,
|
||||
new(&data->node_by_light_index) NodeVector();
|
||||
new(&data->meshes) std::vector<lv_gltf_mesh_data_t>();
|
||||
new(&data->textures) std::vector<GLuint>();
|
||||
new(&data->ibm_by_skin_then_node) std::map<int32_t, std::map<fastgltf::Node *, fastgltf::math::fmat4x4>>;
|
||||
|
||||
lv_array_init(&data->viewers, 1, sizeof(lv_gltf_t *));
|
||||
lv_array_init(&data->compiled_shaders, 1, sizeof(lv_gltf_compiled_shader_t));
|
||||
return data;
|
||||
}
|
||||
|
||||
void lv_gltf_data_delete(lv_gltf_model_t * data)
|
||||
void lv_gltf_model_delete(lv_gltf_model_t * model)
|
||||
{
|
||||
LV_ASSERT_NULL(data);
|
||||
lv_timer_delete(data->animation_update_timer);
|
||||
data->animation_update_timer = NULL;
|
||||
if(!model) {
|
||||
return;
|
||||
}
|
||||
lv_timer_delete(model->animation_update_timer);
|
||||
model->animation_update_timer = NULL;
|
||||
|
||||
lv_gltf_data_delete_textures(data);
|
||||
uint32_t node_count = lv_array_size(&data->nodes);
|
||||
lv_gltf_data_delete_textures(model);
|
||||
uint32_t node_count = lv_array_size(&model->nodes);
|
||||
for(uint32_t i = 0; i < node_count; ++i) {
|
||||
lv_gltf_model_node_t * node = (lv_gltf_model_node_t *) lv_array_at(&data->nodes, i);
|
||||
lv_gltf_model_node_t * node = (lv_gltf_model_node_t *) lv_array_at(&model->nodes, i);
|
||||
lv_gltf_model_node_deinit(node);
|
||||
}
|
||||
lv_array_deinit(&data->nodes);
|
||||
lv_array_deinit(&data->compiled_shaders);
|
||||
lv_array_deinit(&model->viewers);
|
||||
lv_array_deinit(&model->nodes);
|
||||
lv_array_deinit(&model->compiled_shaders);
|
||||
|
||||
/* Explicitly call destructors for C++ objects initialized with placement new */
|
||||
data->textures.~vector();
|
||||
data->meshes.~vector();
|
||||
data->node_by_light_index.~vector();
|
||||
data->local_mesh_to_center_points_by_primitive.~map();
|
||||
data->skin_tex.~vector();
|
||||
data->validated_skins.~vector();
|
||||
data->blended_nodes_by_material_index.~map();
|
||||
data->opaque_nodes_by_material_index.~map();
|
||||
data->node_transform_cache.~map();
|
||||
data->channel_set_cache.~map();
|
||||
data->asset.~Asset();
|
||||
model->ibm_by_skin_then_node.~IbmBySkinThenNodeMap();
|
||||
model->textures.~vector();
|
||||
model->meshes.~vector();
|
||||
model->node_by_light_index.~vector();
|
||||
model->local_mesh_to_center_points_by_primitive.~map();
|
||||
model->skin_tex.~vector();
|
||||
model->validated_skins.~vector();
|
||||
model->blended_nodes_by_material_index.~map();
|
||||
model->opaque_nodes_by_material_index.~map();
|
||||
model->transforms.~map();
|
||||
model->channel_set_cache.~map();
|
||||
model->asset.~Asset();
|
||||
|
||||
lv_free(data);
|
||||
lv_free(model);
|
||||
}
|
||||
|
||||
const char * lv_gltf_get_filename(const lv_gltf_model_t * data)
|
||||
@@ -206,18 +208,16 @@ size_t lv_gltf_model_get_animation(lv_gltf_model_t * model)
|
||||
return model->current_animation;
|
||||
}
|
||||
|
||||
lv_gltf_model_t *
|
||||
lv_gltf_data_load_from_file(const char * file_path,
|
||||
lv_opengl_shader_manager_t * shader_manager)
|
||||
|
||||
lv_gltf_model_t * lv_gltf_data_load_from_file(const char * file_path, lv_gltf_model_loader_t * loader)
|
||||
{
|
||||
return lv_gltf_data_load_internal(file_path, 0, shader_manager);
|
||||
return lv_gltf_data_load_internal(file_path, 0, loader);
|
||||
}
|
||||
|
||||
lv_gltf_model_t *
|
||||
lv_gltf_data_load_from_bytes(const uint8_t * data, size_t data_size,
|
||||
lv_opengl_shader_manager_t * shader_manager)
|
||||
|
||||
lv_gltf_model_t * lv_gltf_data_load_from_bytes(const uint8_t * data, size_t data_size, lv_gltf_model_loader_t * loader)
|
||||
{
|
||||
return lv_gltf_data_load_internal(data, data_size, shader_manager);
|
||||
return lv_gltf_data_load_internal(data, data_size, loader);
|
||||
}
|
||||
|
||||
fastgltf::Asset * lv_gltf_data_get_asset(lv_gltf_model_t * data)
|
||||
@@ -266,6 +266,56 @@ void lv_gltf_data_copy_bounds_info(lv_gltf_model_t * to, lv_gltf_model_t * from)
|
||||
to->bound_radius = from->bound_radius;
|
||||
}
|
||||
|
||||
void lv_gltf_model_set_animation_speed(lv_gltf_model_t * model, uint32_t value)
|
||||
{
|
||||
if(!model) {
|
||||
return;
|
||||
}
|
||||
if(model->animation_speed_ratio == value) {
|
||||
return;
|
||||
}
|
||||
model->animation_speed_ratio = value;
|
||||
lv_gltf_model_invalidate(model);
|
||||
}
|
||||
uint32_t lv_gltf_model_get_animation_speed(const lv_gltf_model_t * model)
|
||||
{
|
||||
if(!model) {
|
||||
return 0;
|
||||
}
|
||||
return model->animation_speed_ratio;
|
||||
}
|
||||
|
||||
lv_result_t lv_gltf_model_add_viewer(lv_gltf_model_t * model, lv_obj_t * viewer)
|
||||
{
|
||||
LV_ASSERT_NULL(model);
|
||||
LV_ASSERT_NULL(viewer);
|
||||
return lv_array_push_back(&model->viewers, &viewer);
|
||||
}
|
||||
|
||||
void lv_gltf_model_remove_viewer(lv_gltf_model_t * model, lv_obj_t * target_viewer)
|
||||
{
|
||||
LV_ASSERT_NULL(model);
|
||||
LV_ASSERT_NULL(target_viewer);
|
||||
const uint32_t viewer_count = lv_array_size(&model->viewers);
|
||||
for(uint32_t i = 0; i < viewer_count; ++i) {
|
||||
lv_obj_t * viewer = *(lv_obj_t **)lv_array_at(&model->viewers, i);
|
||||
if(viewer == target_viewer) {
|
||||
lv_array_remove_unordered(&model->viewers, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_gltf_model_invalidate(lv_gltf_model_t * model)
|
||||
{
|
||||
LV_ASSERT_NULL(model);
|
||||
const uint32_t viewer_count = lv_array_size(&model->viewers);
|
||||
for(uint32_t i = 0; i < viewer_count; ++i) {
|
||||
lv_obj_t * viewer = *(lv_obj_t **)lv_array_at(&model->viewers, i);
|
||||
lv_obj_invalidate(viewer);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -278,12 +328,13 @@ static void update_animation_cb(lv_timer_t * timer)
|
||||
const uint32_t delta = lv_tick_diff(current_tick, model->last_tick);
|
||||
|
||||
model->last_tick = current_tick;
|
||||
model->local_timestamp += (delta * model->viewer->desc.animation_speed_ratio) / 1000;
|
||||
model->local_timestamp += (delta * model->animation_speed_ratio) / 1000;
|
||||
|
||||
if(model->local_timestamp >= model->current_animation_max_time) {
|
||||
model->local_timestamp = 50;
|
||||
}
|
||||
lv_obj_invalidate((lv_obj_t *)model->viewer);
|
||||
lv_gltf_model_invalidate(model);
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_GLTF*/
|
||||
|
||||
@@ -34,31 +34,34 @@
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
fastgltf::math::fmat4x4 lv_gltf_data_get_cached_transform(lv_gltf_model_t * data,
|
||||
fastgltf::Node * node)
|
||||
fastgltf::math::fmat4x4 lv_gltf_data_get_node_transform(lv_gltf_model_t * model,
|
||||
fastgltf::Node * node)
|
||||
{
|
||||
return data->node_transform_cache[node];
|
||||
return model->transforms[node];
|
||||
}
|
||||
|
||||
bool lv_gltf_data_has_cached_transform(lv_gltf_model_t * data, fastgltf::Node * node)
|
||||
bool lv_gltf_model_has_node_transform(lv_gltf_model_t * model, fastgltf::Node * node)
|
||||
{
|
||||
return (data->node_transform_cache.find(node) !=
|
||||
data->node_transform_cache.end());
|
||||
return model->transforms.find(node) !=
|
||||
model->transforms.end();
|
||||
}
|
||||
void lv_gltf_data_set_cached_transform(lv_gltf_model_t * data, fastgltf::Node * node,
|
||||
fastgltf::math::fmat4x4 M)
|
||||
void lv_gltf_model_set_transforms(lv_gltf_model_t * model, fastgltf::Node * node,
|
||||
fastgltf::math::fmat4x4 M)
|
||||
{
|
||||
data->node_transform_cache[node] = M;
|
||||
model->transforms[node] = M;
|
||||
model->transforms_changed = true;
|
||||
}
|
||||
void lv_gltf_data_clear_transform_cache(lv_gltf_model_t * data)
|
||||
void lv_gltf_model_clear_transforms(lv_gltf_model_t * model)
|
||||
{
|
||||
data->node_transform_cache.clear();
|
||||
model->transforms.clear();
|
||||
model->transforms_changed = true;
|
||||
}
|
||||
bool lv_gltf_data_transform_cache_is_empty(lv_gltf_model_t * data)
|
||||
bool lv_gltf_model_needs_transforms(lv_gltf_model_t * model)
|
||||
{
|
||||
return data->node_transform_cache.size() == 0;
|
||||
return model->transforms.size() == 0 || model->transforms_changed;
|
||||
}
|
||||
|
||||
|
||||
void recache_centerpoint(lv_gltf_model_t * data, size_t index_mesh, int32_t primitive)
|
||||
{
|
||||
data->local_mesh_to_center_points_by_primitive[index_mesh][primitive] =
|
||||
|
||||
@@ -81,7 +81,7 @@ static void injest_grow_bounds_to_include(lv_gltf_model_t * data, const fastgltf
|
||||
static void injest_set_initial_bounds(lv_gltf_model_t * data, const fastgltf::math::fmat4x4 & matrix,
|
||||
const fastgltf::Mesh & mesh);
|
||||
|
||||
static bool injest_image(lv_opengl_shader_manager_t * shader_manager, lv_gltf_model_t * data, fastgltf::Image & image,
|
||||
static bool injest_image(lv_gltf_model_loader_t * loader, lv_gltf_model_t * data, fastgltf::Image & image,
|
||||
uint32_t index);
|
||||
|
||||
static bool injest_image_from_buffer_view(lv_gltf_model_t * data, fastgltf::sources::BufferView & view,
|
||||
@@ -158,7 +158,7 @@ static void load_mesh_texture(lv_gltf_model_t * data,
|
||||
**********************/
|
||||
|
||||
lv_gltf_model_t * lv_gltf_data_load_internal(const void * data_source, size_t data_size,
|
||||
lv_opengl_shader_manager_t * shaders)
|
||||
lv_gltf_model_loader_t * loader)
|
||||
{
|
||||
lv_gltf_model_t * model = NULL;
|
||||
if(data_size > 0) {
|
||||
@@ -211,11 +211,23 @@ lv_gltf_model_t * lv_gltf_data_load_internal(const void * data_source, size_t da
|
||||
});
|
||||
|
||||
{
|
||||
bool owns_loader = loader == NULL;
|
||||
if(!loader) {
|
||||
loader = lv_gltf_model_loader_create();
|
||||
if(!loader) {
|
||||
LV_LOG_ERROR("Failed to create gltf model loader");
|
||||
lv_gltf_model_delete(model);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for(auto & image : model->asset.images) {
|
||||
injest_image(shaders, model, image, i);
|
||||
injest_image(loader, model, image, i);
|
||||
i++;
|
||||
}
|
||||
if(owns_loader) {
|
||||
lv_gltf_model_loader_delete(loader);
|
||||
}
|
||||
}
|
||||
uint16_t lightnum = 0;
|
||||
for(auto & light : model->asset.lights) {
|
||||
@@ -477,15 +489,16 @@ static void injest_set_initial_bounds(lv_gltf_model_t * data, const fastgltf::ma
|
||||
set_bounds_info(data, v_min, v_max, v_cen, radius);
|
||||
}
|
||||
|
||||
bool injest_image(lv_opengl_shader_manager_t * shader_manager, lv_gltf_model_t * data, fastgltf::Image & image,
|
||||
uint32_t index)
|
||||
static bool injest_image(lv_gltf_model_loader_t * loader, lv_gltf_model_t * data, fastgltf::Image & image,
|
||||
uint32_t index)
|
||||
{
|
||||
LV_ASSERT_NULL(loader);
|
||||
std::string _tex_id = std::string(lv_gltf_get_filename(data)) + "_IMG" + std::to_string(index);
|
||||
|
||||
char tmp[512];
|
||||
lv_snprintf(tmp, sizeof(tmp), "%s_img_%u", data->filename, index);
|
||||
const uint32_t hash = lv_opengl_shader_hash(tmp);
|
||||
GLuint texture_id = lv_opengl_shader_manager_get_texture(shader_manager, hash);
|
||||
GLuint texture_id = lv_gltf_model_loader_get_texture(loader, hash);
|
||||
|
||||
if(texture_id != GL_NONE) {
|
||||
LV_LOG_TRACE("Emplacing back already cached texture from previous injest iteration %u", texture_id);
|
||||
@@ -547,7 +560,7 @@ bool injest_image(lv_opengl_shader_manager_t * shader_manager, lv_gltf_model_t *
|
||||
LV_LOG_ERROR("Failed to load image %s", image.name.c_str());
|
||||
}
|
||||
LV_LOG_TRACE("Storing texture with hash: %u %u", hash, texture_id);
|
||||
lv_opengl_shader_manager_store_texture(shader_manager, hash, texture_id);
|
||||
lv_gltf_model_loader_store_texture(loader, hash, texture_id);
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
data->textures.emplace_back(texture_id);
|
||||
return true;
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
#ifndef LV_GLTFDATA_PRIVATE_H
|
||||
#define LV_GLTFDATA_PRIVATE_H
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GLTF
|
||||
#include "../../../drivers/opengles/opengl_shader/lv_opengl_shader_internal.h"
|
||||
#include "../../../draw/lv_image_dsc.h"
|
||||
#include "../../../misc/lv_types.h"
|
||||
#include "../../../misc/lv_array.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -177,6 +175,10 @@ typedef struct {
|
||||
|
||||
} lv_gltf_uniform_locations_t;
|
||||
|
||||
struct _lv_gltf_model_loader_t {
|
||||
lv_rb_t textures_map;
|
||||
};
|
||||
|
||||
lv_gltf_uniform_locations_t lv_gltf_uniform_locations_create(GLuint program);
|
||||
|
||||
typedef struct {
|
||||
@@ -187,31 +189,6 @@ typedef struct {
|
||||
void lv_gltf_store_compiled_shader(lv_gltf_model_t * data, size_t identifier, lv_gltf_compiled_shader_t * shader);
|
||||
lv_gltf_compiled_shader_t * lv_gltf_get_compiled_shader(lv_gltf_model_t * data, size_t identifier);
|
||||
|
||||
/**
|
||||
* @brief Load the gltf file at the specified filepath
|
||||
*
|
||||
* @param gltf_path The gltf filename
|
||||
* @param ret_data Pointer to the data container that will be populated.
|
||||
* @param shaders Pointer to the shader cache object this file uses.
|
||||
*/
|
||||
lv_gltf_model_t *
|
||||
lv_gltf_data_load_from_file(const char * file_path,
|
||||
lv_opengl_shader_manager_t * shader_manager);
|
||||
|
||||
/**
|
||||
* @brief Load the gltf file encoded within the supplied byte array
|
||||
*
|
||||
* @param gltf_path The gltf filename
|
||||
* @param gltf_data_size if gltf_path is instead a byte array, pass the size of that array in through this variable (or 0 if it's a file path).
|
||||
* @param ret_data Pointer to the data container that will be populated.
|
||||
* @param shaders Pointer to the shader cache object this file uses.
|
||||
*/
|
||||
|
||||
lv_gltf_model_t *
|
||||
lv_gltf_data_load_from_bytes(const uint8_t * data, size_t data_size,
|
||||
lv_opengl_shader_manager_t * shader_manager);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the radius of the GLTF data object.
|
||||
*
|
||||
@@ -221,13 +198,6 @@ lv_gltf_data_load_from_bytes(const uint8_t * data, size_t data_size,
|
||||
double lv_gltf_data_get_radius(const lv_gltf_model_t * model);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Destroy a GLTF data object and free associated resources.
|
||||
*
|
||||
* @param _data Pointer to the lv_gltf_data_t object to be destroyed.
|
||||
*/
|
||||
void lv_gltf_data_delete(lv_gltf_model_t * _data);
|
||||
|
||||
/**
|
||||
* @brief Copy the bounds information from one GLTF data object to another.
|
||||
*
|
||||
@@ -247,6 +217,10 @@ void lv_gltf_data_rgb_to_bgr(uint8_t * pixel_buffer,
|
||||
size_t byte_total_count,
|
||||
bool has_alpha);
|
||||
|
||||
lv_result_t lv_gltf_model_add_viewer(lv_gltf_model_t * model, lv_obj_t * viewer);
|
||||
void lv_gltf_model_remove_viewer(lv_gltf_model_t * model, lv_obj_t * target_viewer);
|
||||
void lv_gltf_model_invalidate(lv_gltf_model_t * model);
|
||||
|
||||
#endif /*LV_USE_GLTF*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
#include "../gltf_view/lv_gltf.h"
|
||||
#include "lv_gltf_data_internal.h"
|
||||
|
||||
#include "../../../misc/lv_array.h"
|
||||
#include "../../../drivers/opengles/lv_opengles_private.h"
|
||||
|
||||
#include "../../../misc/lv_types.h"
|
||||
#include "../../../misc/lv_ll.h"
|
||||
#include "../../../misc/lv_array.h"
|
||||
#include "../../../misc/lv_event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -43,8 +42,6 @@ using NodePairVector = std::vector<NodeIndexPair>;
|
||||
using NodeDistanceVector = std::vector<NodeIndexDistancePair>;
|
||||
// Map of uint32_t to NodePairVector
|
||||
using MaterialIndexMap = std::map<uint32_t, NodePairVector>;
|
||||
// Map of Node Pointers to Transforms
|
||||
using NodeTransformMap = std::map<NodePtr, Transform>;
|
||||
// Map of Nodes by string (name)
|
||||
using StringNodeMap = std::map<std::string, NodePtr>;
|
||||
// Map of Nodes by string (name)
|
||||
@@ -53,6 +50,10 @@ using NodeIntMap = std::map<NodePtr, uint32_t>;
|
||||
using NodeVector = std::vector<NodePtr>;
|
||||
// Map of Node Index to Map of Prim Index to CenterXYZ+RadiusW Vec4
|
||||
using NodePrimCenterMap = std::map<uint32_t, std::map<uint32_t, fastgltf::math::fvec4> >;
|
||||
// Map of Node Pointers to Transforms
|
||||
using NodeTransformMap = std::map<fastgltf::Node *, fastgltf::math::fmat4x4>;
|
||||
|
||||
using IbmBySkinThenNodeMap = std::map<int32_t, std::map<fastgltf::Node *, fastgltf::math::fmat4x4>>;
|
||||
|
||||
#define LV_GLTF_NODE_CHANNEL_X 0
|
||||
#define LV_GLTF_NODE_CHANNEL_Y 1
|
||||
@@ -105,13 +106,14 @@ struct _lv_gltf_model_t {
|
||||
fastgltf::Asset asset;
|
||||
lv_array_t nodes;
|
||||
NodeVector node_by_light_index;
|
||||
NodeTransformMap node_transform_cache;
|
||||
NodeTransformMap transforms;
|
||||
MaterialIndexMap opaque_nodes_by_material_index;
|
||||
MaterialIndexMap blended_nodes_by_material_index;
|
||||
IbmBySkinThenNodeMap ibm_by_skin_then_node;
|
||||
std::vector<size_t> validated_skins;
|
||||
std::vector<GLuint> skin_tex;
|
||||
NodePrimCenterMap local_mesh_to_center_points_by_primitive;
|
||||
lv_gltf_t * viewer;
|
||||
lv_array_t viewers;
|
||||
|
||||
std::vector<lv_gltf_mesh_data_t> meshes;
|
||||
std::vector<GLuint> textures;
|
||||
@@ -128,7 +130,7 @@ struct _lv_gltf_model_t {
|
||||
size_t current_animation;
|
||||
size_t last_material_index;
|
||||
|
||||
uint32_t last_camera_index;
|
||||
int32_t animation_speed_ratio;
|
||||
int32_t last_anim_num;
|
||||
|
||||
float bound_radius;
|
||||
@@ -138,11 +140,9 @@ struct _lv_gltf_model_t {
|
||||
uint32_t last_tick;
|
||||
uint32_t camera;
|
||||
|
||||
bool transforms_changed;
|
||||
bool is_animation_enabled;
|
||||
bool last_pass_was_transmission;
|
||||
bool last_frame_was_antialiased;
|
||||
bool last_frame_no_motion;
|
||||
bool _last_frame_no_motion;
|
||||
bool write_ops_pending;
|
||||
bool write_ops_flushed;
|
||||
struct _lv_gltf_model_t * linked_view_source;
|
||||
@@ -274,48 +274,6 @@ void lv_gltf_data_add_opaque_node_primitive(lv_gltf_model_t * data, size_t index
|
||||
void lv_gltf_data_add_blended_node_primitive(lv_gltf_model_t * data, size_t mesh_index, fastgltf::Node * node,
|
||||
size_t primitive_index);
|
||||
|
||||
/**
|
||||
* @brief Set the cached transformation matrix for a specific node in the GLTF model data.
|
||||
*
|
||||
* @param D Pointer to the lv_gltf_data_t object containing the model data.
|
||||
* @param N Pointer to the NodePtr representing the node for which to set the transformation.
|
||||
* @param M The transformation matrix to cache.
|
||||
*/
|
||||
void lv_gltf_data_set_cached_transform(lv_gltf_model_t * data, fastgltf::Node * node, fastgltf::math::fmat4x4 M);
|
||||
|
||||
/**
|
||||
* @brief Clear the transformation cache for the GLTF model data.
|
||||
*
|
||||
* @param D Pointer to the lv_gltf_data_t object containing the model data.
|
||||
*/
|
||||
void lv_gltf_data_clear_transform_cache(lv_gltf_model_t * data);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the cached transformation matrix for a specific node in the GLTF model data.
|
||||
*
|
||||
* @param D Pointer to the lv_gltf_data_t object containing the model data.
|
||||
* @param N Pointer to the NodePtr representing the node for which to retrieve the transformation.
|
||||
* @return The cached transformation matrix.
|
||||
*/
|
||||
fastgltf::math::fmat4x4 lv_gltf_data_get_cached_transform(lv_gltf_model_t * data, fastgltf::Node * node);
|
||||
|
||||
/**
|
||||
* @brief Check if a cached transformation matrix exists for a given node.
|
||||
*
|
||||
* @param D Pointer to the lv_gltf_data_t object containing the model data.
|
||||
* @param N Pointer to the NodePtr representing the node for which to retrieve the transformation.
|
||||
* @return true if a cache item exists, false otherwise
|
||||
int32_t*/
|
||||
bool lv_gltf_data_has_cached_transform(lv_gltf_model_t * data, fastgltf::Node * node);
|
||||
|
||||
/**
|
||||
* @brief Check if the transformation cache is empty.
|
||||
*
|
||||
* @param D Pointer to the lv_gltf_data_t object containing the model data.
|
||||
* @return True if the transformation cache is empty, false otherwise.
|
||||
*/
|
||||
bool lv_gltf_data_transform_cache_is_empty(lv_gltf_model_t * data);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the size of the skins in the GLTF model data.
|
||||
*
|
||||
@@ -361,7 +319,7 @@ lv_gltf_mesh_data_t * lv_gltf_get_new_meshdata(lv_gltf_model_t * _data);
|
||||
lv_gltf_model_t * lv_gltf_data_create_internal(const char * gltf_path, fastgltf::Asset);
|
||||
|
||||
lv_gltf_model_t * lv_gltf_data_load_internal(const void * data_source, size_t data_size,
|
||||
lv_opengl_shader_manager_t * shaders);
|
||||
lv_gltf_model_loader_t * loader);
|
||||
|
||||
fastgltf::math::fvec4 lv_gltf_get_primitive_centerpoint(lv_gltf_model_t * data, fastgltf::Mesh & mesh,
|
||||
uint32_t prim_num);
|
||||
@@ -405,6 +363,16 @@ lv_gltf_model_node_t * lv_gltf_model_node_get_by_internal_node(lv_gltf_model_t *
|
||||
|
||||
void lv_gltf_model_send_new_values(lv_gltf_model_t * model);
|
||||
|
||||
void lv_gltf_model_set_transforms(lv_gltf_model_t * model, fastgltf::Node * node, fastgltf::math::fmat4x4 M);
|
||||
|
||||
void lv_gltf_model_clear_transforms(lv_gltf_model_t * model);
|
||||
|
||||
fastgltf::math::fmat4x4 lv_gltf_data_get_node_transform(lv_gltf_model_t * model, fastgltf::Node * node);
|
||||
|
||||
bool lv_gltf_model_has_node_transform(lv_gltf_model_t * model, fastgltf::Node * node);
|
||||
|
||||
bool lv_gltf_model_needs_transforms(lv_gltf_model_t * model);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -7,10 +7,40 @@
|
||||
#include "lv_gltf_model_node.h"
|
||||
#include "../../../misc/lv_types.h"
|
||||
#include "../../../misc/lv_event.h"
|
||||
#include "lv_gltf_model_loader.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Load a glTF model from a file
|
||||
* @param file_path path to the glTF file to load
|
||||
* @param loader pointer to the glTF model loader instance, or NULL to create a new one
|
||||
* @return pointer to the loaded glTF model, or NULL on failure
|
||||
* @note If loader is NULL, an internal loader will be created and managed automatically
|
||||
*/
|
||||
lv_gltf_model_t * lv_gltf_data_load_from_file(const char * file_path,
|
||||
lv_gltf_model_loader_t * loader);
|
||||
|
||||
/**
|
||||
* Load a glTF model from a byte array
|
||||
* @param data pointer to the glTF data buffer
|
||||
* @param data_size size of the data buffer in bytes
|
||||
* @param loader pointer to the glTF model loader instance, or NULL to create a new one
|
||||
* @return pointer to the loaded glTF model, or NULL on failure
|
||||
* @note If loader is NULL, an internal loader will be created and managed automatically
|
||||
*/
|
||||
lv_gltf_model_t * lv_gltf_data_load_from_bytes(const uint8_t * data, size_t data_size,
|
||||
lv_gltf_model_loader_t * loader);
|
||||
|
||||
|
||||
/**
|
||||
* Delete a glTF model
|
||||
* @param model the gltf model to delete
|
||||
*/
|
||||
void lv_gltf_model_delete(lv_gltf_model_t * model);
|
||||
|
||||
/**
|
||||
* @brief Get the number of images in the glTF model
|
||||
*
|
||||
@@ -119,6 +149,27 @@ bool lv_gltf_model_is_animation_paused(lv_gltf_model_t * model);
|
||||
*/
|
||||
size_t lv_gltf_model_get_animation(lv_gltf_model_t * model);
|
||||
|
||||
/**
|
||||
* Set the animation speed ratio
|
||||
*
|
||||
* The actual ratio is the value parameter / LV_GLTF_ANIM_SPEED_NORMAL
|
||||
* Values greater than LV_GLTF_ANIM_SPEED_NORMAL will speed-up the animation
|
||||
* Values less than LV_GLTF_ANIM_SPEED_NORMAL will slow down the animation
|
||||
*
|
||||
* @param model pointer to a glTF model
|
||||
* @param value speed-up ratio of the animation
|
||||
*/
|
||||
void lv_gltf_model_set_animation_speed(lv_gltf_model_t * model, uint32_t value);
|
||||
|
||||
/**
|
||||
* Get the animation speed ratio
|
||||
*
|
||||
* The actual ratio is the return value / LV_GLTF_ANIM_SPEED_NORMAL
|
||||
*
|
||||
* @param model pointer to a glTF model
|
||||
*/
|
||||
uint32_t lv_gltf_model_get_animation_speed(const lv_gltf_model_t * model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
101
src/libs/gltf/gltf_data/lv_gltf_model_loader.c
Normal file
101
src/libs/gltf/gltf_data/lv_gltf_model_loader.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file lv_gltf_model_loader.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gltf_model_loader.h"
|
||||
#include "lv_gltf_data_internal.h"
|
||||
#if LV_USE_GLTF
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t id;
|
||||
} lv_opengl_texture_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static inline lv_rb_compare_res_t opengl_texture_compare_cb(const lv_opengl_texture_t * lhs,
|
||||
const lv_opengl_texture_t * rhs)
|
||||
{
|
||||
return lhs->hash - rhs->hash;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_gltf_model_loader_t * lv_gltf_model_loader_create(void)
|
||||
{
|
||||
lv_gltf_model_loader_t * loader = lv_zalloc(sizeof(*loader));
|
||||
if(!loader) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_rb_init(&loader->textures_map,
|
||||
(lv_rb_compare_t)opengl_texture_compare_cb,
|
||||
sizeof(lv_opengl_texture_t));
|
||||
return loader;
|
||||
}
|
||||
|
||||
void lv_gltf_model_loader_delete(lv_gltf_model_loader_t * loader)
|
||||
{
|
||||
if(!loader) {
|
||||
return;
|
||||
}
|
||||
lv_rb_destroy(&loader->textures_map);
|
||||
lv_free(loader);
|
||||
}
|
||||
|
||||
void lv_gltf_model_loader_store_texture(lv_gltf_model_loader_t * loader, uint32_t texture_hash, uint32_t texture_id)
|
||||
{
|
||||
lv_opengl_texture_t key = { .id = texture_id, .hash = texture_hash };
|
||||
lv_rb_node_t * node = lv_rb_insert(&loader->textures_map, &key);
|
||||
if(!node) {
|
||||
LV_LOG_WARN("Failed to cache texture hash: %d id: %d",
|
||||
texture_hash, texture_id);
|
||||
return;
|
||||
}
|
||||
lv_memcpy(node->data, &key, sizeof(key));
|
||||
}
|
||||
|
||||
|
||||
uint32_t lv_gltf_model_loader_get_texture(lv_gltf_model_loader_t * loader, uint32_t texture_hash)
|
||||
{
|
||||
lv_opengl_texture_t key = { .hash = texture_hash };
|
||||
lv_rb_node_t * node = lv_rb_find(&loader->textures_map, &key);
|
||||
if(!node) {
|
||||
LV_LOG_INFO("Couldn't find texture with hash %" LV_PRIu32 " in cache",
|
||||
texture_hash);
|
||||
return GL_NONE;
|
||||
}
|
||||
return ((lv_opengl_texture_t *)node->data)->id;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
#endif /*LV_USE_GLTF*/
|
||||
75
src/libs/gltf/gltf_data/lv_gltf_model_loader.h
Normal file
75
src/libs/gltf/gltf_data/lv_gltf_model_loader.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file lv_gltf_model_loader.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GLTF_MODEL_LOADER_H
|
||||
#define LV_GLTF_MODEL_LOADER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GLTF
|
||||
|
||||
#include "../../../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_gltf_model_loader_t lv_gltf_model_loader_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new glTF model loader instance
|
||||
* @return pointer to the newly created glTF model loader instance
|
||||
*/
|
||||
lv_gltf_model_loader_t * lv_gltf_model_loader_create(void);
|
||||
|
||||
/**
|
||||
* Store a texture ID associated with a texture hash in the loader
|
||||
* @param loader pointer to the glTF model loader instance
|
||||
* @param texture_hash hash value identifying the texture
|
||||
* @param texture_id the texture ID to associate with the hash
|
||||
*/
|
||||
void lv_gltf_model_loader_store_texture(lv_gltf_model_loader_t * loader, uint32_t texture_hash, uint32_t texture_id);
|
||||
|
||||
/**
|
||||
* Retrieve a texture ID by its hash from the loader
|
||||
* @param loader pointer to the glTF model loader instance
|
||||
* @param texture_hash hash value of the texture to retrieve
|
||||
* @return the texture ID associated with the hash, or 0 if not found
|
||||
*/
|
||||
uint32_t lv_gltf_model_loader_get_texture(lv_gltf_model_loader_t * loader, uint32_t texture_hash);
|
||||
|
||||
/**
|
||||
* Delete a glTF model loader instance and free its resources
|
||||
* @param loader pointer to the glTF model loader instance to delete
|
||||
*/
|
||||
void lv_gltf_model_loader_delete(lv_gltf_model_loader_t * loader);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GLTF*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GLTF_MODEL_LOADER_H*/
|
||||
@@ -12,14 +12,12 @@
|
||||
|
||||
#include <float.h>
|
||||
#include "fastgltf/types.hpp"
|
||||
#include "lv_gltf_model.h"
|
||||
#include "../../../misc/lv_array.h"
|
||||
#include "../../../misc/lv_assert.h"
|
||||
#include "../../../misc/lv_types.h"
|
||||
#include "../../../misc/lv_event_private.h"
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
#include "../../../stdlib/lv_sprintf.h"
|
||||
#include "../../../core/lv_obj_pos.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -170,6 +168,7 @@ void lv_gltf_model_send_new_values(lv_gltf_model_t * model)
|
||||
node->read_attrs->value_changed = false;
|
||||
}
|
||||
model->write_ops_flushed = false;
|
||||
model->transforms_changed = false;
|
||||
}
|
||||
|
||||
lv_event_dsc_t * lv_gltf_model_node_add_event_cb(lv_gltf_model_node_t * node, lv_event_cb_t cb,
|
||||
@@ -335,7 +334,7 @@ lv_result_t lv_gltf_model_node_get_euler_rotation(lv_event_t * e, lv_3dpoint_t *
|
||||
|
||||
static void invalidate_model(lv_gltf_model_t * model)
|
||||
{
|
||||
lv_obj_invalidate((lv_obj_t *)model->viewer);
|
||||
lv_gltf_model_invalidate(model);
|
||||
model->write_ops_pending = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,15 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_GLTF_ANIM_SPEED_TENTH 100
|
||||
#define LV_GLTF_ANIM_SPEED_QUARTER 250
|
||||
#define LV_GLTF_ANIM_SPEED_HALF 500
|
||||
#define LV_GLTF_ANIM_SPEED_NORMAL 1000
|
||||
#define LV_GLTF_ANIM_SPEED_2X 2000
|
||||
#define LV_GLTF_ANIM_SPEED_3X 3000
|
||||
#define LV_GLTF_ANIM_SPEED_4X 4000
|
||||
#define LV_GLTF_DEFAULT_CAMERA 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
@@ -27,15 +27,6 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_GLTF_ANIM_SPEED_TENTH 100
|
||||
#define LV_GLTF_ANIM_SPEED_QUARTER 250
|
||||
#define LV_GLTF_ANIM_SPEED_HALF 500
|
||||
#define LV_GLTF_ANIM_SPEED_NORMAL 1000
|
||||
#define LV_GLTF_ANIM_SPEED_2X 2000
|
||||
#define LV_GLTF_ANIM_SPEED_3X 3000
|
||||
#define LV_GLTF_ANIM_SPEED_4X 4000
|
||||
#define LV_GLTF_DEFAULT_CAMERA 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -90,6 +81,19 @@ lv_gltf_model_t * lv_gltf_load_model_from_file(lv_obj_t * obj, const char * path
|
||||
*/
|
||||
lv_gltf_model_t * lv_gltf_load_model_from_bytes(lv_obj_t * obj, const uint8_t * bytes, size_t len);
|
||||
|
||||
/**
|
||||
* Add a glTF model to the viewer.
|
||||
*
|
||||
* Contrary to `lv_gltf_load_model_from_file` and `lv_gltf_load_model_from_bytes`, the model
|
||||
* is owned by the caller of this function meaning that it's the caller's responsibility
|
||||
* to delete the model when it is no longer needed, that is, the model must outlive the viewer's lifetime.
|
||||
*
|
||||
* @param obj pointer to a glTF viewer object
|
||||
* @param model glTF model to add to the viewer
|
||||
* @return LV_RESULT_OK if the model was added to the viewer or LV_RESULT_INVALID on failure
|
||||
*/
|
||||
lv_result_t lv_gltf_add_model(lv_obj_t * obj, lv_gltf_model_t * model);
|
||||
|
||||
/**
|
||||
* Get the number of models loaded in the glTF viewer
|
||||
* @param obj pointer to a glTF viewer object
|
||||
@@ -103,7 +107,7 @@ size_t lv_gltf_get_model_count(lv_obj_t * obj);
|
||||
* @param id index of the model to retrieve (0-based)
|
||||
* @return pointer to the model at the specified index, or NULL if index is invalid
|
||||
*/
|
||||
lv_gltf_model_t * lv_gltf_get_model_by_index(lv_obj_t * obj, size_t id);
|
||||
lv_gltf_model_t * lv_gltf_get_model_by_index(const lv_obj_t * obj, size_t id);
|
||||
|
||||
/**
|
||||
* Get the primary model from the glTF viewer
|
||||
@@ -112,7 +116,7 @@ lv_gltf_model_t * lv_gltf_get_model_by_index(lv_obj_t * obj, size_t id);
|
||||
* @param obj pointer to a glTF viewer object
|
||||
* @return pointer to the primary model, or NULL if no models are loaded
|
||||
*/
|
||||
lv_gltf_model_t * lv_gltf_get_primary_model(lv_obj_t * obj);
|
||||
lv_gltf_model_t * lv_gltf_get_primary_model(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the yaw (horizontal rotation) of the camera
|
||||
@@ -269,6 +273,8 @@ uint32_t lv_gltf_get_camera(const lv_obj_t * obj);
|
||||
uint32_t lv_gltf_get_camera_count(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* DEPRECATED. See `lv_gltf_model_set_animation_speed`
|
||||
*
|
||||
* Set the animation speed ratio
|
||||
*
|
||||
* The actual ratio is the value parameter / LV_GLTF_ANIM_SPEED_NORMAL
|
||||
@@ -281,6 +287,8 @@ uint32_t lv_gltf_get_camera_count(const lv_obj_t * obj);
|
||||
void lv_gltf_set_animation_speed(lv_obj_t * obj, uint32_t value);
|
||||
|
||||
/**
|
||||
* DEPRECATED. See `lv_gltf_model_get_animation_speed`
|
||||
*
|
||||
* Get the animation speed ratio
|
||||
*
|
||||
* The actual ratio is the return value / LV_GLTF_ANIM_SPEED_NORMAL
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "../gltf_data/lv_gltf_model.h"
|
||||
#include "../gltf_data/lv_gltf_data_internal.hpp"
|
||||
#include "../gltf_data/lv_gltf_data_internal.h"
|
||||
#include "../../../draw/lv_draw_3d.h"
|
||||
#include "../fastgltf/lv_fastgltf.hpp"
|
||||
#include "../../../core/lv_obj_class_private.h"
|
||||
@@ -42,7 +43,7 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static lv_gltf_model_t * lv_gltf_add_model(lv_gltf_t * viewer, lv_gltf_model_t * model);
|
||||
static lv_gltf_model_t * add_model(lv_gltf_t * viewer, lv_gltf_model_t * model, bool owned);
|
||||
static void lv_gltf_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_gltf_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_gltf_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
@@ -120,8 +121,8 @@ lv_gltf_model_t * lv_gltf_load_model_from_file(lv_obj_t * obj, const char * path
|
||||
}
|
||||
}
|
||||
|
||||
lv_gltf_model_t * model = lv_gltf_data_load_from_file(path, &viewer->shader_manager);
|
||||
return lv_gltf_add_model(viewer, model);
|
||||
lv_gltf_model_t * model = lv_gltf_data_load_from_file(path, viewer->model_loader);
|
||||
return add_model(viewer, model, true);
|
||||
}
|
||||
|
||||
lv_gltf_model_t * lv_gltf_load_model_from_bytes(lv_obj_t * obj, const uint8_t * bytes, size_t len)
|
||||
@@ -137,9 +138,28 @@ lv_gltf_model_t * lv_gltf_load_model_from_bytes(lv_obj_t * obj, const uint8_t *
|
||||
}
|
||||
}
|
||||
|
||||
lv_gltf_model_t * model = lv_gltf_data_load_from_bytes(bytes, len, &viewer->shader_manager);
|
||||
return lv_gltf_add_model(viewer, model);
|
||||
lv_gltf_model_t * model = lv_gltf_data_load_from_bytes(bytes, len, viewer->model_loader);
|
||||
return add_model(viewer, model, true);
|
||||
}
|
||||
|
||||
lv_result_t lv_gltf_add_model(lv_obj_t * obj, lv_gltf_model_t * model)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(!model) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
|
||||
if(!viewer->environment) {
|
||||
lv_result_t res = create_default_environment(viewer);
|
||||
if(res != LV_RESULT_OK) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
}
|
||||
return add_model(viewer, model, false) != NULL ? LV_RESULT_OK : LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
void lv_gltf_set_environment(lv_obj_t * obj, lv_gltf_environment_t * env)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
@@ -159,34 +179,31 @@ void lv_gltf_set_environment(lv_obj_t * obj, lv_gltf_environment_t * env)
|
||||
|
||||
size_t lv_gltf_get_model_count(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return lv_array_size(&((lv_gltf_t *)obj)->models);
|
||||
}
|
||||
|
||||
lv_gltf_model_t * lv_gltf_get_model_by_index(lv_obj_t * obj, size_t id)
|
||||
lv_gltf_model_t * lv_gltf_get_model_by_index(const lv_obj_t * obj, size_t id)
|
||||
{
|
||||
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *) obj;
|
||||
|
||||
if(id >= lv_array_size(&viewer->models)) {
|
||||
return NULL;
|
||||
}
|
||||
return *(lv_gltf_model_t **)lv_array_at(&((lv_gltf_t *)obj)->models, id);
|
||||
lv_gltf_model_data_t * modeld = *(lv_gltf_model_data_t **)lv_array_at(&((lv_gltf_t *)obj)->models, id);
|
||||
LV_ASSERT_NULL(modeld);
|
||||
return modeld->model;
|
||||
|
||||
}
|
||||
lv_gltf_model_t * lv_gltf_get_primary_model(lv_obj_t * obj)
|
||||
lv_gltf_model_t * lv_gltf_get_primary_model(const lv_obj_t * obj)
|
||||
{
|
||||
|
||||
return lv_gltf_get_model_by_index(obj, 0);
|
||||
}
|
||||
|
||||
void lv_gltf_set_yaw(lv_obj_t * obj, float yaw)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.yaw = yaw;
|
||||
@@ -195,7 +212,6 @@ void lv_gltf_set_yaw(lv_obj_t * obj, float yaw)
|
||||
|
||||
float lv_gltf_get_yaw(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.yaw;
|
||||
@@ -203,7 +219,6 @@ float lv_gltf_get_yaw(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_pitch(lv_obj_t * obj, float pitch)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.pitch = pitch;
|
||||
@@ -212,7 +227,6 @@ void lv_gltf_set_pitch(lv_obj_t * obj, float pitch)
|
||||
|
||||
float lv_gltf_get_pitch(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.pitch;
|
||||
@@ -220,7 +234,6 @@ float lv_gltf_get_pitch(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_fov(lv_obj_t * obj, float value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.fov = value;
|
||||
@@ -229,7 +242,6 @@ void lv_gltf_set_fov(lv_obj_t * obj, float value)
|
||||
|
||||
float lv_gltf_get_fov(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.fov;
|
||||
@@ -237,7 +249,6 @@ float lv_gltf_get_fov(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_distance(lv_obj_t * obj, float value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.distance = value;
|
||||
@@ -246,7 +257,6 @@ void lv_gltf_set_distance(lv_obj_t * obj, float value)
|
||||
|
||||
float lv_gltf_get_distance(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.distance;
|
||||
@@ -254,37 +264,41 @@ float lv_gltf_get_distance(const lv_obj_t * obj)
|
||||
|
||||
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);
|
||||
lv_gltf_model_data_t * modeld = *(lv_gltf_model_data_t **)lv_array_at(&viewer->models, 0);
|
||||
lv_gltf_model_t * model = modeld->model;
|
||||
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);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.animation_speed_ratio = value;
|
||||
lv_obj_invalidate(obj);
|
||||
LV_LOG_WARN("Deprecated. lv_gltf_set_animation_speed should now be set on the model directly via `lv_gltf_model_set_animation_speed`. Setting it on the main model as a fallback");
|
||||
lv_gltf_model_t * model = lv_gltf_get_primary_model(obj);
|
||||
if(!model) {
|
||||
return;
|
||||
}
|
||||
lv_gltf_model_set_animation_speed(model, value);
|
||||
}
|
||||
|
||||
uint32_t lv_gltf_get_animation_speed(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.animation_speed_ratio;
|
||||
LV_LOG_WARN("Deprecated. lv_gltf_get_animation_speed should now be called on the model directly via `lv_gltf_model_get_animation_speed`. Getting the animation speed from the main model as a fallback");
|
||||
lv_gltf_model_t * model = lv_gltf_get_primary_model(obj);
|
||||
if(!model) {
|
||||
return 0;
|
||||
}
|
||||
return lv_gltf_model_get_animation_speed(model);
|
||||
}
|
||||
|
||||
void lv_gltf_set_focal_x(lv_obj_t * obj, float value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.focal_x = value;
|
||||
@@ -293,7 +307,6 @@ void lv_gltf_set_focal_x(lv_obj_t * obj, float value)
|
||||
|
||||
float lv_gltf_get_focal_x(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.focal_x;
|
||||
@@ -301,7 +314,6 @@ float lv_gltf_get_focal_x(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_focal_y(lv_obj_t * obj, float value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.focal_y = value;
|
||||
@@ -310,7 +322,6 @@ void lv_gltf_set_focal_y(lv_obj_t * obj, float value)
|
||||
|
||||
float lv_gltf_get_focal_y(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.focal_y;
|
||||
@@ -318,7 +329,6 @@ float lv_gltf_get_focal_y(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_focal_z(lv_obj_t * obj, float value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.focal_z = value;
|
||||
@@ -327,7 +337,6 @@ void lv_gltf_set_focal_z(lv_obj_t * obj, float value)
|
||||
|
||||
float lv_gltf_get_focal_z(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.focal_z;
|
||||
@@ -335,7 +344,6 @@ float lv_gltf_get_focal_z(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_camera(lv_obj_t * obj, uint32_t value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
|
||||
@@ -343,7 +351,8 @@ void lv_gltf_set_camera(lv_obj_t * obj, uint32_t value)
|
||||
return;
|
||||
}
|
||||
|
||||
lv_gltf_model_t * model = *(lv_gltf_model_t **) lv_array_at(&viewer->models, 0);
|
||||
lv_gltf_model_data_t * modeld = *(lv_gltf_model_data_t **)lv_array_at(&viewer->models, 0);
|
||||
lv_gltf_model_t * model = modeld->model;
|
||||
|
||||
if(value > model->asset.cameras.size()) {
|
||||
return;
|
||||
@@ -355,7 +364,6 @@ void lv_gltf_set_camera(lv_obj_t * obj, uint32_t value)
|
||||
|
||||
uint32_t lv_gltf_get_camera(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
|
||||
@@ -369,7 +377,6 @@ uint32_t lv_gltf_get_camera(const lv_obj_t * obj)
|
||||
uint32_t lv_gltf_get_camera_count(const lv_obj_t * obj)
|
||||
{
|
||||
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
|
||||
@@ -382,7 +389,6 @@ uint32_t lv_gltf_get_camera_count(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_antialiasing_mode(lv_obj_t * obj, lv_gltf_aa_mode_t value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.aa_mode = value;
|
||||
@@ -391,7 +397,6 @@ 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)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.aa_mode;
|
||||
@@ -399,7 +404,6 @@ lv_gltf_aa_mode_t lv_gltf_get_antialiasing_mode(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_background_mode(lv_obj_t * obj, lv_gltf_bg_mode_t value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.bg_mode = value;
|
||||
@@ -408,7 +412,6 @@ void lv_gltf_set_background_mode(lv_obj_t * obj, lv_gltf_bg_mode_t value)
|
||||
|
||||
lv_gltf_bg_mode_t lv_gltf_get_background_mode(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.bg_mode;
|
||||
@@ -416,7 +419,6 @@ lv_gltf_bg_mode_t lv_gltf_get_background_mode(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_background_blur(lv_obj_t * obj, uint32_t value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
if(value > 100) {
|
||||
@@ -428,7 +430,6 @@ void lv_gltf_set_background_blur(lv_obj_t * obj, uint32_t value)
|
||||
|
||||
uint32_t lv_gltf_get_background_blur(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.blur_bg * 100;
|
||||
@@ -436,7 +437,6 @@ uint32_t lv_gltf_get_background_blur(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_env_brightness(lv_obj_t * obj, uint32_t value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.env_pow = value / 100.;
|
||||
@@ -445,7 +445,6 @@ void lv_gltf_set_env_brightness(lv_obj_t * obj, uint32_t value)
|
||||
|
||||
uint32_t lv_gltf_get_env_brightness(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.env_pow * 100;
|
||||
@@ -453,7 +452,6 @@ uint32_t lv_gltf_get_env_brightness(const lv_obj_t * obj)
|
||||
|
||||
void lv_gltf_set_image_exposure(lv_obj_t * obj, float value)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
viewer->desc.exposure = value;
|
||||
@@ -462,14 +460,12 @@ void lv_gltf_set_image_exposure(lv_obj_t * obj, float value)
|
||||
|
||||
float lv_gltf_get_image_exposure(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
return viewer->desc.exposure;
|
||||
}
|
||||
void lv_gltf_recenter(lv_obj_t * obj, lv_gltf_model_t * model)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_gltf_t * viewer = (lv_gltf_t *)obj;
|
||||
if(model == NULL) {
|
||||
@@ -485,7 +481,6 @@ void lv_gltf_recenter(lv_obj_t * obj, lv_gltf_model_t * model)
|
||||
|
||||
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;
|
||||
|
||||
@@ -542,7 +537,6 @@ lv_result_t lv_intersect_ray_with_plane(const lv_3dray_t * ray, const lv_3dplane
|
||||
|
||||
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, 0, 0}, {0, 0, 0}};
|
||||
@@ -561,7 +555,6 @@ lv_3dplane_t lv_gltf_get_current_view_plane(lv_obj_t * obj, float distance)
|
||||
|
||||
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;
|
||||
|
||||
@@ -589,19 +582,32 @@ lv_result_t lv_gltf_world_to_screen(lv_obj_t * obj, const lv_3dpoint_t world_pos
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_gltf_model_t * lv_gltf_add_model(lv_gltf_t * viewer, lv_gltf_model_t * model)
|
||||
static lv_gltf_model_t * add_model(lv_gltf_t * viewer, lv_gltf_model_t * model, bool owned)
|
||||
{
|
||||
if(!model) {
|
||||
return NULL;
|
||||
}
|
||||
if(lv_array_push_back(&viewer->models, &model) == LV_RESULT_INVALID) {
|
||||
lv_gltf_data_delete(model);
|
||||
lv_gltf_model_data_t model_data;
|
||||
lv_memset(&model_data, 0, sizeof(model_data));
|
||||
model_data.model = model;
|
||||
model_data.owned = owned;
|
||||
lv_array_init(&model_data.skin_textures, 0, sizeof(GLuint));
|
||||
|
||||
if(lv_array_push_back(&viewer->models, &model_data) != LV_RESULT_OK) {
|
||||
if(owned) {
|
||||
lv_gltf_model_delete(model);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if(lv_gltf_model_add_viewer(model, (lv_obj_t *)viewer) != LV_RESULT_OK) {
|
||||
if(owned) {
|
||||
lv_gltf_model_delete(model);
|
||||
}
|
||||
lv_array_remove(&viewer->models, lv_array_size(&viewer->models) - 1);
|
||||
return NULL;
|
||||
}
|
||||
model->viewer = viewer;
|
||||
lv_gltf_parse_model(viewer, model);
|
||||
|
||||
|
||||
if(lv_array_size(&viewer->models) == 1) {
|
||||
lv_gltf_recenter((lv_obj_t *)viewer, model);
|
||||
}
|
||||
@@ -635,8 +641,6 @@ static void lv_gltf_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
view->camera_pos = fastgltf::math::fvec3(0.0f);
|
||||
view->texture.h_flip = false;
|
||||
view->texture.v_flip = true;
|
||||
new(&view->ibm_by_skin_then_node) std::map<int32_t, std::map<fastgltf::Node *, fastgltf::math::fmat4x4>>;
|
||||
|
||||
lv_opengl_shader_portions_t portions;
|
||||
lv_gltf_view_shader_get_src(&portions);
|
||||
char * vertex_shader = lv_gltf_view_shader_get_vertex();
|
||||
@@ -645,7 +649,9 @@ static void lv_gltf_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
lv_free(vertex_shader);
|
||||
lv_free(frag_shader);
|
||||
|
||||
lv_array_init(&view->models, LV_GLTF_INITIAL_MODEL_CAPACITY, sizeof(lv_gltf_model_t *));
|
||||
view->model_loader = lv_gltf_model_loader_create();
|
||||
|
||||
lv_array_init(&view->models, LV_GLTF_INITIAL_MODEL_CAPACITY, sizeof(lv_gltf_model_data_t));
|
||||
|
||||
LV_TRACE_OBJ_CREATE("end");
|
||||
}
|
||||
@@ -675,17 +681,22 @@ static void lv_gltf_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
LV_UNUSED(class_p);
|
||||
lv_gltf_t * view = (lv_gltf_t *)obj;
|
||||
lv_opengl_shader_manager_deinit(&view->shader_manager);
|
||||
using IbmBySkinThenNodeMap = std::map<int32_t, std::map<fastgltf::Node *, fastgltf::math::fmat4x4>>;
|
||||
|
||||
view->ibm_by_skin_then_node.~IbmBySkinThenNodeMap();
|
||||
const size_t n = lv_array_size(&view->models);
|
||||
for(size_t i = 0; i < n; ++i) {
|
||||
lv_gltf_data_delete(*(lv_gltf_model_t **)lv_array_at(&view->models, i));
|
||||
lv_gltf_model_data_t * model_data = (lv_gltf_model_data_t *)lv_array_at(&view->models, i);
|
||||
if(model_data->owned) {
|
||||
lv_gltf_model_delete(model_data->model);
|
||||
}
|
||||
else {
|
||||
lv_gltf_model_remove_viewer(model_data->model, obj);
|
||||
}
|
||||
}
|
||||
lv_array_deinit(&view->models);
|
||||
if(view->environment && view->owns_environment) {
|
||||
lv_gltf_environment_delete(view->environment);
|
||||
}
|
||||
lv_gltf_model_loader_delete(view->model_loader);
|
||||
lv_display_t * disp = lv_obj_get_display(obj);
|
||||
LV_ASSERT_NULL(disp);
|
||||
lv_display_remove_event_cb_with_user_data(disp, display_refr_end_event_cb, obj);
|
||||
@@ -710,7 +721,6 @@ static void lv_gltf_view_desc_init(lv_gltf_view_desc_t * desc)
|
||||
desc->bg_mode = LV_GLTF_BG_MODE_ENVIRONMENT;
|
||||
desc->aa_mode = LV_GLTF_AA_MODE_OFF;
|
||||
desc->fov = 45.f;
|
||||
desc->animation_speed_ratio = LV_GLTF_ANIM_SPEED_NORMAL;
|
||||
desc->frame_was_antialiased = false;
|
||||
}
|
||||
static void lv_gltf_parse_model(lv_gltf_t * viewer, lv_gltf_model_t * model)
|
||||
@@ -734,7 +744,7 @@ static void lv_gltf_parse_model(lv_gltf_t * viewer, lv_gltf_model_t * model)
|
||||
model->asset, ibm_accessor,
|
||||
[&](fastgltf::math::fmat4x4 _matrix, std::size_t idx) {
|
||||
auto & joint_node = model->asset.nodes[skin.joints[idx]];
|
||||
viewer->ibm_by_skin_then_node[skin_index][&joint_node] = _matrix;
|
||||
model->ibm_by_skin_then_node[skin_index][&joint_node] = _matrix;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -856,8 +866,9 @@ static void display_refr_end_event_cb(lv_event_t * e)
|
||||
lv_gltf_t * viewer = (lv_gltf_t *) lv_event_get_user_data(e);
|
||||
uint32_t model_count = lv_array_size(&viewer->models);
|
||||
for(uint32_t i = 0; i < model_count; ++i) {
|
||||
lv_gltf_model_t * model = *(lv_gltf_model_t **)lv_array_at(&viewer->models, i);
|
||||
lv_gltf_model_send_new_values(model);
|
||||
lv_gltf_model_data_t * modeld = *(lv_gltf_model_data_t **)lv_array_at(&viewer->models, i);
|
||||
lv_gltf_model_send_new_values(modeld->model);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GLTF*/
|
||||
|
||||
@@ -95,7 +95,6 @@ typedef struct {
|
||||
float focal_y;
|
||||
float focal_z;
|
||||
bool frame_was_antialiased;
|
||||
int32_t animation_speed_ratio;
|
||||
lv_gltf_aa_mode_t aa_mode;
|
||||
lv_gltf_bg_mode_t bg_mode;
|
||||
float blur_bg; /** How much to blur the environment background, between 0.0 and 1.0 */
|
||||
@@ -156,6 +155,17 @@ typedef struct {
|
||||
#include <fastgltf/types.hpp>
|
||||
#include <map>
|
||||
|
||||
typedef struct {
|
||||
lv_gltf_model_t * model;
|
||||
lv_array_t skin_textures;
|
||||
uint32_t last_camera_index;
|
||||
bool owned;
|
||||
bool last_frame_was_antialiased;
|
||||
bool last_frame_no_motion;
|
||||
bool _last_frame_no_motion;
|
||||
} lv_gltf_model_data_t;
|
||||
|
||||
|
||||
struct _lv_gltf_t {
|
||||
lv_3dtexture_t texture;
|
||||
lv_array_t models;
|
||||
@@ -163,13 +173,13 @@ struct _lv_gltf_t {
|
||||
lv_gltf_view_desc_t desc;
|
||||
lv_gltf_view_desc_t last_desc;
|
||||
lv_opengl_shader_manager_t shader_manager;
|
||||
lv_gltf_model_loader_t * model_loader;
|
||||
lv_gltf_environment_t * environment;
|
||||
fastgltf::math::fmat4x4 view_matrix;
|
||||
fastgltf::math::fmat4x4 projection_matrix;
|
||||
fastgltf::math::fmat4x4 view_projection_matrix;
|
||||
fastgltf::math::fvec3 camera_pos;
|
||||
|
||||
std::map<int32_t, std::map<fastgltf::Node *, fastgltf::math::fmat4x4>> ibm_by_skin_then_node;
|
||||
bool owns_environment;
|
||||
};
|
||||
|
||||
|
||||
@@ -72,18 +72,19 @@ struct lv_gltf_matrices_saver_t {
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * model, bool prepare_bg, bool dirty);
|
||||
static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, bool is_first_model,
|
||||
bool dirty);
|
||||
static void lv_gltf_view_push_opengl_state(lv_opengl_state_t * state);
|
||||
static void lv_gltf_view_pop_opengl_state(const lv_opengl_state_t * state);
|
||||
static void setup_finish_frame(void);
|
||||
static void render_materials(lv_gltf_t * viewer, lv_gltf_model_t * gltf_data, const MaterialIndexMap & map,
|
||||
static void render_materials(lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, const MaterialIndexMap & map,
|
||||
bool is_transmission_pass);
|
||||
static void render_skins(lv_gltf_t * viewer, lv_gltf_model_t * gltf_data);
|
||||
static void render_skins(lv_gltf_t * viewer, lv_gltf_model_data_t * modeld);
|
||||
static lv_result_t render_primary_output(lv_gltf_t * viewer, const lv_gltf_renwin_state_t * state,
|
||||
int32_t texture_w,
|
||||
int32_t texture_h, bool prepare_bg);
|
||||
|
||||
static void lv_gltf_view_recache_all_transforms(lv_gltf_model_t * gltf_data);
|
||||
static void lv_gltf_view_recache_all_transforms(lv_gltf_model_data_t * gltf_data);
|
||||
static fastgltf::math::fmat3x3 create_texture_transform_matrix(std::unique_ptr<fastgltf::TextureTransform> & transform);
|
||||
static fastgltf::math::nvec4 color_convert_to_srgb(fastgltf::math::nvec4 color);
|
||||
static void render_uniform_color_alpha(GLint uniform_loc, fastgltf::math::nvec4 color);
|
||||
@@ -91,20 +92,20 @@ static void render_uniform_color(GLint uniform_loc, fastgltf::math::nvec3 color)
|
||||
static uint32_t render_texture(uint32_t tex_unit, uint32_t tex_name, int32_t tex_coord_index,
|
||||
std::unique_ptr<fastgltf::TextureTransform> & tex_transform, GLint sampler, GLint uv_set,
|
||||
GLint uv_transform);
|
||||
static void draw_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_t * gltf_data, fastgltf::Node & node,
|
||||
static void draw_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, fastgltf::Node & node,
|
||||
std::size_t mesh_index, const fastgltf::math::fmat4x4 & matrix,
|
||||
const lv_gltf_environment_t * env_tex, bool is_transmission_pass);
|
||||
|
||||
static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_t * gltf_data,
|
||||
fastgltf::Node & node,
|
||||
static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, fastgltf::Node & node,
|
||||
std::size_t mesh_index, const fastgltf::math::fmat4x4 & matrix,
|
||||
const lv_gltf_environment_t * env_tex, bool is_transmission_pass);
|
||||
|
||||
static bool draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t * uniforms, lv_gltf_model_t * model,
|
||||
static bool draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t * uniforms,
|
||||
lv_gltf_model_data_t * modeld,
|
||||
lv_gltf_primitive_t * _prim_data, size_t materialIndex, bool is_transmission_pass, GLuint program,
|
||||
uint32_t * tex_num);
|
||||
|
||||
static void draw_lights(lv_gltf_model_t * model, GLuint program);
|
||||
static void draw_lights(lv_gltf_model_data_t * modeld, GLuint program);
|
||||
|
||||
static lv_gltf_renwin_state_t setup_opaque_output(uint32_t texture_width, uint32_t texture_height);
|
||||
static void setup_cleanup_opengl_output(lv_gltf_renwin_state_t * state);
|
||||
@@ -141,20 +142,20 @@ GLuint lv_gltf_view_render(lv_gltf_t * viewer)
|
||||
if(n == 0) {
|
||||
return GL_NONE;
|
||||
}
|
||||
lv_gltf_model_t * model = *(lv_gltf_model_t **)lv_array_at(&viewer->models, 0);
|
||||
lv_gltf_model_data_t * model_data = (lv_gltf_model_data_t *)lv_array_at(&viewer->models, 0);
|
||||
|
||||
bool dirty = lv_memcmp(&viewer->last_desc, &viewer->desc, sizeof(viewer->desc)) != 0;
|
||||
|
||||
for(size_t i = 0; i < n; ++i) {
|
||||
lv_gltf_model_t * model = *(lv_gltf_model_t **)lv_array_at(&viewer->models, i);
|
||||
dirty |= model->is_animation_enabled || model->write_ops_pending;
|
||||
lv_gltf_model_data_t * model_data = (lv_gltf_model_data_t *)lv_array_at(&viewer->models, i);
|
||||
dirty |= model_data->model->is_animation_enabled || model_data->model->write_ops_pending;
|
||||
}
|
||||
|
||||
GLuint texture_id = GL_NONE;
|
||||
texture_id = lv_gltf_view_render_model(viewer, model, true, dirty);
|
||||
texture_id = lv_gltf_view_render_model(viewer, model_data, true, dirty);
|
||||
for(size_t i = 1; i < n; ++i) {
|
||||
lv_gltf_model_t * model = *(lv_gltf_model_t **)lv_array_at(&viewer->models, i);
|
||||
lv_gltf_view_render_model(viewer, model, false, dirty);
|
||||
lv_gltf_model_data_t * model_data = (lv_gltf_model_data_t *)lv_array_at(&viewer->models, i);
|
||||
lv_gltf_view_render_model(viewer, model_data, false, dirty);
|
||||
}
|
||||
|
||||
lv_memcpy(&(viewer->last_desc), &viewer->desc, sizeof(viewer->desc));
|
||||
@@ -285,13 +286,14 @@ static void lv_gltf_view_pop_opengl_state(const lv_opengl_state_t * state)
|
||||
GL_CALL(glClearDepthf(state->clear_depth));
|
||||
}
|
||||
|
||||
static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * model, bool is_first_model, bool dirty)
|
||||
static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, bool is_first_model,
|
||||
bool dirty)
|
||||
{
|
||||
lv_gltf_view_state_t * vstate = &viewer->state;
|
||||
lv_gltf_view_desc_t * view_desc = &viewer->desc;
|
||||
bool opt_draw_bg = is_first_model && (view_desc->bg_mode == LV_GLTF_BG_MODE_ENVIRONMENT);
|
||||
bool opt_aa_this_frame = (view_desc->aa_mode == LV_GLTF_AA_MODE_ON) ||
|
||||
(view_desc->aa_mode == LV_GLTF_AA_MODE_DYNAMIC && model->last_frame_no_motion == true);
|
||||
(view_desc->aa_mode == LV_GLTF_AA_MODE_DYNAMIC && modeld->last_frame_no_motion == true);
|
||||
if(!is_first_model) {
|
||||
/* If this data object is a secondary render pass, inherit the anti-alias setting for this frame from the first gltf_data drawn*/
|
||||
opt_aa_this_frame = view_desc->frame_was_antialiased;
|
||||
@@ -307,7 +309,7 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
|
||||
bool new_size = last_render_h != view_desc->render_height || last_render_w != view_desc->render_width;
|
||||
|
||||
if(opt_aa_this_frame != model->last_frame_was_antialiased) {
|
||||
if(opt_aa_this_frame != modeld->last_frame_was_antialiased) {
|
||||
/* Antialiasing state has changed since the last render */
|
||||
if(is_first_model) {
|
||||
if(vstate->render_state_ready) {
|
||||
@@ -317,7 +319,7 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
opt_aa_this_frame);
|
||||
}
|
||||
}
|
||||
model->last_frame_was_antialiased = opt_aa_this_frame;
|
||||
modeld->last_frame_was_antialiased = opt_aa_this_frame;
|
||||
}
|
||||
|
||||
view_desc->frame_was_antialiased = opt_aa_this_frame;
|
||||
@@ -334,33 +336,34 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
setup_finish_frame();
|
||||
}
|
||||
|
||||
bool last_frame_no_motion = model->_last_frame_no_motion;
|
||||
model->_last_frame_no_motion = model->last_frame_no_motion;
|
||||
model->last_frame_no_motion = true;
|
||||
bool last_frame_no_motion = modeld->_last_frame_no_motion;
|
||||
modeld->_last_frame_no_motion = modeld->last_frame_no_motion;
|
||||
modeld->last_frame_no_motion = true;
|
||||
|
||||
|
||||
if(dirty || lv_gltf_data_transform_cache_is_empty(model) || (model->camera != model->last_camera_index)) {
|
||||
model->last_frame_no_motion = false;
|
||||
lv_gltf_view_recache_all_transforms(model);
|
||||
if(dirty || lv_gltf_model_needs_transforms(modeld->model) ||
|
||||
(modeld->model->camera != modeld->last_camera_index)) {
|
||||
modeld->last_frame_no_motion = false;
|
||||
lv_gltf_view_recache_all_transforms(modeld);
|
||||
}
|
||||
else if(model->last_frame_no_motion && model->_last_frame_no_motion && last_frame_no_motion) {
|
||||
else if(modeld->last_frame_no_motion && modeld->_last_frame_no_motion && last_frame_no_motion) {
|
||||
/* Nothing changed at all, return the previous output frame */
|
||||
setup_finish_frame();
|
||||
lv_gltf_view_pop_opengl_state(&opengl_state);
|
||||
return vstate->render_state.texture;
|
||||
}
|
||||
|
||||
render_skins(viewer, model);
|
||||
render_skins(viewer, modeld);
|
||||
|
||||
NodeDistanceVector distance_sort_nodes;
|
||||
|
||||
for(const auto & kv : model->blended_nodes_by_material_index) {
|
||||
for(const auto & kv : modeld->model->blended_nodes_by_material_index) {
|
||||
for(const auto & pair : kv.second) {
|
||||
auto node = pair.first;
|
||||
auto new_node = NodeIndexDistancePair(
|
||||
fastgltf::math::length(
|
||||
model->view_pos -
|
||||
lv_gltf_data_get_centerpoint(model, lv_gltf_data_get_cached_transform(model, node),
|
||||
modeld->model->view_pos -
|
||||
lv_gltf_data_get_centerpoint(modeld->model, lv_gltf_data_get_node_transform(modeld->model, node),
|
||||
node->meshIndex.value(), pair.second)),
|
||||
NodeIndexPair(node, pair.second));
|
||||
distance_sort_nodes.push_back(new_node);
|
||||
@@ -372,7 +375,7 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
});
|
||||
|
||||
/* Reset the last material index to an unused value once per frame at the start*/
|
||||
model->last_material_index = 99999;
|
||||
modeld->model->last_material_index = 99999;
|
||||
|
||||
if(vstate->render_opaque_buffer) {
|
||||
std::optional<lv_gltf_matrices_saver_t> saver;
|
||||
@@ -381,11 +384,11 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
saver.emplace(viewer);
|
||||
}
|
||||
|
||||
if(model->camera > 0) {
|
||||
setup_view_proj_matrix_from_camera(viewer, model->camera - 1, view_desc, model, true);
|
||||
if(modeld->model->camera > 0) {
|
||||
setup_view_proj_matrix_from_camera(viewer, modeld->model->camera - 1, view_desc, modeld->model, true);
|
||||
}
|
||||
else {
|
||||
setup_view_proj_matrix(viewer, view_desc, model, true);
|
||||
setup_view_proj_matrix(viewer, view_desc, modeld->model, true);
|
||||
}
|
||||
lv_result_t result = setup_restore_opaque_output(viewer, &vstate->opaque_render_state,
|
||||
vstate->opaque_frame_buffer_width,
|
||||
@@ -400,13 +403,13 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
setup_draw_environment_background(&viewer->shader_manager, viewer, view_desc->blur_bg);
|
||||
}
|
||||
|
||||
render_materials(viewer, model, model->opaque_nodes_by_material_index, true);
|
||||
render_materials(viewer, modeld, modeld->model->opaque_nodes_by_material_index, true);
|
||||
|
||||
for(const auto & node_distance_pair : distance_sort_nodes) {
|
||||
const auto & node_element = node_distance_pair.second;
|
||||
const auto & node = node_element.first;
|
||||
draw_primitive(node_element.second, viewer, model, *node, node->meshIndex.value(),
|
||||
lv_gltf_data_get_cached_transform(model, node), viewer->environment, true);
|
||||
draw_primitive(node_element.second, viewer, modeld, *node, node->meshIndex.value(),
|
||||
lv_gltf_data_get_node_transform(modeld->model, node), viewer->environment, true);
|
||||
}
|
||||
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, vstate->opaque_render_state.texture));
|
||||
@@ -416,11 +419,11 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
}
|
||||
|
||||
if(is_first_model) {
|
||||
if(model->camera > 0) {
|
||||
setup_view_proj_matrix_from_camera(viewer, model->camera - 1, view_desc, model, false);
|
||||
if(modeld->model->camera > 0) {
|
||||
setup_view_proj_matrix_from_camera(viewer, modeld->model->camera - 1, view_desc, modeld->model, false);
|
||||
}
|
||||
else {
|
||||
setup_view_proj_matrix(viewer, view_desc, model, false);
|
||||
setup_view_proj_matrix(viewer, view_desc, modeld->model, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,13 +439,13 @@ static GLuint lv_gltf_view_render_model(lv_gltf_t * viewer, lv_gltf_model_t * mo
|
||||
setup_draw_environment_background(&viewer->shader_manager, viewer, view_desc->blur_bg);
|
||||
}
|
||||
|
||||
render_materials(viewer, model, model->opaque_nodes_by_material_index, false);
|
||||
render_materials(viewer, modeld, modeld->model->opaque_nodes_by_material_index, false);
|
||||
|
||||
for(const auto & node_distance_pair : distance_sort_nodes) {
|
||||
const auto & node_element = node_distance_pair.second;
|
||||
const auto & node = node_element.first;
|
||||
draw_primitive(node_element.second, viewer, model, *node, node->meshIndex.value(),
|
||||
lv_gltf_data_get_cached_transform(model, node), viewer->environment, false);
|
||||
draw_primitive(node_element.second, viewer, modeld, *node, node->meshIndex.value(),
|
||||
lv_gltf_data_get_node_transform(modeld->model, node), viewer->environment, false);
|
||||
}
|
||||
if(opt_aa_this_frame) {
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, vstate->render_state.texture));
|
||||
@@ -462,35 +465,44 @@ static void setup_finish_frame(void)
|
||||
GL_CALL(glUseProgram(0));
|
||||
}
|
||||
|
||||
static void render_materials(lv_gltf_t * viewer, lv_gltf_model_t * gltf_data, const MaterialIndexMap & map,
|
||||
static void render_materials(lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, const MaterialIndexMap & map,
|
||||
bool is_transmission_pass)
|
||||
{
|
||||
for(const auto & kv : map) {
|
||||
for(const auto & pair : kv.second) {
|
||||
auto node = pair.first;
|
||||
draw_primitive(pair.second, viewer, gltf_data, *node, node->meshIndex.value(),
|
||||
lv_gltf_data_get_cached_transform(gltf_data, node),
|
||||
draw_primitive(pair.second, viewer, modeld, *node, node->meshIndex.value(),
|
||||
lv_gltf_data_get_node_transform(modeld->model, node),
|
||||
viewer->environment, is_transmission_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void render_skins(lv_gltf_t * viewer, lv_gltf_model_t * model)
|
||||
static void render_skins(lv_gltf_t * viewer, lv_gltf_model_data_t * modeld)
|
||||
{
|
||||
uint32_t skin_count = lv_gltf_data_get_skins_size(model);
|
||||
size_t skin_count = lv_gltf_data_get_skins_size(modeld->model);
|
||||
if(skin_count == 0) {
|
||||
return;
|
||||
}
|
||||
lv_gltf_data_delete_textures(model);
|
||||
const size_t skin_texture_count = lv_array_size(&modeld->skin_textures);
|
||||
for(size_t i = 0; i < skin_texture_count; ++i) {
|
||||
GLuint * texture_id = (GLuint *)lv_array_at(&modeld->skin_textures, i);
|
||||
GL_CALL(glDeleteTextures(1, texture_id));
|
||||
}
|
||||
lv_array_clear(&modeld->skin_textures);
|
||||
|
||||
for(size_t i = 0; i < skin_count; ++i) {
|
||||
const auto & skin_index = lv_gltf_data_get_skin(model, i);
|
||||
const auto & skin = model->asset.skins[skin_index];
|
||||
auto & ibm = viewer->ibm_by_skin_then_node[skin_index];
|
||||
const auto & skin_index = lv_gltf_data_get_skin(modeld->model, i);
|
||||
const auto & skin = modeld->model->asset.skins[skin_index];
|
||||
auto & ibm = modeld->model->ibm_by_skin_then_node[skin_index];
|
||||
|
||||
size_t num_joints = skin.joints.size();
|
||||
size_t tex_width = std::ceil(std::sqrt((float)num_joints * 8.0f));
|
||||
|
||||
GLuint rtex = lv_gltf_data_create_texture(model);
|
||||
GLuint rtex;
|
||||
GL_CALL(glGenTextures(1, &rtex));
|
||||
lv_array_push_back(&modeld->skin_textures, &rtex);
|
||||
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, rtex));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
@@ -501,9 +513,9 @@ static void render_skins(lv_gltf_t * viewer, lv_gltf_model_t * model)
|
||||
size_t texture_data_index = 0;
|
||||
|
||||
for(uint64_t j = 0; j < num_joints; j++) {
|
||||
auto & joint_node = model->asset.nodes[skin.joints[j]];
|
||||
auto & joint_node = modeld->model->asset.nodes[skin.joints[j]];
|
||||
fastgltf::math::fmat4x4 final_joint_matrix =
|
||||
lv_gltf_data_get_cached_transform(model, &joint_node) * ibm[&joint_node];
|
||||
lv_gltf_data_get_node_transform(modeld->model, &joint_node) * ibm[&joint_node];
|
||||
|
||||
lv_memcpy(&texture_data[texture_data_index], final_joint_matrix.data(), sizeof(float) * 16);
|
||||
lv_memcpy(&texture_data[texture_data_index + 16],
|
||||
@@ -518,17 +530,17 @@ static void render_skins(lv_gltf_t * viewer, lv_gltf_model_t * model)
|
||||
lv_free(texture_data);
|
||||
}
|
||||
}
|
||||
static void draw_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_t * gltf_data, fastgltf::Node & node,
|
||||
static void draw_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, fastgltf::Node & node,
|
||||
std::size_t mesh_index, const fastgltf::math::fmat4x4 & matrix,
|
||||
const lv_gltf_environment_t * env_tex, bool is_transmission_pass)
|
||||
{
|
||||
lv_gltf_mesh_data_t * mesh = lv_gltf_data_get_mesh(gltf_data, mesh_index);
|
||||
const auto & asset = lv_gltf_data_get_asset(gltf_data);
|
||||
lv_gltf_mesh_data_t * mesh = lv_gltf_data_get_mesh(modeld->model, mesh_index);
|
||||
const auto & asset = lv_gltf_data_get_asset(modeld->model);
|
||||
const auto & _prim_data = lv_gltf_data_get_primitive_from_mesh(mesh, prim_num);
|
||||
|
||||
std::size_t index_count = 0;
|
||||
auto & indexAccessor = asset->accessors[asset->meshes[mesh_index].primitives[prim_num].indicesAccessor.value()];
|
||||
if(!setup_primitive(prim_num, viewer, gltf_data, node, mesh_index, matrix, env_tex, is_transmission_pass)) {
|
||||
if(!setup_primitive(prim_num, viewer, modeld, node, mesh_index, matrix, env_tex, is_transmission_pass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,10 +551,11 @@ static void draw_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_t
|
||||
GL_CALL(glDrawElements(_prim_data->primitiveType, index_count, _prim_data->indexType, 0));
|
||||
}
|
||||
}
|
||||
static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_t * model, fastgltf::Node & node,
|
||||
static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_data_t * modeld, fastgltf::Node & node,
|
||||
std::size_t mesh_index, const fastgltf::math::fmat4x4 & matrix,
|
||||
const lv_gltf_environment_t * env_tex, bool is_transmission_pass)
|
||||
{
|
||||
lv_gltf_model_t * model = modeld->model;
|
||||
lv_gltf_view_desc_t * view_desc = &viewer->desc;
|
||||
lv_gltf_mesh_data_t * mesh = lv_gltf_data_get_mesh(model, mesh_index);
|
||||
const auto & _prim_data = lv_gltf_data_get_primitive_from_mesh(mesh, prim_num);
|
||||
@@ -589,7 +602,7 @@ static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_
|
||||
GL_CALL(glCullFace(GL_BACK));
|
||||
uint32_t tex_num = 0;
|
||||
|
||||
if(!draw_material(viewer, uniforms, model, _prim_data, materialIndex, is_transmission_pass, program, &tex_num)) {
|
||||
if(!draw_material(viewer, uniforms, modeld, _prim_data, materialIndex, is_transmission_pass, program, &tex_num)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -604,8 +617,9 @@ static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_
|
||||
}
|
||||
|
||||
if(node.skinIndex.has_value()) {
|
||||
GLuint skin_texture = *(GLuint *)lv_array_at(&modeld->skin_textures, node.skinIndex.value());
|
||||
GL_CALL(glActiveTexture(GL_TEXTURE0 + tex_num));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, lv_gltf_data_get_skin_texture_at(model, node.skinIndex.value())));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, skin_texture));
|
||||
GL_CALL(glUniform1i(uniforms->joints_sampler, tex_num));
|
||||
tex_num++;
|
||||
}
|
||||
@@ -637,10 +651,12 @@ static bool setup_primitive(int32_t prim_num, lv_gltf_t * viewer, lv_gltf_model_
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t * uniforms, lv_gltf_model_t * model,
|
||||
static bool draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t * uniforms,
|
||||
lv_gltf_model_data_t * modeld,
|
||||
lv_gltf_primitive_t * _prim_data, size_t materialIndex, bool is_transmission_pass, GLuint program,
|
||||
uint32_t * tex_num)
|
||||
{
|
||||
lv_gltf_model_t * model = modeld->model;
|
||||
const auto & asset = lv_gltf_data_get_asset(model);
|
||||
|
||||
bool has_material = asset->materials.size() > (materialIndex - 1);
|
||||
@@ -679,7 +695,7 @@ static bool draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t
|
||||
}
|
||||
}
|
||||
|
||||
draw_lights(model, program);
|
||||
draw_lights(modeld, program);
|
||||
#if LV_GLTF_CONVERT_BASE_COLOR_TO_SRGB
|
||||
render_uniform_color_alpha(uniforms->base_color_factor, color_convert_to_srgb(gltfMaterial.pbrData.baseColorFactor));
|
||||
#else
|
||||
@@ -835,8 +851,11 @@ static bool draw_material(lv_gltf_t * viewer, const lv_gltf_uniform_locations_t
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static void draw_lights(lv_gltf_model_t * model, GLuint program)
|
||||
static void draw_lights(lv_gltf_model_data_t * modeld, GLuint program)
|
||||
{
|
||||
|
||||
lv_gltf_model_t * model = modeld->model;
|
||||
|
||||
if(model->node_by_light_index.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -853,7 +872,7 @@ static void draw_lights(lv_gltf_model_t * model, GLuint program)
|
||||
// Update each field of the light struct
|
||||
lv_snprintf(prefix, sizeof(prefix), "u_Lights[%zu]", i + 1);
|
||||
auto & lightNode = model->node_by_light_index[i];
|
||||
const fastgltf::math::fmat4x4 & light_matrix = lv_gltf_data_get_cached_transform(model, lightNode);
|
||||
const fastgltf::math::fmat4x4 & light_matrix = lv_gltf_data_get_node_transform(modeld->model, lightNode);
|
||||
|
||||
lv_snprintf(tag, sizeof(tag), "%s.position", prefix);
|
||||
glUniform3fv(glGetUniformLocation(program, tag), 1, &light_matrix[3][0]);
|
||||
@@ -1179,8 +1198,8 @@ static void setup_view_proj_matrix(lv_gltf_t * viewer, lv_gltf_view_desc_t * vie
|
||||
bool transmission_pass)
|
||||
{
|
||||
LV_UNUSED(model);
|
||||
const lv_gltf_model_t * main_model = *(lv_gltf_model_t **)lv_array_at(&viewer->models, 0);
|
||||
auto b_radius = lv_gltf_data_get_radius(main_model);
|
||||
const lv_gltf_model_data_t * main_model = (lv_gltf_model_data_t *)lv_array_at(&viewer->models, 0);
|
||||
auto b_radius = lv_gltf_data_get_radius(main_model->model);
|
||||
|
||||
float radius = b_radius * LV_GLTF_DISTANCE_SCALE_FACTOR;
|
||||
radius *= view_desc->distance;
|
||||
@@ -1313,27 +1332,28 @@ static void setup_draw_solid_background(lv_gltf_t * viewer, lv_color_t bg_color,
|
||||
|
||||
}
|
||||
|
||||
static void lv_gltf_view_recache_all_transforms(lv_gltf_model_t * model)
|
||||
static void lv_gltf_view_recache_all_transforms(lv_gltf_model_data_t * modeld)
|
||||
{
|
||||
int32_t anim_num = model->current_animation;
|
||||
int32_t anim_num = modeld->model->current_animation;
|
||||
uint32_t scene_index = 0;
|
||||
|
||||
model->last_camera_index = model->camera;
|
||||
model->write_ops_flushed = true;
|
||||
model->write_ops_pending = false;
|
||||
modeld->last_camera_index = modeld->model->camera;
|
||||
modeld->model->write_ops_flushed = true;
|
||||
modeld->model->write_ops_pending = false;
|
||||
size_t current_camera_count = 0;
|
||||
|
||||
lv_gltf_data_clear_transform_cache(model);
|
||||
lv_gltf_model_clear_transforms(modeld->model);
|
||||
|
||||
auto tmat = fastgltf::math::fmat4x4{};
|
||||
fastgltf::custom_iterate_scene_nodes(
|
||||
model, scene_index, &tmat,
|
||||
modeld->model, scene_index, &tmat,
|
||||
[&](lv_gltf_model_node_t * node, fastgltf::math::fmat4x4 & parentworldmatrix,
|
||||
fastgltf::math::fmat4x4 & localmatrix) {
|
||||
bool made_changes = false;
|
||||
bool made_rotation_changes = false;
|
||||
if(lv_gltf_data_animation_get_channel_set(anim_num, model, node->fastgltf_node)->size() > 0) {
|
||||
lv_gltf_data_animation_matrix_apply(model->local_timestamp / 1000., anim_num, model, node->fastgltf_node,
|
||||
if(lv_gltf_data_animation_get_channel_set(anim_num, modeld->model, node->fastgltf_node)->size() > 0) {
|
||||
lv_gltf_data_animation_matrix_apply(modeld->model->local_timestamp / 1000., anim_num, modeld->model,
|
||||
node->fastgltf_node,
|
||||
localmatrix);
|
||||
made_changes = true;
|
||||
}
|
||||
@@ -1411,18 +1431,18 @@ static void lv_gltf_view_recache_all_transforms(lv_gltf_model_t * model)
|
||||
}
|
||||
}
|
||||
|
||||
if(made_changes || !lv_gltf_data_has_cached_transform(model, node->fastgltf_node)) {
|
||||
if(made_changes || !lv_gltf_model_has_node_transform(modeld->model, node->fastgltf_node)) {
|
||||
auto world_matrix = worldmatrix_was_inlined ? inlined_worldmatrix : (parentworldmatrix * localmatrix);
|
||||
lv_gltf_data_set_cached_transform(model, node->fastgltf_node, world_matrix);
|
||||
lv_gltf_model_set_transforms(modeld->model, node->fastgltf_node, world_matrix);
|
||||
}
|
||||
|
||||
if(node->fastgltf_node->cameraIndex.has_value()) {
|
||||
current_camera_count++;
|
||||
if(current_camera_count == model->camera) {
|
||||
if(current_camera_count == modeld->model->camera) {
|
||||
fastgltf::math::fmat4x4 cammat = worldmatrix_was_inlined ? inlined_worldmatrix : (parentworldmatrix * localmatrix);
|
||||
fastgltf::removeScale(cammat);
|
||||
model->view_pos = cammat.col(3); /* Implicit conversion from 4 element column to 3 element vector */
|
||||
model->view_mat = fastgltf::math::inverse(cammat);
|
||||
modeld->model->view_pos = cammat.col(3); /* Implicit conversion from 4 element column to 3 element vector */
|
||||
modeld->model->view_mat = fastgltf::math::inverse(cammat);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user