65.9K
CodeProject 正在变化。 阅读更多。
Home

球体的三角形列表生成器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.61/5 (15投票s)

2013年12月20日

CPOL

2分钟阅读

viewsIcon

29027

downloadIcon

476

本文介绍了一种生成构成单位球体表面的规则三角形列表的简单快速的方法。

..

下载 Visual Studio 2012 的源代码

 

介绍  

WPF 缺少内置的 3D 形状,例如球体、圆柱体和立方体。因此,那些打算在他们的 3D 场景中添加此类形状的人别无选择,只能通过额外的编码来生成它们的网格。由于我已经在 CodeProject 上搜索过简单的解决方案,用于在 WPF 中生成一个球体,但我没有找到一个清晰的代码,可以依赖它来完成一个严肃的项目。其中一些太长,另一些则有局限性和歧义。 我在这里提交的代码为半径为 1 的球体生成一个三角列表及其法线向量,然后可以通过简单的计算进行移动和调整大小。它用 VB.Net 编写,可以很容易地转换为其他基于 .Net 的语言。

使用代码 

三角形结构

为了更好地操作 Trianlges 和它们的 Normals,开发了以下结构。

    Public Structure Triangle
       Dim Point1 As Point3D
       Dim Point2 As Point3D
       Dim Point3 As Point3D
       Dim Normal As Vector3D
    End Structure

算法

空间中的点应该这样定位,使它们与球体中心的距离相等,并且这些点的枚举器必须能够记录相邻的点。这可以通过将笛卡尔坐标转换为球坐标来实现。

  

以下显示了参数 r、θ 和 ɸ 如何替换笛卡尔坐标 X、Y 和 Z。

由于 r 应该为 1,因此可以省略它。下图显示了枚举器如何通过球体表面上的点。显示了ɸ枚举器可用于查找特定 Z 表面上的相邻点,而 θ 枚举器遍历所有 Z 表面以生成球体表面点。

仔细观察球体表面,可以揭示如何使用该算法生成三角形。如所示,每次 θ 迭代代表一个点,该点可能在 8 个三角形中通用。为了防止生成额外的三角形,该算法在 ɸ 迭代前向和 θ 等级后向定位两个三角形,如下所示。

现在是时候写代码了。

生成球体点 

CreateTriangleListForSphere 函数返回一个包含 TrianglesArrayList。在这个函数中,首先,以下代码在球体表面上生成点,并将它们添加到 PointList()() 数组中。Density 参数决定了球体的 ɸ 数量。

    
For tita As Integer = 0 To Density
            Dim vtita As Double = tita * (Math.PI / Density)
            For nphi As Integer = -Density To Density
                Dim vphi As Double = nphi * (Math.PI / Density)
                PointList(tita)(nphi + Density).X = Math.Sin(vtita) * Math.Cos(vphi)
                PointList(tita)(nphi + Density).Y = Math.Sin(vtita) * Math.Sin(vphi)
                PointList(tita)(nphi + Density).Z = Math.Cos(vtita)
            Next
Next

生成三角形 

然后,下面的迭代根据描述的算法连接点列表。Triangle1Triangle2 分别是已经解释和说明的三角形。由于球体位于原点,因此可以轻松地将 Normal 向量建议为球体表面上的点的位置。

 Dim TriangleList As New ArrayList

        For n_tita As Integer = 1 To PointList.GetLength(0) - 1
            For n_phi As Integer = 0 To PointList(n_tita).GetLength(0) - 2

                Dim Triangle1, Triangle2 As Triangle

                Triangle1.Point1 = PointList(n_tita)(n_phi)
                Triangle1.Point2 = PointList(n_tita)(n_phi + 1)
                Triangle1.Point3 = PointList(n_tita - 1)(n_phi)
                Triangle1.Normal = New Vector3D(Triangle1.Point1.X, Triangle1.Point1.Y, Triangle1.Point1.Z)


                Triangle2.Point1 = PointList(n_tita)(n_phi + 1)
                Triangle2.Point2 = PointList(n_tita - 1)(n_phi + 1)
                Triangle2.Point3 = PointList(n_tita - 1)(n_phi)
                Triangle2.Normal = New Vector3D(Triangle1.Point1.X, Triangle1.Point1.Y, Triangle1.Point1.Z)


                TriangleList.Add(Triangle1)
                TriangleList.Add(Triangle2)


            Next
        Next

性能 

1) 为了提高应用程序的性能,可以将三角形列表保存在硬盘上,然后
加载到内存中,而不是每次需要球体时都调用 CreateTrianlgeListForSphere 函数。

2) 对于更大的项目,最好使用三角形带而不是 TrianglesArrayList。这将大大减少内存、CPU 和 GPU 的使用。

3) 上面的两个循环可以很容易地合并以获得最佳性能。

应用

添加自定义球体需要调用 CreateTriangleListForSphere 然后调整大小并移动 Triangle 点:Point1Point2Point3Normal 向量保持不变。

© . All rights reserved.