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

Тема в разделе "PHP", создана пользователем jday, 10 апр 2012.

Модераторы: latteo
  1. jday

    jday Писатель

    Регистр.:
    16 апр 2010
    Сообщения:
    7
    Симпатии:
    3
    Решил сделать свой рендер 3D на PHP+GD. Может и велосипед.. но свой !!!!!!
    [​IMG]
    [​IMG]

    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 (www.my-gs.info)", 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>
     
    antiterror нравится это.