1<?php 2 3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5/** 6 * 3d Library 7 * 8 * PHP versions 5 9 * 10 * LICENSE: 11 * This library is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * This library is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with this library; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 * @category Image 26 * @package Image_3D 27 * @author Kore Nordmann <3d@kore-nordmann.de> 28 * @copyright 1997-2005 Kore Nordmann 29 * @license http://www.gnu.org/licenses/lgpl.txt lgpl 2.1 30 * @version CVS: $Id$ 31 * @link http://pear.php.net/package/PackageName 32 * @since File available since Release 0.1.0 33 */ 34 35// {{{ Image_3D_Renderer 36 37/** 38 * Image_3D_Renderer 39 * 40 * @category Image 41 * @package Image_3D 42 * @author Kore Nordmann <3d@kore-nordmann.de> 43 * @copyright 1997-2005 Kore Nordmann 44 * @license http://www.gnu.org/licenses/lgpl.txt lgpl 2.1 45 * @version Release: @package_version@ 46 * @link http://pear.php.net/package/PackageName 47 * @since Class available since Release 0.1.0 48 */ 49abstract class Image_3D_Renderer 50{ 51 52 // {{{ properties 53 54 /** 55 * Worlds polygones 56 * 57 * @var array 58 */ 59 protected $_polygones; 60 61 /** 62 * Worlds points 63 * 64 * @var array 65 */ 66 protected $_points; 67 68 /** 69 * Worlds lights 70 * 71 * @var array 72 */ 73 protected $_lights; 74 75 /** 76 * Driver we use 77 * 78 * @var array 79 */ 80 protected $_driver; 81 82 /** 83 * Size of the Image 84 * 85 * @var array 86 */ 87 protected $_size; 88 89 /** 90 * Backgroundcolol 91 * 92 * @var Image_3D_Color 93 */ 94 protected $_background; 95 96 /** 97 * Type of Shading used 98 * 99 * @var integer 100 */ 101 protected $_shading; 102 103 // }}} 104 // {{{ Constants 105 106 /* 107 * No Shading 108 */ 109 const SHADE_NO = 0; 110 111 /* 112 * Flat Shading 113 */ 114 const SHADE_FLAT = 1; 115 /* 116 * Gauroud Shading 117 */ 118 const SHADE_GAUROUD = 2; 119 /* 120 * Phong Shading 121 */ 122 const SHADE_PHONG = 3; 123 124 // }}} 125 // {{{ __construct() 126 127 /** 128 * Constructor for Image_3D_Renderer 129 * 130 * Initialises the environment 131 * 132 * @return Image_3D_Renderer Instance of Renderer 133 */ 134 public function __construct() 135 { 136 $this->reset(); 137 } 138 139 // }}} 140 // {{{ reset() 141 142 /** 143 * Reset all changeable variables 144 * 145 * Initialises the environment 146 * 147 * @return void 148 */ 149 public function reset() 150 { 151 $this->_objects = array(); 152 $this->_polygones = array(); 153 154 $this->_points = array(); 155 $this->_lights = array(); 156 $this->_size = array(0, 0); 157 158 $this->_background = null; 159 160 $this->_driver = null; 161 162 $this->_shading = self::SHADE_PHONG; 163 } 164 165 // }}} 166 // {{{ _getPolygones() 167 168 /** 169 * Get and merge polygones 170 * 171 * Get polygones and points from an object and merge them unique to local 172 * polygon- and pointarrays. 173 * 174 * @param Image_3D_Object $object Object to merge 175 * 176 * @return void 177 */ 178 protected function _getPolygones(Image_3D_Object $object) 179 { 180 $newPolygones = $object->getPolygones(); 181 182 $this->_polygones = array_merge($this->_polygones, $newPolygones); 183 184 // Add points unique to points-Array 185 foreach ($newPolygones as $polygon) { 186 $points = $polygon->getPoints(); 187 foreach ($points as $point) { 188 if (!$point->isProcessed()) { 189 $point->processed(); 190 array_push($this->_points, $point); 191 } 192 } 193 } 194 } 195 196 // }}} 197 // {{{ _calculateScreenCoordiantes() 198 199 /** 200 * Caclulate Screen Coordinates 201 * 202 * Calculate screen coordinates for a point according to the perspektive 203 * the renderer should display 204 * 205 * @param Image_3D_Point $point Point to process 206 * 207 * @return void 208 */ 209 abstract protected function _calculateScreenCoordiantes(Image_3D_Point $point); 210 211 // }}} 212 // {{{ _sortPolygones() 213 214 /** 215 * Sort polygones 216 * 217 * Set the order the polygones will be displayed 218 * 219 * @return void 220 */ 221 abstract protected function _sortPolygones(); 222 223 // }}} 224 // {{{ addObjects() 225 226 /** 227 * Add objects to renderer 228 * 229 * Add objects to renderer. Only objects which are added will be 230 * displayed 231 * 232 * @param array $objects Array of objects 233 * 234 * @return void 235 */ 236 public function addObjects($objects) 237 { 238 if (is_array($objects)) { 239 foreach ($objects as $object) { 240 if ($object instanceof Image_3D_Object) { 241 $this->_getPolygones($object); 242 } 243 } 244 } elseif ($objects instanceof Image_3D_Object) { 245 $this->_getPolygones($objects); 246 } 247 } 248 249 // }}} 250 // {{{ addObjects() 251 252 /** 253 * Add objects to renderer 254 * 255 * Add objects to renderer. Only objects which are added will be 256 * displayed 257 * 258 * @param array $lights Array of objects 259 * 260 * @return void 261 */ 262 public function addLights($lights) 263 { 264 $this->_lights = array_merge($this->_lights, $lights); 265 } 266 267 // }}} 268 // {{{ setSize() 269 270 /** 271 * Set image size 272 * 273 * Set the size of the destination image. 274 * 275 * @param integer $x Width 276 * @param integer $y Height 277 * 278 * @return void 279 */ 280 public function setSize($x, $y) 281 { 282 $this->_size = array($x / 2, $y / 2); 283 } 284 285 // }}} 286 // {{{ setBackgroundColor() 287 288 /** 289 * Set the Backgroundcolor 290 * 291 * Set the backgroundcolor of the destination image. 292 * 293 * @param Image_3D_Color $color Backgroundcolor 294 * 295 * @return void 296 */ 297 public function setBackgroundColor(Image_3D_Color $color) 298 { 299 $this->_background = $color; 300 } 301 302 // }}} 303 // {{{ setShading() 304 305 /** 306 * Set the quality of the shading 307 * 308 * Set the quality of the shading. Standard value is the maximum shading 309 * quality the driver is able to render. 310 * 311 * @param integer $shading Shading quality 312 * 313 * @return void 314 */ 315 public function setShading($shading) 316 { 317 $this->_shading = min($this->_shading, (int) $shading); 318 } 319 320 // }}} 321 // {{{ setDriver() 322 323 /** 324 * Set the driver 325 * 326 * Set the driver the image should be rendered with 327 * 328 * @param Image_3D_Driver $driver Driver to use 329 * 330 * @return void 331 */ 332 public function setDriver(Image_3D_Driver $driver) 333 { 334 $this->_driver = $driver; 335 336 $this->setShading(max($driver->getSupportedShading())); 337 } 338 339 // }}} 340 // {{{ getPolygonCount() 341 342 /** 343 * Return polygon count 344 * 345 * Return the number of used polygones in this image 346 * 347 * @return integer Number of Polygones 348 */ 349 public function getPolygonCount() 350 { 351 return count($this->_polygones); 352 } 353 354 // }}} 355 // {{{ getPointCount() 356 357 /** 358 * Return point count 359 * 360 * Return the number of used points in this image 361 * 362 * @return integer Number of Points 363 */ 364 public function getPointCount() 365 { 366 return count($this->_points); 367 } 368 369 // }}} 370 // {{{ getLightCount() 371 372 /** 373 * Return light count 374 * 375 * Return the number of used lights in this image 376 * 377 * @return integer Number of Lights 378 */ 379 public function getLightCount() 380 { 381 return count($this->_lights); 382 } 383 384 // }}} 385 // {{{ _calculatePolygonColors() 386 387 /** 388 * Calculate the color of all polygones 389 * 390 * Let each polygon calculate his color based on the lights which are 391 * registered for this image 392 * 393 * @return void 394 */ 395 protected function _calculatePolygonColors() 396 { 397 foreach ($this->_polygones as $polygon) { 398 $polygon->calculateColor($this->_lights); 399 } 400 } 401 402 // }}} 403 // {{{ _calculatePointColors() 404 405 /** 406 * Calculate the colors of all points 407 * 408 * Let each point calculate his color based on his normale which is 409 * calculated on his surrounding polygones and the lights which are 410 * registered for this image 411 * 412 * @return void 413 */ 414 protected function _calculatePointColors() 415 { 416 foreach ($this->_polygones as $polygon) { 417 $normale = $polygon->getNormale(); 418 $color = $polygon->getColor(); 419 420 $points = $polygon->getPoints(); 421 foreach ($points as $point) { 422 $point->addVector($normale); 423 $point->addColor($color); 424 } 425 } 426 427 foreach ($this->_points as $point) { 428 $point->calculateColor($this->_lights); 429 } 430 } 431 432 // }}} 433 // {{{ _shade() 434 435 /** 436 * Draw all polygones 437 * 438 * Draw all polygones concerning the type of shading wich was set for the renderer 439 * 440 * @return void 441 */ 442 protected function _shade() 443 { 444 switch ($this->_shading) { 445 case self::SHADE_NO: 446 foreach ($this->_polygones as $polygon) { 447 $this->_driver->drawPolygon($polygon); 448 } 449 break; 450 451 case self::SHADE_FLAT: 452 $this->_calculatePolygonColors(); 453 foreach ($this->_polygones as $polygon) { 454 $this->_driver->drawPolygon($polygon); 455 } 456 break; 457 458 case self::SHADE_GAUROUD: 459 $this->_calculatePointColors(); 460 foreach ($this->_polygones as $polygon) { 461 $this->_driver->drawPolygon($polygon); 462 } 463 break; 464 465 default: 466 throw new Exception('Shading type not supported.'); 467 break; 468 } 469 } 470 471 // }}} 472 // {{{ render() 473 474 /** 475 * Render the image 476 * 477 * Render the image into the metioned file 478 * 479 * @param string $file Filename 480 * 481 * @return void 482 */ 483 public function render($file) 484 { 485 if (empty($this->_driver)) { 486 return false; 487 } 488 489 // Calculate screen coordinates 490 foreach ($this->_points as $point) { 491 $this->_calculateScreenCoordiantes($point); 492 } 493 494 $this->_sortPolygones(); 495 496 // Draw background 497 $this->_driver->createImage($this->_size[0] * 2, $this->_size[1] * 2); 498 $this->_driver->setBackground($this->_background); 499 500 // Create polygones in driver 501 $this->_shade(); 502 503 // Save image 504 $this->_driver->save($file); 505 } 506 507 // }}} 508} 509 510// }}} 511