#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
const byte tftCSPin = 5;
const byte tftDCPin = 4;
Adafruit_ILI9341 tft = Adafruit_ILI9341(tftCSPin, tftDCPin);
int largeur, hauteur;
// Structure pour un point en 3D
struct Point3D {
int x;
int y;
int z;
};
// Structure pour un parallélépipède en 3D
/*
7--------6
/ /|
/ / |
3--------2 |
| | |
| 4-----|--5
| / | /
|/ |/
0--------1
*/struct Parallelepipede {
Point3D sommets[8];
};
// Définir les points du cube
constexpr int longueur = 50;
Parallelepipede cube = {
{
{0, 0, longueur}, // Sommet 0
{longueur, 0, longueur}, // Sommet 1
{longueur, longueur, longueur}, // Sommet 2
{ 0, longueur, longueur}, // Sommet 3
{ 0, 0, 0}, // Sommet 4
{longueur, 0, 0}, // Sommet 5
{longueur, longueur, 0}, // Sommet 6
{0, longueur, 0} // Sommet 7
}
};
enum AxeRotation {AxeX, AxeY, AxeZ};
// Fonction pour effectuer une rotation d'un point autour d'un axe
void rotationPoint(Point3D& point, AxeRotation axe, float angleDeg) {
float angleRad = angleDeg * PI / 180.0;
float cosA = cos(angleRad);
float sinA = sin(angleRad);
// Matrice de rotation
float matrice[3][3];
switch (axe) {
case AxeX:
matrice[0][0] = 1.0; matrice[0][1] = 0.0; matrice[0][2] = 0.0;
matrice[1][0] = 0.0; matrice[1][1] = cosA; matrice[1][2] = -sinA;
matrice[2][0] = 0.0; matrice[2][1] = sinA; matrice[2][2] = cosA;
break;
case AxeY:
matrice[0][0] = cosA; matrice[0][1] = 0.0; matrice[0][2] = sinA;
matrice[1][0] = 0.0; matrice[1][1] = 1.0; matrice[1][2] = 0.0;
matrice[2][0] = -sinA; matrice[2][1] = 0.0; matrice[2][2] = cosA;
break;
case AxeZ:
matrice[0][0] = cosA; matrice[0][1] = -sinA; matrice[0][2] = 0.0;
matrice[1][0] = sinA; matrice[1][1] = cosA; matrice[1][2] = 0.0;
matrice[2][0] = 0.0; matrice[2][1] = 0.0; matrice[2][2] = 1.0;
break;
}
// Multiplication de la matrice par le point
int x = point.x * matrice[0][0] + point.y * matrice[0][1] + point.z * matrice[0][2];
int y = point.x * matrice[1][0] + point.y * matrice[1][1] + point.z * matrice[1][2];
int z = point.x * matrice[2][0] + point.y * matrice[2][1] + point.z * matrice[2][2];
// Mettre à jour les coordonnées du point
point.x = x;
point.y = y;
point.z = z;
}
void rotationParallelepipede(const Parallelepipede& source, Parallelepipede& destination, AxeRotation axe, float angleDeg) {
for (int i = 0; i < 8; ++i) {
destination.sommets[i] = source.sommets[i];
rotationPoint(destination.sommets[i], axe, angleDeg);
}
}
void tracerLigne(const Point3D& p1, const Point3D& p2, uint16_t couleur) {
// Vecteur Z unitaire en projection (210°)
float angleZ = 210.0 * PI / 180.0;
float cosZ = cos(angleZ);
float sinZ = sin(angleZ);
// Matrice de projection
float matriceProjection[3][3] = {
{1.0, 0.0, cosZ},
{0.0, -1.0, -sinZ},
{0.0, 0.0, 0.0}
};
// Vecteur de translation
int translationX = largeur / 2;
int translationY = hauteur / 2;
// Appliquer la matrice de projection en 3D
float x1_proj = p1.x * matriceProjection[0][0] + p1.y * matriceProjection[0][1] + p1.z * matriceProjection[0][2];
float y1_proj = p1.x * matriceProjection[1][0] + p1.y * matriceProjection[1][1] + p1.z * matriceProjection[1][2];
float x2_proj = p2.x * matriceProjection[0][0] + p2.y * matriceProjection[0][1] + p2.z * matriceProjection[0][2];
float y2_proj = p2.x * matriceProjection[1][0] + p2.y * matriceProjection[1][1] + p2.z * matriceProjection[1][2];
// appliquer le vecteur translation en 2D
x1_proj += translationX;
y1_proj += translationY;
x2_proj += translationX;
y2_proj += translationY;
tft.drawLine(x1_proj, y1_proj, x2_proj, y2_proj, couleur);
}
void dessinerCube(const Parallelepipede& parallelepipede, uint16_t couleur) {
// Tracer la face avant
tracerLigne(parallelepipede.sommets[0], parallelepipede.sommets[1], couleur);
tracerLigne(parallelepipede.sommets[1], parallelepipede.sommets[2], couleur);
tracerLigne(parallelepipede.sommets[2], parallelepipede.sommets[3], couleur);
tracerLigne(parallelepipede.sommets[3], parallelepipede.sommets[0], couleur);
// Tracer la face arrière
tracerLigne(parallelepipede.sommets[4], parallelepipede.sommets[5], couleur);
tracerLigne(parallelepipede.sommets[5], parallelepipede.sommets[6], couleur);
tracerLigne(parallelepipede.sommets[6], parallelepipede.sommets[7], couleur);
tracerLigne(parallelepipede.sommets[7], parallelepipede.sommets[4], couleur);
// Tracer les lignes qui relient les sommets
tracerLigne(parallelepipede.sommets[0], parallelepipede.sommets[4], couleur);
tracerLigne(parallelepipede.sommets[1], parallelepipede.sommets[5], couleur);
tracerLigne(parallelepipede.sommets[2], parallelepipede.sommets[6], couleur);
tracerLigne(parallelepipede.sommets[3], parallelepipede.sommets[7], couleur);
}
void tracerAxes() {
const int L = max(largeur, hauteur); // on dessine des axes qui sortent de l'écran
tracerLigne({-L, 0, 0}, {L, 0, 0}, ILI9341_RED);
tracerLigne({0, -L, 0}, {0, L, 0}, ILI9341_GREEN);
tracerLigne({0, 0, -L}, {0, 0, L}, ILI9341_BLUE);
}
void setup() {
Serial.begin(115200);
tft.begin();
largeur = tft.width(); // 240
hauteur = tft.height(); // 320
// Centre du repère
int centreX = largeur / 2;
int centreY = hauteur / 2;
}
void loop() {
const unsigned long attente = 100;
const int deltaAngle = 20;
Parallelepipede modifCube = cube;
tft.fillScreen(ILI9341_BLACK); // Efface l'écran
for (int angle = 0; angle <= 360; angle += deltaAngle) {
rotationParallelepipede(cube, modifCube, AxeX, angle);
dessinerCube(modifCube, ILI9341_WHITE);
tracerAxes();
delay(attente);
dessinerCube(modifCube, ILI9341_BLACK);
}
tft.fillScreen(ILI9341_BLACK); // Efface l'écran
for (int angle = 0; angle <= 360; angle += deltaAngle) {
rotationParallelepipede(cube, modifCube, AxeY, angle);
dessinerCube(modifCube, ILI9341_WHITE);
tracerAxes();
delay(attente);
dessinerCube(modifCube, ILI9341_BLACK);
}
tft.fillScreen(ILI9341_BLACK); // Efface l'écran
for (int angle = 0; angle <= 360; angle += deltaAngle) {
rotationParallelepipede(cube, modifCube, AxeZ, angle);
dessinerCube(modifCube, ILI9341_WHITE);
tracerAxes();
delay(attente);
dessinerCube(modifCube, ILI9341_BLACK);
}
}