ESP32开发进阶:OLED屏幕显示旋转的3D模型

一、硬件接线

        我选择的是最常见的一块板子:ESP-WROOM-32,硬件接线如下:

  •         21 - SDA
  •         22 - SCL

二、Arduino端代码

        我们使用Arduino和Adafruit SSD1306库在OLED显示屏上绘制和旋转一个3D立方体。        

        首先,定义立方体顶点和边:

        `aa`, `bb`, `cc`:定义立方体的8个顶点的x, y, z坐标。
        `ff`, `gg`:定义立方体的12条边的起始和终止顶点索引。

const signed int aa[8] = {8, -8, -8, 8, 8, -8, -8, 8}; // x
const signed int bb[8] = {8, 8, -8, -8, 8, 8, -8, -8}; // y
const signed int cc[8] = {-8, -8, -8, -8, 8, 8, 8, 8}; // z

const int ff[12] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3}; // start
const int gg[12] = {1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7}; // end

        接着,初始化旋转角度:

        `rotx`, `roty`, `rotz`:定义绕x轴、y轴和z轴的旋转角度。

float rotx = 0.0;
float roty = 0.0;
float rotz = 0.0;

        然后,计算旋转后的立方体顶点,并在OLED屏幕上绘制,定义`Disply3D`函数:计算旋转矩阵(绕x, y, z轴的旋转矩阵),遍历每个顶点,应用旋转矩阵,更新顶点坐标。将每个顶点的3D坐标转换为2D屏幕坐标。清空显示屏并绘制立方体的12条边。

        最后,在主函数里不断循环更新立方体的旋转角度,并调用 `Disply3D` 函数进行绘制。

        完整代码如下:

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <math.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const signed int aa[8] = {8, -8, -8, 8, 8, -8, -8, 8}; // x 
const signed int bb[8] = {8, 8, -8, -8, 8, 8, -8, -8}; // y 
const signed int cc[8] = {-8, -8, -8, -8, 8, 8, 8, 8}; // z

const int ff[12] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3}; // start
const int gg[12] = {1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7}; // end

float rotx = 0.0;
float roty = 0.0;
float rotz = 0.0;

void setup() {
  Serial.begin(9600);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  display.clearDisplay();
}

void Disply3D(float xpos, float ypos, float zpos) {
  int newx[8];
  int newy[8];
  float sinax = sin(rotx);
  float cosax = cos(rotx);
  float sinay = sin(roty);
  float cosay = cos(roty);
  float sinaz = sin(rotz);
  float cosaz = cos(rotz);

  for (int i = 0; i < 8; i++) 
  {
    
    float x = aa[i];
    float y = bb[i];
    float z = cc[i];

    float yt = y * cosax - z * sinax;
    float zt = y * sinax + z * cosax;
    y = yt;
    z = zt;

    float xt = x * cosay - z * sinay;
    zt = x * sinay + z * cosay;
    x = xt;
    z = zt;

    xt = x * cosaz - y * sinaz;
    yt = x * sinaz + y * cosaz;
    x = xt;
    y = yt;

    x = x + xpos;
    y = y + ypos;
    z = z + zpos;

    newx[i] = (x * 64 / z) + SCREEN_WIDTH / 2;
    newy[i] = (y * 64 / z) + SCREEN_HEIGHT / 2;
  }

  display.clearDisplay();
  for (int i = 0; i < 12; i++) {
    int vertex = ff[i];
    int sx = newx[vertex];
    int sy = newy[vertex];
    vertex = gg[i];
    int ex = newx[vertex];
    int ey = newy[vertex];
    display.drawLine(sx, sy, ex, ey, SSD1306_WHITE);
  }
  display.display();
}

void loop() {
  Disply3D(0, 0, 31);
  rotx += 0.02;
  roty += 0.03;
  rotz += 0.01;
  delay(50);
}

三、实际效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值