//Makes a mesh ball.

#define VERTICES_NUM    1024
#define TRIS_NUM                1024

class Ball
{
        I32                     vertex_count;
        I32                     tri_count;
        CD3I32          v[VERTICES_NUM];
        CMeshTri        t[TRIS_NUM];

} *b;

class BallDefineStruct
{
        F64 radius              format "$DA-TRM,A=\"Radius         :%8.3f\"$\n";
        I64 n_longitude format "$DA-TRM,A=\"Longitude Faces:%5d\"$\n";
        I64 n_lattitude format "$DA-TRM,A=\"Lattitude Rings:%5d\"$\n";
};

U0 BDInit(BallDefineStruct *bd)
{
        MemSet(bd, 0, sizeof(BallDefineStruct));
        bd->n_longitude = 16;
        bd->n_lattitude = 8;
        bd->radius              = 20.0;
}

U0 BDCorrect(BallDefineStruct *bd)
{
        bd->n_longitude = (bd->n_longitude + 1) / 2;
        bd->n_lattitude = (bd->n_lattitude + 1) / 2;
}

I64 AddVertex(BallDefineStruct *, I64 x, I64 y, I64 z)
{
        I64 i;

        for (i = 0; i < b->vertex_count; i++)
                if (b->v[i].x == x && b->v[i].y == y && b->v[i].z == z)
                        return i;
        i = b->vertex_count++;
        b->v[i].x = x;
        b->v[i].y = y;
        b->v[i].z = z;

        return i;
}

I64 AddTri(BallDefineStruct *, I64 c, I64 n0, I64 n1, I64 n2)
{
        I64 res = b->tri_count++;

        b->t[res].color = c;
        b->t[res].nums[0] = n0;
        b->t[res].nums[1] = n1;
        b->t[res].nums[2] = n2;

        return res;
}

U8 *Ball2CSprite()
{
//See ::/System/Gr/GrSpritePlot.CC for how CSprite are stored.
        U8      *res = MAlloc(sizeof(CSpriteMeshU8s) +
                                          b->vertex_count * sizeof(CD3I32) +
                                          b->tri_count * sizeof(CMeshTri) + sprite_elem_base_sizes[SPT_END]), 
                *dst = res;
        *dst++ = SPT_MESH;
        *dst(I32 *)++ = b->vertex_count;
        *dst(I32 *)++ = b->tri_count;
        MemCopy(dst, &b->v, b->vertex_count * sizeof(CD3I32));
        dst += b->vertex_count * sizeof(CD3I32);
        MemCopy(dst, &b->t, b->tri_count * sizeof(CMeshTri));
        dst += b->tri_count * sizeof(CMeshTri);
        *dst++ = SPT_END;

        return res;
}

public U8 *BallGen()
{
        U8                              *res;
        I64                              i, j, n, m, c, p1, p2, p3, p4;
        BallDefineStruct bd1, bd2;
        F64                              r, r1, r2, z1, z2, d_a1, d_a2;

        BDInit(&bd1);

        while (TRUE)
        {
                if (!DocForm(&bd1))
                        return NULL;
                MemCopy(&bd2, &bd1, sizeof(BallDefineStruct));
                BDCorrect(&bd2);

                c = PopUpColorLighting;
                if (c < 0)
                        return NULL;

                b = CAlloc(sizeof(Ball));
                r = bd2.radius;
                n = bd2.n_lattitude;
                m = bd2.n_longitude;
                d_a1 = 2 * pi / n / 4;
                d_a2 = 2 * pi / m / 2;
                for (j = -n; j < n; j++)
                {
                        r1 = r * Cos( j         *d_a1);
                        r2 = r * Cos((j+1)*d_a1);
                        z1 = r * Sin( j         *d_a1);
                        z2 = r * Sin((j+1)*d_a1);
                        for (i = 0; i < m; i++)
                        {
                                p1 = AddVertex(&bd2, r1 * Cos((2 * i  + j)       * d_a2), r1 * Sin((2 * i + j)     * d_a2), z1);
                                p2 = AddVertex(&bd2, r1 * Cos((2 * i + 2 +j) * d_a2), r1 * Sin((2 * i + 2 + j) * d_a2), z1);
                                p3 = AddVertex(&bd2, r2 * Cos((2 * i + 1 +j) * d_a2), r2 * Sin((2 * i + 1 + j) * d_a2), z2);
                                p4 = AddVertex(&bd2, r2 * Cos((2 * i + 3 +j) * d_a2), r2 * Sin((2 * i + 3 + j) * d_a2), z2);
                                AddTri(&bd2, c, p1, p2, p3);
                                AddTri(&bd2, c, p3, p2, p4);
                        }
                }

                res = Ball2CSprite;
                "%h7c", '\n';
                Sprite(res, "\t\t$SP,\"<1>\",BI=%d$");
                "%h7c", '\n';
                "Vertices:%d\n", b->vertex_count;
                Free(b);
                "Do another";
                if (YorN)
                        Free(res);
                else
                        break;
        }

        return res;
}