OpenGL——二维几何变换

平移、旋转、缩放的实现

#include<iostream>
#include <math.h>
#include<Windows.h>
#include <GL/glut.h>

using namespace std;

GLsizei winWidth = 600, winHeight = 600;

GLfloat xwcMin = 0.0, xwcMax = 225.0;
GLfloat ywcMin = 0.0, ywcMax = 225.0;


class wcPt2D {
public:
    GLfloat x, y;
};

typedef GLfloat Matrix3x3[3][3];

Matrix3x3 matComposite;

const GLdouble pi = 3.14159;


void init()
{
    //窗口背景为白色
    glClearColor(1.0, 1.0, 1.0, 0.0);
}

void matrix3x3SetIdentity(Matrix3x3 matIdent3x3)
{
    GLint row, col;
    for (row = 0; row < 3; row++) {
        for (col = 0; col < 3; col++) {
            matIdent3x3[row][col] = (row == col);
        }
    }
}

void matrix3x3PreMultiply(Matrix3x3 m1, Matrix3x3 m2)
{
    GLint row, col;
    Matrix3x3 matTemp;

    for (row = 0; row < 3; row++) {
        for (col = 0; col < 3; col++) {
            matTemp[row][col] = m1[row][0] * m2[0][col] + m1[row][1] * m2[1][col] +
                m1[row][2] * m2[2][col];
        }
    }

    for (row = 0; row < 3; row++) {
        for (col = 0; col < 3; col++) {
            m2[row][col] = matTemp[row][col];
        }
    }
}

void translate2D(GLfloat tx, GLfloat ty)
{
    Matrix3x3 matTransl;

    matrix3x3SetIdentity(matTransl);

    matTransl[0][2] = tx;
    matTransl[1][2] = ty;

    matrix3x3PreMultiply(matTransl, matComposite);
}

void rotate2D(wcPt2D pivotPt, GLfloat theta)
{
    Matrix3x3 matRot;

    matrix3x3SetIdentity(matRot);

    matRot[0][0] = cos(theta);
    matRot[0][1] = -sin(theta);
    matRot[0][2] = pivotPt.x * (1 - cos(theta)) + pivotPt.y * sin(theta);
    matRot[1][0] = sin(theta);
    matRot[1][1] = cos(theta);
    matRot[1][2] = pivotPt.y * (1 - cos(theta)) - pivotPt.x * sin(theta);

    matrix3x3PreMultiply(matRot, matComposite);
}

void scale2D(GLfloat sx, GLfloat sy, wcPt2D fixedPt)
{
    Matrix3x3 matScale;

    matrix3x3SetIdentity(matScale);

    matScale[0][0] = sx;
    matScale[0][2] = (1 - sx) * fixedPt.x;
    matScale[1][1] = sy;
    matScale[1][2] = (1 - sy) * fixedPt.y;

    matrix3x3PreMultiply(matScale, matComposite);
}


void transformVerts2D(GLint nVerts, wcPt2D * verts)
{
    GLint k;
    GLfloat temp;

    for (k = 0; k < nVerts; k++) {
        temp = matComposite[0][0] * verts[k].x + matComposite[0][1] * verts[k].y + matComposite[0][2];
        verts[k].y = matComposite[1][0] * verts[k].x + matComposite[1][1] * verts[k].y + matComposite[1][2];
        verts[k].x = temp;
    }
}

void triangle(wcPt2D *verts)
{
    glBegin(GL_TRIANGLES);
    for (GLint k = 0; k < 3; k++) {
        glVertex2f(verts[k].x, verts[k].y);
    }
    glEnd();
}


void displayFcn()
{    
    GLint nVerts = 3;

    wcPt2D verts[3] = { {50.0,25.0},{150.0,25.0},{100.0,100.0} };

    wcPt2D centroidPt;

    GLint xSum = 0, ySum = 0;

    for (GLint k = 0; k < nVerts; k++) {
        xSum += verts[k].x;
        ySum += verts[k].y;
    }

    centroidPt.x = GLfloat(xSum) / GLfloat(nVerts);
    centroidPt.y = GLfloat(ySum) / GLfloat(nVerts);

    wcPt2D pivPt, fixedPt;
    pivPt = centroidPt;
    fixedPt = centroidPt;
    GLfloat tx = 0.0, ty = 100.0;
    GLfloat sx = 0.5, sy = 0.5;
    GLdouble theta = pi / 2;
 
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(200.0 / 255.0, 200.0 / 255.0, 169.0 / 255.0);
    triangle(verts);

    matrix3x3SetIdentity(matComposite);

    scale2D(sx, sy, fixedPt);

    transformVerts2D(nVerts, verts);
    glColor3f(137.0 / 255.0, 190.0 / 255.0, 178.0 / 255.0);
    triangle(verts);


    matrix3x3SetIdentity(matComposite);
    rotate2D(pivPt, theta);
    transformVerts2D(nVerts, verts);
    glColor3f(69.0 / 255.0, 137.0 / 255.0, 148.0 / 255.0);
    triangle(verts);
    

    matrix3x3SetIdentity(matComposite);
    translate2D(tx, ty);
    transformVerts2D(nVerts, verts);
    glColor3f(178.0 / 255.0, 200.0 / 255.0, 187.0 / 255.0);
    triangle(verts);

    

    glFlush();
}

void winReshapeFcn(GLint newWidth, GLint newHeight)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(xwcMin, xwcMax, ywcMin, ywcMax);
    glClear(GL_COLOR_BUFFER_BIT);
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(50, 50);

    glutInitWindowSize(winWidth, winHeight);
    glutCreateWindow("二维几何变换");
    init();
    glutDisplayFunc(displayFcn);
    glutReshapeFunc(winReshapeFcn);
    glutMainLoop();

    system("pause");
    return 0;
}

运行结果

 

posted @ 2018-08-05 12:31  Not-Bad  阅读(1704)  评论(0编辑  收藏  举报