1<?php 2 3class Image_3D_Chunk { 4 5 protected $type; 6 protected $content; 7 protected $size; 8 9 protected $chunks; 10 11 //>------ Primary chunk 12 const MAIN3DS = 0x4D4D; 13 14 //>------ Main Chunks 15 const EDIT3DS = 0x3D3D; // this is the start of the editor config 16 const KEYF3DS = 0xB000; // this is the start of the keyframer config 17 18 //>------ sub defines of EDIT3DS 19 const EDIT_MATERIAL = 0xAFFF; 20 const EDIT_CONFIG1 = 0x0100; 21 const EDIT_CONFIG2 = 0x3E3D; 22 const EDIT_VIEW_P1 = 0x7012; 23 const EDIT_VIEW_P2 = 0x7011; 24 const EDIT_VIEW_P3 = 0x7020; 25 const EDIT_VIEW1 = 0x7001; 26 const EDIT_BACKGR = 0x1200; 27 const EDIT_AMBIENT = 0x2100; 28 const EDIT_OBJECT = 0x4000; 29 30 //>------ sub defines of EDIT_OBJECT 31 const OBJ_TRIMESH = 0x4100; 32 const OBJ_LIGHT = 0x4600; 33 const OBJ_CAMERA = 0x4700; 34 35 const OBJ_UNKNWN01 = 0x4010; 36 const OBJ_UNKNWN02 = 0x4012; 37 38 //>------ sub defines of OBJ_CAMERA 39 const CAM_UNKNWN01 = 0x4710; 40 const CAM_UNKNWN02 = 0x4720; 41 42 //>------ sub defines of OBJ_LIGHT 43 const LIT_OFF = 0x4620; 44 const LIT_SPOT = 0x4610; 45 const LIT_UNKNWN01 = 0x465A; 46 47 //>------ sub defines of OBJ_TRIMESH 48 const TRI_VERTEXL = 0x4110; 49 const TRI_FACEL2 = 0x4111; 50 const TRI_FACEL1 = 0x4120; 51 const TRI_SMOOTH = 0x4150; 52 const TRI_LOCAL = 0x4160; 53 const TRI_VISIBLE = 0x4165; 54 55 //>>------ sub defs of KEYF3DS 56 const KEYF_UNKNWN01 = 0xB009; 57 const KEYF_UNKNWN02 = 0xB00A; 58 const KEYF_FRAMES = 0xB008; 59 const KEYF_OBJDES = 0xB002; 60 61 //>>------ these define the different color chunk types 62 const COL_RGB = 0x0010; 63 const COL_TRU = 0x0011; 64 const COL_UNK = 0x0013; 65 66 //>>------ defines for viewport chunks 67 const TOP = 0x0001; 68 const BOTTOM = 0x0002; 69 const LEFT = 0x0003; 70 const RIGHT = 0x0004; 71 const FRONT = 0x0005; 72 const BACK = 0x0006; 73 const USER = 0x0007; 74 const CAMERA = 0x0008; 75 const LIGHT = 0x0009; 76 const DISABLED = 0x0010; 77 const BOGUS = 0x0011; 78 79 public function __construct($type, $content) 80 { 81 $this->type = (int) $type; 82 $this->size = strlen($content); 83 $this->content = $content; 84 } 85 86 public function readChunks() { 87 88 if (count($this->chunks) || ($this->size < 6)) return false; 89 90 $position = 0; 91 $string = $this->content; 92 $length = $this->size - 6; 93 94 while ($position <= $length) { 95 $type = $this->getWord(substr($string, $position, 2)); 96 $position += 2; 97 $chunkLength = $this->getDWord(substr($string, $position, 4)) - 6; 98 $position += 4; 99 100 $this->chunks[] = new Image_3D_Chunk($type, substr($string, $position, $chunkLength)); 101 $position += $chunkLength; 102 } 103 } 104 105 public function debug() { 106 printf("Typ: %6d (0x%04x) (%6d bytes) | Objects:%4d | Content:%6d\n", $this->type, $this->type, $this->size, count($this->chunks), strlen($this->content)); 107 } 108 109 protected function getWord($string) { 110 return (ord($string{1}) << 8) | ord($string{0}); 111 } 112 113 protected function getDWord($string) { 114 return ord($string{0}) | (ord($string{1}) << 8) | (ord($string{2}) << 16) | (ord($string{3}) << 32); 115 } 116 117 protected function getUnsignedInt($string) { 118 return (ord($string{0}) << 8) | ord($string{1}); 119 } 120 121 protected function getFloat($string) { 122 // Convert C-Float to PHP-Float 123 return (ord($string{3}) & 128 ? -1 : 1) * (1 + (float) (ord($string{2}) & 127) / 127 + (float) (ord($string{1})) / 256 / 127 + (float) (ord($string{0})) / 256 / 256 / 127) * pow(2., ((((ord($string{3}) & 127) << 1) | (ord($string{2}) >> 7)) - 127)); 124 } 125 126 public function getChunks() { 127 return $this->chunks; 128 } 129 130 public function getType() { 131 return $this->type; 132 } 133 134 public function getContent() { 135 return $this->content; 136 } 137 138 public function getFirstChunkByType($type) { 139 if (!is_int($type)) $type = hexdec($type); 140 141 foreach ($this->chunks as $chunk) if ($chunk->getType() === $type) return $chunk; 142 return false; 143 } 144 145 public function getChunksByType($type) { 146 if (!is_int($type)) $type = hexdec($type); 147 148 $chunks = array(); 149 foreach ($this->chunks as $chunk) if ($chunk->getType() === $type) $chunks[] = $chunk; 150 return $chunks; 151 } 152} 153 154class Image_3D_Chunk_Object extends Image_3D_Chunk { 155 156 protected $name; 157 158 public function __construct($type, $content) { 159 parent::__construct($type, $content); 160 $this->getName(); 161 } 162 163 protected function getName() 164 { 165 $i = 0; 166 while ((ord($this->content{$i}) !== 0) && ($i < $this->size)) $this->name .= $this->content{$i++}; 167 $this->content = substr($this->content, $i + 1); 168 } 169 170 public function readChunks(Image_3D_Object_3ds $k3ds) 171 { 172 $subtype = $this->getWord(substr($this->content, 0, 2)); 173 $subcontent = substr($this->content, 6); 174 175 switch ($subtype) { 176 case self::OBJ_TRIMESH: 177 $object = $k3ds->addObject($this->name); 178 $this->chunks[] = new Image_3D_Chunk_TriMesh($subtype, $subcontent, $object); 179 break; 180 } 181 } 182 183 public function debug() { 184 echo 'Object: ', $this->name, "\n"; 185 parent::debug(); 186 } 187} 188 189class Image_3D_Chunk_TriMesh extends Image_3D_Chunk { 190 191 protected $matrix; 192 193 protected $object; 194 195 public function __construct($type, $content, $object) { 196 parent::__construct($type, $content); 197 198 $this->object = $object; 199 200 $this->readChunks(); 201 202 $this->getPoints(); 203 $this->getFaces(); 204 } 205 206 protected function getPoints() 207 { 208 $vertexlists = $this->getChunksByType(Image_3D_Chunk::TRI_VERTEXL); 209 foreach ($vertexlists as $vertexlist) { 210 $points = $vertexlist->getContent(); 211 $count = $this->getWord(substr($points, 0, 2)); 212 $points = substr($points, 2); 213 214 for ($i = 0; $i < $count; $i++) { 215 $x = $this->getFloat(substr($points, 0, 4)); 216 $y = $this->getFloat(substr($points, 4, 4)); 217 $z = $this->getFloat(substr($points, 8, 4)); 218 $this->object->newPoint($x, $y, $z); 219 $points = substr($points, 12); 220 } 221 } 222 } 223 224 protected function getFaces() 225 { 226 $facelists = $this->getChunksByType(Image_3D_Chunk::TRI_FACEL1); 227 foreach ($facelists as $facelist) { 228 $faces = $facelist->getContent(); 229 $count = $this->getWord(substr($faces, 0, 2)); 230 $faces = substr($faces, 2); 231 232 for ($i = 0; $i < $count; $i++) { 233 $p1 = $this->getWord(substr($faces, 0, 2)); 234 $p2 = $this->getWord(substr($faces, 2, 2)); 235 $p3 = $this->getWord(substr($faces, 4, 2)); 236 $this->object->newPolygon($p1, $p2, $p3); 237 $faces = substr($faces, 8); 238 } 239 } 240 } 241 242 protected function getTranslations() 243 { 244 $translists = $this->getChunksByType(Image_3D_Chunk::TRI_LOCAL); 245 foreach ($translists as $translist) { 246 $trans = $translist->getContent(); 247 248 echo "Trans: " . strlen($trans), "\n"; 249 } 250 } 251 252 public function debug() { 253 parent::debug(); 254 printf("Trimesh with %d (0x%04x) points - Pointsize: %.2f\n", $this->pointCount, $this->pointCount, $this->size / $this->pointCount); 255 } 256} 257 258class Image_3D_Object_3ds_Object extends Image_3D_Object { 259 260 protected $_points; 261 262 public function __construct() { 263 parent::__construct(); 264 265 $this->_points = array(); 266 } 267 268 public function newPoint($x, $y, $z) 269 { 270 $this->_points[] = new Image_3D_Point($x, $y, $z); 271// echo "New Point: $x, $y, $z -> ", count($this->_points), "\n"; 272 } 273 274 public function newPolygon($p1, $p2, $p3) { 275 if (!isset($this->_points[$p1]) || !isset($this->_points[$p2]) || !isset($this->_points[$p3])) { 276// printf("ERROR: Unknown point (%d, %d, %d of %d)\n", $p1, $p2, $p3, count($this->_points) - 1); 277 return false; 278 } 279 $this->_addPolygon(new Image_3D_Polygon($this->_points[$p1], $this->_points[$p2], $this->_points[$p3])); 280// echo "New Polygon: $p1, $p2, $p3 -> ", count($this->_polygones), "\n"; 281 } 282 283 public function debug() { 284 printf("Points: %d | Polygones: %d (%d)\n", count($this->_points), count($this->_polygones), $this->_polygonCount); 285 } 286} 287 288?> 289