1 /* 2 * OBJLoader.js 3 * 4 * Sweet Home 3D, Copyright (c) 2024 Space Mushrooms <info@sweethome3d.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 // Requires core.js 22 // gl-matrix-min.js 23 // jszip.min.js 24 // scene3d.js 25 // Triangulator.js 26 // URLContent.js 27 // ModelLoader.js 28 29 /** 30 * Creates an instance of an OBJ + MTL loader. 31 * @constructor 32 * @extends ModelLoader 33 * @author Emmanuel Puybaret 34 */ 35 function OBJLoader() { 36 ModelLoader.call(this, "obj"); 37 38 if (OBJLoader.defaultAppearances === null) { 39 OBJLoader.defaultAppearances = {}; 40 OBJLoader.parseMaterial( 41 // Description of the default Java 3D materials at MTL format 42 // (copied from com.sun.j3d.loaders.objectfile.DefaultMaterials class with inverse d transparency factor) 43 "newmtl amber\n" + 44 "Ka 0.0531 0.0531 0.0531\n" + 45 "Kd 0.5755 0.2678 0.0000\n" + 46 "Ks 0.3000 0.3000 0.3000\n" + 47 "illum 2\n" + 48 "Ns 60.0000\n" + 49 "\n" + 50 "newmtl amber_trans\n" + 51 "Ka 0.0531 0.0531 0.0531\n" + 52 "Kd 0.5755 0.2678 0.0000\n" + 53 "Ks 0.3000 0.3000 0.3000\n" + 54 "illum 2\n" + 55 "d 0.1600\n" + 56 "Ns 60.0000\n" + 57 "\n" + 58 "newmtl charcoal\n" + 59 "Ka 0.0082 0.0082 0.0082\n" + 60 "Kd 0.0041 0.0041 0.0041\n" + 61 "Ks 0.3000 0.3000 0.3000\n" + 62 "illum 2\n" + 63 "Ns 60.0000\n" + 64 "\n" + 65 "newmtl lavendar\n" + 66 "Ka 0.1281 0.0857 0.2122\n" + 67 "Kd 0.2187 0.0906 0.3469\n" + 68 "Ks 0.3000 0.3000 0.3000\n" + 69 "illum 2\n" + 70 "Ns 60.0000\n" + 71 "\n" + 72 "newmtl navy_blue\n" + 73 "Ka 0.0000 0.0000 0.0490\n" + 74 "Kd 0.0000 0.0000 0.0531\n" + 75 "Ks 0.1878 0.1878 0.1878\n" + 76 "illum 2\n" + 77 "Ns 91.4700\n" + 78 "\n" + 79 "newmtl pale_green\n" + 80 "Ka 0.0444 0.0898 0.0447\n" + 81 "Kd 0.0712 0.3796 0.0490\n" + 82 "Ks 0.1878 0.1878 0.1878\n" + 83 "illum 2\n" + 84 "Ns 91.4700\n" + 85 "\n" + 86 "newmtl pale_pink\n" + 87 "Ka 0.0898 0.0444 0.0444\n" + 88 "Kd 0.6531 0.2053 0.4160\n" + 89 "Ks 0.1878 0.1878 0.1878\n" + 90 "illum 2\n" + 91 "Ns 91.4700\n" + 92 "\n" + 93 "newmtl pale_yellow\n" + 94 "Ka 0.3606 0.3755 0.0935\n" + 95 "Kd 0.6898 0.6211 0.1999\n" + 96 "Ks 0.1878 0.1878 0.1878\n" + 97 "illum 2\n" + 98 "Ns 91.4700\n" + 99 "\n" + 100 "newmtl peach\n" + 101 "Ka 0.3143 0.1187 0.0167\n" + 102 "Kd 0.6367 0.1829 0.0156\n" + 103 "Ks 0.1878 0.1878 0.1878\n" + 104 "illum 2\n" + 105 "Ns 91.4700\n" + 106 "\n" + 107 "newmtl periwinkle\n" + 108 "Ka 0.0000 0.0000 0.1184\n" + 109 "Kd 0.0000 0.0396 0.8286\n" + 110 "Ks 0.1878 0.1878 0.1878\n" + 111 "illum 2\n" + 112 "Ns 91.4700\n" + 113 "\n" + 114 "newmtl redwood\n" + 115 "Ka 0.0204 0.0027 0.0000\n" + 116 "Kd 0.2571 0.0330 0.0000\n" + 117 "Ks 0.1878 0.1878 0.1878\n" + 118 "illum 2\n" + 119 "Ns 91.4700\n" + 120 "\n" + 121 "newmtl smoked_glass\n" + 122 "Ka 0.0000 0.0000 0.0000\n" + 123 "Kd 0.0041 0.0041 0.0041\n" + 124 "Ks 0.1878 0.1878 0.1878\n" + 125 "illum 2\n" + 126 "d 0.0200\n" + 127 "Ns 91.4700\n" + 128 "\n" + 129 "newmtl aqua_filter\n" + 130 "Ka 0.0000 0.0000 0.0000\n" + 131 "Kd 0.3743 0.6694 0.5791\n" + 132 "Ks 0.1878 0.1878 0.1878\n" + 133 "illum 2\n" + 134 "d 0.0200\n" + 135 "Ns 91.4700\n" + 136 "\n" + 137 "newmtl yellow_green\n" + 138 "Ka 0.0000 0.0000 0.0000\n" + 139 "Kd 0.1875 0.4082 0.0017\n" + 140 "Ks 0.1878 0.1878 0.1878\n" + 141 "illum 2\n" + 142 "Ns 91.4700\n" + 143 "\n" + 144 "newmtl bluetint\n" + 145 "Ka 0.1100 0.4238 0.5388\n" + 146 "Kd 0.0468 0.7115 0.9551\n" + 147 "Ks 0.3184 0.3184 0.3184\n" + 148 "illum 9\n" + 149 "d 0.4300\n" + 150 "Ns 60.0000\n" + 151 "sharpness 60.0000\n" + 152 "\n" + 153 "newmtl plasma\n" + 154 "Ka 0.4082 0.0816 0.2129\n" + 155 "Kd 1.0000 0.0776 0.4478\n" + 156 "Ks 0.3000 0.3000 0.3000\n" + 157 "illum 9\n" + 158 "d 0.2500\n" + 159 "Ns 60.0000\n" + 160 "sharpness 60.0000\n" + 161 "\n" + 162 "newmtl emerald\n" + 163 "Ka 0.0470 1.0000 0.0000\n" + 164 "Kd 0.0470 1.0000 0.0000\n" + 165 "Ks 0.2000 0.2000 0.2000\n" + 166 "illum 9\n" + 167 "d 0.2500\n" + 168 "Ns 60.0000\n" + 169 "sharpness 60.0000\n" + 170 "\n" + 171 "newmtl ruby\n" + 172 "Ka 1.0000 0.0000 0.0000\n" + 173 "Kd 1.0000 0.0000 0.0000\n" + 174 "Ks 0.2000 0.2000 0.2000\n" + 175 "illum 9\n" + 176 "d 0.2500\n" + 177 "Ns 60.0000\n" + 178 "sharpness 60.0000\n" + 179 "\n" + 180 "newmtl sapphire\n" + 181 "Ka 0.0235 0.0000 1.0000\n" + 182 "Kd 0.0235 0.0000 1.0000\n" + 183 "Ks 0.2000 0.2000 0.2000\n" + 184 "illum 9\n" + 185 "d 0.2500\n" + 186 "Ns 60.0000\n" + 187 "sharpness 60.0000\n" + 188 "\n" + 189 "newmtl white\n" + 190 "Ka 0.4000 0.4000 0.4000\n" + 191 "Kd 1.0000 1.0000 1.0000\n" + 192 "Ks 0.3000 0.3000 0.3000\n" + 193 "illum 2\n" + 194 "Ns 60.0000\n" + 195 "\n" + 196 "newmtl red\n" + 197 "Ka 0.4449 0.0000 0.0000\n" + 198 "Kd 0.7714 0.0000 0.0000\n" + 199 "Ks 0.8857 0.0000 0.0000\n" + 200 "illum 2\n" + 201 "Ns 136.4300\n" + 202 "\n" + 203 "newmtl blue_pure\n" + 204 "Ka 0.0000 0.0000 0.5000\n" + 205 "Kd 0.0000 0.0000 1.0000\n" + 206 "Ks 0.0000 0.0000 0.5000\n" + 207 "illum 2\n" + 208 "Ns 65.8900\n" + 209 "\n" + 210 "newmtl lime\n" + 211 "Ka 0.0000 0.5000 0.0000\n" + 212 "Kd 0.0000 1.0000 0.0000\n" + 213 "Ks 0.0000 0.5000 0.0000\n" + 214 "illum 2\n" + 215 "Ns 65.8900\n" + 216 "\n" + 217 "newmtl green\n" + 218 "Ka 0.0000 0.2500 0.0000\n" + 219 "Kd 0.0000 0.2500 0.0000\n" + 220 "Ks 0.0000 0.2500 0.0000\n" + 221 "illum 2\n" + 222 "Ns 65.8900\n" + 223 "\n" + 224 "newmtl yellow\n" + 225 "Ka 1.0000 0.6667 0.0000\n" + 226 "Kd 1.0000 0.6667 0.0000\n" + 227 "Ks 1.0000 0.6667 0.0000\n" + 228 "illum 2\n" + 229 "Ns 65.8900\n" + 230 "\n" + 231 "newmtl purple\n" + 232 "Ka 0.5000 0.0000 1.0000\n" + 233 "Kd 0.5000 0.0000 1.0000\n" + 234 "Ks 0.5000 0.0000 1.0000\n" + 235 "illum 2\n" + 236 "Ns 65.8900\n" + 237 "\n" + 238 "newmtl orange\n" + 239 "Ka 1.0000 0.1667 0.0000\n" + 240 "Kd 1.0000 0.1667 0.0000\n" + 241 "Ks 1.0000 0.1667 0.0000\n" + 242 "illum 2\n" + 243 "Ns 65.8900\n" + 244 "\n" + 245 "newmtl grey\n" + 246 "Ka 0.5000 0.5000 0.5000\n" + 247 "Kd 0.1837 0.1837 0.1837\n" + 248 "Ks 0.5000 0.5000 0.5000\n" + 249 "illum 2\n" + 250 "Ns 65.8900\n" + 251 "\n" + 252 "newmtl rubber\n" + 253 "Ka 0.0000 0.0000 0.0000\n" + 254 "Kd 0.0100 0.0100 0.0100\n" + 255 "Ks 0.1000 0.1000 0.1000\n" + 256 "illum 2\n" + 257 "Ns 65.8900\n" + 258 "\n" + 259 "newmtl flaqua\n" + 260 "Ka 0.0000 0.4000 0.4000\n" + 261 "Kd 0.0000 0.5000 0.5000\n" + 262 "illum 1\n" + 263 "\n" + 264 "newmtl flblack\n" + 265 "Ka 0.0000 0.0000 0.0000\n" + 266 "Kd 0.0041 0.0041 0.0041\n" + 267 "illum 1\n" + 268 "\n" + 269 "newmtl flblue_pure\n" + 270 "Ka 0.0000 0.0000 0.5592\n" + 271 "Kd 0.0000 0.0000 0.7102\n" + 272 "illum 1\n" + 273 "\n" + 274 "newmtl flgrey\n" + 275 "Ka 0.2163 0.2163 0.2163\n" + 276 "Kd 0.5000 0.5000 0.5000\n" + 277 "illum 1\n" + 278 "\n" + 279 "newmtl fllime\n" + 280 "Ka 0.0000 0.3673 0.0000\n" + 281 "Kd 0.0000 1.0000 0.0000\n" + 282 "illum 1\n" + 283 "\n" + 284 "newmtl florange\n" + 285 "Ka 0.6857 0.1143 0.0000\n" + 286 "Kd 1.0000 0.1667 0.0000\n" + 287 "illum 1\n" + 288 "\n" + 289 "newmtl flpurple\n" + 290 "Ka 0.2368 0.0000 0.4735\n" + 291 "Kd 0.3755 0.0000 0.7510\n" + 292 "illum 1\n" + 293 "\n" + 294 "newmtl flred\n" + 295 "Ka 0.4000 0.0000 0.0000\n" + 296 "Kd 1.0000 0.0000 0.0000\n" + 297 "illum 1\n" + 298 "\n" + 299 "newmtl flyellow\n" + 300 "Ka 0.7388 0.4925 0.0000\n" + 301 "Kd 1.0000 0.6667 0.0000\n" + 302 "illum 1\n" + 303 "\n" + 304 "newmtl pink\n" + 305 "Ka 0.9469 0.0078 0.2845\n" + 306 "Kd 0.9878 0.1695 0.6702\n" + 307 "Ks 0.7429 0.2972 0.2972\n" + 308 "illum 2\n" + 309 "Ns 106.2000\n" + 310 "\n" + 311 "newmtl flbrown\n" + 312 "Ka 0.0571 0.0066 0.0011\n" + 313 "Kd 0.1102 0.0120 0.0013\n" + 314 "illum 1\n" + 315 "\n" + 316 "newmtl brown\n" + 317 "Ka 0.1020 0.0185 0.0013\n" + 318 "Kd 0.0857 0.0147 0.0000\n" + 319 "Ks 0.1633 0.0240 0.0000\n" + 320 "illum 2\n" + 321 "Ns 65.8900\n" + 322 "\n" + 323 "newmtl glass\n" + 324 "Ka 1.0000 1.0000 1.0000\n" + 325 "Kd 0.4873 0.4919 0.5306\n" + 326 "Ks 0.6406 0.6939 0.9020\n" + 327 "illum 2\n" + 328 "Ns 200.0000\n" + 329 "\n" + 330 "newmtl flesh\n" + 331 "Ka 0.4612 0.3638 0.2993\n" + 332 "Kd 0.5265 0.4127 0.3374\n" + 333 "Ks 0.3000 0.3000 0.3000\n" + 334 "illum 2\n" + 335 "Ns 60.0000\n" + 336 "\n" + 337 "newmtl aqua\n" + 338 "Ka 0.0000 0.4000 0.4000\n" + 339 "Kd 0.0000 0.5000 0.5000\n" + 340 "Ks 0.5673 0.5673 0.5673\n" + 341 "illum 2\n" + 342 "Ns 60.0000\n" + 343 "\n" + 344 "newmtl black\n" + 345 "Ka 0.0000 0.0000 0.0000\n" + 346 "Kd 0.0020 0.0020 0.0020\n" + 347 "Ks 0.5184 0.5184 0.5184\n" + 348 "illum 2\n" + 349 "Ns 157.3600\n" + 350 "\n" + 351 "newmtl silver\n" + 352 "Ka 0.9551 0.9551 0.9551\n" + 353 "Kd 0.6163 0.6163 0.6163\n" + 354 "Ks 0.3000 0.3000 0.3000\n" + 355 "illum 2\n" + 356 "Ns 60.0000\n" + 357 "\n" + 358 "newmtl dkblue_pure\n" + 359 "Ka 0.0000 0.0000 0.0449\n" + 360 "Kd 0.0000 0.0000 0.1347\n" + 361 "Ks 0.0000 0.0000 0.5673\n" + 362 "illum 2\n" + 363 "Ns 65.8900\n" + 364 "\n" + 365 "newmtl fldkblue_pure\n" + 366 "Ka 0.0000 0.0000 0.0449\n" + 367 "Kd 0.0000 0.0000 0.1347\n" + 368 "illum 1\n" + 369 "\n" + 370 "newmtl dkgreen\n" + 371 "Ka 0.0000 0.0122 0.0000\n" + 372 "Kd 0.0058 0.0245 0.0000\n" + 373 "Ks 0.0000 0.0490 0.0000\n" + 374 "illum 2\n" + 375 "Ns 60.0000\n" + 376 "\n" + 377 "newmtl dkgrey\n" + 378 "Ka 0.0490 0.0490 0.0490\n" + 379 "Kd 0.0490 0.0490 0.0490\n" + 380 "Ks 0.3000 0.3000 0.3000\n" + 381 "illum 2\n" + 382 "Ns 60.0000\n" + 383 "\n" + 384 "newmtl ltbrown\n" + 385 "Ka 0.1306 0.0538 0.0250\n" + 386 "Kd 0.2776 0.1143 0.0531\n" + 387 "Ks 0.3000 0.1235 0.0574\n" + 388 "illum 2\n" + 389 "Ns 60.0000\n" + 390 "\n" + 391 "newmtl fldkgreen\n" + 392 "Ka 0.0000 0.0122 0.0000\n" + 393 "Kd 0.0058 0.0245 0.0000\n" + 394 "illum 1\n" + 395 "\n" + 396 "newmtl flltbrown\n" + 397 "Ka 0.1306 0.0538 0.0250\n" + 398 "Kd 0.2776 0.1143 0.0531\n" + 399 "illum 1\n" + 400 "\n" + 401 "newmtl tan\n" + 402 "Ka 0.4000 0.3121 0.1202\n" + 403 "Kd 0.6612 0.5221 0.2186\n" + 404 "Ks 0.5020 0.4118 0.2152\n" + 405 "illum 2\n" + 406 "Ns 60.0000\n" + 407 "\n" + 408 "newmtl fltan\n" + 409 "Ka 0.4000 0.3121 0.1202\n" + 410 "Kd 0.6612 0.4567 0.1295\n" + 411 "illum 1\n" + 412 "\n" + 413 "newmtl brzskin\n" + 414 "Ka 0.4408 0.2694 0.1592\n" + 415 "Kd 0.3796 0.2898 0.2122\n" + 416 "Ks 0.3000 0.3000 0.3000\n" + 417 "illum 2\n" + 418 "Ns 25.0000\n" + 419 "\n" + 420 "newmtl lips\n" + 421 "Ka 0.4408 0.2694 0.1592\n" + 422 "Kd 0.9265 0.2612 0.2898\n" + 423 "Ks 0.3000 0.3000 0.3000\n" + 424 "illum 2\n" + 425 "Ns 25.0000\n" + 426 "\n" + 427 "newmtl redorange\n" + 428 "Ka 0.3918 0.0576 0.0000\n" + 429 "Kd 0.7551 0.0185 0.0000\n" + 430 "Ks 0.4694 0.3224 0.1667\n" + 431 "illum 2\n" + 432 "Ns 132.5600\n" + 433 "\n" + 434 "newmtl blutan\n" + 435 "Ka 0.4408 0.2694 0.1592\n" + 436 "Kd 0.0776 0.2571 0.2041\n" + 437 "Ks 0.1467 0.1469 0.0965\n" + 438 "illum 2\n" + 439 "Ns 25.0000\n" + 440 "\n" + 441 "newmtl bluteal\n" + 442 "Ka 0.0041 0.1123 0.1224\n" + 443 "Kd 0.0776 0.2571 0.2041\n" + 444 "Ks 0.1467 0.1469 0.0965\n" + 445 "illum 2\n" + 446 "Ns 25.0000\n" + 447 "\n" + 448 "newmtl pinktan\n" + 449 "Ka 0.4408 0.2694 0.1592\n" + 450 "Kd 0.6857 0.2571 0.2163\n" + 451 "Ks 0.1467 0.1469 0.0965\n" + 452 "illum 2\n" + 453 "Ns 25.0000\n" + 454 "\n" + 455 "newmtl brnhair\n" + 456 "Ka 0.0612 0.0174 0.0066\n" + 457 "Kd 0.0898 0.0302 0.0110\n" + 458 "Ks 0.1306 0.0819 0.0352\n" + 459 "illum 2\n" + 460 "Ns 60.4700\n" + 461 "\n" + 462 "newmtl blondhair\n" + 463 "Ka 0.4449 0.2632 0.0509\n" + 464 "Kd 0.5714 0.3283 0.0443\n" + 465 "Ks 0.7755 0.4602 0.0918\n" + 466 "illum 2\n" + 467 "Ns 4.6500\n" + 468 "\n" + 469 "newmtl flblonde\n" + 470 "Ka 0.4449 0.2632 0.0509\n" + 471 "Kd 0.5714 0.3283 0.0443\n" + 472 "illum 1\n" + 473 "\n" + 474 "newmtl yelloworng\n" + 475 "Ka 0.5837 0.1715 0.0000\n" + 476 "Kd 0.8857 0.2490 0.0000\n" + 477 "Ks 0.3000 0.3000 0.3000\n" + 478 "illum 2\n" + 479 "Ns 60.0000\n" + 480 "\n" + 481 "newmtl bone\n" + 482 "Ka 0.3061 0.1654 0.0650\n" + 483 "Kd 0.9000 0.7626 0.4261\n" + 484 "Ks 0.8939 0.7609 0.5509\n" + 485 "illum 2\n" + 486 "Ns 200.0000\n" + 487 "\n" + 488 "newmtl teeth\n" + 489 "Ka 0.6408 0.5554 0.3845\n" + 490 "Kd 0.9837 0.7959 0.4694\n" + 491 "illum 1\n" + 492 "\n" + 493 "newmtl brass\n" + 494 "Ka 0.2490 0.1102 0.0000\n" + 495 "Kd 0.4776 0.1959 0.0000\n" + 496 "Ks 0.5796 0.5796 0.5796\n" + 497 "illum 2\n" + 498 "Ns 134.8800\n" + 499 "\n" + 500 "newmtl dkred\n" + 501 "Ka 0.0939 0.0000 0.0000\n" + 502 "Kd 0.2286 0.0000 0.0000\n" + 503 "Ks 0.2490 0.0000 0.0000\n" + 504 "illum 2\n" + 505 "Ns 60.0000\n" + 506 "\n" + 507 "newmtl taupe\n" + 508 "Ka 0.1061 0.0709 0.0637\n" + 509 "Kd 0.2041 0.1227 0.1058\n" + 510 "Ks 0.3000 0.3000 0.3000\n" + 511 "illum 2\n" + 512 "Ns 84.5000\n" + 513 "\n" + 514 "newmtl dkteal\n" + 515 "Ka 0.0000 0.0245 0.0163\n" + 516 "Kd 0.0000 0.0653 0.0449\n" + 517 "Ks 0.3000 0.3000 0.3000\n" + 518 "illum 2\n" + 519 "Ns 55.0400\n" + 520 "\n" + 521 "newmtl dkdkgrey\n" + 522 "Ka 0.0000 0.0000 0.0000\n" + 523 "Kd 0.0122 0.0122 0.0122\n" + 524 "Ks 0.3000 0.3000 0.3000\n" + 525 "illum 2\n" + 526 "Ns 60.0000\n" + 527 "\n" + 528 "newmtl dkblue\n" + 529 "Ka 0.0000 0.0029 0.0408\n" + 530 "Kd 0.0000 0.0041 0.0571\n" + 531 "Ks 0.3000 0.3000 0.3000\n" + 532 "illum 2\n" + 533 "Ns 60.0000\n" + 534 "\n" + 535 "newmtl gold\n" + 536 "Ka 0.7224 0.1416 0.0000\n" + 537 "Kd 1.0000 0.4898 0.0000\n" + 538 "Ks 0.7184 0.3695 0.3695\n" + 539 "illum 2\n" + 540 "Ns 123.2600\n" + 541 "\n" + 542 "newmtl redbrick\n" + 543 "Ka 0.1102 0.0067 0.0067\n" + 544 "Kd 0.3306 0.0398 0.0081\n" + 545 "illum 1\n" + 546 "\n" + 547 "newmtl flmustard\n" + 548 "Ka 0.4245 0.2508 0.0000\n" + 549 "Kd 0.8898 0.3531 0.0073\n" + 550 "illum 1\n" + 551 "\n" + 552 "newmtl flpinegreen\n" + 553 "Ka 0.0367 0.0612 0.0204\n" + 554 "Kd 0.1061 0.2163 0.0857\n" + 555 "illum 1\n" + 556 "\n" + 557 "newmtl fldkred\n" + 558 "Ka 0.0939 0.0000 0.0000\n" + 559 "Kd 0.2286 0.0082 0.0082\n" + 560 "illum 1\n" + 561 "\n" + 562 "newmtl fldkgreen2\n" + 563 "Ka 0.0025 0.0122 0.0014\n" + 564 "Kd 0.0245 0.0694 0.0041\n" + 565 "illum 1\n" + 566 "\n" + 567 "newmtl flmintgreen\n" + 568 "Ka 0.0408 0.1429 0.0571\n" + 569 "Kd 0.1306 0.2898 0.1673\n" + 570 "illum 1\n" + 571 "\n" + 572 "newmtl olivegreen\n" + 573 "Ka 0.0167 0.0245 0.0000\n" + 574 "Kd 0.0250 0.0367 0.0000\n" + 575 "Ks 0.2257 0.2776 0.1167\n" + 576 "illum 2\n" + 577 "Ns 97.6700\n" + 578 "\n" + 579 "newmtl skin\n" + 580 "Ka 0.2286 0.0187 0.0187\n" + 581 "Kd 0.1102 0.0328 0.0139\n" + 582 "Ks 0.3000 0.3000 0.3000\n" + 583 "illum 2\n" + 584 "Ns 17.8300\n" + 585 "\n" + 586 "newmtl redbrown\n" + 587 "Ka 0.1469 0.0031 0.0000\n" + 588 "Kd 0.2816 0.0060 0.0000\n" + 589 "Ks 0.3714 0.3714 0.3714\n" + 590 "illum 2\n" + 591 "Ns 141.0900\n" + 592 "\n" + 593 "newmtl deepgreen\n" + 594 "Ka 0.0000 0.0050 0.0000\n" + 595 "Kd 0.0000 0.0204 0.0050\n" + 596 "Ks 0.3000 0.3000 0.3000\n" + 597 "illum 2\n" + 598 "Ns 113.1800\n" + 599 "\n" + 600 "newmtl flltolivegreen\n" + 601 "Ka 0.0167 0.0245 0.0000\n" + 602 "Kd 0.0393 0.0531 0.0100\n" + 603 "illum 1\n" + 604 "\n" + 605 "newmtl jetflame\n" + 606 "Ka 0.7714 0.0000 0.0000\n" + 607 "Kd 0.9510 0.4939 0.0980\n" + 608 "Ks 0.8531 0.5222 0.0000\n" + 609 "illum 2\n" + 610 "Ns 132.5600\n" + 611 "\n" + 612 "newmtl brownskn\n" + 613 "Ka 0.0122 0.0041 0.0000\n" + 614 "Kd 0.0204 0.0082 0.0000\n" + 615 "Ks 0.0735 0.0508 0.0321\n" + 616 "illum 2\n" + 617 "Ns 20.1600\n" + 618 "\n" + 619 "newmtl greenskn\n" + 620 "Ka 0.0816 0.0449 0.0000\n" + 621 "Kd 0.0000 0.0735 0.0000\n" + 622 "Ks 0.0490 0.1224 0.0898\n" + 623 "illum 3\n" + 624 "Ns 46.5100\n" + 625 "sharpness 146.5100\n" + 626 "\n" + 627 "newmtl ltgrey\n" + 628 "Ka 0.5000 0.5000 0.5000\n" + 629 "Kd 0.3837 0.3837 0.3837\n" + 630 "Ks 0.5000 0.5000 0.5000\n" + 631 "illum 2\n" + 632 "Ns 65.8900\n" + 633 "\n" + 634 "newmtl bronze\n" + 635 "Ka 0.0449 0.0204 0.0000\n" + 636 "Kd 0.0653 0.0367 0.0122\n" + 637 "Ks 0.0776 0.0408 0.0000\n" + 638 "illum 3\n" + 639 "Ns 137.2100\n" + 640 "sharpness 125.5800\n" + 641 "\n" + 642 "newmtl bone1\n" + 643 "Ka 0.6408 0.5554 0.3845\n" + 644 "Kd 0.9837 0.7959 0.4694\n" + 645 "illum 1\n" + 646 "\n" + 647 "newmtl flwhite1\n" + 648 "Ka 0.9306 0.9306 0.9306\n" + 649 "Kd 1.0000 1.0000 1.0000\n" + 650 "illum 1\n" + 651 "\n" + 652 "newmtl flwhite\n" + 653 "Ka 0.6449 0.6116 0.5447\n" + 654 "Kd 0.9837 0.9309 0.8392\n" + 655 "Ks 0.8082 0.7290 0.5708\n" + 656 "illum 2\n" + 657 "Ns 200.0000\n" + 658 "\n" + 659 "newmtl shadow\n" + 660 "Kd 0.0350 0.0248 0.0194\n" + 661 "illum 0\n" + 662 "d 0.2500\n" + 663 "\n" + 664 "newmtl fldkolivegreen\n" + 665 "Ka 0.0056 0.0082 0.0000\n" + 666 "Kd 0.0151 0.0204 0.0038\n" + 667 "illum 1\n" + 668 "\n" + 669 "newmtl fldkdkgrey\n" + 670 "Ka 0.0000 0.0000 0.0000\n" + 671 "Kd 0.0122 0.0122 0.0122\n" + 672 "illum 1\n" + 673 "\n" + 674 "newmtl lcdgreen\n" + 675 "Ka 0.4000 0.4000 0.4000\n" + 676 "Kd 0.5878 1.0000 0.5061\n" + 677 "Ks 0.3000 0.3000 0.3000\n" + 678 "illum 2\n" + 679 "Ns 60.0000\n" + 680 "\n" + 681 "newmtl brownlips\n" + 682 "Ka 0.1143 0.0694 0.0245\n" + 683 "Kd 0.1429 0.0653 0.0408\n" + 684 "Ks 0.3000 0.3000 0.3000\n" + 685 "illum 2\n" + 686 "Ns 25.0000\n" + 687 "\n" + 688 "newmtl muscle\n" + 689 "Ka 0.2122 0.0077 0.0154\n" + 690 "Kd 0.4204 0.0721 0.0856\n" + 691 "Ks 0.1184 0.1184 0.1184\n" + 692 "illum 2\n" + 693 "Ns 25.5800\n" + 694 "\n" + 695 "newmtl flltgrey\n" + 696 "Ka 0.5224 0.5224 0.5224\n" + 697 "Kd 0.8245 0.8245 0.8245\n" + 698 "illum 1\n" + 699 "\n" + 700 "newmtl offwhite.warm\n" + 701 "Ka 0.5184 0.4501 0.3703\n" + 702 "Kd 0.8367 0.6898 0.4490\n" + 703 "Ks 0.3000 0.3000 0.3000\n" + 704 "illum 2\n" + 705 "Ns 60.0000\n" + 706 "\n" + 707 "newmtl offwhite.cool\n" + 708 "Ka 0.5184 0.4501 0.3703\n" + 709 "Kd 0.8367 0.6812 0.5703\n" + 710 "Ks 0.3000 0.3000 0.3000\n" + 711 "illum 2\n" + 712 "Ns 60.0000\n" + 713 "\n" + 714 "newmtl yellowbrt\n" + 715 "Ka 0.4000 0.4000 0.4000\n" + 716 "Kd 1.0000 0.7837 0.0000\n" + 717 "Ks 0.3000 0.3000 0.3000\n" + 718 "illum 2\n" + 719 "Ns 60.0000\n" + 720 "\n" + 721 "newmtl chappie\n" + 722 "Ka 0.4000 0.4000 0.4000\n" + 723 "Kd 0.5837 0.1796 0.0367\n" + 724 "Ks 0.3000 0.3000 0.3000\n" + 725 "illum 2\n" + 726 "Ns 60.0000\n" + 727 "\n" + 728 "newmtl archwhite\n" + 729 "Ka 0.2816 0.2816 0.2816\n" + 730 "Kd 0.9959 0.9959 0.9959\n" + 731 "illum 1\n" + 732 "\n" + 733 "newmtl archwhite2\n" + 734 "Ka 0.2816 0.2816 0.2816\n" + 735 "Kd 0.8408 0.8408 0.8408\n" + 736 "illum 1\n" + 737 "\n" + 738 "newmtl lighttan\n" + 739 "Ka 0.0980 0.0536 0.0220\n" + 740 "Kd 0.7020 0.4210 0.2206\n" + 741 "Ks 0.8286 0.8057 0.5851\n" + 742 "illum 2\n" + 743 "Ns 177.5200\n" + 744 "\n" + 745 "newmtl lighttan2\n" + 746 "Ka 0.0980 0.0492 0.0144\n" + 747 "Kd 0.3143 0.1870 0.0962\n" + 748 "Ks 0.8286 0.8057 0.5851\n" + 749 "illum 2\n" + 750 "Ns 177.5200\n" + 751 "\n" + 752 "newmtl lighttan3\n" + 753 "Ka 0.0980 0.0492 0.0144\n" + 754 "Kd 0.1796 0.0829 0.0139\n" + 755 "Ks 0.8286 0.8057 0.5851\n" + 756 "illum 2\n" + 757 "Ns 177.5200\n" + 758 "\n" + 759 "newmtl lightyellow\n" + 760 "Ka 0.5061 0.1983 0.0000\n" + 761 "Kd 1.0000 0.9542 0.3388\n" + 762 "Ks 1.0000 0.9060 0.0000\n" + 763 "illum 2\n" + 764 "Ns 177.5200\n" + 765 "\n" + 766 "newmtl lighttannew\n" + 767 "Ka 0.0980 0.0492 0.0144\n" + 768 "Kd 0.7878 0.6070 0.3216\n" + 769 "Ks 0.8286 0.8057 0.5851\n" + 770 "illum 2\n" + 771 "Ns 177.5200\n" + 772 "\n" + 773 "newmtl default\n" + 774 "Ka 0.4000 0.4000 0.4000\n" + 775 "Kd 0.7102 0.7020 0.6531\n" + 776 "Ks 0.3000 0.3000 0.3000\n" + 777 "illum 2\n" + 778 "Ns 128.0000\n" + 779 "\n" + 780 "newmtl ship2\n" + 781 "Ka 0.0000 0.0000 0.0000\n" + 782 "Kd 1.0000 1.0000 1.0000\n" + 783 "Ks 0.1143 0.1143 0.1143\n" + 784 "illum 2\n" + 785 "Ns 60.0000\n" + 786 "\n" + 787 "newmtl dkpurple\n" + 788 "Ka 0.0082 0.0000 0.0163\n" + 789 "Kd 0.0245 0.0000 0.0490\n" + 790 "Ks 0.1266 0.0000 0.2531\n" + 791 "illum 2\n" + 792 "Ns 65.8900\n" + 793 "\n" + 794 "newmtl dkorange\n" + 795 "Ka 0.4041 0.0123 0.0000\n" + 796 "Kd 0.7143 0.0350 0.0000\n" + 797 "Ks 0.7102 0.0870 0.0000\n" + 798 "illum 2\n" + 799 "Ns 65.8900\n" + 800 "\n" + 801 "newmtl mintgrn\n" + 802 "Ka 0.0101 0.1959 0.0335\n" + 803 "Kd 0.0245 0.4776 0.0816\n" + 804 "Ks 0.0245 0.4776 0.0816\n" + 805 "illum 2\n" + 806 "Ns 65.8900\n" + 807 "\n" + 808 "newmtl fgreen\n" + 809 "Ka 0.0000 0.0449 0.0000\n" + 810 "Kd 0.0000 0.0449 0.0004\n" + 811 "Ks 0.0062 0.0694 0.0000\n" + 812 "illum 2\n" + 813 "Ns 106.2000\n" + 814 "\n" + 815 "newmtl glassblutint\n" + 816 "Ka 0.4000 0.4000 0.4000\n" + 817 "Kd 0.5551 0.8000 0.7730\n" + 818 "Ks 0.7969 0.9714 0.9223\n" + 819 "illum 4\n" + 820 "d 0.6700\n" + 821 "Ns 60.0000\n" + 822 "sharpness 60.0000\n" + 823 "\n" + 824 "newmtl bflesh\n" + 825 "Ka 0.0122 0.0122 0.0122\n" + 826 "Kd 0.0245 0.0081 0.0021\n" + 827 "Ks 0.0531 0.0460 0.0153\n" + 828 "illum 2\n" + 829 "Ns 20.1600\n" + 830 "\n" + 831 "newmtl meh\n" + 832 "Ka 0.4000 0.4000 0.4000\n" + 833 "Kd 0.5551 0.8000 0.7730\n" + 834 "Ks 0.7969 0.9714 0.9223\n" + 835 "illum 4\n" + 836 "d 0.2500\n" + 837 "Ns 183.7200\n" + 838 "sharpness 60.0000\n" + 839 "\n" + 840 "newmtl violet\n" + 841 "Ka 0.0083 0.0000 0.1265\n" + 842 "Kd 0.0287 0.0269 0.1347\n" + 843 "Ks 0.2267 0.4537 0.6612\n" + 844 "illum 2\n" + 845 "Ns 96.9000\n" + 846 "\n" + 847 "newmtl iris\n" + 848 "Ka 0.3061 0.0556 0.0037\n" + 849 "Kd 0.0000 0.0572 0.3184\n" + 850 "Ks 0.8041 0.6782 0.1477\n" + 851 "illum 2\n" + 852 "Ns 188.3700\n" + 853 "\n" + 854 "newmtl blugrn\n" + 855 "Ka 0.4408 0.4144 0.1592\n" + 856 "Kd 0.0811 0.6408 0.2775\n" + 857 "Ks 0.1467 0.1469 0.0965\n" + 858 "illum 2\n" + 859 "Ns 25.0000\n" + 860 "\n" + 861 "newmtl glasstransparent\n" + 862 "Ka 0.2163 0.2163 0.2163\n" + 863 "Kd 0.4694 0.4694 0.4694\n" + 864 "Ks 0.6082 0.6082 0.6082\n" + 865 "illum 4\n" + 866 "d 0.2500\n" + 867 "Ns 200.0000\n" + 868 "sharpness 60.0000\n" + 869 "\n" + 870 "newmtl fleshtransparent\n" + 871 "Ka 0.4000 0.2253 0.2253\n" + 872 "Kd 0.6898 0.2942 0.1295\n" + 873 "Ks 0.7388 0.4614 0.4614\n" + 874 "illum 4\n" + 875 "d 0.2500\n" + 876 "Ns 6.2000\n" + 877 "sharpness 60.0000\n" + 878 "\n" + 879 "newmtl fldkgrey\n" + 880 "Ka 0.0449 0.0449 0.0449\n" + 881 "Kd 0.0939 0.0939 0.0939\n" + 882 "illum 1\n" + 883 "\n" + 884 "newmtl sky_blue\n" + 885 "Ka 0.1363 0.2264 0.4122\n" + 886 "Kd 0.1241 0.5931 0.8000\n" + 887 "Ks 0.0490 0.0490 0.0490\n" + 888 "illum 2\n" + 889 "Ns 13.9500\n" + 890 "\n" + 891 "newmtl fldkpurple\n" + 892 "Ka 0.0443 0.0257 0.0776\n" + 893 "Kd 0.1612 0.0000 0.3347\n" + 894 "Ks 0.0000 0.0000 0.0000\n" + 895 "illum 2\n" + 896 "Ns 13.9500\n" + 897 "\n" + 898 "newmtl dkbrown\n" + 899 "Ka 0.0143 0.0062 0.0027\n" + 900 "Kd 0.0087 0.0038 0.0016\n" + 901 "Ks 0.2370 0.2147 0.1821\n" + 902 "illum 3\n" + 903 "Ns 60.0000\n" + 904 "sharpness 60.0000\n" + 905 "\n" + 906 "newmtl bone2\n" + 907 "Ka 0.6408 0.5388 0.3348\n" + 908 "Kd 0.9837 0.8620 0.6504\n" + 909 "illum 1\n" + 910 "\n" + 911 "newmtl bluegrey\n" + 912 "Ka 0.4000 0.4000 0.4000\n" + 913 "Kd 0.1881 0.2786 0.2898\n" + 914 "Ks 0.3000 0.3000 0.3000\n" + 915 "illum 2\n" + 916 "Ns 14.7300\n" + 917 "\n" + 918 "newmtl metal\n" + 919 "Ka 0.9102 0.8956 0.1932\n" + 920 "Kd 0.9000 0.7626 0.4261\n" + 921 "Ks 0.8939 0.8840 0.8683\n" + 922 "illum 2\n" + 923 "Ns 200.0000\n" + 924 "\n" + 925 "newmtl sand_stone\n" + 926 "Ka 0.1299 0.1177 0.0998\n" + 927 "Kd 0.1256 0.1138 0.0965\n" + 928 "Ks 0.2370 0.2147 0.1821\n" + 929 "illum 3\n" + 930 "Ns 60.0000\n" + 931 "sharpness 60.0000\n" + 932 "\n" + 933 "newmtl hair\n" + 934 "Ka 0.0013 0.0012 0.0010\n" + 935 "Kd 0.0008 0.0007 0.0006\n" + 936 "Ks 0.0000 0.0000 0.0000\n" + 937 "illum 3\n" + 938 "Ns 60.0000\n" + 939 "sharpness 60.0000\n", OBJLoader.defaultAppearances, null, null); 940 } 941 } 942 OBJLoader.prototype = Object.create(ModelLoader.prototype); 943 OBJLoader.prototype.constructor = OBJLoader; 944 945 OBJLoader.defaultAppearances = null; 946 947 /** 948 * Creates a new scene from the parsed <code>groups</code> and calls onmodelcreated asynchronously or 949 * returns the created scene if onmodelcreated is null. 950 * <code>groups</code> is empty after method call. 951 * @private 952 */ 953 OBJLoader.prototype.createScene = function(vertices, textureCoordinates, normals, groups, appearances, onmodelcreated, onprogression) { 954 var sceneRoot = new Group3D(); 955 if (onmodelcreated === null) { 956 onprogression(ModelLoader.BUILDING_MODEL, "", 0); 957 for (var key in groups) { 958 this.createGroupShapes(vertices, textureCoordinates, normals, groups [key], appearances, sceneRoot); 959 } 960 onprogression(ModelLoader.BUILDING_MODEL, "", 1); 961 return sceneRoot; 962 } else { 963 var groupsGeometryCount = 0; 964 for (var key in groups) { 965 groupsGeometryCount += groups [key].geometries.length; 966 } 967 var builtGeometryCount = 0; 968 var loader = this; 969 var sceneBuilder = function() { 970 onprogression(ModelLoader.BUILDING_MODEL, "", groupsGeometryCount !== 0 ? builtGeometryCount / groupsGeometryCount : 0); 971 var start = Date.now(); 972 for (var key in groups) { 973 loader.createGroupShapes(vertices, textureCoordinates, normals, groups [key], appearances, sceneRoot); 974 builtGeometryCount += groups [key].geometries.length; 975 delete groups[key]; 976 if (builtGeometryCount < groupsGeometryCount 977 && Date.now() - start > 10) { 978 // Continue shapes creation later 979 setTimeout(sceneBuilder, 0); 980 return; 981 } 982 } 983 // All shapes are created 984 setTimeout( 985 function() { 986 onprogression(ModelLoader.BUILDING_MODEL, "", 1); 987 onmodelcreated(sceneRoot); 988 }, 0); 989 }; 990 sceneBuilder(); 991 } 992 } 993 994 /** 995 * Creates the 3D shapes matching the parsed data of a group, and adds them to <code>sceneRoot</code>. 996 * @private 997 */ 998 OBJLoader.prototype.createGroupShapes = function(vertices, textureCoordinates, normals, group, appearances, sceneRoot) { 999 var geometries = group.geometries; 1000 if (geometries.length > 0) { 1001 var i = 0; 1002 while (i < geometries.length) { 1003 var firstGeometry = geometries [i]; 1004 var firstGeometryHasTextureCoordinateIndices = firstGeometry.textureCoordinateIndices.length > 0; 1005 var firstFaceHasNormalIndices = (firstGeometry instanceof OBJLoader.OBJFace) && firstGeometry.normalIndices.length > 0; 1006 var firstFaceIsSmooth = (firstGeometry instanceof OBJLoader.OBJFace) && firstGeometry.smooth; 1007 1008 var firstGeometryMaterial = firstGeometry.material; 1009 var appearance = OBJLoader.getAppearance(appearances, firstGeometryMaterial); 1010 // Search how many geometries share the same characteristics 1011 var max = i; 1012 while (++max < geometries.length) { 1013 var geometry = geometries [max]; 1014 var material = geometry.material; 1015 if ((geometry.constructor !== firstGeometry.constructor) 1016 || material === null && firstGeometryMaterial !== null 1017 || material !== null && OBJLoader.getAppearance(appearances, material) !== appearance 1018 || (firstFaceIsSmooth ^ ((geometry instanceof OBJLoader.OBJFace) && geometry.smooth)) 1019 || (firstGeometryHasTextureCoordinateIndices ^ geometry.textureCoordinateIndices.length > 0) 1020 || (firstFaceHasNormalIndices ^ ((geometry instanceof OBJLoader.OBJFace) && geometry.normalIndices.length > 0))) { 1021 break; 1022 } 1023 } 1024 1025 // Clone appearance to avoid sharing it 1026 if (appearance !== null) { 1027 appearance = appearance.clone(); 1028 } 1029 1030 // Create indices arrays for the geometries with an index between i and max 1031 var geometryCount = max - i; 1032 var coordinatesIndices = []; 1033 var stripCounts = []; 1034 var onlyTriangles = true; 1035 for (var j = 0; j < geometryCount; j++) { 1036 var geometryVertexIndices = geometries [i + j].vertexIndices; 1037 coordinatesIndices.push.apply(coordinatesIndices, geometryVertexIndices); 1038 stripCounts.push(geometryVertexIndices.length); 1039 if (onlyTriangles && geometryVertexIndices.length !== 3) { 1040 onlyTriangles = false; 1041 } 1042 } 1043 var textureCoordinateIndices = []; 1044 if (firstGeometryHasTextureCoordinateIndices) { 1045 for (var j = 0; j < geometryCount; j++) { 1046 textureCoordinateIndices.push.apply(textureCoordinateIndices, geometries [i + j].textureCoordinateIndices); 1047 } 1048 } 1049 1050 var geometryArray; 1051 if (firstGeometry instanceof OBJLoader.OBJFace) { 1052 var normalIndices = []; 1053 if (firstFaceHasNormalIndices) { 1054 for (var j = 0; j < geometryCount; j++) { 1055 normalIndices.push.apply(normalIndices, geometries [i + j].normalIndices); 1056 } 1057 } 1058 var geometryInfo = new GeometryInfo3D(onlyTriangles 1059 ? GeometryInfo3D.TRIANGLE_ARRAY 1060 : GeometryInfo3D.POLYGON_ARRAY); 1061 geometryInfo.setCoordinates(vertices); 1062 geometryInfo.setCoordinateIndices(coordinatesIndices); 1063 geometryInfo.setNormals(normals); 1064 geometryInfo.setNormalIndices(normalIndices); 1065 geometryInfo.setTextureCoordinates(textureCoordinates); 1066 geometryInfo.setTextureCoordinateIndices(textureCoordinateIndices); 1067 geometryInfo.setStripCounts(stripCounts); 1068 if (!firstFaceHasNormalIndices) { 1069 geometryInfo.setCreaseAngle(firstFaceIsSmooth ? Math.PI / 2 : 0); 1070 geometryInfo.setGeneratedNormals(true); 1071 } 1072 geometryArray = geometryInfo.getIndexedGeometryArray(); 1073 } else { // Line 1074 var lineCoordinatesIndices = []; 1075 var lineTextureCoordinateIndices = []; 1076 for (var j = 0, index = 0; j < geometryCount; index += stripCounts [j], j++) { 1077 for (var k = 0; k < stripCounts [j] - 1; k++) { 1078 lineCoordinatesIndices.push(coordinatesIndices [index + k]); 1079 lineCoordinatesIndices.push(coordinatesIndices [index + k + 1]); 1080 if (textureCoordinateIndices.length > 0) { 1081 lineTextureCoordinateIndices.push(textureCoordinateIndices [index + k]); 1082 lineTextureCoordinateIndices.push(textureCoordinateIndices [index + k + 1]); 1083 } 1084 } 1085 } 1086 geometryArray = new IndexedLineArray3D(vertices, lineCoordinatesIndices, 1087 textureCoordinates, lineTextureCoordinateIndices); 1088 } 1089 1090 var shape = new Shape3D(geometryArray, appearance); 1091 sceneRoot.addChild(shape); 1092 shape.setName(group.name + (i === 0 ? "" : "_" + i)); 1093 i = max; 1094 } 1095 } 1096 } 1097 1098 /** 1099 * Returns the appearance matching a given material. 1100 * @private 1101 */ 1102 OBJLoader.getAppearance = function(appearances, material) { 1103 var appearance = undefined; 1104 if (material !== null) { 1105 appearance = appearances [material]; 1106 } 1107 if (appearance === undefined) { 1108 appearance = OBJLoader.defaultAppearances ["default"]; 1109 } 1110 return appearance; 1111 } 1112 1113 /** 1114 * Parses the given OBJ content and stores the materials it describes in appearances attribute 1115 * of <code>modelContext</code>. 1116 * @protected 1117 */ 1118 OBJLoader.prototype.parseDependencies = function(objContent, objEntryName, zip, modelContext) { 1119 modelContext.appearances = {}; 1120 for (var k in OBJLoader.defaultAppearances) { 1121 var appearance = OBJLoader.defaultAppearances [k]; 1122 modelContext.appearances [appearance.getName()] = appearance; 1123 } 1124 1125 try { 1126 var mtllibIndex = objContent.indexOf("mtllib"); 1127 while (mtllibIndex !== -1) { 1128 var endOfLine = mtllibIndex + 6; 1129 while (endOfLine < objContent.length 1130 && objContent.charAt(endOfLine) != '\n' 1131 && objContent.charAt(endOfLine) != '\r') { 1132 endOfLine++; 1133 } 1134 var line = objContent.substring(mtllibIndex, endOfLine).trim(); 1135 var mtllib = line.substring(7, line.length).trim(); 1136 this.parseMaterialEntry(mtllib, modelContext.appearances, objEntryName, zip); 1137 1138 mtllibIndex = objContent.indexOf("mtllib", endOfLine); 1139 } 1140 } catch (ex) { 1141 modelContext.appearances = {}; 1142 } 1143 } 1144 1145 /** 1146 * Parses the given OBJ content and calls onmodelloaded asynchronously or 1147 * returns the scene it describes if onmodelloaded is null. 1148 * @protected 1149 */ 1150 OBJLoader.prototype.parseEntryScene = function(objContent, objEntryName, zip, modelContext, onmodelloaded, onprogression) { 1151 var vertices = []; 1152 var textureCoordinates = []; 1153 var normals = []; 1154 var defaultGroup = new OBJLoader.OBJGroup("default"); 1155 var groups = {"default" : defaultGroup}; 1156 var materialGroupsWithNormals = {}; 1157 var currentObjects = {group : defaultGroup, 1158 material : "default", 1159 smooth : false}; 1160 1161 if (onmodelloaded === null) { 1162 try { 1163 onprogression(ModelLoader.PARSING_MODEL, objEntryName, 0); 1164 for (var startOfLine = 0; startOfLine <= objContent.length; ) { 1165 startOfLine = this.parseObjectLine(objContent, startOfLine, vertices, textureCoordinates, normals, groups, 1166 materialGroupsWithNormals, currentObjects); 1167 } 1168 onprogression(ModelLoader.PARSING_MODEL, objEntryName, 1); 1169 return this.createScene(vertices, textureCoordinates, normals, groups, modelContext.appearances, null, onprogression); 1170 } catch (ex) { 1171 onprogression(ModelLoader.PARSING_MODEL, objEntryName, 1); 1172 return this.createScene([], [], [], {}, modelContext.appearances, null, onprogression); 1173 } 1174 } else { 1175 var startOfLine = 0; 1176 var loader = this; 1177 var objEntryParser = function() { 1178 try { 1179 onprogression(ModelLoader.PARSING_MODEL, objEntryName, startOfLine / objContent.length); 1180 var minimumIndexBeforeTimeout = startOfLine + 200000; 1181 var start = Date.now(); 1182 while (startOfLine <= objContent.length) { 1183 startOfLine = loader.parseObjectLine(objContent, startOfLine, vertices, textureCoordinates, normals, groups, 1184 materialGroupsWithNormals, currentObjects); 1185 if (startOfLine <= objContent.length 1186 && startOfLine > minimumIndexBeforeTimeout // Don't call Date.now() after parsing each line! 1187 && Date.now() - start > 10) { 1188 // Continue entry parsing later 1189 setTimeout(objEntryParser, 0); 1190 return; 1191 } 1192 } 1193 // Parsing is finished 1194 setTimeout( 1195 function() { 1196 onprogression(ModelLoader.PARSING_MODEL, objEntryName, 1); 1197 loader.createScene(vertices, textureCoordinates, normals, groups, modelContext.appearances, 1198 function(scene) { 1199 onmodelloaded(scene); 1200 }, 1201 onprogression); 1202 }, 0); 1203 } catch (ex) { 1204 onprogression(ModelLoader.PARSING_MODEL, objEntryName, 1); 1205 loader.createScene([], [], [], {}, modelContext.appearances, onmodelloaded, onprogression); 1206 } 1207 }; 1208 objEntryParser(); 1209 } 1210 } 1211 1212 /** 1213 * @private 1214 */ 1215 OBJLoader.prototype.parseObjectLine = function(objContent, startOfLine, vertices, textureCoordinates, normals, groups, 1216 materialGroupsWithNormals, currentObjects) { 1217 var endOfLine = startOfLine + 1; 1218 while (endOfLine < objContent.length 1219 && objContent.charAt(endOfLine) != '\n' 1220 && objContent.charAt(endOfLine) != '\r') { 1221 endOfLine++; 1222 } 1223 var line = objContent.substring(startOfLine, endOfLine); 1224 if (line.indexOf("v") === 0 || line.indexOf("f ") === 0 || line.indexOf("l ") === 0) { 1225 // Append to line next lines if it ends by a back slash 1226 while (line.charAt(line.length - 1) === '\\') { 1227 // Remove back slash 1228 line = line.substring(0, line.length - 1) + " "; 1229 // Read next line 1230 startOfLine = endOfLine + 1; 1231 if (startOfLine < objContent.length 1232 && objContent.charAt(endOfLine) == '\r' 1233 && objContent.charAt(startOfLine) == '\n') { 1234 startOfLine++; 1235 } 1236 endOfLine = startOfLine + 1; 1237 while (endOfLine < objContent.length 1238 && objContent.charAt(endOfLine) != '\n' 1239 && objContent.charAt(endOfLine) != '\r') { 1240 endOfLine++; 1241 } 1242 line += objContent.substring(startOfLine, endOfLine); 1243 } 1244 } 1245 1246 line = line.trim(); 1247 var strings = line.split(/\s+/); 1248 var start = strings [0]; 1249 if (start === "v") { 1250 vertices.push(OBJLoader.parseVector3f(strings)); 1251 } else if (start === "vt") { 1252 textureCoordinates.push(OBJLoader.parseVector2f(strings)); 1253 } else if (start === "vn") { 1254 try { 1255 normals.push(OBJLoader.parseVector3f(strings)); 1256 } catch (e) { 1257 console.log(objContent + " " + line) 1258 } 1259 } else if (start === "l") { 1260 var line = this.parseLine(strings, currentObjects.material); 1261 if (line.vertexIndices.length > 1) { 1262 currentObjects.group.addGeometry(line); 1263 } 1264 } else if (start === "f") { 1265 var face = this.parseFace(strings, currentObjects.smooth, currentObjects.material); 1266 if (face.vertexIndices.length > 2) { 1267 if (face.normalIndices.length === 0 1268 || currentObjects.group.name.indexOf("sweethome3d_") === 0) { 1269 currentObjects.group.addGeometry(face); 1270 } else { 1271 // Except for group names starting with sweethome3d_ which faces group mustn't be changed, 1272 // add faces with normals to the group with the same material 1273 // since there won't be any smooth normal to computes 1274 if (!(face.material in materialGroupsWithNormals)) { 1275 materialGroupsWithNormals [face.material] = currentObjects.group; 1276 } 1277 materialGroupsWithNormals [face.material].addGeometry(face); 1278 } 1279 } 1280 } else if (start === "g" || start === "o") { 1281 if (strings.length > 1) { 1282 var name = strings [1]; 1283 currentObjects.group = groups [name]; 1284 if (currentObjects.group === undefined) { 1285 currentObjects.group = new OBJLoader.OBJGroup(name); 1286 groups [name] = currentObjects.group; 1287 } 1288 } else { 1289 currentObjects.group = groups ["default"]; 1290 } 1291 } else if (start === "s") { 1292 currentObjects.smooth = strings [1] != "off"; 1293 } else if (start === "usemtl") { 1294 currentObjects.material = line.substring(7, line.length).trim(); 1295 } 1296 1297 startOfLine = endOfLine + 1; 1298 if (startOfLine < objContent.length 1299 && objContent.charAt(endOfLine) == '\r' 1300 && objContent.charAt(startOfLine) == '\n') { 1301 startOfLine++; 1302 } 1303 1304 return startOfLine; 1305 } 1306 1307 /** 1308 * Returns the object line in strings. 1309 * @private 1310 */ 1311 OBJLoader.prototype.parseLine = function(strings, material) { 1312 // l v v v ... 1313 // or l v/vt v/vt v/vt ... 1314 var vertexIndices = []; 1315 var textureCoordinateIndices = []; 1316 for (var i = 0; i < strings.length; i++) { 1317 var indices = strings [i]; 1318 if (i > 0 1319 && indices.length > 0) { 1320 var firstSlashIndex = indices.indexOf('/'); 1321 if (firstSlashIndex === -1) { 1322 // l v 1323 vertexIndices.push(OBJLoader.parseInteger(indices) - 1); 1324 } else { 1325 // l v/vt 1326 vertexIndices.push(OBJLoader.parseInteger(indices.substring(0, firstSlashIndex)) - 1); 1327 textureCoordinateIndices.push(OBJLoader.parseInteger(indices.substring(firstSlashIndex + 1)) - 1); 1328 } 1329 } 1330 } 1331 if (vertexIndices.length !== textureCoordinateIndices.length) { 1332 // Ignore unconsistent texture coordinate 1333 textureCoordinateIndices = []; 1334 } 1335 return new OBJLoader.OBJLine(vertexIndices, textureCoordinateIndices, material); 1336 } 1337 1338 /** 1339 * Returns the object face in strings. 1340 * @private 1341 */ 1342 OBJLoader.prototype.parseFace = function(strings, smooth, material) { 1343 // f v v v ... 1344 // or f v//vn v//vn v//vn ... 1345 // or f v/vt v/vt v/vt ... 1346 // or f v/vt/vn v/vt/vn v/vt/vn ... 1347 var vertexIndices = []; 1348 var textureCoordinateIndices = []; 1349 var normalIndices = []; 1350 for (var i = 0; i < strings.length; i++) { 1351 var indices = strings [i]; 1352 if (i > 0 1353 && indices.length > 0) { 1354 var firstSlashIndex = indices.indexOf('/'); 1355 if (firstSlashIndex === -1) { 1356 // f v 1357 vertexIndices.push(OBJLoader.parseInteger(indices) - 1); 1358 } else { 1359 vertexIndices.push(OBJLoader.parseInteger(indices.substring(0, firstSlashIndex)) - 1); 1360 var lastSlashIndex = indices.lastIndexOf('/'); 1361 if (firstSlashIndex === lastSlashIndex) { 1362 // f v/vt 1363 textureCoordinateIndices.push(OBJLoader.parseInteger(indices.substring(firstSlashIndex + 1)) - 1); 1364 } else { 1365 if (firstSlashIndex + 1 !== lastSlashIndex) { 1366 // f v/vt/vn 1367 textureCoordinateIndices.push(OBJLoader.parseInteger(indices.substring(firstSlashIndex + 1, lastSlashIndex)) - 1); 1368 } 1369 // f v//vn 1370 // or f v/vt/vn 1371 normalIndices.push(OBJLoader.parseInteger(indices.substring(lastSlashIndex + 1)) - 1); 1372 } 1373 } 1374 } 1375 } 1376 if (vertexIndices.length !== textureCoordinateIndices.length) { 1377 // Ignore unconsistent texture coordinate 1378 textureCoordinateIndices = []; 1379 } 1380 if (vertexIndices.length !== normalIndices.length) { 1381 // Ignore unconsistent normals 1382 normalIndices = []; 1383 } 1384 return new OBJLoader.OBJFace(vertexIndices, textureCoordinateIndices, normalIndices, smooth, material); 1385 } 1386 1387 /** 1388 * Parses appearances from the given material entry, then returns true if the given entry exists. 1389 * @private 1390 */ 1391 OBJLoader.prototype.parseMaterialEntry = function(mtlEntryName, appearances, objEntryName, zip) { 1392 var lastSlash = objEntryName.lastIndexOf("/"); 1393 if (lastSlash >= 0) { 1394 mtlEntryName = objEntryName.substring(0, lastSlash + 1) + mtlEntryName; 1395 } 1396 var mtlEntry = zip.file(mtlEntryName); 1397 if (mtlEntry !== null) { 1398 OBJLoader.parseMaterial(mtlEntry.asBinary(), appearances, objEntryName, zip); 1399 } 1400 } 1401 1402 /** 1403 * Returns a vector created from the numbers in 2nd to 4th strings. 1404 * @private 1405 */ 1406 OBJLoader.parseVector3f = function(strings) { 1407 // v x y z 1408 // or vn x y z 1409 // or Ka r g b 1410 // or Kd r g b 1411 // or Ks r g b 1412 return vec3.fromValues(OBJLoader.parseNumber(strings [1]), 1413 OBJLoader.parseNumber(strings [2]), 1414 OBJLoader.parseNumber(strings [3])); 1415 } 1416 1417 /** 1418 * Returns a vector created from the numbers in 2nd and 3rd strings. 1419 * @private 1420 */ 1421 OBJLoader.parseVector2f = function(strings) { 1422 // vt x y z 1423 return vec2.fromValues(OBJLoader.parseNumber(strings [1]), 1424 OBJLoader.parseNumber(strings [2])); 1425 } 1426 1427 /** 1428 * Returns the integer contained in the given parameter. 1429 * @private 1430 */ 1431 OBJLoader.parseInteger = function(string) { 1432 var i = parseInt(string); 1433 if (isNaN(i)) { 1434 throw new IncorrectFormat3DException("Incorrect integer " + string); 1435 } 1436 return i; 1437 } 1438 1439 /** 1440 * Returns the number contained in the given parameter. 1441 * @private 1442 */ 1443 OBJLoader.parseNumber = function(string) { 1444 var x = parseFloat(string); 1445 if (isNaN(x)) { 1446 if (string == "NaN") { 1447 return NaN; 1448 } 1449 throw new IncorrectFormat3DException("Incorrect number " + string); 1450 } 1451 return x; 1452 } 1453 1454 /** 1455 * Parses a map of appearances from the given content. 1456 * @private 1457 */ 1458 OBJLoader.parseMaterial = function(mtlContent, appearances, objEntryName, zip) { 1459 var currentAppearance = null; 1460 var lines = mtlContent.match(/^.*$/mg); 1461 for (var i = 0; i < lines.length; i++) { 1462 var line = lines [i].trim(); 1463 var strings = line.split(/\s+/); 1464 var start = strings [0]; 1465 if (start == "newmtl") { 1466 currentAppearance = new Appearance3D(line.substring(7, line.length).trim()); 1467 appearances [currentAppearance.getName()] = currentAppearance; 1468 } else if (currentAppearance !== null) { 1469 if (start == "Ka") { 1470 currentAppearance.setAmbientColor(OBJLoader.parseVector3f(strings)); 1471 } else if (start == "Kd") { 1472 currentAppearance.setDiffuseColor(OBJLoader.parseVector3f(strings)); 1473 } else if (start == "Ks") { 1474 currentAppearance.setSpecularColor(OBJLoader.parseVector3f(strings)); 1475 } else if (start == "Ns") { 1476 currentAppearance.setShininess(Math.max(1, Math.min(OBJLoader.parseNumber(strings [1]), 128))); 1477 } else if (start == "d") { 1478 // Store transparency opposite value 1479 currentAppearance.setTransparency(1 - Math.max(0, OBJLoader.parseNumber(strings [1] == "-halo" ? strings [2] : strings [1]))); 1480 } else if (start == "illum") { 1481 currentAppearance.setIllumination(OBJLoader.parseInteger(strings [1])); 1482 } else if (start == "map_Kd") { 1483 var imageEntryName = strings [strings.length - 1]; 1484 var lastSlash = objEntryName.lastIndexOf("/"); 1485 if (lastSlash >= 0) { 1486 imageEntryName = objEntryName.substring(0, lastSlash + 1) + imageEntryName; 1487 } 1488 var imageEntry = zip.file(imageEntryName); 1489 if (imageEntry === null 1490 && strings.length > 2) { 1491 imageEntryName = line.substring(7, line.length).trim(); 1492 if (lastSlash >= 0) { 1493 imageEntryName = objEntryName.substring(0, lastSlash + 1) + imageEntryName; 1494 } 1495 imageEntry = zip.file(imageEntryName); 1496 } 1497 if (imageEntry !== null) { 1498 currentAppearance.imageEntryName = imageEntryName; 1499 } 1500 } 1501 // Ignore Ni and sharpness 1502 } 1503 } 1504 } 1505 1506 /** 1507 * Creates a group of geometries read in an OBJ file. 1508 * @constructor 1509 * @private 1510 */ 1511 OBJLoader.OBJGroup = function(name) { 1512 this.name = name; 1513 this.geometries = []; 1514 } 1515 1516 OBJLoader.OBJGroup.prototype.addGeometry = function(geometry) { 1517 this.geometries.push(geometry); 1518 }; 1519 1520 /** 1521 * Creates a line read in an OBJ file. 1522 * @constructor 1523 * @private 1524 */ 1525 OBJLoader.OBJLine = function(vertexIndices, textureCoordinateIndices, material) { 1526 this.vertexIndices = vertexIndices; 1527 this.textureCoordinateIndices = textureCoordinateIndices; 1528 this.material = material; 1529 } 1530 1531 /** 1532 * Creates a face read in an OBJ file. 1533 * @constructor 1534 * @private 1535 */ 1536 OBJLoader.OBJFace = function(vertexIndices, textureCoordinateIndices, normalIndices, smooth, material) { 1537 this.vertexIndices = vertexIndices; 1538 this.textureCoordinateIndices = textureCoordinateIndices; 1539 this.normalIndices = normalIndices; 1540 this.smooth = smooth; 1541 this.material = material; 1542 } 1543