作者:訫梦沁_245 | 来源:互联网 | 2023-06-04 18:18
这是根据视频整理的项目,视频中的讲解有一点小问题,所有作了如下整理,视频链接是:球体
一、编程环境
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。