Advertisement
bigorangemachine

PHP 3D Cube v0.2

Aug 31st, 2011
382
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.65 KB | None | 0 0
  1. <?php
  2. /**
  3.  * This script draws and outputs a Cube.
  4.  *
  5.  * The GD library is used to draw the cube and output it as a
  6.  * PNG image.
  7.  *
  8.  * Developed by Leonel Machava <leonelmachava@gmail.com>
  9.  * http://codentronix.com
  10.  * http://codentronix.com/2011/06/06/how-to-draw-a-cube-using-php/
  11.  *
  12.  * This code is released under the "MIT License" available at
  13.  * http://www.opensource.org/licenses/mit-license.php
  14.  * http://codentronix.com/2011/06/06/how-to-draw-a-cube-using-php/
  15.  *
  16.  * Cube3DImage adapted from provided example: bigorangemachine
  17.  */
  18.  
  19. /* Represents points in 3D space. */
  20. class Point3D {
  21.   public $x;
  22.   public $y;
  23.   public $z;
  24.  
  25.   public function __construct($x,$y,$z) {
  26.     $this->x = $x;
  27.     $this->y = $y;
  28.     $this->z = $z;
  29.   }
  30.  
  31.   public function rotateX($angle) {
  32.     $rad = $angle * M_PI / 180;
  33.     $cosa = cos($rad);
  34.     $sina = sin($rad);
  35.     $y = $this->y * $cosa - $this->z * $sina;
  36.     $z = $this->y * $sina + $this->z * $cosa;
  37.     return new Point3D($this->x, $y, $z);
  38.   }
  39.  
  40.   public function rotateY($angle) {
  41.     $rad = $angle * M_PI / 180;
  42.     $cosa = cos($rad);
  43.     $sina = sin($rad);
  44.     $z = $this->z * $cosa - $this->x * $sina;
  45.     $x = $this->z * $sina + $this->x * $cosa;
  46.     return new Point3D($x, $this->y, $z);
  47.   }
  48.  
  49.   public function rotateZ($angle) {
  50.     $rad = $angle * M_PI / 180;
  51.     $cosa = cos($rad);
  52.     $sina = sin($rad);
  53.     $x = $this->x * $cosa - $this->y * $sina;
  54.     $y = $this->x * $sina + $this->y * $cosa;
  55.     return new Point3D($x, $y, $this->z);
  56.   }
  57.  
  58.   public function project($width,$height,$fov,$viewerDistance) {
  59.     $factor = (float)($fov) / ($viewerDistance + $this->z);
  60.     $x = $this->x * $factor + $width / 2;
  61.     $y = -$this->y * $factor + $height / 2;
  62.     return new Point3D($x,$y,$this->z);
  63.   }
  64. }
  65. class Cube3DImage{
  66.   public function __construct($width,$height,$depth){
  67.         $this->width=$width;
  68.         $this->height=$height;
  69.         $this->depth=$depth;
  70.  
  71.         $this->rotate_x=0;
  72.         $this->rotate_y=0;
  73.         $this->rotate_z=0;
  74.  
  75.         $this->image_width=90;
  76.         $this->image_height=90;
  77.  
  78.         $this->fov=256;//viewable area - how much you see of the world (framing/canvas size)
  79.         $this->view_distance=4;//how far the camera or viewer is from the scene (camera tripod to the subject)
  80.  
  81.         $this->x_color=array(140,140,140);
  82.         $this->y_color=array(192,192,192);
  83.         $this->z_color=array(220,220,220);
  84.         $this->bg_color=array(249, 249, 249);
  85.     }
  86.     function rotate($axis,$val){
  87.         if(strtolower($axis)=='x'){$this->rotate_x=floatVal($val);}
  88.         else if(strtolower($axis)=='y'){$this->rotate_y=floatVal($val);}
  89.         else if(strtolower($axis)=='z'){$this->rotate_z=floatVal($val);}
  90.     }
  91.     function image(){
  92.         $vertices = array(
  93.             'a'=>new Point3D((abs($this->width/2)*(-1)), (abs($this->depth/2)), (abs($this->height/2)*(-1))),                   //a -> 0 = right, front, bottom
  94.             'b'=>new Point3D((abs($this->width/2)),  (abs($this->depth/2)), (abs($this->height/2)*(-1))),                           //b -> 1 = left, front, bottom
  95.             'c'=>new Point3D((abs($this->width/2)), (abs($this->depth/2)*(-1)),  (abs($this->height/2)*(-1))),              //c -> 2 = left, back, bottom
  96.             'd'=>new Point3D((abs($this->width/2)*(-1)), (abs($this->depth/2)*(-1)),  (abs($this->height/2)*(-1))),     //d -> 3 = right, back, bottom
  97.             'e'=>new Point3D((abs($this->width/2)*(-1)), (abs($this->depth/2)), (abs($this->height/2))),                            //e -> 4 = right, front, top
  98.             'f'=>new Point3D((abs($this->width/2)), (abs($this->depth/2)), (abs($this->height/2))),                                     //f -> 5 = left, front, top
  99.             'g'=>new Point3D((abs($this->width/2)), (abs($this->depth/2)*(-1)), (abs($this->height/2))),                            //g -> 6 = left, back, top
  100.             'h'=>new Point3D((abs($this->width/2)*(-1)), (abs($this->depth/2)*(-1)), (abs($this->height/2)))                    //h -> 7 = right, back, top
  101.         );
  102.         $faces = array(
  103.             'bottom'=>array('a', 'b', 'c', 'd'),// BOTTOM SIDE (a,b,c,d)
  104.             'left'=>array('b', 'f', 'g', 'c'),// LEFT SIDE (b,f,g,c)
  105.             'top'=>array('f', 'e', 'h', 'g'),// TOP SIDE (f,e,h,g)
  106.             'right'=>array('e','a', 'd', 'h'),// RIGHT SIDE (e,a,d,h)
  107.             'front'=>array('a', 'e', 'f', 'b'),// FRONT SIDE (a,e,f,b)
  108.             'back'=>array( 'd', 'c', 'g', 'h') // BACK SIDE (d,c,g,h)
  109.         );
  110.  
  111. /*                                                                  AXIS REFERENCE
  112.                                             Z (+1z)
  113.  CUBE VERTICLES 'POINTS'                    .    
  114.     g.  .  , h                              |      
  115.      :  f_ _._ e                            .    
  116.      ,  |    ,|                             |      
  117.     c; ,| .  ;|<-d                          .    
  118.      ` ,|_ _ _|                             |      
  119.         b     a                             .    
  120.                                             |      
  121.                                             .    
  122.                                             |      
  123.                                             .    
  124.                                             |      
  125.                                             .    
  126.                                             |      
  127.                                             ,      
  128.                                      .   /  *  \   ,
  129.                            ,    /         0,0,0        ` .
  130.                      /                                      `  \ .  
  131.              /   `                                                 `  \ .
  132.     (+1x) X                                                               Y (+1y)
  133.  
  134.  
  135. */
  136.         $im = imagecreatetruecolor($this->image_width, $this->image_height);//image resource
  137.         imagefill($im , 0, 0, imagecolorallocate($im, $this->bg_color[0], $this->bg_color[1], $this->bg_color[2]));//background color, draw a box from 0,0
  138.         $colors = array(
  139.             'bottom'=>$this->z_color,
  140.             'left'=>$this->x_color,
  141.             'top'=>$this->z_color,
  142.             'right'=>$this->x_color,
  143.             'front'=>$this->y_color,
  144.             'back'=>$this->y_color
  145.         );
  146.         foreach($colors as $k => $v){
  147.             $im_colors[$k] = imagecolorallocate($im,$v[0],$v[1],$v[2]);
  148.         }
  149.         /* It will store transformed vertices & preserve keys. */
  150.         $transform = array();
  151.         foreach($vertices as $k => $v){
  152.             $transform[$k] = $v->rotateX($this->rotate_x)->rotateY($this->rotate_y)->rotateZ($this->rotate_z)->project($this->image_width, $this->image_height, $this->fov, $this->view_distance);/* Transform all the vertices. */
  153.         }
  154.        
  155.         $avgZ = array();
  156.         /* Calculate the average Z value of each face & preserve keys */
  157.         foreach($faces as $k => $v){// as $k => $v
  158.             //$avgZ[$k] = ($transform[$v[0]]->z + $transform[$v[1]]->z + $transform[$v[2]]->z + $transform[$v[3]]->z) / 4;// divide by # of vertices/'points'
  159.             $avgZ[$k] = ($transform[$v[0]]->z + $transform[$v[1]]->z + $transform[$v[2]]->z + $transform[$v[3]]->z) / count($v);// 8/31/2011 divide by # of vertices/'points'
  160.         }
  161.         arsort($avgZ);
  162.  
  163.         foreach($avgZ as $k => $v){/* Draw the faces from back to front. */
  164.             $_face = $faces[$k];//'bottom'=>, 'left'=>, 'top'=>, 'right'=>, 'front'=>, 'back'=>
  165.             $points = array(
  166.                 $transform[$_face[0]]->x, $transform[$_face[0]]->y, // 0,1 => x1, y1
  167.                 $transform[$_face[1]]->x, $transform[$_face[1]]->y, // 2,3 => x2, y2
  168.                 $transform[$_face[2]]->x, $transform[$_face[2]]->y, // 4,5 => x3, y3
  169.                 $transform[$_face[3]]->x, $transform[$_face[3]]->y  // 6,7 => x4, y4
  170.             );
  171.             imagefilledpolygon($im,$points,4,$im_colors[$k]);
  172.         }
  173.  
  174.         header("Content-Type: image/png");/* Tell the browser/client we are outputing a PNG image. */
  175.         imagepng($im);/* Output the image. */
  176.     }
  177. }
  178. $width=14;//x cord
  179. $height=14;//z cord
  180. $depth=36;//y cord
  181. $cubeOBJ=new Cube3DImage($width, $height, $depth);
  182. $cubeOBJ->image_width=960;
  183. $cubeOBJ->image_height=960;
  184.  
  185. $cubeOBJ->rotate('x', 40);// up and down horizontally
  186. $cubeOBJ->rotate('y', 0);// side to side horizontally
  187. $cubeOBJ->rotate('z', 20);// tilt (tip/roll)
  188.  
  189. $cubeOBJ->image();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement