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 案例效果展示

fishy

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空间中的旋转状态。