/////////////////////////////////////////////////////////////
// CINEMA SDK : RENDERING        													 //
/////////////////////////////////////////////////////////////
// VERSION    : CINEMA 4D																	 //
/////////////////////////////////////////////////////////////
// (c) 1989-2002 MAXON Computer GmbH, all rights reserved	 //
/////////////////////////////////////////////////////////////

// radiosity hook
/*
#include "c4d.h"
#include "c4d_symbols.h"

class GIData : public VideoPostData
{
	public:
		Vector				scene_min,scene_max;
		RayParameter	*rp;

		virtual LONG Execute(PluginVideoPost *node, VideoPostStruct *vps);
		static NodeData *Alloc(void) { return gNew GIData; }
};

static void FlushGI(VideoPostData *s)
{
	GIData *dat = (GIData*)s;
}

LONG GIData::Execute(PluginVideoPost *node, VideoPostStruct *vps)
{
	if (vps->vp==VP_FRAMESEQUENCE && !vps->open) { FlushGI(this); return RAY_OK; }
	if (vps->vp==VP_INNER && vps->open)
	{
		MinMax mm = vps->vd->GetSceneBoundaries();
		scene_min = mm.GetMin();
		scene_max = mm.GetMax();
		rp			  = vps->vd->GetRayParameter();
	}

	return RAY_OK;
}

struct RecursionData
{
	LONG diffuse_level;
};

static Vector	ComputeDiffuseIllumination(VideoPostData *data, VolumeData *vd, Real receive_strength, Real accuracy)
{
	LONG						reshit;
	Vector					col;
	LVector					resp,resn;
	Ray							r;
	RecursionData		rd,*parent=NULL;
	GIData					*dat = (GIData*)data;

	if (vd->recursion_id==C4D_RADIOSITY_ID) // if ray was started within this routine
	{
		parent=(RecursionData*)vd->recursion_data; // retrieve data
		if (parent->diffuse_level>=dat->rp->gi_maxdiffusedepth) return 0.0; // check if maximum diffuse level has been exceeded; if yes, return 0.0
		rd.diffuse_level=parent->diffuse_level+1; // increase raydepth for next ray
	}
	else
		rd.diffuse_level=1; // ray comes from C4D, so start with the first depth level

	// TraceColorDirect needs a VolumeData to operate on. This must NOT be vd, as it will be modified in TraceColor(Direct).
	// So a VolumeData is allocated. This is SLOW though as it generates a memory request for every recursion level. We have
	// to think about optimizations here after getting it to work!
	VolumeData *cpy = VolumeData::Alloc();
	if (!cpy) return 0.0;
	vd->CopyTo(cpy); // copy vd settings into cpy

	r.ior=vd->ray->ior; // medium has not changed, keep index of refraction
	r.p=LV(vd->p); // use intersection point as start of ray
	r.v=ReflectRay(&vd->ray->v,&vd->bumpn); // reflect ray (this is a test, no real GI model :-))

	r.pp[0]=r.pp[1]=r.pp[2]=vd->p; // set pp/vv components to p/v as we don't need MIP mapping for GI
	r.vv[0]=r.vv[1]=r.vv[2]=SV(r.v);

	r.transport=vd->ray->transport*0.8; // modify transported energy (vector). as an example 80% of the energy passes

	cpy->recursion_id   = C4D_RADIOSITY_ID; // set plugin ID
	cpy->recursion_data = &rd;              // set custom data adress that is passed on to the next recursion level. the data has to be on stack or allocated!

	// calculate result color for ray with unlimited travel distance
	// avoid self intersection with already intersected polygon (through passing vd->lhit)
	col = cpy->TraceColorDirect(&r,MAXREAL,vd->raydepth+1,vd->raybits|RAY_DIFFUSE_GI,vd->lhit,&resp,&resn,&reshit);

	VolumeData::Free(cpy); // free copied data

	return col*0.5; // return 50% of color (as an example)
}

static Bool	LoadGI(VideoPostData *data, BaseFile *file, LONG level)
{
	LONG l;
	file->ReadLong(&l);

	if (l!='GLOB')
		GePrint("Oops... something's wrong");

	return TRUE;
}

static Bool SaveGI(VideoPostData *data, BaseFile *file)
{
	file->WriteLong('GLOB');
	return TRUE;
}



class CSData : public VideoPostData
{
	public:
		Vector	col;
		LONG		ls_cnt;

		virtual LONG Execute(PluginVideoPost *node, VideoPostStruct *vps);
		static NodeData *Alloc(void) { return gNew CSData; }
};

static void FlushCS(VideoPostData *s)
{
	CSData *dat = (CSData*)s;
}

LONG CSData::Execute(PluginVideoPost *node, VideoPostStruct *vps)
{
	if (vps->vp==VP_FRAMESEQUENCE && !vps->open) { FlushCS(this); return RAY_OK; }
	if (vps->vp==VP_INNER && vps->open)
	{
		LONG i;

		col			= 1.0;
		ls_cnt  = vps->vd->GetLightCount();

		for (i=0; i<ls_cnt; i++)
		{
			RayLight *ls = vps->vd->GetLight(i);
			if (ls->lc->cs_enable)
			{
				// prepass for lightsource
				// update progress bar, test for user break

				Ray			ray;
				Vector	p,n;
				LONG		hit;

				ray.p=LVector(0.0,0.0,-1000.0);
				ray.v=LVector(0.0,0.0,1.0);
				ray.ior=1.0;
				ray.pp[0]=ray.pp[1]=ray.pp[2]=SV(ray.p);
				ray.vv[0]=ray.vv[1]=ray.vv[2]=SV(ray.v);

				vps->vd->TraceGeometry(&ray,1000000.0,0,&p,&n,&hit);

				if (hit) // example intersection
				{
					SurfaceData data;
					vps->vd->GetSurfaceData(&data,FALSE,FALSE,TRUE,TRUE,&ray,p,n,hit);

					if (data.refl>0.0) // if intersected object reflects set red color
						col=Vector(1.0,0.0,0.0);
				}
			}

			if (ls->lc->vcs_enable)
			{
				// prepass for lightsource
				// update progress bar, test for user break
			}
		}
	}

	return RAY_OK;
}

static Vector	ComputeSurfaceCaustic(VideoPostData *data, VolumeData *vd, Real sampleradius, LONG accuracy)
{
	CSData *rd = (CSData*) data;
	if (Len(vd->p)<100.0) return rd->col; // surface caustic around origin
	return 0.0;
}

static Vector	ComputeVolumeCaustic(VideoPostData *data, const Vector &p)
{
	if (Len(p)<100.0) return 1.0; // volume caustic around origin
	return 0.0;
}

static Bool	LoadCS(VideoPostData *data, BaseFile *file, LONG disklevel)
{
	LONG l;
	file->ReadLong(&l);

	if (l!='CAUS')
		GePrint("Oops... something's wrong");

	return TRUE;
}

static Bool	SaveCS(VideoPostData *data, BaseFile *file)
{
	file->WriteLong('CAUS');
	return TRUE;
}

Bool RegisterRadiosityHook(void)
{
	if (C4DOS.Ra->custom_id || C4DOS.Cs->custom_id) return TRUE; // another plugin already registered this hook

	if (!RegisterVideoPostPlugin(C4D_RADIOSITY_ID,"Radiosity",PLUGINFLAG_HIDE|PLUGINFLAG_VIDEOPOST_INHERENT,GIData::Alloc,"",0,0)) return FALSE;
	if (!RegisterVideoPostPlugin(C4D_CAUSTICS_ID,"Caustics",PLUGINFLAG_HIDE|PLUGINFLAG_VIDEOPOST_INHERENT,CSData::Alloc,"",0,0)) return FALSE;

	C4DOS.Ra->disklevel = 0;				// no revisions so far
	C4DOS.Ra->custom_id = 1000970;	// use your own unique ID here
	C4DOS.Ra->ComputeDiffuseIllumination=ComputeDiffuseIllumination;
	C4DOS.Ra->LoadGI=LoadGI;
	C4DOS.Ra->SaveGI=SaveGI;
	C4DOS.Ra->FlushGI=FlushGI;

	C4DOS.Cs->disklevel = 0;				// no revisions so far
	C4DOS.Cs->custom_id = 1000972;	// use your own unique ID here
	C4DOS.Cs->ComputeSurfaceCaustic=ComputeSurfaceCaustic;
	C4DOS.Cs->ComputeVolumeCaustic=ComputeVolumeCaustic;
	C4DOS.Cs->LoadCS=LoadCS;
	C4DOS.Cs->SaveCS=SaveCS;
	C4DOS.Cs->FlushCS=FlushCS;

	return TRUE;
}
*/