// This is the very first public demo of Raydium Augmented Reality !
// All this need a ****big*** cleanup (I'll do it very soon)

// /!\ Linux only, for now.

// To compile it, you need ARToolKit:
// http://sourceforge.net/projects/artoolkit
// then, export AR_PATH="path to compiled toolkit"
// you can now launch this demo using:
// ./odyncomp.sh ar_new.c (do not use ocomp.sh)

// How to make the demo working:
// Plug you webcam (check focus)
// Print patterns/pattHiro.pdf from the ARToolKit lib
// Launch this demo
// Show the sheet to your camera
// You're now experiencing augmented reality ! ;)

#include "raydium/index.c"
#include "AR/param.h"
#include "AR/ar.h"

GLfloat sun[]={1.0,0.9,0.5,1.0};

GLfloat camx=3.01;
GLfloat camy=3;
GLfloat camz=0;

#define PLAYER_MODEL    "sasc2.tri"

#ifndef WIN32
#define CAMERA_RES_X    320
#define CAMERA_RES_Y    240

#define camera "camera_para.dat"

#else
#define CAMERA_RES_X    640
#define CAMERA_RES_Y    480

#define camera "dvx.dat"
#endif

char            *vconf = "";
int             xsize, ysize;
int             thresh = 100;
int             count = 0;

char           *cparam_name    = camera;
ARParam         cparam;

char           *patt_name      = "patt.hiro";
int             patt_id;
double          patt_width     = 80.0;
double          patt_center[2] = {0.0, 0.0};
double          patt_trans[3][4];
int             rot_ok=0;

double          target_width = 80.0;
double          target_center[2] = {0.0, 0.0};
double          cam_trans[3][4];
double          gl_para[16];

double          gl_cpara[16];

void argConvGlpara( double para[3][4], double gl_para[16] )
{
    int     i, j;

    for( j = 0; j < 3; j++ ) {
        for( i = 0; i < 4; i++ ) {
            gl_para[i*4+j] = para[j][i];
        }
    }
    gl_para[0*4+3] = gl_para[1*4+3] = gl_para[2*4+3] = 0.0;
    gl_para[3*4+3] = 1.0;
}


void ar_camera_start(double patt_trans[3][4])
{
double gl_para[16];

argConvGlpara(patt_trans, gl_para);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixd( gl_para );

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixd( gl_cpara );

glMatrixMode(GL_MODELVIEW);
}


void ar_camera_stop(void)
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}


static void argConvGLcpara2( double cparam[3][4], int width, int height, double gnear, double gfar, double m[16] )
{
    double   icpara[3][4];
    double   trans[3][4];
    double   p[3][3], q[4][4];
    int      i, j;

    if( arParamDecompMat(cparam, icpara, trans) < 0 ) {
        printf("gConvGLcpara: Parameter error!!\n");
        exit(0);
    }

    for( i = 0; i < 3; i++ ) {
        for( j = 0; j < 3; j++ ) {
            p[i][j] = icpara[i][j] / icpara[2][2];
        }
    }
    q[0][0] = (2.0 * p[0][0] / width);
    q[0][1] = (2.0 * p[0][1] / width);
    q[0][2] = ((2.0 * p[0][2] / width)  - 1.0);
    q[0][3] = 0.0;

    q[1][0] = 0.0;
    q[1][1] = (2.0 * p[1][1] / height);
    q[1][2] = ((2.0 * p[1][2] / height) - 1.0);
    q[1][3] = 0.0;

    q[2][0] = 0.0;
    q[2][1] = 0.0;
    q[2][2] = (gfar + gnear)/(gfar - gnear);
    q[2][3] = -2.0 * gfar * gnear / (gfar - gnear);

    q[3][0] = 0.0;
    q[3][1] = 0.0;
    q[3][2] = 1.0;
    q[3][3] = 0.0;

    for( i = 0; i < 4; i++ ) {
        for( j = 0; j < 3; j++ ) {
            m[i+j*4] = q[i][0] * trans[0][j]
                     + q[i][1] * trans[1][j]
                     + q[i][2] * trans[2][j];
        }
        m[i+3*4] = q[i][0] * trans[0][3]
                 + q[i][1] * trans[1][3]
                 + q[i][2] * trans[2][3]
                 + q[i][3];
    }
}

void argConvGLcpara( ARParam *param, double gnear, double gfar, double m[16] )
{
    int i;

    for( i = 0; i < 4; i++ ) {
        param->mat[1][i] = (param->ysize-1)*(param->mat[2][i]) - param->mat[1][i];
    }

    argConvGLcpara2( param->mat, param->xsize, param->ysize, gnear, gfar, m );
}


int data_callback(unsigned char *data, int tx, int ty, int bpp)
{
    ARUint8         *dataPtr;
    ARMarkerInfo    *marker_info;
    int             marker_num;
    int