Because when I turn the scale decreases? (opengl)

36 Views Asked by At

I have a plan:

//    x    y   z
point(20, 20, 00);
point(25, 20, 00);
point(25, 25, 00);
point(20, 20, 00);

I try to rotate the plane with the following formula:

Rx = (Px * cos(angle_rad)) - (Py * sin(angle_rad));
Ry = (Px * sin(rotate_rad)) + (Py * cos(rotate_rad));

But by rotating several times the scale is diminished. How do I solve this?

The C program (OpenGL):

#include <GL/glut.h>
#include <math.h>
#include <stdio.h>

#define HEIGHT 500
#define WIDTH 500
#define POINTS 4

#define TRANSLATE 5
#define ROTATION 5.0
#define SCALE_M 0.5
#define SCALE_P 1.5

void display();
void specialKeys();

typedef struct {
  float x;
  float y;
  float z;
} Dot;

float rotate_y = 0;
float rotate_x = 0;
Dot dots[POINTS], orig[POINTS];
int i, translate = 0, rotate = 0, scale = 0, save = 0;
char typeRotate = '\0';
float rotate_rad = 0.0f, rotate_angle = 5.0f, angle = 0;

Dot point(float x, float y, float z) {
  Dot p;
  p.x = x;
  p.y = y;
  p.z = z;

  return p;
}

void createPoints() {
  // PONTO        X   Y   Z
  dots[0] = point(20, 20, 00);
  dots[1] = point(25, 20, 00);
  dots[2] = point(25, 25, 00);
  dots[3] = point(20, 20, 00);
}

void drawDot(float x, float y, float z) { glVertex3f(x / 30, y / 30, z / 30); }

void display() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  glRotatef(rotate_x, 1.0, 0.0, 0.0);
  glRotatef(rotate_y, 0.0, 1.0, 0.0);

  glBegin(GL_POLYGON);
  glColor3f(1.0, 1.0, 0.0);
  for (i = 0; i < POINTS; i++)
    drawDot(dots[i].x, dots[i].y, dots[i].z);

  glEnd();

  glFlush();
  glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y) {
  if (key == 't') {
    rotate = 0;
    scale = 0;
    if (translate == 0) {
      translate = 1;
      printf("Translação foi ativada.\n");
    } else {
      translate = 0;
      printf("Translação foi desativada.\n");
    }

  } else if (key == '-' && translate == 1) {
    for (i = 0; i < POINTS; i++) {
      dots[i].x -= TRANSLATE;
      dots[i].y -= TRANSLATE;
      dots[i].z -= TRANSLATE;
    }
  } else if (key == '+' && translate == 1) {
    for (i = 0; i < POINTS; i++) {
      dots[i].x += TRANSLATE;
      dots[i].y += TRANSLATE;
      dots[i].z += TRANSLATE;
    }
  }

  else if (key == 'r') {
    scale = 0;
    translate = 0;
    if (rotate == 0) {
      rotate = 1;
      printf("Rotação foi ativada.\n");
    } else {
      rotate = 0;
      printf("Rotação foi desativada.\n");
    }
  } else if (key == '-' && rotate == 1) {
    typeRotate = '-';
    rotate_rad = -ROTATION / 360 * 2 * M_PI;
    printf("Rotação será negativa.\n");
  } else if (key == '+' && rotate == 1) {
    typeRotate = '+';
    rotate_rad = ROTATION / 360 * 2 * M_PI;
    printf("Rotação será positiva.\n");
  } else if (key == 'x' && rotate == 1) {
    for (i = 0; i < POINTS; i++) {
      dots[i].y = (dots[i].y * cos(rotate_rad)) - (dots[i].z * sin(rotate_rad));
      dots[i].z = (dots[i].y * sin(rotate_rad)) + (dots[i].z * cos(rotate_rad));
    }
  } else if (key == 'y' && rotate == 1) {
    for (i = 0; i < POINTS; i++) {
      dots[i].z = (dots[i].z * cos(rotate_rad)) - (dots[i].x * sin(rotate_rad));
      dots[i].x = (dots[i].z * sin(rotate_rad)) + (dots[i].x * cos(rotate_rad));
    }
  } else if (key == 'z' && rotate == 1) {
    for (i = 0; i < POINTS; i++) {

      dots[i].x = (dots[i].x * cos(rotate_rad)) - (dots[i].y * sin(rotate_rad));
      dots[i].y = (dots[i].x * sin(rotate_rad)) + (dots[i].y * cos(rotate_rad));
    }
  }

  else if (key == 's') {
    rotate = 0;
    translate = 0;
    if (scale == 0) {
      scale = 1;
      printf("Escala foi ativada.\n");
    } else {
      scale = 0;
      printf("Escala foi desativada.\n");
    }
  } else if (key == '-' && scale == 1) {
    for (i = 0; i < POINTS; i++) {
      dots[i].x *= SCALE_M;
      dots[i].y *= SCALE_M;
      dots[i].z *= SCALE_M;
    }

  } else if (key == '+' && scale == 1) {
    for (i = 0; i < POINTS; i++) {
      dots[i].x *= SCALE_P;
      dots[i].y *= SCALE_P;
      dots[i].z *= SCALE_P;
    }
  }
  glutPostRedisplay();
}

void special(int key, int x, int y) {
  if (key == GLUT_KEY_RIGHT)
    rotate_y += rotate_angle;
  else if (key == GLUT_KEY_LEFT)
    rotate_y -= rotate_angle;
  else if (key == GLUT_KEY_UP)
    rotate_x += rotate_angle;
  else if (key == GLUT_KEY_DOWN)
    rotate_x -= rotate_angle;

  glutPostRedisplay();
}

int main(int argc, char *argv[]) {
  createPoints();
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(WIDTH, HEIGHT);
  glutInitWindowPosition(150, 150);
  glutCreateWindow("Exercicio Lista");
  glEnable(GL_DEPTH_TEST);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);
  glutSpecialFunc(special);
  glutMainLoop();

  return 0;
}

To test, press 'r', then press '+' and then hold 'z' to rotate on the z-axis.

If possible, how to adapt the formula to rotate in a given coordinate? As the center of the plan?

1

There are 1 best solutions below

0
On

The problem is the implementation, not the formula.

dots[i].x = (dots[i].x * cos(rotate_rad)) - (dots[i].y * sin(rotate_rad)); dots[i].y = (dots[i].x * sin(rotate_rad)) + (dots[i].y * cos(rotate_rad));

Let's try to rotate by $\pi/2$. $\cos(\pi/2)=0$ and $\sin(\pi/2)=1$. And let's have dots[i].x=1 and dots[i].y=0. We expect to get the new values dots[i].x=0 and dots[i].y=1. When you execute the first line you get dots[i].x=0 as expected, but in the next line you get also $0$, since you already replaced dots[i].x with 0. Try something like:

temp = (dots[i].x * cos(rotate_rad)) - (dots[i].y * sin(rotate_rad)); dots[i].y = (dots[i].x * sin(rotate_rad)) + (dots[i].y * cos(rotate_rad)); dots[i].x = temp;