#include <math.h>
#include "fasttrig.h"
#include "bezpt.h"
#include "revolve.h"
#include "mytypes.h"


RevAxisType RevAxis;


short RevMesh = DefRevMeshVal;
short RevImageR, /* revolution index */
      RevImageB; /* bezier index */

static int RotRange = DefRotRange;
static int RotStart = DefRotStart;
static int SecAngle = DefTilt;
static float SurfDist = DefSurfDist;
static float ViewDist = DefViewDist;
static bool Perspective = DefPersp;

void SetPerspective(  value)
    int value;
{
    Perspective = value;
}



void SetRevAxis( value)
    int value;
{
    RevAxis = (value)? RevY : RevX;
}


void SetRotStart( value )
    int value;
{
    RotStart = value;
}

void SetRotRange(  value )
    int value;
{
    RotRange = value;
}

void SetSecAng( value )
    int value;
{
    SecAngle = value;
}

void SetRevMesh( value )
    int value;
{
    RevMesh = value;
}


void SetSurfDist( value )
    int value;
{
    SurfDist = (float )value;
}


void SetViewDist( value )
    int value;
{
    ViewDist = (float )value;
}



static
float secsin, seccos; /* trig values of secondary angle */

static
int sizeptlist = 0;

static
PtGen *ptlist1 = 0,
      *ptlist2 = 0;

static
int NumEnts; /* number of angle slices */


static
bool PrepRev()
{
    NumEnts = RevMesh+1;

    /*
     * allocate space 3d descriptions of a point revolved x degrees
     */
    if( NumEnts > sizeptlist ) {
        if( ptlist1 ) free(ptlist1);
        if( ptlist2 ) free(ptlist2);

        ptlist1 =(PtGen *) malloc( NumEnts * sizeof(PtGen)  );
        ptlist2 =(PtGen *) malloc( NumEnts * sizeof(PtGen)  );
        if( !ptlist1 || !ptlist2 ) {
            OutErr("PrepRev:not enough memory");
            return(true);
        }
    }


    if( InitFastTrig( RotStart, RotRange, NumEnts)) return(true);
    secsin = sin((float)SecAngle*PI/180);
    seccos = cos((float)SecAngle*PI/180);
    return (false);
}


static
void CalcRing(ptlist, xpos, ypos)
register PtGen *ptlist;
float xpos, ypos;
{
    int angle;

    for( angle = 0; angle < NumEnts; angle++, ptlist++) {
        float temp;
        /*
         * calculate 3d coordinate of point revolved
         */
        if( RevAxis == RevX) {
            ptlist->d3.y = ypos * fcos(angle);
            temp = ypos * fsin(angle);
            ptlist->d3.x = xpos* seccos - temp *secsin;
            ptlist->d3.z = xpos * secsin + temp * seccos;
        }
        else {
            ptlist->d3.x = xpos * fcos(angle);
            temp = xpos * fsin( angle);
            ptlist->d3.y = ypos * seccos + temp * secsin;
            ptlist->d3.z = secsin * ypos - temp * seccos;
        }
        ptlist->d3.z -= SurfDist;

        if( Perspective ) {
            float PerspScale;

            PerspScale = fabs(ViewDist / ptlist->d3.z);
            ptlist->d3.x *= PerspScale;
            ptlist->d3.y *= PerspScale;
        }
        /*
         * calculate the 2d screen coordinate equvalent
         */
      /*
        ptlist->d2.x = (short) ptlist->d3.x;
        ptlist->d2.y = (short) ptlist->d3.y;
       */
        ptlist->d2.x = (short) (ptlist->d3.x + 0.5);
        ptlist->d2.y = (short) (ptlist->d3.y + 0.5);
    }
}






/*
 * return true on failure
 */
bool Revolve(acceptfunc)
void (*acceptfunc)();
{
    int segno;
    float tparm, deltat;
    int angle;
    int subseg;

    if( PrepRev() ) {
        return(true);
    }

    deltat = 1.0/BezMesh;
    RevImageB = 0;
    ResetActSeg();
    do {
        float xpos, ypos;


        InitCalcBez();
        xpos = StartPtX(GetCurSeg());
        ypos = StartPtY(GetCurSeg());
        CalcRing(ptlist1, xpos, ypos );
        for( subseg = 1; subseg <= BezMesh; subseg++ ) {
            register PtGen *ptlista, *ptlistb;
            register int numpoly;

            tparm = subseg * deltat;
            if( subseg & 1 ) {
                ptlista = ptlist2; ptlistb = ptlist1;
            }
            else {
                ptlista = ptlist1; ptlistb = ptlist2;
            }

            CalcBezPt(tparm, &xpos, &ypos );
            CalcRing( ptlista, xpos, ypos );
            RevImageR = 0;
            for( numpoly = NumEnts -1; numpoly--; ) {
     /*         (* acceptfunc)(ptlista, ptlista+1, ptlistb+1, ptlistb); */
                (* acceptfunc)(ptlistb, ptlista, ptlista+1, ptlistb+1);
                ptlista++;
                ptlistb++;
                RevImageR++;
            }
            RevImageB++;
        }
        NextSeg();

    } while( ActSeg );
    return( false );
}
