# opengl演示 **Repository Path**: newCoder0/opengl-demonstration ## Basic Information - **Project Name**: opengl演示 - **Description**: 演示opengl渲染模型,随机材质的顶点 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-05-12 - **Last Updated**: 2024-05-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # opengl演示 #### 介绍 演示opengl渲染模型 代码主要在glPlane.cpp文件里面 使用GLU工具库版本:1.2.2.0 Microsoft Corporation ![输入图片说明](image.png) ![输入图片说明](image2.png) ![输入图片说明](image3.png) #### 软件架构 软件说明 ** 光强插值算法:** 第一步插值:采用三角形的面积来加权 calcTriangleNorm函数接受三个顶点 a、b、c,并通过引用返回计算得到的法向量坐标值 x、y、z。 计算两个边的向量: x1 = a.x - b.x,y1 = a.y - b.y,z1 = a.z - b.z,计算第一个边的向量。 x2 = a.x - c.x,y2 = a.y - c.y,z2 = a.z - c.z,计算第二个边的向量。 计算法向量: x = y1 * z2 - y2 * z1,y = x2 * z1 - x1 * z2,z = x1 * y2 - x2 * y1,利用叉乘计算法向量。 归一化法向量: n = sqrt(x*x + y*y + z*z),计算法向量的模长。 x /= n, y /= n, z /= n,将法向量坐标除以模长,使其归一化。 加权处理: w = abs(x + y + z),计算法向量坐标的绝对值之和,用于加权处理(权重)。 x *= w, y *= w, z *= w,将法向量坐标乘以权重,进行加权处理。 第二步插值: 采用平滑着色模式(GL_SMOOTH):在平滑着色模式下,对顶点的插值计算使得颜色在多边形内部平滑过渡。通过对每个顶点指定不同的法向量,并将这些法向量插值到多边形的每个片段上,可以实现平滑的过渡效果。 **加载模型** 打开文件和读取头部信息: ifstream ifile(filename.c_str()); 创建一个输入文件流对象 ifile,用于打开指定的文件。 if (!ifile) 判断文件是否成功打开,如果打开失败,则输出错误信息并返回。 string off; 定义一个字符串变量 off,用于存储从文件中读取的第一行内容,通常是文件格式的标识(如"OFF")。 getline(ifile, off); 读取文件的第一行内容并赋值给 off,将读取位置移动到下一行。 读取顶点、面和边的数量: ifile >> n_vertices >> n_faces >> n_edges; 从文件中按顺序读取顶点数、面数和边数,并分别赋值给 n_vertices、n_faces 和 n_edges。 分配内存空间: vertices.resize(n_vertices); 调整顶点数组 vertices 的大小为 n_vertices,以便存储顶点的坐标。 faces.resize(n_faces); 调整面数组 faces 的大小为 n_faces,以便存储面的顶点索引。 faceVector.resize(n_faces); 调整面向量数组 faceVector 的大小为 n_faces,用于存储面的相关信息。 vertexVector.resize(n_vertices); 调整顶点向量数组 vertexVector 的大小为 n_vertices,用于存储顶点的相关信息。 vertexVectorTempV.resize(n_vertices); 调整顶点向量临时数组 vertexVectorTempV 的大小为 n_vertices,用于暂存顶点的信息。 读取顶点坐标: for (int i = 0; i < n_vertices; i++) 循环遍历每个顶点的索引 i,从0到 n_vertices-1。 ifile >> vertices[i].x >> vertices[i].y >> vertices[i].z; 从文件中按顺序读取顶点的 x、y、z 坐标,并分别赋值给 vertices[i].x、vertices[i].y 和 vertices[i].z。 通过以上步骤,代码成功读取了模型文件的头部信息(文件格式的标识、顶点数、面数和边数),并动态调整了存储模型数据的数组的大小。 **随机材质的生成:** 随机数种子和生成器初始化: std::random_device rd; 创建一个随机数种子对象 rd,用于获取随机数种子。 std::mt19937 gen(rd()); 使用上一步获取的随机数种子初始化随机数生成器 gen,使用 Mersenne Twister 算法生成均匀分布的随机数。 **随机生成材质信息:** vector vRand; 定义一个存储随机数的浮点数向量 vRand,用于存储随机生成的材质值。 int index = 0; 定义一个索引变量 index,初始值为0,用于逐个获取随机数。 randMat()函数实现: if (index > 8000) index -= 8000; 当索引超过8000时,将索引重置为0,以循环使用之前生成的随机数。 mat_ambient[0] = vRand[(index++)]; 将随机数向量中索引对应位置的值设置为环境光材质的红色分量,并将索引加1。 依次类推,将随机数向量中索引对应位置的值设置为其他材质属性的分量,并将索引加1,直到所有材质属性的分量都被设置完毕。 mat_shininess[0] = vRand[(index++)] * 100; 将随机数向量中索引对应位置的值乘以100,并设置为材质的高光系数。 交互的操作 采用OpenGL的交互函数mouse,用于处理鼠标事件。 根据函数的参数: button表示按下或释放的鼠标按钮(左键、右键等)。 state表示按钮的状态,按下或释放。 (x, y)表示鼠标点击的位置。 下面是对这段代码的交互操作的解释: 当左键按下时: 将变量roate设置为0。 记录当前鼠标坐标(x, y)为oldx和oldy。 输出点击的位置(x, y)。 通过调用glReadPixels函数,获取鼠标点击位置像素的RGB颜色值存储在RGB3f数组中。 根据RGB3f数组的值进行判断: 如果颜色为红色(1.0, 0.0, 0.0),则将angley增加30度。 如果颜色为蓝色(0.0, 0.0, 1.0),则将angley减少30度。 如果颜色为黄色(1.0, 1.0, 0.0),则将anglex增加30度。 如果颜色为绿色(0.0, 1.0, 0.0),则将anglex减少30度。 当右键按下时: roate增加1.0。 通过交互改变这些参数,进而改变画出的模型的位置状态 光照的实现 启用光照功能:通过glEnable(GL_LIGHTING)启用OpenGL的光照功能。通过glEnable(GL_LIGHT0)和glEnable(GL_LIGHT1)启用两个光源。 设置灯光参数: 定义两个GLfloat类型数组light_position和light_position1来设置光源的位置。 定义三个GLfloat类型数组light_ambient,light_diffuse和light_specular来设置光照的环境光、漫反射光和镜面光的强度。 使用glLightfv函数为每个光源设置参数: 使用GL_LINEAR_ATTENUATION选项设置衰减因子,传入attenuation数组。 使用GL_POSITION选项设置光源的位置,分别传入light_position和light_position1数组。 使用GL_AMBIENT选项设置环境光的强度,传入light_ambient数组。 使用GL_DIFFUSE选项设置漫反射光的强度,传入light_diffuse数组。 使用GL_SPECULAR选项设置镜面光的强度,传入light_specular数组。 #### 安装教程 1. xxxx 2. xxxx 3. xxxx #### 使用说明 1. xxxx 2. xxxx 3. xxxx #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) ### 其他 ![输入图片说明](image4.png) ![输入图片说明](image5.png)