glutInitDisplayMode(unsigned int mode)

本文介绍了GLUT库中用于设置初始显示模式的函数glutInitDisplayMode的详细用法。该函数允许开发者通过参数mode指定不同的显示特性,如颜色模式、缓存类型等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数功能:设置初始显示模式。

函数原型:void glutInitDisplayMode(unsigned int mode);

mode : mode可取以下值或其组合:

  
对应宏定义意义
GLUT_RGB0x0000指定RGB颜色模式的窗口
GLUT_RGBA0x0000指定RGBA 颜色模式的窗口
GLUT_INDEX0x0001指定颜色索引模式的窗口
GLUT_SINGLE0x0000指定单缓存窗口
GLUT_DOUBLE0x0002指定双缓存窗口
GLUT_ACCUM0x0004窗口使用累加缓存
GLUT_ALPHA0x0008窗口的颜色分量包含 alpha 值
GLUT_DEPTH0x0010窗口使用深度缓存
GLUT_STENCIL0x0020窗口使用模板缓存
GLUT_MULTISAMPLE0x0080指定支持多样本功能的窗口
GLUT_STEREO0x0100指定立体窗口
GLUT_LUMINANCE0x0200窗口使用亮度颜色模型
#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的库吗
最新发布
06-22
<think>我们有一个任务:将基于GLUT的OpenGL代码改写为仅使用Glad和GLFW库的版本。根据引用内容,我们知道:-GLFW是一个用于创建窗口和上下文、处理事件的库。-Glad用于加载OpenGL函数指针(因为OpenGL是函数指针驱动的,不同显卡驱动提供的函数指针地址不同,需要运行时加载)。-GLUT是一个较旧的库,提供窗口管理和事件处理,但现代开发中更推荐使用GLFW。改写步骤:1.初始化GLFW,创建窗口和OpenGL上下文。2.初始化Glad,加载OpenGL函数指针。3.设置必要的回调函数(如窗口大小改变的回调、键盘事件回调等)。4.将GLUT的主循环替换为GLFW的渲染循环。具体步骤:第一步:初始化GLFW并创建窗口-使用`glfwInit()`初始化GLFW。-配置窗口参数,例如设置OpenGL版本和核心模式(如引用[1]所述)。-创建窗口对象。第二步:初始化Glad-在创建窗口后,需要将上下文设为当前,然后初始化Glad。第三步:设置视口和回调函数-设置窗口大小改变时的回调(类似于GLUT的`glutReshapeFunc`)。-设置键盘事件回调(类似于`glutKeyboardFunc`)。第四步:渲染循环-使用`while(!glfwWindowShouldClose(window))`循环来替代GLUT的`glutMainLoop`。-在循环中,处理事件(`glfwPollEvents`或`glfwWaitEvents`),执行渲染,然后交换缓冲区。示例代码结构:假设原GLUT代码结构如下:```c#include<GL/glut.h>voiddisplay(){//渲染代码}voidreshape(intw,inth){//窗口大小变化时调整视口}voidkeyboard(unsignedcharkey,intx,inty){//键盘事件处理}intmain(intargc,char**argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);glutInitWindowSize(800,600);glutCreateWindow("GLUTWindow");glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return0;}```改写为GLFW+Glad版本:```c#include<glad/glad.h>#include<GLFW/glfw3.h>//回调函数声明voidframebuffer_size_callback(GLFWwindow*window,intwidth,intheight);voidprocessInput(GLFWwindow*window);intmain(){//1.初始化GLFWglfwInit();//配置GLFW:设置OpenGL版本为3.3,核心模式glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);//如果是MacOSX,需要加上下面这行//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE);//2.创建窗口GLFWwindow*window=glfwCreateWindow(800,600,"GLFWWindow",NULL,NULL);if(window==NULL){//创建失败处理glfwTerminate();return-1;}glfwMakeContextCurrent(window);//3.初始化Gladif(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){//初始化失败return-1;}//4.设置视口和回调函数//设置窗口大小改变回调glfwSetFramebufferSizeCallback(window,framebuffer_size_callback);//也可以设置键盘回调,但这里我们使用另一种方式:在循环中处理输入//5.渲染循环while(!glfwWindowShouldClose(window)){//输入处理processInput(window);//渲染指令glClearColor(0.2f,0.3f,0.3f,1.0f);glClear(GL_COLOR_BUFFER_BIT);//...绘制代码//交换缓冲glfwSwapBuffers(window);//轮询事件glfwPollEvents();}//6.清理资源glfwTerminate();return0;}//窗口大小改变回调voidframebuffer_size_callback(GLFWwindow*window,intwidth,intheight){glViewport(0,0,width,height);}//输入处理(这里处理键盘输入,例如按下ESC退出)voidprocessInput(GLFWwindow*window){if(glfwGetKey(window,GLFW_KEY_ESCAPE)==GLFW_PRESS)glfwSetWindowShouldClose(window,true);}```注意:-原GLUT的显示函数(display)在GLFW中需要在循环内调用,我们可以将原display函数的内容放到渲染循环中。-原reshape函数的功能由`framebuffer_size_callback`实现。-原键盘回调函数,在GLFW中可以使用回调函数(如`glfwSetKeyCallback`)或者像上面这样在循环中处理。如果需要处理其他事件(如鼠标、键盘按键等),可以设置相应的回调函数,或者在循环中通过`glfwGetKey`等函数查询状态。对于原GLUT代码中的其他功能,如定时器(`glutTimerFunc`)等,GLFW也有相应的函数(`glfwSetTime`和`glfwGetTime`)以及可以自己实现定时功能。以上是一个基本的框架,具体代码需要根据原GLUT程序的功能进行填充。根据引用[5],我们还可以看到一些示例代码的结构,这里也参考了这些结构。因此,改写步骤总结为:1.替换初始化代码:用GLFW初始化代替GLUT初始化。2.创建窗口和上下文:使用GLFW的窗口创建函数。3.加载OpenGL函数指针:使用Glad。4.设置回调函数:将GLUT的各种回调函数用GLFW的回调函数替代。5.重写主循环:使用GLFW的事件循环。注意:GLUT和GLFW的事件处理模型有所不同,GLUT是回调驱动,而GLFW允许在循环中主动查询输入状态,也支持回调函数。可以根据需要选择。最后,确保在程序结束时调用`glfwTerminate()`来清理资源。如果有原GLUT代码,我们可以根据上述框架进行改写。如果没有具体的原代码,以上提供了一个通用的改写方法。</think>### 将GLUT代码迁移到GLFW和Glad的完整指南 #### 核心改写步骤 1. **初始化GLFW替代GLUT** ```c // 替换 glutInit(&argc, argv); if (!glfwInit()) { // 错误处理 } // 设置OpenGL版本和核心模式(引用[1]) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac专用 #endif ``` 2. **创建窗口替代GLUT窗口** ```c // 替换 glutCreateWindow("Title"); GLFWwindow* window = glfwCreateWindow(800, 600, "GLFW Window", NULL, NULL); if (!window) { glfwTerminate(); // 错误处理 } glfwMakeContextCurrent(window); ``` 3. **初始化Glad加载函数指针** ```c // 在创建上下文后立即初始化 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { // 错误处理 } ``` 4. **回调函数迁移** ```c // 替换 glutDisplayFunc(display); // 在渲染循环中直接调用显示函数 // 替换 glutReshapeFunc(reshape); glfwSetFramebufferSizeCallback(window, [](GLFWwindow* w, int width, int height){ glViewport(0, 0, width, height); // 添加其他reshape逻辑 }); // 替换 glutKeyboardFunc(keyboard); glfwSetKeyCallback(window, [](GLFWwindow* w, int key, int scancode, int action, int mods){ if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(w, GLFW_TRUE); // 添加其他键盘处理 }); ``` 5. **主循环重构** ```c // 替换 glutMainLoop(); while (!glfwWindowShouldClose(window)) { // 处理事件 glfwPollEvents(); // 渲染代码(原display函数内容) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // ... 绘制逻辑 // 交换缓冲区 glfwSwapBuffers(window); } ``` #### 完整代码示例 ```c #include <glad/glad.h> #include <GLFW/glfw3.h> int main() { // 1. 初始化GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 2. 创建窗口 GLFWwindow* window = glfwCreateWindow(800, 600, "GLFW Window", NULL, NULL); glfwMakeContextCurrent(window); // 3. 加载Glad gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); // 4. 设置回调 glfwSetFramebufferSizeCallback(window, [](GLFWwindow* w, int width, int height){ glViewport(0, 0, width, height); }); // 5. 主循环 while (!glfwWindowShouldClose(window)) { glfwPollEvents(); // 渲染代码 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // ... 原始绘制代码 glfwSwapBuffers(window); } // 6. 清理 glfwTerminate(); return 0; } ``` #### 关键差异处理 1. **资源管理** - 删除所有`glut`前缀的函数调用 - 纹理/缓冲区对象管理保持不变(引用[3]) - 字体渲染需改用FreeType等库替代GLUT Bitmap 2. **事件处理** - GLFW使用基于回调的现代事件系统 - 鼠标事件使用`glfwSetCursorPosCallback` - 定时器需改用`glfwSetTime`和`glfwGetTime` 3. **上下文管理** - GLFW显式管理OpenGL上下文(引用[4]) - 多窗口支持更灵活 4. **扩展加载** - Glad提供类型安全的扩展加载 - 替代GLUT的隐式扩展加载机制 #### 迁移注意事项 1. **核心模式差异**:现代OpenGL核心模式移除立即渲染模式(如`glBegin/glEnd`),需改用VBO/VAO(引用[2]) 2. **MacOS适配**:必须启用`GLFW_OPENGL_FORWARD_COMPAT`标志(引用[1]) 3. **依赖管理**: ```cmake # CMake配置示例 find_package(glfw3 REQUIRED) include_directories(${GLFW_INCLUDE_DIRS}) target_link_libraries(YourTarget glad glfw) ``` 4. **调试支持**:建议添加OpenGL调试输出回调 ```c glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(glDebugOutput, nullptr); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值