Code Snippets

  

PHP Source Code


Welcome to Dream.In.Code
Become a PHP Expert!

Join 149,620 PHP Programmers for FREE! Get instant access to thousands of PHP experts, tutorials, code snippets, and more! There are 1,885 people online right now. Registration is fast and FREE... Join Now!





3D Engine

A 3D engine written in PHP which highlights you can do anything if you set your mind to it.

Submitted By: grimpirate
Actions:
Rating:
Views: 2,628

Language: PHP

Last Modified: November 15, 2006

Snippet


  1. <?php
  2.      // Creates a virtual cube composed of polygons
  3.      $cube = new VirtualObject();
  4.      // Viewable screen dimensions
  5.      $width = 640;
  6.      $height = 480;
  7.      // Sets up the camera's orientation and its focal distance
  8.      $x = sqrt(2) / 2;
  9.      $focal = 500;
  10.      $a =     array(
  11.                     array(-$x, 0.5, -0.5, 0),
  12.                     array($x, 0.5, -0.5, 0),
  13.                     array(0, -$x, -$x, 0),
  14.                     array(0, 0, 0, 1)
  15.                );
  16.      // The vector normal to the viewing plane and parallel to the viewing direction
  17.      $n2[0][0] = $a[0][2];
  18.      $n2[1][0] = $a[1][2];
  19.      $n2[2][0] = $a[2][2];
  20.      $n2[3][0] = 0;
  21.      // Invert camera's plane to allow for change of basis
  22.      $a = inverse($a);
  23.      // Displace camera to its position in the world
  24.      $a[0][3] = 150;
  25.      $a[1][3] = 150;
  26.      $a[2][3] = 300 * $x;
  27.  
  28.      // Create two images
  29.      $image1 = imagecreate($width, $height);
  30.      $image2 = imagecreate($width, $height);
  31.      // Set the line thickness of each image
  32.      imagesetthickness($image1, 1);
  33.      imagesetthickness($image2, 1);
  34.      // Set the background colors for each image
  35.      $blue1 = imagecolorallocate($image1, 0, 0, 127);
  36.      $blue2 = imagecolorallocate($image2, 0, 0, 127);
  37.      // Define some colors for each image
  38.      $white = imagecolorallocate($image1, 255, 255, 255);
  39.      $gray = imagecolorallocate($image2, 127, 127, 127);
  40.  
  41.      // Draw each polygon
  42.      for($i = 0; $i < $cube->getPolyCount(); $i++){
  43.           // Retrieve the polygons from the cube object
  44.           $points = $cube->getPolygon($i);
  45.           // Modify each point of the polygon so that its now distanced to the camera's center point
  46.           for($j = 0; $j < 3; $j++){
  47.                $points[0][$j][0] -= $a[$j][3];
  48.                $points[1][$j][0] -= $a[$j][3];
  49.                $points[2][$j][0] -= $a[$j][3];
  50.           }
  51.           // Determine the normal vector for each polygon
  52.           $n1 = crossProduct(addition($points[0], scale(-1, $points[1])), addition($points[2], scale(-1, $points[1])));
  53.           // Write each vector in terms of the camera's orientation (change of basis)
  54.           $points[0] = multiply($a, $points[0]);
  55.           $points[1] = multiply($a, $points[1]);
  56.           $points[2] = multiply($a, $points[2]);
  57.           // Determine the distortion due to perspective
  58.           $focus[0] = $focal / magnitude($points[0]);
  59.           $focus[1] = $focal / magnitude($points[1]);
  60.           $focus[2] = $focal / magnitude($points[2]);
  61.           // Transform the 3d points into 2d coordinates for drawing
  62.           $x0 = $width / 2 + ($points[0][0][0] * $focus[0]);
  63.           $x1 = $width / 2 + ($points[1][0][0] * $focus[1]);
  64.           $x2 = $width / 2 + ($points[2][0][0] * $focus[2]);
  65.           $y0 = $height / 2 + ($points[0][1][0] * $focus[0]);
  66.           $y1 = $height / 2 + ($points[1][1][0] * $focus[1]);
  67.           $y2 = $height / 2 + ($points[2][1][0] * $focus[2]);
  68.           // Determine the cosine of the angle between the viewing plane and the polygonal plane
  69.           $cosTheta = dotProduct($n1, $n2) / (magnitude($n1) * magnitude($n2));
  70.           if($cosTheta <= 0){
  71.                // White lines because these are the planes at the front of the object
  72.                imageline($image1, $x0, $y0, $x1, $y1, $white);
  73.                imageline($image1, $x1, $y1, $x2, $y2, $white);
  74. //               imageline($image1, $x2, $y2, $x0, $y0, $white);     // Draws the final polygon line
  75.           }else{
  76.                // Gray lines because these are the planes at the reare of the object
  77.                imageline($image2, $x0, $y0, $x1, $y1, $gray);
  78.                imageline($image2, $x1, $y1, $x2, $y2, $gray);
  79. //               imageline($image2, $x2, $y2, $x0, $y0, $gray);     // Draws the final polygon line
  80.           }
  81.      }
  82.  
  83.      // Make transparent the background of the viewable polygon drawing
  84.      imagecolortransparent($image1, $blue1);
  85.      // Layer it over the non-viewable polygon drawing
  86.      imagecopymerge($image2, $image1, 0, 0, 0, 0, 640, 480, 100);
  87.      // Output the finished image
  88.      imagepng($image2);
  89.      // Destroy the images
  90.      imagedestroy($image1);
  91.      imagedestroy($image2);
  92.  
  93.      // Computes the cross product of two vectors
  94.      // $a: a row or column vector
  95.      // $b: a row or column vector
  96.      function crossProduct($a, $b){
  97.           if(sizeof($a) == 1){     // Cross product of row vectors
  98.                return     array(     // Return the cross product of row vectors as a row vector
  99.                               array(     $a[0][1] * $b[0][2] - $a[0][2] * $b[0][1],
  100.                                         -1 * ($a[0][0] * $b[0][2] - $a[0][2] * $b[0][0]),
  101.                                         $a[0][0] * $b[0][1] - $a[0][1] * $b[0][0],
  102.                                         0
  103.                               )
  104.                          );
  105.           }else{     // Cross product of column vectors
  106.                return     array(     // Return the cross product of column vectors as a column vector
  107.                               array($a[1][0] * $b[2][0] - $a[2][0] * $b[1][0]),
  108.                               array(-1 * ($a[0][0] * $b[2][0] - $a[2][0] * $b[0][0])),
  109.                               array($a[0][0] * $b[1][0] - $a[1][0] * $b[0][0]),
  110.                               array(0)
  111.                          );
  112.           }
  113.      }
  114.  
  115.      // Computes the addition of two matrices
  116.      // $A: an m x n matrix
  117.      // $B: an m x n matrix
  118.      function addition($A, $B){
  119.           $M;     // The added matrix
  120.  
  121.           // Add the two matrices together
  122.           for($i = 0; $i < sizeof($A); $i++){
  123.                for($j = 0; $j < sizeof($A[0]); $j++){
  124.                     $M[$i][$j] = $A[$i][$j] + $B[$i][$j];
  125.                }
  126.           }
  127.  
  128.           return $M;     // Return the added matrix
  129.      }
  130.  
  131.      // Computes a random matrix
  132.      // $m: the row dimension
  133.      // $n: the column dimension
  134.      // $lower: the lower bound of random numbers
  135.      // $upper: the upper bound of random numbers
  136.      function randMatrix($m, $n, $lower, $upper){
  137.           $M;     // A random matrix
  138.  
  139.           // Generate the random matrix
  140.           for($i = 0; $i < $m; $i++){
  141.                for($j = 0; $j < $n; $j++){
  142.                     $M[$i][$j] = rand($lower, $upper);
  143.                }
  144.           }
  145.  
  146.           return $M;     // Return the random matrix
  147.      }
  148.  
  149.      // Computes the magnitude of a vector
  150.      // $a: a row or column vector
  151.      function magnitude($a){
  152.           $result = 0;     // The magnitude of the vector
  153.  
  154.           // Use the Pythagorean theorem to determine the vector's magnitude
  155.           for($i = 0; $i < sizeof($a); $i++){
  156.                for($j = 0; $j < sizeof($a[0]); $j++){
  157.                     $result += pow($a[$i][$j], 2);
  158.                }
  159.           }
  160.  
  161.           return sqrt($result);     // Return the magnitude of the vector
  162.      }
  163.  
  164.      // Computes the adjoint of a matrix
  165.      // $A: a square matrix
  166.      function adjoint($A){
  167.           return scale(determinant($A), inverse($A));     // Returns the adjoint of a matrix
  168.      }
  169.  
  170.      // Computes a scaled matrix
  171.      // $k: a scalar number
  172.      // $A: an m x n matrix
  173.      function scale($k, $A){
  174.  
  175.           // Scale the matrix by multiplying each entry by k
  176.           for($i = 0; $i < sizeof($A); $i++){
  177.                for($j = 0; $j < sizeof($A[0]); $j++){
  178.                     $A[$i][$j] *= $k;
  179.                }
  180.           }
  181.  
  182.           return $A;     // Returns the scaled matrix
  183.      }
  184.  
  185.      // Computes the determinant of a matrix
  186.      // $A: a square matrix
  187.      function determinant($A){
  188.           $determinant = 1;     // The determinant of the matrix
  189.           $n = sizeof($A);     // Dimension of the square matrix
  190.           $E = identity($n);     // An elementary matrix
  191.  
  192.           // Find the determinant of a matrix by performing elementary matrix operations
  193.           // on an augmented matrix through the use of elementary matrices in order
  194.           // to convert the matrix into upper triangular form
  195.           // Multiply the diagonals of the upper triangular matrix to arrive at the
  196.           // determinant, only elementary operations I and III are allowed on the matrix.
  197.           // If operation I is performed at any time, multiply the determinant by a -1.
  198.           for($j = 0; $j < $n; $j++){
  199.                for($i = $j; $i < $n; $i++){
  200.                     if($i == $j){
  201.                          if($A[$i][$j] == 0){
  202.                               for($k = $j + 1; $k < $n; $k++){
  203.                                    if($A[$k][$j] != 0){
  204.                                         $swap = $A[$i];
  205.                                         $A[$i] = $A[$k];
  206.                                         $A[$k] = $swap;
  207.                                         $determinant *= -1;
  208.                                         $k = $n;
  209.                                    }
  210.                               }
  211.                          }
  212.                          $determinant *= $A[$i][$j];
  213.                     }else{
  214.                          $E[$i][$j] = -$A[$i][$j] / $A[$j][$j];
  215.                     }
  216.                     $A = multiply($E, $A);
  217.                     $E = identity($n);
  218.                }
  219.           }
  220.  
  221.           return $determinant;     // Return the determinant of the matrix
  222.      }
  223.  
  224.      // Computes the inverse of a matrix
  225.      // $A: a square matrix
  226.      function inverse($A){
  227.           $n = sizeof($A);     // Dimension of the square matrix
  228.           $V = identity($n);     // The inverse of the matrix
  229.           $E = identity($n);     // An elementary matrix
  230.  
  231.           // Find the inverse matrix by performing elementary matrix operations
  232.           // on an augmented matrix through the use of elementary matrices
  233.           for($j = 0; $j < $n; $j++){
  234.                for($i = $j; $i < $n; $i++){
  235.                     if($i == $j){
  236.                          if($A[$i][$j] == 0){
  237.                               for($k = $j + 1; $k < $n; $k++){
  238.                                    if($A[$k][$j] != 0){
  239.                                         $swap = $A[$i];
  240.                                         $A[$i] = $A[$k];
  241.                                         $A[$k] = $swap;
  242.                                         $swap = $V[$i];
  243.                                         $V[$i] = $V[$k];
  244.                                         $V[$k] = $swap;
  245.                                         $k = $n;
  246.                                    }
  247.                               }
  248.                          }
  249.                          $E[$i][$j] = 1 / $A[$i][$j];
  250.                     }else{
  251.                          $E[$i][$j] = -$A[$i][$j];
  252.                     }
  253.                     $A = multiply($E, $A);
  254.                     $V = multiply($E, $V);
  255.                     $E = identity($n);
  256.                }
  257.           }
  258.           for($j = $n - 1; $j > 0; $j--){
  259.                for($i = $j - 1; $i > -1; $i--){
  260.                     $E[$i][$j] = -$A[$i][$j];
  261.                     $A = multiply($E, $A);
  262.                     $V = multiply($E, $V);
  263.                     $E = identity($n);
  264.                }
  265.           }
  266.  
  267.           return $V;     // Return the inverse matrix
  268.      }
  269.  
  270.      // Computes the product of a matrix multiplication
  271.      // $A: An m x n matrix
  272.      // $B: An n x o matrix
  273.      function multiply($A, $B){
  274.           $M;     // The product of the multiplication
  275.           $B = transpose($B);     // Transpose the second matrix
  276.  
  277.           // Do the multiplication by making use of the dot product
  278.           for($i = 0; $i < sizeof($A); $i++){
  279.                for($j = 0; $j < sizeof($B); $j++){
  280.                     $M[$i][$j] = dotProduct(array($A[$i]), array($B[$j]));
  281.                }
  282.           }
  283.  
  284.           return $M;     // Return the product
  285.      }
  286.  
  287.      // Computes the dot product of two vectors
  288.      // $a: a row or column vector
  289.      // $b; a row or column vector
  290.      function dotProduct($a, $b){
  291.           $result = 0;     // The result of the dot product
  292.  
  293.           // The dot product
  294.           for($i = 0; $i < sizeof($a); $i++){
  295.                for($j = 0; $j < sizeof($a[0]); $j++){
  296.                     $result += $a[$i][$j] * $b[$i][$j];
  297.                }
  298.           }
  299.  
  300.           return $result;     // Return the dot product
  301.      }
  302.