// <ZZ> This file contains lots of global variables and defines and other fun stuff.


//-Includes--------------------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include "SDL.h"

// Platform specific stuff for windows...
#include <windows.h>
#include <GL/gl.h>


//-Defines---------------------------------------------------------------------------------------


// General stuff
#define UPDATES_PER_SECOND 60
#define APPLICATION_NAME "Endoscopy Simulator"
#define VERSION_NUMBER 1.1f
#ifndef FALSE
    #define FALSE 0
#endif
#ifndef TRUE
    #define TRUE 1
#endif
#define PI 3.1415929f
#define X 0             // Position components
#define Y 1
#define Z 2
#define VX 3            // Velocity components
#define VY 4
#define VZ 5
#define NX 6            // Normal vector components
#define NY 7
#define NZ 8
#define OX 9            // Original position components
#define OY 10
#define OZ 11
#define TX 12           // Texture position components
#define TY 13
#define LIGHTX 14        // Light value of object vertex
#define LIGHTY 15
#define NORMR 16
#define NORMG 17
#define NORMB 18
#define PRESS 19        // Mesh vertex will increase in mass as it gets pushed in to this distance...
#define MULTIPLIER 20   // Current mass multiplier for this vertex
#define WELDSTOP 21     // Helps with welding of vertices during collisions
#define MASS 6          // Mass of scope vertex

#define R 0
#define G 1
#define B 2



// Scope stuff...
#define MAX_SCOPE_POINT          4096       // Maximum number of points allowed
#define MAX_SCOPE_CONTROL        500        // Maximum number of control points
#define MAX_SCOPE_BETWEEN        10         // Maximum number of spline points between each control (could probably be removed at this point)
#define MAX_SCOPE_SPRING         10000      // Maximum number of springs between control points, which are used to keep each control point a set distance from the previous
#define TALLY_TIMER_RESET        10         // Used to de-bounce the tally counter (so a single hit doesn't count as two)

// Camera stuff..
#define CAMERA_ROTATION_RATE  90.0f
#define CAMERA_WALK_RATE 0.5f
#define CAMERA_ZOOM_RATE 1.0f
#define SCOPE_CAMERA_ROTATION_RATE 0.35f
#define MAX_TERRAIN_DISTANCE 10000.0f
#define CAMERA_DAMPEN 0.92f


//-Variable--------------------------------------------------------------------------------------
unsigned short screen_x = 800;
unsigned short screen_y = 600;
unsigned char main_loop_active = TRUE;
unsigned char menu_open = FALSE;
unsigned char filelist_open = FALSE;
float filelist_x = 0.0f;
float menu_y = -500.0f;
unsigned char menu_active = FALSE;
unsigned char active_menu_textbox = FALSE;
unsigned short global_frame = 0;
unsigned char global_object_filename[256] = "TEST.X";
unsigned char global_settings_filename[256] = "SETTINGS.TXT";
unsigned char global_scope_length_text[256] = "150.0";
unsigned char global_load_inverted = FALSE;
unsigned char global_scope_cam = FALSE;
unsigned char global_draw_dll_text = FALSE;
unsigned char global_draw_tally_text = TRUE;
int global_animation = 0;
float global_animation_timer = 0.0f;
float global_ambient_light = 0.5f;
float global_cam_light = 1.0f;
float global_gravity = 0.0f;
int global_tally = 0;
int global_tally_timer = 0;
float global_tally_contact_time = 0.0f;
int global_tally_in_contact = FALSE;
float global_whiteout_amount = 0.0f;
float global_percent_chance_of_permanent_whiteout = 10.0f;
unsigned char global_permanent_whiteout = FALSE;
float global_whiteout_drain = 0.0f;
float global_whiteout_min_seconds = 2.0f;
float global_whiteout_max_seconds = 5.0f;

unsigned char debug_draw = FALSE;
unsigned char debug_space = FALSE;

float scope_fore_xyz[3];
float scope_up_xyz[3];
float scope_side_xyz[3];
float scope_xyz[3];


// Stuff for the scope physics...
float global_scope_stiffness = 0.25f;                   // Used for stiffener springs...
float global_scope_tip_stiffness = 0.75f;               // Used for the 3 head springs
float global_scope_turn_stiffness = 0.90f;              // Used for rotation...
float global_scope_radius = 1.0f;                       // The radius of each control point
float global_scope_weight = 0.50f;                      // The relative weight of the scope (1.0 means the scope is unaffected by the mesh, 0.0 means the mesh is unaffected by the scope)
float global_scope_length = 300.0f;                     // The overall length of the scope
float global_scope_spring_force = 0.30f;                // 
float global_scope_toothpick_force = 0.50f;             //
float global_scope_max_tip_angle = 90.0f;               //
float global_scope_dampen = 0.50f;                      //
unsigned short global_scope_between_points = 10;        // Number of subpoints on a spline segment...
unsigned short global_scope_control_points = 10;        //
float global_scope_segment_length = 0.0f;
float global_collision_xyz[3];
float global_collision_percent;
float global_testing = 0.0f;


// Stuff for the input DLL
typedef void (__stdcall *dll_setup_ptr)(void);
typedef float (__stdcall *dll_func_ptr)(void);
typedef float (__stdcall *dll_object_ptr)(int);


HINSTANCE dll_handle;
dll_setup_ptr dll_setup_memory_mapped_file;
dll_func_ptr dll_get_zin;
dll_func_ptr dll_get_zangle;
dll_func_ptr dll_get_headangle;
dll_func_ptr dll_get_degrees;
dll_func_ptr dll_get_topdown;
dll_func_ptr dll_get_whiteout_min_seconds;
dll_func_ptr dll_get_whiteout_max_seconds;
dll_func_ptr dll_get_whiteout_percent_chance;
dll_func_ptr dll_get_tally_shown;
dll_func_ptr dll_get_animation_to_start;
dll_object_ptr dll_get_object_dampen;
dll_object_ptr dll_get_object_return;
dll_object_ptr dll_get_object_spring;
dll_object_ptr dll_get_object_toothpick;
dll_object_ptr dll_get_object_weight;



unsigned char global_dll_active = FALSE;
float global_dll_previous_zin = 0.0f;
float global_dll_zin = 0.0f;
float global_dll_zangle = 0.0f;
float global_dll_headangle = 0.0f;
float global_dll_degrees = 1.0f;
float global_dll_topdown = 0.0f;
float old_dll_zangle = 0.0f;



// General textures...
unsigned int sphere_texture = 0;    // Texture for spheres
unsigned int scope_texture = 0;    // Texture for solid scope particles
unsigned int light_texture = 0;     // Texture for environment mapped lighting
unsigned int camlight_texture = 0;  // Texture for scope camera flash light
unsigned int slideon_texture = 0;    // Texture for the slider puck
unsigned int slideoff_texture = 0;    // Texture for the slider puck
unsigned int slidebar_texture = 0;
unsigned int font_texture = 0;      // Texture for fonts
unsigned int menu_texture[4] = {0, 0, 0, 0};
unsigned int button_texture[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned int whiteout_texture = 0;

unsigned int normal_texture = 0;


//-Colors----------------------------------------------------------------------------------------
unsigned char white[4] = {255, 255, 255, 255};
unsigned char red[4]   = {255,   0,   0, 128};
unsigned char green[4] = {  0, 255,   0, 128};
unsigned char blue[4]  = {  0,   0, 255, 128};
unsigned char dark[4] =  {128, 128, 128, 128};
unsigned char black[4] = {  0,   0,   0, 255};
unsigned char yellow[4] = {255, 255,   0, 255};
unsigned char entry[4] = {255, 255,   0,  64};


//-Macros----------------------------------------------------------------------------------------
#define absolute(A) { A = (A < 0) ? -A : A; }
#define repeat(A, B) for(A=0;  A<B;  A++)
#define cross_product(A, B, C) { C[X] = (A[Y]*B[Z]) - (A[Z]*B[Y]);  C[Y] = (A[Z]*B[X]) - (A[X]*B[Z]);  C[Z] = (A[X]*B[Y]) - (A[Y]*B[X]); }
#define dot_product(A, B) (A[X]*B[X] + A[Y]*B[Y] + A[Z]*B[Z])
float global_normal_length;
#define normalize(A) { global_normal_length = (float) sqrt(A[X]*A[X] + A[Y]*A[Y] + A[Z]*A[Z]); A[X]/=global_normal_length;  A[Y]/=global_normal_length;  A[Z]/=global_normal_length; }
#define vector_reflect(I, N, R) { R[Z] = I[X]*N[X] + I[Y]*N[Y] + I[Z]*N[Z];  R[Z]*=2.0f;  R[X] = I[X] - (N[X] * R[Z]);  R[Y] = I[Y] - (N[Y] * R[Z]);  R[Z] = I[Z] - (N[Z] * R[Z]); }
#define vector_tangent(I, N, T) { T[Z] = I[X]*N[X] + I[Y]*N[Y] + I[Z]*N[Z];  T[X] = I[X] - (N[X] * T[Z]);  T[Y] = I[Y] - (N[Y] * T[Z]);  T[Z] = I[Z] - (N[Z] * T[Z]); }
//-----------------------------------------------------------------------------------------------
