对于二十面体的每一面,您可以将三角形映射到网格,每个网格正方形分为两部分,例如(索引的十六进制编号以方便格式化):
A
+
|\
|0\
+--+
|\2|\
|1\|3\
+--+--+
|\5|\7|\
|4\|6\|8\
+--+--+--+
|\A|\C|\E|\
|9\|B\|D\|F\
+--+--+--+--+
B C
Run Code Online (Sandbox Code Playgroud)
对于被细分 n 次的边,该边有 4 n个三角形,因此您可以为二十面体的每条边创建一个该大小的数组,以存储用于模拟的每个三角形的数据。
对三角形的引用可以存储为(边,行,列)
行索引和列索引都是从 0 开始的。列索引基于行中三角形的数量(即每个网格正方形 2 个)。
如果你有边、行和列,你可以计算边的数组索引,如下所示:
index = (row * row) + column
Run Code Online (Sandbox Code Playgroud)
因此,您可以将数据存储在二维数组中并像这样访问它:
value = data[side][(row * row) + column]
Run Code Online (Sandbox Code Playgroud)
具有偶数列的三角形的相邻三角形:
(side, row, column - 1)
(side, row, column + 1)
(side, row + 1, column + 1)
Run Code Online (Sandbox Code Playgroud)
具有奇数列的三角形的相邻三角形:
(side, row, column - 1)
(side, row, column + 1)
(side, row - 1, column - 1)
Run Code Online (Sandbox Code Playgroud)
这使您可以轻松地引用细分三角形网格中的三角形,而无需显式存储邻接信息。
问题在于如何将其组织成二十面体。计算对相邻三角形的引用后,您需要验证新的引用是否在边的边界内:
int rows = 1 << subdivision_count;
if(row >= rows)
{
// compute (side, row, column) in adjacent side of icosahedron to B-C edge
}
else if(column < 0)
{
// compute (side, row, column) in adjacent side of icosahedron to A-B edge
}
else if(column >= ((row * 2) + 1))
{
// compute (side, row, column) in adjacent side of icosahedron to A-C edge
}
Run Code Online (Sandbox Code Playgroud)
您必须存储每条边的邻接信息以及边的类型(AB、BC、AC)。
您必须找出 9 种不同的可能映射,每种映射对应一种边缘类型组合。例如,如果相邻三角形与AC边相交,并且该边与相邻边的AB边相匹配,则
side = adjacent side (from table)
row = row
column = column - ((row * 2) + 1)
Run Code Online (Sandbox Code Playgroud)
ETC
在某些方面,这是一种更复杂的方法,但在其他方面则更简单。这一切的优点是: