D3DX库已经为我们提供了一些方法来产生简单3D物体的网格数据。比喻l D3DXCreateSphere来生成一个球形网络数据.
若D3DX库没有给我们提供这些库.我们将会通过代码建造每个三角形来建造3D球形物体.构造球形物体需要顶点,索引,及纹理坐标的计算.
1.2 球形天空顶天空是室外场景的一个重要组成部分,常用的天空绘制类型有矩形天空和球面天空.其中,矩形天空就是将一个矩形体去掉其地面,剩下其余的五个面构成一个天空盒,然后贴上云彩就可以模拟出一个天空景象.球面天空是将一个球体去掉下面半球.盖在地面上,然后贴上云彩就可以模拟出一个天空景象.
那么半球和整个球的计算为有什么不同呢?
2.分析 2.1 经纬度
(1):地球坐标系统的定位.
经线和纬线:是人们为了在地球上确定位置和方向的,在地球仪和地图上画出来的,地面上并没有画有经纬线。连接南北两极的线,叫做经线。和经线相垂直的线,叫做纬线。纬线是一条条长度不等的圆圈。最长的纬线,就是赤道(纬度为零度)。 因为经线指示南北方向,所以,经线又叫子午线(经度为零度)。
经纬度是经度与纬度的合称组成一个坐标系统。又称为地理坐标系统,它是一种利用三度空间的球面来定义地球上的空间的球面坐标系统,能够标示地球上的任何一个位置。
如:北京在 北纬:39°54′27〃;东径:116°23′17.
经度: 是地球上一个地点离一根被称为本初子午线的南北方向走线以东或以西的度数。本初子午线的经度是0°,地球上其它地点的经度是向东到180°或向西到180°。不像纬度有赤道作为自然的起点,经度没有自然的起点而使用经过伦敦格林尼治天文台旧址的子午线作为起点。东经180°即西经180°,约等同于国际日期变更线,国际日期变更线的两边,日期相差一日。
纬度: 是指某点与地球球心的连线和地球赤道面所成的线面角,其数值在0至90度之间。位于赤道以北的点的纬度叫北纬,记为N,位于赤道以南的点的纬度称南纬,记为S
------
α:经度
β: 纬度
由图可以知道球面上的点也是经纬线的交点.若得到经纬线的条数则交点数也可以由计算得到
经线的条数 = 360(度) / 自定义单位经度
纬线的条数 = 180(度) / 自定义单位纬度
每条经线上顶点数 = 纬线的条数 + 1
每条纬线上顶点数 = 经线的条数 + 1
交点数 = (经线的条数 + 1) * (纬线的条数 + 1)
(90 (度) / 自定义单位纬度 = 半球的纬线条数)
(+1 是因为度数为0的经纬度线)
2.2 顶点计算知道了每条经纬线上的顶点数,只需要依次遍历每条经线上的顶点数,和每条纬线上的顶点数.就能填充所有的顶点数据.这里的遍历是一个嵌套循环.
mnVertsPerLongi = 每条纬线上顶点数
mnVertsPerLati = 每条经线上顶点数
for (int row = 0; row < mnVertsPerLongi; row++)
{
for (int col = 0; col < mnVertsPerLati; col++)
{
}
}
接下来的问题球面上的顶点坐标怎么计算顶点的x轴,y轴,z轴值
前面我们是通过地理坐标系统来定位球面上的点.而经度纬度的表示主要是XZ平面与Y平面之间的关系.
-
根据β 可以求P.Y轴的值.
(1)计算PY的值
球体以赤道分南半球和北半球,赤道为0度,β度数分别是90度 - 0度 - 负90度.因为我们的遍历循序是呈线型关系,正数的从低到高.为了计算方便,我们也可以自定义我们的0度,定义北级点为0度,南级点为180度, β 度数则是0度 - 180度.则
PY = Radius * cos β
(2)计算PX,PZ的值.
在计算X轴,Z轴上的值时,首先需要将P点映射到XZ平面.然后再根据 ɑ 角计算对应的X,Z值.
经度是以子午线为0度,相当于这里的Z轴为0度.若经度α度,则是靠Z轴的ɑ度.
左右各180度.同样也可以自定义O度.若自定义X轴为O度.则顺时针方向360度.
这样的自定义只是对于计算的方便.不影响物体的构造.
P 点在XZ平面的映射 Radius * sin β
P点在X轴上的值 Radius * sin β * cos ɑ
P点在Z轴上的值Radius * sin β * sin ɑ
2.3 索引计算当计算好球面上的顶点坐标之后,顶点缓存中以每一条经度上的顶点为单位进行存储,即首先存储的是维度角为0的所有的顶点.然后再是第二条经度上的项点.
--
假设A点位于顶点缓存中的第ROW行,第COL列,并且假设每条经度上共包含M个顶点.那么B, C, D 点在顶点缓存中的索引分别为
I A = row * m + col
IB =( row +1) *m + col
IB =( row +1) *m + col + 1
ID = row * m + col +1
说明:在北极点也就是自定义纬度为0的顶点,顶点个数实则有M个.而M个顶点坐标都相同,同在北极点这个坐标.南级点也是同理.这样的做法虽然浪费了2M个顶点数据储存量.但是算法上统一公式.也不用分南北极点来分开计算.
pIndices[nIndex + 0] = row * mnVertsPerLati + col;
pIndices[nIndex + 1] =(row +1) * mnVertsPerLati + col;
pIndices[nIndex + 2] =(row + 1) * mnVertsPerLati + col +1 ;
pIndices[nIndex + 3] = row * mnVertsPerLati + col;
pIndices[nIndex + 4] = (row + 1) * mnVertsPerLati + col +1 ;
pIndices[nIndex + 5] = row * mnVertsPerLati + col +1 ;
nIndex += 6;
2.4 纹理计算经纬度能表示球面的坐标位置,UV贴图是将物体展开,约束1单位下,在U轴的值,V轴的值.
若求得经度的比例值,和纬度的比例值,则为UV值.
XZ平面用经度表示
Y平面用纬度表示.
两个平面前视图可以粗看为UV平面.同理也可以用αβ来定位.
P点的经度值 / 360(经度总值)
P点的纬度值 /180(纬度总值)
v[nIndex].mTX = col * fAlpha/ (2.0f *D3DX_PI);
v[nIndex].mTY = row * fBeta / (D3DX_PI);
3.球体计算 3.1顶点PY = Radius * cos β
P 点在XZ平面的映射 Radius * sin β
P点在X轴上的值 Radius * sin β * cos ɑ
P点在Z轴上的值Radius * sin β * sin ɑ
3.2索引I A = row * m + col
IB =( row +1) *m + col
IB =( row +1) *m + col + 1
ID = row * m + col +1
3.3纹理P点的经度值 / 360(经度总值)
P点的纬度值 /180(纬度总值)
v[nIndex].mTX = col * fAlpha/ (2.0f *D3DX_PI);
v[nIndex].mTY = row * fBeta / (D3DX_PI);
4.半球计算半球的β度数分别是90度 - 0度 ,定义赤道为0度点.
4.1顶点PY = Radius * sin β
P 点在XZ平面的映射 Radius * cos β
P点在X轴上的值 Radius * cosβ * cos ɑ
P点在Z轴上的值Radius * cos β * sin ɑ
4.2索引I A = row * m + col
IB =( row +1) *m + col
IB =( row +1) *m + col + 1
ID = row * m + col +1
4.3纹理P点的经度值 / 360(经度总值)
P点的纬度值 /180(纬度总值)
v[nIndex].mTX = col * fAlpha/ (2.0f *D3DX_PI);
v[nIndex].mTY = row * fBeta / (D3DX_PI);
---