热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenGL自己编码画球体——网格入门小例子

这是根据视频整理的项目,视频中的讲解有一点小问题,所有作了如下整理,视频链接是:球体一、编程环境Win10VS2013Op

这是根据视频整理的项目,视频中的讲解有一点小问题,所有作了如下整理,视频链接是:球体


一、编程环境

     Win 10 + VS 2013 +OpenGL

     采用C语言进行编写


二、结构体定义以及全局变量

enum Ref_Plain { XOY, YOZ, XOZ };struct Vertex{float x, y, z;
};struct HalfQuarterSphere{Vertex topVertex;// 1/8圆的穹顶点Vertex **pVertexs;//其余顶点int numCircles;//纬线数量int numLine;//经线数量,连接南北两极float radius;//半径
};HalfQuarterSphere hqSphere;

三、相关函数

void generateHalfQuarterSphere(int numCir/*纬线数*/, int numLin/*经线数*/, HalfQuarterSphere &hqSphere, float R){//生成1/8球体所有的顶点hqSphere.numCircles = numCir;hqSphere.numLine = numLin;hqSphere.radius = R;hqSphere.topVertex.z = R;hqSphere.topVertex.x = hqSphere.topVertex.y = 0;//申请内存块hqSphere.pVertexs = new Vertex*[numCir];for (int i = 0; i = 0; i--){zOffset = R*sin(angleOffset);//初始化当前纬线与始经线,末经线的交点curR = hqSphere.pVertexs[i][0].x = hqSphere.pVertexs[i][boundLine].y = sqrt(R*R - zOffset*zOffset);hqSphere.pVertexs[i][0].y = hqSphere.pVertexs[i][boundLine].x = 0;hqSphere.pVertexs[i][0].z = hqSphere.pVertexs[i][boundLine].z = zOffset;cirAngleOffset = cirAngleSegment;//初始化当前纬线与其余经线的交点for(int j = 1; j }

        

        cirAngleSegment = HALF_PI / (numLin - 1);// 1/8球体中任意一条纬线的两端点与球心构成的角度是90度(如∠YOX),                                      //numLin是经线条数,由于纬线与每一条经线都有交点,因此这个计算结果就是两相邻交点与球心构成的角                                 //度(如∠BOX),这个地方一定要减1。如OY,OB,OX是三条经线,与纬线XBY只有两个夹角

        linAngleSegment = HALF_PI / (numCir - 1);//与上面同理,是经线上两相邻交点与球心之间的夹角,穹点(NS极)也算一                                  //条纬线,上图有三条纬线,Z,AC所在平面的纬线,XBY。 

        左图中,λ是纬线之间的夹角,即cirAngleSegment,φ是经线之间的夹角,即linAngleSegment。右图中可以看到经线有10条,纬线有6条。左图中的1/8半球有三条经线,三条纬线,所以在代码中的numCir,numLin均为3,由于数组下标从0开始,因此存储所有顶点的二位数组hqSphere.pVertexs的下标从一开始,第一维坐标为纬线,第二维为经线,最后一个点的下标为[2,2]。

         代码解释:

        Step1:

         for (int i = numCir - 1; i >= 0; i--){} //该重for循环是为了依次求出纬线i上与经线的交点坐标。i的初值为 numCir - 1,因此是                           //从后往前求解,即XBY(hqSphere.pVertexs[2][...])                                                                                                                           //AC所在平面的纬线(hqSphere.pVertexs[1][...]),      Z(hqSphere.pVertexs[0][...])。

        Step2:

         zOffset = R*sin(angleOffset);

         angleOffset += linAngleSegment;

         angleOffset初值为0,后来的增量为linAngleSegment,即角度φ,从左图中可以看出R*sinφ是平行于Z轴的分量,即Z坐标,如OC*sinφ=BC(OC为半径,长度为R),故点C的Z坐标为OC*sinφ。即球面上任意一点的Z坐标均为zOffset。

  Step3:

        curR = hqSphere.pVertexs[i][0].x = hqSphere.pVertexs[i][boundLine].y = sqrt(R*R - zOffset*zOffset);
        hqSphere.pVertexs[i][0].y = hqSphere.pVertexs[i][boundLine].x = 0;
        hqSphere.pVertexs[i][0].z = hqSphere.pVertexs[i][boundLine].z = zOffset;

        hqSphere.pVertexs[i][0] 即纬线i与经线ZX的交点(因此y坐标为0),hqSphere.pVertexs[i][boundLine]  即纬线i与经线ZY的交点(因此x坐标为0),根据Step1可知,球面上任意一点的Z坐标均为zOffset。sqrt(R*R - zOffset*zOffset)为XOY平面上的投影长度,如sqrt(OC*OC-CB*CB)=OB,我们把点C移动到纬线i与经线ZX的交点上,就会发现sqrt(OC*OC-CB*CB)是hqSphere.pVertexs[i][0] 的X坐标(点B落在X轴上),而将点C移动到纬线i与经线ZY的交点上,就会发现sqrt(OC*OC-CB*CB)是hqSphere.pVertexs[i][boundLine] 的Y坐标(点B落在Y轴上)。

       Step4:

       cirAngleOffset = cirAngleSegment;
        //初始化当前纬线与其余经线的交点
        for(int j = 1; j             hqSphere.pVertexs[i][j].x = curR*cos(cirAngleOffset);
            hqSphere.pVertexs[i][j].y = curR*sin(cirAngleOffset);
            hqSphere.pVertexs[i][j].z = zOffset;
            cirAngleOffset += cirAngleSegment;
        }

        cirAngleOffset初值为λ,增量也为λ。因为纬线与经线ZX、ZY的交点都已经求出来了,所有for循环的初始化为j=1,循环条件为j

       在视频中Step2与Step4的变量设置有问题,经纬线的偏移角度设置的是错误的,此处一定要注意。

                                                     

void flipHalfQuarterSphere(HalfQuarterSphere &hqSphere, Ref_Plain rp){switch (rp){case XOY://Z坐标取反hqSphere.topVertex.z = -hqSphere.topVertex.z;for (int i = 0; i }void renderHalfQuarterSphere(const HalfQuarterSphere &hqSphere){//绘制1/8球glBegin(GL_TRIANGLE_FAN);//以穹点为中心画三角形扇glNormal3f(hqSphere.topVertex.x, hqSphere.topVertex.y, hqSphere.topVertex.z);glVertex3f(hqSphere.topVertex.x, hqSphere.topVertex.y, hqSphere.topVertex.z);for (int i = 0; i }void renderSphere(HalfQuarterSphere &hqSphere){renderHalfQuarterSphere(hqSphere);//X轴正向Y轴正向Z轴正向的1/8flipHalfQuarterSphere(hqSphere, YOZ);renderHalfQuarterSphere(hqSphere);//X轴负向Y轴正向Z轴正向的1/8flipHalfQuarterSphere(hqSphere, XOZ);renderHalfQuarterSphere(hqSphere);//X轴负向Y轴负向Z轴正向的1/8flipHalfQuarterSphere(hqSphere, YOZ);renderHalfQuarterSphere(hqSphere);//X轴正向Y轴负向Z轴正向的1/8flipHalfQuarterSphere(hqSphere, XOY);renderHalfQuarterSphere(hqSphere);//X轴正向Y轴负向Z轴负向的1/8flipHalfQuarterSphere(hqSphere, XOZ);renderHalfQuarterSphere(hqSphere);//X轴正向Y轴正向Z轴负向的1/8flipHalfQuarterSphere(hqSphere, YOZ);renderHalfQuarterSphere(hqSphere);//X轴负向Y轴正向Z轴负向的1/8flipHalfQuarterSphere(hqSphere, XOZ);renderHalfQuarterSphere(hqSphere);//X轴负向Y轴负向Z轴负向的1/8
}

四、相关配置及源码

相关库文件配置请参考链接:配置OpenGL

源码:https://download.csdn.net/download/qq_33742119/11014712

本文为作者原创,转载请注明出处:https://blog.csdn.net/qq_33742119/article/details/88422059。


推荐阅读
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • C语言的经典程序有哪些
    本篇内容介绍了“C语言的经典程序有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • Java编程实现邻接矩阵表示稠密图的方法及实现类介绍
    本文介绍了Java编程如何实现邻接矩阵表示稠密图的方法,通过一个名为AMWGraph.java的类来构造邻接矩阵表示的图,并提供了插入结点、插入边、获取邻接结点等功能。通过使用二维数组来表示结点之间的关系,并通过元素的值来表示权值的大小,实现了稠密图的表示和操作。对于对稠密图的表示和操作感兴趣的读者可以参考本文。 ... [详细]
  • 《2017年3月全国计算机等级考试二级C语言上机题库完全版》由会员分享,可在线阅读,更多相关《2017年3月全国计算机等级考试二级C语言上机题库完全版( ... [详细]
  • c语言基础编写,c语言 基础
    本文目录一览:1、C语言如何编写?2、如何编写 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 这篇文章主要介绍了Python拼接字符串的七种方式,包括使用%、format()、join()、f-string等方法。每种方法都有其特点和限制,通过本文的介绍可以帮助读者更好地理解和运用字符串拼接的技巧。 ... [详细]
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
author-avatar
訫梦沁_245
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有