欢迎来到汇淘网

汇淘网

OpenGl 导入读取多个3D模型 并且添加鼠标控制移动旋转

时间:2019-12-07 19:43:52 出处:公益阅读(143)

Https://www.cnblogs.com/DOMLX/p/11627508.html序言:由于下一个项目需要阅读多个3D模型,移动和拼接,我将首先编写基本的小演示作为初步测试。 在我之前,互联网上所有的博客只阅读移动和旋转的单个3d模型,结果我根本找不到相关信息,只能自己写 。 一个播种,另一个收获 技术是共享的,每个人都有共同的进步。没有必要让下面的人再次走过这个洞。 对于前两篇文章的部分实现,掌握这一篇并不难:OpenGl读取和导入3d模型,并添加鼠标移动来旋转和显示OpenGl,分别实现多个对象图形的鼠标移动——移动一个对象而另一个对象不移动——读取多个3D模型操作的早期踏脚石,当然,有必要回顾整个实现过程和一些需求准备。 1.读取三维模型在三维图形处理中,模型通常由一个或多个网格组成,网格是可以绘制的独立实体 例如,一个复杂的角色模型可以分为头部、四肢、衣服 、武器等部分来建模,这些网格被组合在一起最终形成一个角色模型 网格由顶点、边和面组成。它包含绘制所需的数据,如顶点位置 、纹理坐标 、法线向量 、材质属性等。它是OpenGL用于绘图的最小实体。 网格的概念如下图所示(摘自:什么是OpenGL中的网格?):网格可以包含多个面。面是可以在网格中绘制的基本元素,例如三角形、多边形和点。 为了使模型更逼真,通常需要添加更多图元来使网格更精细。当然,这也受到硬件处理能力的限制,例如,个人电脑游戏的处理能力优于移动设备 因为多边形可以被分成三角形,而三角形是图形处理器支持的基本图元,所以三角形网格被更频繁地用于建模。 例如 ,下图(来自:什么是OpenGL中的网格?)表达了用越来越复杂的网格来建模兔子的过程:网格2随着三角形数量的增加,兔子模型变得越来越真实 读取3d模型的方法有很多,但最常见的是调用他人编写的库,如(openmesh),其次是读取和分析3d模型文件中的坐标数据,如v vf vn等。 在上面的链接中,我们使用openmesh库导入3d模型并添加灯光 、鼠标控件等。 如图所示:现在,让我们讨论第二种方法,即直接分析和读取三维模型文件,并从中提取我们需要的数据。 下面是一个obj模型文件。我们可以用记事本打开它,看看里面是什么:# blender 3d v 249 objfile:untitled . blend # www . blender 3d . orgmtllib cube . mtlv 1.000000-1.000000v 1.000000-1.000000v-1.000000v-1.000000-1.000000v-1.000000v-1.000000v000000 VN-0.000000-1.000000 0.000000 usemtl Material _ ray . pngs off f 5/1/1/2/1 4/3/1f 5/1 4/3/1 8/4/1f 3/5/2 7/6/2 8/7/2f 3/5/2 8/7/2 4/8/2f 2/9/3 6/10/3/5/3f 6/10/10在这一部分,我们只是试图解释加载模型的原理,而不是讨论它。 o引入一个新的对象v来表示顶点位置vt,顶点纹理坐标vn,顶点法线向量f来表示一个面。面使用1/2/8的格式来表示顶点位置/纹理坐标/法线向量的索引。这里的索引是以前由v、vt和VN定义的数据。注意obj的索引从1开始,而不是从0开始。然后我们只需要获取这些数据,并根据opengl的绘制规则绘制它们。提取数据代码:struct POINT 3 { double X;双Y;双Z;};结构李文;双电视;};结构传真梁{双NX;双纽约;双新西兰元;};结构面(国际诉[3);[国际机场3];[北部3];};PIC类{ public:vector & lt;POINT3>。五.//五:代表顶点 格式是V X Y Z,V后的X Y Z代表三个顶点的坐标。 浮点向量。李文>;VT;//表示纹理坐标 格式是电视 。 浮点向量。传真梁>上;越南;//VN:法向向量 每个三角形的三个顶点必须分配一个法向量 格式为vnnxxnynz 浮点向量。棉棉。f .//女:面条 面后面跟随的整数值分别是属于该面的顶点、纹理坐标和法线向量的索引。 //面的格式为:Fvertex 1/Text 1/Normal 1 vertex 2/Text 2/Normal 2 vertex 3/Text 3/Normal 3 };//GLfloat m _方了= 0.0f;//立方体m_pic1的旋转角度;PIC m _ pic2void readPiC 2(){ if stream if(" cow . obj ");//方块兔子八弦s;棉* f;POINT 3 * v;传真亮* vn李文;而(getline(if ,s)){if (s.length() <。2)继续;如果(s[0]= = ' v '){如果(s[1]= ' t '){//vt 0.581151 0.979929纹理在(s)中流动;vt =新李文();弦头;in >中。>;head >。>;vt->;总工会。>;vt->;电视;m_pic2 。向后推。}否则,如果(s[1]= = = ' n '){//VN 0.637005-0.0421857 0.769705法向量在(s)中流动;vn =新传真梁();弦头;in >中。>;head >。>;vn->;NX >。>;vn->;纽约。>;vn->;新西兰;m_pic2。向后推(* VN);否则{//v-53.0413 158.84-135.806在流中;v =新POINT 3();弦头;in >中。>;head >。>;v->;X >。>;v->;Y >。>;v->;z。m_pic2。v .向后推(* v);}}否则如果(s[0]= = ' f '){//f 2443//26562442//26562444//2656面为(int k = s . size()-1;k >。= 0。k-){ if(s[k]= = = '/')s[k]= ';}正在流中;f =新棉();弦头;in >中 。>;头;int I = 0;而(i & lt3){if (m_pic2。V.size()!= 0){in >中。>;f->;五.[一世];f->;五.[一号]-= 1;}if (m_pic2。VT.size()!= 0){in >中 。>;f->;[一世];f->;[一世]-= 1;}if (m_pic2。VN.size()!= 0){in >中。>;f->;[一世];f->;[一世]-= 1;} i++;}m_pic2。f .向后推(* f);}}}然后直接绘制:for(int I = 0;i <。m_pic1。f . size();i++) { GLbegin(GL _ TALENGS);//绘制三角形if (m_pic1。VT.size()!= 0)GLtexCoorder2f(m _ pic1。[海事卫星1号。[一世]。[0]]。TU,m_pic1。[海事卫星1号。[一世]。[0]]。电视);//纹理if (m_pic1。VN.size()!= 0)glNormal3f(m_pic1 。越南[图片1 。[一世]。[北部0]]。NX,m_pic1。越南[图片1。[一世]。[北部0]] 。纽约,m_pic1。越南[图片1。[一世]。[北部0]] 。新西兰);//法向量glvertex 3f(m _ pic1 . v .[m _ pic1 . f .[一世)。v [0]]。x/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v [0]] 。y/Yu ,m _ pic1 .诉[m _ pic1 . f[一号]。v [0]]。z/Yu);//上顶点if (m_pic1。VT.size()!= 0)GLtexCoorder2f(m _ pic1。[海事卫星1号。[一世]。[1]]。TU,m_pic1。[海事卫星1号。[一世]。[1]]。电视);//纹理if (m_pic1 。VN.size()!= 0)glNormal3f(m_pic1 。越南[图片1。[一世] 。[1]]。NX,m_pic1。越南[图片1。[一世]。[1]]。纽约,m_pic1 。越南[图片1 。[一世] 。[1]]。新西兰);//法向量glvertex 3f(m _ pic1 . v .[m _ pic1 . f .[一世)。v .[1]]。x/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v .[1]] 。y/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v .[1]]。z/Yu);//左下if (m_pic1。VT.size()!= 0)GLtexCoorder2f(m _ pic1。[海事卫星1号 。[一世]。[2]]。TU,m_pic1 。[海事卫星1号。[一世]。[2]]。电视);//纹理if (m_pic1 。VN.size()!= 0)glNormal3f(m_pic1。越南[图片1 。[一世]。[2]]。NX,m_pic1。越南[图片1。[一世] 。[2]]。纽约,m_pic1。越南[图片1。[一世]。[2]]。新西兰);//法向量glvertex 3f(m _ pic1 . v .[m _ pic1 . f .[一世)。v .[2]]。x/Yu,m _ pic1 .诉[m _ pic1 . f[一号] 。v .[2]]。y/Yu ,m _ pic1 .诉[m _ pic1 . f[一号]。v .[2]]。z/Yu);//右下角格伦德();//三角形绘制结束}那么读取多个3d模型只是调用函数并绘制多次。2.鼠标控制相关1。鼠标控制功能准备我们需要获取鼠标信息,然后我们必须需要一个鼠标事件响应功能来控制,很好的opengl已经有了内部鼠标控制功能,我们可以直接使用它 glutMouseFunc( (void*)Func(int按钮,int状态,int x ,int y));GlutMouseFunc是调用鼠标函数的入口,Func是我们给鼠标处理函数取的名字,这三个参数分别是鼠标响应的事件类型,如左键点击、右键点击等。 ,x和y是窗口中当前鼠标位置的坐标。 下面是调用函数GLutmotion FuC(& amp;func(int x,int y));//当鼠标移动时,无论如何,只要编写鼠标点击事件处理程序和鼠标移动事件处理程序,然后将它们传入,在当前鼠标坐标下调用函数X和Y都非常简单。调用函数放在主函数中 无论如何 ,下面的代码是 //void onMouseMove(int x,int y) {//如果(mouse state){如果(选择 != 0) {//x对应于y,因为如果(选择== 1) {movX1 = (x-x1)/2 * 5,它对应于法向向量;glutPurstedisplay();mov 1 =-((y-Y1)/2 * 5);glutPurstedisplay();STD::cout & lt;<。"移动x1 = " < & ltx <。<。" y1 = " <。<。y <。<。STD::endl;}如果(选择= = 2){ MoV x2 =(x-x2)/2 * 5;glutPurstedisplay();mov 2 =-((y-y2)/2 * 5);glutPurstedisplay();STD::cout & lt;<。"移动x2 = " < & ltx <。<。" y2 = " <。<。y <。<。STD::endl;}如果(选择== 3) {//x对应于y ,因为它对应于法向量YRotate 1+= x-Oldx1;glutPurstedisplay();//标记当前窗口需要重绘Oldx1 = x;xrotate 1+= y-old 1;glutPurstedisplay();Oldy1 = y。STD::cout & lt;<。“xRotate = " & lt<。xRotate1 <。<。“yRotate = " & lt<。状态1 <。<。STD::endl;}如果(选择== 4) {//x对应于y ,因为它对应于法向向量YRotate 2+= x-Oldx2;glutPurstedisplay();//标记当前窗口需要重绘Oldx2 = x;xrotate 2+= y-old 2;glutPurstedisplay();Oldy2 = y 。STD::cout & lt;<。“xRotate = " & lt<。xRotate1 <。< 。“yRotate = " & lt<。状态1 <。<。STD::endl;} }其他标准::cout < 。<。“不选择”& lt<。STD::endl;}}2。如果(状态== GLUT_DOWN) //等于& ldquo则发生一些鼠标响应事件。如果按下鼠标按钮。如果(状态== GLUT_UP) //等于& ldquo如果松开鼠标按钮。如果(button = = glue _ left _ button)//等于& ldquo如果按下或释放鼠标左键。如果(button = = glue _ right _ button)//等于& ldquo如果按下或释放鼠标右键。如果(button = = glue _ middle _ button)//等于& ldquo如果按下或释放鼠标中键。还有鼠标滚轮事件GLUT_WHEEL_UP GLUT_WHEEL_DOWN。这两个事件有时可能会遇到自己的gult库没有定义 ,那是因为版本比较旧 。如果您不想为新版本而烦恼,或者如果新版本仍未解决,您可以直接在文件的开头这样定义它:# define glue _ wheel _ up 3//define wheel operation # define glue _ wheel _ down 4 3。在实现过程中,我们将绘制我们读取的两个3d模型,并分别显示它们(光线在质量保证中还没有做好) )绘图代码:void myDisplay(){//清除先前的深度缓存GL clear(GL _ color _ buffer _ bit | GL _ depth _ buffer _ bit);glloadIdentity();//显示相关功能/* GLROTEF(x ROTEF,1.0f ,0.0f,0.0f);//旋转对象的函数的第一个参数是角度 ,下面的参数是旋转法向量GLROTEF(Y ROTEF ,0.0F,1.0F,0.0F);//glTranslatef(0.0f,0.0f,ty);gltrans ref(tx,ty,0);//移动glScalef(比例尺、比例尺、比例尺);//缩放x、y、z倍缩放*///每个显示器将使用glcalllist回调函数来显示要显示的顶点列表///glScalef(缩放、缩放、缩放、缩放);glScalef(0.001,0.001,0.001);//glTranslatef(400,0,0);//GlpushMatrix();//glTranslatef(-6,0,0);glpushMatrix();glColor3f(0,0,1);//glRotatef(50 ,1,0,0);glTranslatef(MoV 1,MoV 1,0);glRotatef(xRotate1,1.0f,0.0f,0.0f);glRotatef(yRotate1,0.0f,1.0f,0.0f);//使用键盘的插入键来控制显示的模式网格。面和网格面分别显示为(int I = 0;i < 。m_pic1。f . size();i++) { GLbegin(GL _ TALENGS);//绘制三角形if (m_pic1。VT.size()!= 0)GLtexCoorder2f(m _ pic1。[海事卫星1号 。[一世]。[0]]。TU,m_pic1。[海事卫星1号。[一世]。[0]]。电视);//纹理if (m_pic1。VN.size()!= 0)glNormal3f(m_pic1 。越南[图片1。[一世]。[北部0]]。NX,m_pic1。越南[图片1。[一世]。[北部0]]。纽约,m_pic1。越南[图片1。[一世]。[北部0]]。新西兰);//法向量glvertex 3f(m _ pic1 . v .[m _ pic1 . f .[一世)。v [0]]。x/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v [0]]。y/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v [0]]。z/Yu);//上顶点if (m_pic1。VT.size()!= 0)GLtexCoorder2f(m _ pic1。[海事卫星1号。[一世]。[1]]。TU,m_pic1。[海事卫星1号。[一世]。[1]]。电视);//纹理if (m_pic1。VN.size()!= 0)glNormal3f(m_pic1。越南[图片1。[一世] 。[1]]。NX,m_pic1 。越南[图片1。[一世]。[1]]。纽约,m_pic1。越南[图片1 。[一世]。[1]]。新西兰);//法向量glvertex 3f(m _ pic1 . v .[m _ pic1 . f .[一世)。v .[1]]。x/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v .[1]]。y/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v .[1]]。z/Yu);//左下if (m_pic1。VT.size()!= 0)GLtexCoorder2f(m _ pic1。[海事卫星1号。[一世]。[2]]。TU,m_pic1。[海事卫星1号。[一世]。[2]] 。电视);//纹理if (m_pic1。VN.size()!= 0)glNormal3f(m_pic1。越南[图片1 。[一世]。[2]]。NX,m_pic1。越南[图片1 。[一世]。[2]]。纽约,m_pic1。越南[图片1。[一世] 。[2]]。新西兰);//法向量glvertex 3f(m _ pic1 . v .[m _ pic1 . f .[一世) 。v .[2]]。x/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v .[2]]。y/Yu,m _ pic1 .诉[m _ pic1 . f[一号]。v .[2]]。z/Yu);//右下角格伦德();//三角形绘制结束} glpopMatrix();glpushMatrix();glColor3f(0,1,0);glTranslatef(MoV 2,MoV 2,0);glRotatef(xRotate2,1.0f,0.0f ,0.0f);glRotatef(旋转状态2,0.0f,1.0f,0.0f);对于(int I = 0;i <。m_pic2。f . size();i++) { GLbegin(GL _ TALENGS);//绘制三角形if (m_pic2。VT.size()!= 0)GLtexCoorder2f(m _ pic2。[海事卫星2号。[一世]。[0]]。TU,m_pic2。[海事卫星2号。[一世] 。[0]]。电视);//纹理if (m_pic2。VN.size()!= 0)glNormal3f(m_pic2。越南[图片2。[一世]。[北部0]]。NX,m_pic2。越南[图片2。[一世] 。[北部0]] 。纽约 ,m_pic2。越南[图片2。[一世]。[北部0]]。新西兰);//法向量glvertex 3f(m _ pic2 . v .[m _ pic2 . f .[一世)。v [0]]。x/yu,m _ pic2 .诉[m _ pic2 . f[一案]。v [0]]。y/yu,m _ pic2 .诉[m _ pic2 . f·[一案]。v [0]]。z/Yu);//上顶点if (m_pic2。VT.size()!= 0)GLtexCoorder2f(m _ pic2。[海事卫星2号。[一世]。[1]]。TU,m_pic2。[海事卫星2号 。[一世]。[1]]。电视);//纹理if (m_pic2。VN.size()!= 0)glNormal3f(m_pic2。越南[图片2。[一世] 。[1]]。NX,m_pic2 。越南[图片2。[一世] 。[1]]。纽约 ,m_pic2。越南[图片2。[一世]。[1]]。新西兰);//法向量glvertex 3f(m _ pic2 . v .[m _ pic2 . f .[一世)。v .[1]]。x/yu,m _ pic2 .诉[m _ pic2 . f[一案] 。v .[1]]。y/yu,m _ pic2 .诉[m _ pic2 . f·[一案]。v .[1]]。z/Yu);//左下if (m_pic2。VT.size()!= 0)GLtexCoorder2f(m _ pic2。[海事卫星2号。[一世]。[2]]。TU,m_pic2。[海事卫星2号。[一世] 。[2]]。电视);//纹理if (m_pic2。VN.size() != 0)glNormal3f(m_pic2。越南[图片2 。[一世]。[2]]。NX,m_pic2。越南[图片2。[一世]。[2]]。纽约,m_pic2。越南[图片2。[一世]。[2]] 。新西兰);//法向量glvertex 3f(m _ pic2 . v .[m _ pic2 . f .[一世) 。v .[2]]。x/yu,m _ pic2 .诉[m _ pic2 . f[一案] 。v .[2]] 。y/yu,m _ pic2 .诉[m _ pic2 . f·[一案]。v .[2]]。z/Yu);//右下角格伦德();//三角形绘制结束} glpopMatrix();glutswapBuffers();//这是Opengl中实现双缓存技术的一个重要功能}其次,我们需要点击并选择一个对象。当我们按住鼠标移动时 ,对象会随着鼠标移动。 按住鼠标单击选定的范围可以是一个矩形区域,对象的中心为固定点坐标,边长为d 。当鼠标在该区域单击时,我们将确定对象已被选中。 当两个对象重叠时,我们优先选择要移动的第一个对象。 然后问题出现了。选择一个对象后,我们如何用鼠标移动该对象?这很简单。在水平方向上 ,只要从运动前的坐标中减去运动后的坐标,然后除以实际运动的差值(自身误差测试),就可以获得运动的法向矢量。 mov x1 =(x-x1)/2 * 5;在垂直方向上,MoV 1 =-((y-Y1)/2 * 5)可以以相同的方式获得;为什么这里有多个减号,因为向下的运动是负的 ,向上的运动是正的 然后,在程序调用窗口中可以重新绘制一次运动后,运动的法向矢量发生了变化。 如果出现闪烁,可以使用双缓冲。 最后,按住右键移动鼠标,选定的对象将旋转。 这对我们来说相对简单。我们只需要把运动后的坐标和运动前的坐标之间的差作为一个法向量,然后把它传递给旋转画出的变量,然后调用重画来实现它。 鼠标部件控制代码://鼠标交互使我的鼠标无效(intbutton,intstate,intx,inty){//如果(button = = glut _ left _ button & & ampstate = = GLUT _ DOWN){ mouse tate = 1;如果(!选择){如果(x<。(x1 +选择宽度)和。& ampx>。(x1 -选择宽度)){如果(y & lt(Y1 +选择高度)和;& ampy>。(Y1 -选择高度)){ x1 = 400Y1 = 400mov x1 =(x-x1)* 2/5;mov 1 =-((y-Y1)* 2/5);选择= 1;STD::cout & lt;<。"选择图1x = " < & lt;x <。< 。" y = " <。<。y <。<。STD::endl;} }否则,如果(x<。(x2 +选择宽度)和。& ampx>。(x2 -选择宽度)){如果(y & lt(y2 +选择高度)和。& ampy>。(y2 -选择高度)){ x2 = 400y2 = 400mov x2 =(x-x2)* 2/5;mov 2 =-((y-y2)* 2/5);选择= 2;} } }标准::cout <。<。" x = " <。<。x <。<。" y = " <。< 。y <。< 。STD::endl;STD::cout & lt;< 。" x1 = " <。< 。x1 <。<。" y1 = " <。<。Y1 <。< 。STD::endl;STD::cout & lt;<。" x2 = " <。<。x2 <。<。" y2 = " <。<。y2 <。<。STD::endl;}如果(button = = GLUT _ LEFT _ BUTTON & amp& amp状态= = GLUT _ UP){如果(选择= = 1){ x1+=(MoV x1 * 2/5);Y1+=-(MovY1 * 2/5);}如果(选择= = 2){ x2+=(MoV x2 * 2/5);y2+=-(MoV 2 * 2/5);} mouse tate = 0;选择= 0;STD::cout & lt;<。" x = " < 。<。x1 <。<。" y = " <。<。Y1 < 。< 。STD::endl;}//如果(按钮= = glut _ right _ button & & ampstate = = GLUT _ DOWN){ mouse tate = 1;如果(!选择){如果(x<。(x1 +选择宽度)和。& ampx>。(x1 -选择宽度)){如果(y & lt(Y1 +选择高度)和;& ampy>。(Y1 -选择高度)){ Oldx1 = x;Oldy1 = y。选择= 3;STD::cout & lt;<。"右键单击选择图1x = " < & lt;x <。<。" y = " <。<。y <。<。STD::endl;} }否则,如果(x<。(x2 +选择宽度)和。& ampx>。(x2 -选择宽度)){如果(y & lt(y2 +选择高度)和。& ampy>。(y2 -选择高度)){ old x2 = x;Oldy2 = y。选择= 4;} } } }如果(button = = GLUT _ RIGHT _ BUTTON & amp& ampstate = = GLUT _ UP){ mouse tate = 0;选择= 0;}//滚轮事件//缩放增加或减少//当前文件使用scaleif(状态= = GLUT _ UP & amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;button = = GLUT _ WHEEL _ UP){//cout & lt;<。“你好”& lt<。endl//如果滑轮向上滑动,当(当前文件= = 1)刻度+= 0.0005时,刻度减小;if(current file = = 2)scale+= 0.001;如果(current file = = 5){ scale+= 0.1;} elsescale+= 0.001;}如果(状态= = GLUT _ UP & amp& ampbutton = = GLUT _ WHEEL _ DOWN){//cout & lt。<。“好”<。<。endl//如果滑轮向下滑动,当(当前文件= = 1)刻度-= 0.0005时,刻度增加;if (currentfile == 2)标度-= 0.001;如果(current file = = 5){ scale-= 0.1;} elsescale-= 0.001;}谷氨酸盐显示();//鼠标移动时提示主程序尽快重绘窗口}//void onmousemove 2 (intx,inty ){//鼠标状态被按下时,输入后续判断STD::cout & lt;<。"移动x = " < & ltx <。<。" y = " <。<。y <。<。STD::endl;}//在MouseMove上无效(int x,int y) {//如果(mouse state){如果(选择!= 0) {//x对应于y,因为如果(选择== 1) {movX1 = (x-x1)/2 * 5,它对应于法向向量;glutPurstedisplay();mov 1 =-((y-Y1)/2 * 5);glutPurstedisplay();STD::cout & lt;<。"移动x1 = " < & ltx <。<。" y1 = " <。<。y <。< 。STD::endl;}如果(选择= = 2){ MoV x2 =(x-x2)/2 * 5;glutPurstedisplay();mov 2 =-((y-y2)/2 * 5);glutPurstedisplay();STD::cout & lt;<。"移动x2 = " < & ltx <。<。" y2 = " <。<。y <。<。STD::endl;}如果(选择== 3) {//x对应于y,因为它对应于法向量YRotate 1+= x-Oldx1;glutPurstedisplay();//标记当前窗口需要重绘Oldx1 = x;xrotate 1+= y-old 1;glutPurstedisplay();Oldy1 = y。STD::cout & lt;<。“xRotate = " & lt<。xRotate1 <。< 。“yRotate = " & lt<。状态1 <。<。STD::endl;}如果(选择== 4) {//x对应于y,因为它对应于法向向量YRotate 2+= x-Oldx2;glutPurstedisplay();//标记当前窗口需要重绘Oldx2 = x;xrotate 2+= y-old 2;glutPurstedisplay();Oldy2 = y。STD::cout & lt;<。“xRotate = " & lt<。xRotate1 < 。< 。“yRotate = " & lt<。状态1 <。<。STD::endl;} }其他标准::cout <。<。“不选择”& lt<。STD::endl;}}这些基本上都是这个博客的内容。让我们最后看看结果。 移动和旋转前:移动和旋转后:如果你对共享技术感兴趣,可以关注你的公开号码,它会偶尔共享各种编程教程和源代码 ,比如研究和共享关于基本编程、图像处理和机器视觉开发的知识,比如c/c++、python、前端、后端、opencv、halcon、opengl和机器学习深度学习。 Linux安装Kafka

分享到:

温馨提示:以上内容和图片整理于网络,仅供参考,希望对您有帮助!如有侵权行为请联系删除!

友情链接: