/*======================================================================*/
/* 3DLib								*/
/*									*/
/* Materials header file						*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Dec-31 23:14:10					*/
/*									*/
/* 3DLib(TM) Copyright (C) 1995 by Gabor Nagy. All rights reserved.	*/
/*======================================================================*/
#ifndef _E3DMaterial_h
#define _E3DMaterial_h


#ifndef _E3DMatrix_h
#include <E3D/Matrix.h>
#endif

#ifndef _E3DTexture_h
#include <E3D/Texture.h>
#endif


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif



//------------------------------------------------------------------------
// Material types
//------------------------------------------------------------------------
enum
{
 E3dMAT_NONE=0,		// Material is not active
 E3dMAT_LIGHTSOURCE,
 E3dMAT_FLAT,
 E3dMAT_BLINN,
 E3dMAT_PHONG,
 E3dMAT_LAMBERT,
 E3dMAT_INFINITE_LIGHT,
 E3dMAT_CONSTANT,
 E3dMAT_SHADOW,
 E3dMAT_CUSTOM
};


// Material color flags
//
#define E3dAMBIENT_COLOR	0x0001
#define E3dDIFFUSE_COLOR	0x0002
#define E3dSPECULAR_COLOR	0x0004
#define E3dREFLECTIVE_COLOR	0x0008
#define E3dEMISSION_COLOR	0x0010
#define E3dTRANSPARENT_COLOR	0x0020
#define E3dABSORPTION_COLOR	0x0040



// Blending functions
//
enum
{
 E3dBLENDF_NONE=0,
 E3dBLENDF_ONE_ZERO,
 E3dBLENDF_ONE_ONE,
 E3dBLENDF_ONE_ONE_MINUS_SRC_ALPHA
};


#define E3dBLENDF_NOT_SET	0xFFFFFFFF

#ifndef _E3dLight
#define _E3dLight
typedef struct E3dLight_S	E3dLight;
#endif


#ifndef _E3dShader
#define _E3dShader
typedef struct E3dShader_S	E3dShader;		// Forward-define E3dShader
#endif

#ifndef _E3dMaterial
#define _E3dMaterial
typedef struct E3dMaterial_S	E3dMaterial;		// Forward-define E3dMaterial
#endif

#ifndef _E3dScene
#define _E3dScene
typedef struct E3dScene_S	E3dScene;		// Forward-define E3dScene
#endif

// Generic ShaderProc for Edit and Destroy
//
typedef int	(*E3dShaderProc)(E3dShader*);

// Position, Normal, Lights, NumOfLights, ColorReturn
// 
typedef int	(*E3dShaderSurfaceProc)(E3dScene*, E3dSurfacePoint*, E3dMaterial*, EcRGBAfColor*);



#ifndef _E3dRay
#define _E3dRay
typedef struct E3dRay_S	E3dRay;				// Forward-define E3dRay
#endif


// Ray (origin, direction, travelled length), Lights, NumOfLights, ColorReturn
//
typedef int	(*E3dShaderVolumeProc)(E3dScene*, E3dRay*, EcRGBAfColor*);


#ifndef _E3dGeometry
#define _E3dGeometry
typedef struct E3dGeometry_S	E3dGeometry;		// Forward-define E3dGeometry
#endif


// Geometry to draw, LocalToWorldMatrix, WorldToViewerMatrix, DisplayFlags
//
typedef int	(*E3dShaderGLDrawProc)(E3dScene*, E3dModel*, E3dGeometry*, int, E3dMatrix, unsigned int);


#define E3dShaderClassCore()\
 char*			Name;\
 unsigned int		StructSize;\
 E3dShaderProc		EditProc;\
 E3dShaderProc		DestroyProc;\
 E3dShaderSurfaceProc	SurfaceProc;\
 E3dShaderVolumeProc	VolumeProc;\
 E3dShaderGLDrawProc	GLDrawProc;\
 unsigned int		ColorsUsed;\
 EResource*		Resources

typedef struct
{
 E3dShaderClassCore();
} E3dShaderClass;


#define E3dShaderCore()\
 int			RefCnt;\
 E3dShaderClass*	Class


struct E3dShader_S
{
 E3dShaderCore();
};



#ifdef USEOpenGL
typedef struct
{
 float		Ambient[4];
 float		Diffuse[4];
 float		Specular[4];
 float		Emission[4];
 float		Shininess[1];
 EcRGBAp8Color	FlatColor;
 int		Type;
 int		BlendingFunction;

// E3d2DTexture*	Texture0;
} E3dGLMaterial;
#endif // USEOpenGL


struct E3dMaterial_S
{
 char*			Name;
 unsigned int		RefCnt;				// Reference count
 char			Type;

#ifdef USEOpenGL
 E3dGLMaterial		GLMaterial;
 E3dGLMaterial		GL2DTextureMaterial;
#endif // USEOpenGL

 E3dShader*		Shader;				// Custom shader

 EcRGBfColor		Ambient;
 EcRGBfColor		Diffuse;
 EcRGBfColor		Specular;
 EcRGBfColor		Emission;
 EcRGBfColor		Reflective;			// Reflective color
 EcRGBfColor		Transparent;			// The Material "lets this color through"
 EcRGBfColor		Absorption;			// A ray travelling in this Material will be attenuated by this, multiplied the square of the distance travelled by the ray

 float			Specularity;			// Specular exponent for phong-shading
 float			Reflectivity;
 float			Transparency;
 float			RefractiveIndex;
 float			Glow;
 unsigned int		NumOf2DTextures;
 int			Current2DTextureIndex;		// For editing
 E3d2DTexture**		Textures2D;
 unsigned int		NumOf3DTextures,
			Current3DTextureIndex;		// For editing
 E3d3DTexture**		Textures3D;

// Internal data used by EQUINOX-3D
//
 E3d3DPosition		SchemTranslation;		// Parent-relative position on schematic view
 E3d3DPosition		SchemPosition;			// World-relative position on schematic view
 void*			Sample;				// Material sample (little icon with name etc. in the lister)
};





//----------------------------------------------------------------
// Global variables & structures
//----------------------------------------------------------------
extern E3dShaderClass**	E3d_ShaderClasses;
extern int		E3d_NumOfShaderClasses;


extern E3dMaterial	E3d_DefaultMaterial;
extern E3d2DTexture	E3d_Default2DTexture;
extern E3d2DTexture*	E3d_Default2DTextureArray[1];
extern E3d3DTexture	E3d_Default3DTexture;
extern E3d3DTexture*	E3d_Default3DTextureArray[1];

extern E3dMaterial	E3d_PlasterMaterial;

//----------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------
extern void		E3d_PrintMaterial(E3dMaterial* LMaterial);

extern void		E3d_MaterialDefault(E3dMaterial* LMaterial);
extern E3dMaterial*	E3d_MaterialAllocate();

extern void		E3d_MaterialCopyContents(E3dMaterial* LSrcMaterial, E3dMaterial* LDstMaterial);

extern E3dMaterial**	E3d_MaterialsAllocate(unsigned int LMaterialNum);
extern void		E3d_MaterialFree(E3dMaterial* LMaterial);
extern void		E3d_MaterialsFree(E3dMaterial** LMaterials, unsigned int LCount);

extern E3d2DTexture*	E3d_MaterialAdd2DTexture(E3dMaterial* LMaterial);
extern void		E3d_MaterialAppend2DTexture(E3dMaterial* LMaterial, E3d2DTexture* L2DTexture);
extern void		E3d_MaterialRemove2DTexture(E3dMaterial* LMaterial, E3d2DTexture* L2DTexture);

extern void		E3d_MaterialUpdateForDisplay(E3dMaterial* LMaterial);


extern E3dShader*	E3d_ShaderAllocate(E3dShaderClass* LClass);
extern void		E3d_ShaderFree(E3dShader* LShader);

extern E3dShaderClass*	E3d_ShaderClassFindByName(char* LName);
extern E3dShaderClass*	E3d_ShaderClassRegister(E3dShaderClass* LTemplate);
extern E3dShaderClass*	E3d_ShaderClassRegisterInactive(char* LName, unsigned int LStructSize);
extern void		E3d_ShaderClassDeactivate(E3dShaderClass* LShader);
extern void		E3d_ShaderClassRemove(E3dShaderClass* LShader);



#ifdef USEOpenGL
extern void		E3d_MaterialConvertToGL(E3dMaterial* LMaterial);
extern void		E3d_MaterialDefineGL(E3dGLMaterial* LGLMaterial);
#endif // USEOpenGL


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration which encloses file.
#endif

#endif	// _E3DMaterial_h
