Micropython 之 旋转立方块

入门 ESP32-C3,学习Micropython还是先从自己手上的模块开始,MPU6050是一个很好的选择,很多场合都用得上。记得几年前用STM32F103接过MPU6050,然后用匿名上位机观测模拟飞机的飞控状态:横滚,俯仰,旋转,然后就没有了。资料看着看着,有一个旋转立方块的范例,用SSD1306 OLED屏显示,于是用面包板接线,修改I2C的接脚后就看到立方块转起来。

想想立方块的旋转也能和陀螺仪结合,但是是如何产生立方块和如何旋转的呢?区区40几行的代码就能完成这个动作有点神奇,开始分析代码发现,自己的数学没学好:向量,矩阵和线性代数一塌糊涂。于是开启了自我补课之旅,先把ESP32-C3 和 micropython放一边,在 慕课网 和 哔哩哔哩 下载一堆线性代数,矩阵变换:

 

 看得似懂非懂的,好像跟我的旋转立方块有关系,但又不是很直接,线性代数得水很深,我怕陷进去走岔了。

今天看到一篇 知乎 (超详细!)计算机图形学 入门篇 1. 变换矩阵,课程资料来源于《Fundamentals of Computer Graphics》以及闫老师的GAMES 101课程GAMES101: 现代计算机图形学入门,原来这个视频集我已经下载过了,而且只有前面4个视频是我所需要的,就顺便把pdf课件也下载:

 

 边看视频,边在pdf课件里做笔记:二维矩阵对向量的变换,推广到三维矩阵对向量的变换,不就是我需要的知识吗。学习完这个视频教材,回头再来分析旋转立方块,呵呵还能看出不规整的地方,做了一些排版,增加了自己了解后的注释:

 1 # -*- coding: UTF-8 -*-
 2 # 合宙CORE ESP32-C3 核心板板载2颗LED +  16MB Flash(原4MB)
 3 # (GPIO12) D4 GND, 高电平有效
 4 # (GPIO13) D5 GND, 高电平有效
 5 
 6 from math import cos, sin, pi
 7 from machine import SoftI2C, Pin
 8 from ssd1306 import SSD1306_I2C
 9 
10 cube = [[-15, -15, -15], [-15, 15, -15], [15, 15, -15], [15, -15, -15], # 下方逆时针4点向量:1,2,3,4
11         [-15, -15, 15], [-15, 15, 15], [15, 15, 15], [15, -15, 15]] # 上方逆时针4点向量:5,6,7,8
12 lineid = [1, 2, 2, 3, 3, 4, 4, 1, # 下方逆时针2点一线,4线段
13           5, 6, 6, 7, 7, 8, 8, 5, # 上方逆时针2点一线,4线段
14           8, 4, 7, 3, 6, 2, 5, 1] # 上下垂直2点一线,4线段
15 
16 i2c = SoftI2C(scl=Pin(0), sda=Pin(1))
17 oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)
18 oled.fill(0)
19 
20 
21 def matconv(a, matrix): # M(3x3) * a(3x1) 
22     res = [0, 0, 0]
23     for i in range(0, 3):
24         res[i] = matrix[i][0] * a[0] + matrix[i][1] * a[1] + matrix[i][2] * a[2]
25     for i in range(0, 3):
26         a[i] = res[i]
27     return a # a(3x1)
28 
29 
30 def rotate(obj, x, y, z):
31     x = x / pi
32     y = y / pi
33     z = z / pi
34     rx = [[1, 0, 0], [0, cos(x), -sin(x)], [0, sin(x), cos(x)]]
35     ry = [[cos(y), 0, sin(y)], [0, 1, 0], [-sin(y), 0, cos(y)]]
36     rz = [[cos(z), -sin(z), 0], [sin(z), cos(z), 0], [0, 0, 1]]
37     matconv(matconv(matconv(obj, rz), ry), rx)
38 
39 def drawcube(x, y, z):
40     oled.fill(0)
41     for i in range(0, 8):
42         rotate(cube[i], x, y, z)
43     for i in range(0, 24, 2):
44         x1 = int(64 + cube[lineid[i] - 1][0]) # 128/2 = 64
45         y1 = int(32 + cube[lineid[i] - 1][1]) #  64/2 = 32, no z1 [2]
46         x2 = int(64 + cube[lineid[i + 1] - 1][0]) # 128/2 = 64
47         y2 = int(32 + cube[lineid[i + 1] - 1][1]) #  64/2 = 32, no z2 [2]
48         oled.line(x1, y1, x2, y2, 1)
49 #         print(lineid[i], cube[lineid[i] - 1][0],     cube[lineid[i] - 1][1],
50 #               lineid[i+1], cube[lineid[i + 1] - 1][0], cube[lineid[i + 1] - 1][1])
51     oled.show()
52 
53 cnt = 0
54 while 1:
55     drawcube(0.1, 0.2, 0.3)
56     print(cnt, end=' ')
57     cnt += 1
View Code

 

 

posted @ 2023-02-03 03:30  mickey_163  阅读(141)  评论(0编辑  收藏  举报