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?
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=1anddots[i].y=0. We expect to get the new valuesdots[i].x=0anddots[i].y=1. When you execute the first line you getdots[i].x=0as expected, but in the next line you get also $0$, since you already replaceddots[i].xwith0. 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;