ESP-IDF Firmware
Firmware architecture and call graph
Loading...
Searching...
No Matches
external_examples/d1468452/apps/3d_graphics/main/3d_graphics_demo.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <stdio.h>
8#include "esp_log.h"
9#include "ssd1306.h"
10#include "bsp/esp-bsp.h"
11#include "esp_dsp.h"
12#include "cube_matrix.h"
13#include "esp_logo.h"
14#include "esp_text.h"
15#include "graphics_support.h"
16#include "image_to_3d_matrix.h"
17
18static ssd1306_handle_t ssd1306_dev = NULL;
19static bool button_pressed = true;
20
22
23extern "C" void app_main();
24
34{
35#ifdef CONFIG_3D_OBJECT_ESP_LOGO
37 image->matrix_len = ((sizeof(image_3d_matrix_esp_logo)) / sizeof(float)) / MATRIX_SIZE;
38 ESP_LOGI("3D image demo", "Selected 3D image - ESP Logo");
39#elif CONFIG_3D_OBJECT_CUSTOM
41 image->matrix_len = ((sizeof(image_to_3d_matrix_custom)) / sizeof(float)) / MATRIX_SIZE;
42 ESP_LOGI("3D image demo", "Selected 3D image - User's custom image");
43#elif CONFIG_3D_OBJECT_CUBE
44 image->matrix = cube_vectors_3d;
45 image->matrix_len = ((sizeof(cube_vectors_3d)) / sizeof(float)) / MATRIX_SIZE;
46 ESP_LOGI("3D image demo", "Selected 3D image - 3D cube");
47#endif
48}
49
53static void app_ssd1306_init(void)
54{
55 ssd1306_dev = ssd1306_create((i2c_port_t)BSP_I2C_NUM, SSD1306_I2C_ADDRESS);
56 ssd1306_clear_screen(ssd1306_dev, 0x00);
57 ssd1306_refresh_gram(ssd1306_dev);
58}
59
68static void display_3d_image(dspm::Mat projected_image)
69{
70 ssd1306_clear_screen(ssd1306_dev, 0);
71
72 if (OBJECT_3D_CUBE) {
73 // For the 3D cube, only the 6 points of the cube are transformed
74 // Cube edges, connecting transformed 3D cube points are connected with lines here
75 for (uint8_t cube_point = 0; cube_point < CUBE_EDGES; cube_point++) {
76 ssd1306_draw_line(ssd1306_dev,
77 (int16_t)projected_image(cube_dict_line_begin[cube_point], 0),
78 (int16_t)projected_image(cube_dict_line_begin[cube_point], 1),
79 (int16_t)projected_image(cube_dict_line_end[cube_point], 0),
80 (int16_t)projected_image(cube_dict_line_end[cube_point], 1));
81 }
82 } else {
83 // Every other 3D image is drawn here pixel by pixel
84 for (uint32_t pixel = 0; pixel < projected_image.rows; pixel++ ) {
85 ssd1306_fill_point(ssd1306_dev, projected_image(pixel, 0), projected_image(pixel, 1), 1);
86 }
87 }
88 ssd1306_refresh_gram(ssd1306_dev);
89}
90
96static void dispaly_esp_text(void)
97{
98 image_3d_matrix_t esp_text;
100 esp_text.matrix_len = ((sizeof(image_3d_array_esp_text)) / sizeof(float)) / MATRIX_SIZE;
101 int16_t shift_x = -SSD1606_X_CENTER;
102
103 dspm::Mat T = dspm::Mat::eye(MATRIX_SIZE); // Transformation matrix
104 dspm::Mat transformed_image(esp_text.matrix_len, MATRIX_SIZE); // 3D image matrix after transformation
105 dspm::Mat matrix_3d((float *)esp_text.matrix[0], esp_text.matrix_len, MATRIX_SIZE);
106
107 ESP_LOGI("3D image demo", "Showing ESP text");
108
109 for (int i = 0; i < 52; i++) {
110 update_translation_matrix(T, true, (float)shift_x, (float)SSD1606_Y_CENTER, 0);
111 transformed_image = matrix_3d * T;
112
113 ssd1306_clear_screen(ssd1306_dev, 0);
114 for (uint32_t point = 0; point < transformed_image.rows; point++ ) {
115 ssd1306_fill_point(ssd1306_dev, transformed_image(point, 0), transformed_image(point, 1), 1);
116 }
117 ssd1306_refresh_gram(ssd1306_dev);
118 vTaskDelay(50 / portTICK_PERIOD_MS);
119
120 shift_x += 5;
121 }
122
123 ssd1306_clear_screen(ssd1306_dev, 0);
124 ssd1306_draw_bitmap(ssd1306_dev, 0, 24, &image_bmp_array_esp_text[0], 128, 24);
125 ssd1306_refresh_gram(ssd1306_dev);
126
128 vTaskDelay(100 / portTICK_PERIOD_MS);
129
130 float scale = 1;
131 for (int i = 0; i < 20; i++) {
132 update_scaling_matrix(T, false, scale, scale, 1);
133 transformed_image = matrix_3d * T;
134
135 ssd1306_clear_screen(ssd1306_dev, 0);
136 for (uint32_t point = 0; point < transformed_image.rows; point++ ) {
137 ssd1306_fill_point(ssd1306_dev, transformed_image(point, 0), transformed_image(point, 1), 1);
138 }
139 ssd1306_refresh_gram(ssd1306_dev);
140 vTaskDelay(50 / portTICK_PERIOD_MS);
141
142 if (i < 10) {
143 scale -= 0.05;
144 } else {
145 scale += 0.05;
146 }
147 }
148}
149
157static void draw_3d_image_task(void *arg)
158{
159 float rot_y = 0, rot_x = 0;
160 const float angle_increment = 4;
162
163 dspm::Mat T = dspm::Mat::eye(MATRIX_SIZE); // Transformation matrix
164 dspm::Mat transformed_image(image->matrix_len, MATRIX_SIZE); // 3D image matrix after transformation
165 dspm::Mat projected_image(image->matrix_len, MATRIX_SIZE); // 3D image matrix after projection
166 dspm::Mat matrix_3d((float *)image->matrix[0], image->matrix_len, MATRIX_SIZE);
167
168 if (OBJECT_3D_CUBE) {
169 rot_x = 45;
170 }
171
172 while (1) {
173 if (button_pressed) {
174 rot_y += angle_increment;
175 if (rot_y >= 360) {
176 rot_y -= 360;
177 }
178 } else {
179 rot_y -= angle_increment;
180 if (rot_y <= 0) {
181 rot_y += 360;
182 }
183 }
184
185 // Apply rotation in all the axes to the transformation matrix
186 update_rotation_matrix(T, rot_x, rot_y, 0);
187 // Apply translation to the transformation matrix
188 update_translation_matrix(T, true, ((float)SSD1606_X_CENTER), ((float)SSD1606_Y_CENTER), 0);
189
190 // explanation for the matrix multiplication is for the 3D cube scenario, applies for all of the objects
191 // where matrix rows for the transformed image and the projected image are set according to the specific 3d object
192
193 // matrix mul cube_matirx(8x4) * transformation_matrix(4x4) = transformed_cube(8x4)
194 transformed_image = matrix_3d * T;
195 // matrix mul transformed_cube(8x4) * perspective_matrix(4x4) = projected_cube(8x4)
196 projected_image = transformed_image * perspective_matrix;
197
198 display_3d_image(projected_image);
199 vTaskDelay(20 / portTICK_PERIOD_MS);
200 }
201}
202
203void app_main(void)
204{
205 static bool button_prev_val = false;
208 ekf13->Init();
209
210 // Init all board components
211 bsp_i2c_init();
212 app_ssd1306_init(); // display init
213 bsp_leds_init(); // LEDs init
214 bsp_i2c_set_clk_speed(I2C_CLK_600KHZ); // Set I2C to 600kHz
215
218
220 vTaskDelay(1000 / portTICK_PERIOD_MS);
221
222 xTaskCreate(draw_3d_image_task, "draw_3d_image", 2048, &image, 4, NULL);
223 ESP_LOGI("3D image demo", "Showing 3D image");
224
225 while (1) {
226 if (bsp_button_get()) {
228 }
229
230 if (button_prev_val != button_pressed) {
231 button_prev_val = button_pressed;
232 if (button_pressed) {
233 bsp_led_set(BSP_LED_AZURE, true);
234 } else {
235 bsp_led_set(BSP_LED_AZURE, false);
236 }
237 }
238 vTaskDelay(100 / portTICK_PERIOD_MS);
239 }
240}
dspm::Mat perspective_matrix(MATRIX_SIZE, MATRIX_SIZE)
static void draw_3d_image_task(void *arg)
RTOS task to draw a 3d image.
const float image_3d_matrix_esp_logo[1427][4]
const float image_to_3d_matrix_custom[1732][4]
void update_translation_matrix(dspm::Mat &T_m, bool row, float move_x, float move_y, float move_z)
update translation matrix
void update_scaling_matrix(dspm::Mat &T_m, bool keep_diagonal, float scale_x, float scale_y, float scale_z)
update scaling matrix
void init_perspective_matrix(dspm::Mat &P_m)
initialize perspective projection matrix
void update_rotation_matrix(dspm::Mat &T_m, float rot_x, float rot_y, float rot_z)
update rotation matrix
struct image_3d_matrix_s image_3d_matrix_t
Data struct of 3d image matrix.
Matrix.
Definition mat.h:30
static Mat eye(int size)
Definition mat.cpp:394
int rows
Definition mat.h:33
This class is used to process and calculate attitude from imu sensors.
dspm::Mat perspective_matrix(MATRIX_SIZE, MATRIX_SIZE)
static void dispaly_esp_text(void)
Display ESPRESSIF text.
static void init_3d_matrix_struct(image_3d_matrix_t *image)
Initialize 3d image structure.
static void display_3d_image(dspm::Mat projected_image)
Display a 3d image.
static void draw_3d_image_task(void *arg)
RTOS task to draw a 3d image.
static void app_ssd1306_init(void)
Initialize display.