Object gets smaller when rotated

I have made a 3D renderer for my Arduino nano 33IoT moving works but when i try to rotate the cube gets smaller and smaller until it becomes a line. Can anyone help me?

The code:

#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // Instanziierung

int point[3] = {2, 1, 1};
int fov = 20;
double pX = 0;
double pY = 0;
int middleX = SCREEN_WIDTH / 2;
int middleY = SCREEN_HEIGHT / 2;

int cube[8][3] = {
  {-15, 1, -15},//0
  {15, 1, -15},//1
  {-15, 1, 15},//2
  {15, 1, 15},//3
  {-15, 15, -15},//4
  {15, 15, -15},//5
  {-15, 15, 15},//6
  {15, 15, 15}//7
};

int vertex[12][2] = {
  {0,1},
  {0,2},
  {0,4},
  {3,2},
  {3,1},
  {3,7},
  {6,2},
  {6,4},
  {6,7},
  {5,1},
  {5,4},
  {5,7}
};

double points[8][2] = {
  {0,0},//0
  {0,0},//1
  {0,0},
  {0,0},
  {0,0},
  {0,0},
  {0,0},
  {0,0}
};

void setup() {
  // put your setup code here, to run once:
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
  display.display();
  Serial.begin(9600);
  render();
  display.display();
  delay(1000);
  for (int i = 0; i < 10; i++) {
    rotateY(0.1);
    delay(10);
    render();
    display.display();
  }

}



void loop() {

}





void render() {
  display.clearDisplay();
  for (int i = 0; i < 8; i++) {
    double sum1 = cube[i][0] * fov;
    double sum2 = cube[i][1] + fov;
    pX = sum1 / sum2 + middleX;
    sum1 = cube[i][2] * fov;
    sum2 = cube[i][1] + fov;
    pY = sum1 / sum2  + middleY;
    Serial.print(pX);
    Serial.println(pY);
    points[i][0] = pX;
    points[i][1] = pY;
    //display.drawPixel(pX, pY, WHITE);
  }
  Serial.println(vertex[0][0]);
  Serial.println(vertex[0][1]);
  Serial.println(points[0][0]);
  Serial.println(points[0][1]);
  for (int i = 0; i < 12; i++) {
    display.drawLine(points[vertex[i][0]][0], points[vertex[i][0]][1], points[vertex[i][1]][0], points[vertex[i][1]][1], WHITE);
  }
}


void move(int amount) {
  for (int i = 0; i < 8; i++) {
    cube[i][2] = cube[i][2] += amount;
  }
  render();
  display.display();
  delay(10);
}

void rotateX(double angle) {
    double cosTheta = cos(angle);
    double sinTheta = sin(angle);

    for (int i = 0; i < 8; i++) {
        double y = cube[i][1];
        double z = cube[i][2];
        cube[i][1] = y * cosTheta - z * sinTheta;
        cube[i][2] = y * sinTheta + z * cosTheta;
    }
}

void rotateY(double angle) {
    double cosTheta = cos(angle);
    double sinTheta = sin(angle);

    for (int i = 0; i < 8; i++) {
        double x = cube[i][0];
        double z = cube[i][2];
        cube[i][0] = x * cosTheta + z * sinTheta;
        cube[i][2] = -x * sinTheta + z * cosTheta;
    }
  
}

The reduction is size makes it clear that transformation you are applying is nonunitary. But the code is rather obscure, and you are including a perspective transformation.

If these are supposed to be the orthogonal, XYZ coordinates of a 3D cube, what is the "1" doing? This looks like a rectangular prism:

int cube[8][3] = {
  {-15, 1, -15},//0
  {15, 1, -15},//1

That's code of a not very experienced coder. It could be reduced to
cube[i][2] += amount;
and all transformations should be made from original data into a temporary array, to prevent any losses.

I'd look for a better library.

UPIR on youtube does a great job of making his cube "rotate in 3D"... maybe examine his code (and use his libraries).
The video...

The simulation...

Thank you I will try to implement his code :pray:

The one was my fault. The 1 is the depth but it could also be a 0.

What do you mean with a different library?
Do you mean Adafruit?

If those are Cartesian coordinates, that coordinate would be -15, for a cube.

It appears that you are using unconventional axis designations, which makes your code extremely difficult to interpret. Add comments explaining your choices.

I suggest to study some other coding examples for object rotation.

I know its pretty confusing but this was my first attempt so its all a bit strange

That is fine for a first attempt, but you can't expect us to interpret unconventional notation without explanation.

Yes i understand

I have modified my code to work with Adafruit:

#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // Instanziierung

int points[8][2]; // eight 2D points for the cube, values will be calculated in the code

int orig_points [8][3] = {  // eight 3D points - set values for 3D cube
{-1,-1, 1},
{1,-1,1},
{1,1,1},
{-1,1,1},
{-1,-1,-1},
{1,-1,-1},
{1,1,-1},
{-1,1,-1}
};

float rotated_3d_points [8][3];   // eight 3D points - rotated around Y axis
float angle_deg = 60.0;           // rotation around the Y axis
float z_offset = -4.0;            // offset on Z axis
float cube_size = 70.0;           // cube size (multiplier)
float time_frame;                 // ever increasing time value

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
  display.display();
}

void loop() {
  // put your main code here, to run repeatedly:
  time_frame++;                                // increase the time frame value by 1
  cube_size = 50 + sin(time_frame * 0.2)*20;   // oscilate cube size between values 30 - 70

  //z_offset =  -2.0;    // 
  //cube_size = 18.0;    // uncomment those two lines for a "wide angle camera" -- bigger perspective distort

  // increase the angle by 5° increments
  if (angle_deg < 90-5) {
    angle_deg = angle_deg + 5;
  } else {
    angle_deg = 0;
  }

  // calculate the points
  for (int i=0; i<8; i++) {
    // rotate 3d points around the Y axis (rotating X nad Z positions)
    rotated_3d_points [i][0] = orig_points [i][0] * cos(radians(angle_deg)) - orig_points [i][2] * sin(radians(angle_deg));
    rotated_3d_points [i][1] = orig_points [i][1];
    rotated_3d_points [i][2] = orig_points [i][0] * sin(radians(angle_deg)) + orig_points [i][2] * cos(radians(angle_deg)) + z_offset;  

    // project 3d points into 2d space with perspective divide -- 2D x = x/z,   2D y = y/z
    points[i][0] = round(64 + rotated_3d_points [i][0] / rotated_3d_points [i][2] * cube_size);
    points[i][1] = round(32 + rotated_3d_points [i][1] / rotated_3d_points [i][2] * cube_size); 
    Serial.println(points[i][0]);
    Serial.println(points[i][1]);
  }

  display.drawLine(points[ 0 ][ 0 ], points[ 0 ][ 1 ] , points[ 1 ][ 0 ] , points[ 1 ][ 1 ], WHITE);
  display.drawLine(points[ 1 ][ 0 ], points[ 1 ][ 1 ] , points[ 2 ][ 0 ] , points[ 2 ][ 1 ], WHITE);
  display.drawLine(points[ 2 ][ 0 ], points[ 2 ][ 1 ] , points[ 3 ][ 0 ] , points[ 3 ][ 1 ], WHITE);
  display.drawLine(points[ 3 ][ 0 ], points[ 3 ][ 1 ] , points[ 0 ][ 0 ] , points[ 0 ][ 1 ], WHITE);

  display.drawLine(points[ 4 ][ 0 ], points[ 4 ][ 1 ] , points[ 5 ][ 0 ] , points[ 5 ][ 1 ], WHITE);
  display.drawLine(points[ 5 ][ 0 ], points[ 5 ][ 1 ] , points[ 6 ][ 0 ] , points[ 6 ][ 1 ], WHITE);
  display.drawLine(points[ 6 ][ 0 ], points[ 6 ][ 1 ] , points[ 7 ][ 0 ] , points[ 7 ][ 1 ], WHITE);
  display.drawLine(points[ 7 ][ 0 ], points[ 7 ][ 1 ] , points[ 4 ][ 0 ] , points[ 4 ][ 1 ], WHITE);

  display.drawLine(points[ 0 ][ 0 ], points[ 0 ][ 1 ] , points[ 4 ][ 0 ] , points[ 4 ][ 1 ], WHITE);
  display.drawLine(points[ 1 ][ 0 ], points[ 1 ][ 1 ] , points[ 5 ][ 0 ] , points[ 5 ][ 1 ], WHITE);
  display.drawLine(points[ 2 ][ 0 ], points[ 2 ][ 1 ] , points[ 6 ][ 0 ] , points[ 6 ][ 1 ], WHITE);
  display.drawLine(points[ 3 ][ 0 ], points[ 3 ][ 1 ] , points[ 7 ][ 0 ] , points[ 7 ][ 1 ], WHITE);
  display.display();
  display.clearDisplay();
}

Good job!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.