变换在操作屏幕上的对象方面起着非常重要的作用。应该注意的是,这里的算法将在代码中实现,并且不会使用内置函数来很好地理解算法的工作原理。
另请注意,所有转换都是在2D中实现的。
计算机图形学中存在三种基本类型的变换:
1. 翻译
2. 旋转
3. 缩放
算法
- 平移:平移是指将对象移动到屏幕上的不同位置。
Formula: X = x + tx Y = y + ty where tx and ty are translation coordinates The OpenGL function is glTranslatef( tx, ty, tz );
- 旋转:旋转是指旋转一个点。
Formula: X = xcosA - ysinA Y = xsinA + ycosA, A is the angle of rotation. The above formula will rotate the point around the origin. To rotate around a different point, the formula: X = cx + (x-cx)*cosA - (y-cy)*sinA, Y = cx + (x-cx)*sinA + (y-cy)*cosA, cx, cy is centre coordinates, A is the angle of rotation. The OpenGL function is glRotatef (A, x, y, z).
- 缩放:缩放是指跨轴以不同的比例放大和缩小对象。
Formula: X = x*sx Y = y*sy, sx, sy being scaling factors. The OpenGL function is glScalef(float x, float y, float z)
注意:如果要应用组合变换,请遵循以下顺序:平移、旋转、缩放
执行
// C code to implement basic
// transformations in OPENGL
#include
#include
#include
#include
// window size
#define maxWD 640
#define maxHT 480
// rotation speed
#define thetaSpeed 0.05
// this creates delay between two actions
void delay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock())
;
}
// this is a basic init for the glut window
void myInit(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, maxWD, 0.0, maxHT);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
// this function just draws a point
void drawPoint(int x, int y)
{
glPointSize(7.0);
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void rotateAroundPt(int px, int py, int cx, int cy)
{
float theta = 0.0;
while (1) {
glClear(GL_COLOR_BUFFER_BIT);
int xf, yf;
// update theta anticlockwise rotation
theta = theta + thetaSpeed;
// check overflow
if (theta >= (2.0 * 3.14159))
theta = theta - (2.0 * 3.14159);
// actual calculations..
xf = cx + (int)((float)(px - cx) * cos(theta))
- ((float)(py - cy) * sin(theta));
yf = cy + (int)((float)(px - cx) * sin(theta))
+ ((float)(py - cy) * cos(theta));
// drawing the centre point
drawPoint(cx, cy);
// drawing the rotating point
drawPoint(xf, yf);
glFlush();
// creating a delay
// so that the point can be noticed
delay(10);
}
}
// this function will translate the point
void translatePoint(int px, int py, int tx, int ty)
{
int fx = px, fy = py;
while (1) {
glClear(GL_COLOR_BUFFER_BIT);
// update
px = px + tx;
py = py + ty;
// check overflow to keep point in screen
if (px > maxWD || px < 0 || py > maxHT || py < 0) {
px = fx;
py = fy;
}
drawPoint(px, py); // drawing the point
glFlush();
// creating a delay
// so that the point can be noticed
delay(10);
}
}
// this function draws
void scalePoint(int px, int py, int sx, int sy)
{
int fx, fy;
while (1) {
glClear(GL_COLOR_BUFFER_BIT);
// update
fx = px * sx;
fy = py * sy;
drawPoint(fx, fy); // drawing the point
glFlush();
// creating a delay
// so that the point can be noticed
delay(500);
glClear(GL_COLOR_BUFFER_BIT);
// update
fx = px;
fy = py;
// drawing the point
drawPoint(fx, fy);
glFlush();
// creating a delay
// so that the point can be noticed
delay(500);
}
}
// Actual display function
void myDisplay(void)
{
int opt;
printf("\nEnter\n\t<1> for translation"
"\n\t<2> for rotation"
"\n\t<3> for scaling\n\t:");
scanf("%d", &opt);
printf("\nGo to the window...");
switch (opt) {
case 1:
translatePoint(100, 200, 1, 5);
break;
case 2:
rotateAroundPt(200, 200, maxWD / 2, maxHT / 2);
// point will circle around
// the centre of the window
break;
case 3:
scalePoint(10, 20, 2, 3);
break;
}
}
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(maxWD, maxHT);
glutInitWindowPosition(100, 150);
glutCreateWindow("Transforming point");
glutDisplayFunc(myDisplay);
myInit();
glutMainLoop();
}