示例#1
0
 public function sub(Image_3D_Vector $vector)
 {
     $this->_x -= $vector->getX();
     $this->_y -= $vector->getY();
     $this->_z -= $vector->getZ();
     $this->_length = null;
 }
示例#2
0
 public function getAngle(Image_3D_Vector $vector)
 {
     $length = $vector->length() * $this->length();
     if ($length < 0.0001) {
         return 1;
     }
     return abs(acos($this->scalar($vector) / $length) / M_PI - 0.5) * 2;
 }
示例#3
0
 public function getColor(Image_3D_Interface_Enlightenable $polygon)
 {
     $color = clone $polygon->getColor();
     $light = new Image_3D_Vector($this->_x, $this->_y, $this->_z);
     $light->sub($polygon->getPosition());
     $light->unify();
     $light->add(new Image_3D_Vector(0, 0, -1));
     $normale = $polygon->getNormale();
     $angle = abs(1 - $normale->getAngle($light));
     $color->addLight($this->_color, $angle);
     return $color;
 }
示例#4
0
 public function getColor(Image_3D_Interface_Enlightenable $polygon)
 {
     $color = clone $polygon->getColor();
     // Create vector from polygons point to light source
     $light = new Image_3D_Vector($this->_x, $this->_y, $this->_z);
     $light->sub($polygon->getPosition());
     // Create vector from polygons point to camera
     //        $camera = new Image_3D_Vector(0, 0, -100);
     //        $camera->sub($polygon->getPosition());
     // Compare with polygones normale vector
     $normale = $polygon->getNormale();
     $angle = $normale->getAngle($light);
     // Use angle as light intensity
     $color->addLight($this->_color, $angle);
     return $color;
 }
示例#5
0
 public function getColor(Image_3D_Interface_Enlightenable $polygon)
 {
     $color = clone $polygon->getColor();
     $light = new Image_3D_Vector($this->_x, $this->_y, $this->_z);
     $light->sub($polygon->getPosition());
     $distance = $light->length();
     if ($distance > $this->_distance) {
         return $color;
     }
     $factor = 1 - pow($distance / $this->_distance, $this->_falloff);
     $light->unify();
     $light->add(new Image_3D_Vector(0, 0, -1));
     $normale = $polygon->getNormale();
     $angle = abs(1 - $normale->getAngle($light));
     $color->addLight($this->_color, $angle * $factor);
     return $color;
 }
示例#6
0
 public function getColor(Image_3D_Interface_Enlightenable $polygon)
 {
     $color = clone $polygon->getColor();
     $light = new Image_3D_Vector($this->_x, $this->_y, $this->_z);
     $light->sub($polygon->getPosition());
     $light->unify();
     $angle = $light->getAngle($this->_direction);
     if ($angle > $this->_angle) {
         return $color;
     }
     if ($this->_float) {
         $factor = 1 - pow($angle / $this->_angle, $this->_float);
     } else {
         $factor = 1;
     }
     $light->add(new Image_3D_Vector(0, 0, -1));
     $normale = $polygon->getNormale();
     $angle = abs(1 - $normale->getAngle($light));
     $color->addLight($this->_color, $angle * $factor);
     return $color;
 }
示例#7
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();
 }
示例#8
0
 public function __toString()
 {
     return parent::__toString() . ' -> ' . $this->getDirection()->__toString();
 }
示例#9
0
 public function distance(Image_3D_Line $line)
 {
     // Calculate parameters for plane
     $normale = $this->getNormale();
     $A = $normale->getX();
     $B = $normale->getY();
     $C = $normale->getZ();
     $D = -($normale->getX() * $this->_points[0]->getX() + $normale->getY() * $this->_points[0]->getY() + $normale->getZ() * $this->_points[0]->getZ());
     // Calculate wheather and where line cuts the polygons plane
     $lineDirection = $line->getDirection();
     $denominator = -($A * $line->getX() + $B * $line->getY() + $C * $line->getZ() + $D);
     $numerator = $A * $lineDirection->getX() + $B * $lineDirection->getY() + $C * $lineDirection->getZ();
     // Nu cut, when denomintor equals 0 (parallel plane)
     if ((int) ($denominator * 100000) === 0) {
         return false;
     }
     if ((int) ($numerator * 100000) === 0) {
         return false;
     }
     $t = $denominator / $numerator;
     // No cut, when $t < 0 (plane is behind the camera)
     if ($t <= 0) {
         return false;
     }
     // TODO: Perhaps add max distance check with unified normale vector
     // Calculate cutting point between line an plane
     $cuttingPoint = $line->calcPoint($t);
     // Perform fast check for point in bounding cube;
     if ($cuttingPoint->getX() < $this->_boundingRect[0] || $cuttingPoint->getY() < $this->_boundingRect[1] || $cuttingPoint->getZ() < $this->_boundingRect[2] || $cuttingPoint->getX() > $this->_boundingRect[3] || $cuttingPoint->getY() > $this->_boundingRect[4] || $cuttingPoint->getZ() > $this->_boundingRect[5]) {
         return false;
     }
     // perform exact check for point in polygon
     $lastScalar = 0;
     foreach ($this->_points as $nr => $point) {
         $nextPoint = $this->_points[($nr + 1) % count($this->_points)];
         $edge = new Image_3D_Vector($nextPoint->getX() - $point->getX(), $nextPoint->getY() - $point->getY(), $nextPoint->getZ() - $point->getZ());
         $v = new Image_3D_Vector($cuttingPoint->getX() - $point->getX(), $cuttingPoint->getY() - $point->getY(), $cuttingPoint->getZ() - $point->getZ());
         $scalar = $edge->crossProduct($v)->scalar($normale);
         if ($scalar * $lastScalar >= 0) {
             $lastScalar = $scalar;
         } else {
             return false;
         }
     }
     // Point is in polygon, return distance to polygon
     return $t;
 }