from machine import Pin, SoftI2C
from ssd1306 import SSD1306_I2C
import math
import utime
# --- ディスプレイのセットアップ ---
# I2C通信の設定 (SCL=GP1, SDA=GP0) [cite: 830-833]
i2c = SoftI2C(scl=Pin(1), sda=Pin(0))
# ディスプレイの設定 (幅128, 高さ64) [cite: 975]
display = SSD1306_I2C(128, 64, i2c)
# --- 立方体のデータ定義 ---
# 立方体のサイズ
size = 20
# 8つの頂点の座標 (x, y, z)
# 原点(0,0,0)を中心とした立方体
points = [
[-size, -size, -size], [size, -size, -size], [size, size, -size], [-size, size, -size],
[-size, -size, size], [size, -size, size], [size, size, size], [-size, size, size]
]
# 辺のつながり (頂点のインデックス番号のペア)
# これに従って線を引く
edges = [
[0,1], [1,2], [2,3], [3,0], # 奥の面
[4,5], [5,6], [6,7], [7,4], # 手前の面
[0,4], [1,5], [2,6], [3,7] # 前後をつなぐ線
]
# 回転角度の初期値
angle_x = 0.0
angle_y = 0.0
# --- メインループ ---
while True:
# 画面をクリア
display.fill(0)
# 計算後の2D座標を保存するリスト
projected_points = []
# 1. すべての頂点を回転・投影する
for p in points:
x = p[0]
y = p[1]
z = p[2]
# X軸周りの回転
ry = y * math.cos(angle_x) - z * math.sin(angle_x)
rz = y * math.sin(angle_x) + z * math.cos(angle_x)
y = ry
z = rz
# Y軸周りの回転
rx = x * math.cos(angle_y) - z * math.sin(angle_y)
rz = x * math.sin(angle_y) + z * math.cos(angle_y)
x = rx
z = rz
# 簡易的な透視投影 (遠近法)
# カメラからの距離を適当に設定 (z + 60) して割ることで、
# 奥にある(zが小さい)ものほど中心に寄るようにする
scale = 120 / (z + 60)
# 画面の中心 (64, 32) に持ってくる
px = int(x * scale + 64)
py = int(y * scale + 32)
projected_points.append([px, py])
# 2. 線を描画する
for edge in edges:
# つなぐ2つの頂点の座標を取得
p1 = projected_points[edge[0]]
p2 = projected_points[edge[1]]
# 線を引く (x1, y1, x2, y2, 色)
display.line(p1[0], p1[1], p2[0], p2[1], 1)
# 画面に反映
display.show()
# 角度を更新 (回転スピード)
angle_x += 0.05
angle_y += 0.08
# 少し待つ (速すぎる場合はここを増やす)
# utime.sleep(0.01)