/*	Renegade Scripts.dll
	3D drawing related engine classes and calls for shaders.dll
	Copyright 2007 Jonathan Wilson

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/
class VertexBufferClass;
class AABTreeClass;
class DX8TextureCategoryClass;
class MeshModelClass;
class MaterialInfoClass;
class DX8FVFCategoryContainer;
class PolyRenderTaskClass;
class MatPassTaskClass;
class MeshClass;

enum ChangedStates {
	WORLD_CHANGED = 0x1,
	VIEW_CHANGED = 0x2,
	LIGHT0_CHANGED = 0x4,
	LIGHT1_CHANGED = 0x8,
	LIGHT2_CHANGED = 0x10,
	LIGHT3_CHANGED = 0x20,
	TEXTURE0_CHANGED = 0x40,
	TEXTURE1_CHANGED = 0x80,
	TEXTURE2_CHANGED = 0x100,
	TEXTURE3_CHANGED = 0x200,
	MATERIAL_CHANGED = 0x4000,
	SHADER_CHANGED = 0x8000,
	VERTEX_BUFFER_CHANGED = 0x10000,
	INDEX_BUFFER_CHANGED = 0x20000,
	WORLD_IDENTITY = 0x40000,
	VIEW_IDENTITY = 0x80000,
	TEXTURES_CHANGED = 0x3c0,
	LIGHTS_CHANGED = 0x3c,
};

struct BlendLUT {
	D3DBLEND blend;
	bool b;
};

class TextureMapperClass : public RefCountClass {
protected:
	unsigned int Stage;
public:
	enum {
		MAPPER_ID_UNKNOWN = 0x0,
		MAPPER_ID_LINEAR_OFFSET = 0x1,
		MAPPER_ID_CLASSIC_ENVIRONMENT = 0x2,
		MAPPER_ID_ENVIRONMENT = 0x3,
		MAPPER_ID_SCREEN = 0x4,
		MAPPER_ID_ANIMATING_1D = 0x5,
		MAPPER_ID_AXIAL = 0x6,
		MAPPER_ID_SILHOUETTE = 0x7,
		MAPPER_ID_SCALE = 0x8,
		MAPPER_ID_GRID = 0x9,
		MAPPER_ID_ROTATE = 0xa,
		MAPPER_ID_SINE_LINEAR_OFFSET = 0xb,
		MAPPER_ID_STEP_LINEAR_OFFSET = 0xc,
		MAPPER_ID_ZIGZAG_LINEAR_OFFSET = 0xd,
		MAPPER_ID_WS_CLASSIC_ENVIRONMENT = 0xe,
		MAPPER_ID_WS_ENVIRONMENT = 0xf,
		MAPPER_ID_GRID_CLASSIC_ENVIRONMENT = 0x10,
		MAPPER_ID_GRID_ENVIRONMENT = 0x11,
		MAPPER_ID_RANDOM = 0x12,
		MAPPER_ID_EDGE = 0x13,
		MAPPER_ID_BUMPENV = 0x14,
	};
	TextureMapperClass(unsigned int stage)
	{
		NumRefs = 1;
		if (stage < 2)
		{
			Stage = stage;
		}
		else
		{
			Stage = 1;
		}
	}
	virtual void Reset()
	{
	}
	virtual TextureMapperClass *Clone() = 0;
	virtual int Mapper_ID()
	{
		return MAPPER_ID_UNKNOWN;
	}
	virtual bool Is_Time_Variant()
	{
		return false;
	}
	virtual void Apply(int uv_array_index) = 0;
	virtual bool Needs_Normals()
	{
		return false;
	}
	~TextureMapperClass()
	{
	}
};

class FVFInfoClass {
	unsigned int FVF;
	unsigned int fvf_size;
	unsigned int location_offset;
	unsigned int normal_offset;
	unsigned int blend_offset;
	unsigned int texcoord_offset[8];
	unsigned int diffuse_offset;
	unsigned int specular_offset;
public:
	FVFInfoClass(unsigned int FVF_);
	unsigned int Get_Location_Offset()
	{
		return location_offset;
	}
	unsigned int Get_Normal_Offset()
	{
		return normal_offset;
	}
	unsigned int Get_Tex_Offset(unsigned int texture)
	{
		return texcoord_offset[texture];
	}
	unsigned int Get_Diffuse_Offset()
	{
		return diffuse_offset;
	}
	unsigned int Get_Specular_Offset()
	{
		return specular_offset;
	}
	unsigned int Get_FVF()
	{
		return FVF;
	}
	unsigned int Get_FVF_Size()
	{
		return fvf_size;
	}
	void Get_FVF_Name(StringClass& fvfname);
};

class VertexBufferLockClass {
protected:
	VertexBufferClass* VertexBuffer;
	void* Vertices;
public:
	VertexBufferLockClass(VertexBufferClass* buffer);
	void* Get_Vertex_Array()
	{
		return Vertices;
	}
};

class VertexBufferClass : public RefCountClass {
protected:
	unsigned int type;
	unsigned short VertexCount;
	int engine_refs;
public:
	FVFInfoClass* fvf_info;
	class WriteLockClass : public VertexBufferLockClass {
	public:
		WriteLockClass(VertexBufferClass* VertexBuffer);
		~WriteLockClass();
	};
	class AppendLockClass : public VertexBufferLockClass {
	public:
		AppendLockClass(VertexBufferClass* VertexBuffer,unsigned int start_index,unsigned int index_range);
		~AppendLockClass();
	};
	~VertexBufferClass();
	void Add_Engine_Ref()
	{
		engine_refs++;
	}
	void Release_Engine_Ref()
	{
		engine_refs--;
	}
	FVFInfoClass& FVF_Info()
	{
		return *fvf_info;
	}
	unsigned short Get_Vertex_Count()
	{
		return VertexCount;
	}
	unsigned int Type()
	{
		return type;
	}
	unsigned int Engine_Refs()
	{
		return engine_refs;
	}
	VertexBufferClass(unsigned int type_,unsigned int FVF,unsigned short vertex_count_);
	VertexBufferClass(unsigned int type_,unsigned short vertex_count_);
};

class DX8VertexBufferClass : public VertexBufferClass {
protected:
	IDirect3DVertexBuffer9* VertexBuffer;
public:
	enum UsageType {
		USAGE_DEFAULT = 0x0,
		USAGE_DYNAMIC = 0x1,
		USAGE_SOFTWAREPROCESSING = 0x2,
		USAGE_NPATCHES = 0x4,
	};
	IDirect3DVertexBuffer9* Get_DX8_Vertex_Buffer()
	{
		return VertexBuffer;
	}
	~DX8VertexBufferClass();
	DX8VertexBufferClass(unsigned int FVF,unsigned short vertex_count_,UsageType usage);
	DX8VertexBufferClass(unsigned short vertex_count_,UsageType usage);
	void Create_Vertex_Buffer(UsageType Usage);
};

class DeclarationVertexBufferClass : public DX8VertexBufferClass {
public:
	IDirect3DVertexDeclaration9 *VertexDecl;
	D3DVERTEXELEMENT9 *Elements;
	unsigned int ElementCount;
	unsigned int DeclarationSize;
	unsigned short location_offset;
	unsigned short normal_offset;
	unsigned short blend_offset;
	unsigned short texcoord_offset[8];
	unsigned short diffuse_offset;
	unsigned short specular_offset;
	unsigned short tangent_offset;
	bool HasNormals;
	bool HasTexCoords;
	bool HasDiffuse;
	bool HasTangents;
	unsigned int texcount;
	DeclarationVertexBufferClass(unsigned int FVF,unsigned short vertex_count_,UsageType usage);
	~DeclarationVertexBufferClass();
	void Create_Declaration_Vertex_Buffer(UsageType Usage);
};

struct VertexFormatXYZNDUV2 {
	float x;
	float y;
	float z;
	float nx;
	float ny;
	float nz;
	unsigned int diffuse;
	float u1;
	float v1;
	float u2;
	float v2;
};

struct VertexFormatXYZNDUV2Extra {
	float x;
	float y;
	float z;
	float nx;
	float ny;
	float nz;
	unsigned int diffuse;
	float u1;
	float v1;
	float u2;
	float v2;
	Vector3 Tangent;
};

class DynamicVBAccessClass {
	FVFInfoClass *FVFInfo;
	unsigned int Type;
	unsigned short VertexCount;
public:
	class WriteLockClass {
		DynamicVBAccessClass* DynamicVBAccess;
		VertexFormatXYZNDUV2* Vertices;
	public:
		WriteLockClass(DynamicVBAccessClass* dynamic_vb_access_);
		~WriteLockClass();
		VertexFormatXYZNDUV2 *Get_Formatted_Vertex_Array()
		{
			return Vertices;
		}
	};
	unsigned short VertexBufferOffset;
	VertexBufferClass* VertexBuffer;
	void Allocate_Sorting_Dynamic_Buffer();
	void Allocate_DX8_Dynamic_Buffer();
	DynamicVBAccessClass(unsigned int t,unsigned int fvf,unsigned short vertex_count_);
	~DynamicVBAccessClass();
	FVFInfoClass& FVF_Info()
	{
		return *FVFInfo;
	}
	unsigned int Get_Type()
	{
		return Type;
	}
	unsigned short Get_Vertex_Count()
	{
		return VertexCount;
	}
};

class DynamicDeclerationAccessClass {
	FVFInfoClass *FVFInfo;
	unsigned int Type;
	unsigned short VertexCount;
public:
	class WriteLockClass {
		DynamicDeclerationAccessClass* DynamicDeclerationAccess;
		VertexFormatXYZNDUV2* Vertices;
	public:
		WriteLockClass(DynamicDeclerationAccessClass* dynamic_decleration_access_);
		~WriteLockClass();
		VertexFormatXYZNDUV2 *Get_Formatted_Vertex_Array()
		{
			return Vertices;
		}
		VertexFormatXYZNDUV2Extra *Get_Formatted_Declaration_Vertex_Array()
		{
			return (VertexFormatXYZNDUV2Extra *)Vertices;
		}
	};
	unsigned short VertexBufferOffset;
	VertexBufferClass* VertexBuffer;
	void Allocate_Sorting_Dynamic_Buffer();
	void Allocate_Decleration_Dynamic_Buffer();
	DynamicDeclerationAccessClass(unsigned int t,unsigned int fvf,unsigned short vertex_count_);
	~DynamicDeclerationAccessClass();
	FVFInfoClass& FVF_Info()
	{
		return *FVFInfo;
	}
	unsigned int Get_Type()
	{
		return Type;
	}
	unsigned short Get_Vertex_Count()
	{
		return VertexCount;
	}
};

class SortingVertexBufferClass : public VertexBufferClass {
public:
	struct VertexFormatXYZNDUV2* VertexBuffer;
	~SortingVertexBufferClass();
	SortingVertexBufferClass(unsigned short VertexCount);
};

class IndexBufferClass : public RefCountClass {
	class WriteLockClass {
		IndexBufferClass* index_buffer;
		unsigned short* indices;
	public:
		WriteLockClass(IndexBufferClass* index_buffer_);
		~WriteLockClass();
		unsigned short *Get_Index_Array()
		{
			return indices;
		}
	};
	class AppendLockClass {
		IndexBufferClass* index_buffer;
		unsigned short* indices;
	public:
		AppendLockClass(IndexBufferClass* index_buffer_,unsigned int start_index,unsigned int index_range);
		~AppendLockClass();
		unsigned short *Get_Index_Array()
		{
			return indices;
		}
	};
	int engine_refs;
	unsigned short index_count;
	unsigned int type;
public:
	virtual ~IndexBufferClass();
	IndexBufferClass(unsigned int type_,unsigned short index_count_);
	void Copy(unsigned short* indices,unsigned int first_index,unsigned int count);
	void Copy(unsigned int* indices,unsigned int first_index,unsigned int count);
	unsigned short Get_Index_Count()
	{
		return index_count;
	}
	unsigned int Type()
	{
		return type;
	}
	void Add_Engine_Ref()
	{
		engine_refs++;
	}
	void Release_Engine_Ref()
	{
		engine_refs--;
	}
	unsigned int Engine_Refs()
	{
		return engine_refs;
	}
};

class DynamicIBAccessClass {
	unsigned int Type;
	unsigned short IndexCount;
public:
	unsigned short IndexBufferOffset;
	IndexBufferClass* IndexBuffer;
	void Allocate_Sorting_Dynamic_Buffer();
	void Allocate_DX8_Dynamic_Buffer();
	DynamicIBAccessClass(unsigned short type_,unsigned short index_count_);
	~DynamicIBAccessClass();
	unsigned int Get_Type()
	{
		return Type;
	}
	unsigned short Get_Index_Count()
	{
		return IndexCount;
	}
};

class DX8IndexBufferClass : public IndexBufferClass {
	enum UsageType {
		USAGE_DEFAULT = 0x0,
		USAGE_DYNAMIC = 0x1,
		USAGE_SOFTWAREPROCESSING = 0x2,
		USAGE_NPATCHES = 0x4,
	};
	IDirect3DIndexBuffer9* index_buffer;
public:
	~DX8IndexBufferClass();
	DX8IndexBufferClass(unsigned short index_count_,UsageType usage);
	void Copy(unsigned short* indices,unsigned int first_index,unsigned int count);
	void Copy(unsigned int* indices,unsigned int first_index,unsigned int count);
	IDirect3DIndexBuffer9 *Get_DX8_Index_Buffer()
	{
		return index_buffer;
	}
};

class SortingIndexBufferClass : public IndexBufferClass {
	unsigned short* index_buffer;
public:
	SortingIndexBufferClass(unsigned short index_count_);
	~SortingIndexBufferClass();
};

struct D3DPRESENT_PARAMETERS8 {
	UINT				BackBufferWidth;
	UINT				BackBufferHeight;
	D3DFORMAT			BackBufferFormat;
	UINT				BackBufferCount;
	D3DMULTISAMPLE_TYPE	MultiSampleType;
	D3DSWAPEFFECT		SwapEffect;
	HWND				hDeviceWindow;
	BOOL				Windowed;
	BOOL				EnableAutoDepthStencil;
	D3DFORMAT			AutoDepthStencilFormat;
	DWORD				Flags;
	UINT				FullScreen_RefreshRateInHz;
	UINT				FullScreen_PresentationInterval;
};

typedef D3DVIEWPORT9 D3DVIEWPORT8;

class VertexMaterialClass : RefCountClass {
public:
	D3DMATERIAL9* Material;
	unsigned int Flags;
	unsigned int AmbientColorSource;
	unsigned int EmissiveColorSource;
	unsigned int DiffuseColorSource;
	StringClass Name;
	TextureMapperClass* Mapper[2];
	unsigned int UVSource[2];
	bool UseLighting;
	unsigned int UniqueID;
	unsigned long CRC;
	bool CRCDirty;
	virtual VertexMaterialClass::~VertexMaterialClass();
};

struct D3DLIGHT8 {
	D3DLIGHTTYPE Type;
	D3DCOLORVALUE Diffuse;
	D3DCOLORVALUE Specular;
	D3DCOLORVALUE Ambient;
	D3DVECTOR Position;
	D3DVECTOR Direction;
	float Range;
	float Falloff;
	float Attenuation0;
	float Attenuation1;
	float Attenuation2;
	float Theta;
	float Phi;
};

struct RenderStateStruct {
	ShaderClass shader;
	VertexMaterialClass* material;
	TextureClass* Textures[2];
	D3DLIGHT8 Lights[4];
	bool LightEnable[4];
	Matrix4 world;
	Matrix4 view;
	unsigned int vertex_buffer_type;
	unsigned int index_buffer_type;
	unsigned short vba_offset;
	unsigned short vba_count;
	unsigned short iba_offset;
	VertexBufferClass* vertex_buffer;
	IndexBufferClass* index_buffer;
	unsigned short index_base_offset;
};

class ShaderCaps {
public:
	ShaderCaps();
	static float PixelShaderVersion;
	static float VertexShaderVersion;
	static bool DepthBiasSupported;
	static D3DCAPS9 Direct3D9Caps;
};

enum WW3DErrorType {
	WW3D_ERROR_OK = 0x0,
	WW3D_ERROR_GENERIC = 0x1,
	WW3D_ERROR_LOAD_FAILED = 0x2,
	WW3D_ERROR_SAVE_FAILED = 0x3,
	WW3D_ERROR_WINDOW_NOT_OPEN = 0x4,
	WW3D_ERROR_INITIALIZATION_FAILED = 0x5,
};

class MeshGeometryClass : public RefCountClass, public MultiListObjectClass {
public:
	ShareBufferClass<char>* MeshName;
	ShareBufferClass<char>* UserText;
	int Flags;
	char SortLevel;
	unsigned long W3dAttributes;
	int PolyCount;
	int VertexCount;
	ShareBufferClass<Vector3i>* Poly;
	ShareBufferClass<Vector3>* Vertex;
	ShareBufferClass<Vector3>* VertexNorm;
	ShareBufferClass<Vector4>* PlaneEq;
	ShareBufferClass<unsigned long>* VertexShadeIdx;
	ShareBufferClass<unsigned short>* VertexBoneLink;
	ShareBufferClass<unsigned char>* PolySurfaceType;
	Vector3 BoundBoxMin;
	Vector3 BoundBoxMax;
	Vector3 BoundSphereCenter;
	float BoundSphereRadius;
	AABTreeClass* CullTree;
	enum FlagsType {
		DIRTY_BOUNDS = 0x1,
		DIRTY_PLANES = 0x2,
		DIRTY_VNORMALS = 0x4,
		SORT = 0x10,
		DISABLE_BOUNDING_BOX = 0x20,
		DISABLE_BOUNDING_SPHERE = 0x40,
		DISABLE_PLANE_EQ = 0x80,
		TWO_SIDED = 0x100,
		ALIGNED = 0x200,
		SKIN = 0x400,
		ORIENTED = 0x800,
		CAST_SHADOW = 0x1000,
		PRELIT_MASK = 0xe000,
		PRELIT_VERTEX = 0x2000,
		PRELIT_LIGHTMAP_MULTI_PASS = 0x4000,
		PRELIT_LIGHTMAP_MULTI_TEXTURE = 0x8000,
		ALLOW_NPATCHES = 0x10000,
	};
	~MeshGeometryClass();
	virtual WW3DErrorType Load_W3D(ChunkLoadClass& cload);
	virtual void Compute_Plane_Equations(Vector4* peq);
	virtual void Compute_Vertex_Normals(Vector3* vnorm);
	virtual void Compute_Bounds(Vector3* verts);
	Vector3 *Get_Vertex_Normal_Array();
};

class DX8PolygonRendererClass : public MultiListObjectClass {
	MeshModelClass* mmc;
	DX8TextureCategoryClass* texture_category;
	unsigned int index_offset;
	unsigned int vertex_offset;
	unsigned int index_count;
	unsigned int min_vertex_index;
	unsigned int vertex_index_range;
	bool strip;
public:
	~DX8PolygonRendererClass();
};

class GapFillerClass {
public:
	Vector3i* PolygonArray;
	unsigned int PolygonCount;
	unsigned int ArraySize;
	TextureClass** TextureArray[4][2];
	VertexMaterialClass** MaterialArray[4];
	ShaderClass* ShaderArray[4];
	MeshModelClass* mmc;
};

class UVBufferClass : public ShareBufferClass<Vector2> {
public:
	unsigned int CRC;
	~UVBufferClass();
};

class TexBufferClass : public ShareBufferClass<TextureClass *> {
public:
	~TexBufferClass();
};

class MatBufferClass : public ShareBufferClass<VertexMaterialClass *> {
public:
	~MatBufferClass();
};

class MeshMatDescClass {
public:
	int PassCount;
	int VertexCount;
	int PolyCount;
	UVBufferClass* UV[8];
	int UVSource[4][2];
	ShareBufferClass<unsigned int>* ColorArray[2];
	ColorSourceType DCGSource[4];
	ColorSourceType DIGSource[4];
	TextureClass* Texture[4][2];
	ShaderClass Shader[4];
	VertexMaterialClass* Material[4];
	TexBufferClass* TextureArray[4][2];
	MatBufferClass* MaterialArray[4];
	ShareBufferClass<ShaderClass>* ShaderArray[4];
	Vector2 *Get_UV_Array_By_Index(int index, bool create);
	unsigned int *Get_Color_Array(int index, bool create);
};

class MeshModelClass : public MeshGeometryClass {
public:
	MeshMatDescClass* DefMatDesc;
	MeshMatDescClass* AlternateMatDesc;
	MeshMatDescClass* CurMatDesc;
	MaterialInfoClass* MatInfo;
	GapFillerClass* GapFiller;
	bool IsRegisteredForRendering;
	~MeshModelClass();
	WW3DErrorType Load_W3D(ChunkLoadClass& cload);
	bool Needs_Vertex_Normals();
};

class Vertex_Split_Table {
public:
	char *mc;
	MeshModelClass* mmc;
	bool npatch_enable;
	unsigned int polygon_count;
	Vector3i* polygon_array;
	bool allocated_polygon_array;
	Vertex_Split_Table(char *MeshClass);
	~Vertex_Split_Table()
	{
		delete[] polygon_array;
	}
};

class DX8TextureCategoryClass : public MultiListObjectClass {
	int pass;
	TextureClass* textures[2];
	ShaderClass shader;
	VertexMaterialClass* material;
	MultiListClass<DX8PolygonRendererClass> PolygonRendererList;
	DX8FVFCategoryContainer* container;
	PolyRenderTaskClass* render_task_head;
public:
	~DX8TextureCategoryClass();
	void Render();
};

class DX8FVFCategoryContainer : public MultiListObjectClass {
public:
	MultiListClass<DX8TextureCategoryClass> texture_category_list[4];
	MultiListClass<DX8TextureCategoryClass> visible_texture_category_list[4];
	MatPassTaskClass* visible_matpass_head;
	MatPassTaskClass* visible_matpass_tail;
	IndexBufferClass* index_buffer;
	int used_indices;
	unsigned int FVF;
	unsigned int passes;
	unsigned int uv_coordinate_channels;
	bool sorting;
	bool AnythingToRender;
	~DX8FVFCategoryContainer();
	virtual void Render() = 0;
	virtual void Add_Mesh(MeshModelClass *mmc) = 0;
	virtual void Log(bool only_visible) = 0;
	virtual bool Check_If_Mesh_Fits(MeshModelClass *mmc) = 0;
	void Generate_Texture_Categories(Vertex_Split_Table *split,unsigned int vertex_offset);
	void Render_Procedural_Material_Passes();
};

class DX8SkinFVFCategoryContainer : public DX8FVFCategoryContainer {
public:
	unsigned int VisibleVertexCount;
	MeshClass *VisibleSkinHead;
	~DX8SkinFVFCategoryContainer();
	void Render();
	void Add_Mesh(MeshModelClass* mmc);
	void Log(bool only_visible);
	bool Check_If_Mesh_Fits(MeshModelClass *mmc);
};

class DX8RigidFVFCategoryContainer : public DX8FVFCategoryContainer {
public:
	VertexBufferClass* vertex_buffer;
	int used_vertices;
	~DX8RigidFVFCategoryContainer();
	void Render();
	void Add_Mesh(MeshModelClass* mmc);
	void Log(bool only_visible);
	bool Check_If_Mesh_Fits(MeshModelClass *mmc);
};

class FontCharsClass : public RefCountClass {
	struct CharDataStruct {
		wchar_t Value;
		short Width;
		unsigned short* Buffer;
	};
	StringClass Name;
	DynamicVectorClass<unsigned short *> BufferList;
	unsigned short Buffers[32];
	int CurrPixelOffset;
	int CharHeight;
	int PointSize;
	StringClass GDIFontName;
	HFONT OldGDIFont;
	HBITMAP OldGDIBitmap;
	HBITMAP GDIBitmap;
	HFONT GDIFont;
	unsigned char* GDIBitmapBits;
	HDC MemDC;
	CharDataStruct* ASCIICharArray[256];
	CharDataStruct** UnicodeCharArray;
	wchar_t FirstUnicodeChar;
	wchar_t LastUnicodeChar;
	bool IsBold;
public:
	~FontCharsClass();
	bool Is_Font(const char *font_name,int point_size, bool is_bold);
	void Initalize_GDI_Font(const char *font_name,int point_size, bool is_bold);
	void Create_GDI_Font(const char *font_name);
	void Free_GDI_Font();
	void Free_Character_Arrays();
	void Grow_Unicode_Array(wchar_t ch);
	void Update_Current_Buffer(int char_width);
	CharDataStruct *Store_GDI_Char(wchar_t ch);
	void Blit_Char(wchar_t ch,unsigned short *dest_ptr,int dest_stride,int x,int y);
	int Get_Char_Spacing(wchar_t ch);
	int Get_Char_Width(wchar_t ch);
	CharDataStruct *Get_Char_Data(wchar_t ch);
	FontCharsClass();
	int Get_Char_Height()
	{
		return CharHeight;
	}
	char *Get_Name()
	{
		return Name.Peek_Buffer();
	}
};

class Font3DDataClass : public RefCountClass {
	char *Name;
	TextureClass *Texture;
	float UOffsetTable[256];
	float VOffsetTable[256];
	float UWidthTable[256];
	float VHeight;
	unsigned char CharWidthTable[256];
	unsigned char CharHeight;
public:
	SurfaceClass *Minimize_Font_Image(SurfaceClass *surface);
	~Font3DDataClass();
};

class Font3DInstanceClass : public RefCountClass {
	Font3DDataClass *FontData;
	float Scale;
	float SpaceSpacing;
	float InterCharSpacing;
	float MonoSpacing;
	float ScaledWidthTable[256];
	float ScaledSpacingTable[256];
	float ScaledHeight;
public:
	~Font3DInstanceClass();
};

struct QuadVertex{
	float x, y, z, rhw;
	float tu, tv;
	float su, sv;
	static const int FVF = 0x204;
};

#define D3DFVF_QUADVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX2)

class RenderQuadClass {
	ShaderClass *Shader;
public:
	RenderQuadClass();
	~RenderQuadClass();
	HRESULT Draw(float x, float y, float width, float height, float tu_scale, float tv_scale);
	HRESULT Draw(float x, float y, float width, float height, float tu_scale, float tv_scale, IDirect3DTexture9 *texture);
	HRESULT Draw(float x, float y, float width, float height, IDirect3DTexture9 *texture);
	HRESULT Draw(float x, float y, IDirect3DTexture9 *texture);
};

class MessageWindowClass {
public:
	unsigned int i1;
	void *TextWindow;
	Render2DClass r;
	RectClass rect;
	unsigned int i2;
	unsigned int i3;
	unsigned int i4;
	bool b1;
	DynamicVectorClass<WideStringClass> strings;
	DynamicVectorClass<Vector3> colors;
	void Add_Message(WideStringClass *message,Vector3 *color,GameObject *obj,float f);
};

void InitEngine3D(unsigned int exe);
void DestroyEngine3D();
extern unsigned int *render_state_changed; //Which render states are to be updated, uses ChangedStates enum
extern RenderStateStruct *render_state; //Current render state
extern unsigned int *MinTextureFilters; //texture filter values
extern unsigned int *MagTextureFilters; //texture filter values
extern unsigned int *MipMapFilters; //texture filter values
extern D3DMATERIAL9 *DefaultMaterial; //default material structure
extern bool *CurrentDX8LightEnables; //current light enables
extern bool CalculateTangents; // Set to true to enable tangent calculation (expensive)
void Draw(unsigned int primitive_type, unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, unsigned short vertex_count); //Call this to do the normal rendering pipe
void Buffers_Apply(); //Apply the vertex and index buffers
extern bool *TexturingEnabled; //Is texturing enabled
extern D3DCOLOR *AmbientColor; //current ambient color
extern RenderQuadClass *RenderQuad; // Textured Quad Drawing Class;
Vector4 GetColorVector4(D3DCOLOR color); //Converts a D3DCOLOR into a Vector4
Vector3 GetColorVector3(D3DCOLOR color); //Converts a D3DCOLOR into a Vector3
Vector3 GetColorVector3(D3DCOLORVALUE color); //Converts a D3DCOLORVALUE into a Vector3
Matrix4* Get_Projection_Matrix(); //Get the projection matrix
void Get_Projection_Matrix(Matrix4* m);
void Set_Light(int pos,D3DLIGHT8 *light); //Set a Light
void Draw_Skin(char *fvfcc); //draw skin models
void Draw_Rigid(char *fvfcc,char *MeshClass); //draw rigid models
extern ShaderCaps* TheShaderCaps; //ShaderCaps pointer
extern D3DPRESENT_PARAMETERS8 *parameters; //Presentation Parameters passed to CreateDevice and Reset
Vector3 *Get_Sky_Color(); //Get the current sky color
extern Vector3 *LightVector; //Current light vector
extern Vector3 *UnitLightVector; //Current unit light vector
extern Render2DClass **ScreenFade; //screen fade manager render2dclass
extern unsigned int *_PolygonCullMode; //current polygon culling mode
void ResetDeclerationBuffer(); //Reset the decleration vertex buffer
extern ScriptNotify Notify; //current script notify function
void AddCombatMessage(const char *message, unsigned int red, unsigned int green, unsigned int blue);
