Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Morph cube into sphere

Tags:

c#

xna

3d

I created a cube of small sphere models that act as dots. The dots have coordinates:

{0 <= x <= 9, 0 <= y <= -9, 0 <= z <= -9}

The interior of the cube is empty so dots only exist on the surface of the cube. The empty spaces are represented as points at (100, 100, 100) and when I do the draw loop I ignore points which match them, which is why in the code I'll post below will have that as a condition for doing certain things or not doing them.

The goal is to take the points of the cube, and apply transformations to them to map them onto a sphere.

This is the set of equations used to transform the points.

This is the code to create the array for the cube positions then to create an array for the sphere positions:

// initialize cube array
points = new Matrix[10, 10, 10];

for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        for (int k = 0; k < 10; k++)
        {
            points[i, j, k] = Matrix.CreateTranslation(new Vector3(100, 100, 100));
        }
    }
}

for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        points[i, j, 0] = Matrix.CreateTranslation(new Vector3(i, -j, 0));
        points[i, j, 9] = Matrix.CreateTranslation(new Vector3(i, -j, -9));
    }
}

for (int j = 0; j < 10; j++)
{
    for (int k = 0; k < 10; k++)
    {
        points[0, j, k] = Matrix.CreateTranslation(new Vector3(0, -j, -k));
        points[9, j, k] = Matrix.CreateTranslation(new Vector3(9, -j, -k));
    }
}

for (int i = 0; i < 10; i++)
{
    for (int k = 0; k < 10; k++)
    {
        points[i, 0, k] = Matrix.CreateTranslation(new Vector3(i, 0, -k));
        points[i, 9, k] = Matrix.CreateTranslation(new Vector3(i, -9, -k));
    }
}
// end cube array initialization

// create sphere array
double d;
double theta;
double phi;
double r = 10;

spherePoints = new Matrix[10, 10, 10];
for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        for (int k = 0; k < 10; k++)
        {
            if (points[i, j, k] != Matrix.CreateTranslation(new Vector3(100, 100, 100)))
            {
                d = Math.Sqrt(Math.Pow(i, 2) + Math.Pow(-j, 2) + Math.Pow(-k, 2));
                theta = Math.Acos(-k / d);
                phi = Math.Atan2(-j, i);

                spherePoints[i, j, k] = Matrix.CreateTranslation(new Vector3((float)(r * Math.Sin(theta) * Math.Cos(phi)),
                                                                            (float)(r * Math.Sin(theta) * Math.Sin(phi)),
                                                                            (float)(r * Math.Cos(theta))));
            }
            else
                spherePoints[i, j, k] = Matrix.CreateTranslation(new Vector3(100, 100, 100));
        }
    }
}
// end creation of sphere array

Cube: enter image description here

Not a sphere...: enter image description here

From what I can tell I followed the formula exactly, but it seems to only generate an eighth of a sphere. There also appears to be weird grouping along the edges.

like image 877
Portaljacker Avatar asked Feb 18 '13 17:02

Portaljacker


1 Answers

The problem is that you're only drawing your cube in one "quadrant" (or perhaps "octrant" would be more appropriate), so you're only getting 1/8 of your sphere.

Instead of having your cube go from [0,9], [-9,0], [-9,0], focus it on the origin.

Once your cube goes from [-5,5], [-5, 5], [-5,5], your spherical calculation will be fine.

Just to give a bit more understanding of how this is the issue:

  • How many quadrants will your answers be in when you evaluate Acos(z/d), given that d is always positive and z is always negative?
  • How many quadrants will your answers be in when you evaluate Atan(y, x), given that y is always negative and x is always negative?

Out of the 8 possible quadrant combinations, you're only filling one.

like image 161
Scott Mermelstein Avatar answered Oct 17 '22 13:10

Scott Mermelstein