예제 #1
0
파일: ASCII.php 프로젝트: ricberw/BotQueue
 protected function _drawLine(Image_3D_Point $p1, Image_3D_Point $p2)
 {
     list($x1, $y1) = $p1->getScreenCoordinates();
     list($x2, $y2) = $p2->getScreenCoordinates();
     $steps = ceil(max(abs($x1 - $x2), abs($y1 - $y2)));
     $xdiff = ($x2 - $x1) / $steps;
     $ydiff = ($y2 - $y1) / $steps;
     $points = array();
     for ($i = 0; $i < $steps; ++$i) {
         $points[(int) round($x1 + $i * $xdiff)][(int) round($y1 + $i * $ydiff)] = true;
     }
     return $points;
 }
예제 #2
0
 protected function _drawLine(Image_3D_Point $p1, Image_3D_Point $p2)
 {
     list($x1, $y1) = $p1->getScreenCoordinates();
     list($x2, $y2) = $p2->getScreenCoordinates();
     $z1 = $p1->getZ();
     $z2 = $p2->getZ();
     $steps = ceil(max(abs($x1 - $x2), abs($y1 - $y2)));
     $xdiff = ($x2 - $x1) / $steps;
     $ydiff = ($y2 - $y1) / $steps;
     $zdiff = ($z2 - $z1) / $steps;
     $points = array('height' => array(), 'coverage' => array());
     for ($i = 0; $i < $steps; $i++) {
         $x = $x1 + $i * $xdiff;
         $xFloor = floor($x);
         $xCeil = ceil($x);
         $xOffset = $x - $xFloor;
         $y = $y1 + $i * $ydiff;
         $yFloor = floor($y);
         $yCeil = ceil($y);
         $yOffset = $y - $yFloor;
         if (!isset($points['coverage'][(int) $xFloor][(int) $yCeil])) {
             $points['height'][(int) $xFloor][(int) $yCeil] = $z1 + $i * $zdiff;
             $points['coverage'][(int) $xFloor][(int) $yCeil] = (1 - $xOffset) * $yOffset;
         } else {
             $points['coverage'][(int) $xFloor][(int) $yCeil] += (1 - $xOffset) * $yOffset;
         }
         if (!isset($points['coverage'][(int) $xFloor][(int) $yFloor])) {
             $points['height'][(int) $xFloor][(int) $yFloor] = $z1 + $i * $zdiff;
             $points['coverage'][(int) $xFloor][(int) $yFloor] = (1 - $xOffset) * (1 - $yOffset);
         } else {
             $points['coverage'][(int) $xFloor][(int) $yFloor] += (1 - $xOffset) * (1 - $yOffset);
         }
         if (!isset($points['coverage'][(int) $xCeil][(int) $yCeil])) {
             $points['height'][(int) $xCeil][(int) $yCeil] = $z1 + $i * $zdiff;
             $points['coverage'][(int) $xCeil][(int) $yCeil] = $xOffset * $yOffset;
         } else {
             $points['coverage'][(int) $xCeil][(int) $yCeil] += $xOffset * $yOffset;
         }
         if (!isset($points['coverage'][(int) $xCeil][(int) $yFloor])) {
             $points['height'][(int) $xCeil][(int) $yFloor] = $z1 + $i * $zdiff;
             $points['coverage'][(int) $xCeil][(int) $yFloor] = $xOffset * (1 - $yOffset);
         } else {
             $points['coverage'][(int) $xCeil][(int) $yFloor] += $xOffset * (1 - $yOffset);
         }
     }
     return $points;
 }
예제 #3
0
 /**
  * Caclulate Screen Coordinates
  *
  * Calculate isometric screen coordinates for a point 
  *
  * @param Image_3D_Point $point Point to process
  *
  * @return  void
  */
 protected function _calculateScreenCoordiantes(Image_3D_Point $point)
 {
     $point->setScreenCoordinates($point->getX() - $point->getZ() * 0.35 + $this->_size[0], $point->getY() + $point->getZ() * 0.35 + $this->_size[1]);
 }
예제 #4
0
 protected function _sendRay(Image_3D_Line $ray, $depth)
 {
     if ($depth <= 0) {
         return false;
     }
     $lowest = 1000;
     $nearest = false;
     foreach ($this->_polygones as $nr => $polygon) {
         $t = $polygon->distance($ray);
         if ($t === false) {
             continue;
         }
         if ($t < $lowest) {
             $nearest = $nr;
             $lowest = $t;
         }
     }
     if ($nearest === false) {
         return false;
     }
     // Examine cutting point
     $cuttingPoint = clone $ray;
     $direction = $cuttingPoint->getDirection();
     $cuttingPoint->add($cuttingPoint->getDirection()->multiply($lowest));
     // Create point to use for enlightenment
     $point = new Image_3D_Point($cuttingPoint->getX(), $cuttingPoint->getY(), $cuttingPoint->getZ());
     $point->addVector($this->_polygones[$nearest]->getNormale());
     $point->addColor($this->_polygones[$nearest]->getColor());
     // Perhaps send new rays
     $transparency = end($this->_polygones[$nearest]->getColor()->getValues());
     $reflection = $this->_polygones[$nearest]->getColor()->getReflection();
     if ($reflection > 0) {
         // Calculate reflection vector
         $normale = $this->_polygones[$nearest]->getNormale();
         $normale->unify();
         $direction = $ray->getDirection();
         $reflectionRay = new Image_3D_Line($cuttingPoint->getX(), $cuttingPoint->getY(), $cuttingPoint->getZ(), $direction->sub($normale->multiply($normale->scalar($direction))->multiply(2)));
         $reflectionColor = $this->_sendRay($reflectionRay, $depth - 1);
         if ($reflectionColor === false) {
             $reflectionColor = $this->_background;
         }
         $reflectionColor->mixAlpha($reflection);
         $point->addColor($reflectionColor);
     }
     if ($transparency > 0) {
         // Calculate colors in the back of our polygon
         $transparencyRay = new Image_3D_Line($cuttingPoint->getX(), $cuttingPoint->getY(), $cuttingPoint->getZ(), $ray->getDirection());
         $transparencyColor = $this->_sendRay($transparencyRay, $depth - 1);
         if ($transparencyColor === false) {
             $transparencyColor = $this->_background;
         }
         $transparencyColor->mixAlpha($transparency);
         $point->addColor($transparencyColor);
     }
     // Check lights influence for cutting point
     $pointLights = array();
     foreach ($this->_lights as $light) {
         // Check for shadow casting polygones
         if ($this->_shadows) {
             // Create line from point to light source
             $lightVector = new Image_3D_Vector($light->getX(), $light->getY(), $light->getZ());
             $lightVector->sub($cuttingPoint);
             $lightVector = new Image_3D_Line($cuttingPoint->getX(), $cuttingPoint->getY(), $cuttingPoint->getZ(), $lightVector);
             // Check all polygones for possible shadows to cast
             $modifyingPolygones = array();
             $modifyLight = false;
             foreach ($this->_polygones as $polygon) {
                 $t = $polygon->distance($lightVector);
                 // $t > 1 means polygon is behind the light, but crosses the ray
                 if ($t !== false && $t < 1) {
                     $transparency = end($polygon->getColor()->getValues());
                     if ($transparency > 0) {
                         // Polygon modifies light source
                         $modifyingPolygones[] = $polygon;
                         $modifyLight = true;
                     } else {
                         // Does not use lightsource when non transparent polygon is in its way
                         continue 2;
                     }
                 }
             }
             // We only reach this code with no, or only transparent polygones
             if ($modifyLight) {
                 $light = clone $light;
                 $lightColor = $light->getRawColor()->getValues();
                 // Modify color for all polygones in the rays way to earth
                 foreach ($modifyingPolygones as $polygon) {
                     $polygonColor = $polygon->getColor()->getValues();
                     $lightColor[0] *= $polygonColor[0] * (1 - $polygonColor[3]);
                     $lightColor[1] *= $polygonColor[1] * (1 - $polygonColor[3]);
                     $lightColor[2] *= $polygonColor[2] * (1 - $polygonColor[3]);
                     $lightColor[3] *= $polygonColor[3];
                 }
                 $light->setColor(new Image_3D_Color($lightColor[0], $lightColor[1], $lightColor[2], $lightColor[3]));
             }
         }
         $pointLights[] = $light;
     }
     $point->calculateColor($pointLights);
     return $point->getColor();
 }
예제 #5
0
 /**
  * Caclulate Screen Coordinates
  *
  * Calculate perspectively screen coordinates for a point
  *
  * @param Image_3D_Point $point Point to process
  *
  * @return  void
  */
 protected function _calculateScreenCoordiantes(Image_3D_Point $point)
 {
     $viewpoint = 500.0;
     $distance = 500.0;
     $point->setScreenCoordinates($viewpoint * $point->getX() / ($point->getZ() + $distance) + $this->_size[0], $viewpoint * $point->getY() / ($point->getZ() + $distance) + $this->_size[1]);
 }
예제 #6
0
 public function addPoint(Image_3D_Point $point)
 {
     $this->_points[] = $point;
     // Adjust bounding rectangle
     if (!isset($this->_boundingRect[0]) || $point->getX() < $this->_boundingRect[0]) {
         $this->_boundingRect[0] = $point->getX();
     }
     if (!isset($this->_boundingRect[1]) || $point->getY() < $this->_boundingRect[1]) {
         $this->_boundingRect[1] = $point->getY();
     }
     if (!isset($this->_boundingRect[2]) || $point->getZ() < $this->_boundingRect[2]) {
         $this->_boundingRect[2] = $point->getZ();
     }
     if (!isset($this->_boundingRect[3]) || $point->getX() > $this->_boundingRect[3]) {
         $this->_boundingRect[3] = $point->getX();
     }
     if (!isset($this->_boundingRect[4]) || $point->getY() > $this->_boundingRect[4]) {
         $this->_boundingRect[4] = $point->getY();
     }
     if (!isset($this->_boundingRect[5]) || $point->getZ() > $this->_boundingRect[5]) {
         $this->_boundingRect[5] = $point->getZ();
     }
 }