/***** Ball.c *****/
/* This file contains code required to implement a trackball user
 * interface for manipulating a 3D scene.  This code was taken from
 * Graphics Gems 4, edited by Andrew Glassner
 */

#include "Ball.h"
#include "BallMath.h"
#include <stdio.h>

HMatrix mId = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
float otherAxis[][4] = {{-0.48, 0.80, 0.36, 1}};

/* Establish reasonable initial values for controller. */
void Ball_Init(BallData *ball)
{
    int i;

    ball->center = qOne;
    ball->radius = 1.0;
    ball->vDown = ball->vNow = qOne;
    ball->qDown = ball->qNow = qOne;
    for (i = 15; i >= 0; i--)
        ((float *)ball->mNow)[i] = ((float *)ball->mDown)[i] =
            ((float *)mId)[i];
    ball->dragging = 0;
}

/* Set the center and size of the controller. */
void Ball_Place(BallData *ball, HVect center, double radius)
{
    ball->center = center;
    ball->radius = radius;
}

/* Incorporate new mouse position. */
void Ball_Mouse(BallData *ball, HVect vNow)
{
    ball->vNow = vNow;
}

/* Using vDown, vNow, dragging, and axisSet, compute rotation etc. */
void Ball_Update(BallData *ball)
{
    Quat qout, qout2;

    ball->vFrom = MouseOnSphere(ball->vDown, ball->center, ball->radius);
    ball->vTo = MouseOnSphere(ball->vNow, ball->center, ball->radius);
    if (ball->dragging) {
        ball->qDrag = Qt_FromBallPoints(ball->vFrom, ball->vTo);
        ball->qNow = Qt_Mul(ball->qDrag, ball->qDown);
    }
    Qt_ToBallPoints(ball->qDown, &ball->vrFrom, &ball->vrTo);

    Qt_ToMatrix(Qt_Conj(ball->qNow), ball->mNow); /* Gives transpose for GL. */
    qout2 = Matrix_to_Qt(ball->mNow);
    qout = Qt_Conj(qout2);
}

void Ball_SetMatrix(BallData *ball, HMatrix mat)
{
    int i, j;
    Quat qt;

    Ball_Init(ball);
    qt = Matrix_to_Qt(mat);
    ball->qNow = Qt_Conj(qt);
    ball->qDown = ball->qNow;
    for (i = 0; i < QuatLen; i++)
        for (j = 0; j < QuatLen; j++)
            ball->mNow[i][j] = mat[i][j];
}

/* Return rotation matrix defined by controller use. */
void Ball_Value(BallData *ball, HMatrix mNow)
{
    int i;

    for (i = 15; i >= 0; i--)
        ((float *)mNow)[i] = ((float *)ball->mNow)[i];
}

/* Begin drag sequence. */
void Ball_BeginDrag(BallData *ball)
{
    ball->dragging = 1;
    ball->vDown = ball->vNow;
}

/* Stop drag sequence. */
void Ball_EndDrag(BallData *ball)
{
    int i;

    ball->dragging = 0;
    ball->qDown = ball->qNow;
    for (i = 15; i >= 0; i--)
        ((float *)ball->mDown)[i] = ((float *)ball->mNow)[i];
}
