////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Shadow renderer
//Roel smit, 2008
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//a few vars...
var shadow_busy;
var bmapmode;
var pixel[2];
var lpixel[2];
var rpixel[2];
var upixel[2];
var dpixel[2];
var Cpixel[3];//colorPixel
var Clpixel[3];//colorleftPixel
var Crpixel[3];//colorrightPixel
var Cupixel[3];//colorupPixel
var Cdpixel[3];//colordownPixel
var writePix;
var readPix;
var vecColor[3];
var pixPos3D[3];
var posPercent[2];
var pixseesun;
var pixobjectlength;
var blurtime;
var blur_index;
var shadow_index;
var shadow_sunpos[3];
var pixels_dist[300000];
var shadowcolors[300000];
var terrain_height[300000];
var shadowpix;
var trace_from[3];
var trace_to[3];
entity* ste;
bmap* IM_TERRAINSHADOW;
//terrainfilehandle, for the shadowmap file reading and writing
var_nsave tfh;
string tstr;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//tsm: terrainshadowmap
function write_shademap
{
	pixel[0] = 1;
	pixel[1] = 1;
	str_cpy(tstr,level_name);
	str_cat(tstr,".tsm");
	tfh = file_open_write(tstr);
	while(pixel[1] < bmap_height(IM_TERRAINSHADOW))
	{
		while(pixel[0] < bmap_width(IM_TERRAINSHADOW))
		{
			bmapmode = bmap_lock(IM_TERRAINSHADOW,0);
			//normal pixel
			readPix = pixel_for_bmap(IM_TERRAINSHADOW,pixel[0],pixel[1]);
			pixel_to_vec(Cpixel,null,bmapmode,readPix);

			file_asc_write(tfh,Cpixel[0]);
			file_asc_write(tfh,Cpixel[1]);
			file_asc_write(tfh,Cpixel[2]);
			
			bmap_unlock(IM_TERRAINSHADOW);
			pixel[0]+=1;
		}
		pixel[1]+=1;
		pixel[0]=1;
	}
	file_close(tfh);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function read_shademap
{
	pixel[0] = 1;
	pixel[1] = 1;
	while(pixel[1] < bmap_height(IM_TERRAINSHADOW))
	{
		while(pixel[0] < bmap_width(IM_TERRAINSHADOW))
		{
			bmapmode = bmap_lock(IM_TERRAINSHADOW,0);

			Cpixel[0] = file_asc_read(tfh);
			Cpixel[1] = file_asc_read(tfh);
			Cpixel[2] = file_asc_read(tfh);
			
			writePix = pixel_for_vec(Cpixel,null,bmapmode);
			pixel_to_bmap(IM_TERRAINSHADOW,pixel[0],pixel[1],writePix);
			
			bmap_unlock(IM_TERRAINSHADOW);
			pixel[0]+=1;
		}
		pixel[1]+=1;
		pixel[0]=1;
	}
	bmap_to_mipmap(IM_TERRAINSHADOW);
	file_close(tfh);
	shadow_busy = 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function blur_tshadow
{
	blur_index = 0;
	blurtech:
	pixel[0] = 1;
	pixel[1] = 1;
	while(pixel[1] < bmap_height(IM_TERRAINSHADOW))
	{
		bmapmode = bmap_lock(IM_TERRAINSHADOW,0);
		while(pixel[0] < bmap_width(IM_TERRAINSHADOW))
		{
			
			pixobjectlength = pixels_dist[512 * pixel[1] + pixel[0]]/8;
			if(pixobjectlength < 0)
			{
				pixobjectlength*=-5;
			}
			lpixel[0] = pixel[0]-(1);
			lpixel[1] = pixel[1];
			rpixel[0] = pixel[0]+(1);
			rpixel[1] = pixel[1];
			upixel[0] = pixel[0];
			upixel[1] = pixel[1]+(1);
			dpixel[0] = pixel[0];
			dpixel[1] = pixel[1]-(1);
			lpixel[0] = clamp(lpixel[0],1,bmap_width(IM_TERRAINSHADOW));
			rpixel[0] = clamp(rpixel[0],1,bmap_width(IM_TERRAINSHADOW));
			upixel[1] = clamp(upixel[1],1,bmap_height(IM_TERRAINSHADOW));
			dpixel[1] = clamp(dpixel[1],1,bmap_height(IM_TERRAINSHADOW));
			//normal pixel
			readPix = pixel_for_bmap(IM_TERRAINSHADOW,pixel[0],pixel[1]);
			pixel_to_vec(Cpixel,null,bmapmode,readPix);
			readPix = pixel_for_bmap(IM_TERRAINSHADOW,lpixel[0],lpixel[1]);
			pixel_to_vec(Clpixel,null,bmapmode,readPix);
			readPix = pixel_for_bmap(IM_TERRAINSHADOW,rpixel[0],rpixel[1]);
			pixel_to_vec(Crpixel,null,bmapmode,readPix);
			readPix = pixel_for_bmap(IM_TERRAINSHADOW,upixel[0],upixel[1]);
			pixel_to_vec(Cupixel,null,bmapmode,readPix);
			readPix = pixel_for_bmap(IM_TERRAINSHADOW,dpixel[0],dpixel[1]);
			pixel_to_vec(Cdpixel,null,bmapmode,readPix);
			
			vecColor[0] = (Cpixel[0]*1.5 + Clpixel[0] + Crpixel[0] + Cupixel[0] + Cdpixel[0])/5.5;
			vecColor[1] = (Cpixel[1]*1.5 + Clpixel[1] + Crpixel[1] + Cupixel[1] + Cdpixel[1])/5.5;
			vecColor[2] = (Cpixel[2]*1.5 + Clpixel[2] + Crpixel[2] + Cupixel[2] + Cdpixel[2])/5.5;
			
			shadowcolors[512 * pixel[1] + pixel[0]] = vecColor[0];
			
			writePix = pixel_for_vec(vecColor,null,bmapmode);
			pixel_to_bmap(IM_TERRAINSHADOW,pixel[0],pixel[1],writePix);
			
			pixel[0]+=1;
		}
		bmap_unlock(IM_TERRAINSHADOW);
		blur_index+=1;
		if(blur_index > 50)
		{
			wait(1);
			blur_index = 0;
		}
		pixel[1]+=1;
		pixel[0]=1;
	}
	blurtime+=1;
	if(blurtime < 6)
	{
		goto blurtech;
	}
	bmap_to_mipmap(IM_TERRAINSHADOW);
	write_shademap();
	shadow_busy = 0;
}
function terrain_shadow
{
	IM_TERRAINSHADOW = bmap_for_entity(ste,0);
	str_cpy(tstr,level_name);
	str_cat(tstr,".tsm");
	tfh = file_open_read(tstr);
	if(tfh)
	{
		read_shademap();
		return;
	}
	shadow_busy = 1;
	blurtime = 1;
	shadow_index = 0;
	//start with the process
	pixel[0] = 1;
	pixel[1] = 1;
	me = ste;
	var minx = 0;
	var miny = 0;
	var maxx = 0;
	var maxy = 0;
	minx  =ste.min_x;
	miny  =ste.min_y;
	maxx  =ste.max_x;
	maxy  =ste.max_y;
	
	
	while(pixel[1] < bmap_height(IM_TERRAINSHADOW))
	{
		while(pixel[0] < bmap_width(IM_TERRAINSHADOW))
		{
			posPercent[0] =(pixel[0]/bmap_width(IM_TERRAINSHADOW));
			posPercent[1] =(pixel[1]/bmap_height(IM_TERRAINSHADOW));
			trace_from.x = (minx+maxx*2*posPercent[1]);
			trace_from.y = (miny+maxy*2*posPercent[0]);
			trace_from.z = ste.max_z + ste.z;
			vec_rotate(trace_from,vector(270,0,0));
			trace_from.x+=ste.x;
			trace_from.y+=ste.y;
			vec_set(trace_to,trace_from);
			trace_to.z = ste.min_z + ste.z;
			c_trace(trace_from,trace_to,ignore_push + use_aabb + ignore_models + ignore_passents + 
			ignore_passable + ignore_content + ignore_sprites);
			vec_set(pixPos3D,target.x);
			pixPos3D.z+=random(100);//to do not get stuck in the terrain, and some variation
			you = null;
			vec_set(shadow_sunpos.x,sun_pos.x);
			vec_normalize(shadow_sunpos.x,ste.max_x);
			vec_add(shadow_sunpos.x,pixPos3D);
			c_trace(shadow_sunpos.x,pixPos3D,ignore_push + ignore_content);
			pixseesun = trace_hit;
			terrain_height[512 * pixel[1] + pixel[0]] = target.z;
			if(pixseesun == 1)
			{
				bmapmode = bmap_lock(IM_TERRAINSHADOW,0);
				readPix = pixel_for_bmap(IM_TERRAINSHADOW,pixel[0],pixel[1]);
				pixel_to_vec(vecColor,null,bmapmode,readPix);
				vec_set(temp,vecColor);
				pixobjectlength = vec_dist(pixPos3D,target.x);
				pixobjectlength = clamp(pixobjectlength,0,5000);
				pixobjectlength/=50;
				pixels_dist[512 * pixel[1] + pixel[0]] = -pixobjectlength;
				vecColor[0] /=2;
				vecColor[1] /=2;
				vecColor[2] /=2;
				//	shadowcolors[512 * pixel[1] + pixel[0]] = 25-pixobjectlength/2;
				/*		if(you != ste)
				{
					if(your.ent_type != type_player && your.ent_type != type_enemy)
					{
						pixels_dist[512 * pixel[1] + pixel[0]] = pixobjectlength;
						vecColor[0] =temp[0]-(50-pixobjectlength)*4;
						vecColor[1] =temp[1]-(50-pixobjectlength)*4;
						vecColor[2] =temp[2]-(50-pixobjectlength)*4;
						//	shadowcolors[512 * pixel[1] + pixel[0]] = 50-pixobjectlength;
					}
				}*/
				vecColor[0] = clamp(vecColor[0],0,255);
				vecColor[1] = clamp(vecColor[1],0,255);
				vecColor[2] = clamp(vecColor[2],0,255);
				writePix = pixel_for_vec(vecColor,null,bmapmode);
				pixel_to_bmap(IM_TERRAINSHADOW,pixel[0],pixel[1],writePix);
				bmap_unlock(IM_TERRAINSHADOW);
			}
			pixel[0]+=1;
		}
		wait(1);
		pixel[1]+=1;
		pixel[0]=1;	
	}
	//	bmap_to_mipmap(bmap_for_entity(ste,1));
		blur_tshadow();
}
action shadowed_terrain
{
	ste = me;
	terrain_shadow();
}