OpenGL 蓝书学习(第四版)第四章

OpenGL 蓝书学习(第四版)第四章

总共22章等着我学习🥹

绘制一个 原子

// mac 特有的头文件
#include <GLUT/glut.h>
#include <OpenGL/gl.h>

#include <iostream>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;

void renderScene() {
    static GLfloat angle = 0.0F;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW); // 模型视图矩阵
    glLoadIdentity();                // 重置模型视图矩阵为单位矩阵

    glTranslatef(0.0F, 0.0F, -100.0F);

    glColor3ub(255, 0, 0);
    glutSolidSphere(10.0F, 15, 15);

    glColor3ub(255, 255, 0);

    glPushMatrix();
    glRotatef(angle, 0.0F, 1.0F, 0.0F);
    glTranslatef(90.0F, 0.0F, 0.0F);
    glutSolidSphere(6.0F, 15, 15);
    glPopMatrix();

    // 第二个
    glPushMatrix();
    glRotatef(45.0F, 0.0F, 0.0F, 1.0F);
    glRotatef(angle, 0.0F, 1.0F, 0.0F);
    glTranslatef(-70.0F, 0.0F, 0.0F);
    glutSolidSphere(6.0F, 15, 15);
    glPopMatrix();

    // 第三个电子
    glPushMatrix();
    glRotatef(360.0F - 45.0F, 0.0F, 0.0F, 1.0F);
    glRotatef(angle, 0.0F, 1.0F, 0.0F);
    glTranslatef(0.0F, 0.0F, 60.0F);
    glutSolidSphere(6.0F, 15, 15);
    glPopMatrix();

    angle += 10.0F;
    if (angle > 360.0F) {
        angle = 0.0F;
    }

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(100, timerFunc, 1);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    if (w < h) {
        glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE * 2.0F);
    } else {
        glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE, COORDINATE_SIZE * 2.0F);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutTimerFunc(500, timerFunc, 1);
    glutReshapeFunc(changeSize);
    setupRc();
    glutMainLoop();
    return 0;
}

绘制原子(使用透视投影)

// mac 特有的头文件
#include <GLUT/glut.h>
#include <OpenGL/gl.h>

#include <iostream>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;

void renderScene() {
    static GLfloat angle = 0.0F;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW); // 模型视图矩阵
    glLoadIdentity();                // 重置模型视图矩阵为单位矩阵

    glTranslatef(0.0F, 0.0F, -200.0F);

    glColor3ub(255, 0, 0);
    glutSolidSphere(10.0F, 15, 15);

    glColor3ub(255, 255, 0);

    glPushMatrix();
    glRotatef(angle, 0.0F, 1.0F, 0.0F);
    glTranslatef(90.0F, 0.0F, 0.0F);
    glutSolidSphere(6.0F, 15, 15);
    glPopMatrix();

    // 第二个
    glPushMatrix();
    glRotatef(45.0F, 0.0F, 0.0F, 1.0F);
    glRotatef(angle, 0.0F, 1.0F, 0.0F);
    glTranslatef(-70.0F, 0.0F, 0.0F);
    glutSolidSphere(6.0F, 15, 15);
    glPopMatrix();

    // 第三个电子
    glPushMatrix();
    glRotatef(360.0F - 45.0F, 0.0F, 0.0F, 1.0F);
    glRotatef(angle, 0.0F, 1.0F, 0.0F);
    glTranslatef(0.0F, 0.0F, 60.0F);
    glutSolidSphere(6.0F, 15, 15);
    glPopMatrix();

    angle += 10.0F;
    if (angle > 360.0F) {
        angle = 0.0F;
    }

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(100, timerFunc, 1);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0, aspectRatio, 1.0, 500.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutTimerFunc(500, timerFunc, 1);
    glutReshapeFunc(changeSize);
    setupRc();
    glutMainLoop();
    return 0;
}

画一个立方体

// mac 特有的头文件
#include <GLUT/glut.h>
#include <OpenGL/gl.h>

#include <iostream>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 100.0F;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glPushMatrix();
    
    glRotatef(xRot, 1.0F, 0.0F, 0.0F);  // 绕 X 轴旋转
    glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
    glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转


    // 红笔
    glColor3f(1.0F, 0.0F, 0.0F);

    // 绘制一个立方体
    glBegin(GL_QUADS);
        // // 前面
        glNormal3f(0.0F, 0.0F, 1.0F); // 法线向前
        glVertex3f(-50.0F, -50.0F, 50.0F);
        glVertex3f(50.0F, -50.0F, 50.0F);
        glVertex3f(50.0F, 50.0F, 50.0F);
        glVertex3f(-50.0F, 50.0F, 50.0F);
        
        glColor3f(0.0F, 1.0F, 0.0F);
        
        // 后面
        glNormal3f(0.0F, 0.0F, -1.0F); // 法线向后
        glVertex3f(-50.0F, -50.0F, -50.0F);
        glVertex3f(-50.0F, 50.0F, -50.0F);
        glVertex3f(50.0F, 50.0F, -50.0F);
        glVertex3f(50.0F, -50.0F, -50.0F);

        glColor3f(0.0F, 0.0F, 1.0F);
        // 左面
        glNormal3f(-1.0F, 0.0F, 0.0F); // 法线向左
        glVertex3f(-50.0F, -50.0F, -50.0F);
        glVertex3f(-50.0F, -50.0F, 50.0F);
        glVertex3f(-50.0F, 50.0F, 50.0F);
        glVertex3f(-50.0F, 50.0F, -50.0F);

        glColor3f(0.3F, 0.6F, 0.4F);
        // 右面
        glNormal3f(1.0F, 0.0F, 0.0F); // 法线向右
        glVertex3f(50.0F, -50.0F, -50.0F);
        glVertex3f(50.0F, 50.0F, -50.0F);
        glVertex3f(50.0F, 50.00f, 50.0F);
        glVertex3f(50.0F, -50.0F, 50.0F);

        glColor3f(1.0F, 1.0F, 1.0F);

        // 上
        glNormal3f(0.0F, 1.0F, 0.0F); // 法线向上
        glVertex3f(-50.0F, 50.0F, -50.0F);
        glVertex3f(-50.0F, 50.0F, 50.0F);
        glVertex3f(50.0F, 50.0F, 50.0F);
        glVertex3f(50.0F, 50.0F, -50.0F);

        glColor3f(1.0F, 1.0F, 0.0F);

        // 下
        glNormal3f(0.0F, -1.0F, 0.0F); // 法线向下
        glVertex3f(-50.0F, -50.0F, -50.0F);
        glVertex3f(50.0F, -50.0F, -50.0F);
        glVertex3f(50.0F, -50.0F, 50.0F);
        glVertex3f(-50.0F, -50.0F, 50.0F);
    glEnd();

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
}
 
void changeSize(const GLsizei w, const GLsizei h){
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    if (w <= h) {
        glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE * 2.0, COORDINATE_SIZE * 2.0);
    } else {
        glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE * 2.0, COORDINATE_SIZE * 2.0);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
 
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case 27:    // ESC 键
        case 'q':
        case 'Q':
            std::cout << "keyboard close..." << "\n";
            exit(0);
            break;
        case 'a':
        case 'A':
            zRot -= 5.0F; // 绕 Z 轴逆时针旋转
            glutPostRedisplay();
            break;
        case 'd':
        case 'D':
            zRot += 5.0F; // 绕 Z 轴顺时针旋转
            glutPostRedisplay();
            break;
        default:
            break;
    }
}
 
void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case GLUT_KEY_UP:
            xRot -= 5.0F;
            break;
        case GLUT_KEY_DOWN:
            xRot += 5.0F;
            break;
        case GLUT_KEY_LEFT:
            yRot -= 5.0F;
            break;
        case GLUT_KEY_RIGHT:
            yRot += 5.0F;
            break;
        default:
            break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);   // 特殊键事件
    glutKeyboardFunc(keyboard);  // 普通键事件
    setupRc();
    glutMainLoop();
    return 0;
}

绘制一个空心立方体

// mac 特有的头文件
#include <GLUT/glut.h>
#include <OpenGL/gl.h>

#include <iostream>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glPushMatrix();
    
    glRotatef(xRot, 1.0F, 0.0F, 0.0F);  // 绕 X 轴旋转
    glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
    glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转


    // 红笔
    glColor3f(1.0F, 0.0F, 0.0F);

    // 绘制一个立方体
    glBegin(GL_QUADS);
        // // 前面
        glNormal3f(0.0F, 0.0F, 1.0F); // 法线向前

        // left
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(-50.0F, -50.0F, 100.0F);
        glVertex3f(-35.0F, -50.0F, 100.0F);
        glVertex3f(-35.0F, 50.0F, 100.0F);
        
        // top
        glVertex3f(-35.0F, 50.0F, 100.0F);
        glVertex3f(-35.0F, 35.0F, 100.0F);
        glVertex3f(35.0F, 35.0F, 100.0F);
        glVertex3f(35.0F, 50.0F, 100.0F);

        // right
        glVertex3f(35.0F, 50.0F, 100.0F);
        glVertex3f(35.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, 100.0F);

        // bottom
        glVertex3f(-35.0F, -35.0F, 100.0F);
        glVertex3f(-35.0F, -50.0F, 100.0F);
        glVertex3f(35.0F, -50.0F, 100.0F);
        glVertex3f(35.0F, -35.0F, 100.0F);

        // 侧面
        // top
        glNormal3f(0.0F, 1.0F, 0.0F); // 法线向上
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F);

        // bottom
        glNormal3f(0.0F, -1.0F, 0.0F); // 法线向下
        glVertex3f(-50.0F, -50.0F, 100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        
        // left
        glNormal3f(1.0F, 0.0F, 0.0F); // 法线向左
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, 100.0F);

        // right
        glNormal3f(-1.0F, 0.0F, 0.0F); // 法线向右
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
    glEnd();

    glFrontFace(GL_CW);
    
    glBegin(GL_QUADS);
        // Back section
        glNormal3f(0.0F, 0.0F, -1.0F); // 法线向后

        // Left Panel
        glVertex3f(-50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(-35.0F, -50.0F, -100.0F);
        glVertex3f(-35.0F, 50.0F, -100.0F);

        // Right Panel
        glVertex3f(50.0F, 50.0F, -100.0F);
        glVertex3f(35.0F, 50.0F, -100.0F);
        glVertex3f(35.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);

        // Top Panel
        glVertex3f(-35.0F, 50.0F, -100.0F);
        glVertex3f(-35.0F, 35.0F, -100.0F);
        glVertex3f(35.0F, 35.0F, -100.0F);
        glVertex3f(35.0F, 50.0F, -100.0F);

        // Bottom Panel
        glVertex3f(-35.0F, -35.0F, -100.0F);
        glVertex3f(-35.0F, -50.0F, -100.0F);
        glVertex3f(35.0F, -50.0F, -100.0F);
        glVertex3f(35.0F, -35.0F, -100.0F);

        // insides
        glColor3f(0.0F, 1.0F, 0.0F); // 绿色
        // Top section
        glNormal3f(0.0F, 1.0F, 0.0F); // 法线向上
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F); 
        // Bottom section
        glNormal3f(0.0F, -1.0F, 0.0F); // 法线向下
        glVertex3f(-50.0F, -50.0F, 100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        // Left section
        glNormal3f(1.0F, 0.0F, 0.0F); // 法线向左
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);    
        glVertex3f(-50.0F, -50.0F, 100.0F);
        // Right section
        glNormal3f(-1.0F, 0.0F, 0.0F); // 法线向右
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
    glEnd();

    glFrontFace(GL_CCW);

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK); // 剔除背面
}
 
void changeSize(const GLsizei w, const GLsizei h){
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    if (w <= h) {
        glOrtho(-COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE / aspectRatio, COORDINATE_SIZE / aspectRatio, -COORDINATE_SIZE * 2.0, COORDINATE_SIZE * 2.0);
    } else {
        glOrtho(-COORDINATE_SIZE * aspectRatio, COORDINATE_SIZE * aspectRatio, -COORDINATE_SIZE, COORDINATE_SIZE, -COORDINATE_SIZE * 2.0, COORDINATE_SIZE * 2.0);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
 
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case 27:    // ESC 键
        case 'q':
        case 'Q':
            std::cout << "keyboard close..." << "\n";
            exit(0);
            break;
        case 'a':
        case 'A':
            zRot -= 5.0F; // 绕 Z 轴逆时针旋转
            glutPostRedisplay();
            break;
        case 'd':
        case 'D':
            zRot += 5.0F; // 绕 Z 轴顺时针旋转
            glutPostRedisplay();
            break;
        default:
            break;
    }
}
 
void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case GLUT_KEY_UP:
            xRot -= 5.0F;
            break;
        case GLUT_KEY_DOWN:
            xRot += 5.0F;
            break;
        case GLUT_KEY_LEFT:
            yRot -= 5.0F;
            break;
        case GLUT_KEY_RIGHT:
            yRot += 5.0F;
            break;
        default:
            break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);   // 特殊键事件
    glutKeyboardFunc(keyboard);  // 普通键事件
    setupRc();
    glutMainLoop();
    return 0;
}

投影空心立方体


// mac 特有的头文件
#include <GLUT/glut.h>
#include <OpenGL/gl.h>

#include <OpenGL/glu.h>
#include <iostream>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glPushMatrix();

    glTranslatef(0.0F, 0.0F, -200.0F); // 把场景推到相机前方

    glRotatef(xRot, 1.0F, 0.0F, 0.0F);  // 绕 X 轴旋转
    glRotatef(yRot, 0.0F, 1.0F, 0.0F); // 绕 Y 轴旋转
    glRotatef(zRot, 0.0F, 0.0F, 1.0F); // 绕 Z 轴旋转


    // 红笔
    glColor3f(1.0F, 0.0F, 0.0F);

    // 绘制一个立方体
    glBegin(GL_QUADS);
        // // 前面
        glNormal3f(0.0F, 0.0F, 1.0F); // 法线向前

        // left
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(-50.0F, -50.0F, 100.0F);
        glVertex3f(-35.0F, -50.0F, 100.0F);
        glVertex3f(-35.0F, 50.0F, 100.0F);
        
        // top
        glVertex3f(-35.0F, 50.0F, 100.0F);
        glVertex3f(-35.0F, 35.0F, 100.0F);
        glVertex3f(35.0F, 35.0F, 100.0F);
        glVertex3f(35.0F, 50.0F, 100.0F);

        // right
        glVertex3f(35.0F, 50.0F, 100.0F);
        glVertex3f(35.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, 100.0F);

        // bottom
        glVertex3f(-35.0F, -35.0F, 100.0F);
        glVertex3f(-35.0F, -50.0F, 100.0F);
        glVertex3f(35.0F, -50.0F, 100.0F);
        glVertex3f(35.0F, -35.0F, 100.0F);

        // 侧面
        // top
        glNormal3f(0.0F, 1.0F, 0.0F); // 法线向上
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F);

        // bottom
        glNormal3f(0.0F, -1.0F, 0.0F); // 法线向下
        glVertex3f(-50.0F, -50.0F, 100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        
        // left
        glNormal3f(1.0F, 0.0F, 0.0F); // 法线向左
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, 100.0F);

        // right
        glNormal3f(-1.0F, 0.0F, 0.0F); // 法线向右
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
    glEnd();

    glFrontFace(GL_CW);
    
    glBegin(GL_QUADS);
        // Back section
        glNormal3f(0.0F, 0.0F, -1.0F); // 法线向后

        // Left Panel
        glVertex3f(-50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(-35.0F, -50.0F, -100.0F);
        glVertex3f(-35.0F, 50.0F, -100.0F);

        // Right Panel
        glVertex3f(50.0F, 50.0F, -100.0F);
        glVertex3f(35.0F, 50.0F, -100.0F);
        glVertex3f(35.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);

        // Top Panel
        glVertex3f(-35.0F, 50.0F, -100.0F);
        glVertex3f(-35.0F, 35.0F, -100.0F);
        glVertex3f(35.0F, 35.0F, -100.0F);
        glVertex3f(35.0F, 50.0F, -100.0F);

        // Bottom Panel
        glVertex3f(-35.0F, -35.0F, -100.0F);
        glVertex3f(-35.0F, -50.0F, -100.0F);
        glVertex3f(35.0F, -50.0F, -100.0F);
        glVertex3f(35.0F, -35.0F, -100.0F);

        // insides
        glColor3f(0.0F, 1.0F, 0.0F); // 绿色
        // Top section
        glNormal3f(0.0F, 1.0F, 0.0F); // 法线向上
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F); 
        // Bottom section
        glNormal3f(0.0F, -1.0F, 0.0F); // 法线向下
        glVertex3f(-50.0F, -50.0F, 100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        // Left section
        glNormal3f(1.0F, 0.0F, 0.0F); // 法线向左
        glVertex3f(-50.0F, 50.0F, 100.0F);
        glVertex3f(-50.0F, 50.0F, -100.0F);
        glVertex3f(-50.0F, -50.0F, -100.0F);    
        glVertex3f(-50.0F, -50.0F, 100.0F);
        // Right section
        glNormal3f(-1.0F, 0.0F, 0.0F); // 法线向右
        glVertex3f(50.0F, 50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, 100.0F);
        glVertex3f(50.0F, -50.0F, -100.0F);
        glVertex3f(50.0F, 50.0F, -100.0F);
    glEnd();

    glFrontFace(GL_CCW);

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK); // 剔除背面
}

void changeSize(const GLsizei w, const GLsizei h){
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 500.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

 
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case 27:    // ESC 键
        case 'q':
        case 'Q':
            std::cout << "keyboard close..." << "\n";
            exit(0);
            break;
        case 'a':
        case 'A':
            zRot -= 5.0F; // 绕 Z 轴逆时针旋转
            glutPostRedisplay();
            break;
        case 'd':
        case 'D':
            zRot += 5.0F; // 绕 Z 轴顺时针旋转
            glutPostRedisplay();
            break;
        default:
            break;
    }
}
 
void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case GLUT_KEY_UP:
            xRot -= 5.0F;
            break;
        case GLUT_KEY_DOWN:
            xRot += 5.0F;
            break;
        case GLUT_KEY_LEFT:
            yRot -= 5.0F;
            break;
        case GLUT_KEY_RIGHT:
            yRot += 5.0F;
            break;
        default:
            break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);   // 特殊键事件
    glutKeyboardFunc(keyboard);  // 普通键事件
    setupRc();
    glutMainLoop();
    return 0;
}

太阳、地球、月球模拟


// mac 特有的头文件
#include <GLUT/glut.h>
#include <OpenGL/gl.h>

#include <OpenGL/glu.h>
#include <iostream>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

void renderScene() {

    static GLfloat earthAngle = 0.0F; // 地球角度
    static GLfloat moonAngle = 0.0F; // 月亮角度

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);

    glPushMatrix();

    glTranslatef(0.0F, 0.0F, -200.0F); // 移动到屏幕内
    
    glColor3ub(255, 255, 0); // 黄色
    glutSolidSphere(20.0F, 30, 30); // 绘制太阳

    glRotatef(earthAngle, 0.0F, 1.0F, 0.0F); // 绕Y轴旋转地球

    glColor3ub(0, 0, 255); // 蓝色
    glTranslatef(105.0F, 0.0F, 0.0F);
    glutSolidSphere(15.0F, 15, 15); // 绘制地球

    glColor3ub(200, 200, 200); // 白色
    glRotatef(moonAngle, 0.0F, 1.0F, 0.0F); // 绕Y轴旋转月亮
    glTranslatef(30.0F, 0.0F, 0.0F);

    glutSolidSphere(6.0F, 15, 15); //

    glPopMatrix();

    moonAngle += 15.0F;
    if (moonAngle > 360.0F) {
        moonAngle = 0.0F;
    }

    earthAngle += 5.0F;
    if (earthAngle > 360.0F) {
        earthAngle = 0.0F;
    }

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK); // 剔除背面
}

void changeSize(const GLsizei w, const GLsizei h){
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio = static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 500.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

 
// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case 27:    // ESC 键
        case 'q':
        case 'Q':
            std::cout << "keyboard close..." << "\n";
            exit(0);
            break;
        case 'a':
        case 'A':
            zRot -= 5.0F; // 绕 Z 轴逆时针旋转
            glutPostRedisplay();
            break;
        case 'd':
        case 'D':
            zRot += 5.0F; // 绕 Z 轴顺时针旋转
            glutPostRedisplay();
            break;
        default:
            break;
    }
}
 
void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
        case GLUT_KEY_UP:
            xRot -= 5.0F;
            break;
        case GLUT_KEY_DOWN:
            xRot += 5.0F;
            break;
        case GLUT_KEY_LEFT:
            yRot -= 5.0F;
            break;
        case GLUT_KEY_RIGHT:
            yRot += 5.0F;
            break;
        default:
            break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);   // 特殊键事件
    glutKeyboardFunc(keyboard);  // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}

绘制圆


// mac 特有的头文件
#include <GLUT/glut.h>

#include <OpenGL/gl.h>
#include <OpenGL/glu.h>

#include <cmath>
#include <iostream>
#include <numbers>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    // 平移到观察位置
    glTranslatef(0.0F, 0.0F, -5.0F);
    // 应用旋转
    glRotatef(xRot, 1.0F, 0.0F, 0.0F);
    glRotatef(yRot, 0.0F, 1.0F, 0.0F);
    glRotatef(zRot, 0.0F, 0.0F, 1.0F);

    constexpr int segments = 100;       // 分段数(越大越圆滑)
    constexpr GLfloat radius = 1.0F;   // 半径

    // --- 填充圆(白色) ---
    glColor3f(1.0F, 1.0F, 1.0F);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(0.0F, 0.0F); // 圆心
    for (int i = 0; i <= segments; ++i) {
        const GLfloat angle = 2.0F * PI * static_cast<GLfloat>(i) /
                              static_cast<GLfloat>(segments);
        glVertex2f(radius * cosf(angle), radius * sinf(angle));
    }
    glEnd();

    // --- 边框线(红色,让轮廓更明显) ---
    glColor3f(1.0F, 0.0F, 0.0F);
    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < segments; ++i) {
        const GLfloat angle = 2.0F * PI * static_cast<GLfloat>(i) /
                              static_cast<GLfloat>(segments);
        glVertex2f(radius * cosf(angle), radius * sinf(angle));
    }
    glEnd();

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 50.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
    case 27: // ESC 键
    case 'q':
    case 'Q':
        std::cout << "keyboard close..." << "\n";
        exit(0);
        break;
    case 'a':
    case 'A':
        zRot -= 5.0F; // 绕 Z 轴逆时针旋转
        glutPostRedisplay();
        break;
    case 'd':
    case 'D':
        zRot += 5.0F; // 绕 Z 轴顺时针旋转
        glutPostRedisplay();
        break;
    default:
        break;
    }
}

void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
              << "\n";
    switch (key) {
    case GLUT_KEY_UP:
        xRot -= 5.0F;
        break;
    case GLUT_KEY_DOWN:
        xRot += 5.0F;
        break;
    case GLUT_KEY_LEFT:
        yRot -= 5.0F;
        break;
    case GLUT_KEY_RIGHT:
        yRot += 5.0F;
        break;
    default:
        break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);           // 特殊键事件
    glutKeyboardFunc(keyboard);             // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}

绘制圆(使用原始矩阵)


// mac 特有的头文件
#include <GLUT/glut.h>

#include <OpenGL/gl.h>
#include <OpenGL/glu.h>

#include <cmath>
#include <iostream>
#include <numbers>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

// 4x4 矩阵乘法: result = a * b(列主序,兼容 OpenGL)
void multiplyMatrix4(const GLfloat a[16], const GLfloat b[16],
                     GLfloat result[16]) {
    for (int col = 0; col < 4; ++col) {
        for (int row = 0; row < 4; ++row) {
            result[col * 4 + row] =
                a[0 * 4 + row] * b[col * 4 + 0] +
                a[1 * 4 + row] * b[col * 4 + 1] +
                a[2 * 4 + row] * b[col * 4 + 2] +
                a[3 * 4 + row] * b[col * 4 + 3];
        }
    }
}

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    // --- 手动构建变换矩阵,替代 glTranslatef / glRotatef ---
    const GLfloat radX = xRot * PI / 180.0F;
    const GLfloat radY = yRot * PI / 180.0F;
    const GLfloat radZ = zRot * PI / 180.0F;

    const GLfloat cx = cosf(radX), sx = sinf(radX);
    const GLfloat cy = cosf(radY), sy = sinf(radY);
    const GLfloat cz = cosf(radZ), sz = sinf(radZ);

    // 平移矩阵 T(列主序)
    const GLfloat trans[16] = {
        1.0F, 0.0F, 0.0F, 0.0F, // col 0
        0.0F, 1.0F, 0.0F, 0.0F, // col 1
        0.0F, 0.0F, 1.0F, 0.0F, // col 2
        0.0F, 0.0F,-5.0F, 1.0F  // col 3 (tx, ty, tz, 1)
    };

    // 绕 X 轴旋转矩阵(列主序)
    const GLfloat rotX[16] = {
        1.0F, 0.0F, 0.0F, 0.0F,
        0.0F,   cx,   sx, 0.0F,
        0.0F,  -sx,   cx, 0.0F,
        0.0F, 0.0F, 0.0F, 1.0F
    };

    // 绕 Y 轴旋转矩阵(列主序)
    const GLfloat rotY[16] = {
          cy, 0.0F,  -sy, 0.0F,
        0.0F, 1.0F, 0.0F, 0.0F,
          sy, 0.0F,   cy, 0.0F,
        0.0F, 0.0F, 0.0F, 1.0F
    };

    // 绕 Z 轴旋转矩阵(列主序)
    const GLfloat rotZ[16] = {
          cz,   sz, 0.0F, 0.0F,
         -sz,   cz, 0.0F, 0.0F,
        0.0F, 0.0F, 1.0F, 0.0F,
        0.0F, 0.0F, 0.0F, 1.0F
    };

    // 组合: T * Rx * Ry * Rz
    GLfloat temp1[16], temp2[16], finalMatrix[16];
    multiplyMatrix4(rotY, rotZ, temp1);         // temp1 = Ry * Rz
    multiplyMatrix4(rotX, temp1, temp2);        // temp2 = Rx * Ry * Rz
    multiplyMatrix4(trans, temp2, finalMatrix); // final = T * Rx * Ry * Rz

    glMultMatrixf(finalMatrix);

    constexpr int segments = 100;       // 分段数(越大越圆滑)
    constexpr GLfloat radius = 1.0F;   // 半径

    // --- 填充圆(白色) ---
    glColor3f(1.0F, 1.0F, 1.0F);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(0.0F, 0.0F); // 圆心
    for (int i = 0; i <= segments; ++i) {
        const GLfloat angle = 2.0F * PI * static_cast<GLfloat>(i) /
                              static_cast<GLfloat>(segments);
        glVertex2f(radius * cosf(angle), radius * sinf(angle));
    }
    glEnd();

    // --- 边框线(红色,让轮廓更明显) ---
    glColor3f(1.0F, 0.0F, 0.0F);
    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < segments; ++i) {
        const GLfloat angle = 2.0F * PI * static_cast<GLfloat>(i) /
                              static_cast<GLfloat>(segments);
        glVertex2f(radius * cosf(angle), radius * sinf(angle));
    }
    glEnd();

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 50.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
    case 27: // ESC 键
    case 'q':
    case 'Q':
        std::cout << "keyboard close..." << "\n";
        exit(0);
        break;
    case 'a':
    case 'A':
        zRot -= 5.0F; // 绕 Z 轴逆时针旋转
        glutPostRedisplay();
        break;
    case 'd':
    case 'D':
        zRot += 5.0F; // 绕 Z 轴顺时针旋转
        glutPostRedisplay();
        break;
    default:
        break;
    }
}

void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
              << "\n";
    switch (key) {
    case GLUT_KEY_UP:
        xRot -= 5.0F;
        break;
    case GLUT_KEY_DOWN:
        xRot += 5.0F;
        break;
    case GLUT_KEY_LEFT:
        yRot -= 5.0F;
        break;
    case GLUT_KEY_RIGHT:
        yRot += 5.0F;
        break;
    default:
        break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);           // 特殊键事件
    glutKeyboardFunc(keyboard);             // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}

根据右手定则,拇指指向x轴,四指弯曲方向为正方向。让x轴正对屏幕方向。正常推理即可。得出结论。

绘制环


// mac 特有的头文件
#include <GLUT/glut.h>

#include <OpenGL/gl.h>
#include <OpenGL/glu.h>

#include <cmath>
#include <iostream>
#include <numbers>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

// 4x4 矩阵乘法: result = a * b(列主序,兼容 OpenGL)
void multiplyMatrix4(const GLfloat a[16], const GLfloat b[16],
                     GLfloat result[16]) {
    for (int col = 0; col < 4; ++col) {
        for (int row = 0; row < 4; ++row) {
            result[col * 4 + row] =
                a[0 * 4 + row] * b[col * 4 + 0] +
                a[1 * 4 + row] * b[col * 4 + 1] +
                a[2 * 4 + row] * b[col * 4 + 2] +
                a[3 * 4 + row] * b[col * 4 + 3];
        }
    }
}

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    // --- 手动构建变换矩阵,替代 glTranslatef / glRotatef ---
    const GLfloat radX = xRot * PI / 180.0F;
    const GLfloat radY = yRot * PI / 180.0F;
    const GLfloat radZ = zRot * PI / 180.0F;

    const GLfloat cx = cosf(radX), sx = sinf(radX);
    const GLfloat cy = cosf(radY), sy = sinf(radY);
    const GLfloat cz = cosf(radZ), sz = sinf(radZ);

    // 平移矩阵 T(列主序)
    const GLfloat trans[16] = {
        1.0F, 0.0F, 0.0F, 0.0F, // col 0
        0.0F, 1.0F, 0.0F, 0.0F, // col 1
        0.0F, 0.0F, 1.0F, 0.0F, // col 2
        0.0F, 0.0F,-5.0F, 1.0F  // col 3 (tx, ty, tz, 1)
    };

    // 绕 X 轴旋转矩阵(列主序)
    const GLfloat rotX[16] = {
        1.0F, 0.0F, 0.0F, 0.0F,
        0.0F,   cx,   sx, 0.0F,
        0.0F,  -sx,   cx, 0.0F,
        0.0F, 0.0F, 0.0F, 1.0F
    };

    // 绕 Y 轴旋转矩阵(列主序)
    const GLfloat rotY[16] = {
          cy, 0.0F,  -sy, 0.0F,
        0.0F, 1.0F, 0.0F, 0.0F,
          sy, 0.0F,   cy, 0.0F,
        0.0F, 0.0F, 0.0F, 1.0F
    };

    // 绕 Z 轴旋转矩阵(列主序)
    const GLfloat rotZ[16] = {
          cz,   sz, 0.0F, 0.0F,
         -sz,   cz, 0.0F, 0.0F,
        0.0F, 0.0F, 1.0F, 0.0F,
        0.0F, 0.0F, 0.0F, 1.0F
    };

    // 组合: T * Rx * Ry * Rz
    GLfloat temp1[16], temp2[16], finalMatrix[16];
    multiplyMatrix4(rotY, rotZ, temp1);         // temp1 = Ry * Rz
    multiplyMatrix4(rotX, temp1, temp2);        // temp2 = Rx * Ry * Rz
    multiplyMatrix4(trans, temp2, finalMatrix); // final = T * Rx * Ry * Rz

    glMultMatrixf(finalMatrix);

    // 圆心
    glColor3f(1.0F, 1.0F, 1.0F);
    glPointSize(6.0F);
    glBegin(GL_POINTS);
        glVertex3f(0.0F, 0.0F, 0.0F);
    glEnd();

    // yz平面大圆环
    constexpr GLfloat majorRadius = 1.5F;
    glBegin(GL_LINE_LOOP);
        for (GLfloat angle = 0.0F; angle <= 2 * PI; angle += 0.1F) {
            glVertex3f(0.0F, majorRadius * cos(angle), majorRadius * sin(angle));
        }
    glEnd();

    // --- 小圆绕 X 轴旋转,扫出圆环面(线框) ---
    constexpr GLfloat minorRadius = 0.5F;
    constexpr int numSweep = 40; // 绕 X 轴旋转的份数
    glColor3f(1.0F, 0.0F, 0.0F);
    for (int s = 0; s < numSweep; ++s) {
        GLfloat theta = (GLfloat)s / (GLfloat)numSweep * 2.0F * PI;
        GLfloat ct = cosf(theta), st = sinf(theta);

        // 绕 X 轴旋转矩阵(列主序)
        const GLfloat rotXSweep[16] = {
            1.0F, 0.0F, 0.0F, 0.0F,
            0.0F,   ct,   st, 0.0F,
            0.0F,  -st,   ct, 0.0F,
            0.0F, 0.0F, 0.0F, 1.0F
        };

        // combined = finalMatrix * rotXSweep
        GLfloat combined[16];
        multiplyMatrix4(finalMatrix, rotXSweep, combined);
        glLoadMatrixf(combined);
        glBegin(GL_LINE_LOOP);
            for (GLfloat angle = 0.0F; angle <= 2 * PI; angle += 0.1F) {
                glVertex2f(minorRadius * cosf(angle),
                           majorRadius + minorRadius * sinf(angle));
            }
        glEnd();
    }

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 50.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
    case 27: // ESC 键
    case 'q':
    case 'Q':
        std::cout << "keyboard close..." << "\n";
        exit(0);
        break;
    case 'a':
    case 'A':
        zRot -= 5.0F; // 绕 Z 轴逆时针旋转
        glutPostRedisplay();
        break;
    case 'd':
    case 'D':
        zRot += 5.0F; // 绕 Z 轴顺时针旋转
        glutPostRedisplay();
        break;
    default:
        break;
    }
}

void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
              << "\n";
    switch (key) {
    case GLUT_KEY_UP:
        xRot -= 5.0F;
        break;
    case GLUT_KEY_DOWN:
        xRot += 5.0F;
        break;
    case GLUT_KEY_LEFT:
        yRot -= 5.0F;
        break;
    case GLUT_KEY_RIGHT:
        yRot += 5.0F;
        break;
    default:
        break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);           // 特殊键事件
    glutKeyboardFunc(keyboard);             // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}

绘制圆环2


// mac 特有的头文件
#include <GLUT/glut.h>

#include <OpenGL/gl.h>
#include <OpenGL/gltypes.h>
#include <OpenGL/glu.h>

#include <cmath>
#include <iostream>
#include <numbers>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

// 4x4 矩阵乘法: result = a * b(列主序,兼容 OpenGL)
void multiplyMatrix4(const GLfloat a[16], const GLfloat b[16],
                     GLfloat result[16]) {
    for (int col = 0; col < 4; ++col) {
        for (int row = 0; row < 4; ++row) {
            result[col * 4 + row] = a[0 * 4 + row] * b[col * 4 + 0] +
                                    a[1 * 4 + row] * b[col * 4 + 1] +
                                    a[2 * 4 + row] * b[col * 4 + 2] +
                                    a[3 * 4 + row] * b[col * 4 + 3];
        }
    }
}

void drawTorus(const GLfloat majorRadius, const GLfloat minorRadius, const GLint numMajor, const GLint numMinor) {
    for (GLint i = 0; i < numMajor; ++i) {
        const GLfloat u0 = (GLfloat)i / numMajor * 2.0F * PI;
        const GLfloat u1 = (GLfloat)(i + 1) / numMajor * 2.0F * PI;

        glBegin(GL_TRIANGLE_STRIP);
        for (GLint j = 0; j <= numMinor; ++j) {
            GLfloat v = (GLfloat)j / numMinor * 2.0F * PI;

            GLfloat x = minorRadius * cosf(v);
            GLfloat y = (majorRadius + minorRadius * sinf(v));
            GLfloat nx = cosf(v);
            GLfloat ny = sinf(v);

            // 点1 (u0)
            GLfloat cu0 = cosf(u0), su0 = sinf(u0);
            glNormal3f(nx, ny * cu0, ny * su0);
            glVertex3f(x, y * cu0, y * su0);

            // 点2 (u1)
            GLfloat cu1 = cosf(u1), su1 = sinf(u1);
            glNormal3f(nx, ny * cu1, ny * su1);
            glVertex3f(x, y * cu1, y * su1);
        }
        glEnd();
    }
}

void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    // --- 手动构建变换矩阵,替代 glTranslatef / glRotatef ---
    const GLfloat radX = xRot * PI / 180.0F;
    const GLfloat radY = yRot * PI / 180.0F;
    const GLfloat radZ = zRot * PI / 180.0F;

    const GLfloat cx = cosf(radX), sx = sinf(radX);
    const GLfloat cy = cosf(radY), sy = sinf(radY);
    const GLfloat cz = cosf(radZ), sz = sinf(radZ);

    // 平移矩阵 T(列主序)
    const GLfloat trans[16] = {
        1.0F, 0.0F, 0.0F,  0.0F, // col 0
        0.0F, 1.0F, 0.0F,  0.0F, // col 1
        0.0F, 0.0F, 1.0F,  0.0F, // col 2
        0.0F, 0.0F, -2.0F, 1.0F  // col 3 (tx, ty, tz, 1)
    };

    // 绕 X 轴旋转矩阵(列主序)
    const GLfloat rotX[16] = {1.0F, 0.0F, 0.0F, 0.0F, 0.0F, cx,   sx,   0.0F,
                              0.0F, -sx,  cx,   0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 绕 Y 轴旋转矩阵(列主序)
    const GLfloat rotY[16] = {cy, 0.0F, -sy, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F,
                              sy, 0.0F, cy,  0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 绕 Z 轴旋转矩阵(列主序)
    const GLfloat rotZ[16] = {cz,   sz,   0.0F, 0.0F, -sz,  cz,   0.0F, 0.0F,
                              0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 组合: T * Rx * Ry * Rz
    GLfloat temp1[16], temp2[16], finalMatrix[16];
    multiplyMatrix4(rotY, rotZ, temp1);         // temp1 = Ry * Rz
    multiplyMatrix4(rotX, temp1, temp2);        // temp2 = Rx * Ry * Rz
    multiplyMatrix4(trans, temp2, finalMatrix); // final = T * Rx * Ry * Rz

    glMultMatrixf(finalMatrix);

    // yz平面大圆环
    constexpr GLfloat majorRadius = 0.35F;
    constexpr GLfloat minorRadius = 0.15F;
    constexpr int numMajor = 40; // 绕大圆的细分
    constexpr int numMinor = 20; // 绕小圆的细分
    drawTorus(majorRadius, minorRadius, numMajor, numMinor);

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 50.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
    case 27: // ESC 键
    case 'q':
    case 'Q':
        std::cout << "keyboard close..." << "\n";
        exit(0);
        break;
    case 'a':
    case 'A':
        zRot -= 5.0F; // 绕 Z 轴逆时针旋转
        glutPostRedisplay();
        break;
    case 'd':
    case 'D':
        zRot += 5.0F; // 绕 Z 轴顺时针旋转
        glutPostRedisplay();
        break;
    default:
        break;
    }
}

void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
              << "\n";
    switch (key) {
    case GLUT_KEY_UP:
        xRot -= 5.0F;
        break;
    case GLUT_KEY_DOWN:
        xRot += 5.0F;
        break;
    case GLUT_KEY_LEFT:
        yRot -= 5.0F;
        break;
    case GLUT_KEY_RIGHT:
        yRot += 5.0F;
        break;
    default:
        break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);           // 特殊键事件
    glutKeyboardFunc(keyboard);             // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}

画球体


// mac 特有的头文件
#include <GLUT/glut.h>

#include <OpenGL/gl.h>
#include <OpenGL/gltypes.h>
#include <OpenGL/glu.h>

#include <cmath>
#include <cstdlib>
#include <iostream>
#include <numbers>

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;

// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

// 4x4 矩阵乘法: result = a * b(列主序,兼容 OpenGL)
void multiplyMatrix4(const GLfloat a[16], const GLfloat b[16],
                     GLfloat result[16]) {
    for (int col = 0; col < 4; ++col) {
        for (int row = 0; row < 4; ++row) {
            result[col * 4 + row] = a[0 * 4 + row] * b[col * 4 + 0] +
                                    a[1 * 4 + row] * b[col * 4 + 1] +
                                    a[2 * 4 + row] * b[col * 4 + 2] +
                                    a[3 * 4 + row] * b[col * 4 + 3];
        }
    }
}
void drawSphere(GLfloat radius, int slices, int stacks) {
      for (int i = 0; i < stacks; ++i) {
          GLfloat phi0   = i       * PI / stacks;       // 从北极到南极
          GLfloat phi1   = (i + 1) * PI / stacks;
          GLfloat sinP0  = sinf(phi0), cosP0 = cosf(phi0);
          GLfloat sinP1  = sinf(phi1), cosP1 = cosf(phi1);

          glBegin(GL_TRIANGLE_STRIP);
          for (int j = 0; j <= slices; ++j) {
              GLfloat theta = j * 2.0f * PI / slices;
              GLfloat sinT  = sinf(theta), cosT = cosf(theta);

              // 点(phi0) — 纬线 i
              GLfloat x0 = radius * sinP0 * cosT;
              GLfloat y0 = radius * cosP0;
              GLfloat z0 = radius * sinP0 * sinT;
              glNormal3f(sinP0 * cosT, cosP0, sinP0 * sinT);
              glVertex3f(x0, y0, z0);

              // 点(phi1) — 纬线 i+1
              GLfloat x1 = radius * sinP1 * cosT;
              GLfloat y1 = radius * cosP1;
              GLfloat z1 = radius * sinP1 * sinT;
              glNormal3f(sinP1 * cosT, cosP1, sinP1 * sinT);
              glVertex3f(x1, y1, z1);
          }
          glEnd();
      }
  }
void renderScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    // --- 手动构建变换矩阵,替代 glTranslatef / glRotatef ---
    const GLfloat radX = xRot * PI / 180.0F;
    const GLfloat radY = yRot * PI / 180.0F;
    const GLfloat radZ = zRot * PI / 180.0F;

    const GLfloat cx = cosf(radX), sx = sinf(radX);
    const GLfloat cy = cosf(radY), sy = sinf(radY);
    const GLfloat cz = cosf(radZ), sz = sinf(radZ);

    // 平移矩阵 T(列主序)
    const GLfloat trans[16] = {
        1.0F, 0.0F, 0.0F,  0.0F, // col 0
        0.0F, 1.0F, 0.0F,  0.0F, // col 1
        0.0F, 0.0F, 1.0F,  0.0F, // col 2
        0.0F, 0.0F, -2.0F, 1.0F  // col 3 (tx, ty, tz, 1)
    };

    // 绕 X 轴旋转矩阵(列主序)
    const GLfloat rotX[16] = {1.0F, 0.0F, 0.0F, 0.0F, 0.0F, cx,   sx,   0.0F,
                              0.0F, -sx,  cx,   0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 绕 Y 轴旋转矩阵(列主序)
    const GLfloat rotY[16] = {cy, 0.0F, -sy, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F,
                              sy, 0.0F, cy,  0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 绕 Z 轴旋转矩阵(列主序)
    const GLfloat rotZ[16] = {cz,   sz,   0.0F, 0.0F, -sz,  cz,   0.0F, 0.0F,
                              0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 组合: T * Rx * Ry * Rz
    GLfloat temp1[16], temp2[16], finalMatrix[16];
    multiplyMatrix4(rotY, rotZ, temp1);         // temp1 = Ry * Rz
    multiplyMatrix4(rotX, temp1, temp2);        // temp2 = Rx * Ry * Rz
    multiplyMatrix4(trans, temp2, finalMatrix); // final = T * Rx * Ry * Rz

    glMultMatrixf(finalMatrix);

    // 圆心
    glColor3f(1.0F, 1.0F, 1.0F);
    glPointSize(6.0F);
    glBegin(GL_POINTS);
    glVertex3f(0.0F, 0.0F, 0.0F);
    glEnd();

    drawSphere(0.5F, 20, 20);

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 50.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
    case 27: // ESC 键
    case 'q':
    case 'Q':
        std::cout << "keyboard close..." << "\n";
        exit(0);
        break;
    case 'a':
    case 'A':
        zRot -= 5.0F; // 绕 Z 轴逆时针旋转
        glutPostRedisplay();
        break;
    case 'd':
    case 'D':
        zRot += 5.0F; // 绕 Z 轴顺时针旋转
        glutPostRedisplay();
        break;
    default:
        break;
    }
}

void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
              << "\n";
    switch (key) {
    case GLUT_KEY_UP:
        xRot -= 5.0F;
        break;
    case GLUT_KEY_DOWN:
        xRot += 5.0F;
        break;
    case GLUT_KEY_LEFT:
        yRot -= 5.0F;
        break;
    case GLUT_KEY_RIGHT:
        yRot += 5.0F;
        break;
    default:
        break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);           // 特殊键事件
    glutKeyboardFunc(keyboard);             // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}

球体世界


// mac 特有的头文件
#include <GLUT/glut.h>

#include <OpenGL/gl.h>
#include <OpenGL/gltypes.h>
#include <OpenGL/glu.h>

#include <cmath>
#include <iostream>
#include <numbers>

struct GLFrame {
    GLfloat vLocation[3]; // 位置  -> move x, y, z
    GLfloat vUp[3];       // 上方向 -> y
    GLfloat vForward[3];  // 前方向 -> z x-> 通过 yz叉积计算 -> 归一化为单位向量
};

// 可视坐标大小
static constexpr GLfloat COORDINATE_SIZE = 120.0F;
static constexpr GLfloat PI = std::numbers::pi_v<GLfloat>;
static constexpr GLint NUM_SPHERES = 50;
GLFrame frames[NUM_SPHERES]{};
GLfloat sphereMatrices[NUM_SPHERES][16];
// 变量
static GLfloat xRot = 0.0F; // x旋转角度
static GLfloat yRot = 0.0F; // y旋转角度
static GLfloat zRot = 0.0F; // z旋转角度

// 4x4 矩阵乘法: result = a * b(列主序,兼容 OpenGL)
void multiplyMatrix4(const GLfloat a[16], const GLfloat b[16],
                     GLfloat result[16]) {
    for (int col = 0; col < 4; ++col) {
        for (int row = 0; row < 4; ++row) {
            result[col * 4 + row] = a[0 * 4 + row] * b[col * 4 + 0] +
                                    a[1 * 4 + row] * b[col * 4 + 1] +
                                    a[2 * 4 + row] * b[col * 4 + 2] +
                                    a[3 * 4 + row] * b[col * 4 + 3];
        }
    }
}
void drawSphere(const GLfloat radius, const GLint slices, const GLint stacks) {
    for (GLint i = 0; i < stacks; ++i) {
        GLfloat phi0 = i * PI / stacks; // 从北极到南极
        GLfloat phi1 = (i + 1) * PI / stacks;
        GLfloat sinP0 = sinf(phi0), cosP0 = cosf(phi0);
        GLfloat sinP1 = sinf(phi1), cosP1 = cosf(phi1);

        glBegin(GL_TRIANGLE_STRIP);
        for (GLint j = 0; j <= slices; ++j) {
            GLfloat theta = j * 2.0f * PI / slices;
            GLfloat sinT = sinf(theta), cosT = cosf(theta);

            // 点(phi0) — 纬线 i
            GLfloat x0 = radius * sinP0 * cosT;
            GLfloat y0 = radius * cosP0;
            GLfloat z0 = radius * sinP0 * sinT;
            glNormal3f(sinP0 * cosT, cosP0, sinP0 * sinT);
            glVertex3f(x0, y0, z0);

            // 点(phi1) — 纬线 i+1
            GLfloat x1 = radius * sinP1 * cosT;
            GLfloat y1 = radius * cosP1;
            GLfloat z1 = radius * sinP1 * sinT;
            glNormal3f(sinP1 * cosT, cosP1, sinP1 * sinT);
            glVertex3f(x1, y1, z1);
        }
        glEnd();
    }
}
void drawGround() {
    constexpr GLfloat fExtent = 20.0F;
    constexpr GLfloat fStep = 1.0F;
    constexpr GLfloat y = -0.4F;

    glBegin(GL_LINES);
    for (GLfloat iLine = -fExtent; iLine <= fExtent; iLine += fStep) {
        glVertex3f(iLine, y, fExtent); // Draw Z lines
        glVertex3f(iLine, y, -fExtent);

        glVertex3f(fExtent, y, iLine);
        glVertex3f(-fExtent, y, iLine);
    }
    glEnd();
}

void gltInitFrame(GLFrame *pFrame) {
    pFrame->vLocation[0] = 0.0f;
    pFrame->vLocation[1] = 0.0f;
    pFrame->vLocation[2] = 0.0f;

    pFrame->vUp[0] = 0.0f;
    pFrame->vUp[1] = 1.0f;
    pFrame->vUp[2] = 0.0f;

    pFrame->vForward[0] = 0.0f;
    pFrame->vForward[1] = 0.0f;
    pFrame->vForward[2] = -1.0f;
}

void drawTorus(const GLfloat majorRadius, const GLfloat minorRadius, const GLint numMajor, const GLint numMinor) {
    for (GLint i = 0; i < numMajor; ++i) {
        const GLfloat u0 = (GLfloat)i / numMajor * 2.0F * PI;
        const GLfloat u1 = (GLfloat)(i + 1) / numMajor * 2.0F * PI;

        glBegin(GL_TRIANGLE_STRIP);
        for (GLint j = 0; j <= numMinor; ++j) {
            GLfloat v = (GLfloat)j / numMinor * 2.0F * PI;
            GLfloat cosV = cosf(v), sinV = sinf(v);

            // 点1 (u0 经线)
            GLfloat cu0 = cosf(u0), su0 = sinf(u0);
            glNormal3f(cu0 * cosV, su0 * cosV, sinV);
            glVertex3f(cu0 * (majorRadius + minorRadius * cosV),
                       su0 * (majorRadius + minorRadius * cosV),
                       minorRadius * sinV);

            // 点2 (u1 经线)
            GLfloat cu1 = cosf(u1), su1 = sinf(u1);
            glNormal3f(cu1 * cosV, su1 * cosV, sinV);
            glVertex3f(cu1 * (majorRadius + minorRadius * cosV),
                       su1 * (majorRadius + minorRadius * cosV),
                       minorRadius * sinV);
        }
        glEnd();
    }
}
void gltGetMatrixFromFrame(GLFrame *pFrame, GLfloat m[16]) {
    // 计算右向量 X = Up × Forward
    GLfloat vRight[3];
    vRight[0] = pFrame->vUp[1] * pFrame->vForward[2] - pFrame->vUp[2] * pFrame->vForward[1];
    vRight[1] = pFrame->vUp[2] * pFrame->vForward[0] - pFrame->vUp[0] * pFrame->vForward[2];
    vRight[2] = pFrame->vUp[0] * pFrame->vForward[1] - pFrame->vUp[1] * pFrame->vForward[0];

    // 填充矩阵(列主序)
    m[0] = vRight[0];           m[4] = vRight[1];           m[8]  = vRight[2];           m[12] = pFrame->vLocation[0];
    m[1] = pFrame->vUp[0];      m[5] = pFrame->vUp[1];      m[9]  = pFrame->vUp[2];      m[13] = pFrame->vLocation[1];
    m[2] = pFrame->vForward[0]; m[6] = pFrame->vForward[1]; m[10] = pFrame->vForward[2]; m[14] = pFrame->vLocation[2];
    m[3] = 0.0f;                m[7] = 0.0f;                m[11] = 0.0f;                m[15] = 1.0f;

}
void renderScene() {
    std::cout << std::format("renderScene: xRot={}, yRot={}, zRot={}", xRot, yRot, zRot) << "\n";
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    // --- 手动构建变换矩阵,替代 glTranslatef / glRotatef ---
    const GLfloat radX = xRot * PI / 180.0F;
    const GLfloat radY = yRot * PI / 180.0F;
    const GLfloat radZ = zRot * PI / 180.0F;

    const GLfloat cx = cosf(radX), sx = sinf(radX);
    const GLfloat cy = cosf(radY), sy = sinf(radY);
    const GLfloat cz = cosf(radZ), sz = sinf(radZ);

    // 平移矩阵 T(列主序)
    const GLfloat trans[16] = {
        1.0F, 0.0F, 0.0F,  0.0F, // col 0
        0.0F, 1.0F, 0.0F,  0.0F, // col 1
        0.0F, 0.0F, 1.0F,  0.0F, // col 2
        0.0F, 0.0F, -1.5F, 1.0F  // col 3 (tx, ty, tz, 1)
    };

    // 绕 X 轴旋转矩阵(列主序)
    const GLfloat rotX[16] = {1.0F, 0.0F, 0.0F, 0.0F, 0.0F, cx,   sx,   0.0F,
                              0.0F, -sx,  cx,   0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 绕 Y 轴旋转矩阵(列主序)
    const GLfloat rotY[16] = {cy, 0.0F, -sy, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F,
                              sy, 0.0F, cy,  0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 绕 Z 轴旋转矩阵(列主序)
    const GLfloat rotZ[16] = {cz,   sz,   0.0F, 0.0F, -sz,  cz,   0.0F, 0.0F,
                              0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F};

    // 组合: T * Rx * Ry * Rz
    GLfloat temp1[16], temp2[16], finalMatrix[16];
    multiplyMatrix4(rotY, rotZ, temp1);         // temp1 = Ry * Rz
    multiplyMatrix4(rotX, temp1, temp2);        // temp2 = Rx * Ry * Rz
    multiplyMatrix4(trans, temp2, finalMatrix); // final = T * Rx * Ry * Rz

    glMultMatrixf(finalMatrix);

    // 地面不随 Y 轴旋转
    drawGround();

    // 圆环 + 大球绕 Y 轴旋转
    static GLfloat orbitAngle = 0.0F;
    orbitAngle += 0.5F; // 逆时针
    if (orbitAngle >= 360.0F) orbitAngle = 0.0F;

    glPushMatrix();
    glRotatef(orbitAngle, 0.0F, 1.0F, 0.0F); // 绕 Y 轴逆时针

    constexpr GLfloat majorRadius = 0.35F;
    constexpr GLfloat minorRadius = 0.15F;
    constexpr int numMajor = 40;
    constexpr int numMinor = 20;
    drawTorus(majorRadius, minorRadius, numMajor, numMinor);

    // 在圆环外侧画一个球体
    glPushMatrix();
    glTranslatef(majorRadius + minorRadius + 0.1F, 0.0F, 0.0F); // 放在圆环外缘
    drawSphere(0.08F, 13, 26);
    glPopMatrix();

    glPopMatrix(); // 结束 Y 轴旋转

    for (GLint i = 0; i < NUM_SPHERES; i++) {
        glPushMatrix();
        glMultMatrixf(sphereMatrices[i]);
        drawSphere(0.1F, 13, 26);
        glPopMatrix();
    }

    glPopMatrix();

    glutSwapBuffers();
}

void setupRc() {
    // 设置清除颜色为黑色
    glClearColor(0.0F, 0.0F, 0.5F, 1.0F);
    glEnable(GL_DEPTH_TEST);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    for (GLint i = 0; i < NUM_SPHERES; ++i) {
        gltInitFrame(&frames[i]);
        frames[i].vLocation[0] = (float)((rand() % 400) - 200) * 0.1f;
        frames[i].vLocation[1] = 0.0F;
        frames[i].vLocation[2] = (float)((rand() % 400) - 200) * 0.1f;
        gltGetMatrixFromFrame(&frames[i], sphereMatrices[i]);
    }
}

void changeSize(const GLsizei w, const GLsizei h) {
    std::cout << std::format("changeSize: w={}, h={}", w, h) << "\n";
    // 防止除以 0
    if (h == 0) {
        throw std::runtime_error("h == 0");
    }
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION); // 投影
    glLoadIdentity();
    const GLfloat aspectRatio =
        static_cast<GLfloat>(w) / static_cast<GLfloat>(h);
    gluPerspective(60.0F, aspectRatio, 1.0F, 50.0F);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// 键盘回调:按 ESC 或 'q' 退出
void keyboard(const unsigned char key, const int x, const int y) {
    std::cout << std::format("keyboard: key={}, x={}, y={}", key, x, y) << "\n";
    switch (key) {
    case 27: // ESC 键
    case 'q':
    case 'Q':
        std::cout << "keyboard close..." << "\n";
        exit(0);
        break;
    case 'a':
    case 'A':
        zRot -= 5.0F; // 绕 Z 轴逆时针旋转
        glutPostRedisplay();
        break;
    case 'd':
    case 'D':
        zRot += 5.0F; // 绕 Z 轴顺时针旋转
        glutPostRedisplay();
        break;
    default:
        break;
    }
}

void specialKeys(const int key, const int x, const int y) {
    std::cout << std::format("specialKeys: key={}, x={}, y={}", key, x, y)
              << "\n";
    switch (key) {
    case GLUT_KEY_UP:
        xRot -= 5.0F;
        break;
    case GLUT_KEY_DOWN:
        xRot += 5.0F;
        break;
    case GLUT_KEY_LEFT:
        yRot -= 5.0F;
        break;
    case GLUT_KEY_RIGHT:
        yRot += 5.0F;
        break;
    default:
        break;
    }
    // Refresh the Window
    glutPostRedisplay();
}

void timerFunc(const int value) {
    glutPostRedisplay();
    glutTimerFunc(1000 / 10, timerFunc, value); // 10 FPS
}

auto main(const int argc, const char **const argv) -> int {
    std::cout << "hello world\n";
    for (int i = 0; i < argc; ++i) {
        std::cout << "argv[" << i << "]: " << argv[i] << "\n";
    }
    // 初始化 glut
    glutInit(const_cast<int *>(&argc), const_cast<char **>(argv));
    // 设置显示模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    // 设置窗口大小
    glutInitWindowSize(800, 600);
    // 创建窗口
    const int result = glutCreateWindow("Hello World");
    std::cout << "result: " << result << "\n";
    if (result == 0) {
        throw std::runtime_error("glutCreateWindow failed");
    }
    // 设置显示回调函数
    glutDisplayFunc(renderScene);
    glutReshapeFunc(changeSize);
    // 注册 键盘事件 回调
    glutSpecialFunc(specialKeys);           // 特殊键事件
    glutKeyboardFunc(keyboard);             // 普通键事件
    glutTimerFunc(1000 / 10, timerFunc, 1); // 10 FPS
    setupRc();
    glutMainLoop();
    return 0;
}
posted @ 2026-08-09 18:03  爱情丶眨眼而去  阅读(7)  评论(0)    收藏  举报