main.cpp
C++ source for Real-time ray tracing on a round ESP32 display, 144 lines. Raw file
#include <string.h>
#include "bsp/display.h"
#include "bsp/esp32_s3_touch_amoled_1_75c.h"
#include "bsp/touch.h"
#include "esp_err.h"
#include "esp_heap_caps.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_touch.h"
#include "esp_log.h"
#include "raytrace2.h"
static const char *TAG = "raytrace2";
static const int k_strip = 20;
static void blit_rect(esp_lcd_panel_handle_t panel, const uint16_t *fb,
uint16_t *pack[2], int x0, int y0, int x1, int y1)
{
if (x0 < 0) {
x0 = 0;
}
if (y0 < 0) {
y0 = 0;
}
if (x1 > RT2_W) {
x1 = RT2_W;
}
if (y1 > RT2_H) {
y1 = RT2_H;
}
if (x0 >= x1 || y0 >= y1) {
return;
}
if (x0 == 0 && x1 == RT2_W) {
for (int y = y0; y < y1; y += k_strip) {
int y2 = y + k_strip;
if (y2 > y1) {
y2 = y1;
}
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(
panel, 0, y, RT2_W, y2, fb + y * RT2_W));
}
return;
}
int w = x1 - x0;
int which = 0;
for (int y = y0; y < y1; y += k_strip) {
int h = k_strip;
if (y + h > y1) {
h = y1 - y;
}
uint16_t *dst = pack[which];
which ^= 1;
for (int dy = 0; dy < h; dy++) {
memcpy(dst + dy * w, fb + (y + dy) * RT2_W + x0, (size_t)w * 2u);
}
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel, x0, y, x1, y + h, dst));
}
}
extern "C" void app_main(void)
{
const bsp_display_config_t cfg = {
.max_transfer_sz = BSP_LCD_H_RES * BSP_LCD_V_RES * BSP_LCD_BITS_PER_PIXEL / 8,
};
esp_lcd_panel_handle_t panel = nullptr;
esp_lcd_panel_io_handle_t io = nullptr;
ESP_ERROR_CHECK(bsp_display_new(&cfg, &panel, &io));
ESP_ERROR_CHECK(bsp_display_backlight_on());
bsp_display_cfg_t touch_cfg = {};
touch_cfg.touch_flags.swap_xy = 0;
touch_cfg.touch_flags.mirror_x = 1;
touch_cfg.touch_flags.mirror_y = 1;
esp_lcd_touch_handle_t tp = nullptr;
ESP_ERROR_CHECK(bsp_touch_new(&touch_cfg, &tp));
uint16_t *pack[2];
pack[0] = (uint16_t *)heap_caps_aligned_alloc(
64, (size_t)RT2_W * k_strip * 2,
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
pack[1] = (uint16_t *)heap_caps_aligned_alloc(
64, (size_t)RT2_W * k_strip * 2,
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
if (!pack[0] || !pack[1]) {
ESP_LOGE(TAG, "strip alloc failed");
return;
}
raytrace2_t fx;
if (raytrace2_init(&fx) != 0) {
ESP_LOGE(TAG, "raytrace2_init failed");
return;
}
ESP_LOGI(TAG, "raytrace2 %dx%d cells, %d tiles, %d corners",
RT2_GW, RT2_GH, fx.vis_n, fx.cvis_n);
uint32_t last = 0;
int down = 0;
int dragged = 0;
uint16_t sx = 0, sy = 0, lx = 0, ly = 0;
while (true) {
if (tp) {
if (esp_lcd_touch_read_data(tp) == ESP_OK) {
esp_lcd_touch_point_data_t pt = {};
uint8_t n = 0;
if (esp_lcd_touch_get_data(tp, &pt, &n, 1) == ESP_OK && n > 0) {
if (!down) {
sx = pt.x;
sy = pt.y;
dragged = 0;
} else {
int tdx = (int)pt.x - (int)sx;
int tdy = (int)pt.y - (int)sy;
if (tdx * tdx + tdy * tdy > 144) {
dragged = 1;
}
raytrace2_orbit(&fx, (float)((int)pt.x - (int)lx),
(float)((int)pt.y - (int)ly));
}
lx = pt.x;
ly = pt.y;
down = 1;
} else if (down) {
if (!dragged && sy >= RT2_H - 40) {
raytrace2_toggle_boxes(&fx);
}
down = 0;
}
}
}
raytrace2_frame(&fx);
raytrace2_draw_fps(&fx);
for (int i = 0; i < fx.flush_n; i++) {
blit_rect(panel, fx.pixels, pack,
fx.flush[i].x0, fx.flush[i].y0,
fx.flush[i].x1, fx.flush[i].y1);
}
if (fx.fps != last && fx.fps != 0) {
last = fx.fps;
ESP_LOGI(TAG, "%lu fps", (unsigned long)fx.fps);
}
}
}