有人可以解释一下如何创建球体的顶点,索引和纹理坐标吗?令人惊讶的是缺少有关如何执行此操作的文档,这是我感兴趣的东西。
我尝试了显而易见的搜索,在gamedev.net上进行了搜索,等等。但是,没有什么可以涵盖世代的球形点,对其进行索引和构造。
有人可以解释一下如何创建球体的顶点,索引和纹理坐标吗?令人惊讶的是缺少有关如何执行此操作的文档,这是我感兴趣的东西。
我尝试了显而易见的搜索,在gamedev.net上进行了搜索,等等。但是,没有什么可以涵盖世代的球形点,对其进行索引和构造。
Answers:
有两种通用方法:
最左边的称为uv-sphere,最右边的称为icosphere。
GLUT倾向于使用紫外线的方法:看功能glutSolidSphere()
在freeglut源代码。
这是一篇有关制作icosphere的优秀文章:http ://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html
uv球看起来像一个地球仪。对于许多目的来说,它是非常好的,但是对于某些用例,例如,如果您要使球体变形,则不利的是,极点周围的顶点密度更大。这里的圈圈比较好,其顶点分布均匀。
您可能还会发现这很有趣:http : //kiwi.atmos.colostate.edu/BUGS/geodesic/text.html,它描述了一种将面部组织成区域的方法。
http://vterrain.org/Textures/spherical.html很好地描述了您如何选择对它们进行纹理处理。
有两种方法可以做到这一点:
在球坐标系中行走theta和phi,生成面和Tris
创建二十面体并递归细分面,直到达到所需的细分为止。
对于第一种方法,您只需要使用double嵌套即可走theta和phi。行走theta和phi时,旋转三角形以创建球体。
执行该操作的代码如下所示:
for( int t = 0 ; t < stacks ; t++ ) // stacks are ELEVATION so they count theta
{
real theta1 = ( (real)(t)/stacks )*PI ;
real theta2 = ( (real)(t+1)/stacks )*PI ;
for( int p = 0 ; p < slices ; p++ ) // slices are ORANGE SLICES so the count azimuth
{
real phi1 = ( (real)(p)/slices )*2*PI ; // azimuth goes around 0 .. 2*PI
real phi2 = ( (real)(p+1)/slices )*2*PI ;
//phi2 phi1
// | |
// 2------1 -- theta1
// |\ _ |
// | \ |
// 3------4 -- theta2
//
//vertex1 = vertex on a sphere of radius r at spherical coords theta1, phi1
//vertex2 = vertex on a sphere of radius r at spherical coords theta1, phi2
//vertex3 = vertex on a sphere of radius r at spherical coords theta2, phi2
//vertex4 = vertex on a sphere of radius r at spherical coords theta2, phi1
// facing out
if( t == 0 ) // top cap
mesh->addTri( vertex1, vertex3, vertex4 ) ; //t1p1, t2p2, t2p1
else if( t + 1 == stacks ) //end cap
mesh->addTri( vertex3, vertex1, vertex2 ) ; //t2p2, t1p1, t1p2
else
{
// body, facing OUT:
mesh->addTri( vertex1, vertex2, vertex4 ) ;
mesh->addTri( vertex2, vertex3, vertex4 ) ;
}
}
}
因此,请注意上面的内容,仅使用Tris而不是Quads来缠绕顶盖和底盖很重要。
要使用二十面体,只需生成二十面体的点,然后从中缠绕三角形。位于原点的二十面体的顶点为:
(0, ±1, ±φ)
(±1, ±φ, 0)
(±φ, 0, ±1)
where φ = (1 + √5) / 2
如果点不必是局部一致的,而应该是全球统一的,而不必遵循任何一套模式,您可以用飞镖投掷算法的一个变体来分发ň半径在球体点[R ,平均dist分。这些值大致为:
在最简单的情况下,然后可以通过从(0,1)中选取两个均匀分布的变量u和v并根据公式θ = 2× π × u和ϕ = arc 来计算极坐标,来随机地均匀拾取点cos(2× v -1); 然后消除太接近已经选取的点的任何点。有关稍微复杂且性能明显更好的算法,请参见Cline,Jeschke,White,Razdan和Wonka撰写的“ Dart Throwing on Surfaces ”。
选择了前四个点后(假设它们中的三个都没有退化,也就是说-它们不在同一个大圆上,但这不太可能),则可以在它们之间创建四个面,并且每次添加一个新点,您可以将其所属的面分为三个子面。
出于纹理化的目的,您可以将这些点映射到立方体贴图。