#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <string.h>
#define PI 3.14159265358979323846
// 全局变量
typedef struct {
float x, y, z;
} Point3D;
typedef struct {
float r, g, b, a;
} Color;
typedef struct {
int v1, v2, v3;
} Face;
// 网格数据结构
typedef struct {
int numVertices;
int numFaces;
Point3D* vertices;
Face* faces;
Point3D* normals; // 用于光照计算的法线
float* texCoords; // 纹理坐标
} Mesh;
// 变换控制
typedef struct {
Point3D translation;
Point3D rotation;
float scale;
int transformMode; // 0:旋转, 1:平移, 2:缩放
} Transform;
// 应用程序状态
typedef struct {
Mesh mesh;
int drawMode; // 0:点, 1:边, 2:面, 3:真实感
Transform transform;
Point3D pivotPoint;
int lastMouseX;
int lastMouseY;
int mouseLeftDown;
int mouseRightDown;
int showHelp;
int showTransformPoints;
int textureEnabled;
GLuint textureID;
Point3D q1, q2; // 用户输入的变换点
Point3D originalP1, originalP2; // 原始北极和南极
} AppState;
AppState appState;
// 纹理数据(简单的棋盘纹理)
#define TEX_WIDTH 64
#define TEX_HEIGHT 64
GLubyte texture[TEX_WIDTH][TEX_HEIGHT][3];
// 创建棋盘纹理
void createTexture() {
for (int i = 0; i < TEX_WIDTH; i++) {
for (int j = 0; j < TEX_HEIGHT; j++) {
int c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;
texture[i][j][0] = (GLubyte)c;
texture[i][j][1] = (GLubyte)(c * 0.7);
texture[i][j][2] = (GLubyte)(255 - c);
}
}
}
// 初始化纹理
void initTexture() {
createTexture();
glGenTextures(1, &appState.textureID);
glBindTexture(GL_TEXTURE_2D, appState.textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0,
GL_RGB, GL_UNSIGNED_BYTE, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
appState.textureEnabled = 1;
}
// 读取网格文件
void ReadMesh(const char* fName) {
FILE* fp = fopen(fName, "r");
if (!fp) {
printf("无法打开文件: %s\n", fName);
exit(1);
}
// 读取顶点数和面数
int nE;
if (fscanf(fp, "%d %d %d", &appState.mesh.numVertices, &nE, &appState.mesh.numFaces) != 3) {
printf("文件格式错误\n");
fclose(fp);
exit(1);
}
// 分配内存
appState.mesh.vertices = (Point3D*)malloc(appState.mesh.numVertices * sizeof(Point3D));
appState.mesh.faces = (Face*)malloc(appState.mesh.numFaces * sizeof(Face));
appState.mesh.normals = (Point3D*)malloc(appState.mesh.numVertices * sizeof(Point3D));
appState.mesh.texCoords = (float*)malloc(appState.mesh.numVertices * 2 * sizeof(float));
// 初始化法线
for (int i = 0; i < appState.mesh.numVertices; i++) {
appState.mesh.normals[i].x = 0.0f;
appState.mesh.normals[i].y = 0.0f;
appState.mesh.normals[i].z = 0.0f;
}
// 读取顶点
for (int i = 0; i < appState.mesh.numVertices; i++) {
float x, y, z;
if (fscanf(fp, "%f %f %f", &x, &y, &z) != 3) {
printf("顶点数据错误\n");
fclose(fp);
free(appState.mesh.vertices);
free(appState.mesh.faces);
exit(1);
}
appState.mesh.vertices[i].x = x;
appState.mesh.vertices[i].y = y;
appState.mesh.vertices[i].z = z;
// 计算纹理坐标 (球面映射)
float u = 0.5f + atan2(z, x) / (2.0f * PI);
float v = 0.5f - asin(y) / PI;
appState.mesh.texCoords[2 * i] = u;
appState.mesh.texCoords[2 * i + 1] = v;
}
// 读取面(假设所有面都是三角形)
for (int i = 0; i < appState.mesh.numFaces; i++) {
int v1, v2, v3;
if (fscanf(fp, "%d %d %d", &v1, &v2, &v3) != 3) {
printf("面数据错误\n");
fclose(fp);
free(appState.mesh.vertices);
free(appState.mesh.faces);
exit(1);
}
appState.mesh.faces[i].v1 = v1;
appState.mesh.faces[i].v2 = v2;
appState.mesh.faces[i].v3 = v3;
// 计算面法线
Point3D p1 = appState.mesh.vertices[v1];
Point3D p2 = appState.mesh.vertices[v2];
Point3D p3 = appState.mesh.vertices[v3];
Point3D v = { p2.x - p1.x, p2.y - p1.y, p2.z - p1.z };
Point3D w = { p3.x - p1.x, p3.y - p1.y, p3.z - p1.z };
// 叉积
Point3D normal;
normal.x = v.y * w.z - v.z * w.y;
normal.y = v.z * w.x - v.x * w.z;
normal.z = v.x * w.y - v.y * w.x;
// 归一化
float len = sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);
if (len > 0) {
normal.x /= len;
normal.y /= len;
normal.z /= len;
}
// 累加到顶点法线
appState.mesh.normals[v1].x += normal.x;
appState.mesh.normals[v1].y += normal.y;
appState.mesh.normals[v1].z += normal.z;
appState.mesh.normals[v2].x += normal.x;
appState.mesh.normals[v2].y += normal.y;
appState.mesh.normals[v2].z += normal.z;
appState.mesh.normals[v3].x += normal.x;
appState.mesh.normals[v3].y += normal.y;
appState.mesh.normals[v3].z += normal.z;
}
// 归一化顶点法线
for (int i = 0; i < appState.mesh.numVertices; i++) {
float len = sqrt(appState.mesh.normals[i].x * appState.mesh.normals[i].x +
appState.mesh.normals[i].y * appState.mesh.normals[i].y +
appState.mesh.normals[i].z * appState.mesh.normals[i].z);
if (len > 0) {
appState.mesh.normals[i].x /= len;
appState.mesh.normals[i].y /= len;
appState.mesh.normals[i].z /= len;
}
}
fclose(fp);
printf("成功加载网格: %d 顶点, %d 面\n", appState.mesh.numVertices, appState.mesh.numFaces);
// 保存原始北极和南极
appState.originalP1 = appState.mesh.vertices[0]; // 北极
appState.originalP2 = appState.mesh.vertices[appState.mesh.numVertices - 1]; // 南极
appState.q1 = appState.originalP1;
appState.q2 = appState.originalP2;
}
// 应用变换矩阵
void applyTransformations() {
// 应用平移
glTranslatef(appState.transform.translation.x,
appState.transform.translation.y,
appState.transform.translation.z);
// 应用旋转
glRotatef(appState.transform.rotation.x, 1.0f, 0.0f, 0.0f);
glRotatef(appState.transform.rotation.y, 0.0f, 1.0f, 0.0f);
glRotatef(appState.transform.rotation.z, 0.0f, 0.0f, 1.0f);
// 应用缩放
glScalef(appState.transform.scale,
appState.transform.scale,
appState.transform.scale);
}
// 应用球面变换(将P1变换到Q1,P2变换到Q2)
void applySphereTransformation() {
// 计算原始地轴向量
Point3D originalAxis;
originalAxis.x = appState.originalP2.x - appState.originalP1.x;
originalAxis.y = appState.originalP2.y - appState.originalP1.y;
originalAxis.z = appState.originalP2.z - appState.originalP1.z;
// 计算目标地轴向量
Point3D targetAxis;
targetAxis.x = appState.q2.x - appState.q1.x;
targetAxis.y = appState.q2.y - appState.q1.y;
targetAxis.z = appState.q2.z - appState.q1.z;
// 计算原始轴长度
float originalLength = sqrt(originalAxis.x * originalAxis.x +
originalAxis.y * originalAxis.y +
originalAxis.z * originalAxis.z);
// 计算目标轴长度
float targetLength = sqrt(targetAxis.x * targetAxis.x +
targetAxis.y * targetAxis.y +
targetAxis.z * targetAxis.z);
// 计算缩放因子
float scale = targetLength / originalLength;
// 计算旋转轴和角度
Point3D axis;
float angle;
if (originalLength > 0 && targetLength > 0) {
// 归一化向量
originalAxis.x /= originalLength;
originalAxis.y /= originalLength;
originalAxis.z /= originalLength;
targetAxis.x /= targetLength;
targetAxis.y /= targetLength;
targetAxis.z /= targetLength;
// 计算旋转轴(叉积)
axis.x = originalAxis.y * targetAxis.z - originalAxis.z * targetAxis.y;
axis.y = originalAxis.z * targetAxis.x - originalAxis.x * targetAxis.z;
axis.z = originalAxis.x * targetAxis.y - originalAxis.y * targetAxis.x;
// 计算旋转角度(点积)
float dot = originalAxis.x * targetAxis.x +
originalAxis.y * targetAxis.y +
originalAxis.z * targetAxis.z;
// 确保点积在有效范围内
if (dot < -1.0f) dot = -1.0f;
else if (dot > 1.0f) dot = 1.0f;
angle = acos(dot) * 180.0f / PI;
// 应用变换
glTranslatef(appState.q1.x, appState.q1.y, appState.q1.z);
glRotatef(angle, axis.x, axis.y, axis.z);
glScalef(scale, scale, scale);
glTranslatef(-appState.originalP1.x, -appState.originalP1.y, -appState.originalP1.z);
}
}
// 初始化OpenGL
void initGL() {
glClearColor(0.1f, 0.1f, 0.15f, 1.0f); // 深蓝色背景
glEnable(GL_DEPTH_TEST); // 启用深度测试
glShadeModel(GL_SMOOTH); // 平滑着色
glEnable(GL_NORMALIZE); // 自动归一化法线
// 设置光照
GLfloat lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat lightDiffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat lightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat lightPosition[] = { 5.0f, 5.0f, 5.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
// 设置材质
GLfloat matAmbient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat matDiffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat matSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat matShininess[] = { 50.0f };
glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, matShininess);
// 初始化纹理
initTexture();
}
// 绘制坐标轴
void drawAxes() {
glDisable(GL_LIGHTING);
glLineWidth(2.0f);
glBegin(GL_LINES);
// X轴 (红色)
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.5f, 0.0f, 0.0f);
// Y轴 (绿色)
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.5f, 0.0f);
// Z轴 (蓝色)
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 1.5f);
glEnd();
glEnable(GL_LIGHTING);
}
// 绘制变换点
void drawTransformPoints() {
if (!appState.showTransformPoints) return;
glDisable(GL_LIGHTING);
glPointSize(10.0f);
// 绘制Q1点 (红色)
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POINTS);
glVertex3f(appState.q1.x, appState.q1.y, appState.q1.z);
glEnd();
// 绘制Q2点 (蓝色)
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_POINTS);
glVertex3f(appState.q2.x, appState.q2.y, appState.q2.z);
glEnd();
// 绘制连接线
glLineWidth(2.0f);
glBegin(GL_LINES);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(appState.q1.x, appState.q1.y, appState.q1.z);
glVertex3f(appState.q2.x, appState.q2.y, appState.q2.z);
glEnd();
glEnable(GL_LIGHTING);
}
// 显示帮助信息
void drawHelp() {
if (!appState.showHelp) return;
glDisable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 800, 0, 600);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(1.0f, 1.0f, 0.8f);
glRasterPos2f(10, 580);
/*const char* helpText[] = {
"球面网格查看器 - 帮助信息",
"--------------------------------",
"视图控制:",
" 鼠标左键拖动: 旋转模型",
" 鼠标右键拖动: 缩放模型",
"",
"渲染模式:",
" V: 顶点模式",
" E: 边模式",
" F: 面模式",
" R: 真实感模式",
"",
"变换控制:",
" T: 切换变换模式(旋转/平移/缩放)",
" S: 重置变换",
" P: 显示/隐藏变换点",
"",
"其他:",
" H: 显示/隐藏帮助",
" L: 切换光源",
" X: 切换纹理",
" 1/2: 设置变换点",
" 3: 重置变换点",
" F1: 系统复位",
" ESC: 退出程序",
};*/
const char* helpText[] = {
"Sphere Mesh Viewer - Help", //球面网格查看器 - 帮助信息
"--------------------------------",
"View Controls:", //视图控制:
" Left mouse drag: Rotate model", // 鼠标左键拖动: 旋转模型
" Right mouse drag: Zoom model", //鼠标右键拖动: 缩放模型
"",
"Render Modes:", //渲染模式
" V: Vertex mode", //V: 顶点模式
" E: Edge mode", //E: 边模式
" F: Face mode", //F: 面模式
" R: Realistic mode", //R: 真实感模式
"",
"Transform Controls:", //变换控制
" T: Toggle transform mode (Rotate/Translate/Scale)", //T: 切换变换模式(旋转/平移/缩放)
" S: Reset transform", //S: 重置变换
" P: Show/Hide transform points", //P: 显示/隐藏变换点
"",
"Other:",
" H: Show/Hide help", // H: 显示/隐藏帮助
" L: Toggle lighting", // L: 切换光源
" X: Toggle texture", // X: 切换纹理
" 1/2: Set transform points", // 1/2: 设置变换点
" 3: Reset transform points", // 3: 重置变换点
" F1: System reset", //F1: 系统复位
" ESC: Quit program", // ESC: 退出程序
};
int numLines = sizeof(helpText) / sizeof(char*);
for (int i = 0; i < numLines; i++) {
const char* line = helpText[i];
while (*line) {
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *line);
line++;
}
glRasterPos2f(10, 580 - (i + 1) * 18);
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING);
}
// 显示状态信息
void drawStatus() {
glDisable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 800, 0, 600);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(0.8f, 0.8f, 1.0f);
glRasterPos2f(10, 20);
// 当前模式信息
char modeInfo[256];
const char* drawModes[] = { "Vertex", "Edge", "Face", "Realistic" }; // const char* drawModes[] = { "顶点", "边", "面", "真实感" };
const char* transformModes[] = { "Rotate", "Translate", "Scale" }; //const char* transformModes[] = { "旋转", "平移", "缩放" };
sprintf_s(modeInfo, sizeof(modeInfo), "Render Mode: %s | Transform Mode: %s | Lighting: %s | Texture: %s", //sprintf_s(modeInfo, sizeof(modeInfo), "渲染模式: %s | 变换模式: %s | 光源: %s | 纹理: %s",
drawModes[appState.drawMode],
transformModes[appState.transform.transformMode],
glIsEnabled(GL_LIGHTING) ? "On" : "Off", // glIsEnabled(GL_LIGHTING) ? "开" : "关",
appState.textureEnabled ? "On" : "Off"); //appState.textureEnabled ? "开" : "关");
const char* p = modeInfo;
while (*p) {
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *p);
p++;
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING);
}
// 显示回调函数
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// 设置相机
gluLookAt(0.0, 0.0, 5.0, // 相机位置
0.0, 0.0, 0.0, // 观察点
0.0, 1.0, 0.0); // 上方向
// 应用交互变换
applyTransformations();
// 应用球面变换
applySphereTransformation();
// 绘制坐标轴
drawAxes();
// 绘制变换点
drawTransformPoints();
// 根据绘制模式渲染网格
if (appState.drawMode == 3) { // 真实感模式
if (appState.textureEnabled) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, appState.textureID);
}
else {
glDisable(GL_TEXTURE_2D);
}
glBegin(GL_TRIANGLES);
for (int i = 0; i < appState.mesh.numFaces; i++) {
int v1 = appState.mesh.faces[i].v1;
int v2 = appState.mesh.faces[i].v2;
int v3 = appState.mesh.faces[i].v3;
// 顶点1
glNormal3f(appState.mesh.normals[v1].x,
appState.mesh.normals[v1].y,
appState.mesh.normals[v1].z);
glTexCoord2f(appState.mesh.texCoords[2 * v1], appState.mesh.texCoords[2 * v1 + 1]);
glVertex3f(appState.mesh.vertices[v1].x,
appState.mesh.vertices[v1].y,
appState.mesh.vertices[v1].z);
// 顶点2
glNormal3f(appState.mesh.normals[v2].x,
appState.mesh.normals[v2].y,
appState.mesh.normals[v2].z);
glTexCoord2f(appState.mesh.texCoords[2 * v2], appState.mesh.texCoords[2 * v2 + 1]);
glVertex3f(appState.mesh.vertices[v2].x,
appState.mesh.vertices[v2].y,
appState.mesh.vertices[v2].z);
// 顶点3
glNormal3f(appState.mesh.normals[v3].x,
appState.mesh.normals[v3].y,
appState.mesh.normals[v3].z);
glTexCoord2f(appState.mesh.texCoords[2 * v3], appState.mesh.texCoords[2 * v3 + 1]);
glVertex3f(appState.mesh.vertices[v3].x,
appState.mesh.vertices[v3].y,
appState.mesh.vertices[v3].z);
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
else { // 点、线、面模式
glDisable(GL_LIGHTING);
if (appState.drawMode == 0) { // 点模式
glPointSize(3.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_POINTS);
for (int i = 0; i < appState.mesh.numVertices; i++) {
glVertex3f(appState.mesh.vertices[i].x,
appState.mesh.vertices[i].y,
appState.mesh.vertices[i].z);
}
glEnd();
}
else if (appState.drawMode == 1) { // 边模式
glLineWidth(1.5f);
glColor3f(0.4f, 0.6f, 1.0f);
glBegin(GL_LINES);
for (int i = 0; i < appState.mesh.numFaces; i++) {
int v1 = appState.mesh.faces[i].v1;
int v2 = appState.mesh.faces[i].v2;
int v3 = appState.mesh.faces[i].v3;
glVertex3f(appState.mesh.vertices[v1].x, appState.mesh.vertices[v1].y, appState.mesh.vertices[v1].z);
glVertex3f(appState.mesh.vertices[v2].x, appState.mesh.vertices[v2].y, appState.mesh.vertices[v2].z);
glVertex3f(appState.mesh.vertices[v2].x, appState.mesh.vertices[v2].y, appState.mesh.vertices[v2].z);
glVertex3f(appState.mesh.vertices[v3].x, appState.mesh.vertices[v3].y, appState.mesh.vertices[v3].z);
glVertex3f(appState.mesh.vertices[v3].x, appState.mesh.vertices[v3].y, appState.mesh.vertices[v3].z);
glVertex3f(appState.mesh.vertices[v1].x, appState.mesh.vertices[v1].y, appState.mesh.vertices[v1].z);
}
glEnd();
}
else if (appState.drawMode == 2) { // 面模式
glColor3f(0.2f, 0.8f, 0.3f);
glBegin(GL_TRIANGLES);
for (int i = 0; i < appState.mesh.numFaces; i++) {
int v1 = appState.mesh.faces[i].v1;
int v2 = appState.mesh.faces[i].v2;
int v3 = appState.mesh.faces[i].v3;
glVertex3f(appState.mesh.vertices[v1].x, appState.mesh.vertices[v1].y, appState.mesh.vertices[v1].z);
glVertex3f(appState.mesh.vertices[v2].x, appState.mesh.vertices[v2].y, appState.mesh.vertices[v2].z);
glVertex3f(appState.mesh.vertices[v3].x, appState.mesh.vertices[v3].y, appState.mesh.vertices[v3].z);
}
glEnd();
}
glEnable(GL_LIGHTING);
}
// 绘制帮助信息
drawHelp();
// 绘制状态信息
drawStatus();
glutSwapBuffers();
}
// 窗口大小调整回调
void reshape(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)width / height, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
}
// 键盘回调
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'v': case 'V': // 顶点模式
appState.drawMode = 0;
break;
case 'e': case 'E': // 边模式
appState.drawMode = 1;
break;
case 'f': case 'F': // 面模式
appState.drawMode = 2;
break;
case 'r': case 'R': // 真实感模式
appState.drawMode = 3;
break;
case 't': case 'T': // 切换变换模式
appState.transform.transformMode = (appState.transform.transformMode + 1) % 3;
break;
case 's': case 'S': // 重置变换
appState.transform.translation.x = 0.0f;
appState.transform.translation.y = 0.0f;
appState.transform.translation.z = 0.0f;
appState.transform.rotation.x = 0.0f;
appState.transform.rotation.y = 0.0f;
appState.transform.rotation.z = 0.0f;
appState.transform.scale = 1.0f;
break;
case 'h': case 'H': // 显示/隐藏帮助
appState.showHelp = !appState.showHelp;
break;
case 'p': case 'P': // 显示/隐藏变换点
appState.showTransformPoints = !appState.showTransformPoints;
break;
case 'l': case 'L': // 切换光源
if (glIsEnabled(GL_LIGHTING)) {
glDisable(GL_LIGHTING);
}
else {
glEnable(GL_LIGHTING);
}
break;
case 'x': case 'X': // 切换纹理
appState.textureEnabled = !appState.textureEnabled;
break;
case '1': // 设置Q1点
appState.q1.x = 0.0f;
appState.q1.y = 1.5f;
appState.q1.z = 0.0f;
break;
case '2': // 设置Q2点
appState.q2.x = 0.0f;
appState.q2.y = -1.5f;
appState.q2.z = 0.0f;
break;
case '3': // 重置变换点
appState.q1 = appState.originalP1;
appState.q2 = appState.originalP2;
break;
case 27: // ESC键退出
exit(0);
break;
}
glutPostRedisplay();
}
// 特殊键盘回调(功能键)
void specialKeys(int key, int x, int y) {
switch (key) {
case GLUT_KEY_F1: // 系统复位
appState.transform.translation.x = 0.0f;
appState.transform.translation.y = 0.0f;
appState.transform.translation.z = 0.0f;
appState.transform.rotation.x = 0.0f;
appState.transform.rotation.y = 0.0f;
appState.transform.rotation.z = 0.0f;
appState.transform.scale = 1.0f;
appState.q1 = appState.originalP1;
appState.q2 = appState.originalP2;
break;
case GLUT_KEY_UP: // 向上平移
if (appState.transform.transformMode == 1) {
appState.transform.translation.y += 0.1f;
}
break;
case GLUT_KEY_DOWN: // 向下平移
if (appState.transform.transformMode == 1) {
appState.transform.translation.y -= 0.1f;
}
break;
case GLUT_KEY_LEFT: // 向左平移
if (appState.transform.transformMode == 1) {
appState.transform.translation.x -= 0.1f;
}
break;
case GLUT_KEY_RIGHT: // 向右平移
if (appState.transform.transformMode == 1) {
appState.transform.translation.x += 0.1f;
}
break;
}
glutPostRedisplay();
}
// 鼠标按钮回调
void mouseButton(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
appState.mouseLeftDown = 1;
appState.lastMouseX = x;
appState.lastMouseY = y;
}
else if (state == GLUT_UP) {
appState.mouseLeftDown = 0;
}
}
else if (button == GLUT_RIGHT_BUTTON) {
if (state == GLUT_DOWN) {
appState.mouseRightDown = 1;
appState.lastMouseX = x;
appState.lastMouseY = y;
}
else if (state == GLUT_UP) {
appState.mouseRightDown = 0;
}
}
}
// 鼠标运动回调
void mouseMotion(int x, int y) {
int dx = x - appState.lastMouseX;
int dy = y - appState.lastMouseY;
if (appState.mouseLeftDown) {
if (appState.transform.transformMode == 0) { // 旋转模式
appState.transform.rotation.y += dx * 0.5f;
appState.transform.rotation.x += dy * 0.5f;
}
else if (appState.transform.transformMode == 1) { // 平移模式
appState.transform.translation.x += dx * 0.01f;
appState.transform.translation.y -= dy * 0.01f;
}
}
else if (appState.mouseRightDown) {
if (appState.transform.transformMode == 2) { // 缩放模式
appState.transform.scale += dy * 0.01f;
if (appState.transform.scale < 0.1f) appState.transform.scale = 0.1f;
}
}
appState.lastMouseX = x;
appState.lastMouseY = y;
glutPostRedisplay();
}
// 初始化应用程序状态
void initAppState() {
memset(&appState, 0, sizeof(AppState));
appState.drawMode = 3; // 默认真实感模式
appState.transform.scale = 1.0f;
appState.showHelp = 1; // 初始显示帮助
appState.showTransformPoints = 1; // 初始显示变换点
appState.textureEnabled = 1;
}
// 主函数
int main(int argc, char** argv) {
// 初始化GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("球面网格查看器 - 图形学与虚拟现实实验");
// 初始化应用程序状态
initAppState();
// 加载网格数据
ReadMesh("sphere30x20.msh");
// 设置回调函数
initGL();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(specialKeys);
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMotion);
// 主循环
glutMainLoop();
// 清理
free(appState.mesh.vertices);
free(appState.mesh.faces);
free(appState.mesh.normals);
free(appState.mesh.texCoords);
return 0;
}这段代码能改成仅仅试用glad glfw的库吗
最新发布