OpenGL - 国旗绘制(五角星绘制)

绘制目标

OpenGL - 国旗绘制(五角星绘制)_第1张图片

主要是五角星的绘制,怎样才能优雅地绘制出准确的五角星呢?

分析

OpenGL - 国旗绘制(五角星绘制)_第2张图片

整体思路:

通过画五个金色的四边形来完成对五角星的绘制
通过P、Q两点的坐标,计算出M、N的坐标,进而绘制出四边形。
然后根据P、Q坐标,计算出其他四个五角星顶点的坐标,依上法绘制其余四边形
完成五角星绘制

角度计算:

根据两个条件:

  • QMN在M处的外角是正五边形的一个内角 108
  • QMN 是等腰三角形

在QMN中的角度列方程组,计算得Q为36
同时,P 是五分之一圆周角, 72

OpenGL - 国旗绘制(五角星绘制)_第3张图片

顶点计算:

根据MPH 和 MQH 的tan 关系, 可以得到:

  • |PH| = tan18/(tan36+tan18) |PQ|
  • |HM| = tan36 |PH|

可以得到向量关系:

  • PH = tan18/(tan36+tan18) PQ
  • HM = tan36 (PH的垂直向量)

可根据向量关系由P、Q坐标算M、N的坐标

其他四个顶点计算:

OpenGL - 国旗绘制(五角星绘制)_第4张图片
依据上图方式计算旋转向量
然后通过向量计算顶点位置

代码实现

五角星整体函数

void mglstar5(GLfloat centerX, GLfloat centerY, GLfloat endX, GLfloat endY){
    for (int i = 0; i < 5; i++)
    {
        mglstar5_part(centerX, centerY, endX, endY);
        rotate(centerX, centerY, &endX, &endY, 2*PI/5); 
    }
}
依次根据(centerX, centerY) (endX, endY)来绘制五分之一五角星四边形
并对该向量进行一次旋转72度操作

旋转函数

void rotate(GLfloat centerX, GLfloat centerY, GLfloat* endX, GLfloat* endY, float rad){
    Vector2f vector = { *endX - centerX, *endY - centerY };
    Vector2f resultV = {
        cos(rad) * vector.x + sin(rad) * vector.y,
        cos(rad) * vector.y + sin(rad) * (-vector.x)
    };

    *endX = centerX + resultV.x;
    *endY = centerY + resultV.y;
}

根据上步理论分析
计算出旋转中心到端点的向量
并以此求出新的坐标
将新坐标存入原地址

四边形绘制函数

void mglstar5_part(GLfloat centerX, GLfloat centerY, GLfloat endX, GLfloat endY){
    float cf1 = tan(PI / 10) / (tan(PI / 5) + tan(PI / 10));
    float cf2 = tan(PI / 5);

    Vector2f PQ = { endX - centerX, endY - centerY };
    Vector2f PH = { cf1 * PQ.x, cf1 * PQ.y };
    Vector2f HM = { cf2 * PH.y, cf2 * (-PH.x) };

    Vector2f M = { centerX + PH.x + HM.x, centerY + PH.y + HM.y };
    Vector2f N = { centerX + PH.x - HM.x, centerY + PH.y - HM.y };

    glBegin(GL_POLYGON);
    glVertex2f(centerX, centerY);
    glVertex2f(M.x, M.y);
    glVertex2f(endX, endY);
    glVertex2f(N.x, N.y);
    glEnd();
}

先根据上一步的理论分析算出四个顶点,然后再绘制四边形

Display函数

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1, 0, 0);
    glBegin(GL_QUADS);
    glVertex2f(-0.9, 0.6);
    glVertex2f(0.9, 0.6);
    glVertex2f(0.9, -0.6);
    glVertex2f(-0.9, -0.6);
    glEnd();

    glColor3f(1, 1, 0);
    //main star
    mglstar5(-0.60, 0.30, -0.78, 0.36);
    //four-star
    mglstar5(-0.30, 0.48, -0.24, 0.48);
    mglstar5(-0.18, 0.36, -0.24, 0.36);
    mglstar5(-0.18, 0.18, -0.18, 0.24);
    mglstar5(-0.30, 0.06, -0.24, 0.06);

    glutSwapBuffers();
}

根据国旗比例,在合适位置调用五角星函数绘制

实验结果

OpenGL - 国旗绘制(五角星绘制)_第5张图片

源码

#include "gl/glut.h"
#include 

#define PI 3.1415926535898

typedef struct Vector2fDefine
{
    GLfloat x;
    GLfloat y;
} Vector2f;

void mglstar5(GLfloat centerX, GLfloat centerY, GLfloat endX, GLfloat endY);
void rotate(GLfloat centerX, GLfloat centerY, GLfloat* endX, GLfloat* endY, float rad);
void mglstar5_part(GLfloat centerX, GLfloat centerY, GLfloat endX, GLfloat endY);

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1, 0, 0);
    glBegin(GL_QUADS);
    glVertex2f(-0.9, 0.6);
    glVertex2f(0.9, 0.6);
    glVertex2f(0.9, -0.6);
    glVertex2f(-0.9, -0.6);
    glEnd();

    glColor3f(1, 1, 0);
    //main star
    mglstar5(-0.60, 0.30, -0.78, 0.36);
    //four-star
    mglstar5(-0.30, 0.48, -0.24, 0.48);
    mglstar5(-0.18, 0.36, -0.24, 0.36);
    mglstar5(-0.18, 0.18, -0.18, 0.24);
    mglstar5(-0.30, 0.06, -0.24, 0.06);

    glutSwapBuffers();
}

int main (int argc,  char *argv[])
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
    glutInitWindowPosition(10, 10);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Simple GLUT App");

    glutDisplayFunc(display);

    glutMainLoop();

    return 0;
}

void mglstar5(GLfloat centerX, GLfloat centerY, GLfloat endX, GLfloat endY){
    for (int i = 0; i < 5; i++)
    {
        mglstar5_part(centerX, centerY, endX, endY);
        rotate(centerX, centerY, &endX, &endY, 2*PI/5); 
    }
}

void mglstar5_part(GLfloat centerX, GLfloat centerY, GLfloat endX, GLfloat endY){
    float cf1 = tan(PI / 10) / (tan(PI / 5) + tan(PI / 10));
    float cf2 = tan(PI / 5);

    Vector2f PQ = { endX - centerX, endY - centerY };
    Vector2f PH = { cf1 * PQ.x, cf1 * PQ.y };
    Vector2f HM = { cf2 * PH.y, cf2 * (-PH.x) };

    Vector2f M = { centerX + PH.x + HM.x, centerY + PH.y + HM.y };
    Vector2f N = { centerX + PH.x - HM.x, centerY + PH.y - HM.y };

    glBegin(GL_POLYGON);
    glVertex2f(centerX, centerY);
    glVertex2f(M.x, M.y);
    glVertex2f(endX, endY);
    glVertex2f(N.x, N.y);
    glEnd();
}

void rotate(GLfloat centerX, GLfloat centerY, GLfloat* endX, GLfloat* endY, float rad){
    Vector2f vector = { *endX - centerX, *endY - centerY };
    Vector2f resultV = {
        cos(rad) * vector.x + sin(rad) * vector.y,
        cos(rad) * vector.y + sin(rad) * (-vector.x)
    };

    *endX = centerX + resultV.x;
    *endY = centerY + resultV.y;
}

你可能感兴趣的:(opengl)