3-D
|
|
|
|
<? /*
Written and copyrighted (2002) by Mitja Slenc
E-mail: <removed>
I wanted to create a kind of ray-tracish look...
Features real diffuse+specular+ambient lightning,
semi-real light refraction+transparency, fake
shadows, wall outlining, anti-aliasing and results
caching.
*/
// ------- START CONFIGURATION -------
// approximate width of image that is wanted $conf_reqwidth=600;
// should cache results? $conf_cache=1;
// direction toward light
// x and y must be negative, z must be positive!
// Will get normalized below.
// Won't work properly, if shadowoffset>tilesize,
// so be careful with relatively small z $conf_light=array(-1, -1.6, 1); // -------- END CONFIGURATION --------
set_time_limit(0); //error_reporting(E_ALL);
// should anti-alias? (4x slower) $conf_aalias=0;
// should apply shading? $conf_shade=0;
// override via form if (isset($_GET["shade"]) && $_GET["shade"]) $conf_shade=1;
if (isset($_GET["alias"]) && $_GET["alias"]) $conf_aalias=1;
// normalize light vector $len=$conf_light[0]*$conf_light[0]+$conf_light[1]*$conf_light[1]+$conf_light[2]*$conf_light[2]; $len=1.0/sqrt($len); $conf_light[0]*=$len; $conf_light[1]*=$len; $conf_light[2]*=$len;
// read mazes $lines=file("mazes.txt");
$mazes=array(); $thismaze=array();
$ditherr=array();
for ($a=0; $a<sizeof($lines); $a++) {
$tmp=trim($lines[$a]);
if (!strlen($tmp)) {
if (sizeof($thismaze)) {
$mazes[]=$thismaze;
$thismaze=array();
}
} else {
$tmp=explode("!", $tmp);
for ($b=0; $b<sizeof($tmp); $b++) {
$thismaze[]=ExplodeMazeLine($tmp[$b]);
}
}
}
if (sizeof($thismaze))
$mazes[]=$thismaze;
if (isset($_GET["getmaze"])) {
OutMaze($mazes[(int)$_GET["getmaze"]]);
exit();
}
if (isset($_GET["makeall"])) {
echo "<html><head><style type="text/css">
body, td {
font-family: "verdana", sans-serif;
}
</style>
</head><body>";
echo "<center>";
echo "<a href="$PHP_SELF?">Back</a><br><br>";
touch("/tmp/mitjasmaze_createdall.txt");
$made=0;
for ($alias=0; $alias<2; $alias++) {
for ($shade=0; $shade<2; $shade++) {
for ($maze=0; $maze<sizeof($mazes); $maze++) {
$conf_shade=$shade;
$conf_aalias=$alias;
$has_generated=0;
$tiles_total=0;
$tiles_copied=0;
ob_start();
list($a,$b)=explode(" ", microtime());
$starttime=(float)$a+(float)$b;
OutMaze($mazes[$maze]);
list($a,$b)=explode(" ", microtime());
$endtime=(float)$a+(float)$b;
ob_end_clean();
if ($has_generated) {
echo "Maze ".($maze+1)." (shade=$shade, alias=$alias)<br>Generated in ".sprintf("%.2f", $endtime-$starttime)." seconds<br>$tiles_total tiles of which $tiles_copied were cached<br><img src="$PHP_SELF?getmaze=$maze&shade=$shade&alias=$alias"><br><hr><br>";
$made=1;
flush();
}
}
}
}
if ($made) {
echo "<br><br><a href="$PHP_SELF?">Back</a>";
} else {
echo "<br><br>All mazes were already generated.";
}
echo "</center></body></html>";
} else {
echo "<html><head><style type="text/css">
body, td {
font-family: "verdana", sans-serif;
}
</style>
</head><body>";
echo "<center>";
echo "<form method=get action="$PHP_SELF">";
echo "<input type=hidden name=formsubmitted value=1>";
echo "<table><tr><td align=right><b>Shading:</b></td><td><input type=checkbox name=shade value=1";
if ($conf_shade)
echo " checked=1";
echo "></td></tr>";
echo "<tr><td align=right><b>Anti-aliasing:</b></td><td><input type=checkbox name=alias value=1";
if ($conf_aalias)
echo " checked=1";
echo "></td></tr>";
echo "<tr><td align=center><input type=submit value="Redraw"></td></tr>";
echo "</table></form>";
if ($conf_cache && (!isset($_GET["formsubmitted"])) && (!file_exists("/tmp/mitjasmaze_createdall.txt") || filemtime("/tmp/mitjasmaze_createdall.txt")<filemtime("mazes.txt"))) {
echo "or<br><br><a href="$PHP_SELF?makeall=1">Create all images</a><br><br>";
}
if (isset($_GET["formsubmitted"])) {
for($a=0; $a<sizeof($mazes); $a++) {
echo "<img src="$PHP_SELF?getmaze=$a&shade=".$conf_shade."&alias=".$conf_aalias.""><br><br><br>";
}
}
echo "</center></body></html>";
}
function OutMaze($maze)
{
$starttime=time();
global $tilesize, $bw, $colors, $ww;
global $conf_reqwidth;
global $conf_cache, $conf_aalias, $conf_shade;
global $conf_light;
global $tiles_total, $tiles_copied;
// double the size for antialiasing
if ($conf_aalias)
$reqwidth=$conf_reqwidth<<1;
else
$reqwidth=$conf_reqwidth;
$w=strlen($maze[0]);
$h=sizeof($maze);
// pad with spaces
$tmp=array();
$tmp[]=str_repeat(" ", $w+2);
foreach($maze as $line)
$tmp[]=" ".$line." ";
$tmp[]=str_repeat(" ", $w+2);
$maxlen=0;
for ($a=0; $a<sizeof($tmp); $a++)
if (strlen($tmp[$a])>$maxlen)
$maxlen=strlen($tmp[$a]);
for ($a=0; $a<sizeof($tmp); $a++) {
if (strlen($tmp[$a])<$maxlen)
$tmp[$a].=str_repeat(" ", $maxlen-strlen($tmp[$a]));
}
$maze=$tmp;
$w=$maxlen;
$h=sizeof($maze);
// compute tile size
$tilesize=(int)($reqwidth/$w);
if ($tilesize & 1)
$tilesize++;
if ($conf_aalias) {
if ($tilesize>128)
$tilesize=128;
if ($tilesize<32)
$tilesize=32;
} else {
if ($tilesize>64)
$tilesize=64;
if ($tilesize<16)
$tilesize=16;
}
// check for cached copy
if ($conf_cache) {
$md5=md5($tilesize."_".implode("_", $conf_light)."_".$conf_shade."_".$conf_aalias."_".implode("_", $maze));
if (file_exists("/tmp/mitjasmaze_$md5.png")) {
header("Content-type: image/png");
readfile("/tmp/mitjasmaze_$md5.png");
return;
}
}
// for makeall
global $has_generated;
$has_generated=1;
$ww=$w*$tilesize+1;
$hh=$h*$tilesize+1;
$im=imagecreatetruecolor($ww, $hh);
imagealphablending($im, true);
// ALLOCATE COLORS
$mycols=array(
array(0,0,0), // " " gets this one always
array(0,0,0),
array(128,255,0),
array(0,128,255),
array(128,0,255),
array(255,128,0),
array(0,0,128),
array(0,0,255),
array(0,128,0),
array(0,128,128),
array(0,255,0),
array(0,255,128),
array(0,255,255),
array(128,0,0),
array(128,0,128),
array(128,128,0),
array(128,128,128),
array(128,128,255),
array(128,255,128),
array(128,255,255),
array(255,0,128),
array(255,0,255),
array(255,128,128),
array(255,128,255),
array(255,255,0),
array(255,255,128),
array(255,255,255)
);
$tmp=implode("", $maze);
$colpointer=0;
$colors=array();
for ($a=0; $a<strlen($tmp); $a++) {
$c=substr($tmp, $a, 1);
if (!isset($colors[$c])) {
if ($c=="*") {
$colors[$c]=array(255,64,64);
} else {
if (isset($mycols[$colpointer])) {
$colors[$c]=$mycols[$colpointer];
$colpointer++;
} else {
$colors[$c]=array(mt_rand(64,192), mt_rand(64,192), mt_rand(64,192));
}
}
}
}
// pre-calc various sizes
$half=$tilesize>>1;
$d=0.2/$conf_light[2];
$soffsetx=(int)(-$conf_light[0]*$d*$tilesize);
$soffsety=(int)(-$conf_light[1]*$d*$tilesize);
$bw=(int)(5*$tilesize/10);
if (!($bw & 1))
$bw++;
$bw=(($bw-1)>>1)+1;
$diff=$half-$bw;
$already=array();
// pre-calc shapes and normals
$precalc=array();
$normals=array();
for ($ox=0; $ox<=$half; $ox++)
for ($oy=0; $oy<=$half; $oy++) {
// FULL
$precalc[0][$ox][$oy]=1;
$normals[0][$ox][$oy]=array(0,0,1);
// VERTICAL TUBE
if ($ox<$bw) {
$precalc[1][$ox][$oy]=1;
$normals[1][$ox][$oy]=array($ox/$bw, 0, sqrt(1-(($ox/$bw)*($ox/$bw))));
} else {
$precalc[1][$ox][$oy]=0;
}
// HORIZONTAL TUBE
if ($oy<$bw) {
$precalc[2][$ox][$oy]=1;
$normals[2][$ox][$oy]=array(0, $oy/$bw, sqrt(1-(($oy/$bw)*($oy/$bw))));
} else {
$precalc[2][$ox][$oy]=0;
}
// OUTER ROUND
if (($ox*$ox+$oy*$oy)<($bw*$bw)) {
$precalc[3][$ox][$oy]=1;
$nx=$ox/$bw;
$ny=$oy/$bw;
$nz=sqrt(1-$nx*$nx-$ny*$ny);
$normals[3][$ox][$oy]=array($nx, $ny, $nz);
} else {
$precalc[3][$ox][$oy]=0;
}
// CROSS (*)
$found1=0;
$found2=0;
$nx=$ox/$half;
$ny=$oy/$half;
$dist=sqrt($nx*$nx+$ny*$ny);
if (($nx+$ny)<1.1 && (abs($nx-$ny)<0.4)) {
$precalc[5][$ox][$oy]=1;
$found2=1;
if ($ny>$nx) {
$vx=-0.6314;
$vy=0.6314;
$vz=0.45;
} else {
$vx=0.66666;
$vy=-0.66666;
$vz=0.45;
}
if (abs($nx-$ny)>0.33 || (($nx+$ny)>1.03)) {
// force outline
$normals[5][$ox][$oy]=array(0,0,0.3);
} else {
$normals[5][$ox][$oy]=array($vx, $vy, $vz);
}
} else {
$precalc[5][$ox][$oy]=0;
}
// INNER ROUND
$vx=$half-$ox;
$vy=$half-$oy;
$sdist=$vx*$vx+$vy*$vy;
if ($sdist>($diff*$diff)) {
$precalc[4][$ox][$oy]=1;
$dist=sqrt($sdist);
if ($dist<$half) {
$tdist=$dist-$diff;
$off=$bw-$tdist;
$vx*=$off/$bw/$dist;
$vy*=$off/$bw/$dist;
$vz=sqrt(1.0-$vx*$vx-$vy*$vy);
$normals[4][$ox][$oy]=array($vx, $vy, $vz);
} else {
$normals[4][$ox][$oy]=array(0,0,1);
}
} else {
$precalc[4][$ox][$oy]=0;
}
// DIAGONAL
if (abs($oy-$ox)/sqrt(2)<$bw) {
$precalc[6][$ox][$oy]=1;
$d=($oy-$ox)/sqrt(2)/$bw;
$vz=sqrt(1-$d*$d);
$vx=-$d/sqrt(2);
$vy=$d/sqrt(2);
$normals[6][$ox][$oy]=array($vx, $vy, $vz);
} else {
$precalc[6][$ox][$oy]=0;
}
if (($oy+$ox)/sqrt(2)<$bw && $oy>$ox) {
$precalc[7][$ox][$oy]=1;
$d=($oy+$ox)/sqrt(2)/$bw;
$vz=sqrt(1-$d*$d);
$vx=$d/sqrt(2);
$vy=$d/sqrt(2);
$normals[7][$ox][$oy]=array($vx,$vy,$vz);
} else {
if ($precalc[3][$ox][$oy]) {
$precalc[7][$ox][$oy]=1;
$normals[7][$ox][$oy]=$normals[3][$ox][$oy];
} else {
$precalc[7][$ox][$oy]=0;
}
}
if (($oy+$ox)/sqrt(2)<$bw && $oy<$ox) {
$precalc[8][$ox][$oy]=1;
$d=($oy+$ox)/sqrt(2)/$bw;
$vz=sqrt(1-$d*$d);
$vx=$d/sqrt(2);
$vy=$d/sqrt(2);
$normals[8][$ox][$oy]=array($vx,$vy,$vz);
} else {
if ($precalc[3][$ox][$oy]) {
$precalc[8][$ox][$oy]=1;
$normals[8][$ox][$oy]=$normals[3][$ox][$oy];
} else {
$precalc[8][$ox][$oy]=0;
}
}
if (($oy+$ox)/sqrt(2)<$bw) {
$precalc[9][$ox][$oy]=1;
$d=($oy+$ox)/sqrt(2)/$bw;
$vz=sqrt(1-$d*$d);
$vx=$d/sqrt(2);
$vy=$d/sqrt(2);
if ($precalc[2][$ox][$oy]) {
if ($normals[2][$ox][$oy][2]>$vz)
list($vx,$vy,$vz)=$normals[2][$ox][$oy];
}
$normals[9][$ox][$oy]=array($vx,$vy,$vz);
} else {
if ($precalc[2][$ox][$oy]) {
$precalc[9][$ox][$oy]=1;
$normals[9][$ox][$oy]=$normals[2][$ox][$oy];
} else {
$precalc[9][$ox][$oy]=0;
}
}
if (($oy+$ox)/sqrt(2)<$bw) {
$precalc[10][$ox][$oy]=1;
$precalc[12][$ox][$oy]=1;
$d=($oy+$ox)/sqrt(2)/$bw;
$vz=sqrt(1-$d*$d);
$vx=$d/sqrt(2);
$vy=$d/sqrt(2);
$normals[12][$ox][$oy]=array($vx,$vy,$vz);
if ($precalc[1][$ox][$oy]) {
if ($normals[1][$ox][$oy][2]>$vz)
list($vx,$vy,$vz)=$normals[1][$ox][$oy];
}
$normals[10][$ox][$oy]=array($vx,$vy,$vz);
} else {
$precalc[12][$ox][$oy]=0;
if ($precalc[1][$ox][$oy]) {
$precalc[10][$ox][$oy]=1;
$normals[10][$ox][$oy]=$normals[1][$ox][$oy];
} else {
$precalc[10][$ox][$oy]=0;
}
}
if ((($half-$ox)+($half-$oy))/sqrt(2)<$bw) {
$d=(($half-$ox)+($half-$oy))/sqrt(2)/$bw;
$vz=sqrt(1-$d*$d);
$vx=-$d/sqrt(2);
$vy=-$d/sqrt(2);
$precalc[11][$ox][$oy]=1;
$normals[11][$ox][$oy]=array($vx, $vy, $vz);
} else {
$precalc[11][$ox][$oy]=0;
}
}
// fill background
$ts=$tilesize;
for ($x=0; $x<$tilesize; $x++)
for ($y=0; $y<$tilesize; $y++)
MyImageSetPixel($im, $x, $y, BackColor($x, $y));
for ($x=0; $x<=$w; $x++) {
for ($y=0; $y<=$h; $y++) {
if (!$x && !$y)
continue;
imagecopy($im, $im, $x*$tilesize, $y*$tilesize, 0, 0, $tilesize, $tilesize);
}
}
// finally, render the maze
for ($y=0; $y<$h; $y++) {
for ($x=0; $x<$w; $x++) {
$tiles_total++;
if (($c=$maze[$y][$x])==" ") {
if (!$x || !$y || ($x==($w-1)) || ($y==($h-1))) {
continue;
}
}
$sm=(($x+$y)&1).substr($maze[$y-1], $x-1, 3).substr($maze[$y],$x-1,3).substr($maze[$y+1],$x-1,3);
if (isset($already[$sm])) {
list($sx, $sy)=$already[$sm];
imagecopy($im, $im, $x*$tilesize, $y*$tilesize, $sx*$tilesize, $sy*$tilesize, $tilesize+$soffsetx+1, $tilesize+$soffsety+1);
$tiles_copied++;
continue;
}
$already[$sm]=array($x, $y);
$sm=array(
array(0,0,0),
array(0,0,0),
array(0,0,0)
);
if ($maze[$y-1][$x]==$c) $sm[1][0]=1;
if ($maze[$y+1][$x]==$c) $sm[1][2]=1;
if ($maze[$y][$x+1]==$c) $sm[2][1]=1;
if ($maze[$y][$x-1]==$c) $sm[0][1]=1;
if ($maze[$y-1][$x-1]==$c) $sm[0][0]=1;
if ($maze[$y+1][$x-1]==$c) $sm[0][2]=1;
if ($maze[$y-1][$x+1]==$c) $sm[2][0]=1;
if ($maze[$y+1][$x+1]==$c) $sm[2][2]=1;
$bx=$x*$tilesize+$half;
$by=$y*$tilesize+$half;
for ($qx=-1; $qx<2; $qx+=2) {
for ($qy=-1; $qy<2; $qy+=2) {
$c=$maze[$y][$x];
if ($sm[$qx+1][1] && $sm[$qx+1][$qy+1] && $sm[1][$qy+1]) { // whole quadrant
$mode=0;
} else
if ($sm[$qx+1][1] && $sm[1][$qy+1]) { // inner round
$mode=4;
} else
if ($sm[$qx+1][1]) { // horizontal tube
if ($sm[1-$qx][1+$qy] && (!$sm[1-$qx][1])) {
$mode=9;
} else {
$mode=2;
}
} else
if ($sm[1][$qy+1]) { // vertical tube
if ($sm[1+$qx][1-$qy] && (!$sm[1][1-$qy])) {
$mode=10;
} else {
$mode=1;
}
} else
if ($sm[$qx+1][$qy+1]) { // diagonal
$mode=6;
} else { // outer round
if ($sm[1-$qx][$qy+1] && !$sm[1-$qx][1]) {
if ($sm[$qx+1][1-$qy] && !$sm[1][1-$qy]) {
$mode=12;
} else {
$mode=7;
}
} else {
if ($sm[$qx+1][1-$qy] && !$sm[1][1-$qy]) {
$mode=8;
} else {
$mode=3;
}
}
}
if ($c=="*")
$mode=5;
if ($c==" ")
$mode=-1;
if ($mode>=0) {
$todo=array(array($c, $mode));
} else {
$todo=array();
}
$blendit=0;
if ($maze[$y+$qy][$x]!=" " && $maze[$y+$qy][$x]!="*") {
if ($maze[$y+$qy][$x]==$maze[$y][$x+$qx]) {
if ($maze[$y+$qy][$x]!=$maze[$y+$qy][$x+$qx]) {
if ($maze[$y+$qy][$x]!=$c) {
$todo[]=array($maze[$y][$x+$qx], 11);
if ($c==" " || (!$sm[$qx+1][$qy+1])) {
$blendit=0;
} else {
$blendit=1;
}
}
}
}
}
if (!sizeof($todo)) {
continue;
}
if (sizeof($todo)>1) {
$flip=0;
if ($qx<0 && $qy<0) {
$flip=1;
} else
if ($qx<0) {
if ($soffsetx>$soffsety)
$flip=1;
} else
if ($qy<0) {
if ($soffsetx<$soffsety)
$flip=1;
}
if ($flip) {
$todo=array_reverse($todo);
}
} else {
$blendit=0;
}
if ($qx<0) {
$startox=$half;
$incox=-1;
} else {
$startox=0;
$incox=1;
}
if ($qy<0) {
$startoy=$half;
$incoy=-1;
} else {
$startoy=0;
$incoy=1;
}
for ($showshadows=$conf_shade; $showshadows>=0; $showshadows--) {
for ($todocounter=0; $todocounter<sizeof($todo); $todocounter++) {
$c=$todo[$todocounter][0];
$mode=$todo[$todocounter][1];
for ($ox=$startox; $ox>=0 && $ox<=$half; $ox+=$incox) {
$pcalc=&$precalc[$mode][$ox];
$norms=&$normals[$mode][$ox];
for ($oy=$startoy; $oy>=0 && $oy<=$half; $oy+=$incoy) {
$tarx=$bx+$ox*$qx;
$tary=$by+$oy*$qy;
if ($pcalc[$oy]) {
$n=$norms[$oy];
$n[0]*=$qx;
$n[1]*=$qy;
if ($conf_shade) {
if ($showshadows) {
$tmp1=BackColor($tarx+$soffsetx, $tary+$soffsety);
$tmp2=$colors[$c];
$s=$n[2];
if ($s<0.9) {
$s=0.5;
} else {
if ($s<0.97) {
$s=0.5+0.5*(($s-0.9)/0.07);
} else {
$s=3.0;
}
}
$s*=0.295;
$tmp2[0]=160+$s*(64+$tmp2[0]);
$tmp2[1]=160+$s*(64+$tmp2[1]);
$tmp2[2]=160+$s*(64+$tmp2[2]);
$col=array();
$col[0]=(int)(($tmp1[0]*$tmp2[0])/255);
$col[1]=(int)(($tmp1[1]*$tmp2[1])/255);
$col[2]=(int)(($tmp1[2]*$tmp2[2])/255);
if ($col[0]>255) $col[0]=255;
if ($col[1]>255) $col[1]=255;
if ($col[2]>255) $col[2]=255;
if ($blendit) {
if ($qx*$qy>0) {
if ($mode==11)
MyImageSetPixel($im, $tarx+$soffsetx, $tary+$soffsety, $col);
else {
if ($todocounter) {
if (($half+$half-$ox-$oy)/sqrt(2)>$bw)
MyImageSetPixel($im, $tarx+$soffsetx, $tary+$soffsety, $col);
} else {
MyImageSetPixel($im, $tarx+$soffsetx, $tary+$soffsety, $col);
}
}
} else {
if ($mode!=11)
MyImageSetPixel($im, $tarx+$soffsetx, $tary+$soffsety, $col);
}
} else {
MyImageSetPixel($im, $tarx+$soffsetx, $tary+$soffsety, $col);
}
} else {
$col=ShadePixel($im, $tarx, $tary, $c, $n);
if ($blendit) {
if ($qx*$qy>0) {
if ($mode==11)
MyImageSetPixel($im, $tarx, $tary, $col);
else {
if ($todocounter) {
if (($half+$half-$ox-$oy)/sqrt(2)>$bw)
MyImageSetPixel($im, $tarx, $tary, $col);
} else {
MyImageSetPixel($im, $tarx, $tary, $col);
}
}
} else {
if ($mode!=11)
MyImageSetPixel($im, $tarx, $tary, $col);
}
} else {
MyImageSetPixel($im, $tarx, $tary, $col);
}
}
} else {
if ($n[2]<0.4) {
$col=array(0,0,0);
} else {
$col=$colors[$c];
}
if ($blendit) {
if ($qx*$qy>0) {
if ($mode==11)
MyImageSetPixel($im, $tarx, $tary, $col);
else {
if ($todocounter) {
if (($half+$half-$ox-$oy)/sqrt(2)>$bw)
MyImageSetPixel($im, $tarx, $tary, $col);
} else {
MyImageSetPixel($im, $tarx, $tary, $col);
}
}
} else {
if ($mode!=11)
MyImageSetPixel($im, $tarx, $tary, $col);
}
} else {
MyImageSetPixel($im, $tarx, $tary, $col);
}
}
}
}
}
}
}
}
}
}
}
// create a stupid frame around the image
$col=imagecolorresolve($im, 255, 255, 255);
for ($a=0; $a<$half; $a++) {
if ($a==($half-1)) {
$col=imagecolorresolve($im, 128,128,128);
}
imageline($im, 0, 0, $ww, $a, $col);
imageline($im, $ww-1, 0, $ww-1-$a, $hh-1, $col);
imageline($im, $ww-1, $hh-1, 0, $hh-1-$a, $col);
imageline($im, 0, $hh-1, $a, 0, $col);
}
if ($conf_cache) {
header("Content-type: image/png");
MyImagePng($im, "/tmp/mitjasmaze_$md5.png");
readfile("/tmp/mitjasmaze_$md5.png");
} else {
header("Content-type: image/png");
MyImagePng($im);
}
}
function MyImagePng($im, $filename="")
{
// outputs the image, resizing if neccesary
global $conf_aalias;
if ($conf_aalias) {
$sx=imagesx($im);
$sy=imagesy($im);
$nx=($sx>>1)+1;
$ny=($sy>>1)+1;
$out=imagecreatetruecolor($nx, $ny);
imagecopyresampled($out, $im, 0, 0, 0, 0, $nx, $ny, $sx, $sy);
if ($filename) {
imagepng($out, $filename);
} else {
imagepng($out);
}
} else {
if ($filename) {
imagepng($im, $filename);
} else {
imagepng($im);
}
}
}
function ShadePixel($im, $x, $y, $c, $normal)
{
// applies shading to a pixel
// black outline
if ($normal[2]<0.4) return array(0,0,0);
global $bw, $colors, $tilesize, $ww;
global $conf_light;
list($r,$g,$b)=$colors[$c];
$bright=$conf_light[0]*$normal[0]+$conf_light[1]*$normal[1]+$conf_light[2]*$normal[2];
$coslightnormal=$bright;
if ($bright<0) {
$bright=0;
}
// ambient/diffuse
if ($c=="*") {
// make * really bright
$bright=1.0+2.0*$bright;
} else {
$bright=0.1+0.7*$bright;
}
$r=$bright*$r;
$g=$bright*$g;
$b=$bright*$b;
if ($c!="*") {
// specular (white light)
$cosa=2.0*$normal[2]*$coslightnormal-$conf_light[2];
if ($cosa>0) {
$spec=(255.0*pow($cosa, 10));
$r+=$spec;
$g+=$spec;
$b+=$spec;
}
// refraction
$n1x=sqrt($normal[0]*$normal[0]+$normal[1]*$normal[1]);
$n1z=$normal[2];
$cosalfa=$n1z;
$alfa=acos($cosalfa);
$sinalfa=sin($alfa);
$sinbeta=$sinalfa/1.4;
$beta=asin($sinbeta);
$singama=$sinbeta*1.4;
if (abs($singama)<=1.0) {
$gama=asin($singama);
$totalangle=$alfa+$gama-$beta-$beta;
$innerx=-sin($alfa-$beta);
$innerz=-cos($alfa-$beta);
$p1x=$n1x;
$p1z=$n1z;
$d=2.0*((-$p1x*$innerx)+(-$p1z*$innerz));
$p2x=$p1x+$d*$innerx;
$p2z=$p1z+$d*$innerz;
$outx=-sin($totalangle);
$outz=-cos($totalangle);
$gotheretimes=(2.2+$p2z)/$outz;
$hitx=-(int)($gotheretimes*$normal[0]*$tilesize/0.6);
$hity=-(int)($gotheretimes*$normal[1]*$tilesize/0.6);
list($rr, $rg, $rb)=BackColor($x+$hitx, $y+$hity);
list($r1, $g1, $b1)=$colors[$c];
$r+=$rr*(128+$r1)*0.002;
$g+=$rg*(128+$g1)*0.002;
$b+=$rb*(128+$b1)*0.002;
}
}
$r=(int)$r; if ($r>255) $r=255;
$g=(int)$g; if ($g>255) $g=255;
$b=(int)$b; if ($b>255) $b=255;
return array($r, $g, $b);
}
function MyImageSetPixel($im, $x, $y, $color)
{
$col=imagecolorresolve($im, $color[0], $color[1], $color[2]);
imagesetpixel($im, $x, $y, $col);
}
function BackColor($x, $y)
{
// returns the color of a background pixel
global $tilesize;
global $c_odd, $c_even, $c_edge, $bw;
$x=abs($x)%$tilesize;
$y=abs($y)%$tilesize;
$x-=$tilesize>>1;
$y-=$tilesize>>1;
if ($x*$x+$y*$y<$bw*$bw) {
return array(255,255,255);
} else {
return array(224,224,224);
}
}
function ExplodeMazeLine($s)
{
// explodes a line of a maze
$result="";
$count=0;
while (strlen($s)) {
$c=substr($s, 0, 1);
$s=substr($s, 1);
if ($c>="0" && $c<="9") {
$count+=(int)$c;
} else {
if ($c=="b" || $c==".") // . can also be used for space
$c=" ";
if ($count<1) // shortcut notation, for easier testing
$count=1;
$result.=str_repeat($c, $count);
$count=0;
}
}
return $result;
}
?>
|
|
|
Usage Example
|
|
|
Rate This Script
|
|
|
|