//----------------------------------------------------------------------------
void ConvexPolyhedron::CreateEggShape (const Vector3& rkCenter, Real fX0,
                                       Real fX1, Real fY0, Real fY1, Real fZ0, Real fZ1, int iMaxSteps,
                                       ConvexPolyhedron& rkEgg)
{
    assert( fX0 > 0.0f && fX1 > 0.0f );
    assert( fY0 > 0.0f && fY1 > 0.0f );
    assert( fZ0 > 0.0f && fZ1 > 0.0f );
    assert( iMaxSteps >= 0 );

    // Start with an octahedron whose 6 vertices are (-x0,0,0), (x1,0,0),
    // (0,-y0,0), (0,y1,0), (0,0,-z0), (0,0,z1).  The center point will be
    // added later.
    vector<Vector3> akPoint(6);
    akPoint[0] = Vector3(-fX0,0.0f,0.0f);
    akPoint[1] = Vector3(fX1,0.0f,0.0f);
    akPoint[2] = Vector3(0.0f,-fY0,0.0f);
    akPoint[3] = Vector3(0.0f,fY1,0.0f);
    akPoint[4] = Vector3(0.0f,0.0f,-fZ0);
    akPoint[5] = Vector3(0.0f,0.0f,fZ1);

    vector<int> aiConnect(24);
    aiConnect[ 0] = 1;
    aiConnect[ 1] = 3;
    aiConnect[ 2] = 5;
    aiConnect[ 3] = 3;
    aiConnect[ 4] = 0;
    aiConnect[ 5] = 5;
    aiConnect[ 6] = 0;
    aiConnect[ 7] = 2;
    aiConnect[ 8] = 5;
    aiConnect[ 9] = 2;
    aiConnect[10] = 1;
    aiConnect[11] = 5;
    aiConnect[12] = 3;
    aiConnect[13] = 1;
    aiConnect[14] = 4;
    aiConnect[15] = 0;
    aiConnect[16] = 3;
    aiConnect[17] = 4;
    aiConnect[18] = 2;
    aiConnect[19] = 0;
    aiConnect[20] = 4;
    aiConnect[21] = 1;
    aiConnect[22] = 2;
    aiConnect[23] = 4;

    rkEgg.InitialELabel() = 0;
    rkEgg.Create(akPoint,aiConnect);

    // Subdivide the triangles.  The midpoints of the edges are computed.
    // The triangle is replaced by four sub triangles using the original 3
    // vertices and the 3 new edge midpoints.

    int i;
    for (int iStep = 1; iStep <= iMaxSteps; iStep++)
    {
        int iVQuantity = rkEgg.GetVQuantity();
        int iEQuantity = rkEgg.GetEQuantity();
        int iTQuantity = rkEgg.GetTQuantity();

        // compute lifted edge midpoints
        for (i = 0; i < iEQuantity; i++)
        {
            // get edge
            const MTEdge& rkE = rkEgg.GetEdge(i);
            int iV0 = rkEgg.GetVLabel(rkE.GetVertex(0));
            int iV1 = rkEgg.GetVLabel(rkE.GetVertex(1));

            // compute "lifted" centroid to points
            Vector3 kCen = rkEgg.Point(iV0)+rkEgg.Point(iV1);
            Real fXR = (kCen.x > 0.0f ? kCen.x/fX1 : kCen.x/fX0);
            Real fYR = (kCen.y > 0.0f ? kCen.y/fY1 : kCen.y/fY0);
            Real fZR = (kCen.z > 0.0f ? kCen.z/fZ1 : kCen.z/fZ0);
            kCen *= Math::InvSqrt(fXR*fXR+fYR*fYR+fZR*fZR);

            // Add the point to the array.  Store the point index in the edge
            // label for support in adding new triangles.
            rkEgg.ELabel(i) = iVQuantity++;
            rkEgg.AddPoint(kCen);
        }

        // Add the new triangles and remove the old triangle.  The removal
        // in slot i will cause the last added triangle to be moved to that
        // slot.  This side effect will not interfere with the iteration
        // and removal of the triangles.
        for (i = 0; i < iTQuantity; i++)
        {
            const MTTriangle& rkT = rkEgg.GetTriangle(i);
            int iV0 = rkEgg.GetVLabel(rkT.GetVertex(0));
            int iV1 = rkEgg.GetVLabel(rkT.GetVertex(1));
            int iV2 = rkEgg.GetVLabel(rkT.GetVertex(2));
            int iV01 = rkEgg.GetELabel(rkT.GetEdge(0));
            int iV12 = rkEgg.GetELabel(rkT.GetEdge(1));
            int iV20 = rkEgg.GetELabel(rkT.GetEdge(2));
            rkEgg.Insert(iV0,iV01,iV20);
            rkEgg.Insert(iV01,iV1,iV12);
            rkEgg.Insert(iV20,iV12,iV2);
            rkEgg.Insert(iV01,iV12,iV20);
            rkEgg.Remove(iV0,iV1,iV2);
        }
    }

    // add center
    for (i = 0; i < (int)rkEgg.m_akPoint.size(); i++)
        rkEgg.m_akPoint[i] += rkCenter;

    rkEgg.UpdatePlanes();
}