OpenGL 立方体平行斜投影的绘制

您所在的位置:网站首页 什么是平行投影法斜投影法和正投影法有何区别 OpenGL 立方体平行斜投影的绘制

OpenGL 立方体平行斜投影的绘制

2023-06-27 11:32| 来源: 网络整理| 查看: 265

OpenGL 长方体平行斜投影的绘制

文章目录 OpenGL 长方体平行斜投影的绘制题目描述分析平行斜投影代码思路必要函数介绍鼠标操作视图操作 编程实现环境代码 效果图思考与拓展

题目描述

绘制一个长方体的平行斜投影

分析

题目不长也很容易理解,首先搞明白什么是平行斜投影,这个问题最难的点在于使用OpenGL绘制三维图像,并且将投影和原图的效果都比较清晰和直观地展示出来。

平行斜投影

计算机图形学里面的投影主要分为两种,一种是平行投影,另一种是透视投影。

平行投影就是平行光的投影,类似于太阳光照射人到地面形成影子这样的情形。即光源离被照射物体很远。

透视投影就是灯光照射杯子都桌面这样子的。即光源离被照射物体很近。

而平行投影又分为正投影和斜投影,这个顾名思义,很容易理解。

题目要求的就是平行投影中的后者了。

代码思路

思路一: 三维效果可以建立坐标系,然后把必要元素都画出来,只要有坐标系相信都是看的懂得。

思路二: 曾经看到过鼠标操作OpenGL这样的操作,可以实现拖拉改变图像视角,就很厉害,也很直观。

第一个画出来太丑了,直接第二个吧,不然交的作业老师不高兴给成绩。。。

必要函数介绍

这里介绍的是Glut开源库的介绍,引一个GLUT官方文档先

http://freeglut.sourceforge.net/docs/api.php

鉴于这个库已经有20年没有更新了,欢迎大家试着用GLFW和GLEW做。给一个中文版的教程

https://learnopengl-cn.github.io/

最后再加一个OpenGL的官方网站。

https://www.opengl.org/

[ 如果有大佬搞定了win10下clion的glfw配置(运行时候没有 undefined reference 报错),请救救孩子谢谢!] 鼠标操作

关于鼠标操作,这边引一个博客教程来参考。

https://blog.csdn.net/m0_37876745/article/details/78147046

比较关键的函数在下表中罗列:

函数名作用glutMouseFunc();处理鼠标点击glutMotionFunc);处理鼠标拖动glutPassiveMotionFunc()追踪鼠标位置 视图操作

主要关于三维坐标下的选取观测点以及设置观测角度问题。 还是给出两篇参考吧。

https://blog.csdn.net/peng6662001/article/details/7082436 https://blog.csdn.net/ivan_ljf/article/details/8764737

函数名作用glMatrixMode()设置矩阵模式(投影/模型/纹理)gluPerspective()设置透视效果参数gluLookAt()设置观测点 编程实现 环境 win10Clionfreeglut 代码 #include #include #define PI 3.1415926 static int init_angel=90, dx=-5, dy=-5; static float r=50,h=90.0; static float angel_trans_unit=float(PI/180.00); void ChangeSize(int w, int h) { // w, h是整个window的宽高 // 这个函数是为了使窗口在被拉伸调整的时候实时重画图像 glViewport(0,0,(GLsizei)w,(GLsizei)h); // 投影模式 glMatrixMode(GL_PROJECTION); // 单位矩阵 glLoadIdentity(); // 产生透视效果 gluPerspective(30.0,(float)w/h,1.0,1000.0); // 模版模式,用于绘图 glMatrixMode(GL_MODELVIEW); } void Line(double x0, double y0, double z0, double x1, double y1, double z1){ glLineWidth(3); glBegin(GL_LINES); glVertex3d(x0,y0,z0); glVertex3d(x1,y1,z1); glEnd(); glFlush(); } void Cube( double x[], double y[], double z[]) { // 绘制原长方体(黄色) glColor3f(1.0,1.0,0.0); // 用很蠢的的方法把长方体所有线画一遍 Line(x[0],y[0],z[0],x[1],y[0],z[0]); Line(x[0],y[0],z[0],x[0],y[1],z[0]); Line(x[0],y[0],z[0],x[0],y[0],z[1]); Line(x[1],y[1],z[0],x[1],y[0],z[0]); Line(x[1],y[1],z[0],x[0],y[1],z[0]); Line(x[0],y[0],z[1],x[0],y[1],z[1]); Line(x[1],y[0],z[0],x[1],y[0],z[1]); Line(x[0],y[1],z[0],x[0],y[1],z[1]); Line(x[0],y[0],z[1],x[1],y[0],z[1]); Line(x[1],y[1],z[1],x[1],y[1],z[0]); Line(x[1],y[1],z[1],x[0],y[1],z[1]); Line(x[1],y[1],z[1],x[1],y[0],z[1]); } void AXIS() // 画个坐标轴 { // 红色的Z轴 glColor3f(1.0,0.0,0.0); Line(0,0,-300,0,0,300); // 绿色的y轴 glColor3f(0.0,1.0,0.0); Line(0,-300,0,0,300,0); // 蓝色的x轴 glColor3f(0.0,0.0,1.0); Line(-300,0,0,300,0,0); } void Projection(double x[], double y[], double z[], double l, double alpha) // 光线沿从(0,0,1)到(l*cos(alpha), l*sin(alpha), 0)方向 { double p[8][2]; int count = 0; // 求出8个顶点的投影点 for(int i=0;i Line(p[i][0],p[i][1],0,p[j][0],p[j][1],0); } glFlush(); } void RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0f,1.0f,1.0f); glLoadIdentity(); // gluLookAt()函数是指相机的位置 // 一直看向原点,即保持原点是视野中心 gluLookAt(r*cos(angel_trans_unit*init_angel), r*sin(angel_trans_unit*h), r*sin(angel_trans_unit*init_angel), 0.0, 0.0, 0.0, 0.0, 1, 0.0); // 设置长方体的一对对角点的坐标 double x[] = {-1.0, -6.0}, y[] = {-1.0, -6.0}, z[] = {-1.0, -5.0}; // 设置平行光的参数 double l, alpha; l = 1; alpha = PI/4; AXIS(); Cube(x, y, z); Projection(x, y, z, l, alpha); // 实现双缓冲的函数 glutSwapBuffers(); } void Mouse(int button, int state, int x, int y) // 鼠标点击处理 { // 记录鼠标按下位置 if(state == GLUT_DOWN) dx = x,dy = y; } void onMouseMove(int x,int y) // 鼠标拖动处理 // (x,y):鼠标在屏幕平面的的新位置 { // 控制左右旋转 init_angel += x - dx; // 控制上下旋转 h += 1 * (y - dy); // 注意gluLookAt()的参数设置,h有些数值不能取 if((int(h) % 180)==0) h++; // 保存此时的坐标 dx = x,dy = y; } int main(int argc, char* argv[]) { // 初始化 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(1200, 700); glutCreateWindow("HomeWork2_1"); // 可以体现图形在视野点看来的前后关系 glEnable(GL_DEPTH_TEST); // 设置视图效果(透视投影、缩放) glutReshapeFunc(ChangeSize); // 两个设置,前者是为了画图,后者是为了拖动操作更流畅 glutDisplayFunc(RenderScene); glutIdleFunc(RenderScene); // 鼠标动作的设定 glutMouseFunc(Mouse); glutMotionFunc(onMouseMove); // 最后日常进入主循环 glutMainLoop(); return 0; } 效果图

长方体及其平行斜投影 上图:红绿蓝是坐标轴,分别对应ZYX轴,平行光向量为( 2 2 \frac{\sqrt{2}}{2} 22 ​​, 2 2 \frac{\sqrt{2}}{2} 22 ​​,-1),投影在z=0平面上。

思考与拓展 画图部分的代码应该可以在进一步,算法功底不够深,思考怎么优化平行斜投影部分怎么才能做到更好的效果,这样子的乱遭遭的线不是个好主意


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3