/*
    Raydium - CQFD Corp.
    http://raydium.org/
    Released under both BSD license and Lesser GPL library license.
    See "license.txt" file.
*/

#ifndef DONT_INCLUDE_HEADERS
#include "index.h"
#else
#include "headers/math.h"
#include "headers/shadow.h"
#endif

GLfloat raydium_math_cos(GLfloat i)
{
return( (GLfloat)cos(i*PI/180) );
}

GLfloat raydium_math_sin(GLfloat i)
{
return( (GLfloat)sin(i*PI/180) );
}

GLfloat raydium_math_cos_inv(GLfloat i)
{
return(acos(i)*180/PI);
}

GLfloat raydium_math_sin_inv(GLfloat i)
{
return(asin(i)*180/PI);
}

void raydium_math_rotate(GLfloat *p, GLfloat rx, GLfloat ry, GLfloat rz, GLfloat *res)
{
res[0]= (p[0]*raydium_math_cos(ry)+(p[2]*raydium_math_cos(rx)+p[1]*raydium_math_sin(rx))*raydium_math_sin(ry))*raydium_math_cos(rz) + (p[1]*raydium_math_cos(rx)-p[2]*raydium_math_sin(rx))*raydium_math_sin(rz);
res[1]=-(p[0]*raydium_math_cos(ry)+(p[2]*raydium_math_cos(rx)+p[1]*raydium_math_sin(rx))*raydium_math_sin(ry))*raydium_math_sin(rz) + (p[1]*raydium_math_cos(rx)-p[2]*raydium_math_sin(rx))*raydium_math_cos(rz);
res[2]= (p[2]*raydium_math_cos(rx)+ p[1]*raydium_math_sin(rx))*raydium_math_cos(ry)-p[0]*raydium_math_sin(ry);
}

void raydium_math_normalize_vector4 (GLfloat * vector){
	GLfloat length;
	length=1.0/sqrtf(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]);
	vector[0]*=length;
	vector[1]*=length;
	vector[2]*=length;
}

// pos: GLfloat[3], m: GLfloat[16]
void raydium_math_pos_to_matrix(GLfloat *pos, GLfloat *m)
{
m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = pos[0];
m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = pos[1];
m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = pos[2];
m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
}

void raydium_math_multiply_matrix4(GLfloat *matrix1,GLfloat *matrix2,GLfloat *result ){

	unsigned int i, j, k;
	for(i=0; i<4; i++)
	{
		for(j=0; j<4; j++)
		{
            GLfloat acc = 0;
		    for (k=0; k<4; k++)
		        acc += matrix1[i+k*4] * matrix2[k+j*4];

		    result[i+j*4] = acc;
		}
	}
}

// res: GLfloat[3]
void raydium_math_pos_get_modelview(GLfloat *res)
{
GLfloat tmp[16];
glGetFloatv(GL_MODELVIEW_MATRIX,tmp);
res[0]=tmp[12];
res[1]=tmp[13];
res[2]=tmp[14];
}

/* Unfinished !
// pos == res is safe
void raydium_trigo_carth_to_sphere(GLfloat *pos, GLfloat *res)
{
GLfloat r,G,T;

r=sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2]);
G=atan(pos[1]/pos[0]);
T=acos(pos[2]/r);

//printf("%f\n",r);
r=1;

if(pos[0]<0)
    res[0]=-r*cos(G);
else
    res[0]=+r*cos(G);

//res[1]=r*sin(G);
if(pos[0]<0)
    res[0]=-r*sin(T)*cos(G);
else
    res[0]=r*sin(T)*cos(G);
res[1]=r*sin(G)*cos(G);
res[2]=r*cos(T);

if(isnan(res[0])) res[0]=0;
if(isnan(res[1])) res[1]=0;
if(isnan(res[2])) res[2]=0;

}
*/

int raydium_math_pow2_next(int value)
{
int pows[]={0,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};
int pows_count=17; // 16 + first (0)
int i;

if(value>65536 || value<0)
    {
    raydium_log("trigo: value is outside of limits of this ugly function :/");
    }

for(i=0;i<pows_count;i++)
    if(pows[i]>=value)
        return pows[i];


// should never hit this point
raydium_log("trigo: raydium_math_pow2_next: ?!!");
return -1;
}

float raydium_math_angle_from_projections(float px, float py)
{
float realangle;
//using the arccos we get the "base angle"
realangle = acos ( px );
//check quadrants
//if the Y projection is negative, the angle has to be adjusted
if ( py < 0 )
    realangle = ( float ) 2 * PI - realangle;

return realangle;
}

#ifndef RAYDIUM_NETWORK_ONLY
signed char raydium_math_point_unproject_3D(GLfloat x, GLfloat y, GLfloat z, float* resx, float* resy)
{
GLdouble sx,sy,sz;
GLdouble modelMatrix[16];
GLdouble projectionMatrix[16];
GLint   viewport[4];

raydium_camera_replace();
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
glGetIntegerv(GL_VIEWPORT, viewport);
gluProject(x,y,z,modelMatrix,projectionMatrix,viewport,&sx,&sy,&sz);

sx=(sx-viewport[0])/viewport[2]*100;
sy=(sy-viewport[1])/viewport[3]*100;
(*resx)=sx;
(*resy)=sy;

if(sz<=1.0f)
   dD=-1;break;
        case 6: speedG=-1;speedD=0;break;
        case 8: speedG=-1;speedD=1;break;
        case 9: speedG=0;speedD=1;break;
        case 12: speedG=0;speedD=-1;break;
        default: speedD=speedG=0;
    }
    speedD*=10;
    speedG*=10;
    raydium_ode_motor_speed_name("tank_moteurG",-speedG);
    raydium_ode_motor_speed_name("tank_moteurD",-speedD);


    speed=raydium_math_abs(speedD)+raydium_math_abs(speedG);
    speed*=0.025;
    speed+=0.5;
    speed+=(raydium_random_neg_pos_1()/15);
    raydium_ode_element_sound_update_name("tank_corps",sound_car);
    raydium_sound_SetSourcePitch(sound_car,raydium_math_abs(speed));

    if(raydium_key_last==1027)
        exit(0);

    raydium_light_position[0][0]=100;
    raydium_light_position[0][1]=100;
    raydium_light_position[0][2]=100;
    raydium_light_position[0][3]=1.0;
    raydium_light_update_position(0);

    raydium_background_color_change(light_color[0],light_color[1],light_color[2],light_color[3]);

    raydium_clear_frame();

    if(!raydium_key[GLUT_KEY_F2]){

        raydium_viewport_enable("camera2");

        raydium_ode_element_camera_inboard_name("tank_tour",0.2,0,0.1,2,0,0);

        raydium_ode_draw_all(RAYDIUM_ODE_DRAW_NORMAL);
        raydium_osd_printf(10,10,40,0.5,"font2.tga","standard viewport");
        raydium_osd_logo("logo.tga");
        raydium_viewport_save();
        raydium_clear_frame();
    }


    delta_x = raydium_mouse_x - (raydium_window_tx/2);
    delta_y = raydium_mouse_y - (raydium_window_ty/2);
    raydium_mouse_move(raydium_window_tx/2, raydium_window_ty/2);

    if (inboard){
        static GLfloat speed=0;

        if (raydium_mouse_button[2]) {
            if (speed==0)
                speed=0.1;
            speed+=0.01;
        }
            else
        speed=0;

        if (raydium_mouse_click==4)
            speed=0.05;
        if (raydium_mouse_click==5)
            speed=-0.05;

        cam_angle_x += (delta_x*3*0.1f);
        cam_angle_y += (delta_y*3*0.1f);

        cam_pos_z += (raydium_math_sin(cam_angle_x+90)*speed*raydium_math_sin(90-cam_angle_y));
        cam_pos_x += (raydium_math_cos(cam_angle_x+90)*speed*raydium_math_sin(90-cam_angle_y));
        cam_pos_y += (raydium_math_cos(90-cam_angle_y)*speed);
        raydium_camera_place(cam_pos_x,cam_pos_y,cam_pos_z,cam_angle_x,cam_angle_y,0);

    }
    else {
        raydium_ode_motor_angle_name("pivot_motor",raydium_ode_motor_angle_get_name("pivot_motor",0)+delta_x*10.0f);
        raydium_ode_motor_angle_name("truk_motor",raydium_ode_motor_angle_get_name("truk_motor",0)-delta_y*10.0f);

        raydium_ode_element_camera_inboard_name("tank_corps",0.7,0,0.2,2,0,0);
    }


    raydium_ode_draw_all(0);
    raydium_ode_draw_all(RAYDIUM_ODE_DRAW_RAY);

    if(raydium_key[GLUT_KEY_F1])
        raydium_ode_draw_all(1);

    if(!raydium_key[GLUT_KEY_F2])
        raydium_viewport_draw("camera2",20,70,60,30);

    raydium_osd_printf(2,98,16,0.5,"font2.tga","- %3i FPS - Viewport demo %s for Raydium %s, CQFD Corp.",raydium_render_fps,version,raydium_version());

    if (raydium_key_last==1000+'m') inboard^=1;

    if(!raydium_key[GLUT_KEY_F3]){
        raydium_viewport_direct_open_4f(20,40,60,30);

        raydium_ode_element_camera_inboard_name("tank_tour",0.2,0,0.1,2,0,0);

        raydium_ode_draw_all(RAYDIUM_ODE_DRAW_NORMAL);
        raydium_osd_printf(10,10,40,0.5,"font2.tga","direct viewport");
        raydium_osd_logo("logo.tga");
        raydium_viewport_direct_close();
    }

    raydium_osd_logo("logo.tga");

    raydium_rendering_finish();
}


int main(int argc, char **argv)
{
    raydium_init_args(argc,argv);

    raydium_window_create(640,480,RAYDIUM_RENDERING_WINDOW,"test Viewports");
    raydium_texture_filter_change(RAYDIUM_TEXTURE_FILTER_TRILINEAR);
    raydium_projection_near=0.01;
    raydium_projection_far=2500;
    raydium_projection_fov=60;
    raydium_fog_disable();
    raydium_window_view_update();
    raydium_shadow_enable();
//    raydium_shadow_disable();

    raydium_light_on(0);
    memcpy(raydium_light_color[0],light_color,raydium_internal_size_vector_float_4);
    raydium_light_intensity[0] = 1000000;
    raydium_light_update_all(0);


    raydium_ode_ground_set_name("cocorobix.tri");
    raydium_ode_element_slip_name("ground",GROUND_SLIP);

    raydium_sound_DefaultReferenceDistance=4.f;
    sound_car=raydium_sound_LoadWav("murcielago.wav");
    raydium_sound_SetSourcePitch(sound_car,0);
    raydium_sound_SetSourceGain(sound_car,0.1);  // Engine Gain

    raydium_viewport_create ("camera2",256,256);

    simul_create();

    raydium_callback(&display);
    return(0);
}
// EOF