Didn't have that much time over the past few weeks. But I read some articles about icosahedrons (and the other platonic bodies).
There I stumbled across an interesting property of this figure.
It can be surrounded by a cube. 2 vertices of the icosahedron rest on each side (in the middle) of the cube - 6 sides of the cube... makes for 12 vertices of the icosahedron.
4 vertices of the icosahedron resting on 2 sides of the cube that are parallel to each other form a rectangle which penetrates the cube. Makes 3 such rectangles.
All of them are equal shaped and have the following proportion: b : a = (1+sqrt(5)) : 2
Knowing this one can construct the vertex-positions of the icosahedron using the theorems of Pythagoras.
I wanted the size of the icosahedron to be dependend on the radius (diameter/2 of the inscribed rectangle):
// substituting b in the above equation
b = a(1+sqrt(5))/2
// inserting
d? = a? + b?
d? = a? + a? * ((1+sqrt(5))/2)?
d? = a? * (1 + ((1+sqrt(5))/2)?)
// calculating the right term - making this a constant in the code so
// we don't need to recalculate it
d? = a? * 3.6180339887498948482045868343656
(Hope this is right, didn't take my notebook with me where I wrote it down)
Well, equipped with the math I tried to create the vertex-positions. Here's the code:
using System;
using Microsoft.Xna.Framework;
namespace Geosphere
{
/*********************************
* Formulas for an Icosahedron: *
* Faces = 20 * F? *
* Edges = 30 * F? *
* Points = 10 * F? + 2 *
*
*
* (b)
* 1 + sqrt(5)
* -----------
* | ***|
* | *** | 2 (a)
* |*** |
* -----------
*
* *** = (d) = 2 * mRadius
*
* d? = a? + b?
*
*********************************/
public class Icosahedron
{
private const double mConstant = 3.6180339887498948482045868343656;
private float mRadius;
private int mFrequency;
private Vector3[] mVertices;
public Icosahedron()
{
mRadius = 1.0f;
mFrequency = 1;
mVertices = new Vector3[12];
createIcosahedron();
}
public Icosahedron(float Radius, int Frequency)
{
mRadius = Radius;
mFrequency = Frequency;
mVertices = new Vector3[(10 * (mFrequency * mFrequency)) + 2];
createIcosahedron();
}
public Vector3[] Vertices
{
get { return this.mVertices; }
}
private void createIcosahedron()
{
// Calculating vertices for icosahedron of frequency 1
// d is the diagonal of the rectangle
// a is the short edge of the rectangle (2)
// b is the long edge of the rectangle (1 + sqrt(5))
double d = 4 * mRadius * mRadius;
// a and b squared
double a = d / mConstant;
double b = d - a;
// getting the square root of a and b
// dividing by 2 to get the final vertex position
a = Math.Sqrt(a) / 2;
b = Math.Sqrt(b) / 2;
double test = a / b;
double zapp = 2 / (1 + Math.Sqrt(5));
// a = short edge in z-direction (depth of screen/monitor)
// b = long edge in x-direction
mVertices[0] = new Vector3((float)b, 0, (float)a);
mVertices[1] = new Vector3((float)b, 0, -(float)a);
mVertices[2] = new Vector3(-(float)b, 0, (float)a);
mVertices[3] = new Vector3(-(float)b, 0, -(float)a);
// a = short edge in y-direction
// b = long edge in z-direction
mVertices[4] = new Vector3(0, (float)a, (float)b);
mVertices[5] = new Vector3(0, (float)a, -(float)b);
mVertices[6] = new Vector3(0, -(float)a, (float)b);
mVertices[7] = new Vector3(0, -(float)a, -(float)b);
// a = short edge in x-direction
// b = long edge in y-direction
mVertices[8] = new Vector3((float)a, (float)b, 0);
mVertices[9] = new Vector3((float)a, -(float)b, 0);
mVertices[10] = new Vector3(-(float)a, (float)b, 0);
mVertices[11] = new Vector3(-(float)a, -(float)b, 0);
}
}
}
First question:
Is this right so far?
Second question:
Now how do I display the vertices using the XNA Framework and draw triangles between them? Haven't done something like this before.
Sadly the "How-To: Draw 3D Primitives" tutorial in XNA GSE doesn't explain vertex buffers, index buffers and the like so amateurs like me can come up with something on their own.
Any literature or tutorials you can point me to?