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;
}

浙公网安备 33010602011771号