Исчу помомощи по PHP 3D Render !!!

jday

Писатель
Регистрация
16 Апр 2010
Сообщения
7
Реакции
3
Решил сделать свой рендер 3D на PHP+GD. Может и велосипед.. но свой !!!!!!
3dr.png

3da2.gif


1) Проблема в том что не могу осилить z-buffer
2) Отрисовка текстур

<?php

class render3d
{
public $ScreenWidth, $ScreenHeight, $bacground, $focus, $scale, $rx, $ry, $rz, $ptext, $XAngle, $YAngle, $ZAngle, $DrawAxes, $NumPoitObject, $copy, $InfoText, $zbuffer;
private $Xpos, $Ypos, $Zpos, $screen,$op;

public function __construct($w,$h,$scale)
{
$this->zbuffer[0][0] = 22;
$this->ScreenWidth = $w;
$this->ScreenHeight = $h;
$this->InfoText = "";
$this->focus = 500;
$this->scale = $scale;
$this->copy = true;
$this->rx = 0;
$this->ry = 0;
$this->rz = 0;
$this->op = 0;
$this->XAngle = $this->XAngle * PI / 180;
$this->YAngle = $this->YAngle * PI / 180;
$this->ZAngle = $this->ZAngle * PI / 180;
$this->screen = imagecreatetruecolor($this->ScreenWidth,$this->ScreenHeight);
imagefill($this->screen, 0, 0, imagecolorallocate($this->screen, $this->bacground[0], $this->bacground[1], $this->bacground[2]));
}

public function Draw()
{
if ($this->DrawAxes)
{
$tmp=$this->NumPoitObject;
$this->NumPoitObject=false;
for ($i=1;$i<=15;$i++)
{
$this->Line3D(-$i-1,0,0,-$i,0,0,255,0,0);
$this->Line3D($i,0,0,$i+1,0,0,255,0,0);
$this->pixel1(-$i,0,0,255,0,0,6);
$this->pixel1($i,0,0,255,0,0,6);
$this->Line3D(0,-$i-1,0,0,$i,0,0,255,0);
$this->Line3D(0,$i,0,0,$i+1,0,0,255,0);
$this->pixel1(0,-$i,0,0,255,0,6);
$this->pixel1(0,$i,0,0,255,0,6);
if ($this->ZAngle!=0||!$this->XAngle!=0)
{
$this->pixel1(0,0,-$i,255,0,255,6);
$this->pixel1(0,0,$i,255,0,255,6);
$this->Line3D(0,0,-$i-1,0,0,$i,255,0,255);
$this->Line3D(0,0,$i,0,0,$i+1,255,0,255);
}
}
$this->NumPoitObject = $tmp;
imagefilledrectangle($this->screen, 20, $this->ScreenHeight-60, 30, $this->ScreenHeight-50, imagecolorallocate($this->screen, 255,0,0));
imagefilledrectangle($this->screen, 20, $this->ScreenHeight-45, 30, $this->ScreenHeight-35, imagecolorallocate($this->screen, 0,255,0));
imagefilledrectangle($this->screen, 20, $this->ScreenHeight-30, 30, $this->ScreenHeight-20, imagecolorallocate($this->screen, 255,0,255));
ImageString($this->screen, 2, 40, $this->ScreenHeight-62, "- X", imagecolorallocate($this->screen,255,0,0));
ImageString($this->screen, 2, 40, $this->ScreenHeight-47, "- Y", imagecolorallocate($this->screen,0,255,0));
ImageString($this->screen, 2, 40, $this->ScreenHeight-32, "- Z", imagecolorallocate($this->screen,255,0,255));
}
if ($this->copy) ImageString($this->screen, 2, $this->ScreenWidth-200, $this->ScreenHeight-20, "Created by JDay (Для просмотра ссылки Войди или Зарегистрируйся)", imagecolorallocate($this->screen,150,150,120));
if (strlen($this->InfoText)>0)ImageString($this->screen, 2, $this->ScreenWidth - imagefontwidth(2)*strlen($this->InfoText)-20, 20, $this->InfoText, imagecolorallocate($this->screen,170,170,120));
unset($this->zbuffer);
return $this->screen;
}
public function SetPosition($x=0,$y=0,$z=0)
{
$this->Xpos = $x;
$this->Ypos = $y;
$this->Zpos = $z;
}
public function roudc($x=0,$y=0,$z=0)
{
$x=$x*$this->scale;$y=$y*$this->scale;$z=$z*$this->scale;
$ratio = $z/$this->focus+1;
$XP = $x/$ratio;
$YP = $y/$ratio;
return array("x"=>round($XP),"y"=>round($YP));
}

public function convert3dTo2d($x,$y,$z)
{
$x=$x*$this->scale;$y=$y*$this->scale;$z=$z*$this->scale;
$ratio = $z/$this->focus+1;
$XP = $x/$ratio;
$YP = $y/$ratio;
return array("x"=>round($XP),"y"=>round($YP));
}

public function object($array,$triangels, $render_mode = 0)
{
$tmin = 0;
$tmax = 0;
if (is_array($triangels))
{
for ($n=0;$n<=(count($triangels)/3)-1;$n++)
{
switch($render_mode)
{
case '1':
$points[] = $array[$triangels[$n*3]*3];
$points[] = $array[$triangels[$n*3]*3+1];
$points[] = $array[$triangels[$n*3]*3+2];
$points[] = $array[$triangels[$n*3+1]*3];
$points[] = $array[$triangels[$n*3+1]*3+1];
$points[] = $array[$triangels[$n*3+1]*3+2];
$points[] = $array[$triangels[$n*3+2]*3];
$points[] = $array[$triangels[$n*3+2]*3+1];
$points[] = $array[$triangels[$n*3+2]*3+2];
$this->poligon($points,122+$n*3,122+$n*3,122+$n*3);
break;
case '2':
if($tmin<min($array[$triangels[$n*3]*3],$array[$triangels[$n*3]*3+1],$array[$triangels[$n*3]*3+2]))$tmin = min($array[$triangels[$n*3]*3],$array[$triangels[$n*3]*3+1],$array[$triangels[$n*3]*3+2]);
$tmax = max($array[$triangels[$n*3]*3],$array[$triangels[$n*3]*3+1],$array[$triangels[$n*3]*3+2]);

$points[] = $array[$triangels[$n*3]*3];
$points[] = $array[$triangels[$n*3]*3+1];
$points[] = $array[$triangels[$n*3]*3+2];
$points[] = $array[$triangels[$n*3+1]*3];
$points[] = $array[$triangels[$n*3+1]*3+1];
$points[] = $array[$triangels[$n*3+1]*3+2];
$points[] = $array[$triangels[$n*3+2]*3];
$points[] = $array[$triangels[$n*3+2]*3+1];
$points[] = $array[$triangels[$n*3+2]*3+2];
$this->poligon($points,55,55,55,1);
break;
default:
$this->Line3D( $array[$triangels[$n*3]*3],$array[$triangels[$n*3]*3+1],$array[$triangels[$n*3]*3+2],
$array[$triangels[$n*3+1]*3],$array[$triangels[$n*3+1]*3+1],$array[$triangels[$n*3+1]*3+2],0,255,255);
$this->Line3D( $array[$triangels[$n*3+2]*3],$array[$triangels[$n*3+2]*3+1],$array[$triangels[$n*3+2]*3+2],
$array[$triangels[$n*3+1]*3],$array[$triangels[$n*3+1]*3+1],$array[$triangels[$n*3+1]*3+2],0,255,0);
$this->Line3D( $array[$triangels[$n*3]*3],$array[$triangels[$n*3]*3+1],$array[$triangels[$n*3]*3+2],
$array[$triangels[$n*3+2]*3],$array[$triangels[$n*3+2]*3+1],$array[$triangels[$n*3+2]*3+2],255,255,0);
}

$this->InfoText = "min: $tmin; max:$max;";
//$this->SetPosition(0,0,0);
//$this->scale = 0;
//$this->XAngle = 0;
//$this->YAngle = 0;
//$this->ZAngle = 0;
}
}

$this->op = 0;
for ($i=0;$i<=(count($array)/3)-1;$i++)
{
$this->op = $i;
$this->pixel1($array[$i*3],$array[$i*3+1],$array[$i*3+2],255,0,0);
}
}
public function poligon($points,$r,$g,$b,$rand=0)
{
$n=1;
for ($i=0;$i<=count($points)/3-1;$i++)
{
$rr=$r+$i*4;
$rg=$g+$i*4;
$rb=$b+$i*4;
$x=$points[$i*3];
$y=$points[$i*3+1];
$z=$points[$i*3+2];

$x=$x+$this->Xpos;
$y=$y+$this->Ypos;
$z=$z+$this->Zpos;
$tmp = $x;
$x = $x * cos($this->XAngle) - $y * sin($this->XAngle);
$y = $tmp * sin($this->XAngle) + $y * cos($this->XAngle);
$tmp = $y;
$y = $y * cos($this->YAngle) - $z * sin($this->YAngle);
$z = $tmp * sin($this->YAngle) + $z * cos($this->YAngle);
$tmp = $z;
$z = $z * cos($this->ZAngle) - $x * sin($this->ZAngle);
$x = $tmp * sin($this->ZAngle) + $x * cos($this->ZAngle);
$x=$x*$this->scale;$y=$y*$this->scale;$z=$z*$this->scale;
$Ar = $this->convert3dTo2d($x,$y,$z);
$pp[] = $this->ScreenWidth/2+$Ar["x"];
$pp[] = $this->ScreenHeight/2+$Ar["y"];
$n++;
if ($n>3)
{
$n = 1;
if (!$rand)
imagefilledpolygon ( $this->screen , $pp , count($pp)/2 , imagecolorallocate($this->screen,$r,$g,$b));
else
imagefilledpolygon ( $this->screen , $pp , count($pp)/2 , imagecolorallocate($this->screen,$rr,$rg,$rb));
unset($pp);
}
}

}
public function pixel($x,$y,$z,$r,$g,$b)
{

$x=$x+$this->Xpos;
$y=$y+$this->Ypos;
$z=$z+$this->Zpos;
$tmp = $x;
$x = $x * cos($this->XAngle) - $y * sin($this->XAngle);
$y = $tmp * sin($this->XAngle) + $y * cos($this->XAngle);
$tmp = $y;
$y = $y * cos($this->YAngle) - $z * sin($this->YAngle);
$z = $tmp * sin($this->YAngle) + $z * cos($this->YAngle);
$tmp = $z;
$z = $z * cos($this->ZAngle) - $x * sin($this->ZAngle);
$x = $tmp * sin($this->ZAngle) + $x * cos($this->ZAngle);
$x=$x*$this->scale;$y=$y*$this->scale;$z=$z*$this->scale;
$Ar = $this->convert3dTo2d($x,$y,$z);
imagesetpixel($this->screen,$this->ScreenWidth/2+$Ar["x"],$this->ScreenHeight/2+$Ar["y"],imagecolorallocate($this->screen,$r,$g,$b));
imageRectangle($this->screen,$this->ScreenWidth/2+$Ar["x"]-1,$this->ScreenHeight/2+$Ar["y"]-1,$this->ScreenWidth/2+$Ar["x"]+1,$this->ScreenHeight/2+$Ar["y"]+1,imagecolorallocate($this->screen,$r,$g,$b));
if ($this->ptext)
{
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]+5, $this->ScreenHeight/2+$Ar["y"]-12, "x: ".round($x,2), imagecolorallocate($this->screen,200,200,200));
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]+5, $this->ScreenHeight/2+$Ar["y"]-5, "y: ".round($y,2), imagecolorallocate($this->screen,200,200,200));
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]+5, $this->ScreenHeight/2+$Ar["y"]+2, "z: ".round($z,2), imagecolorallocate($this->screen,200,200,200));
}

}
public function pixel1($x,$y,$z,$r,$g,$b,$size = 8)
{
if($z>$this->zbuffer[$x][$y])
{
$this->zbuffer[$x][$y]=$z;
$x=$x+$this->Xpos;
$y=$y+$this->Ypos;
$z=$z+$this->Zpos;

$tmp = $x;
$x = $x * cos($this->XAngle) - $y * sin($this->XAngle);
$y = $tmp * sin($this->XAngle) + $y * cos($this->XAngle);
$tmp = $y;
$y = $y * cos($this->YAngle) - $z * sin($this->YAngle);
$z = $tmp * sin($this->YAngle) + $z * cos($this->YAngle);
$tmp = $z;
$z = $z * cos($this->ZAngle) - $x * sin($this->ZAngle);
$x = $tmp * sin($this->ZAngle) + $x * cos($this->ZAngle);
$x=$x*$this->scale;$y=$y*$this->scale;$z=$z*$this->scale;
$Ar = $this->convert3dTo2d($x,$y,$z);
imagefilledellipse ( $this->screen , $this->ScreenWidth/2+$Ar["x"], $this->ScreenHeight/2+$Ar["y"] , $size , $size , imagecolorallocate($this->screen,$r,$g,$b) );
//imageRectangle($this->screen,$this->ScreenWidth/2+$Ar["x"]-2,$this->ScreenHeight/2+$Ar["y"]-2,$this->ScreenWidth/2+$Ar["x"]+2,$this->ScreenHeight/2+$Ar["y"]+2,imagecolorallocate($this->screen,$r,$g,$b));
if ($this->ptext)
{
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]+5, $this->ScreenHeight/2+$Ar["y"]-12, "x: ".round($x,2), imagecolorallocate($this->screen,200,200,200));
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]+5, $this->ScreenHeight/2+$Ar["y"]-5, "y: ".round($y,2), imagecolorallocate($this->screen,200,200,200));
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]+5, $this->ScreenHeight/2+$Ar["y"]+2, "z: ".round($z,2), imagecolorallocate($this->screen,200,200,200));
}
if ($this->NumPoitObject)
{
ImageString($this->screen, 1, $this->ScreenWidth/2+$Ar["x"]-5, $this->ScreenHeight/2+$Ar["y"]-12, $this->op, imagecolorallocate($this->screen,200,200,200));
}
}//imagesetpixel($this->screen,$this->ScreenWidth/2+$Ar["x"]+1,$this->ScreenHeight/2+$Ar["y"]-1,imagecolorallocate($this->screen,$r,$g,$b));
}
public function Line3D($x,$y,$z,$x1,$y1,$z1,$r,$g,$b)
{
$x=$x+$this->Xpos;
$y=$y+$this->Ypos;
$z=$z+$this->Zpos;
$x1=$x1+$this->Xpos;
$y1=$y1+$this->Ypos;
$z1=$z1+$this->Zpos;
$tmp = $x;
$x = $x * cos($this->XAngle) - $y * sin($this->XAngle);
$y = $tmp * sin($this->XAngle) + $y * cos($this->XAngle);
$tmp = $y;
$y = $y * cos($this->YAngle) - $z * sin($this->YAngle);
$z = $tmp * sin($this->YAngle) + $z * cos($this->YAngle);
$tmp = $z;
$z = $z * cos($this->ZAngle) - $x * sin($this->ZAngle);
$x = $tmp * sin($this->ZAngle) + $x * cos($this->ZAngle);

$tmp = $x1;
$x1 = $x1 * cos($this->XAngle) - $y1 * sin($this->XAngle);
$y1 = $tmp * sin($this->XAngle) + $y1 * cos($this->XAngle);
$tmp = $y1;
$y1 = $y1 * cos($this->YAngle) - $z1 * sin($this->YAngle);
$z1 = $tmp * sin($this->YAngle) + $z1 * cos($this->YAngle);
$tmp = $z1;
$z1 = $z1 * cos($this->ZAngle) - $x1 * sin($this->ZAngle);
$x1 = $tmp * sin($this->ZAngle) + $x1 * cos($this->ZAngle);

$x=$x*$this->scale;$y=$y*$this->scale;$z=$z*$this->scale;
$x1=$x1*$this->scale;$y1=$y1*$this->scale;$z1=$z1*$this->scale;
$ar1 = $this->convert3dTo2d($x,$y,$z);
$ar2 = $this->convert3dTo2d($x1,$y1,$z1);
imageline($this->screen , $this->ScreenWidth/2+$ar1['x'] , $this->ScreenHeight/2+$ar1['y'] , $this->ScreenWidth/2+$ar2['x'] , $this->ScreenHeight/2+$ar2['y'] , imagecolorallocate($this->screen,$r,$g,$b));
}

public function __destruct()
{

}
}



//imagefill($img, 0, 0, imagecolorallocate($img, 5, 5, 5));
//imageline ($img , 0 , 0 , $imgWidth , $imgHeight , $line_color );
//$Ar = convert3dTo2d(5.9,-6.8,-3);imagesetpixel($img,320+$Ar["x"],240+$Ar["y"],imagecolorallocate($img,255,255,255));
//$Ar = convert3dTo2d(0,0,0);imagesetpixel($img,320+$Ar["x"],240+$Ar["y"],imagecolorallocate($img,255,255,255));

$r3d = new render3d(800,600,10);
//$r3d->XAngle = 0.52;
$r3d->YAngle = .49;
$r3d->ZAngle = .79;
$r3d->NumPoitObject = true;
$r3d->bacground = array(33,33,33);
$r3d->ptext = true;
//$r3d->DrawAxes = true;
$r3d->SetPosition(0,0,0);

$ctrlpoints = array(
-1.5, -1.5, -1.5,
-1.5, -1.5, 1.5,
1.5, -1.5, 1.5,
1.5, -1.5, -1.5,
-1, 1, -1,
-1, 1, 1,
1, 1, 1,
1, 1, -1);
$triangles = array(
0, 1, 2,
0,3,2,
4,5,6,
6,7,4,
1,2,5,
2,6,5,
2,3,7,
7,6,2,
3,0,4,
4,7,3,
0,1,5,
5,4,0
);
$r3d->object($ctrlpoints,$triangles,2);
$texture = ImageCreateFromPNG('pi_cratebigt.png');
$img = $r3d->draw();
ImageString($img, 4, 5, 5, "frame: ".$i, imagecolorallocate($img,200,200,200));
ImageString($img, 2, 5, 20, "xAngel: ".$r3d->XAngle."'", imagecolorallocate($img,200,200,200));
ImageString($img, 2, 5, 35, "yAngel: ".$r3d->YAngle."'", imagecolorallocate($img,200,200,200));
ImageString($img, 2, 5, 50, "zAngel: ".$r3d->ZAngle."'", imagecolorallocate($img,200,200,200));
imagepng($img,'3dr.png');
//var_dump($r3d->zbuffer);

//===================================animation==================================

$ff=0;
for ($i=0;$i<=62;$i++)
{
$r3d = new render3d(800,600,10);
//$r3d->DrawAxes = true;
//$r3d->SetPosition(0,0,0);
$r3d->NumPoitObject = true;
$r3d->bacground = array(0,0,0);
$r3d->ptext = true;
$r3d->XAngle = $ff;
$r3d->YAngle = 45;
$r3d->ZAngle = $ff;
$ff=$ff+0.1;
//$r3d->Line3D(0,0,0,10,10,0,0,255,0);
//$r3d->pixel(0,0,0,255,0,0);
$r3d->object($ctrlpoints, $triangles,2);




//$r3d->scale = 5;$r3d->SetPosition(-2,-10,-2.19);$r3d->object($ctrlpoints, $triangles);


$img = $r3d->draw();
ImageString($img, 4, 5, 5, "frame: ".$i, imagecolorallocate($img,200,200,200));

ImageString($img, 2, 5, 20, "xAngel: ".$r3d->XAngle."'", imagecolorallocate($img,200,200,200));
ImageString($img, 2, 5, 35, "yAngel: ".$r3d->YAngle."'", imagecolorallocate($img,200,200,200));
ImageString($img, 2, 5, 50, "zAngel: ".$r3d->ZAngle."'", imagecolorallocate($img,200,200,200));
imagegif($img,"frames/$i.gif");
$frames [ ] = "frames/$i.gif";
$framed [ ] = 5;
}
//------------------------------------------------------------------------------
require_once "../classes/agif.class.php";
$gif = new GIFEncoder ($frames, $framed, 0, 2, 0, 0, 0, "url");

FWrite( FOpen ( "3da2.gif", "wb" ), $gif->GetAnimation ( ) );
//==============================================================================


?>
<img src='3dr.png'><br>
<img src='3da2.gif'><br>
 
Назад
Сверху