3D Cube控件¶
1. 控件概述¶
1.1 功能介绍¶
LVGL Cube控件(lvsf_cube)是基于LVGL框架开发、集成VGLite硬件加速的3D立方体可视化控件,支持多边形、图片、文本三类立方体面/元素渲染,提供旋转、缩放、视角调节等3D变换能力,支持点击交互回调,适用于3D可视化交互场景。
1.2 核心特性¶
硬件加速:基于VGLite图形库实现3D渲染硬件加速,提升渲染性能;
多元素支持:支持多边形、图片、文本三种类型的立方体面/子元素;
3D变换:支持旋转矩阵配置、缩放、视角(FOV)、距离调节;
交互能力:支持元素点击事件回调;
渲染优化:双缓冲(Double Buffering)、元素排序渲染、异步渲染;
2. 接口说明¶
接口函数 |
功能说明 |
参数说明 |
|---|---|---|
lv_obj_t *lv_cube_create(lv_obj_t *parent) |
创建一个新的3D立方体控件实例 |
parent:指向父LVGL对象的指针 |
void lv_cube_init(lv_obj_t *cube, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf, float zoom, bool async) |
初始化立方体控件参数 |
cube:立方体控件指针;w:控件宽度;h:控件高度;cf:帧缓冲颜色格式;zoom:初始缩放因子;async:是否启用异步渲染 |
void lv_cube_refr(lv_obj_t *cube) |
刷新立方体控件渲染(重新绘制) |
cube:立方体控件指针 |
void lv_cube_set_bg_color(lv_obj_t *cube, vg_lite_color_t color) |
设置立方体控件的背景颜色 |
cube:立方体控件指针;color:VGLite格式的背景色值 |
lv_cube_item_t *lv_cube_add_face_polygon(lv_obj_t *cube, const vg_lite_vertex_t *point, uint16_t cnt, uint32_t color, void *uset_data) |
为立方体添加多边形类型的面 |
cube:立方体控件指针;point:定义多边形顶点的数组;cnt:顶点数量(最大为CUBE_POINT_MAX);color:多边形颜色;uset_data:用户自定义数据 |
lv_cube_item_t *lv_cube_add_face_img(lv_obj_t *cube, const vg_lite_quad_t quad, const void *src, void *uset_data) |
为立方体添加图片类型的面 |
cube:立方体控件指针;quad:定义面位置的四边形;src:图片源数据指针;uset_data:用户自定义数据 |
lv_cube_item_t *lv_cube_add_txt(lv_obj_t *cube, const vg_lite_quad_t quad, const char *txt, lv_color_t color, lv_font_t *font, void *uset_data) |
为立方体添加文本类型的元素 |
cube:立方体控件指针;quad:定义文本位置的四边形;txt:要显示的文本字符串;color:文本颜色;font:字体指针;uset_data:用户自定义数据 |
void lv_cube_add_click_event(lv_obj_t *cube, lv_cube_item_click_cb cb) |
为立方体控件添加点击事件回调 |
cube:立方体控件指针;cb:点击事件回调函数指针 |
void lv_cube_add_child_img(lv_obj_t *cube, lv_cube_item_t *parent, const void *src, lv_coord_t ofs_x, lv_coord_t ofs_y) |
为立方体子项添加图片子元素 |
cube:立方体控件指针;parent:父立方体项指针;src:子图片源数据指针;ofs_x:X轴偏移量;ofs_y:Y轴偏移量 |
void lv_cube_add_child_txt(lv_obj_t *cube, lv_cube_item_t *parent, const char *txt, lv_color_t color, const lv_font_t *font, lv_coord_t ofs_x, lv_coord_t ofs_y) |
为立方体子项添加文本子元素 |
cube:立方体控件指针;parent:父立方体项指针;txt:子文本字符串;color:子文本颜色;font:子文本字体指针;ofs_x:X轴偏移量;ofs_y:Y轴偏移量 |
void lv_cube_set_rot(lv_obj_t *cube, vg_lite_matrix_4x4_t *rot) |
设置立方体控件的旋转矩阵 |
cube:立方体控件指针;rot:要应用的4x4旋转矩阵(遵循VGLite坐标系规范) |
void lv_cube_get_rot(lv_obj_t *cube, vg_lite_matrix_4x4_t *rot) |
获取立方体控件当前的旋转矩阵 |
cube:立方体控件指针;rot:用于存储旋转矩阵的输出指针(只读,修改需调用lv_cube_set_rot) |
3. 使用案例¶
以下通过使用lvsf_cube控件实现足球菜单。
#define APP_CNT_MAX 20
#define APP_TYPE_BUILD 0
#define APP_TYPE_TABLE 1
typedef struct
{
uint8_t type;
const void *info;
} app_node_t;
typedef struct
{
lv_obj_t *screen;
lv_obj_t *cube;
uint32_t app_num;
vg_lite_matrix_4x4_t rot;
app_node_t node[APP_CNT_MAX];
} mainmenu_t;
static mainmenu_t *p_menu = NULL;
void mainmenu_add_item(builtin_app_desc_t *app, mainmenu_ext_icons_t *table_elem, void *user_data)
{
if (p_menu->app_num < 20)
{
uint32_t index = p_menu->app_num;
const void *src = app ? app->icon : table_elem->img_src;
app_node_t *p_node = &p_menu->node[index];
p_node->type = app ? APP_TYPE_BUILD : APP_TYPE_TABLE;
p_node->info = app ? (void *)app : (void *)table_elem;
lv_cube_item_t *item = lv_cube_add_face_polygon(p_menu->cube, football_vertices[12 + index], 6, 0xFFFFFFFF, p_node);
lv_cube_add_child_img(p_menu->cube, item, src, 0, 0);
p_menu->app_num++;
}
}
void mainmenu_item_click_cb(struct lv_cube_item *item, void *user_data)
{
const app_node_t *p_node = (app_node_t *)user_data;
if (!p_node) return;
if (APP_TYPE_BUILD == p_node->type)
{
builtin_app_desc_t *app = (builtin_app_desc_t *)p_node->info;
if (app && 0 != strcmp(app->id, ""))
{
gui_app_run(app->id);
}
}
#if defined(APP_MENU_EXT_USED)
else
{
mainmenu_ext_icons_t *table_elem = (mainmenu_ext_icons_t *)p_node->info;
LOG_I("ext icon clicked\n");
if (table_elem->page_id != NULL)
gui_app_run_subpage("setting", table_elem->page_id, NULL);
}
#endif
}
static void on_start(void)
{
p_menu = (mainmenu_t *)app_calloc(1, sizeof(mainmenu_t));
RT_ASSERT(p_menu);
lv_obj_t *screen = lv_scr_act();
lv_obj_set_render_async(screen, 0);
//lv_obj_set_style_bg_opa(screen, LV_OPA_100, 0);
//lv_obj_set_style_bg_color(screen, LV_COLOR_RED, 0);
p_menu->screen = screen;
vg_lite_identity_4x4(&p_menu->rot);
}
static void on_resume(void)
{
lv_coord_t size = LV_MIN(LV_HOR_RES_MAX, LV_VER_RES_MAX) * 0.95f;
size = (size >> 4) << 4;
lv_obj_t *cube = lv_cube_create(p_menu->screen);
lv_obj_center(cube);
lv_cube_init(cube, size, size, LV_IMG_CF_TRUE_COLOR_ALPHA, 0.9f, false);
for (uint32_t i = 0; i < 12; i++)
{
lv_cube_item_t *item = lv_cube_add_face_polygon(cube, football_vertices[i], 5, 0xFF555555, NULL);
}
p_menu->cube = cube;
p_menu->app_num = 0;
while (p_menu->app_num < 20)
{
builtin_app_read_all(mainmenu_add_item, NULL, 0, 1, p_menu);
}
lv_cube_set_rot(cube, &p_menu->rot);
lv_cube_add_click_event(cube, mainmenu_item_click_cb);
lv_cube_refr(cube);
}
static void on_pause(void)
{
lv_cube_get_rot(p_menu->cube, &p_menu->rot);
lv_obj_del(p_menu->cube);
p_menu->cube = NULL;
}
static void on_stop(void)
{
app_free(p_menu);
p_menu = NULL;
}
static void msg_handler(gui_app_msg_type_t msg, void *param)
{
static uint8_t start = 0;
switch (msg)
{
case GUI_APP_MSG_ONSTART:
on_start();
break;
case GUI_APP_MSG_ONRESUME:
on_resume();
break;
case GUI_APP_MSG_ONPAUSE:
on_pause();
break;
case GUI_APP_MSG_ONSTOP:
on_stop();
break;
default:
;
}
}
APP_MAINMENU_REGISTER(Football, app_get_strid(key_mainmenu_football, "Football"), img_menu_football, msg_handler);
3.2 案例效果展示¶
4. 注意事项¶
4.1 性能优化¶
顶点数量限制:单个立方体面顶点数不超过
CUBE_POINT_MAX=6,超出会被截断;减少元素数量:过多的cube item会增加渲染耗时,建议按需拆分;
硬件加速适配:确保VGLite驱动正常加载,帧缓冲颜色格式与硬件兼容。
5. 术语说明¶
术语 |
说明 |
|---|---|
VGLite |
嵌入式硬件图形加速库,提供2D/3D渲染接口; |
双缓冲(Double Buffering) |
控件内部维护两个帧缓冲,避免渲染过程中画面撕裂; |
投影矩阵(mat_proj) |
用于将3D顶点转换为2D屏幕坐标的矩阵; |
Cube Item |
立方体的单个面/元素,支持多边形、图片、文本三种类型; |
旋转矩阵(rot) |
4x4矩阵,描述立方体在3D空间中的旋转状态。 |