1<?php 2 3class Image_3D_Driver_ZBuffer extends Image_3D_Driver 4{ 5 6 protected $_filetype; 7 protected $_points; 8 protected $_heigth; 9 10 public function __construct() 11 { 12 parent::__construct(); 13 14 $this->_filetype = 'png'; 15 16 $this->_points = array(); 17 $this->_heigth = array(); 18 } 19 20 public function createImage($x, $y) 21 { 22 $this->_image = imagecreatetruecolor($x, $y); 23 imagealphablending($this->_image, true); 24 imageSaveAlpha($this->_image, true); 25 } 26 27 protected function _getColor(Image_3D_Color $color, $alpha = 1.) 28 { 29 $values = $color->getValues(); 30 31 $values[0] = (int) round($values[0] * 255); 32 $values[1] = (int) round($values[1] * 255); 33 $values[2] = (int) round($values[2] * 255); 34 $values[3] = (int) round((1 - ((1 - $values[3]) * $alpha)) * 127); 35 36 if ($values[3] > 0) { 37 // Tranzparente Farbe allokieren 38 $color = imageColorExactAlpha($this->_image, $values[0], $values[1], $values[2], $values[3]); 39 if ($color === -1) { 40 // Wenn nicht Farbe neu alloziieren 41 $color = imageColorAllocateAlpha($this->_image, $values[0], $values[1], $values[2], $values[3]); 42 } 43 } else { 44 // Deckende Farbe allozieren 45 $color = imageColorExact($this->_image, $values[0], $values[1], $values[2]); 46 if ($color === -1) { 47 // Wenn nicht Farbe neu alloziieren 48 $color = imageColorAllocate($this->_image, $values[0], $values[1], $values[2]); 49 } 50 } 51 52 return $color; 53 } 54 55 public function setBackground(Image_3D_Color $color) 56 { 57 $bg = $this->_getColor($color); 58 imagefill($this->_image, 1, 1, $bg); 59 } 60 61 protected function _drawLine(Image_3D_Point $p1, Image_3D_Point $p2) 62 { 63 list($x1, $y1) = $p1->getScreenCoordinates(); 64 list($x2, $y2) = $p2->getScreenCoordinates(); 65 66 $z1 = $p1->getZ(); 67 $z2 = $p2->getZ(); 68 69 $steps = ceil(max(abs($x1 - $x2), abs($y1 - $y2))); 70 71 $xdiff = ($x2 - $x1) / $steps; 72 $ydiff = ($y2 - $y1) / $steps; 73 $zdiff = ($z2 - $z1) / $steps; 74 75 $points = array('height' => array(), 'coverage' => array()); 76 for ($i = 0; $i < $steps; $i++) { 77 $x = $x1 + $i * $xdiff; 78 79 $xFloor = floor($x); 80 $xCeil = ceil($x); 81 $xOffset = $x - $xFloor; 82 83 $y = $y1 + $i * $ydiff; 84 85 $yFloor = floor($y); 86 $yCeil = ceil($y); 87 $yOffset = $y - $yFloor; 88 89 if (!isset($points['coverage'][(int) $xFloor][(int) $yCeil])) { 90 $points['height'][(int) $xFloor][(int) $yCeil] = $z1 + $i * $zdiff; 91 $points['coverage'][(int) $xFloor][(int) $yCeil] = (1 - $xOffset) * $yOffset; 92 } else { 93 $points['coverage'][(int) $xFloor][(int) $yCeil] += (1 - $xOffset) * $yOffset; 94 } 95 96 if (!isset($points['coverage'][(int) $xFloor][(int) $yFloor])) { 97 $points['height'][(int) $xFloor][(int) $yFloor] = $z1 + $i * $zdiff; 98 $points['coverage'][(int) $xFloor][(int) $yFloor] = (1 - $xOffset) * (1 - $yOffset); 99 } else { 100 $points['coverage'][(int) $xFloor][(int) $yFloor] += (1 - $xOffset) * (1 - $yOffset); 101 } 102 103 if (!isset($points['coverage'][(int) $xCeil][(int) $yCeil])) { 104 $points['height'][(int) $xCeil][(int) $yCeil] = $z1 + $i * $zdiff; 105 $points['coverage'][(int) $xCeil][(int) $yCeil] = $xOffset * $yOffset; 106 } else { 107 $points['coverage'][(int) $xCeil][(int) $yCeil] += $xOffset * $yOffset; 108 } 109 110 if (!isset($points['coverage'][(int) $xCeil][(int) $yFloor])) { 111 $points['height'][(int) $xCeil][(int) $yFloor] = $z1 + $i * $zdiff; 112 $points['coverage'][(int) $xCeil][(int) $yFloor] = $xOffset * (1 - $yOffset); 113 } else { 114 $points['coverage'][(int) $xCeil][(int) $yFloor] += $xOffset * (1 - $yOffset); 115 } 116 } 117 return $points; 118 } 119 120 protected function _getPolygonOutlines($pointArray) 121 { 122 $map = array('height' => array(), 'coverage' => array()); 123 124 $last = end($pointArray); 125 foreach ($pointArray as $point) { 126 $line = $this->_drawLine($last, $point); 127 $last = $point; 128 // Merge line to map 129 foreach ($line['height'] as $x => $row) { 130 foreach ($row as $y => $height) { 131 $map['height'][(int) $x][(int) $y] = $height; 132 $map['coverage'][(int) $x][(int) $y] = $line['coverage'][(int) $x][(int) $y]; 133 } 134 } 135 } 136 137 return $map; 138 } 139 140 public function drawPolygon(Image_3D_Polygon $polygon) 141 { 142 $points = $this->_getPolygonOutlines($polygon->getPoints()); 143 144 foreach ($points['coverage'] as $x => $row) { 145 if (count($row) < 2) { 146 continue; 147 } 148 149 $start = min(array_keys($row)); 150 $end = max(array_keys($row)); 151 152 $zStart = $points['height'][$x][$start]; 153 $zEnd = $points['height'][$x][$end]; 154 $zStep = ($zEnd - $zStart) / ($end - $start); 155 156 // Starting point 157 $this->_heigth[$x][$start][(int) ($zStart * 100)] = $this->_getColor($polygon->getColor(), $points['coverage'][$x][$start]); 158 159 // the way between 160 for ($y = $start + 1; $y < $end; $y++) { 161 $this->_heigth[$x][$y][(int) (($zStart + $zStep * ($y - $start)) * 100)] = $this->_getColor($polygon->getColor()); 162 } 163 164 // Ending point 165 $this->_points[$x][$end][(int) ($zEnd * 100)] = $this->_getColor($polygon->getColor(), $points['coverage'][$x][$end]); 166 } 167 } 168 169 public function drawGradientPolygon(Image_3D_Polygon $polygon) 170 { 171 $this->drawPolygon($polygon); 172 } 173 174 public function setFiletye($type) 175 { 176 $type = strtolower($type); 177 if (in_array($type, array('png', 'jpeg'))) { 178 $this->_filetype = $type; 179 return true; 180 } else { 181 return false; 182 } 183 } 184 185 public function save($file) 186 { 187 188 foreach ($this->_heigth as $x => $row) { 189 foreach ($row as $y => $points) { 190 krsort($points); 191 foreach ($points as $color) { 192 imagesetpixel($this->_image, $x, $y, $color); 193 } 194 } 195 } 196 197 switch ($this->_filetype) { 198 case 'png': 199 return imagepng($this->_image, $file); 200 case 'jpeg': 201 return imagejpeg($this->_image, $file); 202 } 203 } 204 205 public function getSupportedShading() 206 { 207 return array(Image_3D_Renderer::SHADE_NO, 208 Image_3D_Renderer::SHADE_FLAT); 209 } 210} 211 212?> 213