otsdaq_utilities  v2_05_02_indev
three.extra.js
1 // Collection of additional THREE.js classes, required in JSROOT
2 
3 (function( factory ) {
4  if ( typeof define === "function" && define.amd ) {
5  define( ['JSRootCore', 'threejs'], factory );
6  } else
7  if (typeof exports === 'object' && typeof module !== 'undefined') {
8  var jsroot = require("./JSRootCore.js");
9  factory(jsroot, require("three"), jsroot.nodejs || (typeof document=='undefined') ? jsroot.nodejs_document : document);
10  } else {
11 
12  if (typeof JSROOT == 'undefined')
13  throw new Error('JSROOT is not defined', 'three.extra.js');
14 
15  if (typeof THREE == 'undefined')
16  throw new Error('THREE is not defined', 'three.extra.js');
17 
18  factory(JSROOT, THREE, document);
19  }
20 } (function(JSROOT, THREE, document) {
21 
22  "use strict";
23 
24  if ((typeof document=='undefined') && (typeof window=='object')) document = window.document;
25 
26  // ===============================================================
27 
28  // Small initialisation part for used THREE font
29  JSROOT.threejs_font_helvetiker_regular = new THREE.Font(
30 {"glyphs":{"ο":{"x_min":0,"x_max":712,"ha":815,"o":"m 356 -25 q 96 88 192 -25 q 0 368 0 201 q 92 642 0 533 q 356 761 192 761 q 617 644 517 761 q 712 368 712 533 q 619 91 712 201 q 356 -25 520 -25 m 356 85 q 527 175 465 85 q 583 369 583 255 q 528 562 583 484 q 356 651 466 651 q 189 560 250 651 q 135 369 135 481 q 187 177 135 257 q 356 85 250 85 "},"S":{"x_min":0,"x_max":788,"ha":890,"o":"m 788 291 q 662 54 788 144 q 397 -26 550 -26 q 116 68 226 -26 q 0 337 0 168 l 131 337 q 200 152 131 220 q 384 85 269 85 q 557 129 479 85 q 650 270 650 183 q 490 429 650 379 q 194 513 341 470 q 33 739 33 584 q 142 964 33 881 q 388 1041 242 1041 q 644 957 543 1041 q 756 716 756 867 l 625 716 q 561 874 625 816 q 395 933 497 933 q 243 891 309 933 q 164 759 164 841 q 325 609 164 656 q 625 526 475 568 q 788 291 788 454 "},"¦":{"x_min":343,"x_max":449,"ha":792,"o":"m 449 462 l 343 462 l 343 986 l 449 986 l 449 462 m 449 -242 l 343 -242 l 343 280 l 449 280 l 449 -242 "},"/":{"x_min":183.25,"x_max":608.328125,"ha":792,"o":"m 608 1041 l 266 -129 l 183 -129 l 520 1041 l 608 1041 "},"Τ":{"x_min":-0.4375,"x_max":777.453125,"ha":839,"o":"m 777 893 l 458 893 l 458 0 l 319 0 l 319 892 l 0 892 l 0 1013 l 777 1013 l 777 893 "},"y":{"x_min":0,"x_max":684.78125,"ha":771,"o":"m 684 738 l 388 -83 q 311 -216 356 -167 q 173 -279 252 -279 q 97 -266 133 -279 l 97 -149 q 132 -155 109 -151 q 168 -160 155 -160 q 240 -114 213 -160 q 274 -26 248 -98 l 0 738 l 137 737 l 341 139 l 548 737 l 684 738 "},"Π":{"x_min":0,"x_max":803,"ha":917,"o":"m 803 0 l 667 0 l 667 886 l 140 886 l 140 0 l 0 0 l 0 1012 l 803 1012 l 803 0 "},"ΐ":{"x_min":-111,"x_max":339,"ha":361,"o":"m 339 800 l 229 800 l 229 925 l 339 925 l 339 800 m -1 800 l -111 800 l -111 925 l -1 925 l -1 800 m 284 3 q 233 -10 258 -5 q 182 -15 207 -15 q 85 26 119 -15 q 42 200 42 79 l 42 737 l 167 737 l 168 215 q 172 141 168 157 q 226 101 183 101 q 248 103 239 101 q 284 112 257 104 l 284 3 m 302 1040 l 113 819 l 30 819 l 165 1040 l 302 1040 "},"g":{"x_min":0,"x_max":686,"ha":838,"o":"m 686 34 q 586 -213 686 -121 q 331 -306 487 -306 q 131 -252 216 -306 q 31 -84 31 -190 l 155 -84 q 228 -174 166 -138 q 345 -207 284 -207 q 514 -109 454 -207 q 564 89 564 -27 q 461 6 521 36 q 335 -23 401 -23 q 88 100 184 -23 q 0 370 0 215 q 87 634 0 522 q 330 758 183 758 q 457 728 398 758 q 564 644 515 699 l 564 737 l 686 737 l 686 34 m 582 367 q 529 560 582 481 q 358 652 468 652 q 189 561 250 652 q 135 369 135 482 q 189 176 135 255 q 361 85 251 85 q 529 176 468 85 q 582 367 582 255 "},"²":{"x_min":0,"x_max":442,"ha":539,"o":"m 442 383 l 0 383 q 91 566 0 492 q 260 668 176 617 q 354 798 354 727 q 315 875 354 845 q 227 905 277 905 q 136 869 173 905 q 99 761 99 833 l 14 761 q 82 922 14 864 q 232 974 141 974 q 379 926 316 974 q 442 797 442 878 q 351 635 442 704 q 183 539 321 611 q 92 455 92 491 l 442 455 l 442 383 "},"–":{"x_min":0,"x_max":705.5625,"ha":803,"o":"m 705 334 l 0 334 l 0 410 l 705 410 l 705 334 "},"Κ":{"x_min":0,"x_max":819.5625,"ha":893,"o":"m 819 0 l 650 0 l 294 509 l 139 356 l 139 0 l 0 0 l 0 1013 l 139 1013 l 139 526 l 626 1013 l 809 1013 l 395 600 l 819 0 "},"ƒ":{"x_min":-46.265625,"x_max":392,"ha":513,"o":"m 392 651 l 259 651 l 79 -279 l -46 -278 l 134 651 l 14 651 l 14 751 l 135 751 q 151 948 135 900 q 304 1041 185 1041 q 334 1040 319 1041 q 392 1034 348 1039 l 392 922 q 337 931 360 931 q 271 883 287 931 q 260 793 260 853 l 260 751 l 392 751 l 392 651 "},"e":{"x_min":0,"x_max":714,"ha":813,"o":"m 714 326 l 140 326 q 200 157 140 227 q 359 87 260 87 q 488 130 431 87 q 561 245 545 174 l 697 245 q 577 48 670 123 q 358 -26 484 -26 q 97 85 195 -26 q 0 363 0 197 q 94 642 0 529 q 358 765 195 765 q 626 627 529 765 q 714 326 714 503 m 576 429 q 507 583 564 522 q 355 650 445 650 q 206 583 266 650 q 140 429 152 522 l 576 429 "},"ό":{"x_min":0,"x_max":712,"ha":815,"o":"m 356 -25 q 94 91 194 -25 q 0 368 0 202 q 92 642 0 533 q 356 761 192 761 q 617 644 517 761 q 712 368 712 533 q 619 91 712 201 q 356 -25 520 -25 m 356 85 q 527 175 465 85 q 583 369 583 255 q 528 562 583 484 q 356 651 466 651 q 189 560 250 651 q 135 369 135 481 q 187 177 135 257 q 356 85 250 85 m 576 1040 l 387 819 l 303 819 l 438 1040 l 576 1040 "},"J":{"x_min":0,"x_max":588,"ha":699,"o":"m 588 279 q 287 -26 588 -26 q 58 73 126 -26 q 0 327 0 158 l 133 327 q 160 172 133 227 q 288 96 198 96 q 426 171 391 96 q 449 336 449 219 l 449 1013 l 588 1013 l 588 279 "},"»":{"x_min":-1,"x_max":503,"ha":601,"o":"m 503 302 l 280 136 l 281 256 l 429 373 l 281 486 l 280 608 l 503 440 l 503 302 m 221 302 l 0 136 l 0 255 l 145 372 l 0 486 l -1 608 l 221 440 l 221 302 "},"©":{"x_min":-3,"x_max":1008,"ha":1106,"o":"m 502 -7 q 123 151 263 -7 q -3 501 -3 294 q 123 851 -3 706 q 502 1011 263 1011 q 881 851 739 1011 q 1008 501 1008 708 q 883 151 1008 292 q 502 -7 744 -7 m 502 60 q 830 197 709 60 q 940 501 940 322 q 831 805 940 681 q 502 944 709 944 q 174 805 296 944 q 65 501 65 680 q 173 197 65 320 q 502 60 294 60 m 741 394 q 661 246 731 302 q 496 190 591 190 q 294 285 369 190 q 228 497 228 370 q 295 714 228 625 q 499 813 370 813 q 656 762 588 813 q 733 625 724 711 l 634 625 q 589 704 629 673 q 498 735 550 735 q 377 666 421 735 q 334 504 334 597 q 374 340 334 408 q 490 272 415 272 q 589 304 549 272 q 638 394 628 337 l 741 394 "},"ώ":{"x_min":0,"x_max":922,"ha":1030,"o":"m 687 1040 l 498 819 l 415 819 l 549 1040 l 687 1040 m 922 339 q 856 97 922 203 q 650 -26 780 -26 q 538 9 587 -26 q 461 103 489 44 q 387 12 436 46 q 277 -22 339 -22 q 69 97 147 -22 q 0 338 0 202 q 45 551 0 444 q 161 737 84 643 l 302 737 q 175 552 219 647 q 124 336 124 446 q 155 179 124 248 q 275 88 197 88 q 375 163 341 88 q 400 294 400 219 l 400 572 l 524 572 l 524 294 q 561 135 524 192 q 643 88 591 88 q 762 182 719 88 q 797 341 797 257 q 745 555 797 450 q 619 737 705 637 l 760 737 q 874 551 835 640 q 922 339 922 444 "},"^":{"x_min":193.0625,"x_max":598.609375,"ha":792,"o":"m 598 772 l 515 772 l 395 931 l 277 772 l 193 772 l 326 1013 l 462 1013 l 598 772 "},"«":{"x_min":0,"x_max":507.203125,"ha":604,"o":"m 506 136 l 284 302 l 284 440 l 506 608 l 507 485 l 360 371 l 506 255 l 506 136 m 222 136 l 0 302 l 0 440 l 222 608 l 221 486 l 73 373 l 222 256 l 222 136 "},"D":{"x_min":0,"x_max":828,"ha":935,"o":"m 389 1013 q 714 867 593 1013 q 828 521 828 729 q 712 161 828 309 q 382 0 587 0 l 0 0 l 0 1013 l 389 1013 m 376 124 q 607 247 523 124 q 681 510 681 355 q 607 771 681 662 q 376 896 522 896 l 139 896 l 139 124 l 376 124 "},"∙":{"x_min":0,"x_max":142,"ha":239,"o":"m 142 585 l 0 585 l 0 738 l 142 738 l 142 585 "},"ÿ":{"x_min":0,"x_max":47,"ha":125,"o":"m 47 3 q 37 -7 47 -7 q 28 0 30 -7 q 39 -4 32 -4 q 45 3 45 -1 l 37 0 q 28 9 28 0 q 39 19 28 19 l 47 16 l 47 19 l 47 3 m 37 1 q 44 8 44 1 q 37 16 44 16 q 30 8 30 16 q 37 1 30 1 m 26 1 l 23 22 l 14 0 l 3 22 l 3 3 l 0 25 l 13 1 l 22 25 l 26 1 "},"w":{"x_min":0,"x_max":1009.71875,"ha":1100,"o":"m 1009 738 l 783 0 l 658 0 l 501 567 l 345 0 l 222 0 l 0 738 l 130 738 l 284 174 l 432 737 l 576 738 l 721 173 l 881 737 l 1009 738 "},"$":{"x_min":0,"x_max":700,"ha":793,"o":"m 664 717 l 542 717 q 490 825 531 785 q 381 872 450 865 l 381 551 q 620 446 540 522 q 700 241 700 370 q 618 45 700 116 q 381 -25 536 -25 l 381 -152 l 307 -152 l 307 -25 q 81 62 162 -25 q 0 297 0 149 l 124 297 q 169 146 124 204 q 307 81 215 89 l 307 441 q 80 536 148 469 q 13 725 13 603 q 96 910 13 839 q 307 982 180 982 l 307 1077 l 381 1077 l 381 982 q 574 917 494 982 q 664 717 664 845 m 307 565 l 307 872 q 187 831 233 872 q 142 724 142 791 q 180 618 142 656 q 307 565 218 580 m 381 76 q 562 237 562 96 q 517 361 562 313 q 381 423 472 409 l 381 76 "},"\\":{"x_min":-0.015625,"x_max":425.0625,"ha":522,"o":"m 425 -129 l 337 -129 l 0 1041 l 83 1041 l 425 -129 "},"µ":{"x_min":0,"x_max":697.21875,"ha":747,"o":"m 697 -4 q 629 -14 658 -14 q 498 97 513 -14 q 422 9 470 41 q 313 -23 374 -23 q 207 4 258 -23 q 119 81 156 32 l 119 -278 l 0 -278 l 0 738 l 124 738 l 124 343 q 165 173 124 246 q 308 83 216 83 q 452 178 402 83 q 493 359 493 255 l 493 738 l 617 738 l 617 214 q 623 136 617 160 q 673 92 637 92 q 697 96 684 92 l 697 -4 "},"Ι":{"x_min":42,"x_max":181,"ha":297,"o":"m 181 0 l 42 0 l 42 1013 l 181 1013 l 181 0 "},"Ύ":{"x_min":0,"x_max":1144.5,"ha":1214,"o":"m 1144 1012 l 807 416 l 807 0 l 667 0 l 667 416 l 325 1012 l 465 1012 l 736 533 l 1004 1012 l 1144 1012 m 277 1040 l 83 799 l 0 799 l 140 1040 l 277 1040 "},"’":{"x_min":0,"x_max":139,"ha":236,"o":"m 139 851 q 102 737 139 784 q 0 669 65 690 l 0 734 q 59 787 42 741 q 72 873 72 821 l 0 873 l 0 1013 l 139 1013 l 139 851 "},"Ν":{"x_min":0,"x_max":801,"ha":915,"o":"m 801 0 l 651 0 l 131 822 l 131 0 l 0 0 l 0 1013 l 151 1013 l 670 191 l 670 1013 l 801 1013 l 801 0 "},"-":{"x_min":8.71875,"x_max":350.390625,"ha":478,"o":"m 350 317 l 8 317 l 8 428 l 350 428 l 350 317 "},"Q":{"x_min":0,"x_max":968,"ha":1072,"o":"m 954 5 l 887 -79 l 744 35 q 622 -11 687 2 q 483 -26 556 -26 q 127 130 262 -26 q 0 504 0 279 q 127 880 0 728 q 484 1041 262 1041 q 841 884 708 1041 q 968 507 968 735 q 933 293 968 398 q 832 104 899 188 l 954 5 m 723 191 q 802 330 777 248 q 828 499 828 412 q 744 790 828 673 q 483 922 650 922 q 228 791 322 922 q 142 505 142 673 q 227 221 142 337 q 487 91 323 91 q 632 123 566 91 l 520 215 l 587 301 l 723 191 "},"ς":{"x_min":1,"x_max":676.28125,"ha":740,"o":"m 676 460 l 551 460 q 498 595 542 546 q 365 651 448 651 q 199 578 263 651 q 136 401 136 505 q 266 178 136 241 q 508 106 387 142 q 640 -50 640 62 q 625 -158 640 -105 q 583 -278 611 -211 l 465 -278 q 498 -182 490 -211 q 515 -80 515 -126 q 381 12 515 -15 q 134 91 197 51 q 1 388 1 179 q 100 651 1 542 q 354 761 199 761 q 587 680 498 761 q 676 460 676 599 "},"M":{"x_min":0,"x_max":954,"ha":1067,"o":"m 954 0 l 819 0 l 819 869 l 537 0 l 405 0 l 128 866 l 128 0 l 0 0 l 0 1013 l 200 1013 l 472 160 l 757 1013 l 954 1013 l 954 0 "},"Ψ":{"x_min":0,"x_max":1006,"ha":1094,"o":"m 1006 678 q 914 319 1006 429 q 571 200 814 200 l 571 0 l 433 0 l 433 200 q 92 319 194 200 q 0 678 0 429 l 0 1013 l 139 1013 l 139 679 q 191 417 139 492 q 433 326 255 326 l 433 1013 l 571 1013 l 571 326 l 580 326 q 813 423 747 326 q 868 679 868 502 l 868 1013 l 1006 1013 l 1006 678 "},"C":{"x_min":0,"x_max":886,"ha":944,"o":"m 886 379 q 760 87 886 201 q 455 -26 634 -26 q 112 136 236 -26 q 0 509 0 283 q 118 882 0 737 q 469 1041 245 1041 q 748 955 630 1041 q 879 708 879 859 l 745 708 q 649 862 724 805 q 473 920 573 920 q 219 791 312 920 q 136 509 136 675 q 217 229 136 344 q 470 99 311 99 q 672 179 591 99 q 753 379 753 259 l 886 379 "},"!":{"x_min":0,"x_max":138,"ha":236,"o":"m 138 684 q 116 409 138 629 q 105 244 105 299 l 33 244 q 16 465 33 313 q 0 684 0 616 l 0 1013 l 138 1013 l 138 684 m 138 0 l 0 0 l 0 151 l 138 151 l 138 0 "},"{":{"x_min":0,"x_max":480.5625,"ha":578,"o":"m 480 -286 q 237 -213 303 -286 q 187 -45 187 -159 q 194 48 187 -15 q 201 141 201 112 q 164 264 201 225 q 0 314 118 314 l 0 417 q 164 471 119 417 q 201 605 201 514 q 199 665 201 644 q 193 772 193 769 q 241 941 193 887 q 480 1015 308 1015 l 480 915 q 336 866 375 915 q 306 742 306 828 q 310 662 306 717 q 314 577 314 606 q 288 452 314 500 q 176 365 256 391 q 289 275 257 337 q 314 143 314 226 q 313 84 314 107 q 310 -11 310 -5 q 339 -131 310 -94 q 480 -182 377 -182 l 480 -286 "},"X":{"x_min":-0.015625,"x_max":854.15625,"ha":940,"o":"m 854 0 l 683 0 l 423 409 l 166 0 l 0 0 l 347 519 l 18 1013 l 186 1013 l 428 637 l 675 1013 l 836 1013 l 504 520 l 854 0 "},"#":{"x_min":0,"x_max":963.890625,"ha":1061,"o":"m 963 690 l 927 590 l 719 590 l 655 410 l 876 410 l 840 310 l 618 310 l 508 -3 l 393 -2 l 506 309 l 329 310 l 215 -2 l 102 -3 l 212 310 l 0 310 l 36 410 l 248 409 l 312 590 l 86 590 l 120 690 l 347 690 l 459 1006 l 573 1006 l 462 690 l 640 690 l 751 1006 l 865 1006 l 754 690 l 963 690 m 606 590 l 425 590 l 362 410 l 543 410 l 606 590 "},"ι":{"x_min":42,"x_max":284,"ha":361,"o":"m 284 3 q 233 -10 258 -5 q 182 -15 207 -15 q 85 26 119 -15 q 42 200 42 79 l 42 738 l 167 738 l 168 215 q 172 141 168 157 q 226 101 183 101 q 248 103 239 101 q 284 112 257 104 l 284 3 "},"Ά":{"x_min":0,"x_max":906.953125,"ha":982,"o":"m 283 1040 l 88 799 l 5 799 l 145 1040 l 283 1040 m 906 0 l 756 0 l 650 303 l 251 303 l 143 0 l 0 0 l 376 1012 l 529 1012 l 906 0 m 609 421 l 452 866 l 293 421 l 609 421 "},")":{"x_min":0,"x_max":318,"ha":415,"o":"m 318 365 q 257 25 318 191 q 87 -290 197 -141 l 0 -290 q 140 21 93 -128 q 193 360 193 189 q 141 704 193 537 q 0 1024 97 850 l 87 1024 q 257 706 197 871 q 318 365 318 542 "},"ε":{"x_min":0,"x_max":634.71875,"ha":714,"o":"m 634 234 q 527 38 634 110 q 300 -25 433 -25 q 98 29 183 -25 q 0 204 0 93 q 37 314 0 265 q 128 390 67 353 q 56 460 82 419 q 26 555 26 505 q 114 712 26 654 q 295 763 191 763 q 499 700 416 763 q 589 515 589 631 l 478 515 q 419 618 464 580 q 307 657 374 657 q 207 630 253 657 q 151 547 151 598 q 238 445 151 469 q 389 434 280 434 l 389 331 l 349 331 q 206 315 255 331 q 125 210 125 287 q 183 107 125 145 q 302 76 233 76 q 436 117 379 76 q 509 234 493 159 l 634 234 "},"Δ":{"x_min":0,"x_max":952.78125,"ha":1028,"o":"m 952 0 l 0 0 l 400 1013 l 551 1013 l 952 0 m 762 124 l 476 867 l 187 124 l 762 124 "},"}":{"x_min":0,"x_max":481,"ha":578,"o":"m 481 314 q 318 262 364 314 q 282 136 282 222 q 284 65 282 97 q 293 -58 293 -48 q 241 -217 293 -166 q 0 -286 174 -286 l 0 -182 q 143 -130 105 -182 q 171 -2 171 -93 q 168 81 171 22 q 165 144 165 140 q 188 275 165 229 q 306 365 220 339 q 191 455 224 391 q 165 588 165 505 q 168 681 165 624 q 171 742 171 737 q 141 865 171 827 q 0 915 102 915 l 0 1015 q 243 942 176 1015 q 293 773 293 888 q 287 675 293 741 q 282 590 282 608 q 318 466 282 505 q 481 417 364 417 l 481 314 "},"‰":{"x_min":-3,"x_max":1672,"ha":1821,"o":"m 846 0 q 664 76 732 0 q 603 244 603 145 q 662 412 603 344 q 846 489 729 489 q 1027 412 959 489 q 1089 244 1089 343 q 1029 76 1089 144 q 846 0 962 0 m 845 103 q 945 143 910 103 q 981 243 981 184 q 947 340 981 301 q 845 385 910 385 q 745 342 782 385 q 709 243 709 300 q 742 147 709 186 q 845 103 781 103 m 888 986 l 284 -25 l 199 -25 l 803 986 l 888 986 m 241 468 q 58 545 126 468 q -3 715 -3 615 q 56 881 -3 813 q 238 958 124 958 q 421 881 353 958 q 483 712 483 813 q 423 544 483 612 q 241 468 356 468 m 241 855 q 137 811 175 855 q 100 710 100 768 q 136 612 100 653 q 240 572 172 572 q 344 614 306 572 q 382 713 382 656 q 347 810 382 771 q 241 855 308 855 m 1428 0 q 1246 76 1314 0 q 1185 244 1185 145 q 1244 412 1185 344 q 1428 489 1311 489 q 1610 412 1542 489 q 1672 244 1672 343 q 1612 76 1672 144 q 1428 0 1545 0 m 1427 103 q 1528 143 1492 103 q 1564 243 1564 184 q 1530 340 1564 301 q 1427 385 1492 385 q 1327 342 1364 385 q 1291 243 1291 300 q 1324 147 1291 186 q 1427 103 1363 103 "},"a":{"x_min":0,"x_max":698.609375,"ha":794,"o":"m 698 0 q 661 -12 679 -7 q 615 -17 643 -17 q 536 12 564 -17 q 500 96 508 41 q 384 6 456 37 q 236 -25 312 -25 q 65 31 130 -25 q 0 194 0 88 q 118 390 0 334 q 328 435 180 420 q 488 483 476 451 q 495 523 495 504 q 442 619 495 584 q 325 654 389 654 q 209 617 257 654 q 152 513 161 580 l 33 513 q 123 705 33 633 q 332 772 207 772 q 528 712 448 772 q 617 531 617 645 l 617 163 q 624 108 617 126 q 664 90 632 90 l 698 94 l 698 0 m 491 262 l 491 372 q 272 329 350 347 q 128 201 128 294 q 166 113 128 144 q 264 83 205 83 q 414 130 346 83 q 491 262 491 183 "},"—":{"x_min":0,"x_max":941.671875,"ha":1039,"o":"m 941 334 l 0 334 l 0 410 l 941 410 l 941 334 "},"=":{"x_min":8.71875,"x_max":780.953125,"ha":792,"o":"m 780 510 l 8 510 l 8 606 l 780 606 l 780 510 m 780 235 l 8 235 l 8 332 l 780 332 l 780 235 "},"N":{"x_min":0,"x_max":801,"ha":914,"o":"m 801 0 l 651 0 l 131 823 l 131 0 l 0 0 l 0 1013 l 151 1013 l 670 193 l 670 1013 l 801 1013 l 801 0 "},"ρ":{"x_min":0,"x_max":712,"ha":797,"o":"m 712 369 q 620 94 712 207 q 362 -26 521 -26 q 230 2 292 -26 q 119 83 167 30 l 119 -278 l 0 -278 l 0 362 q 91 643 0 531 q 355 764 190 764 q 617 647 517 764 q 712 369 712 536 m 583 366 q 530 559 583 480 q 359 651 469 651 q 190 562 252 651 q 135 370 135 483 q 189 176 135 257 q 359 85 250 85 q 528 175 466 85 q 583 366 583 254 "},"2":{"x_min":59,"x_max":731,"ha":792,"o":"m 731 0 l 59 0 q 197 314 59 188 q 457 487 199 315 q 598 691 598 580 q 543 819 598 772 q 411 867 488 867 q 272 811 328 867 q 209 630 209 747 l 81 630 q 182 901 81 805 q 408 986 271 986 q 629 909 536 986 q 731 694 731 826 q 613 449 731 541 q 378 316 495 383 q 201 122 235 234 l 731 122 l 731 0 "},"¯":{"x_min":0,"x_max":941.671875,"ha":938,"o":"m 941 1033 l 0 1033 l 0 1109 l 941 1109 l 941 1033 "},"Z":{"x_min":0,"x_max":779,"ha":849,"o":"m 779 0 l 0 0 l 0 113 l 621 896 l 40 896 l 40 1013 l 779 1013 l 778 887 l 171 124 l 779 124 l 779 0 "},"u":{"x_min":0,"x_max":617,"ha":729,"o":"m 617 0 l 499 0 l 499 110 q 391 10 460 45 q 246 -25 322 -25 q 61 58 127 -25 q 0 258 0 136 l 0 738 l 125 738 l 125 284 q 156 148 125 202 q 273 82 197 82 q 433 165 369 82 q 493 340 493 243 l 493 738 l 617 738 l 617 0 "},"k":{"x_min":0,"x_max":612.484375,"ha":697,"o":"m 612 738 l 338 465 l 608 0 l 469 0 l 251 382 l 121 251 l 121 0 l 0 0 l 0 1013 l 121 1013 l 121 402 l 456 738 l 612 738 "},"Η":{"x_min":0,"x_max":803,"ha":917,"o":"m 803 0 l 667 0 l 667 475 l 140 475 l 140 0 l 0 0 l 0 1013 l 140 1013 l 140 599 l 667 599 l 667 1013 l 803 1013 l 803 0 "},"Α":{"x_min":0,"x_max":906.953125,"ha":985,"o":"m 906 0 l 756 0 l 650 303 l 251 303 l 143 0 l 0 0 l 376 1013 l 529 1013 l 906 0 m 609 421 l 452 866 l 293 421 l 609 421 "},"s":{"x_min":0,"x_max":604,"ha":697,"o":"m 604 217 q 501 36 604 104 q 292 -23 411 -23 q 86 43 166 -23 q 0 238 0 114 l 121 237 q 175 122 121 164 q 300 85 223 85 q 415 112 363 85 q 479 207 479 147 q 361 309 479 276 q 140 372 141 370 q 21 544 21 426 q 111 708 21 647 q 298 761 190 761 q 492 705 413 761 q 583 531 583 643 l 462 531 q 412 625 462 594 q 298 657 363 657 q 199 636 242 657 q 143 558 143 608 q 262 454 143 486 q 484 394 479 397 q 604 217 604 341 "},"B":{"x_min":0,"x_max":778,"ha":876,"o":"m 580 546 q 724 469 670 535 q 778 311 778 403 q 673 83 778 171 q 432 0 575 0 l 0 0 l 0 1013 l 411 1013 q 629 957 541 1013 q 732 768 732 892 q 691 633 732 693 q 580 546 650 572 m 393 899 l 139 899 l 139 588 l 379 588 q 521 624 462 588 q 592 744 592 667 q 531 859 592 819 q 393 899 471 899 m 419 124 q 566 169 504 124 q 635 303 635 219 q 559 436 635 389 q 402 477 494 477 l 139 477 l 139 124 l 419 124 "},"…":{"x_min":0,"x_max":614,"ha":708,"o":"m 142 0 l 0 0 l 0 151 l 142 151 l 142 0 m 378 0 l 236 0 l 236 151 l 378 151 l 378 0 m 614 0 l 472 0 l 472 151 l 614 151 l 614 0 "},"?":{"x_min":0,"x_max":607,"ha":704,"o":"m 607 777 q 543 599 607 674 q 422 474 482 537 q 357 272 357 391 l 236 272 q 297 487 236 395 q 411 619 298 490 q 474 762 474 691 q 422 885 474 838 q 301 933 371 933 q 179 880 228 933 q 124 706 124 819 l 0 706 q 94 963 0 872 q 302 1044 177 1044 q 511 973 423 1044 q 607 777 607 895 m 370 0 l 230 0 l 230 151 l 370 151 l 370 0 "},"H":{"x_min":0,"x_max":803,"ha":915,"o":"m 803 0 l 667 0 l 667 475 l 140 475 l 140 0 l 0 0 l 0 1013 l 140 1013 l 140 599 l 667 599 l 667 1013 l 803 1013 l 803 0 "},"ν":{"x_min":0,"x_max":675,"ha":761,"o":"m 675 738 l 404 0 l 272 0 l 0 738 l 133 738 l 340 147 l 541 738 l 675 738 "},"c":{"x_min":1,"x_max":701.390625,"ha":775,"o":"m 701 264 q 584 53 681 133 q 353 -26 487 -26 q 91 91 188 -26 q 1 370 1 201 q 92 645 1 537 q 353 761 190 761 q 572 688 479 761 q 690 493 666 615 l 556 493 q 487 606 545 562 q 356 650 428 650 q 186 563 246 650 q 134 372 134 487 q 188 179 134 258 q 359 88 250 88 q 492 136 437 88 q 566 264 548 185 l 701 264 "},"¶":{"x_min":0,"x_max":566.671875,"ha":678,"o":"m 21 892 l 52 892 l 98 761 l 145 892 l 176 892 l 178 741 l 157 741 l 157 867 l 108 741 l 88 741 l 40 871 l 40 741 l 21 741 l 21 892 m 308 854 l 308 731 q 252 691 308 691 q 227 691 240 691 q 207 696 213 695 l 207 712 l 253 706 q 288 733 288 706 l 288 763 q 244 741 279 741 q 193 797 193 741 q 261 860 193 860 q 287 860 273 860 q 308 854 302 855 m 288 842 l 263 843 q 213 796 213 843 q 248 756 213 756 q 288 796 288 756 l 288 842 m 566 988 l 502 988 l 502 -1 l 439 -1 l 439 988 l 317 988 l 317 -1 l 252 -1 l 252 602 q 81 653 155 602 q 0 805 0 711 q 101 989 0 918 q 309 1053 194 1053 l 566 1053 l 566 988 "},"β":{"x_min":0,"x_max":660,"ha":745,"o":"m 471 550 q 610 450 561 522 q 660 280 660 378 q 578 64 660 151 q 367 -22 497 -22 q 239 5 299 -22 q 126 82 178 32 l 126 -278 l 0 -278 l 0 593 q 54 903 0 801 q 318 1042 127 1042 q 519 964 436 1042 q 603 771 603 887 q 567 644 603 701 q 471 550 532 586 m 337 79 q 476 138 418 79 q 535 279 535 198 q 427 437 535 386 q 226 477 344 477 l 226 583 q 398 620 329 583 q 486 762 486 668 q 435 884 486 833 q 312 935 384 935 q 169 861 219 935 q 126 698 126 797 l 126 362 q 170 169 126 242 q 337 79 224 79 "},"Μ":{"x_min":0,"x_max":954,"ha":1068,"o":"m 954 0 l 819 0 l 819 868 l 537 0 l 405 0 l 128 865 l 128 0 l 0 0 l 0 1013 l 199 1013 l 472 158 l 758 1013 l 954 1013 l 954 0 "},"Ό":{"x_min":0.109375,"x_max":1120,"ha":1217,"o":"m 1120 505 q 994 132 1120 282 q 642 -29 861 -29 q 290 130 422 -29 q 167 505 167 280 q 294 883 167 730 q 650 1046 430 1046 q 999 882 868 1046 q 1120 505 1120 730 m 977 504 q 896 784 977 669 q 644 915 804 915 q 391 785 484 915 q 307 504 307 669 q 391 224 307 339 q 644 95 486 95 q 894 224 803 95 q 977 504 977 339 m 277 1040 l 83 799 l 0 799 l 140 1040 l 277 1040 "},"Ή":{"x_min":0,"x_max":1158,"ha":1275,"o":"m 1158 0 l 1022 0 l 1022 475 l 496 475 l 496 0 l 356 0 l 356 1012 l 496 1012 l 496 599 l 1022 599 l 1022 1012 l 1158 1012 l 1158 0 m 277 1040 l 83 799 l 0 799 l 140 1040 l 277 1040 "},"•":{"x_min":0,"x_max":663.890625,"ha":775,"o":"m 663 529 q 566 293 663 391 q 331 196 469 196 q 97 294 194 196 q 0 529 0 393 q 96 763 0 665 q 331 861 193 861 q 566 763 469 861 q 663 529 663 665 "},"¥":{"x_min":0.1875,"x_max":819.546875,"ha":886,"o":"m 563 561 l 697 561 l 696 487 l 520 487 l 482 416 l 482 380 l 697 380 l 695 308 l 482 308 l 482 0 l 342 0 l 342 308 l 125 308 l 125 380 l 342 380 l 342 417 l 303 487 l 125 487 l 125 561 l 258 561 l 0 1013 l 140 1013 l 411 533 l 679 1013 l 819 1013 l 563 561 "},"(":{"x_min":0,"x_max":318.0625,"ha":415,"o":"m 318 -290 l 230 -290 q 61 23 122 -142 q 0 365 0 190 q 62 712 0 540 q 230 1024 119 869 l 318 1024 q 175 705 219 853 q 125 360 125 542 q 176 22 125 187 q 318 -290 223 -127 "},"U":{"x_min":0,"x_max":796,"ha":904,"o":"m 796 393 q 681 93 796 212 q 386 -25 566 -25 q 101 95 208 -25 q 0 393 0 211 l 0 1013 l 138 1013 l 138 391 q 204 191 138 270 q 394 107 276 107 q 586 191 512 107 q 656 391 656 270 l 656 1013 l 796 1013 l 796 393 "},"γ":{"x_min":0.5,"x_max":744.953125,"ha":822,"o":"m 744 737 l 463 54 l 463 -278 l 338 -278 l 338 54 l 154 495 q 104 597 124 569 q 13 651 67 651 l 0 651 l 0 751 l 39 753 q 168 711 121 753 q 242 594 207 676 l 403 208 l 617 737 l 744 737 "},"α":{"x_min":0,"x_max":765.5625,"ha":809,"o":"m 765 -4 q 698 -14 726 -14 q 564 97 586 -14 q 466 7 525 40 q 337 -26 407 -26 q 88 98 186 -26 q 0 369 0 212 q 88 637 0 525 q 337 760 184 760 q 465 728 407 760 q 563 637 524 696 l 563 739 l 685 739 l 685 222 q 693 141 685 168 q 748 94 708 94 q 765 96 760 94 l 765 -4 m 584 371 q 531 562 584 485 q 360 653 470 653 q 192 566 254 653 q 135 379 135 489 q 186 181 135 261 q 358 84 247 84 q 528 176 465 84 q 584 371 584 260 "},"F":{"x_min":0,"x_max":683.328125,"ha":717,"o":"m 683 888 l 140 888 l 140 583 l 613 583 l 613 458 l 140 458 l 140 0 l 0 0 l 0 1013 l 683 1013 l 683 888 "},"­":{"x_min":0,"x_max":705.5625,"ha":803,"o":"m 705 334 l 0 334 l 0 410 l 705 410 l 705 334 "},":":{"x_min":0,"x_max":142,"ha":239,"o":"m 142 585 l 0 585 l 0 738 l 142 738 l 142 585 m 142 0 l 0 0 l 0 151 l 142 151 l 142 0 "},"Χ":{"x_min":0,"x_max":854.171875,"ha":935,"o":"m 854 0 l 683 0 l 423 409 l 166 0 l 0 0 l 347 519 l 18 1013 l 186 1013 l 427 637 l 675 1013 l 836 1013 l 504 521 l 854 0 "},"*":{"x_min":116,"x_max":674,"ha":792,"o":"m 674 768 l 475 713 l 610 544 l 517 477 l 394 652 l 272 478 l 178 544 l 314 713 l 116 766 l 153 876 l 341 812 l 342 1013 l 446 1013 l 446 811 l 635 874 l 674 768 "},"†":{"x_min":0,"x_max":777,"ha":835,"o":"m 458 804 l 777 804 l 777 683 l 458 683 l 458 0 l 319 0 l 319 681 l 0 683 l 0 804 l 319 804 l 319 1015 l 458 1013 l 458 804 "},"°":{"x_min":0,"x_max":347,"ha":444,"o":"m 173 802 q 43 856 91 802 q 0 977 0 905 q 45 1101 0 1049 q 173 1153 90 1153 q 303 1098 255 1153 q 347 977 347 1049 q 303 856 347 905 q 173 802 256 802 m 173 884 q 238 910 214 884 q 262 973 262 937 q 239 1038 262 1012 q 173 1064 217 1064 q 108 1037 132 1064 q 85 973 85 1010 q 108 910 85 937 q 173 884 132 884 "},"V":{"x_min":0,"x_max":862.71875,"ha":940,"o":"m 862 1013 l 505 0 l 361 0 l 0 1013 l 143 1013 l 434 165 l 718 1012 l 862 1013 "},"Ξ":{"x_min":0,"x_max":734.71875,"ha":763,"o":"m 723 889 l 9 889 l 9 1013 l 723 1013 l 723 889 m 673 463 l 61 463 l 61 589 l 673 589 l 673 463 m 734 0 l 0 0 l 0 124 l 734 124 l 734 0 "}," ":{"x_min":0,"x_max":0,"ha":853},"Ϋ":{"x_min":0.328125,"x_max":819.515625,"ha":889,"o":"m 588 1046 l 460 1046 l 460 1189 l 588 1189 l 588 1046 m 360 1046 l 232 1046 l 232 1189 l 360 1189 l 360 1046 m 819 1012 l 482 416 l 482 0 l 342 0 l 342 416 l 0 1012 l 140 1012 l 411 533 l 679 1012 l 819 1012 "},"0":{"x_min":73,"x_max":715,"ha":792,"o":"m 394 -29 q 153 129 242 -29 q 73 479 73 272 q 152 829 73 687 q 394 989 241 989 q 634 829 545 989 q 715 479 715 684 q 635 129 715 270 q 394 -29 546 -29 m 394 89 q 546 211 489 89 q 598 479 598 322 q 548 748 598 640 q 394 871 491 871 q 241 748 298 871 q 190 479 190 637 q 239 211 190 319 q 394 89 296 89 "},"”":{"x_min":0,"x_max":347,"ha":454,"o":"m 139 851 q 102 737 139 784 q 0 669 65 690 l 0 734 q 59 787 42 741 q 72 873 72 821 l 0 873 l 0 1013 l 139 1013 l 139 851 m 347 851 q 310 737 347 784 q 208 669 273 690 l 208 734 q 267 787 250 741 q 280 873 280 821 l 208 873 l 208 1013 l 347 1013 l 347 851 "},"@":{"x_min":0,"x_max":1260,"ha":1357,"o":"m 1098 -45 q 877 -160 1001 -117 q 633 -203 752 -203 q 155 -29 327 -203 q 0 360 0 127 q 176 802 0 616 q 687 1008 372 1008 q 1123 854 969 1008 q 1260 517 1260 718 q 1155 216 1260 341 q 868 82 1044 82 q 772 106 801 82 q 737 202 737 135 q 647 113 700 144 q 527 82 594 82 q 367 147 420 82 q 314 312 314 212 q 401 565 314 452 q 639 690 498 690 q 810 588 760 690 l 849 668 l 938 668 q 877 441 900 532 q 833 226 833 268 q 853 182 833 198 q 902 167 873 167 q 1088 272 1012 167 q 1159 512 1159 372 q 1051 793 1159 681 q 687 925 925 925 q 248 747 415 925 q 97 361 97 586 q 226 26 97 159 q 627 -122 370 -122 q 856 -87 737 -122 q 1061 8 976 -53 l 1098 -45 m 786 488 q 738 580 777 545 q 643 615 700 615 q 483 517 548 615 q 425 322 425 430 q 457 203 425 250 q 552 156 490 156 q 722 273 665 156 q 786 488 738 309 "},"Ί":{"x_min":0,"x_max":499,"ha":613,"o":"m 277 1040 l 83 799 l 0 799 l 140 1040 l 277 1040 m 499 0 l 360 0 l 360 1012 l 499 1012 l 499 0 "},"i":{"x_min":14,"x_max":136,"ha":275,"o":"m 136 873 l 14 873 l 14 1013 l 136 1013 l 136 873 m 136 0 l 14 0 l 14 737 l 136 737 l 136 0 "},"Β":{"x_min":0,"x_max":778,"ha":877,"o":"m 580 545 q 724 468 671 534 q 778 310 778 402 q 673 83 778 170 q 432 0 575 0 l 0 0 l 0 1013 l 411 1013 q 629 957 541 1013 q 732 768 732 891 q 691 632 732 692 q 580 545 650 571 m 393 899 l 139 899 l 139 587 l 379 587 q 521 623 462 587 q 592 744 592 666 q 531 859 592 819 q 393 899 471 899 m 419 124 q 566 169 504 124 q 635 302 635 219 q 559 435 635 388 q 402 476 494 476 l 139 476 l 139 124 l 419 124 "},"υ":{"x_min":0,"x_max":617,"ha":725,"o":"m 617 352 q 540 94 617 199 q 308 -24 455 -24 q 76 94 161 -24 q 0 352 0 199 l 0 739 l 126 739 l 126 355 q 169 185 126 257 q 312 98 220 98 q 451 185 402 98 q 492 355 492 257 l 492 739 l 617 739 l 617 352 "},"]":{"x_min":0,"x_max":275,"ha":372,"o":"m 275 -281 l 0 -281 l 0 -187 l 151 -187 l 151 920 l 0 920 l 0 1013 l 275 1013 l 275 -281 "},"m":{"x_min":0,"x_max":1019,"ha":1128,"o":"m 1019 0 l 897 0 l 897 454 q 860 591 897 536 q 739 660 816 660 q 613 586 659 660 q 573 436 573 522 l 573 0 l 447 0 l 447 455 q 412 591 447 535 q 294 657 372 657 q 165 586 213 657 q 122 437 122 521 l 122 0 l 0 0 l 0 738 l 117 738 l 117 640 q 202 730 150 697 q 316 763 254 763 q 437 730 381 763 q 525 642 494 697 q 621 731 559 700 q 753 763 682 763 q 943 694 867 763 q 1019 512 1019 625 l 1019 0 "},"χ":{"x_min":8.328125,"x_max":780.5625,"ha":815,"o":"m 780 -278 q 715 -294 747 -294 q 616 -257 663 -294 q 548 -175 576 -227 l 379 133 l 143 -277 l 9 -277 l 313 254 l 163 522 q 127 586 131 580 q 36 640 91 640 q 8 637 27 640 l 8 752 l 52 757 q 162 719 113 757 q 236 627 200 690 l 383 372 l 594 737 l 726 737 l 448 250 l 625 -69 q 670 -153 647 -110 q 743 -188 695 -188 q 780 -184 759 -188 l 780 -278 "},"8":{"x_min":55,"x_max":736,"ha":792,"o":"m 571 527 q 694 424 652 491 q 736 280 736 358 q 648 71 736 158 q 395 -26 551 -26 q 142 69 238 -26 q 55 279 55 157 q 96 425 55 359 q 220 527 138 491 q 120 615 153 562 q 88 726 88 668 q 171 904 88 827 q 395 986 261 986 q 618 905 529 986 q 702 727 702 830 q 670 616 702 667 q 571 527 638 565 m 394 565 q 519 610 475 565 q 563 717 563 655 q 521 823 563 781 q 392 872 474 872 q 265 824 312 872 q 224 720 224 783 q 265 613 224 656 q 394 565 312 565 m 395 91 q 545 150 488 91 q 597 280 597 204 q 546 408 597 355 q 395 465 492 465 q 244 408 299 465 q 194 280 194 356 q 244 150 194 203 q 395 91 299 91 "},"ί":{"x_min":42,"x_max":326.71875,"ha":361,"o":"m 284 3 q 233 -10 258 -5 q 182 -15 207 -15 q 85 26 119 -15 q 42 200 42 79 l 42 737 l 167 737 l 168 215 q 172 141 168 157 q 226 101 183 101 q 248 102 239 101 q 284 112 257 104 l 284 3 m 326 1040 l 137 819 l 54 819 l 189 1040 l 326 1040 "},"Ζ":{"x_min":0,"x_max":779.171875,"ha":850,"o":"m 779 0 l 0 0 l 0 113 l 620 896 l 40 896 l 40 1013 l 779 1013 l 779 887 l 170 124 l 779 124 l 779 0 "},"R":{"x_min":0,"x_max":781.953125,"ha":907,"o":"m 781 0 l 623 0 q 587 242 590 52 q 407 433 585 433 l 138 433 l 138 0 l 0 0 l 0 1013 l 396 1013 q 636 946 539 1013 q 749 731 749 868 q 711 597 749 659 q 608 502 674 534 q 718 370 696 474 q 729 207 722 352 q 781 26 736 62 l 781 0 m 373 551 q 533 594 465 551 q 614 731 614 645 q 532 859 614 815 q 373 896 465 896 l 138 896 l 138 551 l 373 551 "},"o":{"x_min":0,"x_max":713,"ha":821,"o":"m 357 -25 q 94 91 194 -25 q 0 368 0 202 q 93 642 0 533 q 357 761 193 761 q 618 644 518 761 q 713 368 713 533 q 619 91 713 201 q 357 -25 521 -25 m 357 85 q 528 175 465 85 q 584 369 584 255 q 529 562 584 484 q 357 651 467 651 q 189 560 250 651 q 135 369 135 481 q 187 177 135 257 q 357 85 250 85 "},"5":{"x_min":54.171875,"x_max":738,"ha":792,"o":"m 738 314 q 626 60 738 153 q 382 -23 526 -23 q 155 47 248 -23 q 54 256 54 125 l 183 256 q 259 132 204 174 q 382 91 314 91 q 533 149 471 91 q 602 314 602 213 q 538 469 602 411 q 386 528 475 528 q 284 506 332 528 q 197 439 237 484 l 81 439 l 159 958 l 684 958 l 684 840 l 254 840 l 214 579 q 306 627 258 612 q 407 643 354 643 q 636 552 540 643 q 738 314 738 457 "},"7":{"x_min":58.71875,"x_max":730.953125,"ha":792,"o":"m 730 839 q 469 448 560 641 q 335 0 378 255 l 192 0 q 328 441 235 252 q 593 830 421 630 l 58 830 l 58 958 l 730 958 l 730 839 "},"K":{"x_min":0,"x_max":819.46875,"ha":906,"o":"m 819 0 l 649 0 l 294 509 l 139 355 l 139 0 l 0 0 l 0 1013 l 139 1013 l 139 526 l 626 1013 l 809 1013 l 395 600 l 819 0 "},",":{"x_min":0,"x_max":142,"ha":239,"o":"m 142 -12 q 105 -132 142 -82 q 0 -205 68 -182 l 0 -138 q 57 -82 40 -124 q 70 0 70 -51 l 0 0 l 0 151 l 142 151 l 142 -12 "},"d":{"x_min":0,"x_max":683,"ha":796,"o":"m 683 0 l 564 0 l 564 93 q 456 6 516 38 q 327 -25 395 -25 q 87 100 181 -25 q 0 365 0 215 q 90 639 0 525 q 343 763 187 763 q 564 647 486 763 l 564 1013 l 683 1013 l 683 0 m 582 373 q 529 562 582 484 q 361 653 468 653 q 190 561 253 653 q 135 365 135 479 q 189 175 135 254 q 358 85 251 85 q 529 178 468 85 q 582 373 582 258 "},"¨":{"x_min":-109,"x_max":247,"ha":232,"o":"m 247 1046 l 119 1046 l 119 1189 l 247 1189 l 247 1046 m 19 1046 l -109 1046 l -109 1189 l 19 1189 l 19 1046 "},"E":{"x_min":0,"x_max":736.109375,"ha":789,"o":"m 736 0 l 0 0 l 0 1013 l 725 1013 l 725 889 l 139 889 l 139 585 l 677 585 l 677 467 l 139 467 l 139 125 l 736 125 l 736 0 "},"Y":{"x_min":0,"x_max":820,"ha":886,"o":"m 820 1013 l 482 416 l 482 0 l 342 0 l 342 416 l 0 1013 l 140 1013 l 411 534 l 679 1012 l 820 1013 "},"\"":{"x_min":0,"x_max":299,"ha":396,"o":"m 299 606 l 203 606 l 203 988 l 299 988 l 299 606 m 96 606 l 0 606 l 0 988 l 96 988 l 96 606 "},"‹":{"x_min":17.984375,"x_max":773.609375,"ha":792,"o":"m 773 40 l 18 376 l 17 465 l 773 799 l 773 692 l 159 420 l 773 149 l 773 40 "},"„":{"x_min":0,"x_max":364,"ha":467,"o":"m 141 -12 q 104 -132 141 -82 q 0 -205 67 -182 l 0 -138 q 56 -82 40 -124 q 69 0 69 -51 l 0 0 l 0 151 l 141 151 l 141 -12 m 364 -12 q 327 -132 364 -82 q 222 -205 290 -182 l 222 -138 q 279 -82 262 -124 q 292 0 292 -51 l 222 0 l 222 151 l 364 151 l 364 -12 "},"δ":{"x_min":1,"x_max":710,"ha":810,"o":"m 710 360 q 616 87 710 196 q 356 -28 518 -28 q 99 82 197 -28 q 1 356 1 192 q 100 606 1 509 q 355 703 199 703 q 180 829 288 754 q 70 903 124 866 l 70 1012 l 643 1012 l 643 901 l 258 901 q 462 763 422 794 q 636 592 577 677 q 710 360 710 485 m 584 365 q 552 501 584 447 q 451 602 521 555 q 372 611 411 611 q 197 541 258 611 q 136 355 136 472 q 190 171 136 245 q 358 85 252 85 q 528 173 465 85 q 584 365 584 252 "},"έ":{"x_min":0,"x_max":634.71875,"ha":714,"o":"m 634 234 q 527 38 634 110 q 300 -25 433 -25 q 98 29 183 -25 q 0 204 0 93 q 37 313 0 265 q 128 390 67 352 q 56 459 82 419 q 26 555 26 505 q 114 712 26 654 q 295 763 191 763 q 499 700 416 763 q 589 515 589 631 l 478 515 q 419 618 464 580 q 307 657 374 657 q 207 630 253 657 q 151 547 151 598 q 238 445 151 469 q 389 434 280 434 l 389 331 l 349 331 q 206 315 255 331 q 125 210 125 287 q 183 107 125 145 q 302 76 233 76 q 436 117 379 76 q 509 234 493 159 l 634 234 m 520 1040 l 331 819 l 248 819 l 383 1040 l 520 1040 "},"ω":{"x_min":0,"x_max":922,"ha":1031,"o":"m 922 339 q 856 97 922 203 q 650 -26 780 -26 q 538 9 587 -26 q 461 103 489 44 q 387 12 436 46 q 277 -22 339 -22 q 69 97 147 -22 q 0 339 0 203 q 45 551 0 444 q 161 738 84 643 l 302 738 q 175 553 219 647 q 124 336 124 446 q 155 179 124 249 q 275 88 197 88 q 375 163 341 88 q 400 294 400 219 l 400 572 l 524 572 l 524 294 q 561 135 524 192 q 643 88 591 88 q 762 182 719 88 q 797 342 797 257 q 745 556 797 450 q 619 738 705 638 l 760 738 q 874 551 835 640 q 922 339 922 444 "},"´":{"x_min":0,"x_max":96,"ha":251,"o":"m 96 606 l 0 606 l 0 988 l 96 988 l 96 606 "},"±":{"x_min":11,"x_max":781,"ha":792,"o":"m 781 490 l 446 490 l 446 255 l 349 255 l 349 490 l 11 490 l 11 586 l 349 586 l 349 819 l 446 819 l 446 586 l 781 586 l 781 490 m 781 21 l 11 21 l 11 115 l 781 115 l 781 21 "},"|":{"x_min":343,"x_max":449,"ha":792,"o":"m 449 462 l 343 462 l 343 986 l 449 986 l 449 462 m 449 -242 l 343 -242 l 343 280 l 449 280 l 449 -242 "},"ϋ":{"x_min":0,"x_max":617,"ha":725,"o":"m 482 800 l 372 800 l 372 925 l 482 925 l 482 800 m 239 800 l 129 800 l 129 925 l 239 925 l 239 800 m 617 352 q 540 93 617 199 q 308 -24 455 -24 q 76 93 161 -24 q 0 352 0 199 l 0 738 l 126 738 l 126 354 q 169 185 126 257 q 312 98 220 98 q 451 185 402 98 q 492 354 492 257 l 492 738 l 617 738 l 617 352 "},"§":{"x_min":0,"x_max":593,"ha":690,"o":"m 593 425 q 554 312 593 369 q 467 233 516 254 q 537 83 537 172 q 459 -74 537 -12 q 288 -133 387 -133 q 115 -69 184 -133 q 47 96 47 -6 l 166 96 q 199 7 166 40 q 288 -26 232 -26 q 371 -5 332 -26 q 420 60 420 21 q 311 201 420 139 q 108 309 210 255 q 0 490 0 383 q 33 602 0 551 q 124 687 66 654 q 75 743 93 712 q 58 812 58 773 q 133 984 58 920 q 300 1043 201 1043 q 458 987 394 1043 q 529 814 529 925 l 411 814 q 370 908 404 877 q 289 939 336 939 q 213 911 246 939 q 180 841 180 883 q 286 720 180 779 q 484 612 480 615 q 593 425 593 534 m 467 409 q 355 544 467 473 q 196 630 228 612 q 146 587 162 609 q 124 525 124 558 q 239 387 124 462 q 398 298 369 315 q 448 345 429 316 q 467 409 467 375 "},"b":{"x_min":0,"x_max":685,"ha":783,"o":"m 685 372 q 597 99 685 213 q 347 -25 501 -25 q 219 5 277 -25 q 121 93 161 36 l 121 0 l 0 0 l 0 1013 l 121 1013 l 121 634 q 214 723 157 692 q 341 754 272 754 q 591 637 493 754 q 685 372 685 526 m 554 356 q 499 550 554 470 q 328 644 437 644 q 162 556 223 644 q 108 369 108 478 q 160 176 108 256 q 330 83 221 83 q 498 169 435 83 q 554 356 554 245 "},"q":{"x_min":0,"x_max":683,"ha":876,"o":"m 683 -278 l 564 -278 l 564 97 q 474 8 533 39 q 345 -23 415 -23 q 91 93 188 -23 q 0 364 0 203 q 87 635 0 522 q 337 760 184 760 q 466 727 408 760 q 564 637 523 695 l 564 737 l 683 737 l 683 -278 m 582 375 q 527 564 582 488 q 358 652 466 652 q 190 565 253 652 q 135 377 135 488 q 189 179 135 261 q 361 84 251 84 q 530 179 469 84 q 582 375 582 260 "},"Ω":{"x_min":-0.171875,"x_max":969.5625,"ha":1068,"o":"m 969 0 l 555 0 l 555 123 q 744 308 675 194 q 814 558 814 423 q 726 812 814 709 q 484 922 633 922 q 244 820 334 922 q 154 567 154 719 q 223 316 154 433 q 412 123 292 199 l 412 0 l 0 0 l 0 124 l 217 124 q 68 327 122 210 q 15 572 15 444 q 144 911 15 781 q 484 1041 274 1041 q 822 909 691 1041 q 953 569 953 777 q 899 326 953 443 q 750 124 846 210 l 969 124 l 969 0 "},"ύ":{"x_min":0,"x_max":617,"ha":725,"o":"m 617 352 q 540 93 617 199 q 308 -24 455 -24 q 76 93 161 -24 q 0 352 0 199 l 0 738 l 126 738 l 126 354 q 169 185 126 257 q 312 98 220 98 q 451 185 402 98 q 492 354 492 257 l 492 738 l 617 738 l 617 352 m 535 1040 l 346 819 l 262 819 l 397 1040 l 535 1040 "},"z":{"x_min":-0.015625,"x_max":613.890625,"ha":697,"o":"m 613 0 l 0 0 l 0 100 l 433 630 l 20 630 l 20 738 l 594 738 l 593 636 l 163 110 l 613 110 l 613 0 "},"™":{"x_min":0,"x_max":894,"ha":1000,"o":"m 389 951 l 229 951 l 229 503 l 160 503 l 160 951 l 0 951 l 0 1011 l 389 1011 l 389 951 m 894 503 l 827 503 l 827 939 l 685 503 l 620 503 l 481 937 l 481 503 l 417 503 l 417 1011 l 517 1011 l 653 580 l 796 1010 l 894 1011 l 894 503 "},"ή":{"x_min":0.78125,"x_max":697,"ha":810,"o":"m 697 -278 l 572 -278 l 572 454 q 540 587 572 536 q 425 650 501 650 q 271 579 337 650 q 206 420 206 509 l 206 0 l 81 0 l 81 489 q 73 588 81 562 q 0 644 56 644 l 0 741 q 68 755 38 755 q 158 721 124 755 q 200 630 193 687 q 297 726 234 692 q 434 761 359 761 q 620 692 544 761 q 697 516 697 624 l 697 -278 m 479 1040 l 290 819 l 207 819 l 341 1040 l 479 1040 "},"Θ":{"x_min":0,"x_max":960,"ha":1056,"o":"m 960 507 q 833 129 960 280 q 476 -32 698 -32 q 123 129 255 -32 q 0 507 0 280 q 123 883 0 732 q 476 1045 255 1045 q 832 883 696 1045 q 960 507 960 732 m 817 500 q 733 789 817 669 q 476 924 639 924 q 223 792 317 924 q 142 507 142 675 q 222 222 142 339 q 476 89 315 89 q 730 218 636 89 q 817 500 817 334 m 716 449 l 243 449 l 243 571 l 716 571 l 716 449 "},"®":{"x_min":-3,"x_max":1008,"ha":1106,"o":"m 503 532 q 614 562 566 532 q 672 658 672 598 q 614 747 672 716 q 503 772 569 772 l 338 772 l 338 532 l 503 532 m 502 -7 q 123 151 263 -7 q -3 501 -3 294 q 123 851 -3 706 q 502 1011 263 1011 q 881 851 739 1011 q 1008 501 1008 708 q 883 151 1008 292 q 502 -7 744 -7 m 502 60 q 830 197 709 60 q 940 501 940 322 q 831 805 940 681 q 502 944 709 944 q 174 805 296 944 q 65 501 65 680 q 173 197 65 320 q 502 60 294 60 m 788 146 l 678 146 q 653 316 655 183 q 527 449 652 449 l 338 449 l 338 146 l 241 146 l 241 854 l 518 854 q 688 808 621 854 q 766 658 766 755 q 739 563 766 607 q 668 497 713 519 q 751 331 747 472 q 788 164 756 190 l 788 146 "},"~":{"x_min":0,"x_max":833,"ha":931,"o":"m 833 958 q 778 753 833 831 q 594 665 716 665 q 402 761 502 665 q 240 857 302 857 q 131 795 166 857 q 104 665 104 745 l 0 665 q 54 867 0 789 q 237 958 116 958 q 429 861 331 958 q 594 765 527 765 q 704 827 670 765 q 729 958 729 874 l 833 958 "},"Ε":{"x_min":0,"x_max":736.21875,"ha":778,"o":"m 736 0 l 0 0 l 0 1013 l 725 1013 l 725 889 l 139 889 l 139 585 l 677 585 l 677 467 l 139 467 l 139 125 l 736 125 l 736 0 "},"³":{"x_min":0,"x_max":450,"ha":547,"o":"m 450 552 q 379 413 450 464 q 220 366 313 366 q 69 414 130 366 q 0 567 0 470 l 85 567 q 126 470 85 504 q 225 437 168 437 q 320 467 280 437 q 360 552 360 498 q 318 632 360 608 q 213 657 276 657 q 195 657 203 657 q 176 657 181 657 l 176 722 q 279 733 249 722 q 334 815 334 752 q 300 881 334 856 q 220 907 267 907 q 133 875 169 907 q 97 781 97 844 l 15 781 q 78 926 15 875 q 220 972 135 972 q 364 930 303 972 q 426 817 426 888 q 344 697 426 733 q 421 642 392 681 q 450 552 450 603 "},"[":{"x_min":0,"x_max":273.609375,"ha":371,"o":"m 273 -281 l 0 -281 l 0 1013 l 273 1013 l 273 920 l 124 920 l 124 -187 l 273 -187 l 273 -281 "},"L":{"x_min":0,"x_max":645.828125,"ha":696,"o":"m 645 0 l 0 0 l 0 1013 l 140 1013 l 140 126 l 645 126 l 645 0 "},"σ":{"x_min":0,"x_max":803.390625,"ha":894,"o":"m 803 628 l 633 628 q 713 368 713 512 q 618 93 713 204 q 357 -25 518 -25 q 94 91 194 -25 q 0 368 0 201 q 94 644 0 533 q 356 761 194 761 q 481 750 398 761 q 608 739 564 739 l 803 739 l 803 628 m 360 85 q 529 180 467 85 q 584 374 584 262 q 527 566 584 490 q 352 651 463 651 q 187 559 247 651 q 135 368 135 478 q 189 175 135 254 q 360 85 251 85 "},"ζ":{"x_min":0,"x_max":573,"ha":642,"o":"m 573 -40 q 553 -162 573 -97 q 510 -278 543 -193 l 400 -278 q 441 -187 428 -219 q 462 -90 462 -132 q 378 -14 462 -14 q 108 45 197 -14 q 0 290 0 117 q 108 631 0 462 q 353 901 194 767 l 55 901 l 55 1012 l 561 1012 l 561 924 q 261 669 382 831 q 128 301 128 489 q 243 117 128 149 q 458 98 350 108 q 573 -40 573 80 "},"θ":{"x_min":0,"x_max":674,"ha":778,"o":"m 674 496 q 601 160 674 304 q 336 -26 508 -26 q 73 153 165 -26 q 0 485 0 296 q 72 840 0 683 q 343 1045 166 1045 q 605 844 516 1045 q 674 496 674 692 m 546 579 q 498 798 546 691 q 336 935 437 935 q 178 798 237 935 q 126 579 137 701 l 546 579 m 546 475 l 126 475 q 170 233 126 348 q 338 80 230 80 q 504 233 447 80 q 546 475 546 346 "},"Ο":{"x_min":0,"x_max":958,"ha":1054,"o":"m 485 1042 q 834 883 703 1042 q 958 511 958 735 q 834 136 958 287 q 481 -26 701 -26 q 126 130 261 -26 q 0 504 0 279 q 127 880 0 729 q 485 1042 263 1042 m 480 98 q 731 225 638 98 q 815 504 815 340 q 733 783 815 670 q 480 913 640 913 q 226 785 321 913 q 142 504 142 671 q 226 224 142 339 q 480 98 319 98 "},"Γ":{"x_min":0,"x_max":705.28125,"ha":749,"o":"m 705 886 l 140 886 l 140 0 l 0 0 l 0 1012 l 705 1012 l 705 886 "}," ":{"x_min":0,"x_max":0,"ha":375},"%":{"x_min":-3,"x_max":1089,"ha":1186,"o":"m 845 0 q 663 76 731 0 q 602 244 602 145 q 661 412 602 344 q 845 489 728 489 q 1027 412 959 489 q 1089 244 1089 343 q 1029 76 1089 144 q 845 0 962 0 m 844 103 q 945 143 909 103 q 981 243 981 184 q 947 340 981 301 q 844 385 909 385 q 744 342 781 385 q 708 243 708 300 q 741 147 708 186 q 844 103 780 103 m 888 986 l 284 -25 l 199 -25 l 803 986 l 888 986 m 241 468 q 58 545 126 468 q -3 715 -3 615 q 56 881 -3 813 q 238 958 124 958 q 421 881 353 958 q 483 712 483 813 q 423 544 483 612 q 241 468 356 468 m 241 855 q 137 811 175 855 q 100 710 100 768 q 136 612 100 653 q 240 572 172 572 q 344 614 306 572 q 382 713 382 656 q 347 810 382 771 q 241 855 308 855 "},"P":{"x_min":0,"x_max":726,"ha":806,"o":"m 424 1013 q 640 931 555 1013 q 726 719 726 850 q 637 506 726 587 q 413 426 548 426 l 140 426 l 140 0 l 0 0 l 0 1013 l 424 1013 m 379 889 l 140 889 l 140 548 l 372 548 q 522 589 459 548 q 593 720 593 637 q 528 845 593 801 q 379 889 463 889 "},"Έ":{"x_min":0,"x_max":1078.21875,"ha":1118,"o":"m 1078 0 l 342 0 l 342 1013 l 1067 1013 l 1067 889 l 481 889 l 481 585 l 1019 585 l 1019 467 l 481 467 l 481 125 l 1078 125 l 1078 0 m 277 1040 l 83 799 l 0 799 l 140 1040 l 277 1040 "},"Ώ":{"x_min":0.125,"x_max":1136.546875,"ha":1235,"o":"m 1136 0 l 722 0 l 722 123 q 911 309 842 194 q 981 558 981 423 q 893 813 981 710 q 651 923 800 923 q 411 821 501 923 q 321 568 321 720 q 390 316 321 433 q 579 123 459 200 l 579 0 l 166 0 l 166 124 l 384 124 q 235 327 289 210 q 182 572 182 444 q 311 912 182 782 q 651 1042 441 1042 q 989 910 858 1042 q 1120 569 1120 778 q 1066 326 1120 443 q 917 124 1013 210 l 1136 124 l 1136 0 m 277 1040 l 83 800 l 0 800 l 140 1041 l 277 1040 "},"_":{"x_min":0,"x_max":705.5625,"ha":803,"o":"m 705 -334 l 0 -334 l 0 -234 l 705 -234 l 705 -334 "},"Ϊ":{"x_min":-110,"x_max":246,"ha":275,"o":"m 246 1046 l 118 1046 l 118 1189 l 246 1189 l 246 1046 m 18 1046 l -110 1046 l -110 1189 l 18 1189 l 18 1046 m 136 0 l 0 0 l 0 1012 l 136 1012 l 136 0 "},"+":{"x_min":23,"x_max":768,"ha":792,"o":"m 768 372 l 444 372 l 444 0 l 347 0 l 347 372 l 23 372 l 23 468 l 347 468 l 347 840 l 444 840 l 444 468 l 768 468 l 768 372 "},"½":{"x_min":0,"x_max":1050,"ha":1149,"o":"m 1050 0 l 625 0 q 712 178 625 108 q 878 277 722 187 q 967 385 967 328 q 932 456 967 429 q 850 484 897 484 q 759 450 798 484 q 721 352 721 416 l 640 352 q 706 502 640 448 q 851 551 766 551 q 987 509 931 551 q 1050 385 1050 462 q 976 251 1050 301 q 829 179 902 215 q 717 68 740 133 l 1050 68 l 1050 0 m 834 985 l 215 -28 l 130 -28 l 750 984 l 834 985 m 224 422 l 142 422 l 142 811 l 0 811 l 0 867 q 104 889 62 867 q 164 973 157 916 l 224 973 l 224 422 "},"Ρ":{"x_min":0,"x_max":720,"ha":783,"o":"m 424 1013 q 637 933 554 1013 q 720 723 720 853 q 633 508 720 591 q 413 426 546 426 l 140 426 l 140 0 l 0 0 l 0 1013 l 424 1013 m 378 889 l 140 889 l 140 548 l 371 548 q 521 589 458 548 q 592 720 592 637 q 527 845 592 801 q 378 889 463 889 "},"'":{"x_min":0,"x_max":139,"ha":236,"o":"m 139 851 q 102 737 139 784 q 0 669 65 690 l 0 734 q 59 787 42 741 q 72 873 72 821 l 0 873 l 0 1013 l 139 1013 l 139 851 "},"ª":{"x_min":0,"x_max":350,"ha":397,"o":"m 350 625 q 307 616 328 616 q 266 631 281 616 q 247 673 251 645 q 190 628 225 644 q 116 613 156 613 q 32 641 64 613 q 0 722 0 669 q 72 826 0 800 q 247 866 159 846 l 247 887 q 220 934 247 916 q 162 953 194 953 q 104 934 129 953 q 76 882 80 915 l 16 882 q 60 976 16 941 q 166 1011 104 1011 q 266 979 224 1011 q 308 891 308 948 l 308 706 q 311 679 308 688 q 331 670 315 670 l 350 672 l 350 625 m 247 757 l 247 811 q 136 790 175 798 q 64 726 64 773 q 83 682 64 697 q 132 667 103 667 q 207 690 174 667 q 247 757 247 718 "},"΅":{"x_min":0,"x_max":450,"ha":553,"o":"m 450 800 l 340 800 l 340 925 l 450 925 l 450 800 m 406 1040 l 212 800 l 129 800 l 269 1040 l 406 1040 m 110 800 l 0 800 l 0 925 l 110 925 l 110 800 "},"T":{"x_min":0,"x_max":777,"ha":835,"o":"m 777 894 l 458 894 l 458 0 l 319 0 l 319 894 l 0 894 l 0 1013 l 777 1013 l 777 894 "},"Φ":{"x_min":0,"x_max":915,"ha":997,"o":"m 527 0 l 389 0 l 389 122 q 110 231 220 122 q 0 509 0 340 q 110 785 0 677 q 389 893 220 893 l 389 1013 l 527 1013 l 527 893 q 804 786 693 893 q 915 509 915 679 q 805 231 915 341 q 527 122 696 122 l 527 0 m 527 226 q 712 310 641 226 q 779 507 779 389 q 712 705 779 627 q 527 787 641 787 l 527 226 m 389 226 l 389 787 q 205 698 275 775 q 136 505 136 620 q 206 308 136 391 q 389 226 276 226 "},"⁋":{"x_min":0,"x_max":0,"ha":694},"j":{"x_min":-77.78125,"x_max":167,"ha":349,"o":"m 167 871 l 42 871 l 42 1013 l 167 1013 l 167 871 m 167 -80 q 121 -231 167 -184 q -26 -278 76 -278 l -77 -278 l -77 -164 l -41 -164 q 26 -143 11 -164 q 42 -65 42 -122 l 42 737 l 167 737 l 167 -80 "},"Σ":{"x_min":0,"x_max":756.953125,"ha":819,"o":"m 756 0 l 0 0 l 0 107 l 395 523 l 22 904 l 22 1013 l 745 1013 l 745 889 l 209 889 l 566 523 l 187 125 l 756 125 l 756 0 "},"1":{"x_min":215.671875,"x_max":574,"ha":792,"o":"m 574 0 l 442 0 l 442 697 l 215 697 l 215 796 q 386 833 330 796 q 475 986 447 875 l 574 986 l 574 0 "},"›":{"x_min":18.0625,"x_max":774,"ha":792,"o":"m 774 376 l 18 40 l 18 149 l 631 421 l 18 692 l 18 799 l 774 465 l 774 376 "},"<":{"x_min":17.984375,"x_max":773.609375,"ha":792,"o":"m 773 40 l 18 376 l 17 465 l 773 799 l 773 692 l 159 420 l 773 149 l 773 40 "},"£":{"x_min":0,"x_max":704.484375,"ha":801,"o":"m 704 41 q 623 -10 664 5 q 543 -26 583 -26 q 359 15 501 -26 q 243 36 288 36 q 158 23 197 36 q 73 -21 119 10 l 6 76 q 125 195 90 150 q 175 331 175 262 q 147 443 175 383 l 0 443 l 0 512 l 108 512 q 43 734 43 623 q 120 929 43 854 q 358 1010 204 1010 q 579 936 487 1010 q 678 729 678 857 l 678 684 l 552 684 q 504 838 552 780 q 362 896 457 896 q 216 852 263 896 q 176 747 176 815 q 199 627 176 697 q 248 512 217 574 l 468 512 l 468 443 l 279 443 q 297 356 297 398 q 230 194 297 279 q 153 107 211 170 q 227 133 190 125 q 293 142 264 142 q 410 119 339 142 q 516 96 482 96 q 579 105 550 96 q 648 142 608 115 l 704 41 "},"t":{"x_min":0,"x_max":367,"ha":458,"o":"m 367 0 q 312 -5 339 -2 q 262 -8 284 -8 q 145 28 183 -8 q 108 143 108 64 l 108 638 l 0 638 l 0 738 l 108 738 l 108 944 l 232 944 l 232 738 l 367 738 l 367 638 l 232 638 l 232 185 q 248 121 232 140 q 307 102 264 102 q 345 104 330 102 q 367 107 360 107 l 367 0 "},"¬":{"x_min":0,"x_max":706,"ha":803,"o":"m 706 411 l 706 158 l 630 158 l 630 335 l 0 335 l 0 411 l 706 411 "},"λ":{"x_min":0,"x_max":750,"ha":803,"o":"m 750 -7 q 679 -15 716 -15 q 538 59 591 -15 q 466 214 512 97 l 336 551 l 126 0 l 0 0 l 270 705 q 223 837 247 770 q 116 899 190 899 q 90 898 100 899 l 90 1004 q 152 1011 125 1011 q 298 938 244 1011 q 373 783 326 901 l 605 192 q 649 115 629 136 q 716 95 669 95 l 736 95 q 750 97 745 97 l 750 -7 "},"W":{"x_min":0,"x_max":1263.890625,"ha":1351,"o":"m 1263 1013 l 995 0 l 859 0 l 627 837 l 405 0 l 265 0 l 0 1013 l 136 1013 l 342 202 l 556 1013 l 701 1013 l 921 207 l 1133 1012 l 1263 1013 "},">":{"x_min":18.0625,"x_max":774,"ha":792,"o":"m 774 376 l 18 40 l 18 149 l 631 421 l 18 692 l 18 799 l 774 465 l 774 376 "},"v":{"x_min":0,"x_max":675.15625,"ha":761,"o":"m 675 738 l 404 0 l 272 0 l 0 738 l 133 737 l 340 147 l 541 737 l 675 738 "},"τ":{"x_min":0.28125,"x_max":644.5,"ha":703,"o":"m 644 628 l 382 628 l 382 179 q 388 120 382 137 q 436 91 401 91 q 474 94 447 91 q 504 97 501 97 l 504 0 q 454 -9 482 -5 q 401 -14 426 -14 q 278 67 308 -14 q 260 233 260 118 l 260 628 l 0 628 l 0 739 l 644 739 l 644 628 "},"ξ":{"x_min":0,"x_max":624.9375,"ha":699,"o":"m 624 -37 q 608 -153 624 -96 q 563 -278 593 -211 l 454 -278 q 491 -183 486 -200 q 511 -83 511 -126 q 484 -23 511 -44 q 370 1 452 1 q 323 0 354 1 q 283 -1 293 -1 q 84 76 169 -1 q 0 266 0 154 q 56 431 0 358 q 197 538 108 498 q 94 613 134 562 q 54 730 54 665 q 77 823 54 780 q 143 901 101 867 l 27 901 l 27 1012 l 576 1012 l 576 901 l 380 901 q 244 863 303 901 q 178 745 178 820 q 312 600 178 636 q 532 582 380 582 l 532 479 q 276 455 361 479 q 118 281 118 410 q 165 173 118 217 q 274 120 208 133 q 494 101 384 110 q 624 -37 624 76 "},"&":{"x_min":-3,"x_max":894.25,"ha":992,"o":"m 894 0 l 725 0 l 624 123 q 471 0 553 40 q 306 -41 390 -41 q 168 -7 231 -41 q 62 92 105 26 q 14 187 31 139 q -3 276 -3 235 q 55 433 -3 358 q 248 581 114 508 q 170 689 196 640 q 137 817 137 751 q 214 985 137 922 q 384 1041 284 1041 q 548 988 483 1041 q 622 824 622 928 q 563 666 622 739 q 431 556 516 608 l 621 326 q 649 407 639 361 q 663 493 653 426 l 781 493 q 703 229 781 352 l 894 0 m 504 818 q 468 908 504 877 q 384 940 433 940 q 293 907 331 940 q 255 818 255 875 q 289 714 255 767 q 363 628 313 678 q 477 729 446 682 q 504 818 504 771 m 556 209 l 314 499 q 179 395 223 449 q 135 283 135 341 q 146 222 135 253 q 183 158 158 192 q 333 80 241 80 q 556 209 448 80 "},"Λ":{"x_min":0,"x_max":862.5,"ha":942,"o":"m 862 0 l 719 0 l 426 847 l 143 0 l 0 0 l 356 1013 l 501 1013 l 862 0 "},"I":{"x_min":41,"x_max":180,"ha":293,"o":"m 180 0 l 41 0 l 41 1013 l 180 1013 l 180 0 "},"G":{"x_min":0,"x_max":921,"ha":1011,"o":"m 921 0 l 832 0 l 801 136 q 655 15 741 58 q 470 -28 568 -28 q 126 133 259 -28 q 0 499 0 284 q 125 881 0 731 q 486 1043 259 1043 q 763 957 647 1043 q 905 709 890 864 l 772 709 q 668 866 747 807 q 486 926 589 926 q 228 795 322 926 q 142 507 142 677 q 228 224 142 342 q 483 94 323 94 q 712 195 625 94 q 796 435 796 291 l 477 435 l 477 549 l 921 549 l 921 0 "},"ΰ":{"x_min":0,"x_max":617,"ha":725,"o":"m 524 800 l 414 800 l 414 925 l 524 925 l 524 800 m 183 800 l 73 800 l 73 925 l 183 925 l 183 800 m 617 352 q 540 93 617 199 q 308 -24 455 -24 q 76 93 161 -24 q 0 352 0 199 l 0 738 l 126 738 l 126 354 q 169 185 126 257 q 312 98 220 98 q 451 185 402 98 q 492 354 492 257 l 492 738 l 617 738 l 617 352 m 489 1040 l 300 819 l 216 819 l 351 1040 l 489 1040 "},"`":{"x_min":0,"x_max":138.890625,"ha":236,"o":"m 138 699 l 0 699 l 0 861 q 36 974 0 929 q 138 1041 72 1020 l 138 977 q 82 931 95 969 q 69 839 69 893 l 138 839 l 138 699 "},"·":{"x_min":0,"x_max":142,"ha":239,"o":"m 142 585 l 0 585 l 0 738 l 142 738 l 142 585 "},"Υ":{"x_min":0.328125,"x_max":819.515625,"ha":889,"o":"m 819 1013 l 482 416 l 482 0 l 342 0 l 342 416 l 0 1013 l 140 1013 l 411 533 l 679 1013 l 819 1013 "},"r":{"x_min":0,"x_max":355.5625,"ha":432,"o":"m 355 621 l 343 621 q 179 569 236 621 q 122 411 122 518 l 122 0 l 0 0 l 0 737 l 117 737 l 117 604 q 204 719 146 686 q 355 753 262 753 l 355 621 "},"x":{"x_min":0,"x_max":675,"ha":764,"o":"m 675 0 l 525 0 l 331 286 l 144 0 l 0 0 l 256 379 l 12 738 l 157 737 l 336 473 l 516 738 l 661 738 l 412 380 l 675 0 "},"μ":{"x_min":0,"x_max":696.609375,"ha":747,"o":"m 696 -4 q 628 -14 657 -14 q 498 97 513 -14 q 422 8 470 41 q 313 -24 374 -24 q 207 3 258 -24 q 120 80 157 31 l 120 -278 l 0 -278 l 0 738 l 124 738 l 124 343 q 165 172 124 246 q 308 82 216 82 q 451 177 402 82 q 492 358 492 254 l 492 738 l 616 738 l 616 214 q 623 136 616 160 q 673 92 636 92 q 696 95 684 92 l 696 -4 "},"h":{"x_min":0,"x_max":615,"ha":724,"o":"m 615 472 l 615 0 l 490 0 l 490 454 q 456 590 490 535 q 338 654 416 654 q 186 588 251 654 q 122 436 122 522 l 122 0 l 0 0 l 0 1013 l 122 1013 l 122 633 q 218 727 149 694 q 362 760 287 760 q 552 676 484 760 q 615 472 615 600 "},".":{"x_min":0,"x_max":142,"ha":239,"o":"m 142 0 l 0 0 l 0 151 l 142 151 l 142 0 "},"φ":{"x_min":-2,"x_max":878,"ha":974,"o":"m 496 -279 l 378 -279 l 378 -17 q 101 88 204 -17 q -2 367 -2 194 q 68 626 -2 510 q 283 758 151 758 l 283 646 q 167 537 209 626 q 133 373 133 462 q 192 177 133 254 q 378 93 259 93 l 378 758 q 445 764 426 763 q 476 765 464 765 q 765 659 653 765 q 878 377 878 553 q 771 96 878 209 q 496 -17 665 -17 l 496 -279 m 496 93 l 514 93 q 687 183 623 93 q 746 380 746 265 q 691 569 746 491 q 522 658 629 658 l 496 656 l 496 93 "},";":{"x_min":0,"x_max":142,"ha":239,"o":"m 142 585 l 0 585 l 0 738 l 142 738 l 142 585 m 142 -12 q 105 -132 142 -82 q 0 -206 68 -182 l 0 -138 q 58 -82 43 -123 q 68 0 68 -56 l 0 0 l 0 151 l 142 151 l 142 -12 "},"f":{"x_min":0,"x_max":378,"ha":472,"o":"m 378 638 l 246 638 l 246 0 l 121 0 l 121 638 l 0 638 l 0 738 l 121 738 q 137 935 121 887 q 290 1028 171 1028 q 320 1027 305 1028 q 378 1021 334 1026 l 378 908 q 323 918 346 918 q 257 870 273 918 q 246 780 246 840 l 246 738 l 378 738 l 378 638 "},"“":{"x_min":1,"x_max":348.21875,"ha":454,"o":"m 140 670 l 1 670 l 1 830 q 37 943 1 897 q 140 1011 74 990 l 140 947 q 82 900 97 940 q 68 810 68 861 l 140 810 l 140 670 m 348 670 l 209 670 l 209 830 q 245 943 209 897 q 348 1011 282 990 l 348 947 q 290 900 305 940 q 276 810 276 861 l 348 810 l 348 670 "},"A":{"x_min":0.03125,"x_max":906.953125,"ha":1008,"o":"m 906 0 l 756 0 l 648 303 l 251 303 l 142 0 l 0 0 l 376 1013 l 529 1013 l 906 0 m 610 421 l 452 867 l 293 421 l 610 421 "},"6":{"x_min":53,"x_max":739,"ha":792,"o":"m 739 312 q 633 62 739 162 q 400 -31 534 -31 q 162 78 257 -31 q 53 439 53 206 q 178 859 53 712 q 441 986 284 986 q 643 912 559 986 q 732 713 732 833 l 601 713 q 544 830 594 786 q 426 875 494 875 q 268 793 331 875 q 193 517 193 697 q 301 597 240 570 q 427 624 362 624 q 643 540 552 624 q 739 312 739 451 m 603 298 q 540 461 603 400 q 404 516 484 516 q 268 461 323 516 q 207 300 207 401 q 269 137 207 198 q 405 83 325 83 q 541 137 486 83 q 603 298 603 197 "},"‘":{"x_min":1,"x_max":139.890625,"ha":236,"o":"m 139 670 l 1 670 l 1 830 q 37 943 1 897 q 139 1011 74 990 l 139 947 q 82 900 97 940 q 68 810 68 861 l 139 810 l 139 670 "},"ϊ":{"x_min":-70,"x_max":283,"ha":361,"o":"m 283 800 l 173 800 l 173 925 l 283 925 l 283 800 m 40 800 l -70 800 l -70 925 l 40 925 l 40 800 m 283 3 q 232 -10 257 -5 q 181 -15 206 -15 q 84 26 118 -15 q 41 200 41 79 l 41 737 l 166 737 l 167 215 q 171 141 167 157 q 225 101 182 101 q 247 103 238 101 q 283 112 256 104 l 283 3 "},"π":{"x_min":-0.21875,"x_max":773.21875,"ha":857,"o":"m 773 -7 l 707 -11 q 575 40 607 -11 q 552 174 552 77 l 552 226 l 552 626 l 222 626 l 222 0 l 97 0 l 97 626 l 0 626 l 0 737 l 773 737 l 773 626 l 676 626 l 676 171 q 695 103 676 117 q 773 90 714 90 l 773 -7 "},"ά":{"x_min":0,"x_max":765.5625,"ha":809,"o":"m 765 -4 q 698 -14 726 -14 q 564 97 586 -14 q 466 7 525 40 q 337 -26 407 -26 q 88 98 186 -26 q 0 369 0 212 q 88 637 0 525 q 337 760 184 760 q 465 727 407 760 q 563 637 524 695 l 563 738 l 685 738 l 685 222 q 693 141 685 168 q 748 94 708 94 q 765 95 760 94 l 765 -4 m 584 371 q 531 562 584 485 q 360 653 470 653 q 192 566 254 653 q 135 379 135 489 q 186 181 135 261 q 358 84 247 84 q 528 176 465 84 q 584 371 584 260 m 604 1040 l 415 819 l 332 819 l 466 1040 l 604 1040 "},"O":{"x_min":0,"x_max":958,"ha":1057,"o":"m 485 1041 q 834 882 702 1041 q 958 512 958 734 q 834 136 958 287 q 481 -26 702 -26 q 126 130 261 -26 q 0 504 0 279 q 127 880 0 728 q 485 1041 263 1041 m 480 98 q 731 225 638 98 q 815 504 815 340 q 733 783 815 669 q 480 912 640 912 q 226 784 321 912 q 142 504 142 670 q 226 224 142 339 q 480 98 319 98 "},"n":{"x_min":0,"x_max":615,"ha":724,"o":"m 615 463 l 615 0 l 490 0 l 490 454 q 453 592 490 537 q 331 656 410 656 q 178 585 240 656 q 117 421 117 514 l 117 0 l 0 0 l 0 738 l 117 738 l 117 630 q 218 728 150 693 q 359 764 286 764 q 552 675 484 764 q 615 463 615 593 "},"3":{"x_min":54,"x_max":737,"ha":792,"o":"m 737 284 q 635 55 737 141 q 399 -25 541 -25 q 156 52 248 -25 q 54 308 54 140 l 185 308 q 245 147 185 202 q 395 96 302 96 q 539 140 484 96 q 602 280 602 190 q 510 429 602 390 q 324 454 451 454 l 324 565 q 487 584 441 565 q 565 719 565 617 q 515 835 565 791 q 395 879 466 879 q 255 824 307 879 q 203 661 203 769 l 78 661 q 166 909 78 822 q 387 992 250 992 q 603 921 513 992 q 701 723 701 844 q 669 607 701 656 q 578 524 637 558 q 696 434 655 499 q 737 284 737 369 "},"9":{"x_min":53,"x_max":739,"ha":792,"o":"m 739 524 q 619 94 739 241 q 362 -32 516 -32 q 150 47 242 -32 q 59 244 59 126 l 191 244 q 246 129 191 176 q 373 82 301 82 q 526 161 466 82 q 597 440 597 255 q 363 334 501 334 q 130 432 216 334 q 53 650 53 521 q 134 880 53 786 q 383 986 226 986 q 659 841 566 986 q 739 524 739 719 m 388 449 q 535 514 480 449 q 585 658 585 573 q 535 805 585 744 q 388 873 480 873 q 242 809 294 873 q 191 658 191 745 q 239 514 191 572 q 388 449 292 449 "},"l":{"x_min":41,"x_max":166,"ha":279,"o":"m 166 0 l 41 0 l 41 1013 l 166 1013 l 166 0 "},"¤":{"x_min":40.09375,"x_max":728.796875,"ha":825,"o":"m 728 304 l 649 224 l 512 363 q 383 331 458 331 q 256 363 310 331 l 119 224 l 40 304 l 177 441 q 150 553 150 493 q 184 673 150 621 l 40 818 l 119 898 l 267 749 q 321 766 291 759 q 384 773 351 773 q 447 766 417 773 q 501 749 477 759 l 649 898 l 728 818 l 585 675 q 612 618 604 648 q 621 553 621 587 q 591 441 621 491 l 728 304 m 384 682 q 280 643 318 682 q 243 551 243 604 q 279 461 243 499 q 383 423 316 423 q 487 461 449 423 q 525 553 525 500 q 490 641 525 605 q 384 682 451 682 "},"κ":{"x_min":0,"x_max":632.328125,"ha":679,"o":"m 632 0 l 482 0 l 225 384 l 124 288 l 124 0 l 0 0 l 0 738 l 124 738 l 124 446 l 433 738 l 596 738 l 312 466 l 632 0 "},"4":{"x_min":48,"x_max":742.453125,"ha":792,"o":"m 742 243 l 602 243 l 602 0 l 476 0 l 476 243 l 48 243 l 48 368 l 476 958 l 602 958 l 602 354 l 742 354 l 742 243 m 476 354 l 476 792 l 162 354 l 476 354 "},"p":{"x_min":0,"x_max":685,"ha":786,"o":"m 685 364 q 598 96 685 205 q 350 -23 504 -23 q 121 89 205 -23 l 121 -278 l 0 -278 l 0 738 l 121 738 l 121 633 q 220 726 159 691 q 351 761 280 761 q 598 636 504 761 q 685 364 685 522 m 557 371 q 501 560 557 481 q 330 651 437 651 q 162 559 223 651 q 108 366 108 479 q 162 177 108 254 q 333 87 224 87 q 502 178 441 87 q 557 371 557 258 "},"‡":{"x_min":0,"x_max":777,"ha":835,"o":"m 458 238 l 458 0 l 319 0 l 319 238 l 0 238 l 0 360 l 319 360 l 319 681 l 0 683 l 0 804 l 319 804 l 319 1015 l 458 1013 l 458 804 l 777 804 l 777 683 l 458 683 l 458 360 l 777 360 l 777 238 l 458 238 "},"ψ":{"x_min":0,"x_max":808,"ha":907,"o":"m 465 -278 l 341 -278 l 341 -15 q 87 102 180 -15 q 0 378 0 210 l 0 739 l 133 739 l 133 379 q 182 195 133 275 q 341 98 242 98 l 341 922 l 465 922 l 465 98 q 623 195 563 98 q 675 382 675 278 l 675 742 l 808 742 l 808 381 q 720 104 808 213 q 466 -13 627 -13 l 465 -278 "},"η":{"x_min":0.78125,"x_max":697,"ha":810,"o":"m 697 -278 l 572 -278 l 572 454 q 540 587 572 536 q 425 650 501 650 q 271 579 337 650 q 206 420 206 509 l 206 0 l 81 0 l 81 489 q 73 588 81 562 q 0 644 56 644 l 0 741 q 68 755 38 755 q 158 720 124 755 q 200 630 193 686 q 297 726 234 692 q 434 761 359 761 q 620 692 544 761 q 697 516 697 624 l 697 -278 "}},"cssFontWeight":"normal","ascender":1189,"underlinePosition":-100,"cssFontStyle":"normal","boundingBox":{"yMin":-334,"xMin":-111,"yMax":1189,"xMax":1672},"resolution":1000,"original_font_information":{"postscript_name":"Helvetiker-Regular","version_string":"Version 1.00 2004 initial release","vendor_url":"http://www.magenta.gr/","full_font_name":"Helvetiker","font_family_name":"Helvetiker","copyright":"Copyright (c) Μagenta ltd, 2004","description":"","trademark":"","designer":"","designer_url":"","unique_font_identifier":"Μagenta ltd:Helvetiker:22-10-104","license_url":"http://www.ellak.gr/fonts/MgOpen/license.html","license_description":"Copyright (c) 2004 by MAGENTA Ltd. All Rights Reserved.\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license (\"Fonts\") and associated documentation files (the \"Font Software\"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: \r\n\r\nThe above copyright and this permission notice shall be included in all copies of one or more of the Font Software typefaces.\r\n\r\nThe Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word \"MgOpen\", or if the modifications are accepted for inclusion in the Font Software itself by the each appointed Administrator.\r\n\r\nThis License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the \"MgOpen\" name.\r\n\r\nThe Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. \r\n\r\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL MAGENTA OR PERSONS OR BODIES IN CHARGE OF ADMINISTRATION AND MAINTENANCE OF THE FONT SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.","manufacturer_name":"Μagenta ltd","font_sub_family_name":"Regular"},"descender":-334,"familyName":"Helvetiker","lineHeight":1522,"underlineThickness":50}
31  );
32 
33 // Content of examples/js/renderers/Projector.js
40 THREE.RenderableObject = function () {
41 
42  this.id = 0;
43 
44  this.object = null;
45  this.z = 0;
46  this.renderOrder = 0;
47 
48 };
49 
50 //
51 
52 THREE.RenderableFace = function () {
53 
54  this.id = 0;
55 
56  this.v1 = new THREE.RenderableVertex();
57  this.v2 = new THREE.RenderableVertex();
58  this.v3 = new THREE.RenderableVertex();
59 
60  this.normalModel = new THREE.Vector3();
61 
62  this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
63  this.vertexNormalsLength = 0;
64 
65  this.color = new THREE.Color();
66  this.material = null;
67  this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];
68 
69  this.z = 0;
70  this.renderOrder = 0;
71 
72 };
73 
74 //
75 
76 THREE.RenderableVertex = function () {
77 
78  this.position = new THREE.Vector3();
79  this.positionWorld = new THREE.Vector3();
80  this.positionScreen = new THREE.Vector4();
81 
82  this.visible = true;
83 
84 };
85 
86 THREE.RenderableVertex.prototype.copy = function ( vertex ) {
87 
88  this.positionWorld.copy( vertex.positionWorld );
89  this.positionScreen.copy( vertex.positionScreen );
90 
91 };
92 
93 //
94 
95 THREE.RenderableLine = function () {
96 
97  this.id = 0;
98 
99  this.v1 = new THREE.RenderableVertex();
100  this.v2 = new THREE.RenderableVertex();
101 
102  this.vertexColors = [ new THREE.Color(), new THREE.Color() ];
103  this.material = null;
104 
105  this.z = 0;
106  this.renderOrder = 0;
107 
108 };
109 
110 //
111 
112 THREE.RenderableSprite = function () {
113 
114  this.id = 0;
115 
116  this.object = null;
117 
118  this.x = 0;
119  this.y = 0;
120  this.z = 0;
121 
122  this.rotation = 0;
123  this.scale = new THREE.Vector2();
124 
125  this.material = null;
126  this.renderOrder = 0;
127 
128 };
129 
130 //
131 
132 THREE.Projector = function () {
133 
134  var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
135  _vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
136  _face, _faceCount, _facePool = [], _facePoolLength = 0,
137  _line, _lineCount, _linePool = [], _linePoolLength = 0,
138  _sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
139 
140  _renderData = { objects: [], lights: [], elements: [] },
141 
142  _vector3 = new THREE.Vector3(),
143  _vector4 = new THREE.Vector4(),
144 
145  _clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
146  _boundingBox = new THREE.Box3(),
147  _points3 = new Array( 3 ),
148 
149  _viewMatrix = new THREE.Matrix4(),
150  _viewProjectionMatrix = new THREE.Matrix4(),
151 
152  _modelMatrix,
153  _modelViewProjectionMatrix = new THREE.Matrix4(),
154 
155  _normalMatrix = new THREE.Matrix3(),
156 
157  _frustum = new THREE.Frustum(),
158 
159  _clippedVertex1PositionScreen = new THREE.Vector4(),
160  _clippedVertex2PositionScreen = new THREE.Vector4();
161 
162  //
163 
164  this.projectVector = function ( vector, camera ) {
165 
166  console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
167  vector.project( camera );
168 
169  };
170 
171  this.unprojectVector = function ( vector, camera ) {
172 
173  console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
174  vector.unproject( camera );
175 
176  };
177 
178  this.pickingRay = function () {
179 
180  console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
181 
182  };
183 
184  //
185 
186  var RenderList = function () {
187 
188  var normals = [];
189  var colors = [];
190  var uvs = [];
191 
192  var object = null;
193  var material = null;
194 
195  var normalMatrix = new THREE.Matrix3();
196 
197  function setObject( value ) {
198 
199  object = value;
200  material = object.material;
201 
202  normalMatrix.getNormalMatrix( object.matrixWorld );
203 
204  normals.length = 0;
205  colors.length = 0;
206  uvs.length = 0;
207 
208  }
209 
210  function projectVertex( vertex ) {
211 
212  var position = vertex.position;
213  var positionWorld = vertex.positionWorld;
214  var positionScreen = vertex.positionScreen;
215 
216  positionWorld.copy( position ).applyMatrix4( _modelMatrix );
217  positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix );
218 
219  var invW = 1 / positionScreen.w;
220 
221  positionScreen.x *= invW;
222  positionScreen.y *= invW;
223  positionScreen.z *= invW;
224 
225  vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 &&
226  positionScreen.y >= - 1 && positionScreen.y <= 1 &&
227  positionScreen.z >= - 1 && positionScreen.z <= 1;
228 
229  }
230 
231  function pushVertex( x, y, z ) {
232 
233  _vertex = getNextVertexInPool();
234  _vertex.position.set( x, y, z );
235 
236  projectVertex( _vertex );
237 
238  }
239 
240  function pushNormal( x, y, z ) {
241 
242  normals.push( x, y, z );
243 
244  }
245 
246  function pushColor( r, g, b ) {
247 
248  colors.push( r, g, b );
249 
250  }
251 
252  function pushUv( x, y ) {
253 
254  uvs.push( x, y );
255 
256  }
257 
258  function checkTriangleVisibility( v1, v2, v3 ) {
259 
260  if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true;
261 
262  _points3[ 0 ] = v1.positionScreen;
263  _points3[ 1 ] = v2.positionScreen;
264  _points3[ 2 ] = v3.positionScreen;
265 
266  return _clipBox.intersectsBox( _boundingBox.setFromPoints( _points3 ) );
267 
268  }
269 
270  function checkBackfaceCulling( v1, v2, v3 ) {
271 
272  return ( ( v3.positionScreen.x - v1.positionScreen.x ) *
273  ( v2.positionScreen.y - v1.positionScreen.y ) -
274  ( v3.positionScreen.y - v1.positionScreen.y ) *
275  ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;
276 
277  }
278 
279  function pushLine( a, b ) {
280 
281  var v1 = _vertexPool[ a ];
282  var v2 = _vertexPool[ b ];
283 
284  // Clip
285 
286  v1.positionScreen.copy( v1.position ).applyMatrix4( _modelViewProjectionMatrix );
287  v2.positionScreen.copy( v2.position ).applyMatrix4( _modelViewProjectionMatrix );
288 
289  if ( clipLine( v1.positionScreen, v2.positionScreen ) === true ) {
290 
291  // Perform the perspective divide
292  v1.positionScreen.multiplyScalar( 1 / v1.positionScreen.w );
293  v2.positionScreen.multiplyScalar( 1 / v2.positionScreen.w );
294 
295  _line = getNextLineInPool();
296  _line.id = object.id;
297  _line.v1.copy( v1 );
298  _line.v2.copy( v2 );
299  _line.z = Math.max( v1.positionScreen.z, v2.positionScreen.z );
300  _line.renderOrder = object.renderOrder;
301 
302  _line.material = object.material;
303 
304  if ( object.material.vertexColors === THREE.VertexColors ) {
305 
306  _line.vertexColors[ 0 ].fromArray( colors, a * 3 );
307  _line.vertexColors[ 1 ].fromArray( colors, b * 3 );
308 
309  }
310 
311  _renderData.elements.push( _line );
312 
313  }
314 
315  }
316 
317  function pushTriangle( a, b, c, material ) {
318 
319  var v1 = _vertexPool[ a ];
320  var v2 = _vertexPool[ b ];
321  var v3 = _vertexPool[ c ];
322 
323  if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return;
324 
325  if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) {
326 
327  _face = getNextFaceInPool();
328 
329  _face.id = object.id;
330  _face.v1.copy( v1 );
331  _face.v2.copy( v2 );
332  _face.v3.copy( v3 );
333  _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
334  _face.renderOrder = object.renderOrder;
335 
336  // face normal
337  _vector3.subVectors( v3.position, v2.position );
338  _vector4.subVectors( v1.position, v2.position );
339  _vector3.cross( _vector4 );
340  _face.normalModel.copy( _vector3 );
341  _face.normalModel.applyMatrix3( normalMatrix ).normalize();
342 
343  for ( var i = 0; i < 3; i ++ ) {
344 
345  var normal = _face.vertexNormalsModel[ i ];
346  normal.fromArray( normals, arguments[ i ] * 3 );
347  normal.applyMatrix3( normalMatrix ).normalize();
348 
349  var uv = _face.uvs[ i ];
350  uv.fromArray( uvs, arguments[ i ] * 2 );
351 
352  }
353 
354  _face.vertexNormalsLength = 3;
355 
356  _face.material = material;
357 
358  if ( material.vertexColors === THREE.FaceColors || material.vertexColors === THREE.VertexColors ) {
359 
360  _face.color.fromArray( colors, a * 3 );
361 
362  }
363 
364  _renderData.elements.push( _face );
365 
366  }
367 
368  }
369 
370  return {
371  setObject: setObject,
372  projectVertex: projectVertex,
373  checkTriangleVisibility: checkTriangleVisibility,
374  checkBackfaceCulling: checkBackfaceCulling,
375  pushVertex: pushVertex,
376  pushNormal: pushNormal,
377  pushColor: pushColor,
378  pushUv: pushUv,
379  pushLine: pushLine,
380  pushTriangle: pushTriangle
381  };
382 
383  };
384 
385  var renderList = new RenderList();
386 
387  function projectObject( object ) {
388 
389  if ( object.visible === false ) return;
390 
391  if ( object instanceof THREE.Light ) {
392 
393  _renderData.lights.push( object );
394 
395  } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
396 
397  if ( object.material.visible === false ) return;
398  if ( object.frustumCulled === true && _frustum.intersectsObject( object ) === false ) return;
399 
400  addObject( object );
401 
402  } else if ( object instanceof THREE.Sprite ) {
403 
404  if ( object.material.visible === false ) return;
405  if ( object.frustumCulled === true && _frustum.intersectsSprite( object ) === false ) return;
406 
407  addObject( object );
408 
409  }
410 
411  var children = object.children;
412 
413  for ( var i = 0, l = children.length; i < l; i ++ ) {
414 
415  projectObject( children[ i ] );
416 
417  }
418 
419  }
420 
421  function addObject( object ) {
422 
423  _object = getNextObjectInPool();
424  _object.id = object.id;
425  _object.object = object;
426 
427  _vector3.setFromMatrixPosition( object.matrixWorld );
428  _vector3.applyMatrix4( _viewProjectionMatrix );
429  _object.z = _vector3.z;
430  _object.renderOrder = object.renderOrder;
431 
432  _renderData.objects.push( _object );
433 
434  }
435 
436  this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
437 
438  _faceCount = 0;
439  _lineCount = 0;
440  _spriteCount = 0;
441 
442  _renderData.elements.length = 0;
443 
444  if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
445  if ( camera.parent === null ) camera.updateMatrixWorld();
446 
447  _viewMatrix.copy( camera.matrixWorldInverse );
448  _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
449 
450  _frustum.setFromMatrix( _viewProjectionMatrix );
451 
452  //
453 
454  _objectCount = 0;
455 
456  _renderData.objects.length = 0;
457  _renderData.lights.length = 0;
458 
459  projectObject( scene );
460 
461  if ( sortObjects === true ) {
462 
463  _renderData.objects.sort( painterSort );
464 
465  }
466 
467  //
468 
469  var objects = _renderData.objects;
470 
471  for ( var o = 0, ol = objects.length; o < ol; o ++ ) {
472 
473  var object = objects[ o ].object;
474  var geometry = object.geometry;
475 
476  renderList.setObject( object );
477 
478  _modelMatrix = object.matrixWorld;
479 
480  _vertexCount = 0;
481 
482  if ( object instanceof THREE.Mesh ) {
483 
484  if ( geometry instanceof THREE.BufferGeometry ) {
485 
486  var material = object.material;
487 
488  var isMultiMaterial = Array.isArray( material );
489 
490  var attributes = geometry.attributes;
491  var groups = geometry.groups;
492 
493  if ( attributes.position === undefined ) continue;
494 
495  var positions = attributes.position.array;
496 
497  for ( var i = 0, l = positions.length; i < l; i += 3 ) {
498 
499  var x = positions[ i ];
500  var y = positions[ i + 1 ];
501  var z = positions[ i + 2 ];
502 
503  if ( material.morphTargets === true ) {
504 
505  var morphTargets = geometry.morphAttributes.position;
506  var morphInfluences = object.morphTargetInfluences;
507 
508  for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
509 
510  var influence = morphInfluences[ t ];
511 
512  if ( influence === 0 ) continue;
513 
514  var target = morphTargets[ t ];
515 
516  x += ( target.getX( i / 3 ) - positions[ i ] ) * influence;
517  y += ( target.getY( i / 3 ) - positions[ i + 1 ] ) * influence;
518  z += ( target.getZ( i / 3 ) - positions[ i + 2 ] ) * influence;
519 
520  }
521 
522  }
523 
524  renderList.pushVertex( x, y, z );
525 
526  }
527 
528  if ( attributes.normal !== undefined ) {
529 
530  var normals = attributes.normal.array;
531 
532  for ( var i = 0, l = normals.length; i < l; i += 3 ) {
533 
534  renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] );
535 
536  }
537 
538  }
539 
540  if ( attributes.color !== undefined ) {
541 
542  var colors = attributes.color.array;
543 
544  for ( var i = 0, l = colors.length; i < l; i += 3 ) {
545 
546  renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] );
547 
548  }
549 
550  }
551 
552  if ( attributes.uv !== undefined ) {
553 
554  var uvs = attributes.uv.array;
555 
556  for ( var i = 0, l = uvs.length; i < l; i += 2 ) {
557 
558  renderList.pushUv( uvs[ i ], uvs[ i + 1 ] );
559 
560  }
561 
562  }
563 
564  if ( geometry.index !== null ) {
565 
566  var indices = geometry.index.array;
567 
568  if ( groups.length > 0 ) {
569 
570  for ( var g = 0; g < groups.length; g ++ ) {
571 
572  var group = groups[ g ];
573 
574  material = isMultiMaterial === true
575  ? object.material[ group.materialIndex ]
576  : object.material;
577 
578  if ( material === undefined ) continue;
579 
580  for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
581 
582  renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material );
583 
584  }
585 
586  }
587 
588  } else {
589 
590  for ( var i = 0, l = indices.length; i < l; i += 3 ) {
591 
592  renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material );
593 
594  }
595 
596  }
597 
598  } else {
599 
600  if ( groups.length > 0 ) {
601 
602  for ( var g = 0; g < groups.length; g ++ ) {
603 
604  var group = groups[ g ];
605 
606  material = isMultiMaterial === true
607  ? object.material[ group.materialIndex ]
608  : object.material;
609 
610  if ( material === undefined ) continue;
611 
612  for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
613 
614  renderList.pushTriangle( i, i + 1, i + 2, material );
615 
616  }
617 
618  }
619 
620  } else {
621 
622  for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) {
623 
624  renderList.pushTriangle( i, i + 1, i + 2, material );
625 
626  }
627 
628  }
629 
630  }
631 
632  } else if ( geometry instanceof THREE.Geometry ) {
633 
634  var vertices = geometry.vertices;
635  var faces = geometry.faces;
636  var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
637 
638  _normalMatrix.getNormalMatrix( _modelMatrix );
639 
640  var material = object.material;
641 
642  var isMultiMaterial = Array.isArray( material );
643 
644  for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
645 
646  var vertex = vertices[ v ];
647 
648  _vector3.copy( vertex );
649 
650  if ( material.morphTargets === true ) {
651 
652  var morphTargets = geometry.morphTargets;
653  var morphInfluences = object.morphTargetInfluences;
654 
655  for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
656 
657  var influence = morphInfluences[ t ];
658 
659  if ( influence === 0 ) continue;
660 
661  var target = morphTargets[ t ];
662  var targetVertex = target.vertices[ v ];
663 
664  _vector3.x += ( targetVertex.x - vertex.x ) * influence;
665  _vector3.y += ( targetVertex.y - vertex.y ) * influence;
666  _vector3.z += ( targetVertex.z - vertex.z ) * influence;
667 
668  }
669 
670  }
671 
672  renderList.pushVertex( _vector3.x, _vector3.y, _vector3.z );
673 
674  }
675 
676  for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
677 
678  var face = faces[ f ];
679 
680  material = isMultiMaterial === true
681  ? object.material[ face.materialIndex ]
682  : object.material;
683 
684  if ( material === undefined ) continue;
685 
686  var side = material.side;
687 
688  var v1 = _vertexPool[ face.a ];
689  var v2 = _vertexPool[ face.b ];
690  var v3 = _vertexPool[ face.c ];
691 
692  if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
693 
694  var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
695 
696  if ( side !== THREE.DoubleSide ) {
697 
698  if ( side === THREE.FrontSide && visible === false ) continue;
699  if ( side === THREE.BackSide && visible === true ) continue;
700 
701  }
702 
703  _face = getNextFaceInPool();
704 
705  _face.id = object.id;
706  _face.v1.copy( v1 );
707  _face.v2.copy( v2 );
708  _face.v3.copy( v3 );
709 
710  _face.normalModel.copy( face.normal );
711 
712  if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
713 
714  _face.normalModel.negate();
715 
716  }
717 
718  _face.normalModel.applyMatrix3( _normalMatrix ).normalize();
719 
720  var faceVertexNormals = face.vertexNormals;
721 
722  for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {
723 
724  var normalModel = _face.vertexNormalsModel[ n ];
725  normalModel.copy( faceVertexNormals[ n ] );
726 
727  if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
728 
729  normalModel.negate();
730 
731  }
732 
733  normalModel.applyMatrix3( _normalMatrix ).normalize();
734 
735  }
736 
737  _face.vertexNormalsLength = faceVertexNormals.length;
738 
739  var vertexUvs = faceVertexUvs[ f ];
740 
741  if ( vertexUvs !== undefined ) {
742 
743  for ( var u = 0; u < 3; u ++ ) {
744 
745  _face.uvs[ u ].copy( vertexUvs[ u ] );
746 
747  }
748 
749  }
750 
751  _face.color = face.color;
752  _face.material = material;
753 
754  _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
755  _face.renderOrder = object.renderOrder;
756 
757  _renderData.elements.push( _face );
758 
759  }
760 
761  }
762 
763  } else if ( object instanceof THREE.Line ) {
764 
765  _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
766 
767  if ( geometry instanceof THREE.BufferGeometry ) {
768 
769  var attributes = geometry.attributes;
770 
771  if ( attributes.position !== undefined ) {
772 
773  var positions = attributes.position.array;
774 
775  for ( var i = 0, l = positions.length; i < l; i += 3 ) {
776 
777  renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
778 
779  }
780 
781  if ( attributes.color !== undefined ) {
782 
783  var colors = attributes.color.array;
784 
785  for ( var i = 0, l = colors.length; i < l; i += 3 ) {
786 
787  renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] );
788 
789  }
790 
791  }
792 
793  if ( geometry.index !== null ) {
794 
795  var indices = geometry.index.array;
796 
797  for ( var i = 0, l = indices.length; i < l; i += 2 ) {
798 
799  renderList.pushLine( indices[ i ], indices[ i + 1 ] );
800 
801  }
802 
803  } else {
804 
805  var step = object instanceof THREE.LineSegments ? 2 : 1;
806 
807  for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
808 
809  renderList.pushLine( i, i + 1 );
810 
811  }
812 
813  }
814 
815  }
816 
817  } else if ( geometry instanceof THREE.Geometry ) {
818 
819  var vertices = object.geometry.vertices;
820 
821  if ( vertices.length === 0 ) continue;
822 
823  v1 = getNextVertexInPool();
824  v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
825 
826  var step = object instanceof THREE.LineSegments ? 2 : 1;
827 
828  for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
829 
830  v1 = getNextVertexInPool();
831  v1.positionScreen.copy( vertices[ v ] ).applyMatrix4( _modelViewProjectionMatrix );
832 
833  if ( ( v + 1 ) % step > 0 ) continue;
834 
835  v2 = _vertexPool[ _vertexCount - 2 ];
836 
837  _clippedVertex1PositionScreen.copy( v1.positionScreen );
838  _clippedVertex2PositionScreen.copy( v2.positionScreen );
839 
840  if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
841 
842  // Perform the perspective divide
843  _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
844  _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
845 
846  _line = getNextLineInPool();
847 
848  _line.id = object.id;
849  _line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
850  _line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
851 
852  _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
853  _line.renderOrder = object.renderOrder;
854 
855  _line.material = object.material;
856 
857  if ( object.material.vertexColors === THREE.VertexColors ) {
858 
859  _line.vertexColors[ 0 ].copy( object.geometry.colors[ v ] );
860  _line.vertexColors[ 1 ].copy( object.geometry.colors[ v - 1 ] );
861 
862  }
863 
864  _renderData.elements.push( _line );
865 
866  }
867 
868  }
869 
870  }
871 
872  } else if ( object instanceof THREE.Points ) {
873 
874  _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
875 
876  if ( geometry instanceof THREE.Geometry ) {
877 
878  var vertices = object.geometry.vertices;
879 
880  for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
881 
882  var vertex = vertices[ v ];
883 
884  _vector4.set( vertex.x, vertex.y, vertex.z, 1 );
885  _vector4.applyMatrix4( _modelViewProjectionMatrix );
886 
887  pushPoint( _vector4, object, camera );
888 
889  }
890 
891  } else if ( geometry instanceof THREE.BufferGeometry ) {
892 
893  var attributes = geometry.attributes;
894 
895  if ( attributes.position !== undefined ) {
896 
897  var positions = attributes.position.array;
898 
899  for ( var i = 0, l = positions.length; i < l; i += 3 ) {
900 
901  _vector4.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ], 1 );
902  _vector4.applyMatrix4( _modelViewProjectionMatrix );
903 
904  pushPoint( _vector4, object, camera );
905 
906  }
907 
908  }
909 
910  }
911 
912  } else if ( object instanceof THREE.Sprite ) {
913 
914  object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
915  _vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 );
916  _vector4.applyMatrix4( _viewProjectionMatrix );
917 
918  pushPoint( _vector4, object, camera );
919 
920  }
921 
922  }
923 
924  if ( sortElements === true ) {
925 
926  _renderData.elements.sort( painterSort );
927 
928  }
929 
930  return _renderData;
931 
932  };
933 
934  function pushPoint( _vector4, object, camera ) {
935 
936  var invW = 1 / _vector4.w;
937 
938  _vector4.z *= invW;
939 
940  if ( _vector4.z >= - 1 && _vector4.z <= 1 ) {
941 
942  _sprite = getNextSpriteInPool();
943  _sprite.id = object.id;
944  _sprite.x = _vector4.x * invW;
945  _sprite.y = _vector4.y * invW;
946  _sprite.z = _vector4.z;
947  _sprite.renderOrder = object.renderOrder;
948  _sprite.object = object;
949 
950  _sprite.rotation = object.rotation;
951 
952  _sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) );
953  _sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) );
954 
955  _sprite.material = object.material;
956 
957  _renderData.elements.push( _sprite );
958 
959  }
960 
961  }
962 
963  // Pools
964 
965  function getNextObjectInPool() {
966 
967  if ( _objectCount === _objectPoolLength ) {
968 
969  var object = new THREE.RenderableObject();
970  _objectPool.push( object );
971  _objectPoolLength ++;
972  _objectCount ++;
973  return object;
974 
975  }
976 
977  return _objectPool[ _objectCount ++ ];
978 
979  }
980 
981  function getNextVertexInPool() {
982 
983  if ( _vertexCount === _vertexPoolLength ) {
984 
985  var vertex = new THREE.RenderableVertex();
986  _vertexPool.push( vertex );
987  _vertexPoolLength ++;
988  _vertexCount ++;
989  return vertex;
990 
991  }
992 
993  return _vertexPool[ _vertexCount ++ ];
994 
995  }
996 
997  function getNextFaceInPool() {
998 
999  if ( _faceCount === _facePoolLength ) {
1000 
1001  var face = new THREE.RenderableFace();
1002  _facePool.push( face );
1003  _facePoolLength ++;
1004  _faceCount ++;
1005  return face;
1006 
1007  }
1008 
1009  return _facePool[ _faceCount ++ ];
1010 
1011 
1012  }
1013 
1014  function getNextLineInPool() {
1015 
1016  if ( _lineCount === _linePoolLength ) {
1017 
1018  var line = new THREE.RenderableLine();
1019  _linePool.push( line );
1020  _linePoolLength ++;
1021  _lineCount ++;
1022  return line;
1023 
1024  }
1025 
1026  return _linePool[ _lineCount ++ ];
1027 
1028  }
1029 
1030  function getNextSpriteInPool() {
1031 
1032  if ( _spriteCount === _spritePoolLength ) {
1033 
1034  var sprite = new THREE.RenderableSprite();
1035  _spritePool.push( sprite );
1036  _spritePoolLength ++;
1037  _spriteCount ++;
1038  return sprite;
1039 
1040  }
1041 
1042  return _spritePool[ _spriteCount ++ ];
1043 
1044  }
1045 
1046  //
1047 
1048  function painterSort( a, b ) {
1049 
1050  if ( a.renderOrder !== b.renderOrder ) {
1051 
1052  return a.renderOrder - b.renderOrder;
1053 
1054  } else if ( a.z !== b.z ) {
1055 
1056  return b.z - a.z;
1057 
1058  } else if ( a.id !== b.id ) {
1059 
1060  return a.id - b.id;
1061 
1062  } else {
1063 
1064  return 0;
1065 
1066  }
1067 
1068  }
1069 
1070  function clipLine( s1, s2 ) {
1071 
1072  var alpha1 = 0, alpha2 = 1,
1073 
1074  // Calculate the boundary coordinate of each vertex for the near and far clip planes,
1075  // Z = -1 and Z = +1, respectively.
1076 
1077  bc1near = s1.z + s1.w,
1078  bc2near = s2.z + s2.w,
1079  bc1far = - s1.z + s1.w,
1080  bc2far = - s2.z + s2.w;
1081 
1082  if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
1083 
1084  // Both vertices lie entirely within all clip planes.
1085  return true;
1086 
1087  } else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) {
1088 
1089  // Both vertices lie entirely outside one of the clip planes.
1090  return false;
1091 
1092  } else {
1093 
1094  // The line segment spans at least one clip plane.
1095 
1096  if ( bc1near < 0 ) {
1097 
1098  // v1 lies outside the near plane, v2 inside
1099  alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );
1100 
1101  } else if ( bc2near < 0 ) {
1102 
1103  // v2 lies outside the near plane, v1 inside
1104  alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );
1105 
1106  }
1107 
1108  if ( bc1far < 0 ) {
1109 
1110  // v1 lies outside the far plane, v2 inside
1111  alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );
1112 
1113  } else if ( bc2far < 0 ) {
1114 
1115  // v2 lies outside the far plane, v2 inside
1116  alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );
1117 
1118  }
1119 
1120  if ( alpha2 < alpha1 ) {
1121 
1122  // The line segment spans two boundaries, but is outside both of them.
1123  // (This can't happen when we're only clipping against just near/far but good
1124  // to leave the check here for future usage if other clip planes are added.)
1125  return false;
1126 
1127  } else {
1128 
1129  // Update the s1 and s2 vertices to match the clipped line segment.
1130  s1.lerp( s2, alpha1 );
1131  s2.lerp( s1, 1 - alpha2 );
1132 
1133  return true;
1134 
1135  }
1136 
1137  }
1138 
1139  }
1140 
1141 };
1142 
1143 // Content of examples/js/renderers/SoftwareRenderer.js
1151 THREE.SoftwareRenderer = function ( parameters ) {
1152 
1153  console.log( 'THREE.SoftwareRenderer', THREE.REVISION );
1154 
1155  parameters = parameters || {};
1156 
1157  var canvas = parameters.canvas !== undefined
1158  ? parameters.canvas
1159  : document.createElement( 'canvas' );
1160 
1161  var context = canvas.getContext( '2d', {
1162  alpha: parameters.alpha === true
1163  } );
1164 
1165  var shaders = {};
1166  var textures = {};
1167 
1168  var canvasWidth, canvasHeight;
1169  var canvasWBlocks, canvasHBlocks;
1170  var viewportXScale, viewportYScale, viewportZScale;
1171  var viewportXOffs, viewportYOffs, viewportZOffs;
1172 
1173  var clearColor = new THREE.Color( 0x000000 );
1174  var clearAlpha = parameters.alpha === true ? 0 : 1;
1175 
1176  var imagedata, data, zbuffer;
1177  var numBlocks, blockMaxZ, blockFlags;
1178 
1179  var BLOCK_ISCLEAR = ( 1 << 0 );
1180  var BLOCK_NEEDCLEAR = ( 1 << 1 );
1181 
1182  var subpixelBits = 4;
1183  var subpixelBias = ( 1 << subpixelBits ) - 1;
1184  var blockShift = 3;
1185  var blockSize = 1 << blockShift;
1186  var maxZVal = ( 1 << 24 ); // Note: You want to size this so you don't get overflows.
1187  var lineMode = false;
1188  var lookVector = new THREE.Vector3( 0, 0, 1 );
1189  var crossVector = new THREE.Vector3();
1190 
1191  var rectx1 = Infinity, recty1 = Infinity;
1192  var rectx2 = 0, recty2 = 0;
1193 
1194  var prevrectx1 = Infinity, prevrecty1 = Infinity;
1195  var prevrectx2 = 0, prevrecty2 = 0;
1196 
1197  var projector = new THREE.Projector();
1198 
1199  var spriteV1 = new THREE.Vector4();
1200  var spriteV2 = new THREE.Vector4();
1201  var spriteV3 = new THREE.Vector4();
1202 
1203  var spriteUV1 = new THREE.Vector2();
1204  var spriteUV2 = new THREE.Vector2();
1205  var spriteUV3 = new THREE.Vector2();
1206 
1207  var mpVPool = [];
1208  var mpVPoolCount = 0;
1209  var mpNPool = [];
1210  var mpNPoolCount = 0;
1211  var mpUVPool = [];
1212  var mpUVPoolCount = 0;
1213 
1214  var _this = this;
1215 
1216  this.domElement = canvas;
1217 
1218  this.autoClear = true;
1219 
1220  this.setClearColor = function ( color, alpha ) {
1221 
1222  clearColor.set( color );
1223  clearAlpha = alpha;
1224  clearColorBuffer( clearColor );
1225 
1226  };
1227 
1228  this.setPixelRatio = function () {};
1229 
1230  this.setSize = function ( width, height ) {
1231 
1232  canvasWBlocks = Math.floor( width / blockSize );
1233  canvasHBlocks = Math.floor( height / blockSize );
1234  canvasWidth = canvasWBlocks * blockSize;
1235  canvasHeight = canvasHBlocks * blockSize;
1236 
1237  var fixScale = 1 << subpixelBits;
1238 
1239  viewportXScale = fixScale * canvasWidth / 2;
1240  viewportYScale = - fixScale * canvasHeight / 2;
1241  viewportZScale = maxZVal / 2;
1242 
1243  viewportXOffs = fixScale * canvasWidth / 2 + 0.5;
1244  viewportYOffs = fixScale * canvasHeight / 2 + 0.5;
1245  viewportZOffs = maxZVal / 2 + 0.5;
1246 
1247  canvas.width = canvasWidth;
1248  canvas.height = canvasHeight;
1249 
1250  imagedata = context.getImageData( 0, 0, canvasWidth, canvasHeight );
1251  data = imagedata.data;
1252 
1253  zbuffer = new Int32Array( data.length / 4 );
1254 
1255  numBlocks = canvasWBlocks * canvasHBlocks;
1256  blockMaxZ = new Int32Array( numBlocks );
1257  blockFlags = new Uint8Array( numBlocks );
1258 
1259  for ( var i = 0, l = zbuffer.length; i < l; i ++ ) {
1260 
1261  zbuffer[ i ] = maxZVal;
1262 
1263  }
1264 
1265  for ( var i = 0; i < numBlocks; i ++ ) {
1266 
1267  blockFlags[ i ] = BLOCK_ISCLEAR;
1268 
1269  }
1270 
1271  clearColorBuffer( clearColor );
1272 
1273  };
1274 
1275  this.clear = function () {
1276 
1277  rectx1 = Infinity;
1278  recty1 = Infinity;
1279  rectx2 = 0;
1280  recty2 = 0;
1281  mpVPoolCount = 0;
1282  mpNPoolCount = 0;
1283  mpUVPoolCount = 0;
1284 
1285  for ( var i = 0; i < numBlocks; i ++ ) {
1286 
1287  blockMaxZ[ i ] = maxZVal;
1288  blockFlags[ i ] = ( blockFlags[ i ] & BLOCK_ISCLEAR ) ? BLOCK_ISCLEAR : BLOCK_NEEDCLEAR;
1289 
1290  }
1291 
1292  };
1293 
1294 
1295  this.render = function ( scene, camera ) {
1296 
1297  // TODO: Check why autoClear can't be false.
1298  this.clear();
1299 
1300  var background = scene.background;
1301 
1302  if ( background && background.isColor ) {
1303 
1304  clearColorBuffer( background );
1305 
1306  }
1307 
1308  var renderData = projector.projectScene( scene, camera, false, false );
1309  var elements = renderData.elements;
1310 
1311  for ( var e = 0, el = elements.length; e < el; e ++ ) {
1312 
1313  var element = elements[ e ];
1314  var material = element.material;
1315  var shader = getMaterialShader( material );
1316 
1317  if ( ! shader ) continue;
1318 
1319  if ( element instanceof THREE.RenderableFace ) {
1320 
1321  if ( ! element.uvs ) {
1322 
1323  drawTriangle(
1324  element.v1.positionScreen,
1325  element.v2.positionScreen,
1326  element.v3.positionScreen,
1327  null, null, null,
1328  shader, element, material
1329  );
1330 
1331  } else {
1332 
1333  drawTriangle(
1334  element.v1.positionScreen,
1335  element.v2.positionScreen,
1336  element.v3.positionScreen,
1337  element.uvs[ 0 ], element.uvs[ 1 ], element.uvs[ 2 ],
1338  shader, element, material
1339  );
1340 
1341  }
1342 
1343 
1344  } else if ( element instanceof THREE.RenderableSprite ) {
1345 
1346  var scaleX = element.scale.x * 0.5;
1347  var scaleY = element.scale.y * 0.5;
1348 
1349  spriteV1.copy( element );
1350  spriteV1.x -= scaleX;
1351  spriteV1.y += scaleY;
1352 
1353  spriteV2.copy( element );
1354  spriteV2.x -= scaleX;
1355  spriteV2.y -= scaleY;
1356 
1357  spriteV3.copy( element );
1358  spriteV3.x += scaleX;
1359  spriteV3.y += scaleY;
1360 
1361  if ( material.map ) {
1362 
1363  spriteUV1.set( 0, 1 );
1364  spriteUV2.set( 0, 0 );
1365  spriteUV3.set( 1, 1 );
1366 
1367  drawTriangle(
1368  spriteV1, spriteV2, spriteV3,
1369  spriteUV1, spriteUV2, spriteUV3,
1370  shader, element, material
1371  );
1372 
1373  } else {
1374 
1375  drawTriangle(
1376  spriteV1, spriteV2, spriteV3,
1377  null, null, null,
1378  shader, element, material
1379  );
1380 
1381  }
1382 
1383  spriteV1.copy( element );
1384  spriteV1.x += scaleX;
1385  spriteV1.y += scaleY;
1386 
1387  spriteV2.copy( element );
1388  spriteV2.x -= scaleX;
1389  spriteV2.y -= scaleY;
1390 
1391  spriteV3.copy( element );
1392  spriteV3.x += scaleX;
1393  spriteV3.y -= scaleY;
1394 
1395  if ( material.map ) {
1396 
1397  spriteUV1.set( 1, 1 );
1398  spriteUV2.set( 0, 0 );
1399  spriteUV3.set( 1, 0 );
1400 
1401  drawTriangle(
1402  spriteV1, spriteV2, spriteV3,
1403  spriteUV1, spriteUV2, spriteUV3,
1404  shader, element, material
1405  );
1406 
1407  } else {
1408 
1409  drawTriangle(
1410  spriteV1, spriteV2, spriteV3,
1411  null, null, null,
1412  shader, element, material
1413  );
1414 
1415  }
1416 
1417  } else if ( element instanceof THREE.RenderableLine ) {
1418 
1419  var shader = getMaterialShader( material );
1420 
1421  drawLine(
1422  element.v1.positionScreen,
1423  element.v2.positionScreen,
1424  element.vertexColors[ 0 ],
1425  element.vertexColors[ 1 ],
1426  shader,
1427  material
1428  );
1429 
1430  }
1431 
1432  }
1433 
1434  finishClear();
1435 
1436  var x = Math.min( rectx1, prevrectx1 );
1437  var y = Math.min( recty1, prevrecty1 );
1438  var width = Math.max( rectx2, prevrectx2 ) - x;
1439  var height = Math.max( recty2, prevrecty2 ) - y;
1440 
1441  /*
1442  // debug; draw zbuffer
1443 
1444  for ( var i = 0, l = zbuffer.length; i < l; i++ ) {
1445 
1446  var o = i * 4;
1447  var v = (65535 - zbuffer[ i ]) >> 3;
1448  data[ o + 0 ] = v;
1449  data[ o + 1 ] = v;
1450  data[ o + 2 ] = v;
1451  data[ o + 3 ] = 255;
1452  }
1453  */
1454 
1455  if ( x !== Infinity ) {
1456 
1457  context.putImageData( imagedata, 0, 0, x, y, width, height );
1458 
1459  }
1460 
1461  prevrectx1 = rectx1; prevrecty1 = recty1;
1462  prevrectx2 = rectx2; prevrecty2 = recty2;
1463 
1464  };
1465 
1466  function getAlpha() {
1467 
1468  return parameters.alpha === true ? clearAlpha : 1;
1469 
1470  }
1471 
1472  function clearColorBuffer( color ) {
1473 
1474  var size = canvasWidth * canvasHeight * 4;
1475 
1476  for ( var i = 0; i < size; i += 4 ) {
1477 
1478  data[ i ] = color.r * 255 | 0;
1479  data[ i + 1 ] = color.g * 255 | 0;
1480  data[ i + 2 ] = color.b * 255 | 0;
1481  data[ i + 3 ] = getAlpha() * 255 | 0;
1482 
1483  }
1484 
1485  context.fillStyle = 'rgba(' + ( ( clearColor.r * 255 ) | 0 ) + ',' + ( ( clearColor.g * 255 ) | 0 ) + ',' + ( ( clearColor.b * 255 ) | 0 ) + ',' + getAlpha() + ')';
1486  context.fillRect( 0, 0, canvasWidth, canvasHeight );
1487 
1488  }
1489 
1490  function getPalette( material, bSimulateSpecular ) {
1491 
1492  var i = 0, j = 0;
1493  var diffuseR = material.color.r * 255;
1494  var diffuseG = material.color.g * 255;
1495  var diffuseB = material.color.b * 255;
1496  var palette = new Uint8Array( 256 * 3 );
1497 
1498  if ( bSimulateSpecular ) {
1499 
1500  while ( i < 204 ) {
1501 
1502  palette[ j ++ ] = Math.min( i * diffuseR / 204, 255 );
1503  palette[ j ++ ] = Math.min( i * diffuseG / 204, 255 );
1504  palette[ j ++ ] = Math.min( i * diffuseB / 204, 255 );
1505  ++ i;
1506 
1507  }
1508 
1509  while ( i < 256 ) {
1510 
1511  // plus specular highlight
1512  palette[ j ++ ] = Math.min( diffuseR + ( i - 204 ) * ( 255 - diffuseR ) / 82, 255 );
1513  palette[ j ++ ] = Math.min( diffuseG + ( i - 204 ) * ( 255 - diffuseG ) / 82, 255 );
1514  palette[ j ++ ] = Math.min( diffuseB + ( i - 204 ) * ( 255 - diffuseB ) / 82, 255 );
1515  ++ i;
1516 
1517  }
1518 
1519  } else {
1520 
1521  while ( i < 256 ) {
1522 
1523  palette[ j ++ ] = Math.min( i * diffuseR / 255, 255 );
1524  palette[ j ++ ] = Math.min( i * diffuseG / 255, 255 );
1525  palette[ j ++ ] = Math.min( i * diffuseB / 255, 255 );
1526  ++ i;
1527 
1528  }
1529 
1530  }
1531 
1532  return palette;
1533 
1534  }
1535 
1536  function basicMaterialShader( buffer, depthBuf, offset, depth, u, v, n, face, material ) {
1537 
1538  var colorOffset = offset * 4;
1539 
1540  var texture = textures[ material.map.id ];
1541 
1542  if ( ! texture.data ) return;
1543 
1544  var tdim = texture.width;
1545  var isTransparent = material.transparent;
1546  var tbound = tdim - 1;
1547  var tdata = texture.data;
1548  var tIndex = ( ( ( v * tdim ) & tbound ) * tdim + ( ( u * tdim ) & tbound ) ) * 4;
1549 
1550  if ( ! isTransparent ) {
1551 
1552  buffer[ colorOffset ] = tdata[ tIndex ];
1553  buffer[ colorOffset + 1 ] = tdata[ tIndex + 1 ];
1554  buffer[ colorOffset + 2 ] = tdata[ tIndex + 2 ];
1555  buffer[ colorOffset + 3 ] = ( material.opacity << 8 ) - 1;
1556  depthBuf[ offset ] = depth;
1557 
1558  } else {
1559 
1560  var srcR = tdata[ tIndex ];
1561  var srcG = tdata[ tIndex + 1 ];
1562  var srcB = tdata[ tIndex + 2 ];
1563  var opaci = tdata[ tIndex + 3 ] * material.opacity / 255;
1564  var destR = buffer[ colorOffset ];
1565  var destG = buffer[ colorOffset + 1 ];
1566  var destB = buffer[ colorOffset + 2 ];
1567 
1568  buffer[ colorOffset ] = ( srcR * opaci + destR * ( 1 - opaci ) );
1569  buffer[ colorOffset + 1 ] = ( srcG * opaci + destG * ( 1 - opaci ) );
1570  buffer[ colorOffset + 2 ] = ( srcB * opaci + destB * ( 1 - opaci ) );
1571  buffer[ colorOffset + 3 ] = ( material.opacity << 8 ) - 1;
1572 
1573  // Only opaue pixls write to the depth buffer
1574 
1575  if ( buffer[ colorOffset + 3 ] == 255 ) depthBuf[ offset ] = depth;
1576 
1577  }
1578 
1579  }
1580 
1581  function lightingMaterialShader( buffer, depthBuf, offset, depth, u, v, n, face, material ) {
1582 
1583  var colorOffset = offset * 4;
1584 
1585  var texture = textures[ material.map.id ];
1586 
1587  if ( ! texture.data ) return;
1588 
1589  var tdim = texture.width;
1590  var isTransparent = material.transparent;
1591  var cIndex = ( n > 0 ? ( ~ ~ n ) : 0 ) * 3;
1592  var tbound = tdim - 1;
1593  var tdata = texture.data;
1594  var tIndex = ( ( ( v * tdim ) & tbound ) * tdim + ( ( u * tdim ) & tbound ) ) * 4;
1595 
1596  if ( ! isTransparent ) {
1597 
1598  buffer[ colorOffset ] = ( material.palette[ cIndex ] * tdata[ tIndex ] ) >> 8;
1599  buffer[ colorOffset + 1 ] = ( material.palette[ cIndex + 1 ] * tdata[ tIndex + 1 ] ) >> 8;
1600  buffer[ colorOffset + 2 ] = ( material.palette[ cIndex + 2 ] * tdata[ tIndex + 2 ] ) >> 8;
1601  buffer[ colorOffset + 3 ] = ( material.opacity << 8 ) - 1;
1602  depthBuf[ offset ] = depth;
1603 
1604  } else {
1605 
1606  var foreColorR = material.palette[ cIndex ] * tdata[ tIndex ];
1607  var foreColorG = material.palette[ cIndex + 1 ] * tdata[ tIndex + 1 ];
1608  var foreColorB = material.palette[ cIndex + 2 ] * tdata[ tIndex + 2 ];
1609  var opaci = tdata[ tIndex + 3 ] * material.opacity / 256;
1610  var destR = buffer[ colorOffset ];
1611  var destG = buffer[ colorOffset + 1 ];
1612  var destB = buffer[ colorOffset + 2 ];
1613 
1614  buffer[ colorOffset ] = foreColorR * opaci + destR * ( 1 - opaci );
1615  buffer[ colorOffset + 1 ] = foreColorG * opaci + destG * ( 1 - opaci );
1616  buffer[ colorOffset + 2 ] = foreColorB * opaci + destB * ( 1 - opaci );
1617  buffer[ colorOffset + 3 ] = ( material.opacity << 8 ) - 1;
1618 
1619  // Only opaue pixls write to the depth buffer
1620 
1621  if ( buffer[ colorOffset + 3 ] == 255 ) depthBuf[ offset ] = depth;
1622 
1623  }
1624 
1625  }
1626 
1627  function getMaterialShader( material ) {
1628 
1629  var id = material.id;
1630  var shader = shaders[ id ];
1631 
1632  if ( shader && material.map && ! textures[ material.map.id ] ) delete shaders[ id ];
1633 
1634  if ( shaders[ id ] === undefined || material.needsUpdate === true ) {
1635 
1636  if ( material instanceof THREE.MeshBasicMaterial ||
1637  material instanceof THREE.MeshLambertMaterial ||
1638  material instanceof THREE.MeshPhongMaterial ||
1639  material instanceof THREE.SpriteMaterial ) {
1640 
1641  if ( material instanceof THREE.MeshLambertMaterial ) {
1642 
1643  // Generate color palette
1644  if ( ! material.palette ) {
1645 
1646  material.palette = getPalette( material, false );
1647 
1648  }
1649 
1650  } else if ( material instanceof THREE.MeshPhongMaterial ) {
1651 
1652  // Generate color palette
1653  if ( ! material.palette ) {
1654 
1655  material.palette = getPalette( material, true );
1656 
1657  }
1658 
1659  }
1660 
1661  var string;
1662 
1663  if ( material.map ) {
1664 
1665  var texture = new THREE.SoftwareRenderer.Texture();
1666  texture.fromImage( material.map.image );
1667 
1668  if ( ! texture.data ) return;
1669 
1670  textures[ material.map.id ] = texture;
1671 
1672  if ( material instanceof THREE.MeshBasicMaterial
1673  || material instanceof THREE.SpriteMaterial ) {
1674 
1675  shader = basicMaterialShader;
1676 
1677  } else {
1678 
1679  shader = lightingMaterialShader;
1680 
1681  }
1682 
1683 
1684  } else {
1685 
1686  if ( material.vertexColors === THREE.FaceColors || material.vertexColors === THREE.VertexColors ) {
1687 
1688  string = [
1689  'var colorOffset = offset * 4;',
1690  'buffer[ colorOffset ] = face.color.r * 255;',
1691  'buffer[ colorOffset + 1 ] = face.color.g * 255;',
1692  'buffer[ colorOffset + 2 ] = face.color.b * 255;',
1693  'buffer[ colorOffset + 3 ] = material.opacity * 255;',
1694  'depthBuf[ offset ] = depth;'
1695  ].join( '\n' );
1696 
1697  } else {
1698 
1699  string = [
1700  'var colorOffset = offset * 4;',
1701  'buffer[ colorOffset ] = material.color.r * 255;',
1702  'buffer[ colorOffset + 1 ] = material.color.g * 255;',
1703  'buffer[ colorOffset + 2 ] = material.color.b * 255;',
1704  'buffer[ colorOffset + 3 ] = material.opacity * 255;',
1705  'depthBuf[ offset ] = depth;'
1706  ].join( '\n' );
1707 
1708  }
1709 
1710  shader = new Function( 'buffer, depthBuf, offset, depth, u, v, n, face, material', string );
1711 
1712  }
1713 
1714  } else if ( material instanceof THREE.LineBasicMaterial ) {
1715 
1716  var string = [
1717  'var colorOffset = offset * 4;',
1718  'buffer[ colorOffset ] = material.color.r * (color1.r+color2.r) * 0.5 * 255;',
1719  'buffer[ colorOffset + 1 ] = material.color.g * (color1.g+color2.g) * 0.5 * 255;',
1720  'buffer[ colorOffset + 2 ] = material.color.b * (color1.b+color2.b) * 0.5 * 255;',
1721  'buffer[ colorOffset + 3 ] = 255;',
1722  'depthBuf[ offset ] = depth;'
1723  ].join( '\n' );
1724 
1725  shader = new Function( 'buffer, depthBuf, offset, depth, color1, color2, material', string );
1726 
1727  } else {
1728 
1729  var string = [
1730  'var colorOffset = offset * 4;',
1731  'buffer[ colorOffset ] = u * 255;',
1732  'buffer[ colorOffset + 1 ] = v * 255;',
1733  'buffer[ colorOffset + 2 ] = 0;',
1734  'buffer[ colorOffset + 3 ] = 255;',
1735  'depthBuf[ offset ] = depth;'
1736  ].join( '\n' );
1737 
1738  shader = new Function( 'buffer, depthBuf, offset, depth, u, v, n, face, material', string );
1739 
1740  }
1741 
1742  shaders[ id ] = shader;
1743 
1744  material.needsUpdate = false;
1745 
1746  }
1747 
1748  return shader;
1749 
1750  }
1751 
1752  /*
1753  function clearRectangle( x1, y1, x2, y2 ) {
1754 
1755  var xmin = Math.max( Math.min( x1, x2 ), 0 );
1756  var xmax = Math.min( Math.max( x1, x2 ), canvasWidth );
1757  var ymin = Math.max( Math.min( y1, y2 ), 0 );
1758  var ymax = Math.min( Math.max( y1, y2 ), canvasHeight );
1759 
1760  var offset = ( xmin + ymin * canvasWidth ) * 4 + 3;
1761  var linestep = ( canvasWidth - ( xmax - xmin ) ) * 4;
1762 
1763  for ( var y = ymin; y < ymax; y ++ ) {
1764 
1765  for ( var x = xmin; x < xmax; x ++ ) {
1766 
1767  data[ offset += 4 ] = 0;
1768 
1769  }
1770 
1771  offset += linestep;
1772 
1773  }
1774 
1775  }
1776  */
1777 
1778  function drawTriangle( v1, v2, v3, uv1, uv2, uv3, shader, face, material ) {
1779 
1780  // TODO: Implement per-pixel z-clipping
1781 
1782  if ( v1.z < - 1 || v1.z > 1 || v2.z < - 1 || v2.z > 1 || v3.z < - 1 || v3.z > 1 ) return;
1783 
1784  // https://gist.github.com/2486101
1785  // explanation: http://pouet.net/topic.php?which=8760&page=1
1786 
1787  var fixscale = ( 1 << subpixelBits );
1788 
1789  // 28.4 fixed-point coordinates
1790 
1791  var x1 = ( v1.x * viewportXScale + viewportXOffs ) | 0;
1792  var x2 = ( v2.x * viewportXScale + viewportXOffs ) | 0;
1793  var x3 = ( v3.x * viewportXScale + viewportXOffs ) | 0;
1794 
1795  var y1 = ( v1.y * viewportYScale + viewportYOffs ) | 0;
1796  var y2 = ( v2.y * viewportYScale + viewportYOffs ) | 0;
1797  var y3 = ( v3.y * viewportYScale + viewportYOffs ) | 0;
1798 
1799  var bHasNormal = face.vertexNormalsModel && face.vertexNormalsModel.length;
1800  var bHasUV = uv1 && uv2 && uv3;
1801 
1802  var longestSide = Math.max(
1803  Math.sqrt( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) ),
1804  Math.sqrt( ( x2 - x3 ) * ( x2 - x3 ) + ( y2 - y3 ) * ( y2 - y3 ) ),
1805  Math.sqrt( ( x3 - x1 ) * ( x3 - x1 ) + ( y3 - y1 ) * ( y3 - y1 ) )
1806  );
1807 
1808  if ( ! ( face instanceof THREE.RenderableSprite ) && ( longestSide > 100 * fixscale ) ) {
1809 
1810  // 1
1811  // |\
1812  // |a\
1813  // |__\
1814  // |\c|\
1815  // |b\|d\
1816  // |__\__\
1817  // 2 3
1818  var tempFace = { vertexNormalsModel: [], color: face.color };
1819  var mpUV12, mpUV23, mpUV31;
1820 
1821  if ( bHasUV ) {
1822 
1823  if ( mpUVPoolCount === mpUVPool.length ) {
1824 
1825  mpUV12 = new THREE.Vector2();
1826  mpUVPool.push( mpUV12 );
1827  ++ mpUVPoolCount;
1828 
1829  mpUV23 = new THREE.Vector2();
1830  mpUVPool.push( mpUV23 );
1831  ++ mpUVPoolCount;
1832 
1833  mpUV31 = new THREE.Vector2();
1834  mpUVPool.push( mpUV31 );
1835  ++ mpUVPoolCount;
1836 
1837  } else {
1838 
1839  mpUV12 = mpUVPool[ mpUVPoolCount ];
1840  ++ mpUVPoolCount;
1841 
1842  mpUV23 = mpUVPool[ mpUVPoolCount ];
1843  ++ mpUVPoolCount;
1844 
1845  mpUV31 = mpUVPool[ mpUVPoolCount ];
1846  ++ mpUVPoolCount;
1847 
1848  }
1849 
1850  var weight;
1851 
1852  weight = ( 1 + v2.z ) * ( v2.w / v1.w ) / ( 1 + v1.z );
1853  mpUV12.copy( uv1 ).multiplyScalar( weight ).add( uv2 ).multiplyScalar( 1 / ( weight + 1 ) );
1854 
1855  weight = ( 1 + v3.z ) * ( v3.w / v2.w ) / ( 1 + v2.z );
1856  mpUV23.copy( uv2 ).multiplyScalar( weight ).add( uv3 ).multiplyScalar( 1 / ( weight + 1 ) );
1857 
1858  weight = ( 1 + v1.z ) * ( v1.w / v3.w ) / ( 1 + v3.z );
1859  mpUV31.copy( uv3 ).multiplyScalar( weight ).add( uv1 ).multiplyScalar( 1 / ( weight + 1 ) );
1860 
1861  }
1862 
1863  var mpV12, mpV23, mpV31;
1864 
1865  if ( mpVPoolCount === mpVPool.length ) {
1866 
1867  mpV12 = new THREE.Vector4();
1868  mpVPool.push( mpV12 );
1869  ++ mpVPoolCount;
1870 
1871  mpV23 = new THREE.Vector4();
1872  mpVPool.push( mpV23 );
1873  ++ mpVPoolCount;
1874 
1875  mpV31 = new THREE.Vector4();
1876  mpVPool.push( mpV31 );
1877  ++ mpVPoolCount;
1878 
1879  } else {
1880 
1881  mpV12 = mpVPool[ mpVPoolCount ];
1882  ++ mpVPoolCount;
1883 
1884  mpV23 = mpVPool[ mpVPoolCount ];
1885  ++ mpVPoolCount;
1886 
1887  mpV31 = mpVPool[ mpVPoolCount ];
1888  ++ mpVPoolCount;
1889 
1890  }
1891 
1892  mpV12.copy( v1 ).add( v2 ).multiplyScalar( 0.5 );
1893  mpV23.copy( v2 ).add( v3 ).multiplyScalar( 0.5 );
1894  mpV31.copy( v3 ).add( v1 ).multiplyScalar( 0.5 );
1895 
1896  var mpN12, mpN23, mpN31;
1897 
1898  if ( bHasNormal ) {
1899 
1900  if ( mpNPoolCount === mpNPool.length ) {
1901 
1902  mpN12 = new THREE.Vector3();
1903  mpNPool.push( mpN12 );
1904  ++ mpNPoolCount;
1905 
1906  mpN23 = new THREE.Vector3();
1907  mpNPool.push( mpN23 );
1908  ++ mpNPoolCount;
1909 
1910  mpN31 = new THREE.Vector3();
1911  mpNPool.push( mpN31 );
1912  ++ mpNPoolCount;
1913 
1914  } else {
1915 
1916  mpN12 = mpNPool[ mpNPoolCount ];
1917  ++ mpNPoolCount;
1918 
1919  mpN23 = mpNPool[ mpNPoolCount ];
1920  ++ mpNPoolCount;
1921 
1922  mpN31 = mpNPool[ mpNPoolCount ];
1923  ++ mpNPoolCount;
1924 
1925  }
1926 
1927  mpN12.copy( face.vertexNormalsModel[ 0 ] ).add( face.vertexNormalsModel[ 1 ] ).normalize();
1928  mpN23.copy( face.vertexNormalsModel[ 1 ] ).add( face.vertexNormalsModel[ 2 ] ).normalize();
1929  mpN31.copy( face.vertexNormalsModel[ 2 ] ).add( face.vertexNormalsModel[ 0 ] ).normalize();
1930 
1931  }
1932 
1933  // a
1934  if ( bHasNormal ) {
1935 
1936  tempFace.vertexNormalsModel[ 0 ] = face.vertexNormalsModel[ 0 ];
1937  tempFace.vertexNormalsModel[ 1 ] = mpN12;
1938  tempFace.vertexNormalsModel[ 2 ] = mpN31;
1939 
1940  }
1941 
1942  drawTriangle( v1, mpV12, mpV31, uv1, mpUV12, mpUV31, shader, tempFace, material );
1943 
1944  // b
1945  if ( bHasNormal ) {
1946 
1947  tempFace.vertexNormalsModel[ 0 ] = face.vertexNormalsModel[ 1 ];
1948  tempFace.vertexNormalsModel[ 1 ] = mpN23;
1949  tempFace.vertexNormalsModel[ 2 ] = mpN12;
1950 
1951  }
1952 
1953  drawTriangle( v2, mpV23, mpV12, uv2, mpUV23, mpUV12, shader, tempFace, material );
1954 
1955  // c
1956  if ( bHasNormal ) {
1957 
1958  tempFace.vertexNormalsModel[ 0 ] = mpN12;
1959  tempFace.vertexNormalsModel[ 1 ] = mpN23;
1960  tempFace.vertexNormalsModel[ 2 ] = mpN31;
1961 
1962  }
1963 
1964  drawTriangle( mpV12, mpV23, mpV31, mpUV12, mpUV23, mpUV31, shader, tempFace, material );
1965 
1966  // d
1967  if ( bHasNormal ) {
1968 
1969  tempFace.vertexNormalsModel[ 0 ] = face.vertexNormalsModel[ 2 ];
1970  tempFace.vertexNormalsModel[ 1 ] = mpN31;
1971  tempFace.vertexNormalsModel[ 2 ] = mpN23;
1972 
1973  }
1974 
1975  drawTriangle( v3, mpV31, mpV23, uv3, mpUV31, mpUV23, shader, tempFace, material );
1976 
1977  return;
1978 
1979  }
1980 
1981  // Z values (.28 fixed-point)
1982 
1983  var z1 = ( v1.z * viewportZScale + viewportZOffs ) | 0;
1984  var z2 = ( v2.z * viewportZScale + viewportZOffs ) | 0;
1985  var z3 = ( v3.z * viewportZScale + viewportZOffs ) | 0;
1986 
1987  // UV values
1988  var bHasUV = false;
1989  var tu1, tv1, tu2, tv2, tu3, tv3;
1990 
1991  if ( uv1 && uv2 && uv3 ) {
1992 
1993  bHasUV = true;
1994 
1995  tu1 = uv1.x;
1996  tv1 = 1 - uv1.y;
1997  tu2 = uv2.x;
1998  tv2 = 1 - uv2.y;
1999  tu3 = uv3.x;
2000  tv3 = 1 - uv3.y;
2001 
2002  }
2003 
2004  // Normal values
2005  var n1, n2, n3, nz1, nz2, nz3;
2006 
2007  if ( bHasNormal ) {
2008 
2009  n1 = face.vertexNormalsModel[ 0 ];
2010  n2 = face.vertexNormalsModel[ 1 ];
2011  n3 = face.vertexNormalsModel[ 2 ];
2012  nz1 = n1.z * 255;
2013  nz2 = n2.z * 255;
2014  nz3 = n3.z * 255;
2015 
2016  }
2017 
2018  // Deltas
2019 
2020  var dx12 = x1 - x2, dy12 = y2 - y1;
2021  var dx23 = x2 - x3, dy23 = y3 - y2;
2022  var dx31 = x3 - x1, dy31 = y1 - y3;
2023 
2024  // Bounding rectangle
2025 
2026  var minx = Math.max( ( Math.min( x1, x2, x3 ) + subpixelBias ) >> subpixelBits, 0 );
2027  var maxx = Math.min( ( Math.max( x1, x2, x3 ) + subpixelBias ) >> subpixelBits, canvasWidth );
2028  var miny = Math.max( ( Math.min( y1, y2, y3 ) + subpixelBias ) >> subpixelBits, 0 );
2029  var maxy = Math.min( ( Math.max( y1, y2, y3 ) + subpixelBias ) >> subpixelBits, canvasHeight );
2030 
2031  rectx1 = Math.min( minx, rectx1 );
2032  rectx2 = Math.max( maxx, rectx2 );
2033  recty1 = Math.min( miny, recty1 );
2034  recty2 = Math.max( maxy, recty2 );
2035 
2036  // Block size, standard 8x8 (must be power of two)
2037 
2038  var q = blockSize;
2039 
2040  // Start in corner of 8x8 block
2041 
2042  minx &= ~ ( q - 1 );
2043  miny &= ~ ( q - 1 );
2044 
2045  // Constant part of half-edge functions
2046 
2047  var minXfixscale = ( minx << subpixelBits );
2048  var minYfixscale = ( miny << subpixelBits );
2049 
2050  var c1 = dy12 * ( ( minXfixscale ) - x1 ) + dx12 * ( ( minYfixscale ) - y1 );
2051  var c2 = dy23 * ( ( minXfixscale ) - x2 ) + dx23 * ( ( minYfixscale ) - y2 );
2052  var c3 = dy31 * ( ( minXfixscale ) - x3 ) + dx31 * ( ( minYfixscale ) - y3 );
2053 
2054  // Correct for fill convention
2055 
2056  if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
2057  if ( dy23 > 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
2058  if ( dy31 > 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++;
2059 
2060  // Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0).
2061  // It's a bit subtle. :)
2062  c1 = ( c1 - 1 ) >> subpixelBits;
2063  c2 = ( c2 - 1 ) >> subpixelBits;
2064  c3 = ( c3 - 1 ) >> subpixelBits;
2065 
2066  // Z interpolation setup
2067 
2068  var dz12 = z1 - z2, dz31 = z3 - z1;
2069  var invDet = 1.0 / ( dx12 * dy31 - dx31 * dy12 );
2070  var dzdx = ( invDet * ( dz12 * dy31 - dz31 * dy12 ) ); // dz per one subpixel step in x
2071  var dzdy = ( invDet * ( dz12 * dx31 - dx12 * dz31 ) ); // dz per one subpixel step in y
2072 
2073  // Z at top/left corner of rast area
2074 
2075  var cz = ( z1 + ( ( minXfixscale ) - x1 ) * dzdx + ( ( minYfixscale ) - y1 ) * dzdy ) | 0;
2076 
2077  // Z pixel steps
2078 
2079  dzdx = ( dzdx * fixscale ) | 0;
2080  dzdy = ( dzdy * fixscale ) | 0;
2081 
2082  var dtvdx, dtvdy, cbtu, cbtv;
2083  if ( bHasUV ) {
2084 
2085  // UV interpolation setup
2086  var dtu12 = tu1 - tu2, dtu31 = tu3 - tu1;
2087  var dtudx = ( invDet * ( dtu12 * dy31 - dtu31 * dy12 ) ); // dtu per one subpixel step in x
2088  var dtudy = ( invDet * ( dtu12 * dx31 - dx12 * dtu31 ) ); // dtu per one subpixel step in y
2089  var dtv12 = tv1 - tv2, dtv31 = tv3 - tv1;
2090  dtvdx = ( invDet * ( dtv12 * dy31 - dtv31 * dy12 ) ); // dtv per one subpixel step in x
2091  dtvdy = ( invDet * ( dtv12 * dx31 - dx12 * dtv31 ) ); // dtv per one subpixel step in y
2092 
2093  // UV at top/left corner of rast area
2094  cbtu = ( tu1 + ( minXfixscale - x1 ) * dtudx + ( minYfixscale - y1 ) * dtudy );
2095  cbtv = ( tv1 + ( minXfixscale - x1 ) * dtvdx + ( minYfixscale - y1 ) * dtvdy );
2096 
2097  // UV pixel steps
2098  dtudx = dtudx * fixscale;
2099  dtudy = dtudy * fixscale;
2100  dtvdx = dtvdx * fixscale;
2101  dtvdy = dtvdy * fixscale;
2102 
2103  }
2104 
2105  var dnzdy, cbnz;
2106 
2107  if ( bHasNormal ) {
2108 
2109  // Normal interpolation setup
2110  var dnz12 = nz1 - nz2, dnz31 = nz3 - nz1;
2111  var dnzdx = ( invDet * ( dnz12 * dy31 - dnz31 * dy12 ) ); // dnz per one subpixel step in x
2112  var dnzdy = ( invDet * ( dnz12 * dx31 - dx12 * dnz31 ) ); // dnz per one subpixel step in y
2113 
2114  // Normal at top/left corner of rast area
2115  cbnz = ( nz1 + ( minXfixscale - x1 ) * dnzdx + ( minYfixscale - y1 ) * dnzdy );
2116 
2117  // Normal pixel steps
2118  dnzdx = ( dnzdx * fixscale );
2119  dnzdy = ( dnzdy * fixscale );
2120 
2121  }
2122 
2123  // Set up min/max corners
2124  var qm1 = q - 1; // for convenience
2125  var nmin1 = 0, nmax1 = 0;
2126  var nmin2 = 0, nmax2 = 0;
2127  var nmin3 = 0, nmax3 = 0;
2128  var nminz = 0, nmaxz = 0;
2129  if ( dx12 >= 0 ) nmax1 -= qm1 * dx12; else nmin1 -= qm1 * dx12;
2130  if ( dy12 >= 0 ) nmax1 -= qm1 * dy12; else nmin1 -= qm1 * dy12;
2131  if ( dx23 >= 0 ) nmax2 -= qm1 * dx23; else nmin2 -= qm1 * dx23;
2132  if ( dy23 >= 0 ) nmax2 -= qm1 * dy23; else nmin2 -= qm1 * dy23;
2133  if ( dx31 >= 0 ) nmax3 -= qm1 * dx31; else nmin3 -= qm1 * dx31;
2134  if ( dy31 >= 0 ) nmax3 -= qm1 * dy31; else nmin3 -= qm1 * dy31;
2135  if ( dzdx >= 0 ) nmaxz += qm1 * dzdx; else nminz += qm1 * dzdx;
2136  if ( dzdy >= 0 ) nmaxz += qm1 * dzdy; else nminz += qm1 * dzdy;
2137 
2138  // Loop through blocks
2139  var linestep = canvasWidth - q;
2140 
2141  var cb1 = c1;
2142  var cb2 = c2;
2143  var cb3 = c3;
2144  var cbz = cz;
2145  var qstep = - q;
2146  var e1x = qstep * dy12;
2147  var e2x = qstep * dy23;
2148  var e3x = qstep * dy31;
2149  var ezx = qstep * dzdx;
2150 
2151  var etux, etvx;
2152  if ( bHasUV ) {
2153 
2154  etux = qstep * dtudx;
2155  etvx = qstep * dtvdx;
2156 
2157  }
2158 
2159  var enzx;
2160  if ( bHasNormal ) {
2161 
2162  enzx = qstep * dnzdx;
2163 
2164  }
2165 
2166  var x0 = minx;
2167 
2168  for ( var y0 = miny; y0 < maxy; y0 += q ) {
2169 
2170  // New block line - keep hunting for tri outer edge in old block line dir
2171  while ( x0 >= minx && x0 < maxx && cb1 >= nmax1 && cb2 >= nmax2 && cb3 >= nmax3 ) {
2172 
2173  x0 += qstep;
2174  cb1 += e1x;
2175  cb2 += e2x;
2176  cb3 += e3x;
2177  cbz += ezx;
2178 
2179  if ( bHasUV ) {
2180 
2181  cbtu += etux;
2182  cbtv += etvx;
2183 
2184  }
2185 
2186  if ( bHasNormal ) {
2187 
2188  cbnz += enzx;
2189 
2190  }
2191 
2192  }
2193 
2194  // Okay, we're now in a block we know is outside. Reverse direction and go into main loop.
2195  qstep = - qstep;
2196  e1x = - e1x;
2197  e2x = - e2x;
2198  e3x = - e3x;
2199  ezx = - ezx;
2200 
2201  if ( bHasUV ) {
2202 
2203  etux = - etux;
2204  etvx = - etvx;
2205 
2206  }
2207 
2208  if ( bHasNormal ) {
2209 
2210  enzx = - enzx;
2211 
2212  }
2213 
2214  while ( 1 ) {
2215 
2216  // Step everything
2217  x0 += qstep;
2218  cb1 += e1x;
2219  cb2 += e2x;
2220  cb3 += e3x;
2221  cbz += ezx;
2222 
2223  if ( bHasUV ) {
2224 
2225  cbtu += etux;
2226  cbtv += etvx;
2227 
2228  }
2229 
2230  if ( bHasNormal ) {
2231 
2232  cbnz += enzx;
2233 
2234  }
2235 
2236  // We're done with this block line when at least one edge completely out
2237  // If an edge function is too small and decreasing in the current traversal
2238  // dir, we're done with this line.
2239  if ( x0 < minx || x0 >= maxx ) break;
2240  if ( cb1 < nmax1 ) if ( e1x < 0 ) break; else continue;
2241  if ( cb2 < nmax2 ) if ( e2x < 0 ) break; else continue;
2242  if ( cb3 < nmax3 ) if ( e3x < 0 ) break; else continue;
2243 
2244  // We can skip this block if it's already fully covered
2245  var blockX = x0 >> blockShift;
2246  var blockY = y0 >> blockShift;
2247  var blockId = blockX + blockY * canvasWBlocks;
2248  var minz = cbz + nminz;
2249 
2250  // farthest point in block closer than closest point in our tri?
2251  if ( blockMaxZ[ blockId ] < minz ) continue;
2252 
2253  // Need to do a deferred clear?
2254  var bflags = blockFlags[ blockId ];
2255  if ( bflags & BLOCK_NEEDCLEAR ) clearBlock( blockX, blockY );
2256  blockFlags[ blockId ] = bflags & ~ ( BLOCK_ISCLEAR | BLOCK_NEEDCLEAR );
2257 
2258  // Offset at top-left corner
2259  var offset = x0 + y0 * canvasWidth;
2260 
2261  // Accept whole block when fully covered
2262  if ( cb1 >= nmin1 && cb2 >= nmin2 && cb3 >= nmin3 ) {
2263 
2264  var maxz = cbz + nmaxz;
2265  blockMaxZ[ blockId ] = Math.min( blockMaxZ[ blockId ], maxz );
2266 
2267  var cy1 = cb1;
2268  var cy2 = cb2;
2269  var cyz = cbz;
2270 
2271  var cytu, cytv;
2272  if ( bHasUV ) {
2273 
2274  cytu = cbtu;
2275  cytv = cbtv;
2276 
2277  }
2278 
2279  var cynz;
2280  if ( bHasNormal ) {
2281 
2282  cynz = cbnz;
2283 
2284  }
2285 
2286 
2287  for ( var iy = 0; iy < q; iy ++ ) {
2288 
2289  var cx1 = cy1;
2290  var cx2 = cy2;
2291  var cxz = cyz;
2292 
2293  var cxtu;
2294  var cxtv;
2295  if ( bHasUV ) {
2296 
2297  cxtu = cytu;
2298  cxtv = cytv;
2299 
2300  }
2301 
2302  var cxnz;
2303  if ( bHasNormal ) {
2304 
2305  cxnz = cynz;
2306 
2307  }
2308 
2309  for ( var ix = 0; ix < q; ix ++ ) {
2310 
2311  var z = cxz;
2312 
2313  if ( z < zbuffer[ offset ] ) {
2314 
2315  shader( data, zbuffer, offset, z, cxtu, cxtv, cxnz, face, material );
2316 
2317  }
2318 
2319  cx1 += dy12;
2320  cx2 += dy23;
2321  cxz += dzdx;
2322 
2323  if ( bHasUV ) {
2324 
2325  cxtu += dtudx;
2326  cxtv += dtvdx;
2327 
2328  }
2329 
2330  if ( bHasNormal ) {
2331 
2332  cxnz += dnzdx;
2333 
2334  }
2335 
2336  offset ++;
2337 
2338  }
2339 
2340  cy1 += dx12;
2341  cy2 += dx23;
2342  cyz += dzdy;
2343 
2344  if ( bHasUV ) {
2345 
2346  cytu += dtudy;
2347  cytv += dtvdy;
2348 
2349  }
2350 
2351  if ( bHasNormal ) {
2352 
2353  cynz += dnzdy;
2354 
2355  }
2356 
2357  offset += linestep;
2358 
2359  }
2360 
2361  } else {
2362 
2363  // Partially covered block
2364 
2365  var cy1 = cb1;
2366  var cy2 = cb2;
2367  var cy3 = cb3;
2368  var cyz = cbz;
2369 
2370  var cytu, cytv;
2371  if ( bHasUV ) {
2372 
2373  cytu = cbtu;
2374  cytv = cbtv;
2375 
2376  }
2377 
2378  var cynz;
2379  if ( bHasNormal ) {
2380 
2381  cynz = cbnz;
2382 
2383  }
2384 
2385  for ( var iy = 0; iy < q; iy ++ ) {
2386 
2387  var cx1 = cy1;
2388  var cx2 = cy2;
2389  var cx3 = cy3;
2390  var cxz = cyz;
2391 
2392  var cxtu;
2393  var cxtv;
2394  if ( bHasUV ) {
2395 
2396  cxtu = cytu;
2397  cxtv = cytv;
2398 
2399  }
2400 
2401  var cxnz;
2402  if ( bHasNormal ) {
2403 
2404  cxnz = cynz;
2405 
2406  }
2407 
2408  for ( var ix = 0; ix < q; ix ++ ) {
2409 
2410  if ( ( cx1 | cx2 | cx3 ) >= 0 ) {
2411 
2412  var z = cxz;
2413 
2414  if ( z < zbuffer[ offset ] ) {
2415 
2416  shader( data, zbuffer, offset, z, cxtu, cxtv, cxnz, face, material );
2417 
2418  }
2419 
2420  }
2421 
2422  cx1 += dy12;
2423  cx2 += dy23;
2424  cx3 += dy31;
2425  cxz += dzdx;
2426 
2427  if ( bHasUV ) {
2428 
2429  cxtu += dtudx;
2430  cxtv += dtvdx;
2431 
2432  }
2433 
2434  if ( bHasNormal ) {
2435 
2436  cxnz += dnzdx;
2437 
2438  }
2439 
2440  offset ++;
2441 
2442  }
2443 
2444  cy1 += dx12;
2445  cy2 += dx23;
2446  cy3 += dx31;
2447  cyz += dzdy;
2448 
2449  if ( bHasUV ) {
2450 
2451  cytu += dtudy;
2452  cytv += dtvdy;
2453 
2454  }
2455 
2456  if ( bHasNormal ) {
2457 
2458  cynz += dnzdy;
2459 
2460  }
2461 
2462  offset += linestep;
2463 
2464  }
2465 
2466  }
2467 
2468  }
2469 
2470  // Advance to next row of blocks
2471  cb1 += q * dx12;
2472  cb2 += q * dx23;
2473  cb3 += q * dx31;
2474  cbz += q * dzdy;
2475 
2476  if ( bHasUV ) {
2477 
2478  cbtu += q * dtudy;
2479  cbtv += q * dtvdy;
2480 
2481  }
2482 
2483  if ( bHasNormal ) {
2484 
2485  cbnz += q * dnzdy;
2486 
2487  }
2488 
2489  }
2490 
2491  }
2492 
2493  // When drawing line, the blockShiftShift has to be zero. In order to clean pixel
2494  // Using color1 and color2 to interpolation pixel color
2495  // LineWidth is according to material.linewidth
2496  function drawLine( v1, v2, color1, color2, shader, material ) {
2497 
2498  // While the line mode is enable, blockSize has to be changed to 0.
2499  if ( ! lineMode ) {
2500 
2501  lineMode = true;
2502  blockShift = 0;
2503  blockSize = 1 << blockShift;
2504 
2505  _this.setSize( canvas.width, canvas.height );
2506 
2507  }
2508 
2509  // TODO: Implement per-pixel z-clipping
2510  if ( v1.z < - 1 || v1.z > 1 || v2.z < - 1 || v2.z > 1 ) return;
2511 
2512  var halfLineWidth = Math.floor( ( material.linewidth - 1 ) * 0.5 );
2513 
2514  // https://gist.github.com/2486101
2515  // explanation: http://pouet.net/topic.php?which=8760&page=1
2516 
2517  // 28.4 fixed-point coordinates
2518  var x1 = ( v1.x * viewportXScale + viewportXOffs ) | 0;
2519  var x2 = ( v2.x * viewportXScale + viewportXOffs ) | 0;
2520 
2521  var y1 = ( v1.y * viewportYScale + viewportYOffs ) | 0;
2522  var y2 = ( v2.y * viewportYScale + viewportYOffs ) | 0;
2523 
2524  var z1 = ( v1.z * viewportZScale + viewportZOffs ) | 0;
2525  var z2 = ( v2.z * viewportZScale + viewportZOffs ) | 0;
2526 
2527  // Deltas
2528  var dx12 = x1 - x2, dy12 = y1 - y2, dz12 = z1 - z2;
2529 
2530  // Bounding rectangle
2531  var minx = Math.max( ( Math.min( x1, x2 ) + subpixelBias ) >> subpixelBits, 0 );
2532  var maxx = Math.min( ( Math.max( x1, x2 ) + subpixelBias ) >> subpixelBits, canvasWidth );
2533  var miny = Math.max( ( Math.min( y1, y2 ) + subpixelBias ) >> subpixelBits, 0 );
2534  var maxy = Math.min( ( Math.max( y1, y2 ) + subpixelBias ) >> subpixelBits, canvasHeight );
2535  var minz = Math.max( ( Math.min( z1, z2 ) + subpixelBias ) >> subpixelBits, 0 );
2536  var maxz = ( Math.max( z1, z2 ) + subpixelBias ) >> subpixelBits;
2537 
2538  rectx1 = Math.min( minx, rectx1 );
2539  rectx2 = Math.max( maxx, rectx2 );
2540  recty1 = Math.min( miny, recty1 );
2541  recty2 = Math.max( maxy, recty2 );
2542 
2543  // Get the line's unit vector and cross vector
2544  var length = Math.sqrt( ( dy12 * dy12 ) + ( dx12 * dx12 ) );
2545  var unitX = ( dx12 / length );
2546  var unitY = ( dy12 / length );
2547  var unitZ = ( dz12 / length );
2548  var pixelX, pixelY, pixelZ;
2549  var pX, pY, pZ;
2550  crossVector.set( unitX, unitY, unitZ );
2551  crossVector.cross( lookVector );
2552  crossVector.normalize();
2553 
2554  while ( length > 0 ) {
2555 
2556  // Get this pixel.
2557  pixelX = x2 + length * unitX;
2558  pixelY = y2 + length * unitY;
2559  pixelZ = z2 + length * unitZ;
2560 
2561  pixelX = ( pixelX + subpixelBias ) >> subpixelBits;
2562  pixelY = ( pixelY + subpixelBias ) >> subpixelBits;
2563  pZ = ( pixelZ + subpixelBias ) >> subpixelBits;
2564 
2565  // Draw line with line width
2566  for ( var i = - halfLineWidth; i <= halfLineWidth; ++ i ) {
2567 
2568  // Compute the line pixels.
2569  // Get the pixels on the vector that crosses to the line vector
2570  pX = Math.floor( ( pixelX + crossVector.x * i ) );
2571  pY = Math.floor( ( pixelY + crossVector.y * i ) );
2572 
2573  // if pixel is over the rect. Continue
2574  if ( rectx1 >= pX || rectx2 <= pX || recty1 >= pY || recty2 <= pY )
2575  continue;
2576 
2577  // Find this pixel at which block
2578  var blockX = pX >> blockShift;
2579  var blockY = pY >> blockShift;
2580  var blockId = blockX + blockY * canvasWBlocks;
2581 
2582  // Compare the pixel depth width z block.
2583  if ( blockMaxZ[ blockId ] < minz ) continue;
2584 
2585  blockMaxZ[ blockId ] = Math.min( blockMaxZ[ blockId ], maxz );
2586 
2587  var bflags = blockFlags[ blockId ];
2588  if ( bflags & BLOCK_NEEDCLEAR ) clearBlock( blockX, blockY );
2589  blockFlags[ blockId ] = bflags & ~ ( BLOCK_ISCLEAR | BLOCK_NEEDCLEAR );
2590 
2591  // draw pixel
2592  var offset = pX + pY * canvasWidth;
2593 
2594  if ( pZ < zbuffer[ offset ] ) {
2595 
2596  shader( data, zbuffer, offset, pZ, color1, color2, material );
2597 
2598  }
2599 
2600  }
2601 
2602  -- length;
2603 
2604  }
2605 
2606  }
2607 
2608  function clearBlock( blockX, blockY ) {
2609 
2610  var zoffset = blockX * blockSize + blockY * blockSize * canvasWidth;
2611  var poffset = zoffset * 4;
2612 
2613  var zlinestep = canvasWidth - blockSize;
2614  var plinestep = zlinestep * 4;
2615 
2616  for ( var y = 0; y < blockSize; y ++ ) {
2617 
2618  for ( var x = 0; x < blockSize; x ++ ) {
2619 
2620  zbuffer[ zoffset ++ ] = maxZVal;
2621 
2622  data[ poffset ++ ] = clearColor.r * 255 | 0;
2623  data[ poffset ++ ] = clearColor.g * 255 | 0;
2624  data[ poffset ++ ] = clearColor.b * 255 | 0;
2625  data[ poffset ++ ] = getAlpha() * 255 | 0;
2626 
2627  }
2628 
2629  zoffset += zlinestep;
2630  poffset += plinestep;
2631 
2632  }
2633 
2634  }
2635 
2636  function finishClear( ) {
2637 
2638  var block = 0;
2639 
2640  for ( var y = 0; y < canvasHBlocks; y ++ ) {
2641 
2642  for ( var x = 0; x < canvasWBlocks; x ++ ) {
2643 
2644  if ( blockFlags[ block ] & BLOCK_NEEDCLEAR ) {
2645 
2646  clearBlock( x, y );
2647  blockFlags[ block ] = BLOCK_ISCLEAR;
2648 
2649  }
2650 
2651  block ++;
2652 
2653  }
2654 
2655  }
2656 
2657  }
2658 
2659 };
2660 
2661 THREE.SoftwareRenderer.Texture = function () {
2662 
2663  var canvas;
2664 
2665  this.fromImage = function ( image ) {
2666 
2667  if ( ! image || image.width <= 0 || image.height <= 0 )
2668  return;
2669 
2670  if ( canvas === undefined ) {
2671 
2672  canvas = document.createElement( 'canvas' );
2673 
2674  }
2675 
2676  var size = image.width > image.height ? image.width : image.height;
2677  size = THREE.Math.ceilPowerOfTwo( size );
2678 
2679  if ( canvas.width != size || canvas.height != size ) {
2680 
2681  canvas.width = size;
2682  canvas.height = size;
2683 
2684  }
2685 
2686  var ctx = canvas.getContext( '2d' );
2687  ctx.clearRect( 0, 0, size, size );
2688  ctx.drawImage( image, 0, 0, size, size );
2689 
2690  var imgData = ctx.getImageData( 0, 0, size, size );
2691 
2692  this.data = imgData.data;
2693  this.width = size;
2694  this.height = size;
2695  this.srcUrl = image.src;
2696 
2697  };
2698 
2699 };
2700 
2701 // wrapper for THREE.SVGRenderer trying to optimize creation of many small SVG elements
2702 
2703 THREE.CreateSVGRenderer = function(as_is, precision, doc) {
2704 
2705  function Create(document) {
2706 
2707 // now include original THREE.SVGRenderer
2708 //
2713 THREE.SVGObject = function ( node ) {
2714 
2715  THREE.Object3D.call( this );
2716 
2717  this.node = node;
2718 
2719 };
2720 
2721 THREE.SVGObject.prototype = Object.create( THREE.Object3D.prototype );
2722 THREE.SVGObject.prototype.constructor = THREE.SVGObject;
2723 
2724 THREE.SVGRenderer = function () {
2725 
2726  console.log( 'THREE.SVGRenderer', THREE.REVISION );
2727 
2728  var _this = this,
2729  _renderData, _elements, _lights,
2730  _projector = new THREE.Projector(),
2731  _svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ),
2732  _svgWidth, _svgHeight, _svgWidthHalf, _svgHeightHalf,
2733 
2734  _v1, _v2, _v3,
2735 
2736  _clipBox = new THREE.Box2(),
2737  _elemBox = new THREE.Box2(),
2738 
2739  _color = new THREE.Color(),
2740  _diffuseColor = new THREE.Color(),
2741  _ambientLight = new THREE.Color(),
2742  _directionalLights = new THREE.Color(),
2743  _pointLights = new THREE.Color(),
2744  _clearColor = new THREE.Color(),
2745  _clearAlpha = 1,
2746 
2747  _vector3 = new THREE.Vector3(), // Needed for PointLight
2748  _centroid = new THREE.Vector3(),
2749  _normal = new THREE.Vector3(),
2750  _normalViewMatrix = new THREE.Matrix3(),
2751 
2752  _viewMatrix = new THREE.Matrix4(),
2753  _viewProjectionMatrix = new THREE.Matrix4(),
2754 
2755  _svgPathPool = [],
2756  _svgNode, _pathCount = 0,
2757 
2758  _currentPath, _currentStyle,
2759 
2760  _quality = 1, _precision = null;
2761 
2762  this.domElement = _svg;
2763 
2764  this.autoClear = true;
2765  this.sortObjects = true;
2766  this.sortElements = true;
2767 
2768  this.info = {
2769 
2770  render: {
2771 
2772  vertices: 0,
2773  faces: 0
2774 
2775  }
2776 
2777  };
2778 
2779  this.setQuality = function ( quality ) {
2780 
2781  switch ( quality ) {
2782 
2783  case "high": _quality = 1; break;
2784  case "low": _quality = 0; break;
2785 
2786  }
2787 
2788  };
2789 
2790  this.setClearColor = function ( color, alpha ) {
2791 
2792  _clearColor.set( color );
2793  _clearAlpha = alpha !== undefined ? alpha : 1;
2794 
2795  };
2796 
2797  this.setPixelRatio = function () {};
2798 
2799  this.setSize = function ( width, height ) {
2800 
2801  _svgWidth = width; _svgHeight = height;
2802  _svgWidthHalf = _svgWidth / 2; _svgHeightHalf = _svgHeight / 2;
2803 
2804  _svg.setAttribute( 'viewBox', ( - _svgWidthHalf ) + ' ' + ( - _svgHeightHalf ) + ' ' + _svgWidth + ' ' + _svgHeight );
2805  _svg.setAttribute( 'width', _svgWidth );
2806  _svg.setAttribute( 'height', _svgHeight );
2807 
2808  _clipBox.min.set( - _svgWidthHalf, - _svgHeightHalf );
2809  _clipBox.max.set( _svgWidthHalf, _svgHeightHalf );
2810 
2811  };
2812 
2813  this.setPrecision = function ( precision ) {
2814 
2815  _precision = precision;
2816 
2817  };
2818 
2819  function removeChildNodes() {
2820 
2821  _pathCount = 0;
2822 
2823  while ( _svg.childNodes.length > 0 ) {
2824 
2825  _svg.removeChild( _svg.childNodes[ 0 ] );
2826 
2827  }
2828 
2829  }
2830 
2831  function getSvgColor( color, opacity ) {
2832 
2833  var arg = Math.floor( color.r * 255 ) + ',' + Math.floor( color.g * 255 ) + ',' + Math.floor( color.b * 255 );
2834 
2835  if ( opacity === undefined || opacity === 1 ) return 'rgb(' + arg + ')';
2836 
2837  return 'rgb(' + arg + '); fill-opacity: ' + opacity;
2838 
2839  }
2840 
2841  function convert( c ) {
2842 
2843  return _precision !== null ? c.toFixed( _precision ) : c;
2844 
2845  }
2846 
2847  this.clear = function () {
2848 
2849  removeChildNodes();
2850  _svg.style.backgroundColor = getSvgColor( _clearColor, _clearAlpha );
2851 
2852  };
2853 
2854  this.render = function ( scene, camera ) {
2855 
2856  if ( camera instanceof THREE.Camera === false ) {
2857 
2858  console.error( 'THREE.SVGRenderer.render: camera is not an instance of THREE.Camera.' );
2859  return;
2860 
2861  }
2862 
2863  var background = scene.background;
2864 
2865  if ( background && background.isColor ) {
2866 
2867  removeChildNodes();
2868  _svg.style.backgroundColor = getSvgColor( background );
2869 
2870  } else if ( this.autoClear === true ) {
2871 
2872  this.clear();
2873 
2874  }
2875 
2876  _this.info.render.vertices = 0;
2877  _this.info.render.faces = 0;
2878 
2879  _viewMatrix.copy( camera.matrixWorldInverse );
2880  _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
2881 
2882  _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
2883  _elements = _renderData.elements;
2884  _lights = _renderData.lights;
2885 
2886  _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );
2887 
2888  calculateLights( _lights );
2889 
2890  // reset accumulated path
2891 
2892  _currentPath = '';
2893  _currentStyle = '';
2894 
2895  for ( var e = 0, el = _elements.length; e < el; e ++ ) {
2896 
2897  var element = _elements[ e ];
2898  var material = element.material;
2899 
2900  if ( material === undefined || material.opacity === 0 ) continue;
2901 
2902  _elemBox.makeEmpty();
2903 
2904  if ( element instanceof THREE.RenderableSprite ) {
2905 
2906  _v1 = element;
2907  _v1.x *= _svgWidthHalf; _v1.y *= - _svgHeightHalf;
2908 
2909  renderSprite( _v1, element, material );
2910 
2911  } else if ( element instanceof THREE.RenderableLine ) {
2912 
2913  _v1 = element.v1; _v2 = element.v2;
2914 
2915  _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf;
2916  _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf;
2917 
2918  _elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen ] );
2919 
2920  if ( _clipBox.intersectsBox( _elemBox ) === true ) {
2921 
2922  renderLine( _v1, _v2, element, material );
2923 
2924  }
2925 
2926  } else if ( element instanceof THREE.RenderableFace ) {
2927 
2928  _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
2929 
2930  if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue;
2931  if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue;
2932  if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue;
2933 
2934  _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf;
2935  _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf;
2936  _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf;
2937 
2938  _elemBox.setFromPoints( [
2939  _v1.positionScreen,
2940  _v2.positionScreen,
2941  _v3.positionScreen
2942  ] );
2943 
2944  if ( _clipBox.intersectsBox( _elemBox ) === true ) {
2945 
2946  renderFace3( _v1, _v2, _v3, element, material );
2947 
2948  }
2949 
2950  }
2951 
2952  }
2953 
2954  flushPath(); // just to flush last svg:path
2955 
2956  scene.traverseVisible( function ( object ) {
2957 
2958  if ( object instanceof THREE.SVGObject ) {
2959 
2960  _vector3.setFromMatrixPosition( object.matrixWorld );
2961  _vector3.applyMatrix4( _viewProjectionMatrix );
2962 
2963  if ( _vector3.z < - 1 || _vector3.z > 1 ) return;
2964 
2965  var x = _vector3.x * _svgWidthHalf;
2966  var y = - _vector3.y * _svgHeightHalf;
2967 
2968  var node = object.node;
2969  node.setAttribute( 'transform', 'translate(' + x + ',' + y + ')' );
2970 
2971  _svg.appendChild( node );
2972 
2973  }
2974 
2975  } );
2976 
2977  };
2978 
2979  function calculateLights( lights ) {
2980 
2981  _ambientLight.setRGB( 0, 0, 0 );
2982  _directionalLights.setRGB( 0, 0, 0 );
2983  _pointLights.setRGB( 0, 0, 0 );
2984 
2985  for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
2986 
2987  var light = lights[ l ];
2988  var lightColor = light.color;
2989 
2990  if ( light.isAmbientLight ) {
2991 
2992  _ambientLight.r += lightColor.r;
2993  _ambientLight.g += lightColor.g;
2994  _ambientLight.b += lightColor.b;
2995 
2996  } else if ( light.isDirectionalLight ) {
2997 
2998  _directionalLights.r += lightColor.r;
2999  _directionalLights.g += lightColor.g;
3000  _directionalLights.b += lightColor.b;
3001 
3002  } else if ( light.isPointLight ) {
3003 
3004  _pointLights.r += lightColor.r;
3005  _pointLights.g += lightColor.g;
3006  _pointLights.b += lightColor.b;
3007 
3008  }
3009 
3010  }
3011 
3012  }
3013 
3014  function calculateLight( lights, position, normal, color ) {
3015 
3016  for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
3017 
3018  var light = lights[ l ];
3019  var lightColor = light.color;
3020 
3021  if ( light.isDirectionalLight ) {
3022 
3023  var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
3024 
3025  var amount = normal.dot( lightPosition );
3026 
3027  if ( amount <= 0 ) continue;
3028 
3029  amount *= light.intensity;
3030 
3031  color.r += lightColor.r * amount;
3032  color.g += lightColor.g * amount;
3033  color.b += lightColor.b * amount;
3034 
3035  } else if ( light.isPointLight ) {
3036 
3037  var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
3038 
3039  var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
3040 
3041  if ( amount <= 0 ) continue;
3042 
3043  amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
3044 
3045  if ( amount == 0 ) continue;
3046 
3047  amount *= light.intensity;
3048 
3049  color.r += lightColor.r * amount;
3050  color.g += lightColor.g * amount;
3051  color.b += lightColor.b * amount;
3052 
3053  }
3054 
3055  }
3056 
3057  }
3058 
3059  function renderSprite( v1, element, material ) {
3060 
3061  var scaleX = element.scale.x * _svgWidthHalf;
3062  var scaleY = element.scale.y * _svgHeightHalf;
3063 
3064  if ( material.isPointsMaterial ) {
3065 
3066  scaleX *= material.size;
3067  scaleY *= material.size;
3068 
3069  }
3070 
3071  var path = 'M' + convert( v1.x - scaleX * 0.5 ) + ',' + convert( v1.y - scaleY * 0.5 ) + 'h' + convert( scaleX ) + 'v' + convert( scaleY ) + 'h' + convert( - scaleX ) + 'z';
3072  var style = "";
3073 
3074  if ( material.isSpriteMaterial || material.isPointsMaterial ) {
3075 
3076  style = 'fill:' + getSvgColor( material.color, material.opacity );
3077 
3078  }
3079 
3080  addPath( style, path );
3081 
3082  }
3083 
3084  function renderLine( v1, v2, element, material ) {
3085 
3086  var path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y );
3087 
3088  if ( material.isLineBasicMaterial ) {
3089 
3090  var style = 'fill:none;stroke:' + getSvgColor( material.color, material.opacity ) + ';stroke-width:' + material.linewidth + ';stroke-linecap:' + material.linecap;
3091 
3092  if ( material.isLineDashedMaterial ) {
3093 
3094  style = style + ';stroke-dasharray:' + material.dashSize + "," + material.gapSize;
3095 
3096  }
3097 
3098  addPath( style, path );
3099 
3100  }
3101 
3102  }
3103 
3104  function renderFace3( v1, v2, v3, element, material ) {
3105 
3106  _this.info.render.vertices += 3;
3107  _this.info.render.faces ++;
3108 
3109  var path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y ) + 'L' + convert( v3.positionScreen.x ) + ',' + convert( v3.positionScreen.y ) + 'z';
3110  var style = '';
3111 
3112  if ( material.isMeshBasicMaterial ) {
3113 
3114  _color.copy( material.color );
3115 
3116  if ( material.vertexColors === THREE.FaceColors || material.vertexColors === THREE.VertexColors ) {
3117 
3118  _color.multiply( element.color );
3119 
3120  }
3121 
3122  } else if ( material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial ) {
3123 
3124  _diffuseColor.copy( material.color );
3125 
3126  if ( material.vertexColors === THREE.FaceColors || material.vertexColors === THREE.VertexColors ) {
3127 
3128  _diffuseColor.multiply( element.color );
3129 
3130  }
3131 
3132  _color.copy( _ambientLight );
3133 
3134  _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 );
3135 
3136  calculateLight( _lights, _centroid, element.normalModel, _color );
3137 
3138  _color.multiply( _diffuseColor ).add( material.emissive );
3139 
3140  } else if ( material.isMeshNormalMaterial ) {
3141 
3142  _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );
3143 
3144  _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
3145 
3146  }
3147 
3148  if ( material.wireframe ) {
3149 
3150  style = 'fill:none;stroke:' + getSvgColor( _color, material.opacity ) + ';stroke-width:' + material.wireframeLinewidth + ';stroke-linecap:' + material.wireframeLinecap + ';stroke-linejoin:' + material.wireframeLinejoin;
3151 
3152  } else {
3153 
3154  style = 'fill:' + getSvgColor( _color, material.opacity );
3155 
3156  }
3157 
3158  addPath( style, path );
3159 
3160  }
3161 
3162  function addPath( style, path ) {
3163 
3164  if ( _currentStyle === style ) {
3165 
3166  _currentPath += path;
3167 
3168  } else {
3169 
3170  flushPath();
3171 
3172  _currentStyle = style;
3173  _currentPath = path;
3174 
3175  }
3176 
3177  }
3178 
3179  function flushPath() {
3180 
3181  if ( _currentPath ) {
3182 
3183  _svgNode = getPathNode( _pathCount ++ );
3184  _svgNode.setAttribute( 'd', _currentPath );
3185  _svgNode.setAttribute( 'style', _currentStyle );
3186  _svg.appendChild( _svgNode );
3187 
3188  }
3189 
3190  _currentPath = '';
3191  _currentStyle = '';
3192 
3193  }
3194 
3195  function getPathNode( id ) {
3196 
3197  if ( _svgPathPool[ id ] == null ) {
3198 
3199  _svgPathPool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
3200 
3201  if ( _quality == 0 ) {
3202 
3203  _svgPathPool[ id ].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed
3204 
3205  }
3206 
3207  return _svgPathPool[ id ];
3208 
3209  }
3210 
3211  return _svgPathPool[ id ];
3212 
3213  }
3214 
3215 };
3216 
3217 // END of SVGRenderer.js
3218 
3219  return new THREE.SVGRenderer();
3220 
3221  }
3222 
3223  var rndr = null;
3224 
3225  if (as_is) {
3226  if ((typeof doc=='undefined') && (typeof window=='object')) doc = window.document;
3227 
3228  rndr = Create(doc);
3229  } else {
3230  var doc_wrapper = {
3231  svg_attr: {},
3232  svg_style: {},
3233  path_attr: {},
3234  accPath: "",
3235  createElementNS: function(ns,kind) {
3236  if (kind == 'path')
3237  return {
3238  _wrapper: this,
3239  setAttribute: function(name, value) {
3240  this._wrapper.path_attr[name] = value;
3241  }
3242  }
3243 
3244  if (kind != 'svg') {
3245  console.error('not supported element for SVGRenderer', kind);
3246  return null;
3247  }
3248 
3249  return {
3250  _wrapper: this,
3251  childNodes: [], // may be accessed - make dummy
3252  style: this.svg_style, // for background color
3253  setAttribute: function(name, value) {
3254  this._wrapper.svg_attr[name] = value;
3255  },
3256  appendChild: function(node) {
3257  this._wrapper.accPath += '<path style="' + this._wrapper.path_attr['style'] + '" d="' + this._wrapper.path_attr['d'] + '"/>';
3258  this._wrapper.path_attr = {};
3259  },
3260  removeChild: function(node) {
3261  this.childNodes = [];
3262  }
3263  };
3264  }
3265  };
3266 
3267  rndr = Create(doc_wrapper);
3268 
3269  rndr.doc_wrapper = doc_wrapper; // use it to get final SVG code
3270 
3271  rndr.makeOuterHTML = function() {
3272 
3273  var wrap = this.doc_wrapper;
3274 
3275  var _textSizeAttr = ' viewBox="' + wrap.svg_attr['viewBox'] + '" width="' + wrap.svg_attr['width'] + '" height="' + wrap.svg_attr['height'] + '"';
3276 
3277  var _textClearAttr = '';
3278 
3279  if (wrap.svg_style.backgroundColor) _textClearAttr = ' style="background:' + wrap.svg_style.backgroundColor + '"';
3280 
3281  return '<svg xmlns="http://www.w3.org/2000/svg"' + _textSizeAttr + _textClearAttr + '>' + wrap.accPath + '</svg>';
3282  }
3283  }
3284 
3285  rndr.setPrecision(precision);
3286 
3287  return rndr;
3288 
3289 }
3290 // Content of examples/js/controls/OrbitControls.js
3299 // This set of controls performs orbiting, dollying (zooming), and panning.
3300 // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
3301 //
3302 // Orbit - left mouse / touch: one-finger move
3303 // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
3304 // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
3305 
3306 THREE.OrbitControls = function ( object, domElement ) {
3307 
3308  this.object = object;
3309 
3310  this.domElement = ( domElement !== undefined ) ? domElement : document;
3311 
3312  // Set to false to disable this control
3313  this.enabled = true;
3314 
3315  // "target" sets the location of focus, where the object orbits around
3316  this.target = new THREE.Vector3();
3317 
3318  // How far you can dolly in and out ( PerspectiveCamera only )
3319  this.minDistance = 0;
3320  this.maxDistance = Infinity;
3321 
3322  // How far you can zoom in and out ( OrthographicCamera only )
3323  this.minZoom = 0;
3324  this.maxZoom = Infinity;
3325 
3326  // How far you can orbit vertically, upper and lower limits.
3327  // Range is 0 to Math.PI radians.
3328  this.minPolarAngle = 0; // radians
3329  this.maxPolarAngle = Math.PI; // radians
3330 
3331  // How far you can orbit horizontally, upper and lower limits.
3332  // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
3333  this.minAzimuthAngle = - Infinity; // radians
3334  this.maxAzimuthAngle = Infinity; // radians
3335 
3336  // Set to true to enable damping (inertia)
3337  // If damping is enabled, you must call controls.update() in your animation loop
3338  this.enableDamping = false;
3339  this.dampingFactor = 0.25;
3340 
3341  // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
3342  // Set to false to disable zooming
3343  this.enableZoom = true;
3344  this.zoomSpeed = 1.0;
3345 
3346  // Set to false to disable rotating
3347  this.enableRotate = true;
3348  this.rotateSpeed = 1.0;
3349 
3350  // Set to false to disable panning
3351  this.enablePan = true;
3352  this.panSpeed = 1.0;
3353  this.screenSpacePanning = false; // if true, pan in screen-space
3354  this.keyPanSpeed = 7.0; // pixels moved per arrow key push
3355 
3356  // Set to true to automatically rotate around the target
3357  // If auto-rotate is enabled, you must call controls.update() in your animation loop
3358  this.autoRotate = false;
3359  this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
3360 
3361  // Set to false to disable use of the keys
3362  this.enableKeys = true;
3363 
3364  // The four arrow keys
3365  this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
3366 
3367  // Mouse buttons
3368  this.mouseButtons = { LEFT: THREE.MOUSE.LEFT, MIDDLE: THREE.MOUSE.MIDDLE, RIGHT: THREE.MOUSE.RIGHT };
3369 
3370  // for reset
3371  this.target0 = this.target.clone();
3372  this.position0 = this.object.position.clone();
3373  this.zoom0 = this.object.zoom;
3374 
3375  //
3376  // public methods
3377  //
3378 
3379  this.getPolarAngle = function () {
3380 
3381  return spherical.phi;
3382 
3383  };
3384 
3385  this.getAzimuthalAngle = function () {
3386 
3387  return spherical.theta;
3388 
3389  };
3390 
3391  this.saveState = function () {
3392 
3393  scope.target0.copy( scope.target );
3394  scope.position0.copy( scope.object.position );
3395  scope.zoom0 = scope.object.zoom;
3396 
3397  };
3398 
3399  this.reset = function () {
3400 
3401  scope.target.copy( scope.target0 );
3402  scope.object.position.copy( scope.position0 );
3403  scope.object.zoom = scope.zoom0;
3404 
3405  scope.object.updateProjectionMatrix();
3406  scope.dispatchEvent( changeEvent );
3407 
3408  scope.update();
3409 
3410  state = STATE.NONE;
3411 
3412  };
3413 
3414  // this method is exposed, but perhaps it would be better if we can make it private...
3415  this.update = function () {
3416 
3417  var offset = new THREE.Vector3();
3418 
3419  // so camera.up is the orbit axis
3420  var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
3421  var quatInverse = quat.clone().inverse();
3422 
3423  var lastPosition = new THREE.Vector3();
3424  var lastQuaternion = new THREE.Quaternion();
3425 
3426  return function update() {
3427 
3428  var position = scope.object.position;
3429 
3430  offset.copy( position ).sub( scope.target );
3431 
3432  // rotate offset to "y-axis-is-up" space
3433  offset.applyQuaternion( quat );
3434 
3435  // angle from z-axis around y-axis
3436  spherical.setFromVector3( offset );
3437 
3438  if ( scope.autoRotate && state === STATE.NONE ) {
3439 
3440  rotateLeft( getAutoRotationAngle() );
3441 
3442  }
3443 
3444  spherical.theta += sphericalDelta.theta;
3445  spherical.phi += sphericalDelta.phi;
3446 
3447  // restrict theta to be between desired limits
3448  spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );
3449 
3450  // restrict phi to be between desired limits
3451  spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
3452 
3453  spherical.makeSafe();
3454 
3455 
3456  spherical.radius *= scale;
3457 
3458  // restrict radius to be between desired limits
3459  spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
3460 
3461  // move target to panned location
3462  scope.target.add( panOffset );
3463 
3464  offset.setFromSpherical( spherical );
3465 
3466  // rotate offset back to "camera-up-vector-is-up" space
3467  offset.applyQuaternion( quatInverse );
3468 
3469  position.copy( scope.target ).add( offset );
3470 
3471  scope.object.lookAt( scope.target );
3472 
3473  if ( scope.enableDamping === true ) {
3474 
3475  sphericalDelta.theta *= ( 1 - scope.dampingFactor );
3476  sphericalDelta.phi *= ( 1 - scope.dampingFactor );
3477 
3478  panOffset.multiplyScalar( 1 - scope.dampingFactor );
3479 
3480  } else {
3481 
3482  sphericalDelta.set( 0, 0, 0 );
3483 
3484  panOffset.set( 0, 0, 0 );
3485 
3486  }
3487 
3488  scale = 1;
3489 
3490  // update condition is:
3491  // min(camera displacement, camera rotation in radians)^2 > EPS
3492  // using small-angle approximation cos(x/2) = 1 - x^2 / 8
3493 
3494  if ( zoomChanged ||
3495  lastPosition.distanceToSquared( scope.object.position ) > EPS ||
3496  8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
3497 
3498  scope.dispatchEvent( changeEvent );
3499 
3500  lastPosition.copy( scope.object.position );
3501  lastQuaternion.copy( scope.object.quaternion );
3502  zoomChanged = false;
3503 
3504  return true;
3505 
3506  }
3507 
3508  return false;
3509 
3510  };
3511 
3512  }();
3513 
3514  this.dispose = function () {
3515 
3516  scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );
3517  scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );
3518  scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );
3519 
3520  scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );
3521  scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );
3522  scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );
3523 
3524  document.removeEventListener( 'mousemove', onMouseMove, false );
3525  document.removeEventListener( 'mouseup', onMouseUp, false );
3526 
3527  window.removeEventListener( 'keydown', onKeyDown, false );
3528 
3529  //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
3530 
3531  };
3532 
3533  //
3534  // internals
3535  //
3536 
3537  var scope = this;
3538 
3539  var changeEvent = { type: 'change' };
3540  var startEvent = { type: 'start' };
3541  var endEvent = { type: 'end' };
3542 
3543  var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4 };
3544 
3545  var state = STATE.NONE;
3546 
3547  var EPS = 0.000001;
3548 
3549  // current position in spherical coordinates
3550  var spherical = new THREE.Spherical();
3551  var sphericalDelta = new THREE.Spherical();
3552 
3553  var scale = 1;
3554  var panOffset = new THREE.Vector3();
3555  var zoomChanged = false;
3556 
3557  var rotateStart = new THREE.Vector2();
3558  var rotateEnd = new THREE.Vector2();
3559  var rotateDelta = new THREE.Vector2();
3560 
3561  var panStart = new THREE.Vector2();
3562  var panEnd = new THREE.Vector2();
3563  var panDelta = new THREE.Vector2();
3564 
3565  var dollyStart = new THREE.Vector2();
3566  var dollyEnd = new THREE.Vector2();
3567  var dollyDelta = new THREE.Vector2();
3568 
3569  function getAutoRotationAngle() {
3570 
3571  return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
3572 
3573  }
3574 
3575  function getZoomScale() {
3576 
3577  return Math.pow( 0.95, scope.zoomSpeed );
3578 
3579  }
3580 
3581  function rotateLeft( angle ) {
3582 
3583  sphericalDelta.theta -= angle;
3584 
3585  }
3586 
3587  function rotateUp( angle ) {
3588 
3589  sphericalDelta.phi -= angle;
3590 
3591  }
3592 
3593  var panLeft = function () {
3594 
3595  var v = new THREE.Vector3();
3596 
3597  return function panLeft( distance, objectMatrix ) {
3598 
3599  v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
3600  v.multiplyScalar( - distance );
3601 
3602  panOffset.add( v );
3603 
3604  };
3605 
3606  }();
3607 
3608  var panUp = function () {
3609 
3610  var v = new THREE.Vector3();
3611 
3612  return function panUp( distance, objectMatrix ) {
3613 
3614  if ( scope.screenSpacePanning === true ) {
3615 
3616  v.setFromMatrixColumn( objectMatrix, 1 );
3617 
3618  } else {
3619 
3620  v.setFromMatrixColumn( objectMatrix, 0 );
3621  v.crossVectors( scope.object.up, v );
3622 
3623  }
3624 
3625  v.multiplyScalar( distance );
3626 
3627  panOffset.add( v );
3628 
3629  };
3630 
3631  }();
3632 
3633  // deltaX and deltaY are in pixels; right and down are positive
3634  var pan = function () {
3635 
3636  var offset = new THREE.Vector3();
3637 
3638  return function pan( deltaX, deltaY ) {
3639 
3640  var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
3641 
3642  if ( scope.object.isPerspectiveCamera ) {
3643 
3644  // perspective
3645  var position = scope.object.position;
3646  offset.copy( position ).sub( scope.target );
3647  var targetDistance = offset.length();
3648 
3649  // half of the fov is center to top of screen
3650  targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
3651 
3652  // we use only clientHeight here so aspect ratio does not distort speed
3653  panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
3654  panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
3655 
3656  } else if ( scope.object.isOrthographicCamera ) {
3657 
3658  // orthographic
3659  panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
3660  panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
3661 
3662  } else {
3663 
3664  // camera neither orthographic nor perspective
3665  console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
3666  scope.enablePan = false;
3667 
3668  }
3669 
3670  };
3671 
3672  }();
3673 
3674  function dollyIn( dollyScale ) {
3675 
3676  if ( scope.object.isPerspectiveCamera ) {
3677 
3678  scale /= dollyScale;
3679 
3680  } else if ( scope.object.isOrthographicCamera ) {
3681 
3682  scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
3683  scope.object.updateProjectionMatrix();
3684  zoomChanged = true;
3685 
3686  } else {
3687 
3688  console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
3689  scope.enableZoom = false;
3690 
3691  }
3692 
3693  }
3694 
3695  function dollyOut( dollyScale ) {
3696 
3697  if ( scope.object.isPerspectiveCamera ) {
3698 
3699  scale *= dollyScale;
3700 
3701  } else if ( scope.object.isOrthographicCamera ) {
3702 
3703  scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
3704  scope.object.updateProjectionMatrix();
3705  zoomChanged = true;
3706 
3707  } else {
3708 
3709  console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
3710  scope.enableZoom = false;
3711 
3712  }
3713 
3714  }
3715 
3716  //
3717  // event callbacks - update the object state
3718  //
3719 
3720  function handleMouseDownRotate( event ) {
3721 
3722  //console.log( 'handleMouseDownRotate' );
3723 
3724  rotateStart.set( event.clientX, event.clientY );
3725 
3726  }
3727 
3728  function handleMouseDownDolly( event ) {
3729 
3730  //console.log( 'handleMouseDownDolly' );
3731 
3732  dollyStart.set( event.clientX, event.clientY );
3733 
3734  }
3735 
3736  function handleMouseDownPan( event ) {
3737 
3738  //console.log( 'handleMouseDownPan' );
3739 
3740  panStart.set( event.clientX, event.clientY );
3741 
3742  }
3743 
3744  function handleMouseMoveRotate( event ) {
3745 
3746  //console.log( 'handleMouseMoveRotate' );
3747 
3748  rotateEnd.set( event.clientX, event.clientY );
3749 
3750  rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
3751 
3752  var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
3753 
3754  rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
3755 
3756  rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
3757 
3758  rotateStart.copy( rotateEnd );
3759 
3760  scope.update();
3761 
3762  }
3763 
3764  function handleMouseMoveDolly( event ) {
3765 
3766  //console.log( 'handleMouseMoveDolly' );
3767 
3768  dollyEnd.set( event.clientX, event.clientY );
3769 
3770  dollyDelta.subVectors( dollyEnd, dollyStart );
3771 
3772  if ( dollyDelta.y > 0 ) {
3773 
3774  dollyIn( getZoomScale() );
3775 
3776  } else if ( dollyDelta.y < 0 ) {
3777 
3778  dollyOut( getZoomScale() );
3779 
3780  }
3781 
3782  dollyStart.copy( dollyEnd );
3783 
3784  scope.update();
3785 
3786  }
3787 
3788  function handleMouseMovePan( event ) {
3789 
3790  //console.log( 'handleMouseMovePan' );
3791 
3792  panEnd.set( event.clientX, event.clientY );
3793 
3794  panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
3795 
3796  pan( panDelta.x, panDelta.y );
3797 
3798  panStart.copy( panEnd );
3799 
3800  scope.update();
3801 
3802  }
3803 
3804  function handleMouseUp( event ) {
3805 
3806  // console.log( 'handleMouseUp' );
3807 
3808  }
3809 
3810  function handleMouseWheel( event ) {
3811 
3812  // console.log( 'handleMouseWheel' );
3813 
3814  if ( event.deltaY < 0 ) {
3815 
3816  dollyOut( getZoomScale() );
3817 
3818  } else if ( event.deltaY > 0 ) {
3819 
3820  dollyIn( getZoomScale() );
3821 
3822  }
3823 
3824  scope.update();
3825 
3826  }
3827 
3828  function handleKeyDown( event ) {
3829 
3830  // console.log( 'handleKeyDown' );
3831 
3832  var needsUpdate = false;
3833 
3834  switch ( event.keyCode ) {
3835 
3836  case scope.keys.UP:
3837  pan( 0, scope.keyPanSpeed );
3838  needsUpdate = true;
3839  break;
3840 
3841  case scope.keys.BOTTOM:
3842  pan( 0, - scope.keyPanSpeed );
3843  needsUpdate = true;
3844  break;
3845 
3846  case scope.keys.LEFT:
3847  pan( scope.keyPanSpeed, 0 );
3848  needsUpdate = true;
3849  break;
3850 
3851  case scope.keys.RIGHT:
3852  pan( - scope.keyPanSpeed, 0 );
3853  needsUpdate = true;
3854  break;
3855 
3856  }
3857 
3858  if ( needsUpdate ) {
3859 
3860  // prevent the browser from scrolling on cursor keys
3861  event.preventDefault();
3862 
3863  scope.update();
3864 
3865  }
3866 
3867 
3868  }
3869 
3870  function handleTouchStartRotate( event ) {
3871 
3872  //console.log( 'handleTouchStartRotate' );
3873 
3874  rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
3875 
3876  }
3877 
3878  function handleTouchStartDollyPan( event ) {
3879 
3880  //console.log( 'handleTouchStartDollyPan' );
3881 
3882  if ( scope.enableZoom ) {
3883 
3884  var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
3885  var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
3886 
3887  var distance = Math.sqrt( dx * dx + dy * dy );
3888 
3889  dollyStart.set( 0, distance );
3890 
3891  }
3892 
3893  if ( scope.enablePan ) {
3894 
3895  var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
3896  var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
3897 
3898  panStart.set( x, y );
3899 
3900  }
3901 
3902  }
3903 
3904  function handleTouchMoveRotate( event ) {
3905 
3906  //console.log( 'handleTouchMoveRotate' );
3907 
3908  rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
3909 
3910  rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
3911 
3912  var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
3913 
3914  rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
3915 
3916  rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
3917 
3918  rotateStart.copy( rotateEnd );
3919 
3920  scope.update();
3921 
3922  }
3923 
3924  function handleTouchMoveDollyPan( event ) {
3925 
3926  //console.log( 'handleTouchMoveDollyPan' );
3927 
3928  if ( scope.enableZoom ) {
3929 
3930  var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
3931  var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
3932 
3933  var distance = Math.sqrt( dx * dx + dy * dy );
3934 
3935  dollyEnd.set( 0, distance );
3936 
3937  dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
3938 
3939  dollyIn( dollyDelta.y );
3940 
3941  dollyStart.copy( dollyEnd );
3942 
3943  }
3944 
3945  if ( scope.enablePan ) {
3946 
3947  var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
3948  var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
3949 
3950  panEnd.set( x, y );
3951 
3952  panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
3953 
3954  pan( panDelta.x, panDelta.y );
3955 
3956  panStart.copy( panEnd );
3957 
3958  }
3959 
3960  scope.update();
3961 
3962  }
3963 
3964  function handleTouchEnd( event ) {
3965 
3966  //console.log( 'handleTouchEnd' );
3967 
3968  }
3969 
3970  //
3971  // event handlers - FSM: listen for events and reset state
3972  //
3973 
3974  function onMouseDown( event ) {
3975 
3976  if ( scope.enabled === false ) return;
3977 
3978  // Prevent the browser from scrolling.
3979 
3980  event.preventDefault();
3981 
3982  // Manually set the focus since calling preventDefault above
3983  // prevents the browser from setting it automatically.
3984 
3985  scope.domElement.focus ? scope.domElement.focus() : window.focus();
3986 
3987  switch ( event.button ) {
3988 
3989  case scope.mouseButtons.LEFT:
3990 
3991  if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
3992 
3993  if ( scope.enablePan === false ) return;
3994 
3995  handleMouseDownPan( event );
3996 
3997  state = STATE.PAN;
3998 
3999  } else {
4000 
4001  if ( scope.enableRotate === false ) return;
4002 
4003  handleMouseDownRotate( event );
4004 
4005  state = STATE.ROTATE;
4006 
4007  }
4008 
4009  break;
4010 
4011  case scope.mouseButtons.MIDDLE:
4012 
4013  if ( scope.enableZoom === false ) return;
4014 
4015  handleMouseDownDolly( event );
4016 
4017  state = STATE.DOLLY;
4018 
4019  break;
4020 
4021  case scope.mouseButtons.RIGHT:
4022 
4023  if ( scope.enablePan === false ) return;
4024 
4025  handleMouseDownPan( event );
4026 
4027  state = STATE.PAN;
4028 
4029  break;
4030 
4031  }
4032 
4033  if ( state !== STATE.NONE ) {
4034 
4035  document.addEventListener( 'mousemove', onMouseMove, false );
4036  document.addEventListener( 'mouseup', onMouseUp, false );
4037 
4038  scope.dispatchEvent( startEvent );
4039 
4040  }
4041 
4042  }
4043 
4044  function onMouseMove( event ) {
4045 
4046  if ( scope.enabled === false ) return;
4047 
4048  event.preventDefault();
4049 
4050  switch ( state ) {
4051 
4052  case STATE.ROTATE:
4053 
4054  if ( scope.enableRotate === false ) return;
4055 
4056  handleMouseMoveRotate( event );
4057 
4058  break;
4059 
4060  case STATE.DOLLY:
4061 
4062  if ( scope.enableZoom === false ) return;
4063 
4064  handleMouseMoveDolly( event );
4065 
4066  break;
4067 
4068  case STATE.PAN:
4069 
4070  if ( scope.enablePan === false ) return;
4071 
4072  handleMouseMovePan( event );
4073 
4074  break;
4075 
4076  }
4077 
4078  }
4079 
4080  function onMouseUp( event ) {
4081 
4082  if ( scope.enabled === false ) return;
4083 
4084  handleMouseUp( event );
4085 
4086  document.removeEventListener( 'mousemove', onMouseMove, false );
4087  document.removeEventListener( 'mouseup', onMouseUp, false );
4088 
4089  scope.dispatchEvent( endEvent );
4090 
4091  state = STATE.NONE;
4092 
4093  }
4094 
4095  function onMouseWheel( event ) {
4096 
4097  if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;
4098 
4099  event.preventDefault();
4100  event.stopPropagation();
4101 
4102  scope.dispatchEvent( startEvent );
4103 
4104  handleMouseWheel( event );
4105 
4106  scope.dispatchEvent( endEvent );
4107 
4108  }
4109 
4110  function onKeyDown( event ) {
4111 
4112  if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;
4113 
4114  handleKeyDown( event );
4115 
4116  }
4117 
4118  function onTouchStart( event ) {
4119 
4120  if ( scope.enabled === false ) return;
4121 
4122  event.preventDefault();
4123 
4124  switch ( event.touches.length ) {
4125 
4126  case 1: // one-fingered touch: rotate
4127 
4128  if ( scope.enableRotate === false ) return;
4129 
4130  handleTouchStartRotate( event );
4131 
4132  state = STATE.TOUCH_ROTATE;
4133 
4134  break;
4135 
4136  case 2: // two-fingered touch: dolly-pan
4137 
4138  if ( scope.enableZoom === false && scope.enablePan === false ) return;
4139 
4140  handleTouchStartDollyPan( event );
4141 
4142  state = STATE.TOUCH_DOLLY_PAN;
4143 
4144  break;
4145 
4146  default:
4147 
4148  state = STATE.NONE;
4149 
4150  }
4151 
4152  if ( state !== STATE.NONE ) {
4153 
4154  scope.dispatchEvent( startEvent );
4155 
4156  }
4157 
4158  }
4159 
4160  function onTouchMove( event ) {
4161 
4162  if ( scope.enabled === false ) return;
4163 
4164  event.preventDefault();
4165  event.stopPropagation();
4166 
4167  switch ( event.touches.length ) {
4168 
4169  case 1: // one-fingered touch: rotate
4170 
4171  if ( scope.enableRotate === false ) return;
4172  if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed?
4173 
4174  handleTouchMoveRotate( event );
4175 
4176  break;
4177 
4178  case 2: // two-fingered touch: dolly-pan
4179 
4180  if ( scope.enableZoom === false && scope.enablePan === false ) return;
4181  if ( state !== STATE.TOUCH_DOLLY_PAN ) return; // is this needed?
4182 
4183  handleTouchMoveDollyPan( event );
4184 
4185  break;
4186 
4187  default:
4188 
4189  state = STATE.NONE;
4190 
4191  }
4192 
4193  }
4194 
4195  function onTouchEnd( event ) {
4196 
4197  if ( scope.enabled === false ) return;
4198 
4199  handleTouchEnd( event );
4200 
4201  scope.dispatchEvent( endEvent );
4202 
4203  state = STATE.NONE;
4204 
4205  }
4206 
4207  function onContextMenu( event ) {
4208 
4209  if ( scope.enabled === false ) return;
4210 
4211  event.preventDefault();
4212 
4213  }
4214 
4215  //
4216 
4217  scope.domElement.addEventListener( 'contextmenu', onContextMenu, false );
4218 
4219  scope.domElement.addEventListener( 'mousedown', onMouseDown, false );
4220  scope.domElement.addEventListener( 'wheel', onMouseWheel, false );
4221 
4222  scope.domElement.addEventListener( 'touchstart', onTouchStart, false );
4223  scope.domElement.addEventListener( 'touchend', onTouchEnd, false );
4224  scope.domElement.addEventListener( 'touchmove', onTouchMove, false );
4225 
4226  window.addEventListener( 'keydown', onKeyDown, false );
4227 
4228  // force an update at start
4229 
4230  this.update();
4231 
4232 };
4233 
4234 THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
4235 THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
4236 
4237 Object.defineProperties( THREE.OrbitControls.prototype, {
4238 
4239  center: {
4240 
4241  get: function () {
4242 
4243  console.warn( 'THREE.OrbitControls: .center has been renamed to .target' );
4244  return this.target;
4245 
4246  }
4247 
4248  },
4249 
4250  // backward compatibility
4251 
4252  noZoom: {
4253 
4254  get: function () {
4255 
4256  console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
4257  return ! this.enableZoom;
4258 
4259  },
4260 
4261  set: function ( value ) {
4262 
4263  console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
4264  this.enableZoom = ! value;
4265 
4266  }
4267 
4268  },
4269 
4270  noRotate: {
4271 
4272  get: function () {
4273 
4274  console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
4275  return ! this.enableRotate;
4276 
4277  },
4278 
4279  set: function ( value ) {
4280 
4281  console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
4282  this.enableRotate = ! value;
4283 
4284  }
4285 
4286  },
4287 
4288  noPan: {
4289 
4290  get: function () {
4291 
4292  console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
4293  return ! this.enablePan;
4294 
4295  },
4296 
4297  set: function ( value ) {
4298 
4299  console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
4300  this.enablePan = ! value;
4301 
4302  }
4303 
4304  },
4305 
4306  noKeys: {
4307 
4308  get: function () {
4309 
4310  console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
4311  return ! this.enableKeys;
4312 
4313  },
4314 
4315  set: function ( value ) {
4316 
4317  console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
4318  this.enableKeys = ! value;
4319 
4320  }
4321 
4322  },
4323 
4324  staticMoving: {
4325 
4326  get: function () {
4327 
4328  console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
4329  return ! this.enableDamping;
4330 
4331  },
4332 
4333  set: function ( value ) {
4334 
4335  console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
4336  this.enableDamping = ! value;
4337 
4338  }
4339 
4340  },
4341 
4342  dynamicDampingFactor: {
4343 
4344  get: function () {
4345 
4346  console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
4347  return this.dampingFactor;
4348 
4349  },
4350 
4351  set: function ( value ) {
4352 
4353  console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
4354  this.dampingFactor = value;
4355 
4356  }
4357 
4358  }
4359 
4360 } );
4361 
4362 // Content of examples/js/controls/TransformControls.js
4367 THREE.TransformControls = function ( camera, domElement ) {
4368 
4369  THREE.Object3D.call( this );
4370 
4371  domElement = ( domElement !== undefined ) ? domElement : document;
4372 
4373  this.visible = false;
4374 
4375  var _gizmo = new THREE.TransformControlsGizmo();
4376  this.add( _gizmo );
4377 
4378  var _plane = new THREE.TransformControlsPlane();
4379  this.add( _plane );
4380 
4381  var scope = this;
4382 
4383  // Define properties with getters/setter
4384  // Setting the defined property will automatically trigger change event
4385  // Defined properties are passed down to gizmo and plane
4386 
4387  defineProperty( "camera", camera );
4388  defineProperty( "object", undefined );
4389  defineProperty( "enabled", true );
4390  defineProperty( "axis", null );
4391  defineProperty( "mode", "translate" );
4392  defineProperty( "translationSnap", null );
4393  defineProperty( "rotationSnap", null );
4394  defineProperty( "space", "world" );
4395  defineProperty( "size", 1 );
4396  defineProperty( "dragging", false );
4397  defineProperty( "showX", true );
4398  defineProperty( "showY", true );
4399  defineProperty( "showZ", true );
4400 
4401  var changeEvent = { type: "change" };
4402  var mouseDownEvent = { type: "mouseDown" };
4403  var mouseUpEvent = { type: "mouseUp", mode: scope.mode };
4404  var objectChangeEvent = { type: "objectChange" };
4405 
4406  // Reusable utility variables
4407 
4408  var ray = new THREE.Raycaster();
4409 
4410  var _tempVector = new THREE.Vector3();
4411  var _tempVector2 = new THREE.Vector3();
4412  var _tempQuaternion = new THREE.Quaternion();
4413  var _unit = {
4414  X: new THREE.Vector3( 1, 0, 0 ),
4415  Y: new THREE.Vector3( 0, 1, 0 ),
4416  Z: new THREE.Vector3( 0, 0, 1 )
4417  };
4418  var _identityQuaternion = new THREE.Quaternion();
4419  var _alignVector = new THREE.Vector3();
4420 
4421  var pointStart = new THREE.Vector3();
4422  var pointEnd = new THREE.Vector3();
4423  var offset = new THREE.Vector3();
4424  var rotationAxis = new THREE.Vector3();
4425  var startNorm = new THREE.Vector3();
4426  var endNorm = new THREE.Vector3();
4427  var rotationAngle = 0;
4428 
4429  var cameraPosition = new THREE.Vector3();
4430  var cameraQuaternion = new THREE.Quaternion();
4431  var cameraScale = new THREE.Vector3();
4432 
4433  var parentPosition = new THREE.Vector3();
4434  var parentQuaternion = new THREE.Quaternion();
4435  var parentQuaternionInv = new THREE.Quaternion();
4436  var parentScale = new THREE.Vector3();
4437 
4438  var worldPositionStart = new THREE.Vector3();
4439  var worldQuaternionStart = new THREE.Quaternion();
4440  var worldScaleStart = new THREE.Vector3();
4441 
4442  var worldPosition = new THREE.Vector3();
4443  var worldQuaternion = new THREE.Quaternion();
4444  var worldQuaternionInv = new THREE.Quaternion();
4445  var worldScale = new THREE.Vector3();
4446 
4447  var eye = new THREE.Vector3();
4448 
4449  var positionStart = new THREE.Vector3();
4450  var quaternionStart = new THREE.Quaternion();
4451  var scaleStart = new THREE.Vector3();
4452 
4453  // TODO: remove properties unused in plane and gizmo
4454 
4455  defineProperty( "worldPosition", worldPosition );
4456  defineProperty( "worldPositionStart", worldPositionStart );
4457  defineProperty( "worldQuaternion", worldQuaternion );
4458  defineProperty( "worldQuaternionStart", worldQuaternionStart );
4459  defineProperty( "cameraPosition", cameraPosition );
4460  defineProperty( "cameraQuaternion", cameraQuaternion );
4461  defineProperty( "pointStart", pointStart );
4462  defineProperty( "pointEnd", pointEnd );
4463  defineProperty( "rotationAxis", rotationAxis );
4464  defineProperty( "rotationAngle", rotationAngle );
4465  defineProperty( "eye", eye );
4466 
4467  {
4468 
4469  domElement.addEventListener( "mousedown", onPointerDown, false );
4470  domElement.addEventListener( "touchstart", onPointerDown, false );
4471  domElement.addEventListener( "mousemove", onPointerHover, false );
4472  domElement.addEventListener( "touchmove", onPointerHover, false );
4473  domElement.addEventListener( "touchmove", onPointerMove, false );
4474  document.addEventListener( "mouseup", onPointerUp, false );
4475  domElement.addEventListener( "touchend", onPointerUp, false );
4476  domElement.addEventListener( "touchcancel", onPointerUp, false );
4477  domElement.addEventListener( "touchleave", onPointerUp, false );
4478 
4479  }
4480 
4481  this.dispose = function () {
4482 
4483  domElement.removeEventListener( "mousedown", onPointerDown );
4484  domElement.removeEventListener( "touchstart", onPointerDown );
4485  domElement.removeEventListener( "mousemove", onPointerHover );
4486  domElement.removeEventListener( "touchmove", onPointerHover );
4487  domElement.removeEventListener( "touchmove", onPointerMove );
4488  document.removeEventListener( "mouseup", onPointerUp );
4489  domElement.removeEventListener( "touchend", onPointerUp );
4490  domElement.removeEventListener( "touchcancel", onPointerUp );
4491  domElement.removeEventListener( "touchleave", onPointerUp );
4492 
4493  };
4494 
4495  // Set current object
4496  this.attach = function ( object ) {
4497 
4498  this.object = object;
4499  this.visible = true;
4500 
4501  };
4502 
4503  // Detatch from object
4504  this.detach = function () {
4505 
4506  this.object = undefined;
4507  this.visible = false;
4508  this.axis = null;
4509 
4510  };
4511 
4512  // Defined getter, setter and store for a property
4513  function defineProperty( propName, defaultValue ) {
4514 
4515  var propValue = defaultValue;
4516 
4517  Object.defineProperty( scope, propName, {
4518 
4519  get: function() {
4520 
4521  return propValue !== undefined ? propValue : defaultValue;
4522 
4523  },
4524 
4525  set: function( value ) {
4526 
4527  if ( propValue !== value ) {
4528 
4529  propValue = value;
4530  _plane[ propName ] = value;
4531  _gizmo[ propName ] = value;
4532 
4533  scope.dispatchEvent( { type: propName + "-changed", value: value } );
4534  scope.dispatchEvent( changeEvent );
4535 
4536  }
4537 
4538  }
4539 
4540  });
4541 
4542  scope[ propName ] = defaultValue;
4543  _plane[ propName ] = defaultValue;
4544  _gizmo[ propName ] = defaultValue;
4545 
4546  }
4547 
4548  // updateMatrixWorld updates key transformation variables
4549  this.updateMatrixWorld = function () {
4550 
4551  if ( this.object !== undefined ) {
4552 
4553  this.object.updateMatrixWorld();
4554  this.object.parent.matrixWorld.decompose( parentPosition, parentQuaternion, parentScale );
4555  this.object.matrixWorld.decompose( worldPosition, worldQuaternion, worldScale );
4556 
4557  parentQuaternionInv.copy( parentQuaternion ).inverse();
4558  worldQuaternionInv.copy( worldQuaternion ).inverse();
4559 
4560  }
4561 
4562  this.camera.updateMatrixWorld();
4563  this.camera.matrixWorld.decompose( cameraPosition, cameraQuaternion, cameraScale );
4564 
4565  if ( this.camera instanceof THREE.PerspectiveCamera ) {
4566 
4567  eye.copy( cameraPosition ).sub( worldPosition ).normalize();
4568 
4569  } else if ( this.camera instanceof THREE.OrthographicCamera ) {
4570 
4571  eye.copy( cameraPosition ).normalize();
4572 
4573  }
4574 
4575  THREE.Object3D.prototype.updateMatrixWorld.call( this );
4576 
4577  };
4578 
4579  this.pointerHover = function( pointer ) {
4580 
4581  if ( this.object === undefined || this.dragging === true || ( pointer.button !== undefined && pointer.button !== 0 ) ) return;
4582 
4583  ray.setFromCamera( pointer, this.camera );
4584 
4585  var intersect = ray.intersectObjects( _gizmo.picker[ this.mode ].children, true )[ 0 ] || false;
4586 
4587  if ( intersect ) {
4588 
4589  this.axis = intersect.object.name;
4590 
4591  } else {
4592 
4593  this.axis = null;
4594 
4595  }
4596 
4597  };
4598 
4599  this.pointerDown = function( pointer ) {
4600 
4601  if ( this.object === undefined || this.dragging === true || ( pointer.button !== undefined && pointer.button !== 0 ) ) return;
4602 
4603  if ( ( pointer.button === 0 || pointer.button === undefined ) && this.axis !== null ) {
4604 
4605  ray.setFromCamera( pointer, this.camera );
4606 
4607  var planeIntersect = ray.intersectObjects( [ _plane ], true )[ 0 ] || false;
4608 
4609  if ( planeIntersect ) {
4610 
4611  var space = this.space;
4612 
4613  if ( this.mode === 'scale') {
4614 
4615  space = 'local';
4616 
4617  } else if ( this.axis === 'E' || this.axis === 'XYZE' || this.axis === 'XYZ' ) {
4618 
4619  space = 'world';
4620 
4621  }
4622 
4623  if ( space === 'local' && this.mode === 'rotate' ) {
4624 
4625  var snap = this.rotationSnap;
4626 
4627  if ( this.axis === 'X' && snap ) this.object.rotation.x = Math.round( this.object.rotation.x / snap ) * snap;
4628  if ( this.axis === 'Y' && snap ) this.object.rotation.y = Math.round( this.object.rotation.y / snap ) * snap;
4629  if ( this.axis === 'Z' && snap ) this.object.rotation.z = Math.round( this.object.rotation.z / snap ) * snap;
4630 
4631  }
4632 
4633  this.object.updateMatrixWorld();
4634  this.object.parent.updateMatrixWorld();
4635 
4636  positionStart.copy( this.object.position );
4637  quaternionStart.copy( this.object.quaternion );
4638  scaleStart.copy( this.object.scale );
4639 
4640  this.object.matrixWorld.decompose( worldPositionStart, worldQuaternionStart, worldScaleStart );
4641 
4642  pointStart.copy( planeIntersect.point ).sub( worldPositionStart );
4643 
4644  }
4645 
4646  this.dragging = true;
4647  mouseDownEvent.mode = this.mode;
4648  this.dispatchEvent( mouseDownEvent );
4649 
4650  }
4651 
4652  };
4653 
4654  this.pointerMove = function( pointer ) {
4655 
4656  var axis = this.axis;
4657  var mode = this.mode;
4658  var object = this.object;
4659  var space = this.space;
4660 
4661  if ( mode === 'scale') {
4662 
4663  space = 'local';
4664 
4665  } else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) {
4666 
4667  space = 'world';
4668 
4669  }
4670 
4671  if ( object === undefined || axis === null || this.dragging === false || ( pointer.button !== undefined && pointer.button !== 0 ) ) return;
4672 
4673  ray.setFromCamera( pointer, this.camera );
4674 
4675  var planeIntersect = ray.intersectObjects( [ _plane ], true )[ 0 ] || false;
4676 
4677  if ( planeIntersect === false ) return;
4678 
4679  pointEnd.copy( planeIntersect.point ).sub( worldPositionStart );
4680 
4681  if ( mode === 'translate' ) {
4682 
4683  // Apply translate
4684 
4685  offset.copy( pointEnd ).sub( pointStart );
4686 
4687  if ( space === 'local' && axis !== 'XYZ' ) {
4688  offset.applyQuaternion( worldQuaternionInv );
4689  }
4690 
4691  if ( axis.indexOf( 'X' ) === -1 ) offset.x = 0;
4692  if ( axis.indexOf( 'Y' ) === -1 ) offset.y = 0;
4693  if ( axis.indexOf( 'Z' ) === -1 ) offset.z = 0;
4694 
4695  if ( space === 'local' && axis !== 'XYZ') {
4696  offset.applyQuaternion( quaternionStart ).divide( parentScale );
4697  } else {
4698  offset.applyQuaternion( parentQuaternionInv ).divide( parentScale );
4699  }
4700 
4701  object.position.copy( offset ).add( positionStart );
4702 
4703  // Apply translation snap
4704 
4705  if ( this.translationSnap ) {
4706 
4707  if ( space === 'local' ) {
4708 
4709  object.position.applyQuaternion(_tempQuaternion.copy( quaternionStart ).inverse() );
4710 
4711  if ( axis.search( 'X' ) !== -1 ) {
4712  object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
4713  }
4714 
4715  if ( axis.search( 'Y' ) !== -1 ) {
4716  object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
4717  }
4718 
4719  if ( axis.search( 'Z' ) !== -1 ) {
4720  object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
4721  }
4722 
4723  object.position.applyQuaternion( quaternionStart );
4724 
4725  }
4726 
4727  if ( space === 'world' ) {
4728 
4729  if ( object.parent ) {
4730  object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
4731  }
4732 
4733  if ( axis.search( 'X' ) !== -1 ) {
4734  object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
4735  }
4736 
4737  if ( axis.search( 'Y' ) !== -1 ) {
4738  object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
4739  }
4740 
4741  if ( axis.search( 'Z' ) !== -1 ) {
4742  object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
4743  }
4744 
4745  if ( object.parent ) {
4746  object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
4747  }
4748 
4749  }
4750 
4751  }
4752 
4753  } else if ( mode === 'scale' ) {
4754 
4755  if ( axis.search( 'XYZ' ) !== -1 ) {
4756 
4757  var d = pointEnd.length() / pointStart.length();
4758 
4759  if ( pointEnd.dot( pointStart ) < 0 ) d *= -1;
4760 
4761  _tempVector.set( d, d, d );
4762 
4763  } else {
4764 
4765  _tempVector.copy( pointEnd ).divide( pointStart );
4766 
4767  if ( axis.search( 'X' ) === -1 ) {
4768  _tempVector.x = 1;
4769  }
4770  if ( axis.search( 'Y' ) === -1 ) {
4771  _tempVector.y = 1;
4772  }
4773  if ( axis.search( 'Z' ) === -1 ) {
4774  _tempVector.z = 1;
4775  }
4776 
4777  }
4778 
4779  // Apply scale
4780 
4781  object.scale.copy( scaleStart ).multiply( _tempVector );
4782 
4783  } else if ( mode === 'rotate' ) {
4784 
4785  offset.copy( pointEnd ).sub( pointStart );
4786 
4787  var ROTATION_SPEED = 20 / worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) );
4788 
4789  if ( axis === 'E' ) {
4790 
4791  rotationAxis.copy( eye );
4792  rotationAngle = pointEnd.angleTo( pointStart );
4793 
4794  startNorm.copy( pointStart ).normalize();
4795  endNorm.copy( pointEnd ).normalize();
4796 
4797  rotationAngle *= ( endNorm.cross( startNorm ).dot( eye ) < 0 ? 1 : -1);
4798 
4799  } else if ( axis === 'XYZE' ) {
4800 
4801  rotationAxis.copy( offset ).cross( eye ).normalize( );
4802  rotationAngle = offset.dot( _tempVector.copy( rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED;
4803 
4804  } else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) {
4805 
4806  rotationAxis.copy( _unit[ axis ] );
4807 
4808  _tempVector.copy( _unit[ axis ] );
4809 
4810  if ( space === 'local' ) {
4811  _tempVector.applyQuaternion( worldQuaternion );
4812  }
4813 
4814  rotationAngle = offset.dot( _tempVector.cross( eye ).normalize() ) * ROTATION_SPEED;
4815 
4816  }
4817 
4818  // Apply rotation snap
4819 
4820  if ( this.rotationSnap ) rotationAngle = Math.round( rotationAngle / this.rotationSnap ) * this.rotationSnap;
4821 
4822  this.rotationAngle = rotationAngle;
4823 
4824  // Apply rotate
4825  if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) {
4826 
4827  object.quaternion.copy( quaternionStart );
4828  object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) ).normalize();
4829 
4830  } else {
4831 
4832  rotationAxis.applyQuaternion( parentQuaternionInv );
4833  object.quaternion.copy( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) );
4834  object.quaternion.multiply( quaternionStart ).normalize();
4835 
4836  }
4837 
4838  }
4839 
4840  this.dispatchEvent( changeEvent );
4841  this.dispatchEvent( objectChangeEvent );
4842 
4843  };
4844 
4845  this.pointerUp = function( pointer ) {
4846 
4847  if ( pointer.button !== undefined && pointer.button !== 0 ) return;
4848 
4849  if ( this.dragging && ( this.axis !== null ) ) {
4850 
4851  mouseUpEvent.mode = this.mode;
4852  this.dispatchEvent( mouseUpEvent );
4853 
4854  }
4855 
4856  this.dragging = false;
4857 
4858  if ( pointer.button === undefined ) this.axis = null;
4859 
4860  };
4861 
4862  // normalize mouse / touch pointer and remap {x,y} to view space.
4863 
4864  function getPointer( event ) {
4865 
4866  var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
4867 
4868  var rect = domElement.getBoundingClientRect();
4869 
4870  return {
4871  x: ( pointer.clientX - rect.left ) / rect.width * 2 - 1,
4872  y: - ( pointer.clientY - rect.top ) / rect.height * 2 + 1,
4873  button: event.button
4874  };
4875 
4876  }
4877 
4878  // mouse / touch event handlers
4879 
4880  function onPointerHover( event ) {
4881 
4882  if ( !scope.enabled ) return;
4883 
4884  scope.pointerHover( getPointer( event ) );
4885 
4886  }
4887 
4888  function onPointerDown( event ) {
4889 
4890  if ( !scope.enabled ) return;
4891 
4892  document.addEventListener( "mousemove", onPointerMove, false );
4893 
4894  scope.pointerHover( getPointer( event ) );
4895  scope.pointerDown( getPointer( event ) );
4896 
4897  }
4898 
4899  function onPointerMove( event ) {
4900 
4901  if ( !scope.enabled ) return;
4902 
4903  scope.pointerMove( getPointer( event ) );
4904 
4905  }
4906 
4907  function onPointerUp( event ) {
4908 
4909  if ( !scope.enabled ) return;
4910 
4911  document.removeEventListener( "mousemove", onPointerMove, false );
4912 
4913  scope.pointerUp( getPointer( event ) );
4914 
4915  }
4916 
4917  // TODO: depricate
4918 
4919  this.getMode = function () {
4920 
4921  return scope.mode;
4922 
4923  };
4924 
4925  this.setMode = function ( mode ) {
4926 
4927  scope.mode = mode;
4928 
4929  };
4930 
4931  this.setTranslationSnap = function ( translationSnap ) {
4932 
4933  scope.translationSnap = translationSnap;
4934 
4935  };
4936 
4937  this.setRotationSnap = function ( rotationSnap ) {
4938 
4939  scope.rotationSnap = rotationSnap;
4940 
4941  };
4942 
4943  this.setSize = function ( size ) {
4944 
4945  scope.size = size;
4946 
4947  };
4948 
4949  this.setSpace = function ( space ) {
4950 
4951  scope.space = space;
4952 
4953  };
4954 
4955  this.update = function () {
4956 
4957  console.warn( 'THREE.TransformControls: update function has been depricated.' );
4958 
4959  };
4960 
4961 };
4962 
4963 THREE.TransformControls.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
4964 
4965  constructor: THREE.TransformControls,
4966 
4967  isTransformControls: true
4968 
4969 } );
4970 
4971 
4972 THREE.TransformControlsGizmo = function () {
4973 
4974  'use strict';
4975 
4976  THREE.Object3D.call( this );
4977 
4978  this.type = 'TransformControlsGizmo';
4979 
4980  // shared materials
4981 
4982  var gizmoMaterial = new THREE.MeshBasicMaterial({
4983  depthTest: false,
4984  depthWrite: false,
4985  transparent: true,
4986  side: THREE.DoubleSide,
4987  fog: false
4988  });
4989 
4990  var gizmoLineMaterial = new THREE.LineBasicMaterial({
4991  depthTest: false,
4992  depthWrite: false,
4993  transparent: true,
4994  linewidth: 1,
4995  fog: false
4996  });
4997 
4998  // Make unique material for each axis/color
4999 
5000  var matInvisible = gizmoMaterial.clone();
5001  matInvisible.opacity = 0.15;
5002 
5003  var matHelper = gizmoMaterial.clone();
5004  matHelper.opacity = 0.33;
5005 
5006  var matRed = gizmoMaterial.clone();
5007  matRed.color.set( 0xff0000 );
5008 
5009  var matGreen = gizmoMaterial.clone();
5010  matGreen.color.set( 0x00ff00 );
5011 
5012  var matBlue = gizmoMaterial.clone();
5013  matBlue.color.set( 0x0000ff );
5014 
5015  var matWhiteTransperent = gizmoMaterial.clone();
5016  matWhiteTransperent.opacity = 0.25;
5017 
5018  var matYellowTransparent = matWhiteTransperent.clone();
5019  matYellowTransparent.color.set( 0xffff00 );
5020 
5021  var matCyanTransparent = matWhiteTransperent.clone();
5022  matCyanTransparent.color.set( 0x00ffff );
5023 
5024  var matMagentaTransparent = matWhiteTransperent.clone();
5025  matMagentaTransparent.color.set( 0xff00ff );
5026 
5027  var matYellow = gizmoMaterial.clone();
5028  matYellow.color.set( 0xffff00 );
5029 
5030  var matLineRed = gizmoLineMaterial.clone();
5031  matLineRed.color.set( 0xff0000 );
5032 
5033  var matLineGreen = gizmoLineMaterial.clone();
5034  matLineGreen.color.set( 0x00ff00 );
5035 
5036  var matLineBlue = gizmoLineMaterial.clone();
5037  matLineBlue.color.set( 0x0000ff );
5038 
5039  var matLineCyan = gizmoLineMaterial.clone();
5040  matLineCyan.color.set( 0x00ffff );
5041 
5042  var matLineMagenta = gizmoLineMaterial.clone();
5043  matLineMagenta.color.set( 0xff00ff );
5044 
5045  var matLineYellow = gizmoLineMaterial.clone();
5046  matLineYellow.color.set( 0xffff00 );
5047 
5048  var matLineGray = gizmoLineMaterial.clone();
5049  matLineGray.color.set( 0x787878);
5050 
5051  var matLineYellowTransparent = matLineYellow.clone();
5052  matLineYellowTransparent.opacity = 0.25;
5053 
5054  // reusable geometry
5055 
5056  var arrowGeometry = new THREE.CylinderBufferGeometry( 0, 0.05, 0.2, 12, 1, false);
5057 
5058  var scaleHandleGeometry = new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125);
5059 
5060  var lineGeometry = new THREE.BufferGeometry( );
5061  lineGeometry.addAttribute('position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
5062 
5063  var CircleGeometry = function( radius, arc ) {
5064 
5065  var geometry = new THREE.BufferGeometry( );
5066  var vertices = [];
5067 
5068  for ( var i = 0; i <= 64 * arc; ++i ) {
5069 
5070  vertices.push( 0, Math.cos( i / 32 * Math.PI ) * radius, Math.sin( i / 32 * Math.PI ) * radius );
5071 
5072  }
5073 
5074  geometry.addAttribute('position', new THREE.Float32BufferAttribute( vertices, 3 ) );
5075 
5076  return geometry;
5077 
5078  };
5079 
5080  // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
5081 
5082  var TranslateHelperGeometry = function( radius, arc ) {
5083 
5084  var geometry = new THREE.BufferGeometry()
5085 
5086  geometry.addAttribute('position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );
5087 
5088  return geometry;
5089 
5090  };
5091 
5092  // Gizmo definitions - custom hierarchy definitions for setupGizmo() function
5093 
5094  var gizmoTranslate = {
5095  X: [
5096  [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, -Math.PI / 2 ], null, 'fwd' ],
5097  [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, Math.PI / 2 ], null, 'bwd' ],
5098  [ new THREE.Line( lineGeometry, matLineRed ) ]
5099  ],
5100  Y: [
5101  [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], null, null, 'fwd' ],
5102  [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], [ Math.PI, 0, 0 ], null, 'bwd' ],
5103  [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ] ]
5104  ],
5105  Z: [
5106  [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ Math.PI / 2, 0, 0 ], null, 'fwd' ],
5107  [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ -Math.PI / 2, 0, 0 ], null, 'bwd' ],
5108  [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, -Math.PI / 2, 0 ] ]
5109  ],
5110  XYZ: [
5111  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.1, 0 ), matWhiteTransperent ), [ 0, 0, 0 ], [ 0, 0, 0 ] ]
5112  ],
5113  XY: [
5114  [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.295, 0.295 ), matYellowTransparent ), [ 0.15, 0.15, 0 ] ],
5115  [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.18, 0.3, 0 ], null, [ 0.125, 1, 1 ] ],
5116  [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.3, 0.18, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ]
5117  ],
5118  YZ: [
5119  [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.295, 0.295 ), matCyanTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ] ],
5120  [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.18, 0.3 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ],
5121  [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.3, 0.18 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ]
5122  ],
5123  XZ: [
5124  [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.295, 0.295 ), matMagentaTransparent ), [ 0.15, 0, 0.15 ], [ -Math.PI / 2, 0, 0 ] ],
5125  [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.18, 0, 0.3 ], null, [ 0.125, 1, 1 ] ],
5126  [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.3, 0, 0.18 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ]
5127  ]
5128  };
5129 
5130  var pickerTranslate = {
5131  X: [
5132  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0.6, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ]
5133  ],
5134  Y: [
5135  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0.6, 0 ] ]
5136  ],
5137  Z: [
5138  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ] ]
5139  ],
5140  XYZ: [
5141  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.2, 0 ), matInvisible ) ]
5142  ],
5143  XY: [
5144  [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0.2, 0 ] ]
5145  ],
5146  YZ: [
5147  [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0, 0.2, 0.2 ], [ 0, Math.PI / 2, 0 ] ]
5148  ],
5149  XZ: [
5150  [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0, 0.2 ], [ -Math.PI / 2, 0, 0 ] ]
5151  ]
5152  };
5153 
5154  var helperTranslate = {
5155  START: [
5156  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
5157  ],
5158  END: [
5159  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
5160  ],
5161  DELTA: [
5162  [ new THREE.Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]
5163  ],
5164  X: [
5165  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
5166  ],
5167  Y: [
5168  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
5169  ],
5170  Z: [
5171  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
5172  ]
5173  };
5174 
5175  var gizmoRotate = {
5176  X: [
5177  [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineRed ) ],
5178  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.04, 0 ), matRed ), [ 0, 0, 0.99 ], null, [ 1, 3, 1 ] ],
5179  ],
5180  Y: [
5181  [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineGreen ), null, [ 0, 0, -Math.PI / 2 ] ],
5182  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.04, 0 ), matGreen ), [ 0, 0, 0.99 ], null, [ 3, 1, 1 ] ],
5183  ],
5184  Z: [
5185  [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineBlue ), null, [ 0, Math.PI / 2, 0 ] ],
5186  [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.04, 0 ), matBlue ), [ 0.99, 0, 0 ], null, [ 1, 3, 1 ] ],
5187  ],
5188  E: [
5189  [ new THREE.Line( CircleGeometry( 1.25, 1 ), matLineYellowTransparent ), null, [ 0, Math.PI / 2, 0 ] ],
5190  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 1.17, 0, 0 ], [ 0, 0, -Math.PI / 2 ], [ 1, 1, 0.001 ]],
5191  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ -1.17, 0, 0 ], [ 0, 0, Math.PI / 2 ], [ 1, 1, 0.001 ]],
5192  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, -1.17, 0 ], [ Math.PI, 0, 0 ], [ 1, 1, 0.001 ]],
5193  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, 1.17, 0 ], [ 0, 0, 0 ], [ 1, 1, 0.001 ]],
5194  ],
5195  XYZE: [
5196  [ new THREE.Line( CircleGeometry( 1, 1 ), matLineGray ), null, [ 0, Math.PI / 2, 0 ] ]
5197  ]
5198  };
5199 
5200  var helperRotate = {
5201  AXIS: [
5202  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
5203  ]
5204  };
5205 
5206  var pickerRotate = {
5207  X: [
5208  [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, -Math.PI / 2, -Math.PI / 2 ] ],
5209  ],
5210  Y: [
5211  [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ],
5212  ],
5213  Z: [
5214  [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ],
5215  ],
5216  E: [
5217  [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1.25, 0.1, 2, 24 ), matInvisible ) ]
5218  ],
5219  XYZE: [
5220  [ new THREE.Mesh( new THREE.SphereBufferGeometry( 0.7, 10, 8 ), matInvisible ) ]
5221  ]
5222  };
5223 
5224  var gizmoScale = {
5225  X: [
5226  [ new THREE.Mesh( scaleHandleGeometry, matRed ), [ 0.8, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ],
5227  [ new THREE.Line( lineGeometry, matLineRed ), null, null, [ 0.8, 1, 1 ] ]
5228  ],
5229  Y: [
5230  [ new THREE.Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.8, 0 ] ],
5231  [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ], [ 0.8, 1, 1 ] ]
5232  ],
5233  Z: [
5234  [ new THREE.Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.8 ], [ Math.PI / 2, 0, 0 ] ],
5235  [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, -Math.PI / 2, 0 ], [ 0.8, 1, 1 ] ]
5236  ],
5237  XY: [
5238  [ new THREE.Mesh( scaleHandleGeometry, matYellowTransparent ), [ 0.85, 0.85, 0 ], null, [ 2, 2, 0.2 ] ],
5239  [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.855, 0.98, 0 ], null, [ 0.125, 1, 1 ] ],
5240  [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.98, 0.855, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ]
5241  ],
5242  YZ: [
5243  [ new THREE.Mesh( scaleHandleGeometry, matCyanTransparent ), [ 0, 0.85, 0.85 ], null, [ 0.2, 2, 2 ] ],
5244  [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.855, 0.98 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ],
5245  [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.98, 0.855 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ]
5246  ],
5247  XZ: [
5248  [ new THREE.Mesh( scaleHandleGeometry, matMagentaTransparent ), [ 0.85, 0, 0.85 ], null, [ 2, 0.2, 2 ] ],
5249  [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.855, 0, 0.98 ], null, [ 0.125, 1, 1 ] ],
5250  [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.98, 0, 0.855 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ]
5251  ],
5252  XYZX: [
5253  [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransperent ), [ 1.1, 0, 0 ] ],
5254  ],
5255  XYZY: [
5256  [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransperent ), [ 0, 1.1, 0 ] ],
5257  ],
5258  XYZZ: [
5259  [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransperent ), [ 0, 0, 1.1 ] ],
5260  ]
5261  };
5262 
5263  var pickerScale = {
5264  X: [
5265  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0.5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ]
5266  ],
5267  Y: [
5268  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0.5, 0 ] ]
5269  ],
5270  Z: [
5271  [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ] ]
5272  ],
5273  XY: [
5274  [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0.85, 0 ], null, [ 3, 3, 0.2 ] ],
5275  ],
5276  YZ: [
5277  [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0, 0.85, 0.85 ], null, [ 0.2, 3, 3 ] ],
5278  ],
5279  XZ: [
5280  [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0, 0.85 ], null, [ 3, 0.2, 3 ] ],
5281  ],
5282  XYZX: [
5283  [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 1.1, 0, 0 ] ],
5284  ],
5285  XYZY: [
5286  [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 1.1, 0 ] ],
5287  ],
5288  XYZZ: [
5289  [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 1.1 ] ],
5290  ]
5291  };
5292 
5293  var helperScale = {
5294  X: [
5295  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
5296  ],
5297  Y: [
5298  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
5299  ],
5300  Z: [
5301  [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
5302  ]
5303  };
5304 
5305  // Creates an Object3D with gizmos described in custom hierarchy definition.
5306 
5307  var setupGizmo = function( gizmoMap ) {
5308 
5309  var gizmo = new THREE.Object3D();
5310 
5311  for ( var name in gizmoMap ) {
5312 
5313  for ( var i = gizmoMap[ name ].length; i --; ) {
5314 
5315  var object = gizmoMap[ name ][ i ][ 0 ].clone();
5316  var position = gizmoMap[ name ][ i ][ 1 ];
5317  var rotation = gizmoMap[ name ][ i ][ 2 ];
5318  var scale = gizmoMap[ name ][ i ][ 3 ];
5319  var tag = gizmoMap[ name ][ i ][ 4 ];
5320 
5321  // name and tag properties are essential for picking and updating logic.
5322  object.name = name;
5323  object.tag = tag;
5324 
5325  if (position) {
5326  object.position.set(position[ 0 ], position[ 1 ], position[ 2 ]);
5327  }
5328  if (rotation) {
5329  object.rotation.set(rotation[ 0 ], rotation[ 1 ], rotation[ 2 ]);
5330  }
5331  if (scale) {
5332  object.scale.set(scale[ 0 ], scale[ 1 ], scale[ 2 ]);
5333  }
5334 
5335  object.updateMatrix();
5336 
5337  var tempGeometry = object.geometry.clone();
5338  tempGeometry.applyMatrix(object.matrix);
5339  object.geometry = tempGeometry;
5340 
5341  object.position.set( 0, 0, 0 );
5342  object.rotation.set( 0, 0, 0 );
5343  object.scale.set(1, 1, 1);
5344 
5345  gizmo.add(object);
5346 
5347  }
5348 
5349  }
5350 
5351  return gizmo;
5352 
5353  };
5354 
5355  // Reusable utility variables
5356 
5357  var tempVector = new THREE.Vector3( 0, 0, 0 );
5358  var tempEuler = new THREE.Euler();
5359  var alignVector = new THREE.Vector3( 0, 1, 0 );
5360  var zeroVector = new THREE.Vector3( 0, 0, 0 );
5361  var lookAtMatrix = new THREE.Matrix4();
5362  var tempQuaternion = new THREE.Quaternion();
5363  var tempQuaternion2 = new THREE.Quaternion();
5364  var identityQuaternion = new THREE.Quaternion();
5365 
5366  var unitX = new THREE.Vector3( 1, 0, 0 );
5367  var unitY = new THREE.Vector3( 0, 1, 0 );
5368  var unitZ = new THREE.Vector3( 0, 0, 1 );
5369 
5370  // Gizmo creation
5371 
5372  this.gizmo = {};
5373  this.picker = {};
5374  this.helper = {};
5375 
5376  this.add( this.gizmo[ "translate" ] = setupGizmo( gizmoTranslate ) );
5377  this.add( this.gizmo[ "rotate" ] = setupGizmo( gizmoRotate ) );
5378  this.add( this.gizmo[ "scale" ] = setupGizmo( gizmoScale ) );
5379  this.add( this.picker[ "translate" ] = setupGizmo( pickerTranslate ) );
5380  this.add( this.picker[ "rotate" ] = setupGizmo( pickerRotate ) );
5381  this.add( this.picker[ "scale" ] = setupGizmo( pickerScale ) );
5382  this.add( this.helper[ "translate" ] = setupGizmo( helperTranslate ) );
5383  this.add( this.helper[ "rotate" ] = setupGizmo( helperRotate ) );
5384  this.add( this.helper[ "scale" ] = setupGizmo( helperScale ) );
5385 
5386  // Pickers should be hidden always
5387 
5388  this.picker[ "translate" ].visible = false;
5389  this.picker[ "rotate" ].visible = false;
5390  this.picker[ "scale" ].visible = false;
5391 
5392  // updateMatrixWorld will update transformations and appearance of individual handles
5393 
5394  this.updateMatrixWorld = function () {
5395 
5396  var space = this.space;
5397 
5398  if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation
5399 
5400  var quaternion = space === "local" ? this.worldQuaternion : identityQuaternion;
5401 
5402  // Show only gizmos for current transform mode
5403 
5404  this.gizmo[ "translate" ].visible = this.mode === "translate";
5405  this.gizmo[ "rotate" ].visible = this.mode === "rotate";
5406  this.gizmo[ "scale" ].visible = this.mode === "scale";
5407 
5408  this.helper[ "translate" ].visible = this.mode === "translate";
5409  this.helper[ "rotate" ].visible = this.mode === "rotate";
5410  this.helper[ "scale" ].visible = this.mode === "scale";
5411 
5412 
5413  var handles = [];
5414  handles = handles.concat( this.picker[ this.mode ].children );
5415  handles = handles.concat( this.gizmo[ this.mode ].children );
5416  handles = handles.concat( this.helper[ this.mode ].children );
5417 
5418  for ( var i = 0; i < handles.length; i++ ) {
5419 
5420  var handle = handles[i];
5421 
5422  // hide aligned to camera
5423 
5424  handle.visible = true;
5425  handle.rotation.set( 0, 0, 0 );
5426  handle.position.copy( this.worldPosition );
5427 
5428  var eyeDistance = this.worldPosition.distanceTo( this.cameraPosition);
5429  handle.scale.set( 1, 1, 1 ).multiplyScalar( eyeDistance * this.size / 7 );
5430 
5431  // TODO: simplify helpers and consider decoupling from gizmo
5432 
5433  if ( handle.tag === 'helper' ) {
5434 
5435  handle.visible = false;
5436 
5437  if ( handle.name === 'AXIS' ) {
5438 
5439  handle.position.copy( this.worldPositionStart );
5440  handle.visible = !!this.axis;
5441 
5442  if ( this.axis === 'X' ) {
5443 
5444  tempQuaternion.setFromEuler( tempEuler.set( 0, 0, 0 ) );
5445  handle.quaternion.copy( quaternion ).multiply( tempQuaternion );
5446 
5447  if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
5448  handle.visible = false;
5449  }
5450 
5451  }
5452 
5453  if ( this.axis === 'Y' ) {
5454 
5455  tempQuaternion.setFromEuler( tempEuler.set( 0, 0, Math.PI / 2 ) );
5456  handle.quaternion.copy( quaternion ).multiply( tempQuaternion );
5457 
5458  if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
5459  handle.visible = false;
5460  }
5461 
5462  }
5463 
5464  if ( this.axis === 'Z' ) {
5465 
5466  tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) );
5467  handle.quaternion.copy( quaternion ).multiply( tempQuaternion );
5468 
5469  if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
5470  handle.visible = false;
5471  }
5472 
5473  }
5474 
5475  if ( this.axis === 'XYZE' ) {
5476 
5477  tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) );
5478  alignVector.copy( this.rotationAxis );
5479  handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( zeroVector, alignVector, unitY ) );
5480  handle.quaternion.multiply( tempQuaternion );
5481  handle.visible = this.dragging;
5482 
5483  }
5484 
5485  if ( this.axis === 'E' ) {
5486 
5487  handle.visible = false;
5488 
5489  }
5490 
5491 
5492  } else if ( handle.name === 'START' ) {
5493 
5494  handle.position.copy( this.worldPositionStart );
5495  handle.visible = this.dragging;
5496 
5497  } else if ( handle.name === 'END' ) {
5498 
5499  handle.position.copy( this.worldPosition );
5500  handle.visible = this.dragging;
5501 
5502  } else if ( handle.name === 'DELTA' ) {
5503 
5504  handle.position.copy( this.worldPositionStart );
5505  handle.quaternion.copy( this.worldQuaternionStart );
5506  tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( -1 );
5507  tempVector.applyQuaternion( this.worldQuaternionStart.clone().inverse() );
5508  handle.scale.copy( tempVector );
5509  handle.visible = this.dragging;
5510 
5511  } else {
5512 
5513  handle.quaternion.copy( quaternion );
5514 
5515  if ( this.dragging ) {
5516 
5517  handle.position.copy( this.worldPositionStart );
5518 
5519  } else {
5520 
5521  handle.position.copy( this.worldPosition );
5522 
5523  }
5524 
5525  if ( this.axis ) {
5526 
5527  handle.visible = this.axis.search( handle.name ) !== -1;
5528 
5529  }
5530 
5531  }
5532 
5533  // If updating helper, skip rest of the loop
5534  continue;
5535 
5536  }
5537 
5538  // Align handles to current local or world rotation
5539 
5540  handle.quaternion.copy( quaternion );
5541 
5542  if ( this.mode === 'translate' || this.mode === 'scale' ) {
5543 
5544  // Hide translate and scale axis facing the camera
5545 
5546  var AXIS_HIDE_TRESHOLD = 0.99;
5547  var PLANE_HIDE_TRESHOLD = 0.2;
5548  var AXIS_FLIP_TRESHOLD = -0.4;
5549 
5550 
5551  if ( handle.name === 'X' || handle.name === 'XYZX' ) {
5552  if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
5553  handle.scale.set( 1e-10, 1e-10, 1e-10 );
5554  handle.visible = false;
5555  }
5556  }
5557  if ( handle.name === 'Y' || handle.name === 'XYZY' ) {
5558  if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
5559  handle.scale.set( 1e-10, 1e-10, 1e-10 );
5560  handle.visible = false;
5561  }
5562  }
5563  if ( handle.name === 'Z' || handle.name === 'XYZZ' ) {
5564  if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
5565  handle.scale.set( 1e-10, 1e-10, 1e-10 );
5566  handle.visible = false;
5567  }
5568  }
5569  if ( handle.name === 'XY' ) {
5570  if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
5571  handle.scale.set( 1e-10, 1e-10, 1e-10 );
5572  handle.visible = false;
5573  }
5574  }
5575  if ( handle.name === 'YZ' ) {
5576  if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
5577  handle.scale.set( 1e-10, 1e-10, 1e-10 );
5578  handle.visible = false;
5579  }
5580  }
5581  if ( handle.name === 'XZ' ) {
5582  if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
5583  handle.scale.set( 1e-10, 1e-10, 1e-10 );
5584  handle.visible = false;
5585  }
5586  }
5587 
5588  // Flip translate and scale axis ocluded behind another axis
5589 
5590  if ( handle.name.search( 'X' ) !== -1 ) {
5591  if ( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) {
5592  if ( handle.tag === 'fwd' ) {
5593  handle.visible = false;
5594  } else {
5595  handle.scale.x *= -1;
5596  }
5597  } else if ( handle.tag === 'bwd' ) {
5598  handle.visible = false;
5599  }
5600  }
5601 
5602  if ( handle.name.search( 'Y' ) !== -1 ) {
5603  if ( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) {
5604  if ( handle.tag === 'fwd' ) {
5605  handle.visible = false;
5606  } else {
5607  handle.scale.y *= -1;
5608  }
5609  } else if ( handle.tag === 'bwd' ) {
5610  handle.visible = false;
5611  }
5612  }
5613 
5614  if ( handle.name.search( 'Z' ) !== -1 ) {
5615  if ( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) {
5616  if ( handle.tag === 'fwd' ) {
5617  handle.visible = false;
5618  } else {
5619  handle.scale.z *= -1;
5620  }
5621  } else if ( handle.tag === 'bwd' ) {
5622  handle.visible = false;
5623  }
5624  }
5625 
5626  } else if ( this.mode === 'rotate' ) {
5627 
5628  // Align handles to current local or world rotation
5629 
5630  tempQuaternion2.copy( quaternion );
5631  alignVector.copy( this.eye ).applyQuaternion( tempQuaternion.copy( quaternion ).inverse() );
5632 
5633  if ( handle.name.search( "E" ) !== - 1 ) {
5634 
5635  handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( this.eye, zeroVector, unitY ) );
5636 
5637  }
5638 
5639  if ( handle.name === 'X' ) {
5640 
5641  tempQuaternion.setFromAxisAngle( unitX, Math.atan2( -alignVector.y, alignVector.z ) );
5642  tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion );
5643  handle.quaternion.copy( tempQuaternion );
5644 
5645  }
5646 
5647  if ( handle.name === 'Y' ) {
5648 
5649  tempQuaternion.setFromAxisAngle( unitY, Math.atan2( alignVector.x, alignVector.z ) );
5650  tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion );
5651  handle.quaternion.copy( tempQuaternion );
5652 
5653  }
5654 
5655  if ( handle.name === 'Z' ) {
5656 
5657  tempQuaternion.setFromAxisAngle( unitZ, Math.atan2( alignVector.y, alignVector.x ) );
5658  tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion );
5659  handle.quaternion.copy( tempQuaternion );
5660 
5661  }
5662 
5663  }
5664 
5665  // Hide disabled axes
5666  handle.visible = handle.visible && ( handle.name.indexOf( "X" ) === -1 || this.showX );
5667  handle.visible = handle.visible && ( handle.name.indexOf( "Y" ) === -1 || this.showY );
5668  handle.visible = handle.visible && ( handle.name.indexOf( "Z" ) === -1 || this.showZ );
5669  handle.visible = handle.visible && ( handle.name.indexOf( "E" ) === -1 || ( this.showX && this.showY && this.showZ ) );
5670 
5671  // highlight selected axis
5672 
5673  handle.material._opacity = handle.material._opacity || handle.material.opacity;
5674  handle.material._color = handle.material._color || handle.material.color.clone();
5675 
5676  handle.material.color.copy( handle.material._color );
5677  handle.material.opacity = handle.material._opacity;
5678 
5679  if ( !this.enabled ) {
5680 
5681  handle.material.opacity *= 0.5;
5682  handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 );
5683 
5684  } else if ( this.axis ) {
5685 
5686  if ( handle.name === this.axis ) {
5687 
5688  handle.material.opacity = 1.0;
5689  handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 );
5690 
5691  } else if ( this.axis.split('').some( function( a ) { return handle.name === a; } ) ) {
5692 
5693  handle.material.opacity = 1.0;
5694  handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 );
5695 
5696  } else {
5697 
5698  handle.material.opacity *= 0.25;
5699  handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 );
5700 
5701  }
5702 
5703  }
5704 
5705  }
5706 
5707  THREE.Object3D.prototype.updateMatrixWorld.call( this );
5708 
5709  };
5710 
5711 };
5712 
5713 THREE.TransformControlsGizmo.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
5714 
5715  constructor: THREE.TransformControlsGizmo,
5716 
5717  isTransformControlsGizmo: true
5718 
5719 } );
5720 
5721 
5722 THREE.TransformControlsPlane = function () {
5723 
5724  'use strict';
5725 
5726  THREE.Mesh.call( this,
5727  new THREE.PlaneBufferGeometry( 100000, 100000, 2, 2 ),
5728  new THREE.MeshBasicMaterial( { visible: false, wireframe: true, side: THREE.DoubleSide, transparent: true, opacity: 0.1 } )
5729  );
5730 
5731  this.type = 'TransformControlsPlane';
5732 
5733  var unitX = new THREE.Vector3( 1, 0, 0 );
5734  var unitY = new THREE.Vector3( 0, 1, 0 );
5735  var unitZ = new THREE.Vector3( 0, 0, 1 );
5736 
5737  var tempVector = new THREE.Vector3();
5738  var dirVector = new THREE.Vector3();
5739  var alignVector = new THREE.Vector3();
5740  var tempMatrix = new THREE.Matrix4();
5741  var identityQuaternion = new THREE.Quaternion();
5742 
5743  this.updateMatrixWorld = function() {
5744 
5745  var space = this.space;
5746 
5747  this.position.copy( this.worldPosition );
5748 
5749  if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation
5750 
5751  unitX.set( 1, 0, 0 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion );
5752  unitY.set( 0, 1, 0 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion );
5753  unitZ.set( 0, 0, 1 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion );
5754 
5755  // Align the plane for current transform mode, axis and space.
5756 
5757  alignVector.copy( unitY );
5758 
5759  switch ( this.mode ) {
5760  case 'translate':
5761  case 'scale':
5762  switch ( this.axis ) {
5763  case 'X':
5764  alignVector.copy( this.eye ).cross( unitX );
5765  dirVector.copy( unitX ).cross( alignVector );
5766  break;
5767  case 'Y':
5768  alignVector.copy( this.eye ).cross( unitY );
5769  dirVector.copy( unitY ).cross( alignVector );
5770  break;
5771  case 'Z':
5772  alignVector.copy( this.eye ).cross( unitZ );
5773  dirVector.copy( unitZ ).cross( alignVector );
5774  break;
5775  case 'XY':
5776  dirVector.copy( unitZ );
5777  break;
5778  case 'YZ':
5779  dirVector.copy( unitX );
5780  break;
5781  case 'XZ':
5782  alignVector.copy( unitZ );
5783  dirVector.copy( unitY );
5784  break;
5785  case 'XYZ':
5786  case 'E':
5787  dirVector.set( 0, 0, 0 );
5788  break;
5789  }
5790  break;
5791  case 'rotate':
5792  default:
5793  // special case for rotate
5794  dirVector.set( 0, 0, 0 );
5795  }
5796 
5797  if ( dirVector.length() === 0 ) {
5798 
5799  // If in rotate mode, make the plane parallel to camera
5800  this.quaternion.copy( this.cameraQuaternion );
5801 
5802  } else {
5803 
5804  tempMatrix.lookAt( tempVector.set( 0, 0, 0 ), dirVector, alignVector );
5805 
5806  this.quaternion.setFromRotationMatrix( tempMatrix );
5807 
5808  }
5809 
5810  THREE.Object3D.prototype.updateMatrixWorld.call( this );
5811 
5812  };
5813 
5814 };
5815 
5816 THREE.TransformControlsPlane.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {
5817 
5818  constructor: THREE.TransformControlsPlane,
5819 
5820  isTransformControlsPlane: true
5821 
5822 } );
5823 
5824 // Content of examples/js/shaders/CopyShader.js
5831 THREE.CopyShader = {
5832 
5833  uniforms: {
5834 
5835  "tDiffuse": { value: null },
5836  "opacity": { value: 1.0 }
5837 
5838  },
5839 
5840  vertexShader: [
5841 
5842  "varying vec2 vUv;",
5843 
5844  "void main() {",
5845 
5846  "vUv = uv;",
5847  "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
5848 
5849  "}"
5850 
5851  ].join( "\n" ),
5852 
5853  fragmentShader: [
5854 
5855  "uniform float opacity;",
5856 
5857  "uniform sampler2D tDiffuse;",
5858 
5859  "varying vec2 vUv;",
5860 
5861  "void main() {",
5862 
5863  "vec4 texel = texture2D( tDiffuse, vUv );",
5864  "gl_FragColor = opacity * texel;",
5865 
5866  "}"
5867 
5868  ].join( "\n" )
5869 
5870 };
5871 
5872 // Content of examples/js/postprocessing/EffectComposer.js
5877 THREE.EffectComposer = function ( renderer, renderTarget ) {
5878 
5879  this.renderer = renderer;
5880 
5881  if ( renderTarget === undefined ) {
5882 
5883  var parameters = {
5884  minFilter: THREE.LinearFilter,
5885  magFilter: THREE.LinearFilter,
5886  format: THREE.RGBAFormat,
5887  stencilBuffer: false
5888  };
5889 
5890  var size = renderer.getDrawingBufferSize( new THREE.Vector2() );
5891  renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );
5892  renderTarget.texture.name = 'EffectComposer.rt1';
5893 
5894  }
5895 
5896  this.renderTarget1 = renderTarget;
5897  this.renderTarget2 = renderTarget.clone();
5898  this.renderTarget2.texture.name = 'EffectComposer.rt2';
5899 
5900  this.writeBuffer = this.renderTarget1;
5901  this.readBuffer = this.renderTarget2;
5902 
5903  this.passes = [];
5904 
5905  // dependencies
5906 
5907  if ( THREE.CopyShader === undefined ) {
5908 
5909  console.error( 'THREE.EffectComposer relies on THREE.CopyShader' );
5910 
5911  }
5912 
5913  if ( THREE.ShaderPass === undefined ) {
5914 
5915  console.error( 'THREE.EffectComposer relies on THREE.ShaderPass' );
5916 
5917  }
5918 
5919  this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
5920 
5921  this._previousFrameTime = Date.now();
5922 
5923 };
5924 
5925 Object.assign( THREE.EffectComposer.prototype, {
5926 
5927  swapBuffers: function () {
5928 
5929  var tmp = this.readBuffer;
5930  this.readBuffer = this.writeBuffer;
5931  this.writeBuffer = tmp;
5932 
5933  },
5934 
5935  addPass: function ( pass ) {
5936 
5937  this.passes.push( pass );
5938 
5939  var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() );
5940  pass.setSize( size.width, size.height );
5941 
5942  },
5943 
5944  insertPass: function ( pass, index ) {
5945 
5946  this.passes.splice( index, 0, pass );
5947 
5948  },
5949 
5950  render: function ( deltaTime ) {
5951 
5952  // deltaTime value is in seconds
5953 
5954  if ( deltaTime === undefined ) {
5955 
5956  deltaTime = ( Date.now() - this._previousFrameTime ) * 0.001;
5957 
5958  }
5959 
5960  this._previousFrameTime = Date.now();
5961 
5962  var currentRenderTarget = this.renderer.getRenderTarget();
5963 
5964  var maskActive = false;
5965 
5966  var pass, i, il = this.passes.length;
5967 
5968  for ( i = 0; i < il; i ++ ) {
5969 
5970  pass = this.passes[ i ];
5971 
5972  if ( pass.enabled === false ) continue;
5973 
5974  pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );
5975 
5976  if ( pass.needsSwap ) {
5977 
5978  if ( maskActive ) {
5979 
5980  var context = this.renderer.context;
5981 
5982  context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
5983 
5984  this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );
5985 
5986  context.stencilFunc( context.EQUAL, 1, 0xffffffff );
5987 
5988  }
5989 
5990  this.swapBuffers();
5991 
5992  }
5993 
5994  if ( THREE.MaskPass !== undefined ) {
5995 
5996  if ( pass instanceof THREE.MaskPass ) {
5997 
5998  maskActive = true;
5999 
6000  } else if ( pass instanceof THREE.ClearMaskPass ) {
6001 
6002  maskActive = false;
6003 
6004  }
6005 
6006  }
6007 
6008  }
6009 
6010  this.renderer.setRenderTarget( currentRenderTarget );
6011 
6012  },
6013 
6014  reset: function ( renderTarget ) {
6015 
6016  if ( renderTarget === undefined ) {
6017 
6018  var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() );
6019 
6020  renderTarget = this.renderTarget1.clone();
6021  renderTarget.setSize( size.width, size.height );
6022 
6023  }
6024 
6025  this.renderTarget1.dispose();
6026  this.renderTarget2.dispose();
6027  this.renderTarget1 = renderTarget;
6028  this.renderTarget2 = renderTarget.clone();
6029 
6030  this.writeBuffer = this.renderTarget1;
6031  this.readBuffer = this.renderTarget2;
6032 
6033  },
6034 
6035  setSize: function ( width, height ) {
6036 
6037  this.renderTarget1.setSize( width, height );
6038  this.renderTarget2.setSize( width, height );
6039 
6040  for ( var i = 0; i < this.passes.length; i ++ ) {
6041 
6042  this.passes[ i ].setSize( width, height );
6043 
6044  }
6045 
6046  }
6047 
6048 } );
6049 
6050 
6051 THREE.Pass = function () {
6052 
6053  // if set to true, the pass is processed by the composer
6054  this.enabled = true;
6055 
6056  // if set to true, the pass indicates to swap read and write buffer after rendering
6057  this.needsSwap = true;
6058 
6059  // if set to true, the pass clears its buffer before rendering
6060  this.clear = false;
6061 
6062  // if set to true, the result of the pass is rendered to screen
6063  this.renderToScreen = false;
6064 
6065 };
6066 
6067 Object.assign( THREE.Pass.prototype, {
6068 
6069  setSize: function ( width, height ) {},
6070 
6071  render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
6072 
6073  console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
6074 
6075  }
6076 
6077 } );
6078 
6079 // Content of examples/js/postprocessing/MaskPass.js
6084 THREE.MaskPass = function ( scene, camera ) {
6085 
6086  THREE.Pass.call( this );
6087 
6088  this.scene = scene;
6089  this.camera = camera;
6090 
6091  this.clear = true;
6092  this.needsSwap = false;
6093 
6094  this.inverse = false;
6095 
6096 };
6097 
6098 THREE.MaskPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
6099 
6100  constructor: THREE.MaskPass,
6101 
6102  render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
6103 
6104  var context = renderer.context;
6105  var state = renderer.state;
6106 
6107  // don't update color or depth
6108 
6109  state.buffers.color.setMask( false );
6110  state.buffers.depth.setMask( false );
6111 
6112  // lock buffers
6113 
6114  state.buffers.color.setLocked( true );
6115  state.buffers.depth.setLocked( true );
6116 
6117  // set up stencil
6118 
6119  var writeValue, clearValue;
6120 
6121  if ( this.inverse ) {
6122 
6123  writeValue = 0;
6124  clearValue = 1;
6125 
6126  } else {
6127 
6128  writeValue = 1;
6129  clearValue = 0;
6130 
6131  }
6132 
6133  state.buffers.stencil.setTest( true );
6134  state.buffers.stencil.setOp( context.REPLACE, context.REPLACE, context.REPLACE );
6135  state.buffers.stencil.setFunc( context.ALWAYS, writeValue, 0xffffffff );
6136  state.buffers.stencil.setClear( clearValue );
6137 
6138  // draw into the stencil buffer
6139 
6140  renderer.setRenderTarget( readBuffer );
6141  if ( this.clear ) renderer.clear();
6142  renderer.render( this.scene, this.camera );
6143 
6144  renderer.setRenderTarget( writeBuffer );
6145  if ( this.clear ) renderer.clear();
6146  renderer.render( this.scene, this.camera );
6147 
6148  // unlock color and depth buffer for subsequent rendering
6149 
6150  state.buffers.color.setLocked( false );
6151  state.buffers.depth.setLocked( false );
6152 
6153  // only render where stencil is set to 1
6154 
6155  state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
6156  state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP );
6157 
6158  }
6159 
6160 } );
6161 
6162 
6163 THREE.ClearMaskPass = function () {
6164 
6165  THREE.Pass.call( this );
6166 
6167  this.needsSwap = false;
6168 
6169 };
6170 
6171 THREE.ClearMaskPass.prototype = Object.create( THREE.Pass.prototype );
6172 
6173 Object.assign( THREE.ClearMaskPass.prototype, {
6174 
6175  render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
6176 
6177  renderer.state.buffers.stencil.setTest( false );
6178 
6179  }
6180 
6181 } );
6182 
6183 // Content of examples/js/postprocessing/RenderPass.js
6188 THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) {
6189 
6190  THREE.Pass.call( this );
6191 
6192  this.scene = scene;
6193  this.camera = camera;
6194 
6195  this.overrideMaterial = overrideMaterial;
6196 
6197  this.clearColor = clearColor;
6198  this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
6199 
6200  this.clear = true;
6201  this.clearDepth = false;
6202  this.needsSwap = false;
6203 
6204 };
6205 
6206 THREE.RenderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
6207 
6208  constructor: THREE.RenderPass,
6209 
6210  render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
6211 
6212  var oldAutoClear = renderer.autoClear;
6213  renderer.autoClear = false;
6214 
6215  this.scene.overrideMaterial = this.overrideMaterial;
6216 
6217  var oldClearColor, oldClearAlpha;
6218 
6219  if ( this.clearColor ) {
6220 
6221  oldClearColor = renderer.getClearColor().getHex();
6222  oldClearAlpha = renderer.getClearAlpha();
6223 
6224  renderer.setClearColor( this.clearColor, this.clearAlpha );
6225 
6226  }
6227 
6228  if ( this.clearDepth ) {
6229 
6230  renderer.clearDepth();
6231 
6232  }
6233 
6234  renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
6235 
6236  // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
6237  if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
6238  renderer.render( this.scene, this.camera );
6239 
6240  if ( this.clearColor ) {
6241 
6242  renderer.setClearColor( oldClearColor, oldClearAlpha );
6243 
6244  }
6245 
6246  this.scene.overrideMaterial = null;
6247  renderer.autoClear = oldAutoClear;
6248 
6249  }
6250 
6251 } );
6252 
6253 // Content of examples/js/postprocessing/ShaderPass.js
6258 THREE.ShaderPass = function ( shader, textureID ) {
6259 
6260  THREE.Pass.call( this );
6261 
6262  this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
6263 
6264  if ( shader instanceof THREE.ShaderMaterial ) {
6265 
6266  this.uniforms = shader.uniforms;
6267 
6268  this.material = shader;
6269 
6270  } else if ( shader ) {
6271 
6272  this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
6273 
6274  this.material = new THREE.ShaderMaterial( {
6275 
6276  defines: Object.assign( {}, shader.defines ),
6277  uniforms: this.uniforms,
6278  vertexShader: shader.vertexShader,
6279  fragmentShader: shader.fragmentShader
6280 
6281  } );
6282 
6283  }
6284 
6285  this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
6286  this.scene = new THREE.Scene();
6287 
6288  this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
6289  this.quad.frustumCulled = false; // Avoid getting clipped
6290  this.scene.add( this.quad );
6291 
6292 };
6293 
6294 THREE.ShaderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
6295 
6296  constructor: THREE.ShaderPass,
6297 
6298  render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
6299 
6300  if ( this.uniforms[ this.textureID ] ) {
6301 
6302  this.uniforms[ this.textureID ].value = readBuffer.texture;
6303 
6304  }
6305 
6306  this.quad.material = this.material;
6307 
6308  if ( this.renderToScreen ) {
6309 
6310  renderer.setRenderTarget( null );
6311  renderer.render( this.scene, this.camera );
6312 
6313  } else {
6314 
6315  renderer.setRenderTarget( writeBuffer );
6316  // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
6317  if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
6318  renderer.render( this.scene, this.camera );
6319 
6320  }
6321 
6322  }
6323 
6324 } );
6325 
6326 // Content of examples/js/shaders/SSAOShader.js
6336 THREE.SSAOShader = {
6337 
6338  defines: {
6339  "PERSPECTIVE_CAMERA": 1,
6340  "KERNEL_SIZE": 32
6341  },
6342 
6343  uniforms: {
6344 
6345  "tDiffuse": { value: null },
6346  "tNormal": { value: null },
6347  "tDepth": { value: null },
6348  "tNoise": { value: null },
6349  "kernel": { value: null },
6350  "cameraNear": { value: null },
6351  "cameraFar": { value: null },
6352  "resolution": { value: new THREE.Vector2() },
6353  "cameraProjectionMatrix": { value: new THREE.Matrix4() },
6354  "cameraInverseProjectionMatrix": { value: new THREE.Matrix4() },
6355  "kernelRadius": { value: 8 },
6356  "minDistance": { value: 0.005 },
6357  "maxDistance": { value: 0.05 },
6358 
6359  },
6360 
6361  vertexShader: [
6362 
6363  "varying vec2 vUv;",
6364 
6365  "void main() {",
6366 
6367  " vUv = uv;",
6368 
6369  " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
6370 
6371  "}"
6372 
6373  ].join( "\n" ),
6374 
6375  fragmentShader: [
6376 
6377  "uniform sampler2D tDiffuse;",
6378  "uniform sampler2D tNormal;",
6379  "uniform sampler2D tDepth;",
6380  "uniform sampler2D tNoise;",
6381 
6382  "uniform vec3 kernel[ KERNEL_SIZE ];",
6383 
6384  "uniform vec2 resolution;",
6385 
6386  "uniform float cameraNear;",
6387  "uniform float cameraFar;",
6388  "uniform mat4 cameraProjectionMatrix;",
6389  "uniform mat4 cameraInverseProjectionMatrix;",
6390 
6391  "uniform float kernelRadius;",
6392  "uniform float minDistance;", // avoid artifacts caused by neighbour fragments with minimal depth difference
6393  "uniform float maxDistance;", // avoid the influence of fragments which are too far away
6394 
6395  "varying vec2 vUv;",
6396 
6397  "#include <packing>",
6398 
6399  "float getDepth( const in vec2 screenPosition ) {",
6400 
6401  " return texture2D( tDepth, screenPosition ).x;",
6402 
6403  "}",
6404 
6405  "float getLinearDepth( const in vec2 screenPosition ) {",
6406 
6407  " #if PERSPECTIVE_CAMERA == 1",
6408 
6409  " float fragCoordZ = texture2D( tDepth, screenPosition ).x;",
6410  " float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );",
6411  " return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );",
6412 
6413  " #else",
6414 
6415  " return texture2D( depthSampler, coord ).x;",
6416 
6417  " #endif",
6418 
6419  "}",
6420 
6421  "float getViewZ( const in float depth ) {",
6422 
6423  " #if PERSPECTIVE_CAMERA == 1",
6424 
6425  " return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );",
6426 
6427  " #else",
6428 
6429  " return orthographicDepthToViewZ( depth, cameraNear, cameraFar );",
6430 
6431  " #endif",
6432 
6433  "}",
6434 
6435  "vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {",
6436 
6437  " float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];",
6438 
6439  " vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );",
6440 
6441  " clipPosition *= clipW; // unprojection.",
6442 
6443  " return ( cameraInverseProjectionMatrix * clipPosition ).xyz;",
6444 
6445  "}",
6446 
6447  "vec3 getViewNormal( const in vec2 screenPosition ) {",
6448 
6449  " return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );",
6450 
6451  "}",
6452 
6453  "void main() {",
6454 
6455  " float depth = getDepth( vUv );",
6456  " float viewZ = getViewZ( depth );",
6457 
6458  " vec3 viewPosition = getViewPosition( vUv, depth, viewZ );",
6459  " vec3 viewNormal = getViewNormal( vUv );",
6460 
6461  " vec2 noiseScale = vec2( resolution.x / 4.0, resolution.y / 4.0 );",
6462  " vec3 random = texture2D( tNoise, vUv * noiseScale ).xyz;",
6463 
6464  // compute matrix used to reorient a kernel vector
6465 
6466  " vec3 tangent = normalize( random - viewNormal * dot( random, viewNormal ) );",
6467  " vec3 bitangent = cross( viewNormal, tangent );",
6468  " mat3 kernelMatrix = mat3( tangent, bitangent, viewNormal );",
6469 
6470  " float occlusion = 0.0;",
6471 
6472  " for ( int i = 0; i < KERNEL_SIZE; i ++ ) {",
6473 
6474  " vec3 sampleVector = kernelMatrix * kernel[ i ];", // reorient sample vector in view space
6475  " vec3 samplePoint = viewPosition + ( sampleVector * kernelRadius );", // calculate sample point
6476 
6477  " vec4 samplePointNDC = cameraProjectionMatrix * vec4( samplePoint, 1.0 );", // project point and calculate NDC
6478  " samplePointNDC /= samplePointNDC.w;",
6479 
6480  " vec2 samplePointUv = samplePointNDC.xy * 0.5 + 0.5;", // compute uv coordinates
6481 
6482  " float realDepth = getLinearDepth( samplePointUv );", // get linear depth from depth texture
6483  " float sampleDepth = viewZToOrthographicDepth( samplePoint.z, cameraNear, cameraFar );", // compute linear depth of the sample view Z value
6484  " float delta = sampleDepth - realDepth;",
6485 
6486  " if ( delta > minDistance && delta < maxDistance ) {", // if fragment is before sample point, increase occlusion
6487 
6488  " occlusion += 1.0;",
6489 
6490  " }",
6491 
6492  " }",
6493 
6494  " occlusion = clamp( occlusion / float( KERNEL_SIZE ), 0.0, 1.0 );",
6495 
6496  " gl_FragColor = vec4( vec3( 1.0 - occlusion ), 1.0 );",
6497 
6498  "}"
6499 
6500  ].join( "\n" )
6501 
6502 };
6503 
6504 THREE.SSAODepthShader = {
6505 
6506  defines: {
6507  "PERSPECTIVE_CAMERA": 1
6508  },
6509 
6510  uniforms: {
6511 
6512  "tDepth": { value: null },
6513  "cameraNear": { value: null },
6514  "cameraFar": { value: null },
6515 
6516  },
6517 
6518  vertexShader: [
6519 
6520  "varying vec2 vUv;",
6521 
6522  "void main() {",
6523 
6524  " vUv = uv;",
6525  " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
6526 
6527  "}"
6528 
6529  ].join( "\n" ),
6530 
6531  fragmentShader: [
6532 
6533  "uniform sampler2D tDepth;",
6534 
6535  "uniform float cameraNear;",
6536  "uniform float cameraFar;",
6537 
6538  "varying vec2 vUv;",
6539 
6540  "#include <packing>",
6541 
6542  "float getLinearDepth( const in vec2 screenPosition ) {",
6543 
6544  " #if PERSPECTIVE_CAMERA == 1",
6545 
6546  " float fragCoordZ = texture2D( tDepth, screenPosition ).x;",
6547  " float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );",
6548  " return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );",
6549 
6550  " #else",
6551 
6552  " return texture2D( depthSampler, coord ).x;",
6553 
6554  " #endif",
6555 
6556  "}",
6557 
6558  "void main() {",
6559 
6560  " float depth = getLinearDepth( vUv );",
6561  " gl_FragColor = vec4( vec3( 1.0 - depth ), 1.0 );",
6562 
6563  "}"
6564 
6565  ].join( "\n" )
6566 
6567 };
6568 
6569 THREE.SSAOBlurShader = {
6570 
6571  uniforms: {
6572 
6573  "tDiffuse": { value: null },
6574  "resolution": { value: new THREE.Vector2() }
6575 
6576  },
6577 
6578  vertexShader: [
6579 
6580  "varying vec2 vUv;",
6581 
6582  "void main() {",
6583 
6584  " vUv = uv;",
6585  " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
6586 
6587  "}"
6588 
6589  ].join( "\n" ),
6590 
6591  fragmentShader: [
6592 
6593  "uniform sampler2D tDiffuse;",
6594 
6595  "uniform vec2 resolution;",
6596 
6597  "varying vec2 vUv;",
6598 
6599  "void main() {",
6600 
6601  " vec2 texelSize = ( 1.0 / resolution );",
6602  " float result = 0.0;",
6603 
6604  " for ( int i = - 2; i <= 2; i ++ ) {",
6605 
6606  " for ( int j = - 2; j <= 2; j ++ ) {",
6607 
6608  " vec2 offset = ( vec2( float( i ), float( j ) ) ) * texelSize;",
6609  " result += texture2D( tDiffuse, vUv + offset ).r;",
6610 
6611  " }",
6612 
6613  " }",
6614 
6615  " gl_FragColor = vec4( vec3( result / ( 5.0 * 5.0 ) ), 1.0 );",
6616 
6617  "}"
6618 
6619  ].join( "\n" )
6620 
6621 };
6622 
6623 // Content of examples/js/postprocessing/SSAOPass.js
6628 THREE.SSAOPass = function ( scene, camera, width, height ) {
6629 
6630  THREE.Pass.call( this );
6631 
6632  this.width = ( width !== undefined ) ? width : 512;
6633  this.height = ( height !== undefined ) ? height : 512;
6634 
6635  this.clear = true;
6636 
6637  this.camera = camera;
6638  this.scene = scene;
6639 
6640  this.kernelRadius = 8;
6641  this.kernelSize = 32;
6642  this.kernel = [];
6643  this.noiseTexture = null;
6644  this.output = 0;
6645 
6646  this.minDistance = 0.005;
6647  this.maxDistance = 0.1;
6648 
6649  //
6650 
6651  this.generateSampleKernel();
6652  this.generateRandomKernelRotations();
6653 
6654  // beauty render target with depth buffer
6655 
6656  var depthTexture = new THREE.DepthTexture();
6657  depthTexture.type = THREE.UnsignedShortType;
6658  depthTexture.minFilter = THREE.NearestFilter;
6659  depthTexture.maxFilter = THREE.NearestFilter;
6660 
6661  this.beautyRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
6662  minFilter: THREE.LinearFilter,
6663  magFilter: THREE.LinearFilter,
6664  format: THREE.RGBAFormat,
6665  depthTexture: depthTexture,
6666  depthBuffer: true
6667  } );
6668 
6669  // normal render target
6670 
6671  this.normalRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
6672  minFilter: THREE.NearestFilter,
6673  magFilter: THREE.NearestFilter,
6674  format: THREE.RGBAFormat
6675  } );
6676 
6677  // ssao render target
6678 
6679  this.ssaoRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
6680  minFilter: THREE.LinearFilter,
6681  magFilter: THREE.LinearFilter,
6682  format: THREE.RGBAFormat
6683  } );
6684 
6685  this.blurRenderTarget = this.ssaoRenderTarget.clone();
6686 
6687  // ssao material
6688 
6689  if ( THREE.SSAOShader === undefined ) {
6690 
6691  console.error( 'THREE.SSAOPass: The pass relies on THREE.SSAOShader.' );
6692 
6693  }
6694 
6695  this.ssaoMaterial = new THREE.ShaderMaterial( {
6696  defines: Object.assign( {}, THREE.SSAOShader.defines ),
6697  uniforms: THREE.UniformsUtils.clone( THREE.SSAOShader.uniforms ),
6698  vertexShader: THREE.SSAOShader.vertexShader,
6699  fragmentShader: THREE.SSAOShader.fragmentShader,
6700  blending: THREE.NoBlending
6701  } );
6702 
6703  this.ssaoMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
6704  this.ssaoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
6705  this.ssaoMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
6706  this.ssaoMaterial.uniforms[ 'tNoise' ].value = this.noiseTexture;
6707  this.ssaoMaterial.uniforms[ 'kernel' ].value = this.kernel;
6708  this.ssaoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
6709  this.ssaoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
6710  this.ssaoMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
6711  this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
6712  this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.camera.projectionMatrix );
6713 
6714  // normal material
6715 
6716  this.normalMaterial = new THREE.MeshNormalMaterial();
6717  this.normalMaterial.blending = THREE.NoBlending;
6718 
6719  // blur material
6720 
6721  this.blurMaterial = new THREE.ShaderMaterial( {
6722  defines: Object.assign( {}, THREE.SSAOBlurShader.defines ),
6723  uniforms: THREE.UniformsUtils.clone( THREE.SSAOBlurShader.uniforms ),
6724  vertexShader: THREE.SSAOBlurShader.vertexShader,
6725  fragmentShader: THREE.SSAOBlurShader.fragmentShader
6726  } );
6727  this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
6728  this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
6729 
6730  // material for rendering the depth
6731 
6732  this.depthRenderMaterial = new THREE.ShaderMaterial( {
6733  defines: Object.assign( {}, THREE.SSAODepthShader.defines ),
6734  uniforms: THREE.UniformsUtils.clone( THREE.SSAODepthShader.uniforms ),
6735  vertexShader: THREE.SSAODepthShader.vertexShader,
6736  fragmentShader: THREE.SSAODepthShader.fragmentShader,
6737  blending: THREE.NoBlending
6738  } );
6739  this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
6740  this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
6741  this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
6742 
6743  // material for rendering the content of a render target
6744 
6745  this.copyMaterial = new THREE.ShaderMaterial( {
6746  uniforms: THREE.UniformsUtils.clone( THREE.CopyShader.uniforms ),
6747  vertexShader: THREE.CopyShader.vertexShader,
6748  fragmentShader: THREE.CopyShader.fragmentShader,
6749  transparent: true,
6750  depthTest: false,
6751  depthWrite: false,
6752  blendSrc: THREE.DstColorFactor,
6753  blendDst: THREE.ZeroFactor,
6754  blendEquation: THREE.AddEquation,
6755  blendSrcAlpha: THREE.DstAlphaFactor,
6756  blendDstAlpha: THREE.ZeroFactor,
6757  blendEquationAlpha: THREE.AddEquation
6758  } );
6759 
6760  //
6761 
6762  this.quadCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
6763  this.quadScene = new THREE.Scene();
6764  this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
6765  this.quadScene.add( this.quad );
6766 
6767  //
6768 
6769  this.originalClearColor = new THREE.Color();
6770 
6771 };
6772 
6773 THREE.SSAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
6774 
6775  constructor: THREE.SSAOPass,
6776 
6777  dispose: function () {
6778 
6779  // dispose render targets
6780 
6781  this.beautyRenderTarget.dispose();
6782  this.normalRenderTarget.dispose();
6783  this.ssaoRenderTarget.dispose();
6784  this.blurRenderTarget.dispose();
6785 
6786  // dispose geometry
6787 
6788  this.quad.geometry.dispose();
6789 
6790  // dispose materials
6791 
6792  this.normalMaterial.dispose();
6793  this.blurMaterial.dispose();
6794  this.copyMaterial.dispose();
6795  this.depthRenderMaterial.dispose();
6796 
6797  },
6798 
6799  render: function ( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) {
6800 
6801  // render beauty and depth
6802 
6803  renderer.setRenderTarget( this.beautyRenderTarget );
6804  renderer.clear();
6805  renderer.render( this.scene, this.camera );
6806 
6807  // render normals
6808 
6809  this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
6810 
6811  // render SSAO
6812 
6813  this.ssaoMaterial.uniforms[ 'kernelRadius' ].value = this.kernelRadius;
6814  this.ssaoMaterial.uniforms[ 'minDistance' ].value = this.minDistance;
6815  this.ssaoMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
6816  this.renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget );
6817 
6818  // render blur
6819 
6820  this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
6821 
6822  // output result to screen
6823 
6824  switch ( this.output ) {
6825 
6826  case THREE.SSAOPass.OUTPUT.SSAO:
6827 
6828  this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
6829  this.copyMaterial.blending = THREE.NoBlending;
6830  this.renderPass( renderer, this.copyMaterial, null );
6831 
6832  break;
6833 
6834  case THREE.SSAOPass.OUTPUT.Blur:
6835 
6836  this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
6837  this.copyMaterial.blending = THREE.NoBlending;
6838  this.renderPass( renderer, this.copyMaterial, null );
6839 
6840  break;
6841 
6842  case THREE.SSAOPass.OUTPUT.Beauty:
6843 
6844  this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
6845  this.copyMaterial.blending = THREE.NoBlending;
6846  this.renderPass( renderer, this.copyMaterial, null );
6847 
6848  break;
6849 
6850  case THREE.SSAOPass.OUTPUT.Depth:
6851 
6852  this.renderPass( renderer, this.depthRenderMaterial, null );
6853 
6854  break;
6855 
6856  case THREE.SSAOPass.OUTPUT.Normal:
6857 
6858  this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
6859  this.copyMaterial.blending = THREE.NoBlending;
6860  this.renderPass( renderer, this.copyMaterial, null );
6861 
6862  break;
6863 
6864  case THREE.SSAOPass.OUTPUT.Default:
6865 
6866  this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
6867  this.copyMaterial.blending = THREE.NoBlending;
6868  this.renderPass( renderer, this.copyMaterial, null );
6869 
6870  this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
6871  this.copyMaterial.blending = THREE.CustomBlending;
6872  this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
6873 
6874  break;
6875 
6876  default:
6877  console.warn( 'THREE.SSAOPass: Unknown output type.' );
6878 
6879  }
6880 
6881  },
6882 
6883  renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
6884 
6885  // save original state
6886  this.originalClearColor.copy( renderer.getClearColor() );
6887  var originalClearAlpha = renderer.getClearAlpha();
6888  var originalAutoClear = renderer.autoClear;
6889 
6890  renderer.setRenderTarget( renderTarget );
6891 
6892  // setup pass state
6893  renderer.autoClear = false;
6894  if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
6895 
6896  renderer.setClearColor( clearColor );
6897  renderer.setClearAlpha( clearAlpha || 0.0 );
6898  renderer.clear();
6899 
6900  }
6901 
6902  this.quad.material = passMaterial;
6903  renderer.render( this.quadScene, this.quadCamera );
6904 
6905  // restore original state
6906  renderer.autoClear = originalAutoClear;
6907  renderer.setClearColor( this.originalClearColor );
6908  renderer.setClearAlpha( originalClearAlpha );
6909 
6910  },
6911 
6912  renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
6913 
6914  this.originalClearColor.copy( renderer.getClearColor() );
6915  var originalClearAlpha = renderer.getClearAlpha();
6916  var originalAutoClear = renderer.autoClear;
6917 
6918  renderer.setRenderTarget( renderTarget );
6919  renderer.autoClear = false;
6920 
6921  clearColor = overrideMaterial.clearColor || clearColor;
6922  clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
6923 
6924  if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
6925 
6926  renderer.setClearColor( clearColor );
6927  renderer.setClearAlpha( clearAlpha || 0.0 );
6928  renderer.clear();
6929 
6930  }
6931 
6932  this.scene.overrideMaterial = overrideMaterial;
6933  renderer.render( this.scene, this.camera );
6934  this.scene.overrideMaterial = null;
6935 
6936  // restore original state
6937 
6938  renderer.autoClear = originalAutoClear;
6939  renderer.setClearColor( this.originalClearColor );
6940  renderer.setClearAlpha( originalClearAlpha );
6941 
6942  },
6943 
6944  setSize: function ( width, height ) {
6945 
6946  this.width = width;
6947  this.height = height;
6948 
6949  this.beautyRenderTarget.setSize( width, height );
6950  this.ssaoRenderTarget.setSize( width, height );
6951  this.normalRenderTarget.setSize( width, height );
6952  this.blurRenderTarget.setSize( width, height );
6953 
6954  this.ssaoMaterial.uniforms[ 'resolution' ].value.set( width, height );
6955  this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
6956  this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.camera.projectionMatrix );
6957 
6958  this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
6959 
6960  },
6961 
6962  generateSampleKernel: function () {
6963 
6964  var kernelSize = this.kernelSize;
6965  var kernel = this.kernel;
6966 
6967  for ( var i = 0; i < kernelSize; i ++ ) {
6968 
6969  var sample = new THREE.Vector3();
6970  sample.x = ( Math.random() * 2 ) - 1;
6971  sample.y = ( Math.random() * 2 ) - 1;
6972  sample.z = Math.random();
6973 
6974  sample.normalize();
6975 
6976  var scale = i / kernelSize;
6977  scale = THREE.Math.lerp( 0.1, 1, scale * scale );
6978  sample.multiplyScalar( scale );
6979 
6980  kernel.push( sample );
6981 
6982  }
6983 
6984  },
6985 
6986  generateRandomKernelRotations: function () {
6987 
6988  var width = 4, height = 4;
6989 
6990  if ( SimplexNoise === undefined ) {
6991 
6992  console.error( 'THREE.SSAOPass: The pass relies on THREE.SimplexNoise.' );
6993 
6994  }
6995 
6996  var simplex = new SimplexNoise();
6997 
6998  var size = width * height;
6999  var data = new Float32Array( size * 4 );
7000 
7001  for ( var i = 0; i < size; i ++ ) {
7002 
7003  var stride = i * 4;
7004 
7005  var x = ( Math.random() * 2 ) - 1;
7006  var y = ( Math.random() * 2 ) - 1;
7007  var z = 0;
7008 
7009  var noise = simplex.noise3d( x, y, z );
7010 
7011  data[ stride ] = noise;
7012  data[ stride + 1 ] = noise;
7013  data[ stride + 2 ] = noise;
7014  data[ stride + 3 ] = 1;
7015 
7016  }
7017 
7018  this.noiseTexture = new THREE.DataTexture( data, width, height, THREE.RGBAFormat, THREE.FloatType );
7019  this.noiseTexture.wrapS = THREE.RepeatWrapping;
7020  this.noiseTexture.wrapT = THREE.RepeatWrapping;
7021  this.noiseTexture.needsUpdate = true;
7022 
7023  }
7024 
7025 } );
7026 
7027 THREE.SSAOPass.OUTPUT = {
7028  'Default': 0,
7029  'SSAO': 1,
7030  'Blur': 2,
7031  'Beauty': 3,
7032  'Depth': 4,
7033  'Normal': 5
7034 };
7035 
7036 // Content of examples/js/SimplexNoise.js
7037 // Ported from Stefan Gustavson's java implementation
7038 // http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
7039 // Read Stefan's excellent paper for details on how this code works.
7040 //
7041 // Sean McCullough banksean@gmail.com
7042 //
7043 // Added 4D noise
7044 // Joshua Koo zz85nus@gmail.com
7045 
7050 var SimplexNoise = function(r) {
7051  if (r == undefined) r = Math;
7052  this.grad3 = [[ 1,1,0 ],[ -1,1,0 ],[ 1,-1,0 ],[ -1,-1,0 ],
7053  [ 1,0,1 ],[ -1,0,1 ],[ 1,0,-1 ],[ -1,0,-1 ],
7054  [ 0,1,1 ],[ 0,-1,1 ],[ 0,1,-1 ],[ 0,-1,-1 ]];
7055 
7056  this.grad4 = [[ 0,1,1,1 ], [ 0,1,1,-1 ], [ 0,1,-1,1 ], [ 0,1,-1,-1 ],
7057  [ 0,-1,1,1 ], [ 0,-1,1,-1 ], [ 0,-1,-1,1 ], [ 0,-1,-1,-1 ],
7058  [ 1,0,1,1 ], [ 1,0,1,-1 ], [ 1,0,-1,1 ], [ 1,0,-1,-1 ],
7059  [ -1,0,1,1 ], [ -1,0,1,-1 ], [ -1,0,-1,1 ], [ -1,0,-1,-1 ],
7060  [ 1,1,0,1 ], [ 1,1,0,-1 ], [ 1,-1,0,1 ], [ 1,-1,0,-1 ],
7061  [ -1,1,0,1 ], [ -1,1,0,-1 ], [ -1,-1,0,1 ], [ -1,-1,0,-1 ],
7062  [ 1,1,1,0 ], [ 1,1,-1,0 ], [ 1,-1,1,0 ], [ 1,-1,-1,0 ],
7063  [ -1,1,1,0 ], [ -1,1,-1,0 ], [ -1,-1,1,0 ], [ -1,-1,-1,0 ]];
7064 
7065  this.p = [];
7066  for (var i = 0; i < 256; i ++) {
7067  this.p[i] = Math.floor(r.random() * 256);
7068  }
7069  // To remove the need for index wrapping, double the permutation table length
7070  this.perm = [];
7071  for (var i = 0; i < 512; i ++) {
7072  this.perm[i] = this.p[i & 255];
7073  }
7074 
7075  // A lookup table to traverse the simplex around a given point in 4D.
7076  // Details can be found where this table is used, in the 4D noise method.
7077  this.simplex = [
7078  [ 0,1,2,3 ],[ 0,1,3,2 ],[ 0,0,0,0 ],[ 0,2,3,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,2,3,0 ],
7079  [ 0,2,1,3 ],[ 0,0,0,0 ],[ 0,3,1,2 ],[ 0,3,2,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,3,2,0 ],
7080  [ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],
7081  [ 1,2,0,3 ],[ 0,0,0,0 ],[ 1,3,0,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,3,0,1 ],[ 2,3,1,0 ],
7082  [ 1,0,2,3 ],[ 1,0,3,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,0,3,1 ],[ 0,0,0,0 ],[ 2,1,3,0 ],
7083  [ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],
7084  [ 2,0,1,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,0,1,2 ],[ 3,0,2,1 ],[ 0,0,0,0 ],[ 3,1,2,0 ],
7085  [ 2,1,0,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,1,0,2 ],[ 0,0,0,0 ],[ 3,2,0,1 ],[ 3,2,1,0 ]];
7086 };
7087 
7088 SimplexNoise.prototype.dot = function(g, x, y) {
7089  return g[0] * x + g[1] * y;
7090 };
7091 
7092 SimplexNoise.prototype.dot3 = function(g, x, y, z) {
7093  return g[0] * x + g[1] * y + g[2] * z;
7094 };
7095 
7096 SimplexNoise.prototype.dot4 = function(g, x, y, z, w) {
7097  return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
7098 };
7099 
7100 SimplexNoise.prototype.noise = function(xin, yin) {
7101  var n0, n1, n2; // Noise contributions from the three corners
7102  // Skew the input space to determine which simplex cell we're in
7103  var F2 = 0.5 * (Math.sqrt(3.0) - 1.0);
7104  var s = (xin + yin) * F2; // Hairy factor for 2D
7105  var i = Math.floor(xin + s);
7106  var j = Math.floor(yin + s);
7107  var G2 = (3.0 - Math.sqrt(3.0)) / 6.0;
7108  var t = (i + j) * G2;
7109  var X0 = i - t; // Unskew the cell origin back to (x,y) space
7110  var Y0 = j - t;
7111  var x0 = xin - X0; // The x,y distances from the cell origin
7112  var y0 = yin - Y0;
7113  // For the 2D case, the simplex shape is an equilateral triangle.
7114  // Determine which simplex we are in.
7115  var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
7116  if (x0 > y0) {i1 = 1; j1 = 0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
7117  else {i1 = 0; j1 = 1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
7118  // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
7119  // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
7120  // c = (3-sqrt(3))/6
7121  var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
7122  var y1 = y0 - j1 + G2;
7123  var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
7124  var y2 = y0 - 1.0 + 2.0 * G2;
7125  // Work out the hashed gradient indices of the three simplex corners
7126  var ii = i & 255;
7127  var jj = j & 255;
7128  var gi0 = this.perm[ii + this.perm[jj]] % 12;
7129  var gi1 = this.perm[ii + i1 + this.perm[jj + j1]] % 12;
7130  var gi2 = this.perm[ii + 1 + this.perm[jj + 1]] % 12;
7131  // Calculate the contribution from the three corners
7132  var t0 = 0.5 - x0 * x0 - y0 * y0;
7133  if (t0 < 0) n0 = 0.0;
7134  else {
7135  t0 *= t0;
7136  n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient
7137  }
7138  var t1 = 0.5 - x1 * x1 - y1 * y1;
7139  if (t1 < 0) n1 = 0.0;
7140  else {
7141  t1 *= t1;
7142  n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1);
7143  }
7144  var t2 = 0.5 - x2 * x2 - y2 * y2;
7145  if (t2 < 0) n2 = 0.0;
7146  else {
7147  t2 *= t2;
7148  n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2);
7149  }
7150  // Add contributions from each corner to get the final noise value.
7151  // The result is scaled to return values in the interval [-1,1].
7152  return 70.0 * (n0 + n1 + n2);
7153 };
7154 
7155 // 3D simplex noise
7156 SimplexNoise.prototype.noise3d = function(xin, yin, zin) {
7157  var n0, n1, n2, n3; // Noise contributions from the four corners
7158  // Skew the input space to determine which simplex cell we're in
7159  var F3 = 1.0 / 3.0;
7160  var s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D
7161  var i = Math.floor(xin + s);
7162  var j = Math.floor(yin + s);
7163  var k = Math.floor(zin + s);
7164  var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too
7165  var t = (i + j + k) * G3;
7166  var X0 = i - t; // Unskew the cell origin back to (x,y,z) space
7167  var Y0 = j - t;
7168  var Z0 = k - t;
7169  var x0 = xin - X0; // The x,y,z distances from the cell origin
7170  var y0 = yin - Y0;
7171  var z0 = zin - Z0;
7172  // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
7173  // Determine which simplex we are in.
7174  var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
7175  var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
7176  if (x0 >= y0) {
7177  if (y0 >= z0)
7178  { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // X Y Z order
7179  else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } // X Z Y order
7180  else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } // Z X Y order
7181  }
7182  else { // x0<y0
7183  if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } // Z Y X order
7184  else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } // Y Z X order
7185  else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // Y X Z order
7186  }
7187  // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
7188  // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
7189  // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
7190  // c = 1/6.
7191  var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
7192  var y1 = y0 - j1 + G3;
7193  var z1 = z0 - k1 + G3;
7194  var x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
7195  var y2 = y0 - j2 + 2.0 * G3;
7196  var z2 = z0 - k2 + 2.0 * G3;
7197  var x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
7198  var y3 = y0 - 1.0 + 3.0 * G3;
7199  var z3 = z0 - 1.0 + 3.0 * G3;
7200  // Work out the hashed gradient indices of the four simplex corners
7201  var ii = i & 255;
7202  var jj = j & 255;
7203  var kk = k & 255;
7204  var gi0 = this.perm[ii + this.perm[jj + this.perm[kk]]] % 12;
7205  var gi1 = this.perm[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]] % 12;
7206  var gi2 = this.perm[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]] % 12;
7207  var gi3 = this.perm[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]] % 12;
7208  // Calculate the contribution from the four corners
7209  var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
7210  if (t0 < 0) n0 = 0.0;
7211  else {
7212  t0 *= t0;
7213  n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0);
7214  }
7215  var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
7216  if (t1 < 0) n1 = 0.0;
7217  else {
7218  t1 *= t1;
7219  n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1);
7220  }
7221  var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
7222  if (t2 < 0) n2 = 0.0;
7223  else {
7224  t2 *= t2;
7225  n2 = t2 * t2 * this.dot3(this.grad3[gi2], x2, y2, z2);
7226  }
7227  var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
7228  if (t3 < 0) n3 = 0.0;
7229  else {
7230  t3 *= t3;
7231  n3 = t3 * t3 * this.dot3(this.grad3[gi3], x3, y3, z3);
7232  }
7233  // Add contributions from each corner to get the final noise value.
7234  // The result is scaled to stay just inside [-1,1]
7235  return 32.0 * (n0 + n1 + n2 + n3);
7236 };
7237 
7238 // 4D simplex noise
7239 SimplexNoise.prototype.noise4d = function( x, y, z, w ) {
7240  // For faster and easier lookups
7241  var grad4 = this.grad4;
7242  var simplex = this.simplex;
7243  var perm = this.perm;
7244 
7245  // The skewing and unskewing factors are hairy again for the 4D case
7246  var F4 = (Math.sqrt(5.0) - 1.0) / 4.0;
7247  var G4 = (5.0 - Math.sqrt(5.0)) / 20.0;
7248  var n0, n1, n2, n3, n4; // Noise contributions from the five corners
7249  // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
7250  var s = (x + y + z + w) * F4; // Factor for 4D skewing
7251  var i = Math.floor(x + s);
7252  var j = Math.floor(y + s);
7253  var k = Math.floor(z + s);
7254  var l = Math.floor(w + s);
7255  var t = (i + j + k + l) * G4; // Factor for 4D unskewing
7256  var X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
7257  var Y0 = j - t;
7258  var Z0 = k - t;
7259  var W0 = l - t;
7260  var x0 = x - X0; // The x,y,z,w distances from the cell origin
7261  var y0 = y - Y0;
7262  var z0 = z - Z0;
7263  var w0 = w - W0;
7264 
7265  // For the 4D case, the simplex is a 4D shape I won't even try to describe.
7266  // To find out which of the 24 possible simplices we're in, we need to
7267  // determine the magnitude ordering of x0, y0, z0 and w0.
7268  // The method below is a good way of finding the ordering of x,y,z,w and
7269  // then find the correct traversal order for the simplex we’re in.
7270  // First, six pair-wise comparisons are performed between each possible pair
7271  // of the four coordinates, and the results are used to add up binary bits
7272  // for an integer index.
7273  var c1 = (x0 > y0) ? 32 : 0;
7274  var c2 = (x0 > z0) ? 16 : 0;
7275  var c3 = (y0 > z0) ? 8 : 0;
7276  var c4 = (x0 > w0) ? 4 : 0;
7277  var c5 = (y0 > w0) ? 2 : 0;
7278  var c6 = (z0 > w0) ? 1 : 0;
7279  var c = c1 + c2 + c3 + c4 + c5 + c6;
7280  var i1, j1, k1, l1; // The integer offsets for the second simplex corner
7281  var i2, j2, k2, l2; // The integer offsets for the third simplex corner
7282  var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
7283  // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
7284  // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
7285  // impossible. Only the 24 indices which have non-zero entries make any sense.
7286  // We use a thresholding to set the coordinates in turn from the largest magnitude.
7287  // The number 3 in the "simplex" array is at the position of the largest coordinate.
7288  i1 = simplex[c][0] >= 3 ? 1 : 0;
7289  j1 = simplex[c][1] >= 3 ? 1 : 0;
7290  k1 = simplex[c][2] >= 3 ? 1 : 0;
7291  l1 = simplex[c][3] >= 3 ? 1 : 0;
7292  // The number 2 in the "simplex" array is at the second largest coordinate.
7293  i2 = simplex[c][0] >= 2 ? 1 : 0;
7294  j2 = simplex[c][1] >= 2 ? 1 : 0; k2 = simplex[c][2] >= 2 ? 1 : 0;
7295  l2 = simplex[c][3] >= 2 ? 1 : 0;
7296  // The number 1 in the "simplex" array is at the second smallest coordinate.
7297  i3 = simplex[c][0] >= 1 ? 1 : 0;
7298  j3 = simplex[c][1] >= 1 ? 1 : 0;
7299  k3 = simplex[c][2] >= 1 ? 1 : 0;
7300  l3 = simplex[c][3] >= 1 ? 1 : 0;
7301  // The fifth corner has all coordinate offsets = 1, so no need to look that up.
7302  var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
7303  var y1 = y0 - j1 + G4;
7304  var z1 = z0 - k1 + G4;
7305  var w1 = w0 - l1 + G4;
7306  var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
7307  var y2 = y0 - j2 + 2.0 * G4;
7308  var z2 = z0 - k2 + 2.0 * G4;
7309  var w2 = w0 - l2 + 2.0 * G4;
7310  var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
7311  var y3 = y0 - j3 + 3.0 * G4;
7312  var z3 = z0 - k3 + 3.0 * G4;
7313  var w3 = w0 - l3 + 3.0 * G4;
7314  var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
7315  var y4 = y0 - 1.0 + 4.0 * G4;
7316  var z4 = z0 - 1.0 + 4.0 * G4;
7317  var w4 = w0 - 1.0 + 4.0 * G4;
7318  // Work out the hashed gradient indices of the five simplex corners
7319  var ii = i & 255;
7320  var jj = j & 255;
7321  var kk = k & 255;
7322  var ll = l & 255;
7323  var gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32;
7324  var gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32;
7325  var gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32;
7326  var gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32;
7327  var gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32;
7328  // Calculate the contribution from the five corners
7329  var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
7330  if (t0 < 0) n0 = 0.0;
7331  else {
7332  t0 *= t0;
7333  n0 = t0 * t0 * this.dot4(grad4[gi0], x0, y0, z0, w0);
7334  }
7335  var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
7336  if (t1 < 0) n1 = 0.0;
7337  else {
7338  t1 *= t1;
7339  n1 = t1 * t1 * this.dot4(grad4[gi1], x1, y1, z1, w1);
7340  }
7341  var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
7342  if (t2 < 0) n2 = 0.0;
7343  else {
7344  t2 *= t2;
7345  n2 = t2 * t2 * this.dot4(grad4[gi2], x2, y2, z2, w2);
7346  } var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
7347  if (t3 < 0) n3 = 0.0;
7348  else {
7349  t3 *= t3;
7350  n3 = t3 * t3 * this.dot4(grad4[gi3], x3, y3, z3, w3);
7351  }
7352  var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
7353  if (t4 < 0) n4 = 0.0;
7354  else {
7355  t4 *= t4;
7356  n4 = t4 * t4 * this.dot4(grad4[gi4], x4, y4, z4, w4);
7357  }
7358  // Sum up and scale the result to cover the range [-1,1]
7359  return 27.0 * (n0 + n1 + n2 + n3 + n4);
7360 };
7361 
7362 
7363 }));