Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've created a tetrahedron by creating a BoundingBox and building the faces of the tetrahedron within the bounding box as follows (see image as well):

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];

enter image description here

What would I then have to do to transform this tetrahedron into an icosahedron? Similar to this image:

enter image description here

I understand the concept but applying it is another thing entirely for me.

And to clarify, I'm not wanting an animation, I simply want to create an icosahedron from the vertices of a tetrahedron.

EDIT: So I now have an alternative way to create an icosahedron using golden rectangles. That's fine for the purposes of my particular project. However, I'd like to leave the question open for solutions to the original problem, i.e. mathematically converting a tetrahedron in Cartesian co-ords into an icosahedron (not vice-versa).

share|improve this question
    
Do you need an animated transformation, or do you just want to create an icosahedron that shares some vertices with the tetrahedron? –  Sam Hocevar Nov 28 '12 at 11:45
    
I just want to create one, no animation. –  Djentleman Nov 28 '12 at 18:45

3 Answers 3

up vote 2 down vote accepted

First, create three sets of 4 points, each set being a 3D golden rectangle in the X, Y or Z direction:

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);
}

Then create triangles to build the icosahedron:

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]];
}

Area formula

From the Wikipedia article Icosahedron, we know that with an edge length of a, the radius of the circumscribed sphere is a * sin(2 * pi / 5). Since we built golden rectangles, the radius is currently 0.5 * sqrt(1 + phi²), which can be expanded to sqrt((5 + sqrt(5)) / 8), which is precisely sin(2 * pi / 5)! This means that our edge length is 1.

From the Wikipedia article again, we know that the surface area is therefore 5 * sqrt(3).

So if you want a surface area A, you need to multiply all point coordinates with sqrt(A / (5 * sqrt(3)).

Transformation from tetrahedron

In order to transform a tetrahedron into an icosahedron in a smooth way, each vertex needs to be duplicated 3 times. Conversely, in order to transform the icosahedron into a tetrahedron, groups of 3 vertices need to be merged into one vertex:

  • Group 1 : vertices 0, 1, 2
  • Group 2 : vertices 3, 7, 11
  • Group 3 : vertices 6, 10, 5
  • Group 4 : vertices 9, 4, 8

This is some code that should work. Just use t as a parameter between 0.0 and 1.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]);
}

Then use the code above, building vertices using newpoints instead of points. The result can be seen in this YouTube video.

share|improve this answer
    
This is fantastic! Just a question: Given the input float surfaceArea, is there some known way of determining the sizes of the golden rectangles to ensure the total surface area of the icosahedron matches the `float surfaceArea? –  Djentleman Nov 28 '12 at 22:59
    
@Djentleman Yes, I'll add a note about this. –  Sam Hocevar Nov 28 '12 at 23:04
    
You are a god among men. Thank you sir. –  Djentleman Nov 29 '12 at 4:06
    
@Djentleman Heh, thanks :-) For completeness I added some information about the tetrahedron transformation; do you think it's enough? –  Sam Hocevar Nov 29 '12 at 19:21
    
It's good but I'm looking for an actual coded solution. I'm wondering if it will possibly require the use of quaternions (trying to solve it myself). Also, just as a side note, I corrected a syntax error where you were checking for even or odd numbers in your for loop. And I've implemented a buffer as per Steven's answer for slightly increased performance. - I'll most likely be marking this as my chosen answer in a week :) –  Djentleman Nov 29 '12 at 20:30

First of all, you probably don't want to get your coordinates by 'converting' a tetrahedron; instead, just start with icosahedron coordinates. Fortunately, coordinates for the vertices of an icosahedron are actually pretty straightforward; they're just the corners of three 'golden rectangles' interlocked with each other: (±1, ±φ, 0), (0, ±1, ±φ), and (±φ, 0, ±1), where φ is the golden ratio (sqrt(5)+1)/2. Finding the 20 triangles that use those vertices is actually probably best done 'by hand' - put together three rectangles like that and look at how they connect and you'll get the idea pretty quickly.

On a side note, I would recommend using vertex buffers - rather than having explicit vertices for every point of every triangle, instead have just a list of the 12 vertices and then index into the buffer for your triangles. In your tetrahedron example, this would be more like:

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)
// [ ... ]

etc. When doing larger figures where each vertex will be part of several triangles, this saves both memory and time.

share|improve this answer
    
Thanks! Great advice. I especially like the idea of a vertex buffer. The only real problem I'm having with this approach is finding out which vertices go together to form triangles. But of course it's doable :) –  Djentleman Nov 28 '12 at 19:42
    
Djentleman: Yeah, it's something that's easier to pick up with practice visualizing; that's why I suggested building a model, because that sort of intuition will serve you well in the long run. Alternately you could mark up the verts of a d20 in the appropriate colors and use that as your guide; you'd be surprised how well that works. :-) –  Steven Stadnicki Nov 28 '12 at 22:14

Rather than trying to transform your tetrahedron into an icosahedron, work backwards.

Construct your icosahedron, then pick four "opposite" faces of the icosahedron (like the blue or the red ones in your animated image).

The four faces you picked will be the red ones from the animation, which condense into one corner point of the tetrahedron each (green lines show which vertices move to which point on the tetrahedron):

(tetrahedron smaller for better visibility)

(actual sizes)

For the actual animation part, a simple way would be to just do a linear interpolation from those faces' vertices' positions in the icosahedron to the centerpoint of that face, which will become the corners of the tetrahedron.

Then simply animate in reverse to transform from the tetra- to the icosahedron.

share|improve this answer
    
Thank you so much for the answer but I really should clarify. I'm not wanting an animation, I simply want to create an icosahedron from a tetrahedron. –  Djentleman Nov 28 '12 at 18:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.