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 35require_once 'Image/3D/Paintable.php'; 36require_once 'Image/3D/Enlightenable.php'; 37 38require_once 'Image/3D/Color.php'; 39require_once 'Image/3D/Coordinate.php'; 40require_once 'Image/3D/Point.php'; 41require_once 'Image/3D/Vector.php'; 42require_once 'Image/3D/Line.php'; 43require_once 'Image/3D/Renderer.php'; 44require_once 'Image/3D/Driver.php'; 45 46require_once 'Image/3D/Paintable/Object.php'; 47require_once 'Image/3D/Paintable/Light.php'; 48require_once 'Image/3D/Paintable/Polygon.php'; 49 50// {{{ Image_3D 51 52/** 53 * Image_3D 54 * 55 * Class for creation of 3d images only with native PHP. 56 * 57 * @category Image 58 * @package Image_3D 59 * @author Kore Nordmann <3d@kore-nordmann.de> 60 * @copyright 1997-2005 Kore Nordmann 61 * @license http://www.gnu.org/licenses/lgpl.txt lgpl 2.1 62 * @version Release: @package_version@ 63 * @link http://pear.php.net/package/PackageName 64 * @since Class available since Release 0.1.0 65 */ 66class Image_3D 67{ 68 69 // {{{ properties 70 71 /** 72 * Backgroundcolor 73 * 74 * @var Image_3D_Color 75 */ 76 protected $_color; 77 78 /** 79 * List of known objects 80 * 81 * @var array 82 */ 83 protected $_objects; 84 85 /** 86 * List of lights 87 * 88 * @var array 89 */ 90 protected $_lights; 91 92 /** 93 * Active renderer 94 * 95 * @var Image_3D_Renderer 96 */ 97 protected $_renderer; 98 99 /** 100 * Active outputdriver 101 * 102 * @var Image_3D_Driver 103 */ 104 protected $_driver; 105 106 107 /** 108 * Options for rendering 109 */ 110 protected $_option; 111 112 /** 113 * Options set by the user 114 * 115 * @var array 116 */ 117 protected $_optionSet; 118 119 /** 120 * Begin of world creation 121 * 122 * @var float 123 */ 124 protected $_start; 125 126 // }}} 127 // {{{ constants 128 129 /** 130 * Option for filled polygones (depreceated) 131 */ 132 const IMAGE_3D_OPTION_FILLED = 1; 133 134 /** 135 * Option for backface culling (depreceated) 136 */ 137 const IMAGE_3D_OPTION_BF_CULLING = 2; 138 139 // }}} 140 // {{{ __construct() 141 142 /** 143 * Constructor for Image_3D 144 * 145 * Initialises the environment 146 * 147 * @return Image_3D World instance 148 */ 149 public function __construct() 150 { 151 $this->_objects = array(); 152 $this->_lights = array(); 153 $this->_renderer = null; 154 $this->_driver = null; 155 $this->_color = null; 156 157 $this->_option[self::IMAGE_3D_OPTION_FILLED] = true; 158 $this->_option[self::IMAGE_3D_OPTION_BF_CULLING] = true; 159 160 $this->_optionSet = array(); 161 162 $this->_start = microtime(true); 163 } 164 165 // }}} 166 // {{{ createObject() 167 168 /** 169 * Factory method for Objects 170 * 171 * Creates and returns a printable object. 172 * Standard objects with parameters: 173 * - cube array(float $x, float $y, float $z) 174 * - sphere array(float $r, int $detail) 175 * - 3ds string $filename 176 * - map [array(array(Image_3D_Point))] 177 * - text string $string 178 * 179 * @param string $type Objectname 180 * @param array $parameter Parameters 181 * 182 * @return Image_3D_Object Object instance 183 */ 184 public function createObject($type, $parameter = array()) 185 { 186 $name = ucfirst($type); 187 $class = 'Image_3D_Object_' . $name; 188 189 $absolute_path = dirname(__FILE__) . '/3D/Paintable/Object/' . $name . '.php'; 190 $user_path = dirname(__FILE__) . '/3D/User/Object/' . $name . '.php'; 191 192 if (is_file($absolute_path) && is_readable($absolute_path)) { 193 include_once $absolute_path; 194 } elseif (is_file($user_path) && is_readable($user_path)) { 195 include_once $user_path; 196 } else { 197 throw new Exception("Class for object $name not found (Searched: $absolute_path, $user_path)."); 198 } 199 200 return $this->_objects[] = new $class($parameter); 201 } 202 203 // }}} 204 // {{{ createLight() 205 206 /** 207 * Factory method for lights 208 * 209 * Creates and returns a light. Needs only the position of the lights as a 210 * parameter. 211 * 212 * @param string $type Class 213 * @param mixed $parameter Parameters 214 * 215 * @return Image_3D_Light Object instance 216 */ 217 public function createLight($type, $parameter = array()) 218 { 219 $name = ucfirst($type); 220 if ($name != 'Light') { 221 $class = 'Image_3D_Light_' . $name; 222 223 $absolute_path = dirname(__FILE__) . '/3D/Paintable/Light/' . $name . '.php'; 224 $user_path = dirname(__FILE__) . '/3D/User/Light/' . $name . '.php'; 225 226 if (is_file($absolute_path) && is_readable($absolute_path)) { 227 include_once $absolute_path; 228 } elseif (is_file($user_path) && is_readable($user_path)) { 229 include_once $user_path; 230 } else { 231 throw new Exception("Class for object $name not found (Searched: $absolute_path, $user_path)."); 232 } 233 234 return $this->_lights[] = new $class($parameter[0], $parameter[1], $parameter[2], array_slice($parameter, 3)); 235 } else { 236 return $this->_lights[] = new Image_3D_Light($parameter[0], $parameter[1], $parameter[2]); 237 } 238 } 239 240 // }}} 241 // {{{ createMatrix() 242 243 /** 244 * Factory method for transformation matrixes 245 * 246 * Creates a transformation matrix 247 * Known matrix types: 248 * - rotation array(float $x, float $y, float $z) 249 * - scale array(float $x, float $y, float $z) 250 * - move array(float $x, float $y, float $z) 251 * 252 * @param string $type Matrix type 253 * @param array $parameter Parameters 254 * 255 * @return Image_3D_Matrix Object instance 256 */ 257 public function createMatrix($type, $parameter = array()) 258 { 259 $name = ucfirst($type); 260 $class = 'Image_3D_Matrix_' . $name; 261 262 $absolute_path = dirname(__FILE__) . '/3D/Matrix/' . $name . '.php'; 263 264 if (is_file($absolute_path) && is_readable($absolute_path)) { 265 include_once $absolute_path; 266 } else { 267 throw new Exception("Class for matrix $name not found (Searched: $absolute_path, $user_path)."); 268 } 269 270 return new $class($parameter); 271 } 272 273 // }}} 274 // {{{ setColor() 275 276 /** 277 * Sets world backgroundcolor 278 * 279 * Sets the backgroundcolor for final image. Transparancy is not supported 280 * by all drivers 281 * 282 * @param Image_3D_Color $color Backgroundcolor 283 * 284 * @return void 285 */ 286 public function setColor(Image_3D_Color $color) 287 { 288 $this->_color = $color; 289 } 290 291 // }}} 292 // {{{ createRenderer() 293 294 /** 295 * Factory method for renderer 296 * 297 * Creates and returns a renderer. 298 * Avaible renderers 299 * - Isometric 300 * - Perspektively 301 * 302 * @param string $type Renderer type 303 * 304 * @return Image_3D_Renderer Object instance 305 */ 306 public function createRenderer($type) 307 { 308 $name = ucfirst($type); 309 $class = 'Image_3D_Renderer_' . $name; 310 311 $absolute_path = dirname(__FILE__) . '/3D/Renderer/' . $name . '.php'; 312 $user_path = dirname(__FILE__) . '/3D/User/Renderer/' . $name . '.php'; 313 314 if (is_file($absolute_path) && is_readable($absolute_path)) { 315 include_once $absolute_path; 316 } elseif (is_file($user_path) && is_readable($user_path)) { 317 include_once $user_path; 318 } else { 319 throw new Exception("Class for renderer $name not found (Searched: $absolute_path, $user_path)."); 320 } 321 322 return $this->_renderer = new $class(); 323 } 324 325 // }}} 326 // {{{ createDriver() 327 328 /** 329 * Factory method for drivers 330 * 331 * Creates and returns a new driver 332 * Standrad available drivers: 333 * - GD 334 * - SVG 335 * 336 * @param string $type Driver type 337 * 338 * @return Image_3D_Driver Object instance 339 */ 340 public function createDriver($type) 341 { 342 $name = ucfirst($type); 343 $class = 'Image_3D_Driver_' . $name; 344 345 $absolute_path = dirname(__FILE__) . '/3D/Driver/' . $name . '.php'; 346 $user_path = dirname(__FILE__) . '/3D/User/Driver/' . $name . '.php'; 347 348 if (is_file($absolute_path) && is_readable($absolute_path)) { 349 include_once $absolute_path; 350 } elseif (is_file($user_path) && is_readable($user_path)) { 351 include_once $user_path; 352 } else { 353 throw new Exception("Class for driver $name not found (Searched: $absolute_path, $user_path)."); 354 } 355 356 return $this->_driver = new $class(); 357 } 358 359 // }}} 360 // {{{ setOption() 361 362 /** 363 * Sets an option for all known objects 364 * 365 * Sets one of the Image_3D options for all known objects 366 * 367 * @param integer $option Option 368 * @param mixed $value Value 369 * 370 * @return void 371 */ 372 public function setOption($option, $value) 373 { 374 $this->_option[$option] = $value; 375 $this->_optionSet[$option] = true; 376 377 foreach ($this->_objects as $object) { 378 $object->setOption($option, $value); 379 } 380 } 381 382 // }}} 383 // {{{ transform() 384 385 /** 386 * Transform all known objects 387 * 388 * Transform all known objects with the given transformation matrix. 389 * Can be interpreted as a transformation of the viewpoint. 390 * 391 * The id is an optional value which shouldn't be set by the user to 392 * avoid double calculations, if a point is related to more than one 393 * object. 394 * 395 * @param Image_3D_Matrix $matrix Transformation matrix 396 * @param mixed $id Transformation ID 397 * 398 * @return void 399 */ 400 public function transform(Image_3D_Matrix $matrix, $id = null) 401 { 402 403 if ($id === null) { 404 $id = substr(md5(microtime()), 0, 8); 405 } 406 407 foreach ($this->_objects as $object) { 408 $object->transform($matrix, $id); 409 } 410 } 411 412 // }}} 413 // {{{ render() 414 415 /** 416 * Renders the image 417 * 418 * Starts rendering an image with given size into the given file. 419 * 420 * @param integer $x Width 421 * @param integer $y Height 422 * @param string $file Filename 423 * 424 * @return boolean Success 425 */ 426 public function render($x, $y, $file) 427 { 428 // Hack because stdout is not writeable 429 if ((is_file($file) || !is_writeable(dirname($file))) 430 && (!is_file($file) || !is_writeable($file)) 431 && !preg_match('/^\s*php:\/\/(stdout|output)\s*$/i', $file)) { 432 throw new Exception('Cannot write outputfile.'); 433 } 434 435 $x = min(1280, max(0, (int) $x)); 436 $y = min(1280, max(0, (int) $y)); 437 438 $this->_renderer->setSize($x, $y); 439 $this->_renderer->setBackgroundColor($this->_color); 440 $this->_renderer->addObjects($this->_objects); 441 $this->_renderer->addLights($this->_lights); 442 $this->_renderer->setDriver($this->_driver); 443 444 return $this->_renderer->render($file); 445 } 446 447 // }}} 448 // {{{ stats() 449 450 /** 451 * Statistics for Image_3D 452 * 453 * Returns simple statisics for Image_3D as a string. 454 * 455 * @return string Statistics 456 */ 457 public function stats() 458 { 459 return sprintf('Image 3D 460 461objects: %d 462lights: %d 463polygones: %d 464points: %d 465 466time: %.4f s 467', 468 count($this->_objects), 469 $this->_renderer->getLightCount(), 470 $this->_renderer->getPolygonCount(), 471 $this->_renderer->getPointCount(), 472 microtime(true) - $this->_start); 473 } 474 475 // }}} 476} 477 478// }}} 479