把一个原始的四面体变成一个原始的二十面体?

我创建了一个四面体,创建一个BoundingBox并在边界框内构建四面体的面(如下图):

VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[12]; BoundingBox box = new BoundingBox(new Vector3(-1f, 1f, 1f), new Vector3(1f, -1f, -1f)); vertices[0].Position = box.GetCorners()[0]; vertices[1].Position = box.GetCorners()[2]; vertices[2].Position = box.GetCorners()[7]; vertices[3].Position = box.GetCorners()[0]; vertices[4].Position = box.GetCorners()[5]; vertices[5].Position = box.GetCorners()[2]; vertices[6].Position = box.GetCorners()[5]; vertices[7].Position = box.GetCorners()[7]; vertices[8].Position = box.GetCorners()[2]; vertices[9].Position = box.GetCorners()[5]; vertices[10].Position = box.GetCorners()[0]; vertices[11].Position = box.GetCorners()[7]; 

在这里输入图像描述

那么我将要做些什么才能将这个四面体转换成二十面体呢? 与此图像类似:

在这里输入图像描述

我理解这个概念,但是应用这个概念对我来说完全是另一回事。

为了澄清,我不想animation,我只是想从四面体的顶点创建一个二十面体。

编辑:所以我现在有另一种方法来创建使用金色矩形的二十面体。 这对于我的特定项目来说很好。 但是,我想留下一个问题,解决原始问题,即将笛卡尔坐标系中的四面体math转换为二十面体(反之亦然)。

首先,创建三组4点,每个点在X,Y或Z方向上是一个三维黄金矩形:

 Vector3[] points = new Vector3[12]; float phi = 0.5 + 0.5 * sqrt(5.0); for (int i = 0; i < 4; i++) { float x = ((i & 1) != 0) ? 0.5 : -0.5; float y = ((i & 2) != 0) ? phi * 0.5 : phi * -0.5; points[3 * i] = Vector3(x, y, 0.0); points[3 * i + 1] = Vector3(0.0, x, y); points[3 * i + 2] = Vector3(y, 0.0, x); } 

然后创建三角形来构建二十面体:

 static int[] trilist = { 0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8, 7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11, 0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1, 2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6, 7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8 }; VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[60]; for (int i = 0; i < 60; i += 3) { vertices[i].Position = points[trilist[i]]; vertices[i + 1].Position = points[trilist[i + 1]]; vertices[i + 2].Position = points[trilist[i + 2]]; } 

面积公式

从维基百科二十面体的文章中,我们知道,边长为a ,外接球体的半径为a * sin(2 * pi / 5) 。 由于我们构建了金色的矩形,因此半径为0.5 * sqrt(1 + phi²) ,可扩展到sqrt((5 + sqrt(5)) / 8) ,这正好是sin(2 * pi / 5) ! 这意味着我们的边长是1

再次从维基百科的文章中,我们知道表面积因此是5 * sqrt(3)

所以如果你想要一个表面积A ,你需要把所有的点坐标乘以sqrt(A / (5 * sqrt(3))

从四面体转换

为了平滑地将四面体变换成二十面体,每个顶点需要重复3次。 相反,为了将二十面体转化为四面体,需要将3个顶点组合成一个顶点:

  • 组1:顶点0,1,2
  • 组2:顶点3,7,11
  • 组3:顶点6,10,5
  • 组4:顶点9,4,8

这是一些应该工作的代码。 只需使用t作为0.01.0之间的参数:

 static int[] mergelist[] = { 0, 1, 2, 3, 7, 11, 6, 10, 5, 9, 4, 8, }; float t = 0.5; /* 0.0 for tetrahedron, 1.0 for icosahedron */ float t1 = (1.0 + 2.0 * t) / 3.0; float t2 = (1.0 - t) / 3.0; Vector3[] newpoints = new Vector3[12]; for (int i = 0; i < 12; i += 3) { int j = mergelist[i], k = mergelist[i + 1], l = mergelist[i + 2]; newpoints[j] = t1 * points[j] + t2 * (points[k] + points[l]); newpoints[k] = t1 * points[k] + t2 * (points[l] + points[j]); newpoints[l] = t1 * points[l] + t2 * (points[j] + points[k]); } 

然后使用上面的代码,使用newpoints points而不是points来构建vertices 。 结果可以在这个YouTubevideo中看到。

而不是试图把你的四面体变成二十面体,倒退。

构建你的二十面体,然后select二十面体的四个“相反”面(如animation图像中的蓝色或红色面)。

您挑选的四个面将是animation中的红色面,每个面都会凝聚成四面体的一个角点(绿色线显示哪个顶点移动到四面体上的哪个点):

(为了更好的可视性,四面体变小)

(实际尺寸)

对于实际的animation部分,一个简单的方法是从二十面体中的这些面的顶点位置到该面的中心点进行线性插值,这将成为四面体的拐角。

然后简单地animation,从四面体转变为二十面体。

首先,你可能不想通过“转换”一个四面体来获得你的坐标; 相反,只需从二十面体坐标开始。 幸运的是,二十面体的顶点坐标实际上相当简单, (±1,±φ,0),(0,±1,±φ)和(±φ,0,±1)的三个“黄金长方形”是黄金比例(sqrt(5)+1)/ 2。 find使用这些顶点的20个三角形实际上可能是最好的“手工” – 把三个这样的矩形放在一起,看看它们是如何连接的,你会很快得到这个想法。

在附注中,我建议使用顶点缓冲区 – 而不是每个三角形的每个点都有明确的顶点,而只是列出12个顶点,然后索引到三角形的缓冲区中。 在你的四面体的例子中,这更像是:

 Vector Vertices[4] = {{-1, -1, -1}, {-1, 1, 1}, {1, -1, 1}, {1, 1, -1}}; Triangle[0].Vert[0] = 0; // (-1, -1, -1) Triangle[0].Vert[1] = 1; // (-1, 1, 1) Triangle[0].Vert[2] = 2; // (1, -1, 1) Triangle[1].Vert[0] = 0; // (-1, -1, -1) Triangle[1].Vert[1] = 2; // (1, -1, 1) Triangle[1].Vert[2] = 3; // (1, 1, -1) // [ ... ] 

等等。当做更大的数字,其中每个顶点将成为几个三角形的一部分,这节省了内存和时间。