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; }
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; }
/** * 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]); }
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(); }
/** * 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]); }
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(); } }