#define MGML_GUARDIAN

//#define DRIVER_BUGS

#pragma warning(disable:4996) // Заткнись


#ifndef __CUDACC__

//	#include <d3d9.h> 
	#include <string>
	#include <vector>
	#include <list>
	#include <map>
	#include <fstream>
	#include <algorithm>
	#include <windows.h>
	#include <glut.h>  

#else

typedef unsigned int UINT;
typedef unsigned char BYTE;

#define _RDTSC(ts) \
		__asm rdtsc \
		__asm mov DWORD PTR [ts], eax \
		__asm mov DWORD PTR [ts+4], edx

#endif

typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char BYTE;

typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long int uint64;

#ifndef MGML_MATH_GUARDIAN
	#include "MGML_MATH.h"
#endif

// if you want to disable SIMD operations just comment that
#ifndef __CUDACC__
	#ifndef MGML_MATH_SIMD_GUARDIAN
		#include "MGML_MATH_SIMD.h"
	#endif
#else
	#ifndef MGML_MATH_CUDA_SIMD_GUARDIAN
		#include "MGML_MATH_CUDA_SIMD.h" 
	#endif
#endif

#ifndef MGML_MATH_INTERSECTIONS_GUARDIAN
	#include "MGML_MATH_INTERSECTIONS.h"
#endif

#ifndef MGML_GRAPHICS
	#include "MGML_GRAPHICS.h" 
#endif


#ifndef __CUDACC__
  //#include "MGML_MESH.h"

	#ifndef MGML_IMAGE_GUARDIAN
		#include "MGML_IMAGE.h"
	#endif

  #include "shared_ptr.h"

#endif



namespace IMAGES
{
	class IMAGE;
};



namespace MGML
{

	typedef MGML_MATH::VECTOR<2,float> vec2f;
	typedef MGML_MATH::VECTOR<3,float> vec3f;
	typedef MGML_MATH::VECTOR<4,float> vec4f;

	typedef MGML_MATH::VECTOR<2,double> vec2d;
	typedef MGML_MATH::VECTOR<3,double> vec3d;
	typedef MGML_MATH::VECTOR<4,double> vec4d;

	typedef MGML_MATH::VECTOR<2,int> vec2i;
	typedef MGML_MATH::VECTOR<3,int> vec3i;
	typedef MGML_MATH::VECTOR<4,int> vec4i;

	typedef MGML_MATH::VECTOR<2,UINT> vec2ui;
	typedef MGML_MATH::VECTOR<3,UINT> vec3ui;
	typedef MGML_MATH::VECTOR<4,UINT> vec4ui;

	typedef MGML_MATH::VECTOR<2,unsigned char> vec2ub;
	typedef MGML_MATH::VECTOR<3,unsigned char> vec3ub;
	typedef MGML_MATH::VECTOR<4,unsigned char> vec4ub;

	typedef MGML_MATH::MATRIX<2,2,float>  Matrix2x2f;
	typedef MGML_MATH::MATRIX<3,3,float>  Matrix3x3f;
	typedef MGML_MATH::MATRIX<3,4,float>  Matrix3x4f;
	typedef MGML_MATH::MATRIX<4,3,float>  Matrix4x3f;
	typedef MGML_MATH::MATRIX<4,4,float>  Matrix4x4f;

	typedef MGML_MATH::QUATERNION<float>  quatf;
	typedef MGML_MATH::QUATERNION<double> quatd;
	typedef MGML_MATH::QUATERNION<int>    quati;
 
	typedef MGML_MATH::LINE<3,float>	    Line3f;
	typedef MGML_MATH::LINE<4,float>	    Line4f;

	typedef MGML_MATH::RAY<4,float>	      Ray4f;
	typedef MGML_MATH::RAY<3,float>	      Ray3f;

	typedef MGML_MATH::SEGMENT<4,float>	  Segment4f;
	typedef MGML_MATH::SEGMENT<3,float>	  Segment3f;

  typedef MGML_MATH::SPHERE<3,float>	  Sphere3f;
	typedef MGML_MATH::SPHERE<4,float>	  Sphere4f;

  typedef MGML_MATH::PACKED_SPHERE3<float>  PackedSphere3f;
	typedef MGML_MATH::PACKED_SPHERE3<double> PackedSphere3d;

	typedef MGML_MATH::AABB<4,float>	    AABB4f;
	typedef MGML_MATH::AABB<3,float>	    AABB3f;
	typedef MGML_MATH::BOX<4,float>			  Box4f;
	typedef MGML_MATH::BOX<3,float>			  Box3f;

	typedef MGML_MATH::PLANE<3,float>	    Plane3f;
	typedef MGML_MATH::PLANE<4,float>	    Plane4f;

	typedef MGML_MATH::TRIANGLE<3,float>  Triangle3f;
	typedef MGML_MATH::TRIANGLE<4,float>  Triangle4f;

	typedef MGML_GRAPHICS::VERTEX<3,float>  Vertex3f;
	typedef MGML_GRAPHICS::VERTEX<4,float>  Vertex4f;

  typedef MGML_GRAPHICS::VERTEX<3,double> Vertex3d;
	typedef MGML_GRAPHICS::VERTEX<4,double>	Vertex4d;

	typedef MGML_GRAPHICS::VERTEX<3,int>	 Vertex3i;
	typedef MGML_GRAPHICS::VERTEX<4,int>	 Vertex4i;

	typedef MGML_GRAPHICS::Material Material;
	typedef MGML_GRAPHICS::Triangle Triangle;

	typedef MGML_GRAPHICS::Point_Light<4,float>    PointLight;
	typedef MGML_GRAPHICS::Infinite_Light<4,float> InfiniteLight;
	typedef MGML_GRAPHICS::Spot_Light<4,float>     SpotLight;
	typedef MGML_GRAPHICS::Sphere_Light<4,float>   Sphere_Light;
	typedef MGML_GRAPHICS::Flat_Light<4,float>     Flat_Light;

	typedef MGML_GRAPHICS::D3D_HAL		D3D_HAL;	
	typedef MGML_GRAPHICS::OpenGL_HAL	OpenGL_HAL;

	//typedef MGML_GRAPHICS::MESH<4,float,OpenGL_HAL> Mesh;

	typedef IMAGES::IMAGE	            Image;
    
	/*
	typedef MGML_GRAPHICS::MESH<4,
								float,
								MGML_GRAPHICS::OpenGL_HAL,
								Triangle>		Mesh;
	 */

#ifndef __CUDACC__

	inline universal_call vec3f to_vec3f(const vec4f& rhs)
	{
		return vec3f(rhs.M[0],rhs.M[1],rhs.M[2]);
	}

#else

  inline universal_call vec3f to_vec3f(const vec4f& rhs)
	{
    vec3f res;
    res.set(rhs.M[0],rhs.M[1],rhs.M[2]);
		return res;
	}
#endif

	#ifdef __CUDACC__
	
	inline universal_call vec3f make_vec3f(float x,float y,float z, vec3f& v)
	{
		v[0] = x;
		v[1] = y;
		v[2] = z;
		return v;
	}

	inline universal_call vec2f make_vec2f(float x, float y, vec2f& v)
	{
		v[0] = x;
		v[1] = y;
		return v;
	}


	#endif

};





///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace MGML_TESTS
{
#ifndef __CUDACC__

 void test_all(std::ostream& out);
 void test_mgml_types_sizes(std::ostream& out);
 void test_mgml_mat_vec_op(std::ostream& out);
 void test_mgml_vec_func(std::ostream& out);
 void test_operators(std::ostream& out);
 void test_kd_tree(std::ostream& out);

 

#endif
};