3D 模型 (3D Model)
Lite3D 是由 Realtek 自主研发的轻量级、跨平台的 3D 图形渲染库,支持软件渲染与硬件加速扩展,具有以下特点:
轻量级:代码体积小,便于集成。
跨平台:适配 HoneyGUI、LVGL 等 GUI 框架,支持 FreeRTOS 和 Zephyr 环境运行。
灵活渲染:提供软件渲染管线,支持扩展 GPU 加速接口。
Lite3D 支持加载由 .obj
和 .mtl
文件组成的 3D 模型,能够处理模型的几何形状和材质信息,并支持为模型添加丰富的动画特效以增强视觉表现力。该引擎的工作流程如下:

Lite3D 工作流程
3D 模型组成要素
完整的 3D 模型包含三个核心组件:
-
.obj 文件
-
存储几何数据,包括:
顶点坐标
法线向量
纹理坐标(UV 映射)
面定义
需引用
.mtl
文件中的材质信息。
-
-
.mtl 文件(材质库)
-
定义表面属性,包括:
环境光/漫反射/镜面反射颜色
折射率
透明度
光照模型
纹理贴图引用
-
-
纹理图片
-
通常为 PNG 格式,用于:
漫反射贴图
法线贴图
高光贴图
透明贴图
-

3D 模型组成示例
3D 模型预处理
在绘制 3D 模型前,需要将其转换为二进制格式。以下是处理流程:
-
定位转换工具
-
在 HoneyGUI 安装目录下找到以下工具:
your_HoneyGUI_dir/tool/3D-tool/png2c.py
your_HoneyGUI_dir/tool/3D-tool/extract_desc.exe
-
-
准备模型目录
将上述工具复制到模型目录。
-
该模型目录确保包含:
.obj
文件.mtl
文件所有引用的纹理图片
-
生成描述文件
使用提取器处理模型:
extract_desc.exe xxx.obj
,该可执行文件会自动调用png2c.py
将所有的 PNG 纹理转换为二进制数组。
脚本处理
-
生成的
desc.txt
和desc.bin
文件包含以下内容:obj 解析数据
mtl 解析数据
内嵌纹理数据
生成二进制数组
3D 模型生成
创建模型
调用 Lite3D 库中的 l3_create_model(void *desc_addr, L3_DRAW_TYPE draw_type, int16_t x, int16_t y, int16_t view_w, int16_t view_h)
函数创建 3D 模型,导入的 desc_addr
文件即为脚本中提取的解析数据, draw_type
为模型绘制方式,支持以下三种方式:
L3_DRAW_FRONT_ONLY
:仅绘制模型的正面,适用于需要隐藏背面的场景,如蝴蝶模型。L3_DRAW_FRONT_AND_BACK
:绘制模型的正面和背面,适用于需要双面可见的场景,如棱镜模型。L3_DRAW_FRONT_AND_SORT
:绘制模型的正面并排序,适用于前后景遮挡的场景,如人脸模型。
变换控制
全局变换
使用 l3_set_global_transform(l3_model_t *_this, l3_global_transform_cb cb)
函数对 3D 模型进行整体变换,其中 l3_global_transform_cb
类型的回调函数可以为物体的所有面设置相同的形状变换。例如 world
世界坐标变换和 camera
相机视角投影。
典型应用场景:
模型整体旋转/平移
场景视角切换
相机变换
初始化函数为 l3_camera_UVN_initialize(l3_camera_t *camera, l3_4d_point_t cameraPosition, l3_4d_point_t cameraTarget, float near, float far, float fov, float viewPortWidth, float viewPortHeight)
。
camera
:指向相机结构体的指针,用于初始化相机的属性。cameraPosition
:相机在世界坐标系中的位置。cameraTarget
:相机所指向的目标点,即相机视线的焦点。near
:近裁剪平面距离,定义了相机截取视锥体的近端平面到相机的距离,所有靠近相机而小于这个距离的物体将被裁剪掉。far
:远裁剪平面距离,定义了视锥体远端平面到相机的距离,所有远离相机而大于这个距离的物体将被裁剪掉。fov
:视野范围,通常以垂直角度(单位:度)表示,定义了相机的开阔程度,即相机视锥体的张开角度。viewPortWidth
:视口的宽度,定义渲染目标或窗口的横向尺寸。viewPortHeight
:视口的高度,定义渲染目标或窗口的纵向尺寸。
作用:
相机变换定义了观察者在场景中的位置和方向,它将世界坐标系转换到摄像机坐标系。
通过操作相机,可以实现不同的视角,例如平移摄像机位置和改变观察方向。
世界变换
初始化函数为 l3_world_initialize(l3_4x4_matrix_t *world, float x, float y, float z, float rotX, float rotY, float rotZ, float scale)
。
world
:指向世界变换矩阵的指针,将 3D 对象从模型坐标系转换到世界坐标系。x
:沿 X 轴进行平移的距离,用以确定对象在世界坐标系中 X 方向上的位置。y
:沿 Y 轴进行平移的距离,用以确定对象在世界坐标系中 Y 方向上的位置。z
:沿 Z 轴进行平移的距离,用以确定对象在世界坐标系中 Z 方向上的位置。rotX
:绕 X 轴旋转的角度(单位:度)。rotY
:绕 Y 轴旋转的角度(单位:度)。rotZ
:绕 Z 轴旋转的角度(单位:度)。scale
:统一缩放系数,用于在各个方向上等比例地缩放对象。
作用:
世界变换定义了模型在世界坐标系中的位置和方向,负责将模型坐标系转换到世界坐标系。
通过世界变换矩阵可以实现模型整体的平移、旋转和缩放。
面变换
使用 l3_set_face_transform(l3_model_t *_this, l3_face_transform_cb cb)
函数对 3D 模型进行局部变换,其中 l3_face_transform_cb
类型的回调函数可以为物体的每个面设置不同的形状变换, face_index
为指定变换的面。
功能特点:
支持按面片索引独立控制。
使用
l3_calculator_4x4_matrix(l3_4x4_matrix_t *matrix, float tx, float ty, float tz, l3_4d_point_t point, l3_4d_vector_t vector, float degrees, float scale)
为每个面生成不同的矩阵以实现个性化的局部动画。
3D 模型绘制
创建控件
HoneyGUI 中已集成了 Lite3D 库,并封装成 gui_lite3d
控件,使用 gui_lite3d_create()
函数可以创建 3D 模型控件。
设置点击事件
gui_lite3d_on_click()
函数可以为 3D 模型控件设置点击事件,当用户点击模型时,会触发回调函数。
设置动画
gui_obj_create_timer()
函数可以为 3D 模型控件设置动画属性,其中 callback
为动画更新的回调函数。
示例
3D 蝴蝶
该模型由 8 个矩形面构成,每个面都有相应的纹理贴图,绘制方式为 L3_DRAW_FRONT_ONLY
。通过调用 l3_set_face_transform(l3_model_t *_this, l3_face_transform_cb cb)
函数,可以为不同的面设置局部变换,从而实现动画效果。
/*============================================================================*
* Header Files
*============================================================================*/
#include "root_image/ui_resource.h"
#include "gui_img.h"
#include "gui_win.h"
#include "gui_text.h"
#include "time.h"
#include "tp_algo.h"
#include <math.h>
#include "app_main_watch.h"
#include "gui_view.h"
#include "gui_lite3d.h"
/*============================================================================*
* Macros
*============================================================================*/
#define CURRENT_VIEW_NAME "butterfly_view"
/*============================================================================*
* Function Declaration
*============================================================================*/
static void butterfly_app(gui_view_t *view);
/*============================================================================*
* Variables
*============================================================================*/
/* View Management */
static gui_view_t *current_view = NULL;
const static gui_view_descriptor_t *menu_view = NULL;
static gui_view_descriptor_t const descriptor =
{
/* change Here for current view */
.name = (const char *)CURRENT_VIEW_NAME,
.pView = ¤t_view,
.on_switch_in = butterfly_app,
};
/* Animation Variables */
static float wing_angle = 0.0f;
static float butterfly_x = 0.0f;
static float butterfly_y = 0.0f;
static float butterfly_z = 0.0f;
static float butterfly_rz = 0.0f;
bool is_moving_to_target = false;
static float target_dx = 0.0f;
static float target_dy = 0.0f;
static float source_dx = 0.0f;
static float source_dy = 0.0f;
static const float move_speed = 0.02f;
static float wing_time = 0.0f;
static float total_flight_distance = 0.0f;
static float flight_progress = 1.0f;
/*============================================================================*
* Private Functions
*============================================================================*/
static int gui_view_descriptor_register_init(void)
{
gui_view_descriptor_register(&descriptor);
gui_log("File: %s, Function: %s\n", __FILE__, __func__);
return 0;
}
static GUI_INIT_VIEW_DESCRIPTOR_REGISTER(gui_view_descriptor_register_init);
static int gui_view_get_other_view_descriptor_init(void)
{
/* you can get other view descriptor point here */
menu_view = gui_view_descriptor_get("menu_view");
gui_log("File: %s, Function: %s\n", __FILE__, __func__);
return 0;
}
static GUI_INIT_VIEW_DESCRIPTOR_GET(gui_view_get_other_view_descriptor_init);
static void update_animation(void *param)
{
touch_info_t *tp = tp_get_info();
gui_dispdev_t *dc = gui_get_dc();
(void)param;
if (tp->pressed)
{
target_dx = (tp->x - dc->screen_width / 2) / 4.0f;
target_dy = (tp->y - dc->screen_height / 2) / 4.0f;
is_moving_to_target = true;
float dx = target_dx - source_dx;
float dy = target_dy - source_dy;
total_flight_distance = sqrtf(dx * dx + dy * dy);
flight_progress = 0.0f;
}
if (is_moving_to_target)
{
float current_dx = target_dx - source_dx;
float current_dy = target_dy - source_dy;
float remaining_distance = sqrtf(current_dx * current_dx + current_dy * current_dy);
flight_progress = fminf(1.0f - (remaining_distance / total_flight_distance), 1.0f);
if (flight_progress < 0.8f)
{
// Acceleration and deceleration
// float speed_factor = fminf(remaining_distance / 40.0f, 1.0f);
source_dx += current_dx * move_speed * (1.0f - flight_progress);
source_dy += current_dy * move_speed * (1.0f - flight_progress);
// Caculate new rotate angle
float desired_angle = atan2f(current_dy, current_dx) * (180.0f / M_PI_F) + 90;
float angle_difference = desired_angle - butterfly_rz;
if (angle_difference > 180.0f)
{
angle_difference -= 360.0f;
}
if (angle_difference < -180.0f)
{
angle_difference += 360.0f;
}
butterfly_rz += angle_difference * 0.1f;
// Adjust wing flapping frequency based on speed
wing_time += 0.2f + (1.0f - flight_progress) * 0.2f;
wing_angle = 60.0f * sinf(wing_time);
butterfly_x = source_dx;
butterfly_y = source_dy;
butterfly_z = 30.0f * (4.0f * flight_progress * (0.8f - flight_progress));
}
else
{
is_moving_to_target = false;
}
}
else
{
wing_time += 0.1f;
wing_angle = 50.0f * sinf(wing_time);
butterfly_z = -5.0f * sinf(wing_time);
}
}
static void butterfly_global_cb(l3_model_t *this)
{
l3_camera_UVN_initialize(&this->camera, l3_4d_point(0, 0, 0), l3_4d_point(0, 0, 45), 1,
32767,
90, this->viewPortWidth, this->viewPortHeight);
l3_world_initialize(&this->world, butterfly_x, butterfly_y, 45.0f - butterfly_z, 0, 0, butterfly_rz,
5);
}
static l3_4x4_matrix_t butterfly_face_cb(l3_model_t *this, size_t face_index/*face offset*/)
{
l3_4x4_matrix_t face_matrix;
l3_4x4_matrix_t transform_matrix;
if (face_index == 0 || face_index == 2)
{
l3_calculator_4x4_matrix(&face_matrix, 0, 0, 0, l3_4d_point(0, 0, 0), l3_4d_vector(0, 1, 0),
wing_angle, 1);
}
else if (face_index == 1 || face_index == 3)
{
l3_calculator_4x4_matrix(&face_matrix, 0, 0, 0, l3_4d_point(0, 0, 0), l3_4d_vector(0, 1, 0),
-wing_angle, 1);
}
else
{
l3_calculator_4x4_matrix(&face_matrix, 0, 0, 0, l3_4d_point(0, 0, 0), l3_4d_vector(0, 1, 0), 0,
1);
}
l3_4x4_matrix_mul(&this->world, &face_matrix, &transform_matrix);
return transform_matrix;
}
static void butterfly_app(gui_view_t *view)
{
gui_obj_t *obj = GUI_BASE(view);
gui_view_switch_on_event(view, menu_view, SWITCH_OUT_ANIMATION_FADE,
SWITCH_IN_ANIMATION_FADE,
GUI_EVENT_KB_SHORT_CLICKED);
l3_model_t *butterfly_3d = l3_create_model(DESC_BUTTERFLY_BIN, L3_DRAW_FRONT_ONLY, 0, 0, 410, 502);
l3_set_global_transform(butterfly_3d, (l3_global_transform_cb)butterfly_global_cb);
l3_set_face_transform(butterfly_3d, (l3_face_transform_cb)butterfly_face_cb);
gui_lite3d_t *lite3d_butterfly = gui_lite3d_create(obj, "lite3d-widget", butterfly_3d,
0, 0, 410, 502);
gui_obj_create_timer(GUI_BASE(lite3d_butterfly), 10, true, update_animation);
}

3D 人脸
该模型由 1454 个三角形面构成,使用默认材质基础色进行填充,绘制方式为 L3_DRAW_FRONT_AND_SORT
。
/*============================================================================*
* Header Files
*============================================================================*/
#include "root_image/ui_resource.h"
#include "gui_img.h"
#include "gui_win.h"
#include "gui_text.h"
#include "time.h"
#include "tp_algo.h"
#include <math.h>
#include "app_main_watch.h"
#include "gui_view.h"
#include "gui_lite3d.h"
/*============================================================================*
* Macros
*============================================================================*/
#define CURRENT_VIEW_NAME "face_view"
/*============================================================================*
* Function Declaration
*============================================================================*/
static void face_app(gui_view_t *view);
/*============================================================================*
* Variables
*============================================================================*/
/* View Management */
static gui_view_t *current_view = NULL;
const static gui_view_descriptor_t *menu_view = NULL;
static gui_view_descriptor_t const descriptor =
{
/* change Here for current view */
.name = (const char *)CURRENT_VIEW_NAME,
.pView = ¤t_view,
.on_switch_in = face_app,
};
/* Animation Variables */
static float rot_angle = 5.0f;
/*============================================================================*
* Private Functions
*============================================================================*/
static int gui_view_descriptor_register_init(void)
{
gui_view_descriptor_register(&descriptor);
gui_log("File: %s, Function: %s\n", __FILE__, __func__);
return 0;
}
static GUI_INIT_VIEW_DESCRIPTOR_REGISTER(gui_view_descriptor_register_init);
static int gui_view_get_other_view_descriptor_init(void)
{
/* you can get other view descriptor point here */
menu_view = gui_view_descriptor_get("menu_view");
gui_log("File: %s, Function: %s\n", __FILE__, __func__);
return 0;
}
static GUI_INIT_VIEW_DESCRIPTOR_GET(gui_view_get_other_view_descriptor_init);
static void update_face_animation(void *param)
{
touch_info_t *tp = tp_get_info();
(void)param;
if (tp->pressed || tp->pressing)
{
if (tp->x > 20 && tp->x < 390)
{
rot_angle += tp->deltaX / 5.0f;
}
}
}
static void face_global_cb(l3_model_t *this)
{
l3_camera_UVN_initialize(&this->camera, l3_4d_point(0, 0, 0), l3_4d_point(0, 0, 65), 1,
32767,
90, this->viewPortWidth, this->viewPortHeight);
l3_world_initialize(&this->world, 0, 22, 65, 0, rot_angle, 0, 5);
}
static void face_app(gui_view_t *view)
{
gui_obj_t *obj = GUI_BASE(view);
gui_view_switch_on_event(view, menu_view, SWITCH_OUT_ANIMATION_FADE,
SWITCH_IN_ANIMATION_FADE,
GUI_EVENT_KB_SHORT_CLICKED);
l3_model_t *face_3d = l3_create_model(DESC_FACE_BIN, L3_DRAW_FRONT_AND_SORT, 0, 0, 410, 502);
l3_set_global_transform(face_3d, (l3_global_transform_cb)face_global_cb);
gui_lite3d_t *lite3d_face = gui_lite3d_create(obj, "lite3d-widget", face_3d,
0, 0, 410, 502);
gui_obj_create_timer(GUI_BASE(lite3d_face), 10, true, update_face_animation);
}

3D 小狗
在 menu_config.h
中开启宏定义 CONFIG_REALTEK_BUILD_REAL_DOG_3D
来运行此示例。该模型由 774 个三角形面组成,支持自定义材质基础色的填充。
#include "guidef.h"
#include "gui_img.h"
#include "gui_obj.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "gui_server.h"
#include "gui_components_init.h"
#include "gui_lite3d.h"
#include "tp_algo.h"
#include "dog3d/desc.txt"
static float rot_angle = 0.0f;
static void update_dog_animation()
{
touch_info_t *tp = tp_get_info();
if (tp->pressed || tp->pressing)
{
rot_angle += tp->deltaX / 5.0f;
}
}
static void dog_global_cb(l3_model_t *this)
{
l3_camera_UVN_initialize(&this->camera, l3_4d_point(0, 0, 0), l3_4d_point(0, 3, 30), 1, 32767,
90, this->viewPortWidth, this->viewPortHeight);
l3_world_initialize(&this->world, 0, 15, 30, 0, rot_angle, 0, 5);
}
static int app_init(void)
{
l3_model_t *dog_3d = l3_create_model((void *)_acdesc, L3_DRAW_FRONT_AND_SORT, 50, 50, 380, 380);
l3_set_global_transform(dog_3d, (l3_global_transform_cb)dog_global_cb);
gui_lite3d_t *lite3d_dog = gui_lite3d_create(gui_obj_get_root(), "lite3d-widget", dog_3d,
0, 0, 480, 480);
gui_obj_create_timer(GUI_BASE(lite3d_dog), 17, true, update_dog_animation);
return 0;
}

3D 应用列表
该界面由 6 个 3D 应用图标组成,通过调用 l3_set_face_image(l3_model_t *_this, uint8_t face_index, void *image_addr)
函数可以为 3D 模型的指定面替换纹理贴图。
/*============================================================================*
* Header Files
*============================================================================*/
#include "root_image/ui_resource.h"
#include "gui_img.h"
#include "gui_win.h"
#include "gui_text.h"
#include "time.h"
#include "tp_algo.h"
#include <math.h>
#include "app_main_watch.h"
#include "gui_view.h"
#include "gui_lite3d.h"
/*============================================================================*
* Macros
*============================================================================*/
#define CURRENT_VIEW_NAME "applist_view"
#define APP_NUM 6
/*============================================================================*
* Types
*============================================================================*/
typedef struct
{
int16_t pos_x;
int16_t pos_y;
} Position;
/*============================================================================*
* Function Declaration
*============================================================================*/
static void applist_app(gui_view_t *view);
/*============================================================================*
* Variables
*============================================================================*/
/* View Management */
static gui_view_t *current_view = NULL;
const static gui_view_descriptor_t *menu_view = NULL;
static gui_view_descriptor_t const descriptor =
{
/* change Here for current view */
.name = (const char *)CURRENT_VIEW_NAME,
.pView = ¤t_view,
.on_switch_in = applist_app,
};
/* 3D Applications List */
static gui_lite3d_t *app_3d_list[APP_NUM]; // Static array
static const Position app_positions[APP_NUM] =
{
{0, 50},
{100, 50},
{200, 50},
{0, 200},
{100, 200},
{200, 200}
};
/* Animation Variables */
static float rot_y_angle = 0.0f; // Current angle
static float velocity = 0.0f; // Angular velocity
static bool isAnimating = false; // Whether animation is ongoing
static const float amplitude = 30.0f; // Initial amplitude
static const float damping =
0.95f; // Damping coefficient (between 0.9~0.99, higher values result in longer oscillation)
static const float frequency =
0.2f; // Oscillation frequency (higher values result in faster oscillation)
static bool click_amplify = false;
static float click_on_rot_y = 0.0f;
static float click_on_shift_z = 0.0f;
/*============================================================================*
* Private Functions
*============================================================================*/
static int gui_view_descriptor_register_init(void)
{
gui_view_descriptor_register(&descriptor);
gui_log("File: %s, Function: %s\n", __FILE__, __func__);
return 0;
}
static GUI_INIT_VIEW_DESCRIPTOR_REGISTER(gui_view_descriptor_register_init);
static int gui_view_get_other_view_descriptor_init(void)
{
/* you can get other view descriptor point here */
menu_view = gui_view_descriptor_get("menu_view");
gui_log("File: %s, Function: %s\n", __FILE__, __func__);
return 0;
}
static GUI_INIT_VIEW_DESCRIPTOR_GET(gui_view_get_other_view_descriptor_init);
static void update_applist_animation(void *param)
{
touch_info_t *tp = tp_get_info();
(void)param;
if (tp->pressed)
{
isAnimating = true; // Start animation
rot_y_angle = 0.0f; // Reset angle
velocity = amplitude * frequency; // Initial velocity
}
if (isAnimating)
{
// Harmonic motion + damping decay
float acceleration = -frequency * frequency *
rot_y_angle; // Acceleration (towards equilibrium point)
velocity += acceleration; // Update velocity
velocity *= damping; // Apply damping decay
rot_y_angle += velocity; // Update angle
// Stop animation when oscillation is small enough
if (fabsf(rot_y_angle) < 0.1f && fabsf(velocity) < 0.1f)
{
rot_y_angle = 0.0f; // Ensure complete stop
velocity = 0.0f;
isAnimating = false;
}
}
}
static void applist_global_cb(l3_model_t *this)
{
l3_camera_UVN_initialize(&this->camera, l3_4d_point(0, 0, 0), l3_4d_point(0, 0, 15), 1,
32767,
90, this->viewPortWidth, this->viewPortHeight);
l3_world_initialize(&this->world, 0, 0, 15, 0, 0, 0, 5);
}
static l3_4x4_matrix_t applist_face_cb(l3_model_t *this, size_t face_index)
{
(void)face_index;
l3_4x4_matrix_t face_matrix;
l3_4x4_matrix_t transform_matrix;
l3_calculator_4x4_matrix(&face_matrix, 0, 0, 0, l3_4d_point(0, 0, 0), l3_4d_vector(0, 1, 0),
rot_y_angle, 1);
l3_4x4_matrix_mul(&this->world, &face_matrix, &transform_matrix);
return transform_matrix;
}
static void app_click_on_cb(l3_model_t *this)
{
if (click_on_rot_y < 720.f)
{
click_on_rot_y += 10.0f;
}
if (click_on_shift_z < 5.0f)
{
click_on_shift_z += 0.2f;
}
this->x = 0;
this->y = 46;
this->viewPortWidth = 410;
this->viewPortHeight = 410;
l3_camera_UVN_initialize(&this->camera, l3_4d_point(0, 0, 0), l3_4d_point(0, 0, 15), 1,
32767,
90, this->viewPortWidth, this->viewPortHeight);
l3_world_initialize(&this->world, 0, 0, 15.0f - click_on_shift_z, 0, click_on_rot_y, 0, 5);
}
static int get_app_index(gui_lite3d_t *target)
{
for (int i = 0; i < APP_NUM; i++)
{
if (app_3d_list[i] == target)
{
return i;
}
}
return -1;
}
static void gui_app_switch(gui_lite3d_t *this)
{
gui_log("clicked app: %s\n", this->base.name);
if (!click_amplify)
{
click_amplify = true;
for (int i = 0; i < APP_NUM; i++)
{
gui_lite3d_t *app = app_3d_list[i];
if (app != this)
{
app->base.not_show = true;
}
}
click_on_rot_y = 0.0f;
click_on_shift_z = 0.0f;
l3_set_global_transform(this->model, (l3_global_transform_cb)app_click_on_cb);
}
else
{
click_amplify = false;
int clicked_index = get_app_index(this);
if (clicked_index == -1)
{
gui_log("Error: Target app not found!");
return;
}
this->model->x = app_positions[clicked_index].pos_x;
this->model->y = app_positions[clicked_index].pos_y;
this->model->viewPortWidth = 200;
this->model->viewPortHeight = 200;
l3_set_global_transform(this->model, (l3_global_transform_cb)applist_global_cb);
for (int i = 0; i < APP_NUM; i++)
{
app_3d_list[i]->base.not_show = false;
}
}
}
static void applist_app(gui_view_t *view)
{
gui_obj_t *obj = GUI_BASE(view);
gui_view_switch_on_event(view, menu_view, SWITCH_OUT_ANIMATION_FADE,
SWITCH_IN_ANIMATION_FADE,
GUI_EVENT_KB_SHORT_CLICKED);
click_amplify = false;
// App0
l3_model_t *app0 = l3_create_model(DESC_APP_BIN, L3_DRAW_FRONT_ONLY,
app_positions[0].pos_x, app_positions[0].pos_y, 200, 200);
app_3d_list[0] = gui_lite3d_create(obj, "app0", app0, 0, 0, 0, 0);
// App1
l3_model_t *app1 = l3_create_model(DESC_APP_BIN, L3_DRAW_FRONT_ONLY,
app_positions[1].pos_x, app_positions[1].pos_y, 200, 200);
l3_set_face_image(app1, 5, FILM_BIN);
app_3d_list[1] = gui_lite3d_create(obj, "app1", app1, 0, 0, 0, 0);
// App2
l3_model_t *app2 = l3_create_model(DESC_APP_BIN, L3_DRAW_FRONT_ONLY,
app_positions[2].pos_x, app_positions[2].pos_y, 200, 200);
l3_set_face_image(app2, 5, MUSIC_BIN);
app_3d_list[2] = gui_lite3d_create(obj, "app2", app2, 0, 0, 0, 0);
// App3
l3_model_t *app3 = l3_create_model(DESC_APP_BIN, L3_DRAW_FRONT_ONLY,
app_positions[3].pos_x, app_positions[3].pos_y, 200, 200);
l3_set_face_image(app3, 5, MAIL_BIN);
app_3d_list[3] = gui_lite3d_create(obj, "app3", app3, 0, 0, 0, 0);
// App4
l3_model_t *app4 = l3_create_model(DESC_APP_BIN, L3_DRAW_FRONT_ONLY,
app_positions[4].pos_x, app_positions[4].pos_y, 200, 200);
l3_set_face_image(app4, 5, VOICE_BIN);
app_3d_list[4] = gui_lite3d_create(obj, "app4", app4, 0, 0, 0, 0);
// App5
l3_model_t *app5 = l3_create_model(DESC_APP_BIN, L3_DRAW_FRONT_ONLY,
app_positions[5].pos_x, app_positions[5].pos_y, 200, 200);
l3_set_face_image(app5, 5, WECHAT_BIN);
app_3d_list[5] = gui_lite3d_create(obj, "app5", app5, 0, 0, 0, 0);
for (int i = 0; i < APP_NUM; i++)
{
l3_set_global_transform(app_3d_list[i]->model, (l3_global_transform_cb)applist_global_cb);
l3_set_face_transform(app_3d_list[i]->model, (l3_face_transform_cb)applist_face_cb);
gui_lite3d_on_click(app_3d_list[i], (gui_event_cb_t)gui_app_switch, app_3d_list[i]);
}
gui_obj_create_timer(GUI_BASE(app_3d_list[0]), 10, true, update_applist_animation);
}

帧率测试
以下表格展示了不同芯片平台上,各个示例的帧率表现。编译环境采用 ARMCLANG V6.22
,编译选项为 -O3 LTO
。
芯片型号 |
处理器主频 |
分辨率 |
||||
---|---|---|---|---|---|---|
RTL8773E |
100MHz |
410 x 502 |
33 FPS |
13 FPS |
22 FPS |
24 FPS |
RTL8773G |
200MHz |
410 x 502 |
58 FPS |
24 FPS |
46 FPS |
56 FPS |
API
Functions
-
gui_lite3d_t *gui_lite3d_create(void *parent, const char *name, l3_model_t *model, int16_t x, int16_t y, int16_t w, int16_t h)
-
Lite3D Widget Create.
- 参数:
parent – Parent widget.
name – Widget name.
model – Lite3D model.
x – The X-axis coordinate relative to parent widget.
y – The Y-axis coordinate relative to parent widget.
w – Width.
h – Height.
- 返回:
-
The widget object pointer.
-
void gui_lite3d_on_click(gui_lite3d_t *this, void *callback, void *parameter)
-
Lite3D Widget On Click.
- 参数:
this – Widget object pointer.
callback – Callback function.
parameter – Parameter.
-
struct gui_lite3d_t