/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

#ifndef __C4D_SHADER_H
#define __C4D_SHADER_H

#include "ge_lmatrix.h"
#include "ge_matrix.h"
#include "c4d_file.h"
#include "c4d_basetime.h"
#include "ge_prepass.h" // important

#define SHADER_RAYTRACING_EX			0x00000001	// no longer necessary
#define SHADER_REFLECTANCE				0x00000002	// shader calculates reflections
#define SHADER_TRANSPARENCY				0x00000004	// shader calculates transparency
#define SHADER_ALPHA							0x00000008	// shader calculates alpha
#define SHADER_CHANGENORMAL				0x00002000	// shader calculates bump mapping
#define SHADER_DISPLACE						0x00004000	// shader calculates displacement mapping
#define SHADER_ENVREQUIRED				0x00100000	// shader needs environment reflection data
#define SHADER_DUDVREQUIRED				0x00200000	// shader needs du/dv bump mapping data
#define SHADER_MIPSAT							0x02000000	// shader requires MIP/SAT data
#define SHADER_VOLUMETRIC					0x20000000	// shader is a volumetric shader
#define SHADER_ASYNC_EX						0x01000000	// shader dialog is asynchronous
#define SHADER_TRANSFORM					0x00000010	// shader needs back-transformed data
#define SHADER_TRANSFORM_N				0x00000020	// shader needs back-transformed normal
#define SHADER_EVALUATEPROJECTION	0x04000000	// shader requires texture tag projections
#define SHADER_INITCALCULATION		0x80000000  // shader needs initcalculation call

#define CHANNEL_RAYTRACING_EX			0x00000001	// no longer necessary
#define CHANNEL_DIRECTBUMP_EX			0x00000002	// channel shader does direct bump evaluation (obsolete)
#define CHANNEL_TRANSFORM					0x00000004	// channel shader needs back-transformed data
#define CHANNEL_TRANSFORM_N				0x00000008	// channel shader needs back-transformed normal
#define CHANNEL_BUMP_SUPPORT			0x00000010  // channel shader supports new bump system (strongly recommended for all shaders but simple 2d (UV) samplers)
#define CHANNEL_ALPHA_SUPPORT		  0x00000020  // channel shader supports alpha output

#define TEX_TILE							0x01				// texture tile enabled
#define TEX_MIRROR						0x02				// texture mirroring enabled
#define TEX_ALPHA							0x04				// texture uses alpha channel (for use within channel shaders)
#define TEX_BUMP							0x08				// bump calculation

#define GET_TEX_BUMP_SAMPLE(texflag) (((texflag)>>4)&3)
#define GET_TEX_CHANNEL(texflag) (((texflag)>>6)&15)

inline LONG CALC_TEXINFO(LONG texflag, LONG channel) { return (texflag&~0x3f0)|(channel<<6); }
inline LONG CALC_TEXINFO_BUMP(LONG texflag, LONG channel, LONG sample) { return (texflag&~0x3f0)|((sample&3)<<4)|(channel<<6); }

#define SAMPLEBUMP_MIPFALLOFF	(1<<0)

#define INIT_SURFACE					0
#define INIT_TRANSPARENCY			1
#define INIT_DISPLACEMENT			3

#define RAY_REFLECTION					(1<<0)			// ray chain contains a reflection ray
#define RAY_TRANSPARENCY				(1<<1)			// ray chain contains a transparency ray (note: refractions are not contained)
#define RAY_REFRACTION					(1<<2)			// ray chain contains a refraction ray
#define RAY_CUSTOM							(1<<3)			// ray chain contains a custom ray

#define RAY_CURR_REFLECTION			(1<<4)			// current ray is a reflection ray
#define RAY_CURR_TRANSPARENCY		(1<<5)			// current ray is a transparency ray
#define RAY_CURR_REFRACTION			(1<<6)			// current ray is a refraction ray
#define RAY_CURR_CUSTOM					(1<<7)			// current ray is a custom ray

#define RAY_VOLUMETRICLIGHT			(1<<8)			// current ray is used to calculate a volumetric light
#define RAY_ALLOWVLMIX					(1<<9)			// custom mixing of visible light sources allowed for this ray; bit must be deleted by shader if used

#define RAY_DIFFUSE_GI					(1<<10)			// current ray is a GI ray
#define RAY_BLURRY							(1<<11)			// current ray is a blurry ray
#define RAY_SSS									(1<<12)			// current ray is a subsurface ray

#define RAY_CURR_AO           	(1<<13)     // current ray is an AO ray

class  CDialog;
class  HyperFile;
class  BaseChannel;
class  BaseDocument;
class  BaseObject;
class  BaseTag;
class  BaseDraw;
class  BaseDrawHelp;
class  BaseThread;
class  Filename;
class  String;
class  BaseView;
class  BaseContainer;
struct RayLight;
struct RayObject;
struct VolumeData;

// channels
#define MAXCHANNELS						14 // channels in C4D material
#define CHANNEL_ANY						-1 // unlabeled plugin channel

#define CHANNEL_COLOR					 0
#define CHANNEL_LUMINANCE			 1
#define CHANNEL_TRANSPARENCY	 2
#define CHANNEL_REFLECTION		 3
#define CHANNEL_ENVIRONMENT		 4
#define CHANNEL_FOG						 5
#define CHANNEL_BUMP					 6
#define CHANNEL_ALPHA					 7
#define CHANNEL_SPECULAR			 8
#define CHANNEL_SPECULARCOLOR	 9
#define CHANNEL_GLOW					10
#define CHANNEL_DISPLACEMENT	11
#define CHANNEL_DIFFUSION			12
#define CHANNEL_NORMAL				13

#define BASECHANNEL_COLOR_EX					1000  // VECTOR
#define BASECHANNEL_BRIGHTNESS_EX			1001  // REAL
#define BASECHANNEL_MIXMODE_EX   			1006	// LONG
#define BASECHANNEL_MIXSTRENGTH_EX		1007	// REAL

#define BASECHANNEL_TEXTURE      			1002  // STRING
#define BASECHANNEL_BLUR_OFFSET  			1003	// REAL
#define BASECHANNEL_BLUR_STRENGTH			1004	// REAL
#define BASECHANNEL_INTERPOLATION			1005	// LONG
#define BASECHANNEL_TIME_FROM    			1008	// LONG
#define BASECHANNEL_TIME_TO      			1009	// LONG
#define BASECHANNEL_TIME_FPS     			1010	// LONG
#define BASECHANNEL_TIME_MODE    			1011	// LONG
#define BASECHANNEL_TIME_TIMING  			1012	// LONG
#define BASECHANNEL_TIME_START   			1013	// BASETIME
#define BASECHANNEL_TIME_END     			1014	// BASETIME
#define BASECHANNEL_TIME_LOOPS   			1015	// LONG
#define BASECHANNEL_SHADERID					1016  // LONG
#define BASECHANNEL_SUGGESTEDFOLDER		1017	// FILENAME

#define INITRENDERFLAG_TEXTURES				(1<<0)
#define INITRENDERFLAG_PAINTERNOMIP		(1<<1)
#define INITRENDERFLAG_NOMIP					(1<<2)
#define INITRENDERFLAG_PREVIEWRENDER	(1<<3)

struct InitRenderStruct
{
	InitRenderStruct(void)
	{
		version=0;
		fps=30;
		docpath=NULL;
		errorlist=NULL;
		matname=NULL;
		vd=NULL;
		doc=NULL;
		thread=NULL;
		flags=INITRENDERFLAG_TEXTURES;
	}

	LONG					version;
	BaseTime			time;
	LONG					fps;
	Filename			*docpath;
	String				*matname;
	void					*errorlist;
	VolumeData		*vd;
	BaseDocument	*doc;
	BaseThread		*thread;
	LONG					flags;
};

// TexData::side
#define SIDE_FRONT_AND_BACK	0
#define SIDE_FRONT					1
#define SIDE_BACK						2

// texture information, read-only
struct TexData
{
	private:
		TexData();
		~TexData();
	public:
		Matrix			m,im;
		CHAR				texflag;
		CHAR				additive,proj,side;
		LONG				restrict;
		Real				ox,oy,lenx,leny;
		GeListNode	*mp;
		LONG				uvwind;
		BaseView		*camera;
		CHAR				uvbump;
		BaseTag			*link;

	static TexData *Alloc();
	static void Free(TexData *&td);
	void Init(void);
};

// ray structure
struct Ray
{
	// read and write
	LVector p,v;			// ray position and vector
	Real		ior;			// current index of refraction
	Vector	pp[3];		// 3 additional ray points for MIP-Mapping
	Vector	vv[3];		// 3 additional ray vectors for MIP-Mapping

	// read-only
	Vector	transport; // current intensity (for special shadow calculation)
};

// intersection structure
struct SurfaceIntersection
{
	SurfaceIntersection() : p(DC), n(DC) {}

	RayObject	*op;					// intersected object
	LONG			gid;					// global hit ID
	LVector 	p,n;					// point and normal
	LONG			sid;					// sub ID, only used for SPD
	Real			par_u,par_v;	// barycentric coordinates, only used for SPD
};

class VPBitmap;

struct Multipass
{
	VPBitmap	**bmp;
	LONG			*ind;
	Real			*result;
	LONG			cnt,cmp;

	Vector		**diffuse;
	LONG			diffuse_cnt;

	Vector		**specular;
	LONG			specular_cnt;

	Vector		**shadow;
	LONG			shadow_cnt;

	RayLight	**light;
	LONG			light_cnt;

	Real			**ochannel;
	LONG			*ochannelid;
	LONG			ochannel_cnt;

	Vector		*vp_ambient,*vp_diffuse,*vp_specular,*vp_shadow,*vp_reflection,*vp_transparency;
	Vector		*vp_radiosity,*vp_caustics,*vp_illumination;
	Vector		*vp_mat_color,*vp_mat_luminance,*vp_mat_transparency,*vp_mat_reflection;
	Vector		*vp_mat_environment,*vp_mat_specularcolor,*vp_atmosphere;
	Real			*vp_depth,*vp_mat_specular,*vp_mat_diffusion,*vp_atmosphere_mul;
	Vector		*vp_ambientocclusion,*vp_mat_uv,*vp_mat_normal,*vp_motionvector;
};

// main volume shader structure
struct BaseVolumeData
{
	protected:
		BaseVolumeData(void);
	public:
		// read-only
		LONG				version;	// version number of structure
		LONG				fps;			// frames per second
		Vector			ambient;	// global ambient component
		Real				time;			// current time in seconds

		// read and write
		// returnable data: color, transparency, reflection, genlock colour, transparent and reflectant ray, point and normal
		Vector			col;							// set the calculated color here
		Vector			trans;						// set the calculated transparency here
		Vector			refl;							// set the calculated reflection here
		Real				alpha;						// set the calculated alpha here
		Ray					*tray,*rray;			// read and write the transparency/reflection rays; NEVER change the pointers
		Vector			p;								// surface point - may only be modified by Displace
		Vector			bumpn;						// surface phong & bump normal

		// read-only
		Ray					*ray;							// current eye ray
		Vector			orign;						// original surface normal
		Vector			n;								// surface phong normal
		Vector			dispn;						// suggested displacement direction
		Vector			uvw;							// surface uvw coordinates - INVALID for volumetric shaders
		Vector			delta;						// MIP sample radius
		Real				dist;							// distance from eye to surface point
		LONG				lhit;							// surface identity
		TexData			*tex;							// surface texture, NEVER change pointer
		Real				cosc;							// angle beween ray vector and unbumped normal
		Vector			ddu,ddv;					// bump mapping basis vectors
		LONG				raydepth;					// depth of actual ray

		LONG				calc_trans;				// specifies, if transparency shall be rendered
		LONG				calc_refl;				// specifies, if reflections shall be rendered
		LONG				calc_shadow;			// specifies, if shadows shall be rendered
		LONG				calc_illum;				// specifies, if illumination shall be rendered
		LONG				calc_mip;					// specifies, if mip calculations shall be done

		Vector			pp[3];						// MIP corner points in global space
		Vector			nn[3];						// MIP normals of the three other corner points

		LONG				raybits;					// ray information
		RayLight		*xlight;					// lightsource during shadow evaluation
		RayObject		*op;							// object

		// read and write
		LONG				recursion_id;			// plugin ID of data passed through recursion
		void				*recursion_data;	// address of data passed through recursion
		Multipass   *multipass;				// to be filled for multipasses

		// read only
		Vector			back_p;						// set SHADER_TRANSFORM   (CHANNEL_TRANSFORM  ) to access this value
		Vector			back_delta;				// set SHADER_TRANSFORM   (CHANNEL_TRANSFORM  ) to access this value; local space
		Vector			back_orign;				// set SHADER_TRANSFORM_N (CHANNEL_TRANSFORM_N) to access this value
		Vector			back_n;						// set SHADER_TRANSFORM_N (CHANNEL_TRANSFORM_N) to access this value

		Real				global_mip;				// global MIP scale

		LONG				sid;							// subpolygon information: subpolygon and barycentric coordinates
		Real				par_u,par_v;
};

// main channel shader structure
struct ChannelData
{
	ChannelData() { }
	ChannelData(BaseVolumeData *t_vd) : p(t_vd->uvw), n(t_vd->n), d(t_vd->delta) { t=t_vd->time; texflag=0; vd=(VolumeData*)t_vd; off=0.0; scale=t_vd->global_mip; }

	// read-only
	Vector			p;					// texture position in UVW coordinates
	Vector			n;					// surface normal
	Vector			d;					// MIP sample radius in UVW coordinates
	Real				t;					// current time in seconds
	LONG				texflag;		// texture flags
	VolumeData	*vd;				// pointer to volume information, can be NULL
	Real				off,scale;	// blur offset and scale 
};

#define MSG_SETDATA					112000
#define MSG_GETDATA					112001
#define MSG_GETALLSTRINGS		112004
#define MSG_SHADERV5TOV6		112005
#define MSG_SHADERV6TOV7		112006
#define MSG_SHADERREAD			112009
#define MSG_RENAMETEXTURES	112010

class RootTextureString;

struct GetAllStringData
{
	GetAllStringData(BaseDocument *t_doc, RootTextureString *t_rts, LONG t_flags)
	{
		doc				= t_doc;
		rs        = t_rts;
		flags     = t_flags;
	}

	BaseDocument			*doc;
	RootTextureString *rs;
	LONG							flags;
};

struct RenameTextureMessage
{
	Filename oldname;
	Filename newname;
	BaseDocument *doc;
	LONG changecnt;
};

struct VPFragment
{
	LONG				id;
	UCHAR 			subx,suby;
	WORD 				weight;
	RayObject		*op;
	
	Vector			color;

	Real				z;
	Vector			p;
	Vector			n;
	
	VPFragment	*next;
};

struct ShaderReadData
{
	HyperFile			*hf;
	LONG					oldid;
	Real					*data;
	LONG					oldlevel;
	BaseContainer	*oldctr;
};

#endif
