3D Model

Lite3D is a lightweight, cross-platform 3D graphics rendering library independently developed by Realtek. It supports software rendering and hardware acceleration extensions with the following features:

  • Lightweight: Small code size, easy to integrate.

  • Cross-platform: Compatible with GUI frameworks such as HoneyGUI and LVGL, and supports environments like FreeRTOS and Zephyr.

  • Flexible Rendering: Provides a software rendering pipeline with support for extending GPU acceleration interfaces.

Lite3D supports loading 3D models comprised of .obj and .mtl files, capable of handling both the geometry and material information of the models. It also supports adding rich animation effects to enhance visual performance. The engine workflow is as follows:

https://foruda.gitee.com/images/1755252209828076518/c91dad94_13408154.png

Lite3D Workflow

Components of a 3D Model

A complete 3D model consists of three core components:

  1. .obj File

    • Stores geometric data, including:

      • Vertex coordinates

      • Normal vectors

      • Texture coordinates (UV mapping)

      • Face definitions

    • References material information from the .mtl file.

  2. .mtl File (Material Library)

    • Defines surface properties, including:

      • Ambient/Diffuse/Specular colors

      • Refractive index

      • Transparency

      • Illumination model

      • Texture map references

  3. Texture Images

    • Usually in PNG format, used for:

      • Diffuse maps

      • Normal maps

      • Specular maps

      • Transparency maps

https://foruda.gitee.com/images/1735113754178839767/916a3f95_13408154.png

Example of 3D Model Components

3D Model Preprocessing

Before rendering a 3D model, it needs to be converted into a binary format. The processing flow is as follows:

  1. Locate Conversion Tools

    • Find the following tools in the HoneyGUI installation directory:

      • your_HoneyGUI_dir/tool/3D-tool/png2c.py

      • your_HoneyGUI_dir/tool/3D-tool/extract_desc.exe

  2. Prepare the Model Directory

    • Copy the above tools into the model directory.

    • Ensure the model directory contains:

      • .obj file

      • .mtl file

      • All referenced texture images

  3. Generate Descriptor File

    • Use the extractor to process the model: extract_desc.exe xxx.obj. This executable will automatically call png2c.py to convert all PNG textures into binary arrays.

    https://foruda.gitee.com/images/1735540370568112173/cf1c0126_13408154.png

    Script Processing

    • The generated desc.txt and desc.bin files contain the following:

      • Parsed obj data

      • Parsed mtl data

      • Embedded texture data

    https://foruda.gitee.com/images/1735114445910760790/2a41eeab_13408154.png

    Generating Binary Arrays

3D Model Generation

Creating a Model

Invoke the function 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) from the Lite3D library to create a 3D model. The imported desc_addr file contains the parsed data extracted by the script, whereas draw_type specifies the rendering method for the model. It supports the following three modes:

  • L3_DRAW_FRONT_ONLY: Renders only the front of the model, suitable for scenarios like a butterfly model where the back needs to be hidden.

  • L3_DRAW_FRONT_AND_BACK: Renders both the front and back of the model, suitable for scenarios where both sides need to be visible, like a prism model.

  • L3_DRAW_FRONT_AND_SORT: Renders the front of the model with sorting, suitable for scenarios with foreground and background occlusion, like a face model.

Transformation Control

Global Transformation

Use the function l3_set_global_transform(l3_model_t *_this, l3_global_transform_cb cb) to perform global transformations on the 3D model. The callback function of type l3_global_transform_cb can apply the same shape transformation to all faces of the object. Examples include world coordinate transformations and camera view projections.

Typical use cases:

  • Overall rotation/translation of the model

  • Scene perspective switching

Camera Transformation

The initialization function is 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: A pointer to the camera structure, used to initialize camera properties.

  • cameraPosition: The position of the camera in world coordinates.

  • cameraTarget: The target point the camera is directed at, i.e., the focal point of the camera’s line of sight.

  • near: The near clipping plane distance, defining the distance from the camera to the near plane of the camera’s view frustum. Objects closer than this distance will be clipped.

  • far: The far clipping plane distance, defining the distance from the camera to the far plane of the view frustum. Objects farther than this distance will be clipped.

  • fov: The field of view, usually expressed as a vertical angle (in degrees), defining the openness of the camera, i.e., the opening angle of the camera’s view frustum.

  • viewPortWidth: The width of the viewport, defining the horizontal size of the rendering target or window.

  • viewPortHeight: The height of the viewport, defining the vertical size of the rendering target or window.

Purpose:

  1. Camera transformation defines the observer’s position and direction in the scene, transforming the world coordinate system to the camera coordinate system.

  2. By manipulating the camera, different perspectives can be achieved, such as translating the camera position or changing the viewing direction.

World Transformation

The initialization function is l3_world_initialize(l3_4x4_matrix_t *world, float x, float y, float z, float rotX, float rotY, float rotZ, float scale).

  • world: A pointer to the world transformation matrix, which transforms the 3D object from model coordinates to world coordinates.

  • x: The distance of translation along the X-axis, used to determine the object’s position in the X direction within the world coordinate system.

  • y: The distance of translation along the Y-axis, used to determine the object’s position in the Y direction within the world coordinate system.

  • z: The distance of translation along the Z-axis, used to determine the object’s position in the Z direction within the world coordinate system.

  • rotX: The angle of rotation around the X-axis (in degrees).

  • rotY: The angle of rotation around the Y-axis (in degrees).

  • rotZ: The angle of rotation around the Z-axis (in degrees).

  • scale: A uniform scaling factor used to proportionally scale the object in all directions.

Purpose:

  1. The world transformation defines the model’s position and orientation in the world coordinate system, responsible for converting the model coordinate system to the world coordinate system.

  2. Through the world transformation matrix, the overall translation, rotation, and scaling of the model can be achieved.

Face Transformation

Use the function l3_set_face_transform(l3_model_t *_this, l3_face_transform_cb cb) for local transformations on a 3D model. The callback function of type l3_face_transform_cb can apply different shape transformations to each face of the object, with face_index specifying the face to transform.

Features:

  • Supports independent control by face index.

  • Use 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) to generate different matrices for each face, enabling customized local animations.

3D Model Rendering

Create Widget

The Lite3D library has been integrated into HoneyGUI and encapsulated into the gui_lite3d widget. You can create a 3D model widget using the function gui_lite3d_create().

Set Click Events

The function gui_lite3d_on_click() can be used to set click events for the 3D model widget. When the user clicks the model, a callback function is triggered.

Set Animations

The function gui_obj_create_timer() can be used to set animation properties for the 3D model widget, where callback is the animation update callback function.

Example

3D Butterfly

This model consists of 8 rectangular faces, each with a corresponding texture map, and uses the L3_DRAW_FRONT_ONLY rendering method. By calling the function l3_set_face_transform(l3_model_t *_this, l3_face_transform_cb cb), you can set local transformations for different faces to achieve animation effects.

/*============================================================================*
 *                        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 = &current_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 Face

This model consists of 1454 triangular faces and is filled with a default material base color. The rendering method used is 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 = &current_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 Dog

To run this example, enable the macro definition CONFIG_REALTEK_BUILD_REAL_DOG_3D in menu_config.h. The model consists of 774 triangular surfaces and supports filling with a custom material base color.

#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 App List

This interface consists of 6 3D application icons. By calling the function l3_set_face_image(l3_model_t *_this, uint8_t face_index, void *image_addr), you can replace the texture map of a specified face of the 3D model.

/*============================================================================*
 *                        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 = &current_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);

}


FPS Benchmark

The table below shows the frame rate performance of various examples on different chip platforms. The compilation environment uses ARMCLANG V6.22 with the -O3 LTO compilation option.

FPS Benchmark Results

Chip Model

CPU Frequency

Resolution

3D Butterfly

3D Face

3D Dog

3D App List

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.

Parameters:
  • 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.

Returns:

The widget object pointer.

void gui_lite3d_on_click(gui_lite3d_t *this, void *callback, void *parameter)

Lite3D Widget On Click.

Parameters:
  • this – Widget object pointer.

  • callback – Callback function.

  • parameter – Parameter.

struct gui_lite3d_t

Public Members

gui_obj_t base
l3_model_t *model