<!DOCTYPE html> <html> <head> <script type="text/javascript"> // timing start _pageLoadingStartAt = +new Date; // offline detection IS_OFFLINE = (document.location.protocol == 'file:'); // iframe -- IS_IFRAME = (window.top !== window.self); </script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Geodesic dome calculator - Acidome.ru</title> <!-- FB meta --> <!-- <meta property="og:image" content="http://acidome.ru/lab/calc/i/GeodesicTessellation.png" />--> <meta property="og:image" content="http://dreamscope-prod-v1.s3.amazonaws.com/images/d57c53fa-37f9-4a6b-b5d7-d17a6d355415.jpeg"/> <style type="text/css" rel="stylesheet">/* page */ body, html { min-height: 101vh; margin: 0; padding: 0; font-family: Tahoma, Verdana, Arial, sans-serif; } /* offline */ .offline .welcome .download { display: none; } /* iframe */ .iframe .head, .iframe .welcome, .iframe .geodesic form, .iframe .budget-list { display: none } .iframe .copyleft { position: absolute; bottom: 8px; right: 8px; } /* shortcuts */ .absolute { position: absolute; } .transparent { background-color: white; background-color: rgba(255, 255, 255, 0.9); } .right { right: 0; } .left { left: 0; } .bottom { bottom: 0; } .margin { margin: 1em; } .big-font { font-size: 141%; } .small-font { font-size: 70%; } .red { color: red } .gray { color: gray } .bold { font-weight: bold } .pseudo { border-bottom: 1px black dashed; text-decoration: none; color: green; } /* buttons */ .button { padding: 6px 10px 6px 10px; border: 1px solid gray; border-radius: 10px; background-color: #ddd; cursor: pointer; } .button.round { height: 26px; border-radius: 50%; line-height: 26px; text-align: center; } .button.active { background-color: white; } .button:hover { background-color: #eee; } /*.button.active { color: white; }*/ /* common calc place */ .geodesic { position: relative; font-size: 12px; } /* preview place */ .geodesic canvas.preview { margin: 0; border: 0; } /* head */ .geodesic .head { position: absolute; top: 0; width: 100%; height: 50px; padding: 0; margin: 0; font-size: 13px; text-align: right; } .geodesic .head .title { float: left; font-size: 1.3em; padding: 5px; } /*.geodesic .head .revision { font-size: 38%; }*/ /*.geodesic .head .version { position: absolute; top: 0; left: 38%; font-size: 12px; line-height: 20px; text-decoration: none; }*/ .geodesic .welcome { float: right; padding: 5px; font-family: monospace } .geodesic .welcome .sample-to-use { color: red; } .geodesic .welcome .facebook-group { color: green; } .geodesic .welcome > * { margin-bottom: .6em; } .geodesic h1 { display: inline; font-size: 20px; margin: 0 } .geodesic h2 { font-size: 18px; border-bottom: 1px solid gray; margin-top: 1em } .geodesic h3 { font-size: 16px; } .geodesic h4 { font-size: 14px; } .geodesic .lang-select { font-size: .8em } /* info */ /*.geodesic .info { float: right }*/ /* form */ .geodesic .options { position: absolute; top: 50px; width: 300px; padding: 5px; } .geodesic .options h3 { display: inline-block; border-bottom: 1px solid gray; font-size: 15px; color: black; } .geodesic .options dl { min-height: 24px; line-height: 24px; overflow-x: auto; width: 100% } .geodesic .options dt { width: 133px; float: left; text-align: right; margin-right: 4px; overflow: visible; } .geodesic .options dd { margin-left: 133px; overflow: hidden } .geodesic .options .sub dt { width: 157px; } .geodesic .options .sub dd { margin-left: 157px; } .geodesic .options input { max-width: 50px; } .geodesic .progress { display: none; position: absolute; top: 0; left: 0; width: 280px; text-align: right; color: #bbb; } .geodesic .options input, .geodesic .options select { font-weight: bolder } .geodesic .mode-list { position: absolute; top: 0; left: 100%; width: 34em; margin-top: 10px; padding: 0; } .geodesic .mode:first-child { margin-left: -8px; } .geodesic .mode { list-style-type: none; display: inline-block; margin-right: -8px; } .geodesic .mode.active { border-color: black; } .geodesic .stat { position: absolute; top: 0; left: 100%; margin-top: 90px; } .geodesic .stat .toggle { display: inline-block; padding: 6px 10px 6px 10px; font-family: monospace; border: none; cursor: pointer; } .geodesic .stat .report { display: none; } .geodesic .stat.active .report { display: block; line-height: 20px; font-size: 1.2em; } .geodesic .stat.active { padding: 6px 10px 6px 10px; } .geodesic .stat.active .toggle { padding: 0; border-color: white; } .geodesic .stat.active .content { display: block; } /* plot */ .geodesic .budget-list { margin: 1em } .geodesic .budget-list ul { list-style-type: none; padding: 0; margin-top: 20px; font-size: 0 } .geodesic .budget-list li { margin-top: 20px; font-size: 12px } .geodesic .product { display: inline-block; padding: 0 0 16px 0; vertical-align: top; } .geodesic .product canvas { display: inline; padding-top: 10px; } .geodesic .product-index { display: inline-block; width: 2em; line-height: 2em; margin-right: 1em; border-radius: 50%; text-align: center; text-shadow: 0 0 .5em white, 0 0 .5em white; box-shadow: inset 0 0 2px white; font-size: 1.8em; } .geodesic .product-index + span { font-size: 1.6em; } /* ask */ .donation { position: relative; min-height: 24px; padding-top: 5px; } .donation__popup { display: none; position: absolute; right: 0; margin-top: -24px; border: 1px gray solid; padding: 1em; min-width: 440px; background-color: white; z-index: 1; } .donation:hover + .donation__popup, .donation__popup:hover { display: block } .donation__popup > .yandex { margin-bottom: 1em; width: 100%; } .donation__popup > .paypal { float: right; display: inline-block; } .donation__popup > .visa { float: left; display: inline-block; padding-left: 40px; height: 32px; line-height: 32px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAKQWlDQ1BJQ0MgUHJvZmlsZQAAeAGdlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/ul8iYiAAADiElEQVRYCe1WWUhUYRT+xmWcxhyrccZSNCtqIlMUNMqk1HwrS4OgghbspYcoqKDoJSl7iLaHog1bHyorjYLURMsoixaSlMSyLFu0hkYdl9FxdKZzfucOc620B6+9eODcfz/fd89y/6tyuVz4n+LzP8EZe4zAmAf8OBFUKlUENTNJQ3k8CvKDMOqpAr/AXYZpdru9k/qjIoxFBNIIDMIDNAhVq9WBKy89xq16s6IOyJppROGG5EDGZCCJgAAV4L6yKTE/ko/BL/g7Wn/fSOINa0tGwJGzfNgDI71B9h1wOp2Q9FhpFfy3X8CsAzc8c2cqapBxshhtth7477yIwyWv0N3rwOXKWhj3XsW0/dfR3Nrp2b+n8KmwUfCi3jPH9r1FRoCzUtKtS2KBAH+A7iqeM1u7sOXea3H20btvgNOFhKkG5Nx5jk0Fz9Da0YOvrV1IP1Ui9n62tOPQk7dif4vN7rHLtrxFFoLB7FKmTEBje7dgn1v8CrA7kDEnHPdqv9ItooIhSIOjzz8gMWwiHm5b6m0XW69XCpI8+aPdJmzINrgHf/UAM50bGgwnuaCq0YwzLxuwMFKPdfNNKHr/HQsIdIpOi4VhE/CiqRXltQPfFD5X19yCvKpPglimKQyWITwgIyDFX2pNBh0c5Oodt19SwfrgeNY8NJjb8KXNhtTpRmjVvri2fjESiETGtSc4cb8aHd12HCytRrwxGIXZqTCOD0Cz2wOSXW9PDBmC8GAtmgiMdV9aNGYQoXOVdeJ8QkSIcGs7Ad7cmILM8xXYVVoDFa3mc4hIInILRZsUMenfQiAxlNpQnUYYMBmCsHnRbGGkqK5JzM2erENWXjmij9zF8Qdv8I0qIy0qBL6UGyxxFL6Pu1cg2qjDd1uvOCvZFRvcjyFDMEmrFttOr0iAL/WsFMuyxp+IJeP6QA1WxUTCQCSPUH5sjovC+dVJXDIwhQQhf10ydBo/GMep0eBO5D8RUHHS0G24htorFovFm5xifb1ez5hrCfOqLAdctxMVA5UZzm7wDCUCA4GjaT91v2dRiU5fLwdTiMD0I1fQ5w4i21zGdPSZy9zryjSM4RYNY7MHGNxhtVpthmVntdKqki1jMSapht0wnjSeNIaUfxI84aC+EsKXAf+S1ZBWMRiHYBxpAKmsLGmslPCVaCftlsqQiSj95oNfhqrQ5RIEBq+M5ni0XP7Xdxoj8AvTyyj3bHcnXgAAAABJRU5ErkJggg==) no-repeat; } /* auto producer offer */ .buyme { position: absolute; margin-top: 50px; display: none; opacity: 0; transition: opacity 600ms ease; -moz-transition: opacity 600ms ease; -webkit-transition: opacity 600ms ease; text-align: left; font-family: Tahoma, Verdana, Arial, sans-serif; max-width: 300px; right: 16px; } .buyme_visible { display: block; opacity: 1 } .buyme-title:after { content: ' ▼' } .buyme_show .buyme-title:after { } .buyme .producer-list { display: none } .buyme_show .producer-list { display: block } .buyme .producer-list { list-style-type: none; padding: 0 } .buyme .producer-item { margin-top: 2em } .buyme .producer-name { display: inline-block; margin: .5em 0; border-bottom: 1px solid black; font-size: 1.1em; font-weight: bolder } .buyme a.producer-name { border-bottom: none } .buyme a:after { content: ' →'; position: absolute; } .buyme .offer-list { list-style-type: none; padding: 0 } .buyme .offer-item { display: block; padding: .5em 0 } .buyme .offer-name { display: table-cell; vertical-align: top } .buyme .offer-item .offer-currency { float: right; font-size: 0.8em; color: #888 } .buyme .offer-item .offer-price { float: right; padding-left: 8px; font-size: 1.1em; font-weight: bold; color: green } .buyme .offer-item .conditional-price { float: right; } .buyme .offer-item input[type="checkbox"] { display: none; position: absolute; right: 100% } .buyme .offer-item input[type="checkbox"]:after { content: 's'; position: absolute; left: 100%; opacity: 0 } .buyme .offer-item:hover input[type="checkbox"], .buyme .offer-item input[type="checkbox"]:hover, .buyme .offer-item input[type="checkbox"]:checked { display: block } .buyme .offer-item_fuzzy { opacity: .618 } .buyme .offer-item .offer-condition { display: table-cell; vertical-align: top; font-size: .8em } .buyme .offer-item .offer-condition a { float: right; text-decoration: none; color: black; border-bottom: 1px dashed black } .buyme .offer-item .offer-condition a:after { content: ''; clear: both } /*http://jsfiddle.net/ostrio/MVDh6/6/*/ .share { display: inline-block; margin-right: 8px; padding: 3px 8px; border: 1px dotted #eee; border-radius: 11px; } .share-btn { display: inline-block; width: 16px; height: 16px; padding-left: 3px; float: right; }</style> </head> <body class="offline" style="height: 6000px"><!-- scrollsaver --> <!-- params & view --> <div class="geodesic"> <!-- viewport --> <canvas class="preview"></canvas> <!-- copyleft --> <div class="copyleft" style="display: none" data-bind="visible: IS_IFRAME"> 2011-<span data-bind="text: (new Date).getFullYear()"></span> <a href target="_blank" data-bind="attr: { href: 'http://acidome.ru/lab/calc' + location.hash }">acidome.ru/lab/calc</a> → </div> <!-- header --> <div class="head" style="display: none" data-bind="visible: detailList() && !IS_IFRAME"> <div class="title transparent"> <span style="font-size: .7em; color: gray"> Acid<span style="margin: 0 -.1em;">☺</span>me </span> <h1 data-bind="text: 'title:Geodesic dome calculator'">Geodesic dome calculator</h1> <select class="lang-select" style="display: none" data-bind=" options: i18n.langOptions(), optionsValue: 'id', optionsText: 'name', value: i18n.lang, event: { change: $.proxy(console, 'log') }, visible: true "></select> </div> <div class="version"></div> <div class="welcome transparent"> <!-- http://jsfiddle.net/ostrio/MVDh6/6/ --> <div class="share"> <span data-bind="text: 'share:Share'">Share</span> → <a class="share-btn" target="_blank" title="Facebook" href data-bind=" attr: { href: 'http://www.facebook.com/sharer.php?u=' + encodeURIComponent(form.figureUrl()) + '&t=' + encodeURIComponent(form.figureName()) }"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QTZFREVBOTAxODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QTZFREVBOTExODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBNkVERUE4RTE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBNkVERUE4RjE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PpH2LXcAAAGmSURBVHjapFJNKERRFP7eu2/e84zI+ElJKYrJAitJSVKzkJ9IFrZ2VjZKbC0UWQsLO1nZSX7KYnaS1VB+EhtFz88Y7z3zfpx7Mat5MzSnzrvvnnvPd77z3SN1jW+sARjGtynIYb4vvuJfkiSPlkOeMIk/mGk78D0fiiLDo1UNMTBZGlP+mtzWXIORWBSV5Tos28Xq1gkubw3kBbA/HbQ0VmFlLobSEi0T3zm4QOLqKT+A43gY6G0SyRYxOTt/gGk5eDI+EKJ28oomyzKqIrrY78dvMLt8AI3611QFRRqDHJhMnjLTSKZspB1PxB6NFN5p77h+pkBWBh6dqApDf08jqc5QW1Mq4tGGSkwMtQoG8dN7vCWtAAB6Jo3ozU91Q9dCmXhne53wtONidGobLn/WbAA0JHCJZuLyEZEyHdUVYYSLVbxQxecXE9d3zzBeTSgsQEQaEKH49MIePaOLxZk+9HTUY/f4CkvrcRTrKvXvk8BSsIjcuHgcgLf03Zon5sJ1PcGSW04AXoExCT93RRIj2jyeuYMCrWAALuIm+eCvfv/MP/oSYAC/DZ1HI56fOwAAAABJRU5ErkJggg=="/> </a> <a class="share-btn" target="_blank" title="Twitter" href data-bind=" attr: { href: 'http://twitter.com/share?url=' + encodeURIComponent(form.figureUrl()) + '&text=' + encodeURIComponent(form.figureName() + ' | acidome.ru') }"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzA5RkVFNjkxODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzA5RkVFNkExODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBNkVERUE5MjE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMDlGRUU2ODE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiemuFcAAAC6UExURQCs7QCs7QCs7QCs7QCs7QCs7QCs7QCs7QCs7QCh6wCm7ACn7ACo7ACp7ACp7QCq7ACq7QCr7QCs7QGs7QKq7AKq7QOr7Qis7Qmu7Qqu7RKx7hSv7hax7hey7ii48Cy58D698UXB8VDE8lHF8lHF81TG83PQ9XfR9X/U9n/V9oLV9orY94vY94zX94/Z95rd+Kzj+azk+bbm+rfn+sPr+83v+87v/NPx/Nfy/Nvz/OD1/ej4/fP7/v///zDzFH4AAAAJdFJOU5abr7Tp7e7v8TlIFh4AAACMSURBVBgZBcHbSsNAFADAOXsJjfoQQxUE///nCgFTizSbZJ0JRQag7zEDABIAHSTYO32r24Y80qejxfB1vYxa5JH9++24f3zW1/poUdD/ri/zgHW5KJCUCY4gIe4HOJ+FhLqsHW5LJiHefzf8LAMKzjKl7bneSiBmnEPuj14DCqTWVEABAUBEkQHQ/gFK1TB99kc61wAAAABJRU5ErkJggg=="/> </a> <a class="share-btn" target="_blank" title="Google Plus" href data-bind=" attr: { href: 'https://plusone.google.com/_/+1/confirm?hl=en&url=' + encodeURIComponent(form.figureUrl()) }"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzA5RkVFNzExODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzA5RkVFNzIxODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMDlGRUU2RjE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMDlGRUU3MDE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PlHKW2sAAAKTSURBVHjabFNNSFRRFP7ufe85M6Zm/mulNpVKRi0qyKCkZW1CREzDioqEIIiWrYIgqKBWrYuoRVCQmwgiI/oh0NQsTJjJoVLHH0ZpdH6c9969nfteM85kB87innvud893znfYRHvrDYD1wDUfucQaUyGWHWB/gwMseGSfhJQ5VzKVgrRtSCEAYQO6Ae7xgnGOnFwyXaoXbBVdrCTAav3w7NiNvJrNzp0VmUdq8APEzBSg6TkAXEpVgOsimYCx5wAqei9DBsbAwpOo6j4Lz4ZS2NO/IBlHdr5yF4BKVS6kQEnHSYjJn4gPD2DhyUNEXz1HQUsriBDl2LDpE0l5uQAZJ05eH4w6P6SuQ5gpJCYCYPRQmha1w4a2tcnpj7AtF0Co0hV35ZS48PgefE07UdjWDWxpgFa9EbN3b1L5DNzfiMrzl8AoLrnmAOZUwDw+RN+8ROhCNzSvFw0P+pAYG8Xiiz7oFdUo7+hB/rZGlHeeglZcCmFZBCBW+SiOFgVj4Sn8/jICGhrKuqiJ+1uR/BFC+M41LL3vR/jWVaRmp2kiGtjo4V0ZHdjEq+hYF/Jr6xEf+gi5vIyqcxdhbKpHsLcT1sw0tMIiZ1rp0evO+OIx51B4tB01x0/j+5k2mAsRp6rY50Fsv/8MBXtbEHn6iLhzEpSWEawuhXSaocxbVQ2jpAyW7oFtmmCGAYsoxkNBJAPjjiLBXS2kBc+GDzVLabkA2vpi1F25Dl5ahsW3/TAjc9CpWWbwG6LvXoNTY/81NnSwOSNuSb8qZa+jMRrllbCWl5AMBWDOz4GRPhhja1ZM52p86TiVTGJA4usIEmqRFF8jD4YvP+tJ7krq48nkbS5xImudhYPINDd/JYX/WPrLT38EGAA8kFoJbGb//AAAAABJRU5ErkJggg=="/> </a> <a class="share-btn" target="_blank" title="LinkedIn" href data-bind=" attr: { href: 'http://www.linkedin.com/shareArticle?mini=true&url=' + encodeURIComponent(form.figureUrl()) }"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzA5RkVFNkQxODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzA5RkVFNkUxODJEMTFFMzkzM0E4RkVFOTc5OEYzOUQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMDlGRUU2QjE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMDlGRUU2QzE4MkQxMUUzOTMzQThGRUU5Nzk4RjM5RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Po54gukAAAIDSURBVHjajFNLSxxBEP5muufhjLuSLGo2qBgPCQjBQzyI3j2Id3MKMXjJJepRPOVijhpYvOQXiAQCYnKSQA4+IJeITxCyG0GNGpD1tePszFg1s7vuGsRtqG6quru6vu+rVjD+dQrASwQwQBMUBVWMoLAuSZqG4ZMfkKl02fMBoaLK0afyRUsTmOxvx9yrTrQ3xIC8X20CqHy4IxnHSM8T9D9rwOsXTcCVV3UCyeVu/c1iZnUPbQ8tfF47ADT1pgqGw7CK0GQlPIVIDBhG0jZg6wK/Ty6hEBeNth5Ss09+W8JCS9xEOptD+vicHhBlFVDmx7S5MNSFxlodb2Z/YfPwFD/e9iBHVXxZP8BgZzNilPzfhYuxb1v4tJIBdFHggKskexTT8aBGgykF+QrqbQ0tdSbedbfi6DRHtPhIWBre9z5FfZwU94LQ1KKorhdJ6xOccv/D9x08n1jA6NxG6CdjBloTdomXOwVXCg01v32Ii6s8lv+cwPWjpBaTGUS9c2/HMKHMvhRKqf+Cij64L8Gt9f9GQtTBcUOGAY1eElS+pkZXpBq9LGjlvVKsJCMdzro+Pi6mUWdKbJLOx46L1HImPLibdULJ9s4cpJYyIZRd6ofif4kaiYeTj8Cxvkwg+xzQqTJ+mQl0vJtYsUKyabIBGFKrAGfKys/LSctjJCLZz2sBBgATpK1IbdAo2wAAAABJRU5ErkJggg=="/> </a> <a class="share-btn" target="_blank" title="VK.com" href data-bind=" attr: { href: 'http://vk.com/share.php?url=' + encodeURIComponent(form.figureUrl()) + '&title=' + encodeURIComponent(form.figureName() + ' | acidome.ru') + '&description=&image=' }"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEFBRDg3REE2NERBMTFFMzk5MTlCRUE2RDEyNDhFN0IiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEFBRDg3REI2NERBMTFFMzk5MTlCRUE2RDEyNDhFN0IiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyNjM2RTczNTY0OUIxMUUzOTkxOUJFQTZEMTI0OEU3QiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyNjM2RTczNjY0OUIxMUUzOTkxOUJFQTZEMTI0OEU3QiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiDRXYQAAADbUExURU50p050p050p050p050p0VpmkVqnEZzp0dspUhumkhum0pvnEx0oU1yn01zpk10pU10p050p1B2oFh8pll8pFp+pFyBoVyCrGeJsGuHqG2MrXCPr3CVsXKOq3SOr3aTs3uVs3yZtX2ZuoKeuoSctYuiuoumwZesw6G1zaK2zbXE0rrH18LO18vV3szU3tHc5dff5Njk69nk6tzk6eXt8Ofu8Ony9O7y9e7z8vP19/P29/T3+PX3+fr7+/r9+/v7+/v9/f37+f39/P79//7+/P7+/f///P///v///zEOGxsAAAAFdFJOUz9IyeTnJbi1yAAAAH9JREFUGNNjYGASRAJMDAwsgiiAhUEQDRAlIKOnxalmrs8vqqOrDBYQtvFQEnGz4NL0sJcEC/Cpexgp2JkoWtqqskHM4DX2sHZ2cvQwYGWHCAhIWHl4uJp6OGhwwGyRM3QxE9N2d1eBWyskK8XNIy0vTpTDmFH5zAyMKN5lYQQAgNYXvjpI3BoAAAAASUVORK5CYII="/> </a> </div> <div style="text-align: right"> <!-- ko ifnot: i18n.lang() == 'ru' --> <a class="sample-to-use" href="http://northernhomestead.com/how-to-build-a-geodome-greenhouse/" target="_blank">How to use it</a> → <!-- /ko --> <!-- ko if: i18n.lang() == 'ru' --> <a class="sample-to-use" href="http://dompodrobno.ru/instrukciya_kalkulyator_kupolnyi/" target="_blank">Как этим пользоваться</a> → <!-- /ko --> </div> <div style="text-align: right"> <a class="facebook-group" href="https://www.facebook.com/groups/136778896376859/" target="_blank">Facebook group</a> → </div> <div style="text-align: right"> <a class="help-to-translate" href="https://www.facebook.com/groups/acidome.calc/permalink/753359898052086/" target="_blank">Translate me</a> → </div> <div class="download" style="margin-right: 16px"> <a id="js-download-link" class="pseudo" href="download.php" data-href-base="download.php" title="Come in peace. Free license for non-commercial usage, free distribute this program, and free commercial usage for growing cannabis."> Offline version </a> </div> <div class="download" style="margin-right: 16px"> <a class="pseudo" href="javascript://" onclick="figure.clientDownload(); return false;">Download figure as .obj</a> </div> <a href class="donation pseudo" onclick="event.preventDefault()" data-bind="text: 'Donate'">Donate</a> ← <div class="donation__popup"> <iframe class="yandex" frameborder="0" allowtransparency="true" scrolling="no" style="z-index: 1" src="http://money.yandex.ru/embed/donate.xml?account=41001351235394&quickpay=donate&default-sum=&targets=%D0%9D%D0%B0+%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D1%83+%D0%BA%D0%B0%D0%BB%D1%8C%D0%BA%D1%83%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0&target-visibility=on&project-name=&project-site=&button-text=05" width="439" height="104"></iframe> <div style="clear: both"></div> <div class="visa" title="Visa card number"> 4276 3800 5748 2981 </div> <div class="paypal" title="PayPal donation"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"> <input type="hidden" name="cmd" value="_s-xclick"> <input type="hidden" name="hosted_button_id" value="XSULWE6C9RHZJ"> <input type="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAVCAYAAADWxrdnAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABWFJREFUeNrsVwlsVFUUPX86e2famcJM6crUUhtLKbZFYpGCMICEBgImQsCQGAiIERRQohIMiaKJmhpFISoGEha1CbKYWBWNDZvYUkqhLQNdoO1Mp6XrLJ19ed7/Ck201YQ0MTH2JW+Sn//ufeedc+59fwTGGP6rQ4L/8BgHPw7+/wZeKv5cs9jYo698AfgDQDQ69Earwdr8bLz7wiKkJiUIY9nk1a/qWGmVFRCzRKm7KaQoMGrx3nwTFhQk/2PuHoeXJe+vRtgfRsvzhWjr9VK4BAPe0BDzF6/eATweQCbD3KlTMD0zHfD6cOSXS9ixt3w4kcPpYXd7nMzp8gz3V78/wLxe/5/6bTAYYoMeH59+f5CVNvUBkQgQp8LiKROJMglqWvuw8Ng1NNucPNZHeQZcPj79geBwvhvtLoTtDk6qXiuHUiaBQh4DOeXgzF+yECvhCGaZkvHzR+t4kPnlgzhfdxMtd/tR09DO5u8pg9PhHlJGqcCSzBT26dal2FR6GmfaunBy8zK2fEEeZ3HDnm9xuMaCF4vysHPjU4DbT6wLuPDMI5iZPQFVjf2YfeAKEIqgs9+LE9Vd7LXKdnqODhmZDlk2dzJbWTxZqG1zAnQXmQ0a6ONUQuEUKRMVlMtkAmf+3J1Ontw8LYMD7+h04nzPALEVxbRUI240dyNXp8GukiJsW/gYHTSE8t9rcej0ZUjES66zC2erW3jswROV7HBFFVdu7ZJ81FldJE+QACmRkx7P19RZ75FA7KmVMly968b23ETsM2diUaoO6HJi1fe34PEFWKWd1tIW89KGYuVymSAC556/0WRn7SJQssy+i/W4cMuGihZSwkknNhqw7dliZD9kxIzcFNy83QNbjxNyTSyCrkEkGeJQSOB/vFKPpu4BBEMhtuObCs7UujmFKMhNwxtlFk4MAhFsPFaP6+4AGq1kAxbFrsczkJcRj32JObD2+tDR70O+Q40zzbReIUMgGMHXXQReGoNZmbqRBVtrsVNiKtSYGPT3OVAxQExpY7GRJN+9wQyn24fpG/bDYiV1lHJApQLENXIFivMzUGPpIKklaOpzYefH5ejv7AYm6PHWpkV8gxM25xB4suXxxh4iKQZT0/TYU5yGkhlJ+PxMK7acu02FQjWhVfJ1ItPrSSW3N0x7+XiBZyVpRoKvtNjIayEkJRlx+cP1ZGcZ1Go5VEoFl2bFrqPMcqsZW1eY8f62EvxW04onXz9ANtAgy2SAQ/QzHaTR3oNSezcHWvr0HKRM0gudvYPsDnlaVOLIshwsnZEo4oJOq+K5z17vYlt+uMlB395RhFSDCiu/rMWpejvmZyagwUYkhcOIN+qQatSO6ErSXxuo00TCWJyVhpS/tESX28uqREtJZeh0DOLgycv44LtLxFIAc5JMUCjkQlpiPOOK+II8T0GWCZvXPMHjLaLfvUHO3OxsPeLvgb4/Wrqow0WJaYmA6pYBHLpoxSlRHVIyb3IcyipJ1XAUqydpR7+knFSUSE7G8rm5I17GadXCm2KBqmMpUQM++6kGpoQ4QJ+A5UU5fE2iQUugtNzDkErxznMLcb+g7A6yI6m46mEDTMnxI5hbMN1Ie+upTQexsrwRHW46qE6N3PQEmIxq9Poj/HnJ1ImjghfEHi1+FqvVyr+9LFqtvSxC3SF1ko5kZ+SyCLEu4yA9Hj8zrNsLX4cda+fNxOG31wznEft1KMzI5gKUSvmo+d0U3+sMQqeR8VY46A2wGOqBom3FOyJC2GJVitGxicDHMvcePcdQvJ2hZDdrbutmY833IHNM3zYDjkH20vGzpJ8En6w2IzPdIPyb3zbC+D+pcfAPPv4QYADNfs6Oc0aWEAAAAABJRU5ErkJggg==" border="0" name="submit" alt="PayPal – The safer, easier way to pay online."> <!--<img alt="" border="0" src="https://www.paypalobjects.com/ru_RU/i/scr/pixel.gif" width="1" height="1">--> </form> </div> </div> <div class="buyme" data-bind=" css: { buyme_visible: !_.isEmpty( OfferFactory.resultList() ), buyme_show: !localStorage.getItem('env.buymeHidden') } "> <h4 class="buyme-title" style="cursor: pointer; color: green" data-bind=" click: function($data, event) { localStorage.setItem('env.offerHidden', $('.buyme').toggleClass('buyme_show').is('.buyme_show') ? '' : 1); } "> <span data-bind="text: 'buyme:Buy me'">Buy me</span> </h4> <ul class="producer-list"> <!-- promo test --> <li class="producer-item" style="display: none" data-bind="visible: i18n.lang() == 'en'"> <a class="producer-name" href="http://www.vikingdome.com/geodesic-domes/?utm_source=acidome&utm_medium=link" target="_blank" onclick="pageTracker._trackEvent('outbound', 'vikingdome.com')">Vikingdome.com</a> <div> Struts, hubs and covers for your Geodesic dome. Made in EU, worldwide delivery. <a href="http://www.vikingdome.com/geodesic-domes/?utm_source=acidome&utm_medium=link" target="_blank" onclick="pageTracker._trackEvent('outbound', 'vikingdome.com')">Learn more…</a> </div> </li> <!-- /promo test --> <!-- ko foreach: OfferFactory.resultList --> <li class="producer-item"> <!-- ko if: $data.producerLink --> <a class="producer-name" target="_blank" data-bind="text: producerName, attr: { href: producerLink }"></a> <!-- /ko --> <!-- ko if: !$data.producerLink --> <div class="producer-name" data-bind="text: producerName"></div> <!-- /ko --> <form action="" target="_blank" data-bind="with: new OfferFactory.Order($data)"> <ul class="offer-list" data-bind="foreach: $parent.offer"> <!-- ko if: !$data.conditions --> <li class="offer-item"> <label> <input type="checkbox" data-bind="checked: $parent.selectedPositions, value: name"/> <sub class="offer-currency" data-bind="text: currency"></sub> <span class="offer-price" data-bind="text: OfferFactory.formatPrice(price)"></span> <span class="name" data-bind="html: name"></span> </label> </li> <!-- /ko --> <!-- ko if: $data.conditions --> <li class="offer-item offer-item_fuzzy"> <div class="offer-name" data-bind="html: name"></div> <div class="offer-condition"> <!-- ko if: $data.price --> <button class="conditional-price" data-bind="click: form.update.bind(null, conditions[0].condition)"> <sub class="offer-currency" data-bind="text: currency"></sub> <span class="offer-price" data-bind="text: OfferFactory.formatPrice(price)"></span> </button> <!-- /ko --> <!-- ko foreach: conditions --> <a href data-bind="click: form.update.bind(null, condition), html: name"></a> <!-- /ko --> </div> </li> <!-- /ko --> </ul> <!-- ko if: !_.isEmpty(selectedPositions()) --> <input type="email" placeholder="E-mail" data-bind="value: email, attr: { disabled: pending }"/> <button data-bind="text: 'buyme:Buy it', click: submit, attr: { disabled: pending }"></button> <!-- /ko --> </form> </li> <!-- /ko --> </ul> </div> </div> <p> <!--<i>"Носи пальто и мечтай о чем-нибудь великом",</i><br/> Кинофильм <a target="_blank" href="http://www.kinopoisk.ru/film/45028/>">«Курьер»</a>, СССР, 1986--> </p> </div> <!-- geodesic options form --> <form class="options transparent slow-toggle-visibility" style="display: none" data-bind="visible: detailList() && !IS_IFRAME"> <!-- by right side of form --> <div class="stat transparent"> <label class="toggle" style="white-space: nowrap;"> <span data-bind="text: 'Resulting'"></span> ▼ </label> <pre class="report" data-bind=" html: function() { //debugger; return reportText() }() "></pre> </div> <ul class="mode-list"> <li class="mode round button active" data-mode="carcass" data-bind="text: 'Carcass'"></li> <li class="mode round button" data-mode="schema" data-bind="text: 'Schema'"></li> <li class="mode round button" data-mode="cover" data-bind="text: 'Cover'"></li> <li class="mode round button" data-mode="base" data-bind="text: 'Base'"></li> <li class="mode round button" data-mode="clothier" data-bind="text: 'clothier:Clothier', visible: clothier.onRun"></li> </ul> <!-- form content start here --> <div class="progress"></div> <h3 data-bind="text: 'Figure options'"></h3> <dl> <dt data-bind="text: 'Level of detail, V'"></dt> <dd> <select data-bind=" options: detailList, value: detail "></select> </dd> </dl> <dl data-bind="visible: detail() >= 2"> <dt data-bind="text: 'Subdivision class'"></dt> <dd> <select data-bind=" value: subdivClass, options: subdivClassList, optionsText: 'name', optionsValue: 'id', attr: { disabled: subdivClassList().length <= 1 } "></select> </dd> </dl> <dl data-bind="visible: detail() >= 3 && 'I' == subdivClass()"> <dt data-bind="text: 'Subdivision method'"></dt> <dd> <select data-bind=" value: subdivMethod, options: subdivMethodList, optionsValue: 'id', optionsText: 'name' "></select> </dd> </dl> <dl data-bind="visible: 1 || (subdivClass() == 'II')"> <dt data-bind="text: 'Rotational symmetry'"></dt> <dd> <select data-bind="options: ['Pentad', 'Cross', 'Triad'], value: symmetry"></select> </dd> </dl> <dl data-bind="visible: connType() != 'Joint'"> <dt data-bind="text: 'Fullerene'"></dt> <dd> <select data-bind=" value: fullerenType, options: FULLEREN_TYPE_LIST, optionsText: 'name', optionsValue: 'id', optionsCaption: __('fulleren:None') "> </select> </dd> </dl> <dl> <dt data-bind="text: 'Part of full sphere'"></dt> <dd> <select data-bind=" options: partialList, value: partial "></select> </dd> </dl> <dl class="sub" data-bind="visible: canAlignTheBase"> <dt> <label for="alignTheBase_switcher" data-bind="text: 'Align the base'"></label> </dt> <dd> <input id="alignTheBase_switcher" type="checkbox" data-bind=" checked: alignTheBase "></select> </dd> </dl> <h3 data-bind="text: 'Product options'"></h3> <dl> <dt data-bind="text: 'Sphere radius, m'"></dt> <dd><input data-bind=" value: radius"/> </dd> </dl> <dl> <dt data-bind="text: 'Connection type'"></dt> <dd><select data-bind="options: connTypeList, value: connType"><select> </dd> </dl> <!-- properties what caused from connector type (and other) --> <dl class="sub" data-bind=" visible: (connType() == 'Piped') "> <dt data-bind="text: 'Pipe diameter, mm'"></dt> <dd><input data-bind=" value: pipeD, valueUpdate: 'keyup'"/> </dd> </dl> <dl class="sub" data-bind="visible: _.contains(['Joint', 'Nose', 'GoodKarma'], connType())"> <dt> <label for="clockwise_switcher" data-bind="text: 'Spinning clockwise'"></label> </dt> <dd> <input id="clockwise_switcher" type="checkbox" data-bind="checked: clockwise"/> <span class="gray"> (<label for="clockwise_switcher" data-bind="text: 'else counter'"></label>) </span> </dd> </dl> <h3 data-bind="text: 'Timber size'"></h3> <dl> <dt data-bind="text: 'Width, mm'"></dt> <dd><input data-bind=" value: beamsWidth"/> </dd> </dl> <dl> <dt data-bind="text: 'Thickness, mm'"></dt> <dd><input data-bind=" value: beamsThickness"/> </dd> </dl> <!-- ko with: IS_OFFLINE && clothier --> <h3> <span style="position: relative"> <span data-bind="text: 'clothier:Clothier'"></span> <sup class="absolute red" style="top: 0; left: 100%; padding-left: .5em">will be</sup> </span> </h3> <dl> <dt data-bind="text: 'clothier:Source width, mm'"></dt> <dd><input data-bind="value: width"/></dd> </dl> <dl> <dt data-bind="text: 'clothier:Source height, mm'"></dt> <dd><input data-bind="value: height"/></dd> </dl> <dl> <dt data-bind="text: 'clothier:Find the best pattern'"></dt> <dd> <!-- ko if: !onRun() || onPause() --> <button data-bind="click: run">▶</button> <!-- /ko --> <!-- ko if: onRun() && !onPause() --> <button data-bind="click: pause">▮▮</button> <!-- /ko --> <!-- ko if: onRun --> <button data-bind="click: stop">◾</button> <!-- /ko --> </dd> </dl> <!-- /ko --> </form> <!--<div class="info"> </div>--> <div class="budget-list" data-bind="visible: true" style="display: none"> <!-- ko foreach: budgetList --> <h2 data-bind="text: 'budget:title:' + type"></h2> <ul data-bind="attr: { 'class': type }"> <!-- ko foreach: sizeList --> <li class="product" data-bind="visible: units().length > 0"> <i class="product-index" data-bind="text: index, attr: { style: 'background-color: ' + color }"></i> <span data-bind="text: units().length + ' ' + __('pcs')"></span> <!-- ko if: $parent.type == 'line' --> <a href="http://popitch1.livejournal.com/7699.html" target="_blank" style="border: 1px solid gray; border-radius: 50%; margin-left: 10px; text-decoration:none; width: .9em; display: inline-block; padding-left: 4px;">?</a> <!-- /ko --> <br/> <canvas data-bind="attr: $parent.canvasAttr, plot: product"></canvas> </li> <!-- /ko --> </ul> <!-- /ko --> </div> </div> <!-- timing start --> <script type="text/javascript"> var _jsLoadingStartAt = +new Date; </script> <!-- libs --> <!-- jQuery --> <script type="text/javascript">/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ !function (a, b) { "object" == typeof module && "object" == typeof module.exports ? module.exports = a.document ? b(a, !0) : function (a) { if (!a.document) throw new Error("jQuery requires a window with a document"); return b(a) } : b(a) }("undefined" != typeof window ? window : this, function (a, b) { var c = [], d = c.slice, e = c.concat, f = c.push, g = c.indexOf, h = {}, i = h.toString, j = h.hasOwnProperty, k = "".trim, l = {}, m = "1.11.0", n = function (a, b) { return new n.fn.init(a, b) }, o = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, p = /^-ms-/, q = /-([\da-z])/gi, r = function (a, b) { return b.toUpperCase() }; n.fn = n.prototype = { jquery: m, constructor: n, selector: "", length: 0, toArray: function () { return d.call(this) }, get: function (a) { return null != a ? 0 > a ? this[a + this.length] : this[a] : d.call(this) }, pushStack: function (a) { var b = n.merge(this.constructor(), a); return b.prevObject = this, b.context = this.context, b }, each: function (a, b) { return n.each(this, a, b) }, map: function (a) { return this.pushStack(n.map(this, function (b, c) { return a.call(b, c, b) })) }, slice: function () { return this.pushStack(d.apply(this, arguments)) }, first: function () { return this.eq(0) }, last: function () { return this.eq(-1) }, eq: function (a) { var b = this.length, c = +a + (0 > a ? b : 0); return this.pushStack(c >= 0 && b > c ? [this[c]] : []) }, end: function () { return this.prevObject || this.constructor(null) }, push: f, sort: c.sort, splice: c.splice }, n.extend = n.fn.extend = function () { var a, b, c, d, e, f, g = arguments[0] || {}, h = 1, i = arguments.length, j = !1; for ("boolean" == typeof g && (j = g, g = arguments[h] || {}, h++), "object" == typeof g || n.isFunction(g) || (g = {}), h === i && (g = this, h--); i > h; h++) if (null != (e = arguments[h])) for (d in e) a = g[d], c = e[d], g !== c && (j && c && (n.isPlainObject(c) || (b = n.isArray(c))) ? (b ? (b = !1, f = a && n.isArray(a) ? a : []) : f = a && n.isPlainObject(a) ? a : {}, g[d] = n.extend(j, f, c)) : void 0 !== c && (g[d] = c)); return g }, n.extend({ expando: "jQuery" + (m + Math.random()).replace(/\D/g, ""), isReady: !0, error: function (a) { throw new Error(a) }, noop: function () { }, isFunction: function (a) { return "function" === n.type(a) }, isArray: Array.isArray || function (a) { return "array" === n.type(a) }, isWindow: function (a) { return null != a && a == a.window }, isNumeric: function (a) { return a - parseFloat(a) >= 0 }, isEmptyObject: function (a) { var b; for (b in a) return !1; return !0 }, isPlainObject: function (a) { var b; if (!a || "object" !== n.type(a) || a.nodeType || n.isWindow(a)) return !1; try { if (a.constructor && !j.call(a, "constructor") && !j.call(a.constructor.prototype, "isPrototypeOf")) return !1 } catch (c) { return !1 } if (l.ownLast) for (b in a) return j.call(a, b); for (b in a) ; return void 0 === b || j.call(a, b) }, type: function (a) { return null == a ? a + "" : "object" == typeof a || "function" == typeof a ? h[i.call(a)] || "object" : typeof a }, globalEval: function (b) { b && n.trim(b) && (a.execScript || function (b) { a.eval.call(a, b) })(b) }, camelCase: function (a) { return a.replace(p, "ms-").replace(q, r) }, nodeName: function (a, b) { return a.nodeName && a.nodeName.toLowerCase() === b.toLowerCase() }, each: function (a, b, c) { var d, e = 0, f = a.length, g = s(a); if (c) { if (g) { for (; f > e; e++) if (d = b.apply(a[e], c), d === !1) break } else for (e in a) if (d = b.apply(a[e], c), d === !1) break } else if (g) { for (; f > e; e++) if (d = b.call(a[e], e, a[e]), d === !1) break } else for (e in a) if (d = b.call(a[e], e, a[e]), d === !1) break; return a }, trim: k && !k.call("\ufeff\xa0") ? function (a) { return null == a ? "" : k.call(a) } : function (a) { return null == a ? "" : (a + "").replace(o, "") }, makeArray: function (a, b) { var c = b || []; return null != a && (s(Object(a)) ? n.merge(c, "string" == typeof a ? [a] : a) : f.call(c, a)), c }, inArray: function (a, b, c) { var d; if (b) { if (g) return g.call(b, a, c); for (d = b.length, c = c ? 0 > c ? Math.max(0, d + c) : c : 0; d > c; c++) if (c in b && b[c] === a) return c } return -1 }, merge: function (a, b) { var c = +b.length, d = 0, e = a.length; while (c > d) a[e++] = b[d++]; if (c !== c) while (void 0 !== b[d]) a[e++] = b[d++]; return a.length = e, a }, grep: function (a, b, c) { for (var d, e = [], f = 0, g = a.length, h = !c; g > f; f++) d = !b(a[f], f), d !== h && e.push(a[f]); return e }, map: function (a, b, c) { var d, f = 0, g = a.length, h = s(a), i = []; if (h) for (; g > f; f++) d = b(a[f], f, c), null != d && i.push(d); else for (f in a) d = b(a[f], f, c), null != d && i.push(d); return e.apply([], i) }, guid: 1, proxy: function (a, b) { var c, e, f; return "string" == typeof b && (f = a[b], b = a, a = f), n.isFunction(a) ? (c = d.call(arguments, 2), e = function () { return a.apply(b || this, c.concat(d.call(arguments))) }, e.guid = a.guid = a.guid || n.guid++, e) : void 0 }, now: function () { return +new Date }, support: l }), n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function (a, b) { h["[object " + b + "]"] = b.toLowerCase() }); function s(a) { var b = a.length, c = n.type(a); return "function" === c || n.isWindow(a) ? !1 : 1 === a.nodeType && b ? !0 : "array" === c || 0 === b || "number" == typeof b && b > 0 && b - 1 in a } var t = function (a) { var b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s = "sizzle" + -new Date, t = a.document, u = 0, v = 0, w = eb(), x = eb(), y = eb(), z = function (a, b) { return a === b && (j = !0), 0 }, A = "undefined", B = 1 << 31, C = {}.hasOwnProperty, D = [], E = D.pop, F = D.push, G = D.push, H = D.slice, I = D.indexOf || function (a) { for (var b = 0, c = this.length; c > b; b++) if (this[b] === a) return b; return -1 }, J = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", K = "[\\x20\\t\\r\\n\\f]", L = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", M = L.replace("w", "w#"), N = "\\[" + K + "*(" + L + ")" + K + "*(?:([*^$|!~]?=)" + K + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + M + ")|)|)" + K + "*\\]", O = ":(" + L + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + N.replace(3, 8) + ")*)|.*)\\)|)", P = new RegExp("^" + K + "+|((?:^|[^\\\\])(?:\\\\.)*)" + K + "+$", "g"), Q = new RegExp("^" + K + "*," + K + "*"), R = new RegExp("^" + K + "*([>+~]|" + K + ")" + K + "*"), S = new RegExp("=" + K + "*([^\\]'\"]*?)" + K + "*\\]", "g"), T = new RegExp(O), U = new RegExp("^" + M + "$"), V = { ID: new RegExp("^#(" + L + ")"), CLASS: new RegExp("^\\.(" + L + ")"), TAG: new RegExp("^(" + L.replace("w", "w*") + ")"), ATTR: new RegExp("^" + N), PSEUDO: new RegExp("^" + O), CHILD: new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + K + "*(even|odd|(([+-]|)(\\d*)n|)" + K + "*(?:([+-]|)" + K + "*(\\d+)|))" + K + "*\\)|)", "i"), bool: new RegExp("^(?:" + J + ")$", "i"), needsContext: new RegExp("^" + K + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + K + "*((?:-\\d)?\\d*)" + K + "*\\)|)(?=[^-]|$)", "i") }, W = /^(?:input|select|textarea|button)$/i, X = /^h\d$/i, Y = /^[^{]+\{\s*\[native \w/, Z = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, $ = /[+~]/, _ = /'|\\/g, ab = new RegExp("\\\\([\\da-f]{1,6}" + K + "?|(" + K + ")|.)", "ig"), bb = function (a, b, c) { var d = "0x" + b - 65536; return d !== d || c ? b : 0 > d ? String.fromCharCode(d + 65536) : String.fromCharCode(d >> 10 | 55296, 1023 & d | 56320) }; try { G.apply(D = H.call(t.childNodes), t.childNodes), D[t.childNodes.length].nodeType } catch (cb) { G = { apply: D.length ? function (a, b) { F.apply(a, H.call(b)) } : function (a, b) { var c = a.length, d = 0; while (a[c++] = b[d++]) ; a.length = c - 1 } } } function db(a, b, d, e) { var f, g, h, i, j, m, p, q, u, v; if ((b ? b.ownerDocument || b : t) !== l && k(b), b = b || l, d = d || [], !a || "string" != typeof a) return d; if (1 !== (i = b.nodeType) && 9 !== i) return []; if (n && !e) { if (f = Z.exec(a)) if (h = f[1]) { if (9 === i) { if (g = b.getElementById(h), !g || !g.parentNode) return d; if (g.id === h) return d.push(g), d } else if (b.ownerDocument && (g = b.ownerDocument.getElementById(h)) && r(b, g) && g.id === h) return d.push(g), d } else { if (f[2]) return G.apply(d, b.getElementsByTagName(a)), d; if ((h = f[3]) && c.getElementsByClassName && b.getElementsByClassName) return G.apply(d, b.getElementsByClassName(h)), d } if (c.qsa && (!o || !o.test(a))) { if (q = p = s, u = b, v = 9 === i && a, 1 === i && "object" !== b.nodeName.toLowerCase()) { m = ob(a), (p = b.getAttribute("id")) ? q = p.replace(_, "\\$&") : b.setAttribute("id", q), q = "[id='" + q + "'] ", j = m.length; while (j--) m[j] = q + pb(m[j]); u = $.test(a) && mb(b.parentNode) || b, v = m.join(",") } if (v) try { return G.apply(d, u.querySelectorAll(v)), d } catch { } finally { p || b.removeAttribute("id") } } } return xb(a.replace(P, "$1"), b, d, e) } function eb() { var a = []; function b(c, e) { return a.push(c + " ") > d.cacheLength && delete b[a.shift()], b[c + " "] = e } return b } function fb(a) { return a[s] = !0, a } function gb(a) { var b = l.createElement("div"); try { return !!a(b) } catch (c) { return !1 } finally { b.parentNode && b.parentNode.removeChild(b), b = null } } function hb(a, b) { var c = a.split("|"), e = a.length; while (e--) d.attrHandle[c[e]] = b } function ib(a, b) { var c = b && a, d = c && 1 === a.nodeType && 1 === b.nodeType && (~b.sourceIndex || B) - (~a.sourceIndex || B); if (d) return d; if (c) while (c = c.nextSibling) if (c === b) return -1; return a ? 1 : -1 } function jb(a) { return function (b) { var c = b.nodeName.toLowerCase(); return "input" === c && b.type === a } } function kb(a) { return function (b) { var c = b.nodeName.toLowerCase(); return ("input" === c || "button" === c) && b.type === a } } function lb(a) { return fb(function (b) { return b = +b, fb(function (c, d) { var e, f = a([], c.length, b), g = f.length; while (g--) c[e = f[g]] && (c[e] = !(d[e] = c[e])) }) }) } function mb(a) { return a && typeof a.getElementsByTagName !== A && a } c = db.support = {}, f = db.isXML = function (a) { var b = a && (a.ownerDocument || a).documentElement; return b ? "HTML" !== b.nodeName : !1 }, k = db.setDocument = function (a) { var b, e = a ? a.ownerDocument || a : t, g = e.defaultView; return e !== l && 9 === e.nodeType && e.documentElement ? (l = e, m = e.documentElement, n = !f(e), g && g !== g.top && (g.addEventListener ? g.addEventListener("unload", function () { k() }, !1) : g.attachEvent && g.attachEvent("onunload", function () { k() })), c.attributes = gb(function (a) { return a.className = "i", !a.getAttribute("className") }), c.getElementsByTagName = gb(function (a) { return a.appendChild(e.createComment("")), !a.getElementsByTagName("*").length }), c.getElementsByClassName = Y.test(e.getElementsByClassName) && gb(function (a) { return a.innerHTML = "<div class='a'></div><div class='a i'></div>", a.firstChild.className = "i", 2 === a.getElementsByClassName("i").length }), c.getById = gb(function (a) { return m.appendChild(a).id = s, !e.getElementsByName || !e.getElementsByName(s).length }), c.getById ? (d.find.ID = function (a, b) { if (typeof b.getElementById !== A && n) { var c = b.getElementById(a); return c && c.parentNode ? [c] : [] } }, d.filter.ID = function (a) { var b = a.replace(ab, bb); return function (a) { return a.getAttribute("id") === b } }) : (delete d.find.ID, d.filter.ID = function (a) { var b = a.replace(ab, bb); return function (a) { var c = typeof a.getAttributeNode !== A && a.getAttributeNode("id"); return c && c.value === b } }), d.find.TAG = c.getElementsByTagName ? function (a, b) { return typeof b.getElementsByTagName !== A ? b.getElementsByTagName(a) : void 0 } : function (a, b) { var c, d = [], e = 0, f = b.getElementsByTagName(a); if ("*" === a) { while (c = f[e++]) 1 === c.nodeType && d.push(c); return d } return f }, d.find.CLASS = c.getElementsByClassName && function (a, b) { return typeof b.getElementsByClassName !== A && n ? b.getElementsByClassName(a) : void 0 }, p = [], o = [], (c.qsa = Y.test(e.querySelectorAll)) && (gb(function (a) { a.innerHTML = "<select t=''><option selected=''></option></select>", a.querySelectorAll("[t^='']").length && o.push("[*^$]=" + K + "*(?:''|\"\")"), a.querySelectorAll("[selected]").length || o.push("\\[" + K + "*(?:value|" + J + ")"), a.querySelectorAll(":checked").length || o.push(":checked") }), gb(function (a) { var b = e.createElement("input"); b.setAttribute("type", "hidden"), a.appendChild(b).setAttribute("name", "D"), a.querySelectorAll("[name=d]").length && o.push("name" + K + "*[*^$|!~]?="), a.querySelectorAll(":enabled").length || o.push(":enabled", ":disabled"), a.querySelectorAll("*,:x"), o.push(",.*:") })), (c.matchesSelector = Y.test(q = m.webkitMatchesSelector || m.mozMatchesSelector || m.oMatchesSelector || m.msMatchesSelector)) && gb(function (a) { c.disconnectedMatch = q.call(a, "div"), q.call(a, "[s!='']:x"), p.push("!=", O) }), o = o.length && new RegExp(o.join("|")), p = p.length && new RegExp(p.join("|")), b = Y.test(m.compareDocumentPosition), r = b || Y.test(m.contains) ? function (a, b) { var c = 9 === a.nodeType ? a.documentElement : a, d = b && b.parentNode; return a === d || !(!d || 1 !== d.nodeType || !(c.contains ? c.contains(d) : a.compareDocumentPosition && 16 & a.compareDocumentPosition(d))) } : function (a, b) { if (b) while (b = b.parentNode) if (b === a) return !0; return !1 }, z = b ? function (a, b) { if (a === b) return j = !0, 0; var d = !a.compareDocumentPosition - !b.compareDocumentPosition; return d ? d : (d = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1, 1 & d || !c.sortDetached && b.compareDocumentPosition(a) === d ? a === e || a.ownerDocument === t && r(t, a) ? -1 : b === e || b.ownerDocument === t && r(t, b) ? 1 : i ? I.call(i, a) - I.call(i, b) : 0 : 4 & d ? -1 : 1) } : function (a, b) { if (a === b) return j = !0, 0; var c, d = 0, f = a.parentNode, g = b.parentNode, h = [a], k = [b]; if (!f || !g) return a === e ? -1 : b === e ? 1 : f ? -1 : g ? 1 : i ? I.call(i, a) - I.call(i, b) : 0; if (f === g) return ib(a, b); c = a; while (c = c.parentNode) h.unshift(c); c = b; while (c = c.parentNode) k.unshift(c); while (h[d] === k[d]) d++; return d ? ib(h[d], k[d]) : h[d] === t ? -1 : k[d] === t ? 1 : 0 }, e) : l }, db.matches = function (a, b) { return db(a, null, null, b) }, db.matchesSelector = function (a, b) { if ((a.ownerDocument || a) !== l && k(a), b = b.replace(S, "='$1']"), !(!c.matchesSelector || !n || p && p.test(b) || o && o.test(b))) try { var d = q.call(a, b); if (d || c.disconnectedMatch || a.document && 11 !== a.document.nodeType) return d } catch (e) { } return db(b, l, null, [a]).length > 0 }, db.contains = function (a, b) { return (a.ownerDocument || a) !== l && k(a), r(a, b) }, db.attr = function (a, b) { (a.ownerDocument || a) !== l && k(a); var e = d.attrHandle[b.toLowerCase()], f = e && C.call(d.attrHandle, b.toLowerCase()) ? e(a, b, !n) : void 0; return void 0 !== f ? f : c.attributes || !n ? a.getAttribute(b) : (f = a.getAttributeNode(b)) && f.specified ? f.value : null }, db.error = function (a) { throw new Error("Syntax error, unrecognized expression: " + a) }, db.uniqueSort = function (a) { var b, d = [], e = 0, f = 0; if (j = !c.detectDuplicates, i = !c.sortStable && a.slice(0), a.sort(z), j) { while (b = a[f++]) b === a[f] && (e = d.push(f)); while (e--) a.splice(d[e], 1) } return i = null, a }, e = db.getText = function (a) { var b, c = "", d = 0, f = a.nodeType; if (f) { if (1 === f || 9 === f || 11 === f) { if ("string" == typeof a.textContent) return a.textContent; for (a = a.firstChild; a; a = a.nextSibling) c += e(a) } else if (3 === f || 4 === f) return a.nodeValue } else while (b = a[d++]) c += e(b); return c }, d = db.selectors = { cacheLength: 50, createPseudo: fb, match: V, attrHandle: {}, find: {}, relative: { ">": {dir: "parentNode", first: !0}, " ": {dir: "parentNode"}, "+": {dir: "previousSibling", first: !0}, "~": {dir: "previousSibling"} }, preFilter: { ATTR: function (a) { return a[1] = a[1].replace(ab, bb), a[3] = (a[4] || a[5] || "").replace(ab, bb), "~=" === a[2] && (a[3] = " " + a[3] + " "), a.slice(0, 4) }, CHILD: function (a) { return a[1] = a[1].toLowerCase(), "nth" === a[1].slice(0, 3) ? (a[3] || db.error(a[0]), a[4] = +(a[4] ? a[5] + (a[6] || 1) : 2 * ("even" === a[3] || "odd" === a[3])), a[5] = +(a[7] + a[8] || "odd" === a[3])) : a[3] && db.error(a[0]), a }, PSEUDO: function (a) { var b, c = !a[5] && a[2]; return V.CHILD.test(a[0]) ? null : (a[3] && void 0 !== a[4] ? a[2] = a[4] : c && T.test(c) && (b = ob(c, !0)) && (b = c.indexOf(")", c.length - b) - c.length) && (a[0] = a[0].slice(0, b), a[2] = c.slice(0, b)), a.slice(0, 3)) } }, filter: { TAG: function (a) { var b = a.replace(ab, bb).toLowerCase(); return "*" === a ? function () { return !0 } : function (a) { return a.nodeName && a.nodeName.toLowerCase() === b } }, CLASS: function (a) { var b = w[a + " "]; return b || (b = new RegExp("(^|" + K + ")" + a + "(" + K + "|$)")) && w(a, function (a) { return b.test("string" == typeof a.className && a.className || typeof a.getAttribute !== A && a.getAttribute("class") || "") }) }, ATTR: function (a, b, c) { return function (d) { var e = db.attr(d, a); return null == e ? "!=" === b : b ? (e += "", "=" === b ? e === c : "!=" === b ? e !== c : "^=" === b ? c && 0 === e.indexOf(c) : "*=" === b ? c && e.indexOf(c) > -1 : "$=" === b ? c && e.slice(-c.length) === c : "~=" === b ? (" " + e + " ").indexOf(c) > -1 : "|=" === b ? e === c || e.slice(0, c.length + 1) === c + "-" : !1) : !0 } }, CHILD: function (a, b, c, d, e) { var f = "nth" !== a.slice(0, 3), g = "last" !== a.slice(-4), h = "of-type" === b; return 1 === d && 0 === e ? function (a) { return !!a.parentNode } : function (b, c, i) { var j, k, l, m, n, o, p = f !== g ? "nextSibling" : "previousSibling", q = b.parentNode, r = h && b.nodeName.toLowerCase(), t = !i && !h; if (q) { if (f) { while (p) { l = b; while (l = l[p]) if (h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) return !1; o = p = "only" === a && !o && "nextSibling" } return !0 } if (o = [g ? q.firstChild : q.lastChild], g && t) { k = q[s] || (q[s] = {}), j = k[a] || [], n = j[0] === u && j[1], m = j[0] === u && j[2], l = n && q.childNodes[n]; while (l = ++n && l && l[p] || (m = n = 0) || o.pop()) if (1 === l.nodeType && ++m && l === b) { k[a] = [u, n, m]; break } } else if (t && (j = (b[s] || (b[s] = {}))[a]) && j[0] === u) m = j[1]; else while (l = ++n && l && l[p] || (m = n = 0) || o.pop()) if ((h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) && ++m && (t && ((l[s] || (l[s] = {}))[a] = [u, m]), l === b)) break; return m -= e, m === d || m % d === 0 && m / d >= 0 } } }, PSEUDO: function (a, b) { var c, e = d.pseudos[a] || d.setFilters[a.toLowerCase()] || db.error("unsupported pseudo: " + a); return e[s] ? e(b) : e.length > 1 ? (c = [a, a, "", b], d.setFilters.hasOwnProperty(a.toLowerCase()) ? fb(function (a, c) { var d, f = e(a, b), g = f.length; while (g--) d = I.call(a, f[g]), a[d] = !(c[d] = f[g]) }) : function (a) { return e(a, 0, c) }) : e } }, pseudos: { not: fb(function (a) { var b = [], c = [], d = g(a.replace(P, "$1")); return d[s] ? fb(function (a, b, c, e) { var f, g = d(a, null, e, []), h = a.length; while (h--) (f = g[h]) && (a[h] = !(b[h] = f)) }) : function (a, e, f) { return b[0] = a, d(b, null, f, c), !c.pop() } }), has: fb(function (a) { return function (b) { return db(a, b).length > 0 } }), contains: fb(function (a) { return function (b) { return (b.textContent || b.innerText || e(b)).indexOf(a) > -1 } }), lang: fb(function (a) { return U.test(a || "") || db.error("unsupported lang: " + a), a = a.replace(ab, bb).toLowerCase(), function (b) { var c; do if (c = n ? b.lang : b.getAttribute("xml:lang") || b.getAttribute("lang")) return c = c.toLowerCase(), c === a || 0 === c.indexOf(a + "-"); while ((b = b.parentNode) && 1 === b.nodeType); return !1 } }), target: function (b) { var c = a.location && a.location.hash; return c && c.slice(1) === b.id }, root: function (a) { return a === m }, focus: function (a) { return a === l.activeElement && (!l.hasFocus || l.hasFocus()) && !!(a.type || a.href || ~a.tabIndex) }, enabled: function (a) { return a.disabled === !1 }, disabled: function (a) { return a.disabled === !0 }, checked: function (a) { var b = a.nodeName.toLowerCase(); return "input" === b && !!a.checked || "option" === b && !!a.selected }, selected: function (a) { return a.parentNode && a.parentNode.selectedIndex, a.selected === !0 }, empty: function (a) { for (a = a.firstChild; a; a = a.nextSibling) if (a.nodeType < 6) return !1; return !0 }, parent: function (a) { return !d.pseudos.empty(a) }, header: function (a) { return X.test(a.nodeName) }, input: function (a) { return W.test(a.nodeName) }, button: function (a) { var b = a.nodeName.toLowerCase(); return "input" === b && "button" === a.type || "button" === b }, text: function (a) { var b; return "input" === a.nodeName.toLowerCase() && "text" === a.type && (null == (b = a.getAttribute("type")) || "text" === b.toLowerCase()) }, first: lb(function () { return [0] }), last: lb(function (a, b) { return [b - 1] }), eq: lb(function (a, b, c) { return [0 > c ? c + b : c] }), even: lb(function (a, b) { for (var c = 0; b > c; c += 2) a.push(c); return a }), odd: lb(function (a, b) { for (var c = 1; b > c; c += 2) a.push(c); return a }), lt: lb(function (a, b, c) { for (var d = 0 > c ? c + b : c; --d >= 0;) a.push(d); return a }), gt: lb(function (a, b, c) { for (var d = 0 > c ? c + b : c; ++d < b;) a.push(d); return a }) } }, d.pseudos.nth = d.pseudos.eq; for (b in{radio: !0, checkbox: !0, file: !0, password: !0, image: !0}) d.pseudos[b] = jb(b); for (b in{submit: !0, reset: !0}) d.pseudos[b] = kb(b); function nb() { } nb.prototype = d.filters = d.pseudos, d.setFilters = new nb; function ob(a, b) { var c, e, f, g, h, i, j, k = x[a + " "]; if (k) return b ? 0 : k.slice(0); h = a, i = [], j = d.preFilter; while (h) { (!c || (e = Q.exec(h))) && (e && (h = h.slice(e[0].length) || h), i.push(f = [])), c = !1, (e = R.exec(h)) && (c = e.shift(), f.push({ value: c, type: e[0].replace(P, " ") }), h = h.slice(c.length)); for (g in d.filter) !(e = V[g].exec(h)) || j[g] && !(e = j[g](e)) || (c = e.shift(), f.push({ value: c, type: g, matches: e }), h = h.slice(c.length)); if (!c) break } return b ? h.length : h ? db.error(a) : x(a, i).slice(0) } function pb(a) { for (var b = 0, c = a.length, d = ""; c > b; b++) d += a[b].value; return d } function qb(a, b, c) { var d = b.dir, e = c && "parentNode" === d, f = v++; return b.first ? function (b, c, f) { while (b = b[d]) if (1 === b.nodeType || e) return a(b, c, f) } : function (b, c, g) { var h, i, j = [u, f]; if (g) { while (b = b[d]) if ((1 === b.nodeType || e) && a(b, c, g)) return !0 } else while (b = b[d]) if (1 === b.nodeType || e) { if (i = b[s] || (b[s] = {}), (h = i[d]) && h[0] === u && h[1] === f) return j[2] = h[2]; if (i[d] = j, j[2] = a(b, c, g)) return !0 } } } function rb(a) { return a.length > 1 ? function (b, c, d) { var e = a.length; while (e--) if (!a[e](b, c, d)) return !1; return !0 } : a[0] } function sb(a, b, c, d, e) { for (var f, g = [], h = 0, i = a.length, j = null != b; i > h; h++) (f = a[h]) && (!c || c(f, d, e)) && (g.push(f), j && b.push(h)); return g } function tb(a, b, c, d, e, f) { return d && !d[s] && (d = tb(d)), e && !e[s] && (e = tb(e, f)), fb(function (f, g, h, i) { var j, k, l, m = [], n = [], o = g.length, p = f || wb(b || "*", h.nodeType ? [h] : h, []), q = !a || !f && b ? p : sb(p, m, a, h, i), r = c ? e || (f ? a : o || d) ? [] : g : q; if (c && c(q, r, h, i), d) { j = sb(r, n), d(j, [], h, i), k = j.length; while (k--) (l = j[k]) && (r[n[k]] = !(q[n[k]] = l)) } if (f) { if (e || a) { if (e) { j = [], k = r.length; while (k--) (l = r[k]) && j.push(q[k] = l); e(null, r = [], j, i) } k = r.length; while (k--) (l = r[k]) && (j = e ? I.call(f, l) : m[k]) > -1 && (f[j] = !(g[j] = l)) } } else r = sb(r === g ? r.splice(o, r.length) : r), e ? e(null, g, r, i) : G.apply(g, r) }) } function ub(a) { for (var b, c, e, f = a.length, g = d.relative[a[0].type], i = g || d.relative[" "], j = g ? 1 : 0, k = qb(function (a) { return a === b }, i, !0), l = qb(function (a) { return I.call(b, a) > -1 }, i, !0), m = [function (a, c, d) { return !g && (d || c !== h) || ((b = c).nodeType ? k(a, c, d) : l(a, c, d)) }]; f > j; j++) if (c = d.relative[a[j].type]) m = [qb(rb(m), c)]; else { if (c = d.filter[a[j].type].apply(null, a[j].matches), c[s]) { for (e = ++j; f > e; e++) if (d.relative[a[e].type]) break; return tb(j > 1 && rb(m), j > 1 && pb(a.slice(0, j - 1).concat({value: " " === a[j - 2].type ? "*" : ""})).replace(P, "$1"), c, e > j && ub(a.slice(j, e)), f > e && ub(a = a.slice(e)), f > e && pb(a)) } m.push(c) } return rb(m) } function vb(a, b) { var c = b.length > 0, e = a.length > 0, f = function (f, g, i, j, k) { var m, n, o, p = 0, q = "0", r = f && [], s = [], t = h, v = f || e && d.find.TAG("*", k), w = u += null == t ? 1 : Math.random() || .1, x = v.length; for (k && (h = g !== l && g); q !== x && null != (m = v[q]); q++) { if (e && m) { n = 0; while (o = a[n++]) if (o(m, g, i)) { j.push(m); break } k && (u = w) } c && ((m = !o && m) && p--, f && r.push(m)) } if (p += q, c && q !== p) { n = 0; while (o = b[n++]) o(r, s, g, i); if (f) { if (p > 0) while (q--) r[q] || s[q] || (s[q] = E.call(j)); s = sb(s) } G.apply(j, s), k && !f && s.length > 0 && p + b.length > 1 && db.uniqueSort(j) } return k && (u = w, h = t), r }; return c ? fb(f) : f } g = db.compile = function (a, b) { var c, d = [], e = [], f = y[a + " "]; if (!f) { b || (b = ob(a)), c = b.length; while (c--) f = ub(b[c]), f[s] ? d.push(f) : e.push(f); f = y(a, vb(e, d)) } return f }; function wb(a, b, c) { for (var d = 0, e = b.length; e > d; d++) db(a, b[d], c); return c } function xb(a, b, e, f) { var h, i, j, k, l, m = ob(a); if (!f && 1 === m.length) { if (i = m[0] = m[0].slice(0), i.length > 2 && "ID" === (j = i[0]).type && c.getById && 9 === b.nodeType && n && d.relative[i[1].type]) { if (b = (d.find.ID(j.matches[0].replace(ab, bb), b) || [])[0], !b) return e; a = a.slice(i.shift().value.length) } h = V.needsContext.test(a) ? 0 : i.length; while (h--) { if (j = i[h], d.relative[k = j.type]) break; if ((l = d.find[k]) && (f = l(j.matches[0].replace(ab, bb), $.test(i[0].type) && mb(b.parentNode) || b))) { if (i.splice(h, 1), a = f.length && pb(i), !a) return G.apply(e, f), e; break } } } return g(a, m)(f, b, !n, e, $.test(a) && mb(b.parentNode) || b), e } return c.sortStable = s.split("").sort(z).join("") === s, c.detectDuplicates = !!j, k(), c.sortDetached = gb(function (a) { return 1 & a.compareDocumentPosition(l.createElement("div")) }), gb(function (a) { return a.innerHTML = "<a href='#'></a>", "#" === a.firstChild.getAttribute("href") }) || hb("type|href|height|width", function (a, b, c) { return c ? void 0 : a.getAttribute(b, "type" === b.toLowerCase() ? 1 : 2) }), c.attributes && gb(function (a) { return a.innerHTML = "<input/>", a.firstChild.setAttribute("value", ""), "" === a.firstChild.getAttribute("value") }) || hb("value", function (a, b, c) { return c || "input" !== a.nodeName.toLowerCase() ? void 0 : a.defaultValue }), gb(function (a) { return null == a.getAttribute("disabled") }) || hb(J, function (a, b, c) { var d; return c ? void 0 : a[b] === !0 ? b.toLowerCase() : (d = a.getAttributeNode(b)) && d.specified ? d.value : null }), db }(a); n.find = t, n.expr = t.selectors, n.expr[":"] = n.expr.pseudos, n.unique = t.uniqueSort, n.text = t.getText, n.isXMLDoc = t.isXML, n.contains = t.contains; var u = n.expr.match.needsContext, v = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, w = /^.[^:#\[\.,]*$/; function x(a, b, c) { if (n.isFunction(b)) return n.grep(a, function (a, d) { return !!b.call(a, d, a) !== c }); if (b.nodeType) return n.grep(a, function (a) { return a === b !== c }); if ("string" == typeof b) { if (w.test(b)) return n.filter(b, a, c); b = n.filter(b, a) } return n.grep(a, function (a) { return n.inArray(a, b) >= 0 !== c }) } n.filter = function (a, b, c) { var d = b[0]; return c && (a = ":not(" + a + ")"), 1 === b.length && 1 === d.nodeType ? n.find.matchesSelector(d, a) ? [d] : [] : n.find.matches(a, n.grep(b, function (a) { return 1 === a.nodeType })) }, n.fn.extend({ find: function (a) { var b, c = [], d = this, e = d.length; if ("string" != typeof a) return this.pushStack(n(a).filter(function () { for (b = 0; e > b; b++) if (n.contains(d[b], this)) return !0 })); for (b = 0; e > b; b++) n.find(a, d[b], c); return c = this.pushStack(e > 1 ? n.unique(c) : c), c.selector = this.selector ? this.selector + " " + a : a, c }, filter: function (a) { return this.pushStack(x(this, a || [], !1)) }, not: function (a) { return this.pushStack(x(this, a || [], !0)) }, is: function (a) { return !!x(this, "string" == typeof a && u.test(a) ? n(a) : a || [], !1).length } }); var y, z = a.document, A = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, B = n.fn.init = function (a, b) { var c, d; if (!a) return this; if ("string" == typeof a) { if (c = "<" === a.charAt(0) && ">" === a.charAt(a.length - 1) && a.length >= 3 ? [null, a, null] : A.exec(a), !c || !c[1] && b) return !b || b.jquery ? (b || y).find(a) : this.constructor(b).find(a); if (c[1]) { if (b = b instanceof n ? b[0] : b, n.merge(this, n.parseHTML(c[1], b && b.nodeType ? b.ownerDocument || b : z, !0)), v.test(c[1]) && n.isPlainObject(b)) for (c in b) n.isFunction(this[c]) ? this[c](b[c]) : this.attr(c, b[c]); return this } if (d = z.getElementById(c[2]), d && d.parentNode) { if (d.id !== c[2]) return y.find(a); this.length = 1, this[0] = d } return this.context = z, this.selector = a, this } return a.nodeType ? (this.context = this[0] = a, this.length = 1, this) : n.isFunction(a) ? "undefined" != typeof y.ready ? y.ready(a) : a(n) : (void 0 !== a.selector && (this.selector = a.selector, this.context = a.context), n.makeArray(a, this)) }; B.prototype = n.fn, y = n(z); var C = /^(?:parents|prev(?:Until|All))/, D = {children: !0, contents: !0, next: !0, prev: !0}; n.extend({ dir: function (a, b, c) { var d = [], e = a[b]; while (e && 9 !== e.nodeType && (void 0 === c || 1 !== e.nodeType || !n(e).is(c))) 1 === e.nodeType && d.push(e), e = e[b]; return d }, sibling: function (a, b) { for (var c = []; a; a = a.nextSibling) 1 === a.nodeType && a !== b && c.push(a); return c } }), n.fn.extend({ has: function (a) { var b, c = n(a, this), d = c.length; return this.filter(function () { for (b = 0; d > b; b++) if (n.contains(this, c[b])) return !0 }) }, closest: function (a, b) { for (var c, d = 0, e = this.length, f = [], g = u.test(a) || "string" != typeof a ? n(a, b || this.context) : 0; e > d; d++) for (c = this[d]; c && c !== b; c = c.parentNode) if (c.nodeType < 11 && (g ? g.index(c) > -1 : 1 === c.nodeType && n.find.matchesSelector(c, a))) { f.push(c); break } return this.pushStack(f.length > 1 ? n.unique(f) : f) }, index: function (a) { return a ? "string" == typeof a ? n.inArray(this[0], n(a)) : n.inArray(a.jquery ? a[0] : a, this) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 }, add: function (a, b) { return this.pushStack(n.unique(n.merge(this.get(), n(a, b)))) }, addBack: function (a) { return this.add(null == a ? this.prevObject : this.prevObject.filter(a)) } }); function E(a, b) { do a = a[b]; while (a && 1 !== a.nodeType); return a } n.each({ parent: function (a) { var b = a.parentNode; return b && 11 !== b.nodeType ? b : null }, parents: function (a) { return n.dir(a, "parentNode") }, parentsUntil: function (a, b, c) { return n.dir(a, "parentNode", c) }, next: function (a) { return E(a, "nextSibling") }, prev: function (a) { return E(a, "previousSibling") }, nextAll: function (a) { return n.dir(a, "nextSibling") }, prevAll: function (a) { return n.dir(a, "previousSibling") }, nextUntil: function (a, b, c) { return n.dir(a, "nextSibling", c) }, prevUntil: function (a, b, c) { return n.dir(a, "previousSibling", c) }, siblings: function (a) { return n.sibling((a.parentNode || {}).firstChild, a) }, children: function (a) { return n.sibling(a.firstChild) }, contents: function (a) { return n.nodeName(a, "iframe") ? a.contentDocument || a.contentWindow.document : n.merge([], a.childNodes) } }, function (a, b) { n.fn[a] = function (c, d) { var e = n.map(this, b, c); return "Until" !== a.slice(-5) && (d = c), d && "string" == typeof d && (e = n.filter(d, e)), this.length > 1 && (D[a] || (e = n.unique(e)), C.test(a) && (e = e.reverse())), this.pushStack(e) } }); var F = /\S+/g, G = {}; function H(a) { var b = G[a] = {}; return n.each(a.match(F) || [], function (a, c) { b[c] = !0 }), b } n.Callbacks = function (a) { a = "string" == typeof a ? G[a] || H(a) : n.extend({}, a); var b, c, d, e, f, g, h = [], i = !a.once && [], j = function (l) { for (c = a.memory && l, d = !0, f = g || 0, g = 0, e = h.length, b = !0; h && e > f; f++) if (h[f].apply(l[0], l[1]) === !1 && a.stopOnFalse) { c = !1; break } b = !1, h && (i ? i.length && j(i.shift()) : c ? h = [] : k.disable()) }, k = { add: function () { if (h) { var d = h.length; !function f(b) { n.each(b, function (b, c) { var d = n.type(c); "function" === d ? a.unique && k.has(c) || h.push(c) : c && c.length && "string" !== d && f(c) }) }(arguments), b ? e = h.length : c && (g = d, j(c)) } return this }, remove: function () { return h && n.each(arguments, function (a, c) { var d; while ((d = n.inArray(c, h, d)) > -1) h.splice(d, 1), b && (e >= d && e--, f >= d && f--) }), this }, has: function (a) { return a ? n.inArray(a, h) > -1 : !(!h || !h.length) }, empty: function () { return h = [], e = 0, this }, disable: function () { return h = i = c = void 0, this }, disabled: function () { return !h }, lock: function () { return i = void 0, c || k.disable(), this }, locked: function () { return !i }, fireWith: function (a, c) { return !h || d && !i || (c = c || [], c = [a, c.slice ? c.slice() : c], b ? i.push(c) : j(c)), this }, fire: function () { return k.fireWith(this, arguments), this }, fired: function () { return !!d } }; return k }, n.extend({ Deferred: function (a) { var b = [["resolve", "done", n.Callbacks("once memory"), "resolved"], ["reject", "fail", n.Callbacks("once memory"), "rejected"], ["notify", "progress", n.Callbacks("memory")]], c = "pending", d = { state: function () { return c }, always: function () { return e.done(arguments).fail(arguments), this }, then: function () { var a = arguments; return n.Deferred(function (c) { n.each(b, function (b, f) { var g = n.isFunction(a[b]) && a[b]; e[f[1]](function () { var a = g && g.apply(this, arguments); a && n.isFunction(a.promise) ? a.promise().done(c.resolve).fail(c.reject).progress(c.notify) : c[f[0] + "With"](this === d ? c.promise() : this, g ? [a] : arguments) }) }), a = null }).promise() }, promise: function (a) { return null != a ? n.extend(a, d) : d } }, e = {}; return d.pipe = d.then, n.each(b, function (a, f) { var g = f[2], h = f[3]; d[f[1]] = g.add, h && g.add(function () { c = h }, b[1 ^ a][2].disable, b[2][2].lock), e[f[0]] = function () { return e[f[0] + "With"](this === e ? d : this, arguments), this }, e[f[0] + "With"] = g.fireWith }), d.promise(e), a && a.call(e, e), e }, when: function (a) { var b = 0, c = d.call(arguments), e = c.length, f = 1 !== e || a && n.isFunction(a.promise) ? e : 0, g = 1 === f ? a : n.Deferred(), h = function (a, b, c) { return function (e) { b[a] = this, c[a] = arguments.length > 1 ? d.call(arguments) : e, c === i ? g.notifyWith(b, c) : --f || g.resolveWith(b, c) } }, i, j, k; if (e > 1) for (i = new Array(e), j = new Array(e), k = new Array(e); e > b; b++) c[b] && n.isFunction(c[b].promise) ? c[b].promise().done(h(b, k, c)).fail(g.reject).progress(h(b, j, i)) : --f; return f || g.resolveWith(k, c), g.promise() } }); var I; n.fn.ready = function (a) { return n.ready.promise().done(a), this }, n.extend({ isReady: !1, readyWait: 1, holdReady: function (a) { a ? n.readyWait++ : n.ready(!0) }, ready: function (a) { if (a === !0 ? !--n.readyWait : !n.isReady) { if (!z.body) return setTimeout(n.ready); n.isReady = !0, a !== !0 && --n.readyWait > 0 || (I.resolveWith(z, [n]), n.fn.trigger && n(z).trigger("ready").off("ready")) } } }); function J() { z.addEventListener ? (z.removeEventListener("DOMContentLoaded", K, !1), a.removeEventListener("load", K, !1)) : (z.detachEvent("onreadystatechange", K), a.detachEvent("onload", K)) } function K() { (z.addEventListener || "load" === event.type || "complete" === z.readyState) && (J(), n.ready()) } n.ready.promise = function (b) { if (!I) if (I = n.Deferred(), "complete" === z.readyState) setTimeout(n.ready); else if (z.addEventListener) z.addEventListener("DOMContentLoaded", K, !1), a.addEventListener("load", K, !1); else { z.attachEvent("onreadystatechange", K), a.attachEvent("onload", K); var c = !1; try { c = null == a.frameElement && z.documentElement } catch (d) { } c && c.doScroll && !function e() { if (!n.isReady) { try { c.doScroll("left") } catch (a) { return setTimeout(e, 50) } J(), n.ready() } }() } return I.promise(b) }; var L = "undefined", M; for (M in n(l)) break; l.ownLast = "0" !== M, l.inlineBlockNeedsLayout = !1, n(function () { var a, b, c = z.getElementsByTagName("body")[0]; c && (a = z.createElement("div"), a.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px", b = z.createElement("div"), c.appendChild(a).appendChild(b), typeof b.style.zoom !== L && (b.style.cssText = "border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1", (l.inlineBlockNeedsLayout = 3 === b.offsetWidth) && (c.style.zoom = 1)), c.removeChild(a), a = b = null) }), function () { var a = z.createElement("div"); if (null == l.deleteExpando) { l.deleteExpando = !0; try { delete a.test } catch (b) { l.deleteExpando = !1 } } a = null }(), n.acceptData = function (a) { var b = n.noData[(a.nodeName + " ").toLowerCase()], c = +a.nodeType || 1; return 1 !== c && 9 !== c ? !1 : !b || b !== !0 && a.getAttribute("classid") === b }; var N = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, O = /([A-Z])/g; function P(a, b, c) { if (void 0 === c && 1 === a.nodeType) { var d = "data-" + b.replace(O, "-$1").toLowerCase(); if (c = a.getAttribute(d), "string" == typeof c) { try { c = "true" === c ? !0 : "false" === c ? !1 : "null" === c ? null : +c + "" === c ? +c : N.test(c) ? n.parseJSON(c) : c } catch (e) { } n.data(a, b, c) } else c = void 0 } return c } function Q(a) { var b; for (b in a) if (("data" !== b || !n.isEmptyObject(a[b])) && "toJSON" !== b) return !1; return !0 } function R(a, b, d, e) { if (n.acceptData(a)) { var f, g, h = n.expando, i = a.nodeType, j = i ? n.cache : a, k = i ? a[h] : a[h] && h; if (k && j[k] && (e || j[k].data) || void 0 !== d || "string" != typeof b) return k || (k = i ? a[h] = c.pop() || n.guid++ : h), j[k] || (j[k] = i ? {} : {toJSON: n.noop}), ("object" == typeof b || "function" == typeof b) && (e ? j[k] = n.extend(j[k], b) : j[k].data = n.extend(j[k].data, b)), g = j[k], e || (g.data || (g.data = {}), g = g.data), void 0 !== d && (g[n.camelCase(b)] = d), "string" == typeof b ? (f = g[b], null == f && (f = g[n.camelCase(b)])) : f = g, f } } function S(a, b, c) { if (n.acceptData(a)) { var d, e, f = a.nodeType, g = f ? n.cache : a, h = f ? a[n.expando] : n.expando; if (g[h]) { if (b && (d = c ? g[h] : g[h].data)) { n.isArray(b) ? b = b.concat(n.map(b, n.camelCase)) : b in d ? b = [b] : (b = n.camelCase(b), b = b in d ? [b] : b.split(" ")), e = b.length; while (e--) delete d[b[e]]; if (c ? !Q(d) : !n.isEmptyObject(d)) return } (c || (delete g[h].data, Q(g[h]))) && (f ? n.cleanData([a], !0) : l.deleteExpando || g != g.window ? delete g[h] : g[h] = null) } } } n.extend({ cache: {}, noData: {"applet ": !0, "embed ": !0, "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"}, hasData: function (a) { return a = a.nodeType ? n.cache[a[n.expando]] : a[n.expando], !!a && !Q(a) }, data: function (a, b, c) { return R(a, b, c) }, removeData: function (a, b) { return S(a, b) }, _data: function (a, b, c) { return R(a, b, c, !0) }, _removeData: function (a, b) { return S(a, b, !0) } }), n.fn.extend({ data: function (a, b) { var c, d, e, f = this[0], g = f && f.attributes; if (void 0 === a) { if (this.length && (e = n.data(f), 1 === f.nodeType && !n._data(f, "parsedAttrs"))) { c = g.length; while (c--) d = g[c].name, 0 === d.indexOf("data-") && (d = n.camelCase(d.slice(5)), P(f, d, e[d])); n._data(f, "parsedAttrs", !0) } return e } return "object" == typeof a ? this.each(function () { n.data(this, a) }) : arguments.length > 1 ? this.each(function () { n.data(this, a, b) }) : f ? P(f, a, n.data(f, a)) : void 0 }, removeData: function (a) { return this.each(function () { n.removeData(this, a) }) } }), n.extend({ queue: function (a, b, c) { var d; return a ? (b = (b || "fx") + "queue", d = n._data(a, b), c && (!d || n.isArray(c) ? d = n._data(a, b, n.makeArray(c)) : d.push(c)), d || []) : void 0 }, dequeue: function (a, b) { b = b || "fx"; var c = n.queue(a, b), d = c.length, e = c.shift(), f = n._queueHooks(a, b), g = function () { n.dequeue(a, b) }; "inprogress" === e && (e = c.shift(), d--), e && ("fx" === b && c.unshift("inprogress"), delete f.stop, e.call(a, g, f)), !d && f && f.empty.fire() }, _queueHooks: function (a, b) { var c = b + "queueHooks"; return n._data(a, c) || n._data(a, c, { empty: n.Callbacks("once memory").add(function () { n._removeData(a, b + "queue"), n._removeData(a, c) }) }) } }), n.fn.extend({ queue: function (a, b) { var c = 2; return "string" != typeof a && (b = a, a = "fx", c--), arguments.length < c ? n.queue(this[0], a) : void 0 === b ? this : this.each(function () { var c = n.queue(this, a, b); n._queueHooks(this, a), "fx" === a && "inprogress" !== c[0] && n.dequeue(this, a) }) }, dequeue: function (a) { return this.each(function () { n.dequeue(this, a) }) }, clearQueue: function (a) { return this.queue(a || "fx", []) }, promise: function (a, b) { var c, d = 1, e = n.Deferred(), f = this, g = this.length, h = function () { --d || e.resolveWith(f, [f]) }; "string" != typeof a && (b = a, a = void 0), a = a || "fx"; while (g--) c = n._data(f[g], a + "queueHooks"), c && c.empty && (d++, c.empty.add(h)); return h(), e.promise(b) } }); var T = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, U = ["Top", "Right", "Bottom", "Left"], V = function (a, b) { return a = b || a, "none" === n.css(a, "display") || !n.contains(a.ownerDocument, a) }, W = n.access = function (a, b, c, d, e, f, g) { var h = 0, i = a.length, j = null == c; if ("object" === n.type(c)) { e = !0; for (h in c) n.access(a, b, h, c[h], !0, f, g) } else if (void 0 !== d && (e = !0, n.isFunction(d) || (g = !0), j && (g ? (b.call(a, d), b = null) : (j = b, b = function (a, b, c) { return j.call(n(a), c) })), b)) for (; i > h; h++) b(a[h], c, g ? d : d.call(a[h], h, b(a[h], c))); return e ? a : j ? b.call(a) : i ? b(a[0], c) : f }, X = /^(?:checkbox|radio)$/i; !function () { var a = z.createDocumentFragment(), b = z.createElement("div"), c = z.createElement("input"); if (b.setAttribute("className", "t"), b.innerHTML = " <link/><table></table><a href='/a'>a</a>", l.leadingWhitespace = 3 === b.firstChild.nodeType, l.tbody = !b.getElementsByTagName("tbody").length, l.htmlSerialize = !!b.getElementsByTagName("link").length, l.html5Clone = "<:nav></:nav>" !== z.createElement("nav").cloneNode(!0).outerHTML, c.type = "checkbox", c.checked = !0, a.appendChild(c), l.appendChecked = c.checked, b.innerHTML = "<textarea>x</textarea>", l.noCloneChecked = !!b.cloneNode(!0).lastChild.defaultValue, a.appendChild(b), b.innerHTML = "<input type='radio' checked='checked' name='t'/>", l.checkClone = b.cloneNode(!0).cloneNode(!0).lastChild.checked, l.noCloneEvent = !0, b.attachEvent && (b.attachEvent("onclick", function () { l.noCloneEvent = !1 }), b.cloneNode(!0).click()), null == l.deleteExpando) { l.deleteExpando = !0; try { delete b.test } catch (d) { l.deleteExpando = !1 } } a = b = c = null }(), function () { var b, c, d = z.createElement("div"); for (b in{ submit: !0, change: !0, focusin: !0 }) c = "on" + b, (l[b + "Bubbles"] = c in a) || (d.setAttribute(c, "t"), l[b + "Bubbles"] = d.attributes[c].expando === !1); d = null }(); var Y = /^(?:input|select|textarea)$/i, Z = /^key/, $ = /^(?:mouse|contextmenu)|click/, _ = /^(?:focusinfocus|focusoutblur)$/, ab = /^([^.]*)(?:\.(.+)|)$/; function bb() { return !0 } function cb() { return !1 } function db() { try { return z.activeElement } catch (a) { } } n.event = { global: {}, add: function (a, b, c, d, e) { var f, g, h, i, j, k, l, m, o, p, q, r = n._data(a); if (r) { c.handler && (i = c, c = i.handler, e = i.selector), c.guid || (c.guid = n.guid++), (g = r.events) || (g = r.events = {}), (k = r.handle) || (k = r.handle = function (a) { return typeof n === L || a && n.event.triggered === a.type ? void 0 : n.event.dispatch.apply(k.elem, arguments) }, k.elem = a), b = (b || "").match(F) || [""], h = b.length; while (h--) f = ab.exec(b[h]) || [], o = q = f[1], p = (f[2] || "").split(".").sort(), o && (j = n.event.special[o] || {}, o = (e ? j.delegateType : j.bindType) || o, j = n.event.special[o] || {}, l = n.extend({ type: o, origType: q, data: d, handler: c, guid: c.guid, selector: e, needsContext: e && n.expr.match.needsContext.test(e), namespace: p.join(".") }, i), (m = g[o]) || (m = g[o] = [], m.delegateCount = 0, j.setup && j.setup.call(a, d, p, k) !== !1 || (a.addEventListener ? a.addEventListener(o, k, !1) : a.attachEvent && a.attachEvent("on" + o, k))), j.add && (j.add.call(a, l), l.handler.guid || (l.handler.guid = c.guid)), e ? m.splice(m.delegateCount++, 0, l) : m.push(l), n.event.global[o] = !0); a = null } }, remove: function (a, b, c, d, e) { var f, g, h, i, j, k, l, m, o, p, q, r = n.hasData(a) && n._data(a); if (r && (k = r.events)) { b = (b || "").match(F) || [""], j = b.length; while (j--) if (h = ab.exec(b[j]) || [], o = q = h[1], p = (h[2] || "").split(".").sort(), o) { l = n.event.special[o] || {}, o = (d ? l.delegateType : l.bindType) || o, m = k[o] || [], h = h[2] && new RegExp("(^|\\.)" + p.join("\\.(?:.*\\.|)") + "(\\.|$)"), i = f = m.length; while (f--) g = m[f], !e && q !== g.origType || c && c.guid !== g.guid || h && !h.test(g.namespace) || d && d !== g.selector && ("**" !== d || !g.selector) || (m.splice(f, 1), g.selector && m.delegateCount--, l.remove && l.remove.call(a, g)); i && !m.length && (l.teardown && l.teardown.call(a, p, r.handle) !== !1 || n.removeEvent(a, o, r.handle), delete k[o]) } else for (o in k) n.event.remove(a, o + b[j], c, d, !0); n.isEmptyObject(k) && (delete r.handle, n._removeData(a, "events")) } }, trigger: function (b, c, d, e) { var f, g, h, i, k, l, m, o = [d || z], p = j.call(b, "type") ? b.type : b, q = j.call(b, "namespace") ? b.namespace.split(".") : []; if (h = l = d = d || z, 3 !== d.nodeType && 8 !== d.nodeType && !_.test(p + n.event.triggered) && (p.indexOf(".") >= 0 && (q = p.split("."), p = q.shift(), q.sort()), g = p.indexOf(":") < 0 && "on" + p, b = b[n.expando] ? b : new n.Event(p, "object" == typeof b && b), b.isTrigger = e ? 2 : 3, b.namespace = q.join("."), b.namespace_re = b.namespace ? new RegExp("(^|\\.)" + q.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, b.result = void 0, b.target || (b.target = d), c = null == c ? [b] : n.makeArray(c, [b]), k = n.event.special[p] || {}, e || !k.trigger || k.trigger.apply(d, c) !== !1)) { if (!e && !k.noBubble && !n.isWindow(d)) { for (i = k.delegateType || p, _.test(i + p) || (h = h.parentNode); h; h = h.parentNode) o.push(h), l = h; l === (d.ownerDocument || z) && o.push(l.defaultView || l.parentWindow || a) } m = 0; while ((h = o[m++]) && !b.isPropagationStopped()) b.type = m > 1 ? i : k.bindType || p, f = (n._data(h, "events") || {})[b.type] && n._data(h, "handle"), f && f.apply(h, c), f = g && h[g], f && f.apply && n.acceptData(h) && (b.result = f.apply(h, c), b.result === !1 && b.preventDefault()); if (b.type = p, !e && !b.isDefaultPrevented() && (!k._default || k._default.apply(o.pop(), c) === !1) && n.acceptData(d) && g && d[p] && !n.isWindow(d)) { l = d[g], l && (d[g] = null), n.event.triggered = p; try { d[p]() } catch (r) { } n.event.triggered = void 0, l && (d[g] = l) } return b.result } }, dispatch: function (a) { a = n.event.fix(a); var b, c, e, f, g, h = [], i = d.call(arguments), j = (n._data(this, "events") || {})[a.type] || [], k = n.event.special[a.type] || {}; if (i[0] = a, a.delegateTarget = this, !k.preDispatch || k.preDispatch.call(this, a) !== !1) { h = n.event.handlers.call(this, a, j), b = 0; while ((f = h[b++]) && !a.isPropagationStopped()) { a.currentTarget = f.elem, g = 0; while ((e = f.handlers[g++]) && !a.isImmediatePropagationStopped()) (!a.namespace_re || a.namespace_re.test(e.namespace)) && (a.handleObj = e, a.data = e.data, c = ((n.event.special[e.origType] || {}).handle || e.handler).apply(f.elem, i), void 0 !== c && (a.result = c) === !1 && (a.preventDefault(), a.stopPropagation())) } return k.postDispatch && k.postDispatch.call(this, a), a.result } }, handlers: function (a, b) { var c, d, e, f, g = [], h = b.delegateCount, i = a.target; if (h && i.nodeType && (!a.button || "click" !== a.type)) for (; i != this; i = i.parentNode || this) if (1 === i.nodeType && (i.disabled !== !0 || "click" !== a.type)) { for (e = [], f = 0; h > f; f++) d = b[f], c = d.selector + " ", void 0 === e[c] && (e[c] = d.needsContext ? n(c, this).index(i) >= 0 : n.find(c, this, null, [i]).length), e[c] && e.push(d); e.length && g.push({elem: i, handlers: e}) } return h < b.length && g.push({elem: this, handlers: b.slice(h)}), g }, fix: function (a) { if (a[n.expando]) return a; var b, c, d, e = a.type, f = a, g = this.fixHooks[e]; g || (this.fixHooks[e] = g = $.test(e) ? this.mouseHooks : Z.test(e) ? this.keyHooks : {}), d = g.props ? this.props.concat(g.props) : this.props, a = new n.Event(f), b = d.length; while (b--) c = d[b], a[c] = f[c]; return a.target || (a.target = f.srcElement || z), 3 === a.target.nodeType && (a.target = a.target.parentNode), a.metaKey = !!a.metaKey, g.filter ? g.filter(a, f) : a }, props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: { props: "char charCode key keyCode".split(" "), filter: function (a, b) { return null == a.which && (a.which = null != b.charCode ? b.charCode : b.keyCode), a } }, mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function (a, b) { var c, d, e, f = b.button, g = b.fromElement; return null == a.pageX && null != b.clientX && (d = a.target.ownerDocument || z, e = d.documentElement, c = d.body, a.pageX = b.clientX + (e && e.scrollLeft || c && c.scrollLeft || 0) - (e && e.clientLeft || c && c.clientLeft || 0), a.pageY = b.clientY + (e && e.scrollTop || c && c.scrollTop || 0) - (e && e.clientTop || c && c.clientTop || 0)), !a.relatedTarget && g && (a.relatedTarget = g === a.target ? b.toElement : g), a.which || void 0 === f || (a.which = 1 & f ? 1 : 2 & f ? 3 : 4 & f ? 2 : 0), a } }, special: { load: {noBubble: !0}, focus: { trigger: function () { if (this !== db() && this.focus) try { return this.focus(), !1 } catch (a) { } }, delegateType: "focusin" }, blur: { trigger: function () { return this === db() && this.blur ? (this.blur(), !1) : void 0 }, delegateType: "focusout" }, click: { trigger: function () { return n.nodeName(this, "input") && "checkbox" === this.type && this.click ? (this.click(), !1) : void 0 }, _default: function (a) { return n.nodeName(a.target, "a") } }, beforeunload: { postDispatch: function (a) { void 0 !== a.result && (a.originalEvent.returnValue = a.result) } } }, simulate: function (a, b, c, d) { var e = n.extend(new n.Event, c, {type: a, isSimulated: !0, originalEvent: {}}); d ? n.event.trigger(e, null, b) : n.event.dispatch.call(b, e), e.isDefaultPrevented() && c.preventDefault() } }, n.removeEvent = z.removeEventListener ? function (a, b, c) { a.removeEventListener && a.removeEventListener(b, c, !1) } : function (a, b, c) { var d = "on" + b; a.detachEvent && (typeof a[d] === L && (a[d] = null), a.detachEvent(d, c)) }, n.Event = function (a, b) { return this instanceof n.Event ? (a && a.type ? (this.originalEvent = a, this.type = a.type, this.isDefaultPrevented = a.defaultPrevented || void 0 === a.defaultPrevented && (a.returnValue === !1 || a.getPreventDefault && a.getPreventDefault()) ? bb : cb) : this.type = a, b && n.extend(this, b), this.timeStamp = a && a.timeStamp || n.now(), void(this[n.expando] = !0)) : new n.Event(a, b) }, n.Event.prototype = { isDefaultPrevented: cb, isPropagationStopped: cb, isImmediatePropagationStopped: cb, preventDefault: function () { var a = this.originalEvent; this.isDefaultPrevented = bb, a && (a.preventDefault ? a.preventDefault() : a.returnValue = !1) }, stopPropagation: function () { var a = this.originalEvent; this.isPropagationStopped = bb, a && (a.stopPropagation && a.stopPropagation(), a.cancelBubble = !0) }, stopImmediatePropagation: function () { this.isImmediatePropagationStopped = bb, this.stopPropagation() } }, n.each({mouseenter: "mouseover", mouseleave: "mouseout"}, function (a, b) { n.event.special[a] = { delegateType: b, bindType: b, handle: function (a) { var c, d = this, e = a.relatedTarget, f = a.handleObj; return (!e || e !== d && !n.contains(d, e)) && (a.type = f.origType, c = f.handler.apply(this, arguments), a.type = b), c } } }), l.submitBubbles || (n.event.special.submit = { setup: function () { return n.nodeName(this, "form") ? !1 : void n.event.add(this, "click._submit keypress._submit", function (a) { var b = a.target, c = n.nodeName(b, "input") || n.nodeName(b, "button") ? b.form : void 0; c && !n._data(c, "submitBubbles") && (n.event.add(c, "submit._submit", function (a) { a._submit_bubble = !0 }), n._data(c, "submitBubbles", !0)) }) }, postDispatch: function (a) { a._submit_bubble && (delete a._submit_bubble, this.parentNode && !a.isTrigger && n.event.simulate("submit", this.parentNode, a, !0)) }, teardown: function () { return n.nodeName(this, "form") ? !1 : void n.event.remove(this, "._submit") } }), l.changeBubbles || (n.event.special.change = { setup: function () { return Y.test(this.nodeName) ? (("checkbox" === this.type || "radio" === this.type) && (n.event.add(this, "propertychange._change", function (a) { "checked" === a.originalEvent.propertyName && (this._just_changed = !0) }), n.event.add(this, "click._change", function (a) { this._just_changed && !a.isTrigger && (this._just_changed = !1), n.event.simulate("change", this, a, !0) })), !1) : void n.event.add(this, "beforeactivate._change", function (a) { var b = a.target; Y.test(b.nodeName) && !n._data(b, "changeBubbles") && (n.event.add(b, "change._change", function (a) { !this.parentNode || a.isSimulated || a.isTrigger || n.event.simulate("change", this.parentNode, a, !0) }), n._data(b, "changeBubbles", !0)) }) }, handle: function (a) { var b = a.target; return this !== b || a.isSimulated || a.isTrigger || "radio" !== b.type && "checkbox" !== b.type ? a.handleObj.handler.apply(this, arguments) : void 0 }, teardown: function () { return n.event.remove(this, "._change"), !Y.test(this.nodeName) } }), l.focusinBubbles || n.each({focus: "focusin", blur: "focusout"}, function (a, b) { var c = function (a) { n.event.simulate(b, a.target, n.event.fix(a), !0) }; n.event.special[b] = { setup: function () { var d = this.ownerDocument || this, e = n._data(d, b); e || d.addEventListener(a, c, !0), n._data(d, b, (e || 0) + 1) }, teardown: function () { var d = this.ownerDocument || this, e = n._data(d, b) - 1; e ? n._data(d, b, e) : (d.removeEventListener(a, c, !0), n._removeData(d, b)) } } }), n.fn.extend({ on: function (a, b, c, d, e) { var f, g; if ("object" == typeof a) { "string" != typeof b && (c = c || b, b = void 0); for (f in a) this.on(f, b, c, a[f], e); return this } if (null == c && null == d ? (d = b, c = b = void 0) : null == d && ("string" == typeof b ? (d = c, c = void 0) : (d = c, c = b, b = void 0)), d === !1) d = cb; else if (!d) return this; return 1 === e && (g = d, d = function (a) { return n().off(a), g.apply(this, arguments) }, d.guid = g.guid || (g.guid = n.guid++)), this.each(function () { n.event.add(this, a, d, c, b) }) }, one: function (a, b, c, d) { return this.on(a, b, c, d, 1) }, off: function (a, b, c) { var d, e; if (a && a.preventDefault && a.handleObj) return d = a.handleObj, n(a.delegateTarget).off(d.namespace ? d.origType + "." + d.namespace : d.origType, d.selector, d.handler), this; if ("object" == typeof a) { for (e in a) this.off(e, b, a[e]); return this } return (b === !1 || "function" == typeof b) && (c = b, b = void 0), c === !1 && (c = cb), this.each(function () { n.event.remove(this, a, c, b) }) }, trigger: function (a, b) { return this.each(function () { n.event.trigger(a, b, this) }) }, triggerHandler: function (a, b) { var c = this[0]; return c ? n.event.trigger(a, b, c, !0) : void 0 } }); function eb(a) { var b = fb.split("|"), c = a.createDocumentFragment(); if (c.createElement) while (b.length) c.createElement(b.pop()); return c } var fb = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", gb = / jQuery\d+="(?:null|\d+)"/g, hb = new RegExp("<(?:" + fb + ")[\\s/>]", "i"), ib = /^\s+/, jb = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, kb = /<([\w:]+)/, lb = /<tbody/i, mb = /<|&#?\w+;/, nb = /<(?:script|style|link)/i, ob = /checked\s*(?:[^=]|=\s*.checked.)/i, pb = /^$|\/(?:java|ecma)script/i, qb = /^true\/(.*)/, rb = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, sb = { option: [1, "<select multiple='multiple'>", "</select>"], legend: [1, "<fieldset>", "</fieldset>"], area: [1, "<map>", "</map>"], param: [1, "<object>", "</object>"], thead: [1, "<table>", "</table>"], tr: [2, "<table><tbody>", "</tbody></table>"], col: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"], td: [3, "<table><tbody><tr>", "</tr></tbody></table>"], _default: l.htmlSerialize ? [0, "", ""] : [1, "X<div>", "</div>"] }, tb = eb(z), ub = tb.appendChild(z.createElement("div")); sb.optgroup = sb.option, sb.tbody = sb.tfoot = sb.colgroup = sb.caption = sb.thead, sb.th = sb.td; function vb(a, b) { var c, d, e = 0, f = typeof a.getElementsByTagName !== L ? a.getElementsByTagName(b || "*") : typeof a.querySelectorAll !== L ? a.querySelectorAll(b || "*") : void 0; if (!f) for (f = [], c = a.childNodes || a; null != (d = c[e]); e++) !b || n.nodeName(d, b) ? f.push(d) : n.merge(f, vb(d, b)); return void 0 === b || b && n.nodeName(a, b) ? n.merge([a], f) : f } function wb(a) { X.test(a.type) && (a.defaultChecked = a.checked) } function xb(a, b) { return n.nodeName(a, "table") && n.nodeName(11 !== b.nodeType ? b : b.firstChild, "tr") ? a.getElementsByTagName("tbody")[0] || a.appendChild(a.ownerDocument.createElement("tbody")) : a } function yb(a) { return a.type = (null !== n.find.attr(a, "type")) + "/" + a.type, a } function zb(a) { var b = qb.exec(a.type); return b ? a.type = b[1] : a.removeAttribute("type"), a } function Ab(a, b) { for (var c, d = 0; null != (c = a[d]); d++) n._data(c, "globalEval", !b || n._data(b[d], "globalEval")) } function Bb(a, b) { if (1 === b.nodeType && n.hasData(a)) { var c, d, e, f = n._data(a), g = n._data(b, f), h = f.events; if (h) { delete g.handle, g.events = {}; for (c in h) for (d = 0, e = h[c].length; e > d; d++) n.event.add(b, c, h[c][d]) } g.data && (g.data = n.extend({}, g.data)) } } function Cb(a, b) { var c, d, e; if (1 === b.nodeType) { if (c = b.nodeName.toLowerCase(), !l.noCloneEvent && b[n.expando]) { e = n._data(b); for (d in e.events) n.removeEvent(b, d, e.handle); b.removeAttribute(n.expando) } "script" === c && b.text !== a.text ? (yb(b).text = a.text, zb(b)) : "object" === c ? (b.parentNode && (b.outerHTML = a.outerHTML), l.html5Clone && a.innerHTML && !n.trim(b.innerHTML) && (b.innerHTML = a.innerHTML)) : "input" === c && X.test(a.type) ? (b.defaultChecked = b.checked = a.checked, b.value !== a.value && (b.value = a.value)) : "option" === c ? b.defaultSelected = b.selected = a.defaultSelected : ("input" === c || "textarea" === c) && (b.defaultValue = a.defaultValue) } } n.extend({ clone: function (a, b, c) { var d, e, f, g, h, i = n.contains(a.ownerDocument, a); if (l.html5Clone || n.isXMLDoc(a) || !hb.test("<" + a.nodeName + ">") ? f = a.cloneNode(!0) : (ub.innerHTML = a.outerHTML, ub.removeChild(f = ub.firstChild)), !(l.noCloneEvent && l.noCloneChecked || 1 !== a.nodeType && 11 !== a.nodeType || n.isXMLDoc(a))) for (d = vb(f), h = vb(a), g = 0; null != (e = h[g]); ++g) d[g] && Cb(e, d[g]); if (b) if (c) for (h = h || vb(a), d = d || vb(f), g = 0; null != (e = h[g]); g++) Bb(e, d[g]); else Bb(a, f); return d = vb(f, "script"), d.length > 0 && Ab(d, !i && vb(a, "script")), d = h = e = null, f }, buildFragment: function (a, b, c, d) { for (var e, f, g, h, i, j, k, m = a.length, o = eb(b), p = [], q = 0; m > q; q++) if (f = a[q], f || 0 === f) if ("object" === n.type(f)) n.merge(p, f.nodeType ? [f] : f); else if (mb.test(f)) { h = h || o.appendChild(b.createElement("div")), i = (kb.exec(f) || ["", ""])[1].toLowerCase(), k = sb[i] || sb._default, h.innerHTML = k[1] + f.replace(jb, "<$1></$2>") + k[2], e = k[0]; while (e--) h = h.lastChild; if (!l.leadingWhitespace && ib.test(f) && p.push(b.createTextNode(ib.exec(f)[0])), !l.tbody) { f = "table" !== i || lb.test(f) ? "<table>" !== k[1] || lb.test(f) ? 0 : h : h.firstChild, e = f && f.childNodes.length; while (e--) n.nodeName(j = f.childNodes[e], "tbody") && !j.childNodes.length && f.removeChild(j) } n.merge(p, h.childNodes), h.textContent = ""; while (h.firstChild) h.removeChild(h.firstChild); h = o.lastChild } else p.push(b.createTextNode(f)); h && o.removeChild(h), l.appendChecked || n.grep(vb(p, "input"), wb), q = 0; while (f = p[q++]) if ((!d || -1 === n.inArray(f, d)) && (g = n.contains(f.ownerDocument, f), h = vb(o.appendChild(f), "script"), g && Ab(h), c)) { e = 0; while (f = h[e++]) pb.test(f.type || "") && c.push(f) } return h = null, o }, cleanData: function (a, b) { for (var d, e, f, g, h = 0, i = n.expando, j = n.cache, k = l.deleteExpando, m = n.event.special; null != (d = a[h]); h++) if ((b || n.acceptData(d)) && (f = d[i], g = f && j[f])) { if (g.events) for (e in g.events) m[e] ? n.event.remove(d, e) : n.removeEvent(d, e, g.handle); j[f] && (delete j[f], k ? delete d[i] : typeof d.removeAttribute !== L ? d.removeAttribute(i) : d[i] = null, c.push(f)) } } }), n.fn.extend({ text: function (a) { return W(this, function (a) { return void 0 === a ? n.text(this) : this.empty().append((this[0] && this[0].ownerDocument || z).createTextNode(a)) }, null, a, arguments.length) }, append: function () { return this.domManip(arguments, function (a) { if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { var b = xb(this, a); b.appendChild(a) } }) }, prepend: function () { return this.domManip(arguments, function (a) { if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { var b = xb(this, a); b.insertBefore(a, b.firstChild) } }) }, before: function () { return this.domManip(arguments, function (a) { this.parentNode && this.parentNode.insertBefore(a, this) }) }, after: function () { return this.domManip(arguments, function (a) { this.parentNode && this.parentNode.insertBefore(a, this.nextSibling) }) }, remove: function (a, b) { for (var c, d = a ? n.filter(a, this) : this, e = 0; null != (c = d[e]); e++) b || 1 !== c.nodeType || n.cleanData(vb(c)), c.parentNode && (b && n.contains(c.ownerDocument, c) && Ab(vb(c, "script")), c.parentNode.removeChild(c)); return this }, empty: function () { for (var a, b = 0; null != (a = this[b]); b++) { 1 === a.nodeType && n.cleanData(vb(a, !1)); while (a.firstChild) a.removeChild(a.firstChild); a.options && n.nodeName(a, "select") && (a.options.length = 0) } return this }, clone: function (a, b) { return a = null == a ? !1 : a, b = null == b ? a : b, this.map(function () { return n.clone(this, a, b) }) }, html: function (a) { return W(this, function (a) { var b = this[0] || {}, c = 0, d = this.length; if (void 0 === a) return 1 === b.nodeType ? b.innerHTML.replace(gb, "") : void 0; if (!("string" != typeof a || nb.test(a) || !l.htmlSerialize && hb.test(a) || !l.leadingWhitespace && ib.test(a) || sb[(kb.exec(a) || ["", ""])[1].toLowerCase()])) { a = a.replace(jb, "<$1></$2>"); try { for (; d > c; c++) b = this[c] || {}, 1 === b.nodeType && (n.cleanData(vb(b, !1)), b.innerHTML = a); b = 0 } catch (e) { } } b && this.empty().append(a) }, null, a, arguments.length) }, replaceWith: function () { var a = arguments[0]; return this.domManip(arguments, function (b) { a = this.parentNode, n.cleanData(vb(this)), a && a.replaceChild(b, this) }), a && (a.length || a.nodeType) ? this : this.remove() }, detach: function (a) { return this.remove(a, !0) }, domManip: function (a, b) { a = e.apply([], a); var c, d, f, g, h, i, j = 0, k = this.length, m = this, o = k - 1, p = a[0], q = n.isFunction(p); if (q || k > 1 && "string" == typeof p && !l.checkClone && ob.test(p)) return this.each(function (c) { var d = m.eq(c); q && (a[0] = p.call(this, c, d.html())), d.domManip(a, b) }); if (k && (i = n.buildFragment(a, this[0].ownerDocument, !1, this), c = i.firstChild, 1 === i.childNodes.length && (i = c), c)) { for (g = n.map(vb(i, "script"), yb), f = g.length; k > j; j++) d = i, j !== o && (d = n.clone(d, !0, !0), f && n.merge(g, vb(d, "script"))), b.call(this[j], d, j); if (f) for (h = g[g.length - 1].ownerDocument, n.map(g, zb), j = 0; f > j; j++) d = g[j], pb.test(d.type || "") && !n._data(d, "globalEval") && n.contains(h, d) && (d.src ? n._evalUrl && n._evalUrl(d.src) : n.globalEval((d.text || d.textContent || d.innerHTML || "").replace(rb, ""))); i = c = null } return this } }), n.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function (a, b) { n.fn[a] = function (a) { for (var c, d = 0, e = [], g = n(a), h = g.length - 1; h >= d; d++) c = d === h ? this : this.clone(!0), n(g[d])[b](c), f.apply(e, c.get()); return this.pushStack(e) } }); var Db, Eb = {}; function Fb(b, c) { var d = n(c.createElement(b)).appendTo(c.body), e = a.getDefaultComputedStyle ? a.getDefaultComputedStyle(d[0]).display : n.css(d[0], "display"); return d.detach(), e } function Gb(a) { var b = z, c = Eb[a]; return c || (c = Fb(a, b), "none" !== c && c || (Db = (Db || n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement), b = (Db[0].contentWindow || Db[0].contentDocument).document, b.write(), b.close(), c = Fb(a, b), Db.detach()), Eb[a] = c), c } !function () { var a, b, c = z.createElement("div"), d = "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0"; c.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>", a = c.getElementsByTagName("a")[0], a.style.cssText = "float:left;opacity:.5", l.opacity = /^0.5/.test(a.style.opacity), l.cssFloat = !!a.style.cssFloat, c.style.backgroundClip = "content-box", c.cloneNode(!0).style.backgroundClip = "", l.clearCloneStyle = "content-box" === c.style.backgroundClip, a = c = null, l.shrinkWrapBlocks = function () { var a, c, e, f; if (null == b) { if (a = z.getElementsByTagName("body")[0], !a) return; f = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px", c = z.createElement("div"), e = z.createElement("div"), a.appendChild(c).appendChild(e), b = !1, typeof e.style.zoom !== L && (e.style.cssText = d + ";width:1px;padding:1px;zoom:1", e.innerHTML = "<div></div>", e.firstChild.style.width = "5px", b = 3 !== e.offsetWidth), a.removeChild(c), a = c = e = null } return b } }(); var Hb = /^margin/, Ib = new RegExp("^(" + T + ")(?!px)[a-z%]+$", "i"), Jb, Kb, Lb = /^(top|right|bottom|left)$/; a.getComputedStyle ? (Jb = function (a) { return a.ownerDocument.defaultView.getComputedStyle(a, null) }, Kb = function (a, b, c) { var d, e, f, g, h = a.style; return c = c || Jb(a), g = c ? c.getPropertyValue(b) || c[b] : void 0, c && ("" !== g || n.contains(a.ownerDocument, a) || (g = n.style(a, b)), Ib.test(g) && Hb.test(b) && (d = h.width, e = h.minWidth, f = h.maxWidth, h.minWidth = h.maxWidth = h.width = g, g = c.width, h.width = d, h.minWidth = e, h.maxWidth = f)), void 0 === g ? g : g + "" }) : z.documentElement.currentStyle && (Jb = function (a) { return a.currentStyle }, Kb = function (a, b, c) { var d, e, f, g, h = a.style; return c = c || Jb(a), g = c ? c[b] : void 0, null == g && h && h[b] && (g = h[b]), Ib.test(g) && !Lb.test(b) && (d = h.left, e = a.runtimeStyle, f = e && e.left, f && (e.left = a.currentStyle.left), h.left = "fontSize" === b ? "1em" : g, g = h.pixelLeft + "px", h.left = d, f && (e.left = f)), void 0 === g ? g : g + "" || "auto" }); function Mb(a, b) { return { get: function () { var c = a(); if (null != c) return c ? void delete this.get : (this.get = b).apply(this, arguments) } } } !function () { var b, c, d, e, f, g, h = z.createElement("div"), i = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px", j = "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0"; h.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>", b = h.getElementsByTagName("a")[0], b.style.cssText = "float:left;opacity:.5", l.opacity = /^0.5/.test(b.style.opacity), l.cssFloat = !!b.style.cssFloat, h.style.backgroundClip = "content-box", h.cloneNode(!0).style.backgroundClip = "", l.clearCloneStyle = "content-box" === h.style.backgroundClip, b = h = null, n.extend(l, { reliableHiddenOffsets: function () { if (null != c) return c; var a, b, d, e = z.createElement("div"), f = z.getElementsByTagName("body")[0]; if (f) return e.setAttribute("className", "t"), e.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>", a = z.createElement("div"), a.style.cssText = i, f.appendChild(a).appendChild(e), e.innerHTML = "<table><tr><td></td><td>t</td></tr></table>", b = e.getElementsByTagName("td"), b[0].style.cssText = "padding:0;margin:0;border:0;display:none", d = 0 === b[0].offsetHeight, b[0].style.display = "", b[1].style.display = "none", c = d && 0 === b[0].offsetHeight, f.removeChild(a), e = f = null, c }, boxSizing: function () { return null == d && k(), d }, boxSizingReliable: function () { return null == e && k(), e }, pixelPosition: function () { return null == f && k(), f }, reliableMarginRight: function () { var b, c, d, e; if (null == g && a.getComputedStyle) { if (b = z.getElementsByTagName("body")[0], !b) return; c = z.createElement("div"), d = z.createElement("div"), c.style.cssText = i, b.appendChild(c).appendChild(d), e = d.appendChild(z.createElement("div")), e.style.cssText = d.style.cssText = j, e.style.marginRight = e.style.width = "0", d.style.width = "1px", g = !parseFloat((a.getComputedStyle(e, null) || {}).marginRight), b.removeChild(c) } return g } }); function k() { var b, c, h = z.getElementsByTagName("body")[0]; h && (b = z.createElement("div"), c = z.createElement("div"), b.style.cssText = i, h.appendChild(b).appendChild(c), c.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;display:block;padding:1px;border:1px;width:4px;margin-top:1%;top:1%", n.swap(h, null != h.style.zoom ? {zoom: 1} : {}, function () { d = 4 === c.offsetWidth }), e = !0, f = !1, g = !0, a.getComputedStyle && (f = "1%" !== (a.getComputedStyle(c, null) || {}).top, e = "4px" === (a.getComputedStyle(c, null) || {width: "4px"}).width), h.removeChild(b), c = h = null) } }(), n.swap = function (a, b, c, d) { var e, f, g = {}; for (f in b) g[f] = a.style[f], a.style[f] = b[f]; e = c.apply(a, d || []); for (f in b) a.style[f] = g[f]; return e }; var Nb = /alpha\([^)]*\)/i, Ob = /opacity\s*=\s*([^)]*)/, Pb = /^(none|table(?!-c[ea]).+)/, Qb = new RegExp("^(" + T + ")(.*)$", "i"), Rb = new RegExp("^([+-])=(" + T + ")", "i"), Sb = {position: "absolute", visibility: "hidden", display: "block"}, Tb = {letterSpacing: 0, fontWeight: 400}, Ub = ["Webkit", "O", "Moz", "ms"]; function Vb(a, b) { if (b in a) return b; var c = b.charAt(0).toUpperCase() + b.slice(1), d = b, e = Ub.length; while (e--) if (b = Ub[e] + c, b in a) return b; return d } function Wb(a, b) { for (var c, d, e, f = [], g = 0, h = a.length; h > g; g++) d = a[g], d.style && (f[g] = n._data(d, "olddisplay"), c = d.style.display, b ? (f[g] || "none" !== c || (d.style.display = ""), "" === d.style.display && V(d) && (f[g] = n._data(d, "olddisplay", Gb(d.nodeName)))) : f[g] || (e = V(d), (c && "none" !== c || !e) && n._data(d, "olddisplay", e ? c : n.css(d, "display")))); for (g = 0; h > g; g++) d = a[g], d.style && (b && "none" !== d.style.display && "" !== d.style.display || (d.style.display = b ? f[g] || "" : "none")); return a } function Xb(a, b, c) { var d = Qb.exec(b); return d ? Math.max(0, d[1] - (c || 0)) + (d[2] || "px") : b } function Yb(a, b, c, d, e) { for (var f = c === (d ? "border" : "content") ? 4 : "width" === b ? 1 : 0, g = 0; 4 > f; f += 2) "margin" === c && (g += n.css(a, c + U[f], !0, e)), d ? ("content" === c && (g -= n.css(a, "padding" + U[f], !0, e)), "margin" !== c && (g -= n.css(a, "border" + U[f] + "Width", !0, e))) : (g += n.css(a, "padding" + U[f], !0, e), "padding" !== c && (g += n.css(a, "border" + U[f] + "Width", !0, e))); return g } function Zb(a, b, c) { var d = !0, e = "width" === b ? a.offsetWidth : a.offsetHeight, f = Jb(a), g = l.boxSizing() && "border-box" === n.css(a, "boxSizing", !1, f); if (0 >= e || null == e) { if (e = Kb(a, b, f), (0 > e || null == e) && (e = a.style[b]), Ib.test(e)) return e; d = g && (l.boxSizingReliable() || e === a.style[b]), e = parseFloat(e) || 0 } return e + Yb(a, b, c || (g ? "border" : "content"), d, f) + "px" } n.extend({ cssHooks: { opacity: { get: function (a, b) { if (b) { var c = Kb(a, "opacity"); return "" === c ? "1" : c } } } }, cssNumber: { columnCount: !0, fillOpacity: !0, fontWeight: !0, lineHeight: !0, opacity: !0, order: !0, orphans: !0, widows: !0, zIndex: !0, zoom: !0 }, cssProps: {"float": l.cssFloat ? "cssFloat" : "styleFloat"}, style: function (a, b, c, d) { if (a && 3 !== a.nodeType && 8 !== a.nodeType && a.style) { var e, f, g, h = n.camelCase(b), i = a.style; if (b = n.cssProps[h] || (n.cssProps[h] = Vb(i, h)), g = n.cssHooks[b] || n.cssHooks[h], void 0 === c) return g && "get" in g && void 0 !== (e = g.get(a, !1, d)) ? e : i[b]; if (f = typeof c, "string" === f && (e = Rb.exec(c)) && (c = (e[1] + 1) * e[2] + parseFloat(n.css(a, b)), f = "number"), null != c && c === c && ("number" !== f || n.cssNumber[h] || (c += "px"), l.clearCloneStyle || "" !== c || 0 !== b.indexOf("background") || (i[b] = "inherit"), !(g && "set" in g && void 0 === (c = g.set(a, c, d))))) try { i[b] = "", i[b] = c } catch (j) { } } }, css: function (a, b, c, d) { var e, f, g, h = n.camelCase(b); return b = n.cssProps[h] || (n.cssProps[h] = Vb(a.style, h)), g = n.cssHooks[b] || n.cssHooks[h], g && "get" in g && (f = g.get(a, !0, c)), void 0 === f && (f = Kb(a, b, d)), "normal" === f && b in Tb && (f = Tb[b]), "" === c || c ? (e = parseFloat(f), c === !0 || n.isNumeric(e) ? e || 0 : f) : f } }), n.each(["height", "width"], function (a, b) { n.cssHooks[b] = { get: function (a, c, d) { return c ? 0 === a.offsetWidth && Pb.test(n.css(a, "display")) ? n.swap(a, Sb, function () { return Zb(a, b, d) }) : Zb(a, b, d) : void 0 }, set: function (a, c, d) { var e = d && Jb(a); return Xb(a, c, d ? Yb(a, b, d, l.boxSizing() && "border-box" === n.css(a, "boxSizing", !1, e), e) : 0) } } }), l.opacity || (n.cssHooks.opacity = { get: function (a, b) { return Ob.test((b && a.currentStyle ? a.currentStyle.filter : a.style.filter) || "") ? .01 * parseFloat(RegExp.$1) + "" : b ? "1" : "" }, set: function (a, b) { var c = a.style, d = a.currentStyle, e = n.isNumeric(b) ? "alpha(opacity=" + 100 * b + ")" : "", f = d && d.filter || c.filter || ""; c.zoom = 1, (b >= 1 || "" === b) && "" === n.trim(f.replace(Nb, "")) && c.removeAttribute && (c.removeAttribute("filter"), "" === b || d && !d.filter) || (c.filter = Nb.test(f) ? f.replace(Nb, e) : f + " " + e) } }), n.cssHooks.marginRight = Mb(l.reliableMarginRight, function (a, b) { return b ? n.swap(a, {display: "inline-block"}, Kb, [a, "marginRight"]) : void 0 }), n.each({margin: "", padding: "", border: "Width"}, function (a, b) { n.cssHooks[a + b] = { expand: function (c) { for (var d = 0, e = {}, f = "string" == typeof c ? c.split(" ") : [c]; 4 > d; d++) e[a + U[d] + b] = f[d] || f[d - 2] || f[0]; return e } }, Hb.test(a) || (n.cssHooks[a + b].set = Xb) }), n.fn.extend({ css: function (a, b) { return W(this, function (a, b, c) { var d, e, f = {}, g = 0; if (n.isArray(b)) { for (d = Jb(a), e = b.length; e > g; g++) f[b[g]] = n.css(a, b[g], !1, d); return f } return void 0 !== c ? n.style(a, b, c) : n.css(a, b) }, a, b, arguments.length > 1) }, show: function () { return Wb(this, !0) }, hide: function () { return Wb(this) }, toggle: function (a) { return "boolean" == typeof a ? a ? this.show() : this.hide() : this.each(function () { V(this) ? n(this).show() : n(this).hide() }) } }); function $b(a, b, c, d, e) { return new $b.prototype.init(a, b, c, d, e) } n.Tween = $b, $b.prototype = { constructor: $b, init: function (a, b, c, d, e, f) { this.elem = a, this.prop = c, this.easing = e || "swing", this.options = b, this.start = this.now = this.cur(), this.end = d, this.unit = f || (n.cssNumber[c] ? "" : "px") }, cur: function () { var a = $b.propHooks[this.prop]; return a && a.get ? a.get(this) : $b.propHooks._default.get(this) }, run: function (a) { var b, c = $b.propHooks[this.prop]; return this.pos = b = this.options.duration ? n.easing[this.easing](a, this.options.duration * a, 0, 1, this.options.duration) : a, this.now = (this.end - this.start) * b + this.start, this.options.step && this.options.step.call(this.elem, this.now, this), c && c.set ? c.set(this) : $b.propHooks._default.set(this), this } }, $b.prototype.init.prototype = $b.prototype, $b.propHooks = { _default: { get: function (a) { var b; return null == a.elem[a.prop] || a.elem.style && null != a.elem.style[a.prop] ? (b = n.css(a.elem, a.prop, ""), b && "auto" !== b ? b : 0) : a.elem[a.prop] }, set: function (a) { n.fx.step[a.prop] ? n.fx.step[a.prop](a) : a.elem.style && (null != a.elem.style[n.cssProps[a.prop]] || n.cssHooks[a.prop]) ? n.style(a.elem, a.prop, a.now + a.unit) : a.elem[a.prop] = a.now } } }, $b.propHooks.scrollTop = $b.propHooks.scrollLeft = { set: function (a) { a.elem.nodeType && a.elem.parentNode && (a.elem[a.prop] = a.now) } }, n.easing = { linear: function (a) { return a }, swing: function (a) { return .5 - Math.cos(a * Math.PI) / 2 } }, n.fx = $b.prototype.init, n.fx.step = {}; var _b, ac, bc = /^(?:toggle|show|hide)$/, cc = new RegExp("^(?:([+-])=|)(" + T + ")([a-z%]*)$", "i"), dc = /queueHooks$/, ec = [jc], fc = { "*": [function (a, b) { var c = this.createTween(a, b), d = c.cur(), e = cc.exec(b), f = e && e[3] || (n.cssNumber[a] ? "" : "px"), g = (n.cssNumber[a] || "px" !== f && +d) && cc.exec(n.css(c.elem, a)), h = 1, i = 20; if (g && g[3] !== f) { f = f || g[3], e = e || [], g = +d || 1; do h = h || ".5", g /= h, n.style(c.elem, a, g + f); while (h !== (h = c.cur() / d) && 1 !== h && --i) } return e && (g = c.start = +g || +d || 0, c.unit = f, c.end = e[1] ? g + (e[1] + 1) * e[2] : +e[2]), c }] }; function gc() { return setTimeout(function () { _b = void 0 }), _b = n.now() } function hc(a, b) { var c, d = {height: a}, e = 0; for (b = b ? 1 : 0; 4 > e; e += 2 - b) c = U[e], d["margin" + c] = d["padding" + c] = a; return b && (d.opacity = d.width = a), d } function ic(a, b, c) { for (var d, e = (fc[b] || []).concat(fc["*"]), f = 0, g = e.length; g > f; f++) if (d = e[f].call(c, b, a)) return d } function jc(a, b, c) { var d, e, f, g, h, i, j, k, m = this, o = {}, p = a.style, q = a.nodeType && V(a), r = n._data(a, "fxshow"); c.queue || (h = n._queueHooks(a, "fx"), null == h.unqueued && (h.unqueued = 0, i = h.empty.fire, h.empty.fire = function () { h.unqueued || i() }), h.unqueued++, m.always(function () { m.always(function () { h.unqueued--, n.queue(a, "fx").length || h.empty.fire() }) })), 1 === a.nodeType && ("height" in b || "width" in b) && (c.overflow = [p.overflow, p.overflowX, p.overflowY], j = n.css(a, "display"), k = Gb(a.nodeName), "none" === j && (j = k), "inline" === j && "none" === n.css(a, "float") && (l.inlineBlockNeedsLayout && "inline" !== k ? p.zoom = 1 : p.display = "inline-block")), c.overflow && (p.overflow = "hidden", l.shrinkWrapBlocks() || m.always(function () { p.overflow = c.overflow[0], p.overflowX = c.overflow[1], p.overflowY = c.overflow[2] })); for (d in b) if (e = b[d], bc.exec(e)) { if (delete b[d], f = f || "toggle" === e, e === (q ? "hide" : "show")) { if ("show" !== e || !r || void 0 === r[d]) continue; q = !0 } o[d] = r && r[d] || n.style(a, d) } if (!n.isEmptyObject(o)) { r ? "hidden" in r && (q = r.hidden) : r = n._data(a, "fxshow", {}), f && (r.hidden = !q), q ? n(a).show() : m.done(function () { n(a).hide() }), m.done(function () { var b; n._removeData(a, "fxshow"); for (b in o) n.style(a, b, o[b]) }); for (d in o) g = ic(q ? r[d] : 0, d, m), d in r || (r[d] = g.start, q && (g.end = g.start, g.start = "width" === d || "height" === d ? 1 : 0)) } } function kc(a, b) { var c, d, e, f, g; for (c in a) if (d = n.camelCase(c), e = b[d], f = a[c], n.isArray(f) && (e = f[1], f = a[c] = f[0]), c !== d && (a[d] = f, delete a[c]), g = n.cssHooks[d], g && "expand" in g) { f = g.expand(f), delete a[d]; for (c in f) c in a || (a[c] = f[c], b[c] = e) } else b[d] = e } function lc(a, b, c) { var d, e, f = 0, g = ec.length, h = n.Deferred().always(function () { delete i.elem }), i = function () { if (e) return !1; for (var b = _b || gc(), c = Math.max(0, j.startTime + j.duration - b), d = c / j.duration || 0, f = 1 - d, g = 0, i = j.tweens.length; i > g; g++) j.tweens[g].run(f); return h.notifyWith(a, [j, f, c]), 1 > f && i ? c : (h.resolveWith(a, [j]), !1) }, j = h.promise({ elem: a, props: n.extend({}, b), opts: n.extend(!0, {specialEasing: {}}, c), originalProperties: b, originalOptions: c, startTime: _b || gc(), duration: c.duration, tweens: [], createTween: function (b, c) { var d = n.Tween(a, j.opts, b, c, j.opts.specialEasing[b] || j.opts.easing); return j.tweens.push(d), d }, stop: function (b) { var c = 0, d = b ? j.tweens.length : 0; if (e) return this; for (e = !0; d > c; c++) j.tweens[c].run(1); return b ? h.resolveWith(a, [j, b]) : h.rejectWith(a, [j, b]), this } }), k = j.props; for (kc(k, j.opts.specialEasing); g > f; f++) if (d = ec[f].call(j, a, k, j.opts)) return d; return n.map(k, ic, j), n.isFunction(j.opts.start) && j.opts.start.call(a, j), n.fx.timer(n.extend(i, { elem: a, anim: j, queue: j.opts.queue })), j.progress(j.opts.progress).done(j.opts.done, j.opts.complete).fail(j.opts.fail).always(j.opts.always) } n.Animation = n.extend(lc, { tweener: function (a, b) { n.isFunction(a) ? (b = a, a = ["*"]) : a = a.split(" "); for (var c, d = 0, e = a.length; e > d; d++) c = a[d], fc[c] = fc[c] || [], fc[c].unshift(b) }, prefilter: function (a, b) { b ? ec.unshift(a) : ec.push(a) } }), n.speed = function (a, b, c) { var d = a && "object" == typeof a ? n.extend({}, a) : { complete: c || !c && b || n.isFunction(a) && a, duration: a, easing: c && b || b && !n.isFunction(b) && b }; return d.duration = n.fx.off ? 0 : "number" == typeof d.duration ? d.duration : d.duration in n.fx.speeds ? n.fx.speeds[d.duration] : n.fx.speeds._default, (null == d.queue || d.queue === !0) && (d.queue = "fx"), d.old = d.complete, d.complete = function () { n.isFunction(d.old) && d.old.call(this), d.queue && n.dequeue(this, d.queue) }, d }, n.fn.extend({ fadeTo: function (a, b, c, d) { return this.filter(V).css("opacity", 0).show().end().animate({opacity: b}, a, c, d) }, animate: function (a, b, c, d) { var e = n.isEmptyObject(a), f = n.speed(b, c, d), g = function () { var b = lc(this, n.extend({}, a), f); (e || n._data(this, "finish")) && b.stop(!0) }; return g.finish = g, e || f.queue === !1 ? this.each(g) : this.queue(f.queue, g) }, stop: function (a, b, c) { var d = function (a) { var b = a.stop; delete a.stop, b(c) }; return "string" != typeof a && (c = b, b = a, a = void 0), b && a !== !1 && this.queue(a || "fx", []), this.each(function () { var b = !0, e = null != a && a + "queueHooks", f = n.timers, g = n._data(this); if (e) g[e] && g[e].stop && d(g[e]); else for (e in g) g[e] && g[e].stop && dc.test(e) && d(g[e]); for (e = f.length; e--;) f[e].elem !== this || null != a && f[e].queue !== a || (f[e].anim.stop(c), b = !1, f.splice(e, 1)); (b || !c) && n.dequeue(this, a) }) }, finish: function (a) { return a !== !1 && (a = a || "fx"), this.each(function () { var b, c = n._data(this), d = c[a + "queue"], e = c[a + "queueHooks"], f = n.timers, g = d ? d.length : 0; for (c.finish = !0, n.queue(this, a, []), e && e.stop && e.stop.call(this, !0), b = f.length; b--;) f[b].elem === this && f[b].queue === a && (f[b].anim.stop(!0), f.splice(b, 1)); for (b = 0; g > b; b++) d[b] && d[b].finish && d[b].finish.call(this); delete c.finish }) } }), n.each(["toggle", "show", "hide"], function (a, b) { var c = n.fn[b]; n.fn[b] = function (a, d, e) { return null == a || "boolean" == typeof a ? c.apply(this, arguments) : this.animate(hc(b, !0), a, d, e) } }), n.each({ slideDown: hc("show"), slideUp: hc("hide"), slideToggle: hc("toggle"), fadeIn: {opacity: "show"}, fadeOut: {opacity: "hide"}, fadeToggle: {opacity: "toggle"} }, function (a, b) { n.fn[a] = function (a, c, d) { return this.animate(b, a, c, d) } }), n.timers = [], n.fx.tick = function () { var a, b = n.timers, c = 0; for (_b = n.now(); c < b.length; c++) a = b[c], a() || b[c] !== a || b.splice(c--, 1); b.length || n.fx.stop(), _b = void 0 }, n.fx.timer = function (a) { n.timers.push(a), a() ? n.fx.start() : n.timers.pop() }, n.fx.interval = 13, n.fx.start = function () { ac || (ac = setInterval(n.fx.tick, n.fx.interval)) }, n.fx.stop = function () { clearInterval(ac), ac = null }, n.fx.speeds = {slow: 600, fast: 200, _default: 400}, n.fn.delay = function (a, b) { return a = n.fx ? n.fx.speeds[a] || a : a, b = b || "fx", this.queue(b, function (b, c) { var d = setTimeout(b, a); c.stop = function () { clearTimeout(d) } }) }, function () { var a, b, c, d, e = z.createElement("div"); e.setAttribute("className", "t"), e.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>", a = e.getElementsByTagName("a")[0], c = z.createElement("select"), d = c.appendChild(z.createElement("option")), b = e.getElementsByTagName("input")[0], a.style.cssText = "top:1px", l.getSetAttribute = "t" !== e.className, l.style = /top/.test(a.getAttribute("style")), l.hrefNormalized = "/a" === a.getAttribute("href"), l.checkOn = !!b.value, l.optSelected = d.selected, l.enctype = !!z.createElement("form").enctype, c.disabled = !0, l.optDisabled = !d.disabled, b = z.createElement("input"), b.setAttribute("value", ""), l.input = "" === b.getAttribute("value"), b.value = "t", b.setAttribute("type", "radio"), l.radioValue = "t" === b.value, a = b = c = d = e = null }(); var mc = /\r/g; n.fn.extend({ val: function (a) { var b, c, d, e = this[0]; { if (arguments.length) return d = n.isFunction(a), this.each(function (c) { var e; 1 === this.nodeType && (e = d ? a.call(this, c, n(this).val()) : a, null == e ? e = "" : "number" == typeof e ? e += "" : n.isArray(e) && (e = n.map(e, function (a) { return null == a ? "" : a + "" })), b = n.valHooks[this.type] || n.valHooks[this.nodeName.toLowerCase()], b && "set" in b && void 0 !== b.set(this, e, "value") || (this.value = e)) }); if (e) return b = n.valHooks[e.type] || n.valHooks[e.nodeName.toLowerCase()], b && "get" in b && void 0 !== (c = b.get(e, "value")) ? c : (c = e.value, "string" == typeof c ? c.replace(mc, "") : null == c ? "" : c) } } }), n.extend({ valHooks: { option: { get: function (a) { var b = n.find.attr(a, "value"); return null != b ? b : n.text(a) } }, select: { get: function (a) { for (var b, c, d = a.options, e = a.selectedIndex, f = "select-one" === a.type || 0 > e, g = f ? null : [], h = f ? e + 1 : d.length, i = 0 > e ? h : f ? e : 0; h > i; i++) if (c = d[i], !(!c.selected && i !== e || (l.optDisabled ? c.disabled : null !== c.getAttribute("disabled")) || c.parentNode.disabled && n.nodeName(c.parentNode, "optgroup"))) { if (b = n(c).val(), f) return b; g.push(b) } return g }, set: function (a, b) { var c, d, e = a.options, f = n.makeArray(b), g = e.length; while (g--) if (d = e[g], n.inArray(n.valHooks.option.get(d), f) >= 0) try { d.selected = c = !0 } catch (h) { d.scrollHeight } else d.selected = !1; return c || (a.selectedIndex = -1), e } } } }), n.each(["radio", "checkbox"], function () { n.valHooks[this] = { set: function (a, b) { return n.isArray(b) ? a.checked = n.inArray(n(a).val(), b) >= 0 : void 0 } }, l.checkOn || (n.valHooks[this].get = function (a) { return null === a.getAttribute("value") ? "on" : a.value }) }); var nc, oc, pc = n.expr.attrHandle, qc = /^(?:checked|selected)$/i, rc = l.getSetAttribute, sc = l.input; n.fn.extend({ attr: function (a, b) { return W(this, n.attr, a, b, arguments.length > 1) }, removeAttr: function (a) { return this.each(function () { n.removeAttr(this, a) }) } }), n.extend({ attr: function (a, b, c) { var d, e, f = a.nodeType; if (a && 3 !== f && 8 !== f && 2 !== f) return typeof a.getAttribute === L ? n.prop(a, b, c) : (1 === f && n.isXMLDoc(a) || (b = b.toLowerCase(), d = n.attrHooks[b] || (n.expr.match.bool.test(b) ? oc : nc)), void 0 === c ? d && "get" in d && null !== (e = d.get(a, b)) ? e : (e = n.find.attr(a, b), null == e ? void 0 : e) : null !== c ? d && "set" in d && void 0 !== (e = d.set(a, c, b)) ? e : (a.setAttribute(b, c + ""), c) : void n.removeAttr(a, b)) }, removeAttr: function (a, b) { var c, d, e = 0, f = b && b.match(F); if (f && 1 === a.nodeType) while (c = f[e++]) d = n.propFix[c] || c, n.expr.match.bool.test(c) ? sc && rc || !qc.test(c) ? a[d] = !1 : a[n.camelCase("default-" + c)] = a[d] = !1 : n.attr(a, c, ""), a.removeAttribute(rc ? c : d) }, attrHooks: { type: { set: function (a, b) { if (!l.radioValue && "radio" === b && n.nodeName(a, "input")) { var c = a.value; return a.setAttribute("type", b), c && (a.value = c), b } } } } }), oc = { set: function (a, b, c) { return b === !1 ? n.removeAttr(a, c) : sc && rc || !qc.test(c) ? a.setAttribute(!rc && n.propFix[c] || c, c) : a[n.camelCase("default-" + c)] = a[c] = !0, c } }, n.each(n.expr.match.bool.source.match(/\w+/g), function (a, b) { var c = pc[b] || n.find.attr; pc[b] = sc && rc || !qc.test(b) ? function (a, b, d) { var e, f; return d || (f = pc[b], pc[b] = e, e = null != c(a, b, d) ? b.toLowerCase() : null, pc[b] = f), e } : function (a, b, c) { return c ? void 0 : a[n.camelCase("default-" + b)] ? b.toLowerCase() : null } }), sc && rc || (n.attrHooks.value = { set: function (a, b, c) { return n.nodeName(a, "input") ? void(a.defaultValue = b) : nc && nc.set(a, b, c) } }), rc || (nc = { set: function (a, b, c) { var d = a.getAttributeNode(c); return d || a.setAttributeNode(d = a.ownerDocument.createAttribute(c)), d.value = b += "", "value" === c || b === a.getAttribute(c) ? b : void 0 } }, pc.id = pc.name = pc.coords = function (a, b, c) { var d; return c ? void 0 : (d = a.getAttributeNode(b)) && "" !== d.value ? d.value : null }, n.valHooks.button = { get: function (a, b) { var c = a.getAttributeNode(b); return c && c.specified ? c.value : void 0 }, set: nc.set }, n.attrHooks.contenteditable = { set: function (a, b, c) { nc.set(a, "" === b ? !1 : b, c) } }, n.each(["width", "height"], function (a, b) { n.attrHooks[b] = { set: function (a, c) { return "" === c ? (a.setAttribute(b, "auto"), c) : void 0 } } })), l.style || (n.attrHooks.style = { get: function (a) { return a.style.cssText || void 0 }, set: function (a, b) { return a.style.cssText = b + "" } }); var tc = /^(?:input|select|textarea|button|object)$/i, uc = /^(?:a|area)$/i; n.fn.extend({ prop: function (a, b) { return W(this, n.prop, a, b, arguments.length > 1) }, removeProp: function (a) { return a = n.propFix[a] || a, this.each(function () { try { this[a] = void 0, delete this[a] } catch (b) { } }) } }), n.extend({ propFix: {"for": "htmlFor", "class": "className"}, prop: function (a, b, c) { var d, e, f, g = a.nodeType; if (a && 3 !== g && 8 !== g && 2 !== g) return f = 1 !== g || !n.isXMLDoc(a), f && (b = n.propFix[b] || b, e = n.propHooks[b]), void 0 !== c ? e && "set" in e && void 0 !== (d = e.set(a, c, b)) ? d : a[b] = c : e && "get" in e && null !== (d = e.get(a, b)) ? d : a[b] }, propHooks: { tabIndex: { get: function (a) { var b = n.find.attr(a, "tabindex"); return b ? parseInt(b, 10) : tc.test(a.nodeName) || uc.test(a.nodeName) && a.href ? 0 : -1 } } } }), l.hrefNormalized || n.each(["href", "src"], function (a, b) { n.propHooks[b] = { get: function (a) { return a.getAttribute(b, 4) } } }), l.optSelected || (n.propHooks.selected = { get: function (a) { var b = a.parentNode; return b && (b.selectedIndex, b.parentNode && b.parentNode.selectedIndex), null } }), n.each(["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function () { n.propFix[this.toLowerCase()] = this }), l.enctype || (n.propFix.enctype = "encoding"); var vc = /[\t\r\n\f]/g; n.fn.extend({ addClass: function (a) { var b, c, d, e, f, g, h = 0, i = this.length, j = "string" == typeof a && a; if (n.isFunction(a)) return this.each(function (b) { n(this).addClass(a.call(this, b, this.className)) }); if (j) for (b = (a || "").match(F) || []; i > h; h++) if (c = this[h], d = 1 === c.nodeType && (c.className ? (" " + c.className + " ").replace(vc, " ") : " ")) { f = 0; while (e = b[f++]) d.indexOf(" " + e + " ") < 0 && (d += e + " "); g = n.trim(d), c.className !== g && (c.className = g) } return this }, removeClass: function (a) { var b, c, d, e, f, g, h = 0, i = this.length, j = 0 === arguments.length || "string" == typeof a && a; if (n.isFunction(a)) return this.each(function (b) { n(this).removeClass(a.call(this, b, this.className)) }); if (j) for (b = (a || "").match(F) || []; i > h; h++) if (c = this[h], d = 1 === c.nodeType && (c.className ? (" " + c.className + " ").replace(vc, " ") : "")) { f = 0; while (e = b[f++]) while (d.indexOf(" " + e + " ") >= 0) d = d.replace(" " + e + " ", " "); g = a ? n.trim(d) : "", c.className !== g && (c.className = g) } return this }, toggleClass: function (a, b) { var c = typeof a; return "boolean" == typeof b && "string" === c ? b ? this.addClass(a) : this.removeClass(a) : this.each(n.isFunction(a) ? function (c) { n(this).toggleClass(a.call(this, c, this.className, b), b) } : function () { if ("string" === c) { var b, d = 0, e = n(this), f = a.match(F) || []; while (b = f[d++]) e.hasClass(b) ? e.removeClass(b) : e.addClass(b) } else (c === L || "boolean" === c) && (this.className && n._data(this, "__className__", this.className), this.className = this.className || a === !1 ? "" : n._data(this, "__className__") || "") }) }, hasClass: function (a) { for (var b = " " + a + " ", c = 0, d = this.length; d > c; c++) if (1 === this[c].nodeType && (" " + this[c].className + " ").replace(vc, " ").indexOf(b) >= 0) return !0; return !1 } }), n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "), function (a, b) { n.fn[b] = function (a, c) { return arguments.length > 0 ? this.on(b, null, a, c) : this.trigger(b) } }), n.fn.extend({ hover: function (a, b) { return this.mouseenter(a).mouseleave(b || a) }, bind: function (a, b, c) { return this.on(a, null, b, c) }, unbind: function (a, b) { return this.off(a, null, b) }, delegate: function (a, b, c, d) { return this.on(b, a, c, d) }, undelegate: function (a, b, c) { return 1 === arguments.length ? this.off(a, "**") : this.off(b, a || "**", c) } }); var wc = n.now(), xc = /\?/, yc = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g; n.parseJSON = function (b) { if (a.JSON && a.JSON.parse) return a.JSON.parse(b + ""); var c, d = null, e = n.trim(b + ""); return e && !n.trim(e.replace(yc, function (a, b, e, f) { return c && b && (d = 0), 0 === d ? a : (c = e || b, d += !f - !e, "") })) ? Function("return " + e)() : n.error("Invalid JSON: " + b) }, n.parseXML = function (b) { var c, d; if (!b || "string" != typeof b) return null; try { a.DOMParser ? (d = new DOMParser, c = d.parseFromString(b, "text/xml")) : (c = new ActiveXObject("Microsoft.XMLDOM"), c.async = "false", c.loadXML(b)) } catch (e) { c = void 0 } return c && c.documentElement && !c.getElementsByTagName("parsererror").length || n.error("Invalid XML: " + b), c }; var zc, Ac, Bc = /#.*$/, Cc = /([?&])_=[^&]*/, Dc = /^(.*?):[ \t]*([^\r\n]*)\r?$/gm, Ec = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, Fc = /^(?:GET|HEAD)$/, Gc = /^\/\//, Hc = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, Ic = {}, Jc = {}, Kc = "*/".concat("*"); try { Ac = location.href } catch (Lc) { Ac = z.createElement("a"), Ac.href = "", Ac = Ac.href } zc = Hc.exec(Ac.toLowerCase()) || []; function Mc(a) { return function (b, c) { "string" != typeof b && (c = b, b = "*"); var d, e = 0, f = b.toLowerCase().match(F) || []; if (n.isFunction(c)) while (d = f[e++]) "+" === d.charAt(0) ? (d = d.slice(1) || "*", (a[d] = a[d] || []).unshift(c)) : (a[d] = a[d] || []).push(c) } } function Nc(a, b, c, d) { var e = {}, f = a === Jc; function g(h) { var i; return e[h] = !0, n.each(a[h] || [], function (a, h) { var j = h(b, c, d); return "string" != typeof j || f || e[j] ? f ? !(i = j) : void 0 : (b.dataTypes.unshift(j), g(j), !1) }), i } return g(b.dataTypes[0]) || !e["*"] && g("*") } function Oc(a, b) { var c, d, e = n.ajaxSettings.flatOptions || {}; for (d in b) void 0 !== b[d] && ((e[d] ? a : c || (c = {}))[d] = b[d]); return c && n.extend(!0, a, c), a } function Pc(a, b, c) { var d, e, f, g, h = a.contents, i = a.dataTypes; while ("*" === i[0]) i.shift(), void 0 === e && (e = a.mimeType || b.getResponseHeader("Content-Type")); if (e) for (g in h) if (h[g] && h[g].test(e)) { i.unshift(g); break } if (i[0] in c) f = i[0]; else { for (g in c) { if (!i[0] || a.converters[g + " " + i[0]]) { f = g; break } d || (d = g) } f = f || d } return f ? (f !== i[0] && i.unshift(f), c[f]) : void 0 } function Qc(a, b, c, d) { var e, f, g, h, i, j = {}, k = a.dataTypes.slice(); if (k[1]) for (g in a.converters) j[g.toLowerCase()] = a.converters[g]; f = k.shift(); while (f) if (a.responseFields[f] && (c[a.responseFields[f]] = b), !i && d && a.dataFilter && (b = a.dataFilter(b, a.dataType)), i = f, f = k.shift()) if ("*" === f) f = i; else if ("*" !== i && i !== f) { if (g = j[i + " " + f] || j["* " + f], !g) for (e in j) if (h = e.split(" "), h[1] === f && (g = j[i + " " + h[0]] || j["* " + h[0]])) { g === !0 ? g = j[e] : j[e] !== !0 && (f = h[0], k.unshift(h[1])); break } if (g !== !0) if (g && a["throws"]) b = g(b); else try { b = g(b) } catch (l) { return {state: "parsererror", error: g ? l : "No conversion from " + i + " to " + f} } } return {state: "success", data: b} } n.extend({ active: 0, lastModified: {}, etag: {}, ajaxSettings: { url: Ac, type: "GET", isLocal: Ec.test(zc[1]), global: !0, processData: !0, async: !0, contentType: "application/x-www-form-urlencoded; charset=UTF-8", accepts: { "*": Kc, text: "text/plain", html: "text/html", xml: "application/xml, text/xml", json: "application/json, text/javascript" }, contents: {xml: /xml/, html: /html/, json: /json/}, responseFields: {xml: "responseXML", text: "responseText", json: "responseJSON"}, converters: {"* text": String, "text html": !0, "text json": n.parseJSON, "text xml": n.parseXML}, flatOptions: {url: !0, context: !0} }, ajaxSetup: function (a, b) { return b ? Oc(Oc(a, n.ajaxSettings), b) : Oc(n.ajaxSettings, a) }, ajaxPrefilter: Mc(Ic), ajaxTransport: Mc(Jc), ajax: function (a, b) { "object" == typeof a && (b = a, a = void 0), b = b || {}; var c, d, e, f, g, h, i, j, k = n.ajaxSetup({}, b), l = k.context || k, m = k.context && (l.nodeType || l.jquery) ? n(l) : n.event, o = n.Deferred(), p = n.Callbacks("once memory"), q = k.statusCode || {}, r = {}, s = {}, t = 0, u = "canceled", v = { readyState: 0, getResponseHeader: function (a) { var b; if (2 === t) { if (!j) { j = {}; while (b = Dc.exec(f)) j[b[1].toLowerCase()] = b[2] } b = j[a.toLowerCase()] } return null == b ? null : b }, getAllResponseHeaders: function () { return 2 === t ? f : null }, setRequestHeader: function (a, b) { var c = a.toLowerCase(); return t || (a = s[c] = s[c] || a, r[a] = b), this }, overrideMimeType: function (a) { return t || (k.mimeType = a), this }, statusCode: function (a) { var b; if (a) if (2 > t) for (b in a) q[b] = [q[b], a[b]]; else v.always(a[v.status]); return this }, abort: function (a) { var b = a || u; return i && i.abort(b), x(0, b), this } }; if (o.promise(v).complete = p.add, v.success = v.done, v.error = v.fail, k.url = ((a || k.url || Ac) + "").replace(Bc, "").replace(Gc, zc[1] + "//"), k.type = b.method || b.type || k.method || k.type, k.dataTypes = n.trim(k.dataType || "*").toLowerCase().match(F) || [""], null == k.crossDomain && (c = Hc.exec(k.url.toLowerCase()), k.crossDomain = !(!c || c[1] === zc[1] && c[2] === zc[2] && (c[3] || ("http:" === c[1] ? "80" : "443")) === (zc[3] || ("http:" === zc[1] ? "80" : "443")))), k.data && k.processData && "string" != typeof k.data && (k.data = n.param(k.data, k.traditional)), Nc(Ic, k, b, v), 2 === t) return v; h = k.global, h && 0 === n.active++ && n.event.trigger("ajaxStart"), k.type = k.type.toUpperCase(), k.hasContent = !Fc.test(k.type), e = k.url, k.hasContent || (k.data && (e = k.url += (xc.test(e) ? "&" : "?") + k.data, delete k.data), k.cache === !1 && (k.url = Cc.test(e) ? e.replace(Cc, "$1_=" + wc++) : e + (xc.test(e) ? "&" : "?") + "_=" + wc++)), k.ifModified && (n.lastModified[e] && v.setRequestHeader("If-Modified-Since", n.lastModified[e]), n.etag[e] && v.setRequestHeader("If-None-Match", n.etag[e])), (k.data && k.hasContent && k.contentType !== !1 || b.contentType) && v.setRequestHeader("Content-Type", k.contentType), v.setRequestHeader("Accept", k.dataTypes[0] && k.accepts[k.dataTypes[0]] ? k.accepts[k.dataTypes[0]] + ("*" !== k.dataTypes[0] ? ", " + Kc + "; q=0.01" : "") : k.accepts["*"]); for (d in k.headers) v.setRequestHeader(d, k.headers[d]); if (k.beforeSend && (k.beforeSend.call(l, v, k) === !1 || 2 === t)) return v.abort(); u = "abort"; for (d in{success: 1, error: 1, complete: 1}) v[d](k[d]); if (i = Nc(Jc, k, b, v)) { v.readyState = 1, h && m.trigger("ajaxSend", [v, k]), k.async && k.timeout > 0 && (g = setTimeout(function () { v.abort("timeout") }, k.timeout)); try { t = 1, i.send(r, x) } catch { if (!(2 > t)) throw w; x(-1, w) } } else x(-1, "No Transport"); function x(a, b, c, d) { var j, r, s, u, w, x = b; 2 !== t && (t = 2, g && clearTimeout(g), i = void 0, f = d || "", v.readyState = a > 0 ? 4 : 0, j = a >= 200 && 300 > a || 304 === a, c && (u = Pc(k, v, c)), u = Qc(k, u, v, j), j ? (k.ifModified && (w = v.getResponseHeader("Last-Modified"), w && (n.lastModified[e] = w), w = v.getResponseHeader("etag"), w && (n.etag[e] = w)), 204 === a || "HEAD" === k.type ? x = "nocontent" : 304 === a ? x = "notmodified" : (x = u.state, r = u.data, s = u.error, j = !s)) : (s = x, (a || !x) && (x = "error", 0 > a && (a = 0))), v.status = a, v.statusText = (b || x) + "", j ? o.resolveWith(l, [r, x, v]) : o.rejectWith(l, [v, x, s]), v.statusCode(q), q = void 0, h && m.trigger(j ? "ajaxSuccess" : "ajaxError", [v, k, j ? r : s]), p.fireWith(l, [v, x]), h && (m.trigger("ajaxComplete", [v, k]), --n.active || n.event.trigger("ajaxStop"))) } return v }, getJSON: function (a, b, c) { return n.get(a, b, c, "json") }, getScript: function (a, b) { return n.get(a, void 0, b, "script") } }), n.each(["get", "post"], function (a, b) { n[b] = function (a, c, d, e) { return n.isFunction(c) && (e = e || d, d = c, c = void 0), n.ajax({ url: a, type: b, dataType: e, data: c, success: d }) } }), n.each(["ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend"], function (a, b) { n.fn[b] = function (a) { return this.on(b, a) } }), n._evalUrl = function (a) { return n.ajax({url: a, type: "GET", dataType: "script", async: !1, global: !1, "throws": !0}) }, n.fn.extend({ wrapAll: function (a) { if (n.isFunction(a)) return this.each(function (b) { n(this).wrapAll(a.call(this, b)) }); if (this[0]) { var b = n(a, this[0].ownerDocument).eq(0).clone(!0); this[0].parentNode && b.insertBefore(this[0]), b.map(function () { var a = this; while (a.firstChild && 1 === a.firstChild.nodeType) a = a.firstChild; return a }).append(this) } return this }, wrapInner: function (a) { return this.each(n.isFunction(a) ? function (b) { n(this).wrapInner(a.call(this, b)) } : function () { var b = n(this), c = b.contents(); c.length ? c.wrapAll(a) : b.append(a) }) }, wrap: function (a) { var b = n.isFunction(a); return this.each(function (c) { n(this).wrapAll(b ? a.call(this, c) : a) }) }, unwrap: function () { return this.parent().each(function () { n.nodeName(this, "body") || n(this).replaceWith(this.childNodes) }).end() } }), n.expr.filters.hidden = function (a) { return a.offsetWidth <= 0 && a.offsetHeight <= 0 || !l.reliableHiddenOffsets() && "none" === (a.style && a.style.display || n.css(a, "display")) }, n.expr.filters.visible = function (a) { return !n.expr.filters.hidden(a) }; var Rc = /%20/g, Sc = /\[\]$/, Tc = /\r?\n/g, Uc = /^(?:submit|button|image|reset|file)$/i, Vc = /^(?:input|select|textarea|keygen)/i; function Wc(a, b, c, d) { var e; if (n.isArray(b)) n.each(b, function (b, e) { c || Sc.test(a) ? d(a, e) : Wc(a + "[" + ("object" == typeof e ? b : "") + "]", e, c, d) }); else if (c || "object" !== n.type(b)) d(a, b); else for (e in b) Wc(a + "[" + e + "]", b[e], c, d) } n.param = function (a, b) { var c, d = [], e = function (a, b) { b = n.isFunction(b) ? b() : null == b ? "" : b, d[d.length] = encodeURIComponent(a) + "=" + encodeURIComponent(b) }; if (void 0 === b && (b = n.ajaxSettings && n.ajaxSettings.traditional), n.isArray(a) || a.jquery && !n.isPlainObject(a)) n.each(a, function () { e(this.name, this.value) }); else for (c in a) Wc(c, a[c], b, e); return d.join("&").replace(Rc, "+") }, n.fn.extend({ serialize: function () { return n.param(this.serializeArray()) }, serializeArray: function () { return this.map(function () { var a = n.prop(this, "elements"); return a ? n.makeArray(a) : this }).filter(function () { var a = this.type; return this.name && !n(this).is(":disabled") && Vc.test(this.nodeName) && !Uc.test(a) && (this.checked || !X.test(a)) }).map(function (a, b) { var c = n(this).val(); return null == c ? null : n.isArray(c) ? n.map(c, function (a) { return {name: b.name, value: a.replace(Tc, "\r\n")} }) : {name: b.name, value: c.replace(Tc, "\r\n")} }).get() } }), n.ajaxSettings.xhr = void 0 !== a.ActiveXObject ? function () { return !this.isLocal && /^(get|post|head|put|delete|options)$/i.test(this.type) && $c() || _c() } : $c; var Xc = 0, Yc = {}, Zc = n.ajaxSettings.xhr(); a.ActiveXObject && n(a).on("unload", function () { for (var a in Yc) Yc[a](void 0, !0) }), l.cors = !!Zc && "withCredentials" in Zc, Zc = l.ajax = !!Zc, Zc && n.ajaxTransport(function (a) { if (!a.crossDomain || l.cors) { var b; return { send: function (c, d) { var e, f = a.xhr(), g = ++Xc; if (f.open(a.type, a.url, a.async, a.username, a.password), a.xhrFields) for (e in a.xhrFields) f[e] = a.xhrFields[e]; a.mimeType && f.overrideMimeType && f.overrideMimeType(a.mimeType), a.crossDomain || c["X-Requested-With"] || (c["X-Requested-With"] = "XMLHttpRequest"); for (e in c) void 0 !== c[e] && f.setRequestHeader(e, c[e] + ""); f.send(a.hasContent && a.data || null), b = function (c, e) { var h, i, j; if (b && (e || 4 === f.readyState)) if (delete Yc[g], b = void 0, f.onreadystatechange = n.noop, e) 4 !== f.readyState && f.abort(); else { j = {}, h = f.status, "string" == typeof f.responseText && (j.text = f.responseText); try { i = f.statusText } catch (k) { i = "" } h || !a.isLocal || a.crossDomain ? 1223 === h && (h = 204) : h = j.text ? 200 : 404 } j && d(h, i, j, f.getAllResponseHeaders()) }, a.async ? 4 === f.readyState ? setTimeout(b) : f.onreadystatechange = Yc[g] = b : b() }, abort: function () { b && b(void 0, !0) } } } }); function $c() { try { return new a.XMLHttpRequest } catch (b) { } } function _c() { try { return new a.ActiveXObject("Microsoft.XMLHTTP") } catch (b) { } } n.ajaxSetup({ accepts: {script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"}, contents: {script: /(?:java|ecma)script/}, converters: { "text script": function (a) { return n.globalEval(a), a } } }), n.ajaxPrefilter("script", function (a) { void 0 === a.cache && (a.cache = !1), a.crossDomain && (a.type = "GET", a.global = !1) }), n.ajaxTransport("script", function (a) { if (a.crossDomain) { var b, c = z.head || n("head")[0] || z.documentElement; return { send: function (d, e) { b = z.createElement("script"), b.async = !0, a.scriptCharset && (b.charset = a.scriptCharset), b.src = a.url, b.onload = b.onreadystatechange = function (a, c) { (c || !b.readyState || /loaded|complete/.test(b.readyState)) && (b.onload = b.onreadystatechange = null, b.parentNode && b.parentNode.removeChild(b), b = null, c || e(200, "success")) }, c.insertBefore(b, c.firstChild) }, abort: function () { b && b.onload(void 0, !0) } } } }); var ad = [], bd = /(=)\?(?=&|$)|\?\?/; n.ajaxSetup({ jsonp: "callback", jsonpCallback: function () { var a = ad.pop() || n.expando + "_" + wc++; return this[a] = !0, a } }), n.ajaxPrefilter("json jsonp", function (b, c, d) { var e, f, g, h = b.jsonp !== !1 && (bd.test(b.url) ? "url" : "string" == typeof b.data && !(b.contentType || "").indexOf("application/x-www-form-urlencoded") && bd.test(b.data) && "data"); return h || "jsonp" === b.dataTypes[0] ? (e = b.jsonpCallback = n.isFunction(b.jsonpCallback) ? b.jsonpCallback() : b.jsonpCallback, h ? b[h] = b[h].replace(bd, "$1" + e) : b.jsonp !== !1 && (b.url += (xc.test(b.url) ? "&" : "?") + b.jsonp + "=" + e), b.converters["script json"] = function () { return g || n.error(e + " was not called"), g[0] }, b.dataTypes[0] = "json", f = a[e], a[e] = function () { g = arguments }, d.always(function () { a[e] = f, b[e] && (b.jsonpCallback = c.jsonpCallback, ad.push(e)), g && n.isFunction(f) && f(g[0]), g = f = void 0 }), "script") : void 0 }), n.parseHTML = function (a, b, c) { if (!a || "string" != typeof a) return null; "boolean" == typeof b && (c = b, b = !1), b = b || z; var d = v.exec(a), e = !c && []; return d ? [b.createElement(d[1])] : (d = n.buildFragment([a], b, e), e && e.length && n(e).remove(), n.merge([], d.childNodes)) }; var cd = n.fn.load; n.fn.load = function (a, b, c) { if ("string" != typeof a && cd) return cd.apply(this, arguments); var d, e, f, g = this, h = a.indexOf(" "); return h >= 0 && (d = a.slice(h, a.length), a = a.slice(0, h)), n.isFunction(b) ? (c = b, b = void 0) : b && "object" == typeof b && (f = "POST"), g.length > 0 && n.ajax({ url: a, type: f, dataType: "html", data: b }).done(function (a) { e = arguments, g.html(d ? n("<div>").append(n.parseHTML(a)).find(d) : a) }).complete(c && function (a, b) { g.each(c, e || [a.responseText, b, a]) }), this }, n.expr.filters.animated = function (a) { return n.grep(n.timers, function (b) { return a === b.elem }).length }; var dd = a.document.documentElement; function ed(a) { return n.isWindow(a) ? a : 9 === a.nodeType ? a.defaultView || a.parentWindow : !1 } n.offset = { setOffset: function (a, b, c) { var d, e, f, g, h, i, j, k = n.css(a, "position"), l = n(a), m = {}; "static" === k && (a.style.position = "relative"), h = l.offset(), f = n.css(a, "top"), i = n.css(a, "left"), j = ("absolute" === k || "fixed" === k) && n.inArray("auto", [f, i]) > -1, j ? (d = l.position(), g = d.top, e = d.left) : (g = parseFloat(f) || 0, e = parseFloat(i) || 0), n.isFunction(b) && (b = b.call(a, c, h)), null != b.top && (m.top = b.top - h.top + g), null != b.left && (m.left = b.left - h.left + e), "using" in b ? b.using.call(a, m) : l.css(m) } }, n.fn.extend({ offset: function (a) { if (arguments.length) return void 0 === a ? this : this.each(function (b) { n.offset.setOffset(this, a, b) }); var b, c, d = {top: 0, left: 0}, e = this[0], f = e && e.ownerDocument; if (f) return b = f.documentElement, n.contains(b, e) ? (typeof e.getBoundingClientRect !== L && (d = e.getBoundingClientRect()), c = ed(f), { top: d.top + (c.pageYOffset || b.scrollTop) - (b.clientTop || 0), left: d.left + (c.pageXOffset || b.scrollLeft) - (b.clientLeft || 0) }) : d }, position: function () { if (this[0]) { var a, b, c = {top: 0, left: 0}, d = this[0]; return "fixed" === n.css(d, "position") ? b = d.getBoundingClientRect() : (a = this.offsetParent(), b = this.offset(), n.nodeName(a[0], "html") || (c = a.offset()), c.top += n.css(a[0], "borderTopWidth", !0), c.left += n.css(a[0], "borderLeftWidth", !0)), { top: b.top - c.top - n.css(d, "marginTop", !0), left: b.left - c.left - n.css(d, "marginLeft", !0) } } }, offsetParent: function () { return this.map(function () { var a = this.offsetParent || dd; while (a && !n.nodeName(a, "html") && "static" === n.css(a, "position")) a = a.offsetParent; return a || dd }) } }), n.each({scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function (a, b) { var c = /Y/.test(b); n.fn[a] = function (d) { return W(this, function (a, d, e) { var f = ed(a); return void 0 === e ? f ? b in f ? f[b] : f.document.documentElement[d] : a[d] : void(f ? f.scrollTo(c ? n(f).scrollLeft() : e, c ? e : n(f).scrollTop()) : a[d] = e) }, a, d, arguments.length, null) } }), n.each(["top", "left"], function (a, b) { n.cssHooks[b] = Mb(l.pixelPosition, function (a, c) { return c ? (c = Kb(a, b), Ib.test(c) ? n(a).position()[b] + "px" : c) : void 0 }) }), n.each({Height: "height", Width: "width"}, function (a, b) { n.each({padding: "inner" + a, content: b, "": "outer" + a}, function (c, d) { n.fn[d] = function (d, e) { var f = arguments.length && (c || "boolean" != typeof d), g = c || (d === !0 || e === !0 ? "margin" : "border"); return W(this, function (b, c, d) { var e; return n.isWindow(b) ? b.document.documentElement["client" + a] : 9 === b.nodeType ? (e = b.documentElement, Math.max(b.body["scroll" + a], e["scroll" + a], b.body["offset" + a], e["offset" + a], e["client" + a])) : void 0 === d ? n.css(b, c, g) : n.style(b, c, d, g) }, b, f ? d : void 0, f, null) } }) }), n.fn.size = function () { return this.length }, n.fn.andSelf = n.fn.addBack, "function" == typeof define && define.amd && define("jquery", [], function () { return n }); var fd = a.jQuery, gd = a.$; return n.noConflict = function (b) { return a.$ === n && (a.$ = gd), b && a.jQuery === n && (a.jQuery = fd), n }, typeof b === L && (a.jQuery = a.$ = n), n }); </script> <!-- Underscore + Knockout --> <script type="text/javascript">// Underscore.js 1.8.3 // http://underscorejs.org // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Underscore may be freely distributed under the MIT license. (function () { function n(n) { function t(t, r, e, u, i, o) { for (; i >= 0 && o > i; i += n) { var a = u ? u[i] : i; e = r(e, t[a], a, t) } return e } return function (r, e, u, i) { e = b(e, i, 4); var o = !k(r) && m.keys(r), a = (o || r).length, c = n > 0 ? 0 : a - 1; return arguments.length < 3 && (u = r[o ? o[c] : c], c += n), t(r, e, u, o, c, a) } } function t(n) { return function (t, r, e) { r = x(r, e); for (var u = O(t), i = n > 0 ? 0 : u - 1; i >= 0 && u > i; i += n) if (r(t[i], i, t)) return i; return -1 } } function r(n, t, r) { return function (e, u, i) { var o = 0, a = O(e); if ("number" == typeof i) n > 0 ? o = i >= 0 ? i : Math.max(i + a, o) : a = i >= 0 ? Math.min(i + 1, a) : i + a + 1; else if (r && i && a) return i = r(e, u), e[i] === u ? i : -1; if (u !== u) return i = t(l.call(e, o, a), m.isNaN), i >= 0 ? i + o : -1; for (i = n > 0 ? o : a - 1; i >= 0 && a > i; i += n) if (e[i] === u) return i; return -1 } } function e(n, t) { var r = I.length, e = n.constructor, u = m.isFunction(e) && e.prototype || a, i = "constructor"; for (m.has(n, i) && !m.contains(t, i) && t.push(i); r--;) i = I[r], i in n && n[i] !== u[i] && !m.contains(t, i) && t.push(i) } var u = this, i = u._, o = Array.prototype, a = Object.prototype, c = Function.prototype, f = o.push, l = o.slice, s = a.toString, p = a.hasOwnProperty, h = Array.isArray, v = Object.keys, g = c.bind, y = Object.create, d = function () { }, m = function (n) { return n instanceof m ? n : this instanceof m ? void(this._wrapped = n) : new m(n) }; "undefined" != typeof exports ? ("undefined" != typeof module && module.exports && (exports = module.exports = m), exports._ = m) : u._ = m, m.VERSION = "1.8.3"; var b = function (n, t, r) { if (t === void 0) return n; switch (null == r ? 3 : r) { case 1: return function (r) { return n.call(t, r) }; case 2: return function (r, e) { return n.call(t, r, e) }; case 3: return function (r, e, u) { return n.call(t, r, e, u) }; case 4: return function (r, e, u, i) { return n.call(t, r, e, u, i) } } return function () { return n.apply(t, arguments) } }, x = function (n, t, r) { return null == n ? m.identity : m.isFunction(n) ? b(n, t, r) : m.isObject(n) ? m.matcher(n) : m.property(n) }; m.iteratee = function (n, t) { return x(n, t, 1 / 0) }; var _ = function (n, t) { return function (r) { var e = arguments.length; if (2 > e || null == r) return r; for (var u = 1; e > u; u++) for (var i = arguments[u], o = n(i), a = o.length, c = 0; a > c; c++) { var f = o[c]; t && r[f] !== void 0 || (r[f] = i[f]) } return r } }, j = function (n) { if (!m.isObject(n)) return {}; if (y) return y(n); d.prototype = n; var t = new d; return d.prototype = null, t }, w = function (n) { return function (t) { return null == t ? void 0 : t[n] } }, A = Math.pow(2, 53) - 1, O = w("length"), k = function (n) { var t = O(n); return "number" == typeof t && t >= 0 && A >= t }; m.each = m.forEach = function (n, t, r) { t = b(t, r); var e, u; if (k(n)) for (e = 0, u = n.length; u > e; e++) t(n[e], e, n); else { var i = m.keys(n); for (e = 0, u = i.length; u > e; e++) t(n[i[e]], i[e], n) } return n }, m.map = m.collect = function (n, t, r) { t = x(t, r); for (var e = !k(n) && m.keys(n), u = (e || n).length, i = Array(u), o = 0; u > o; o++) { var a = e ? e[o] : o; i[o] = t(n[a], a, n) } return i }, m.reduce = m.foldl = m.inject = n(1), m.reduceRight = m.foldr = n(-1), m.find = m.detect = function (n, t, r) { var e; return e = k(n) ? m.findIndex(n, t, r) : m.findKey(n, t, r), e !== void 0 && e !== -1 ? n[e] : void 0 }, m.filter = m.select = function (n, t, r) { var e = []; return t = x(t, r), m.each(n, function (n, r, u) { t(n, r, u) && e.push(n) }), e }, m.reject = function (n, t, r) { return m.filter(n, m.negate(x(t)), r) }, m.every = m.all = function (n, t, r) { t = x(t, r); for (var e = !k(n) && m.keys(n), u = (e || n).length, i = 0; u > i; i++) { var o = e ? e[i] : i; if (!t(n[o], o, n)) return !1 } return !0 }, m.some = m.any = function (n, t, r) { t = x(t, r); for (var e = !k(n) && m.keys(n), u = (e || n).length, i = 0; u > i; i++) { var o = e ? e[i] : i; if (t(n[o], o, n)) return !0 } return !1 }, m.contains = m.includes = m.include = function (n, t, r, e) { return k(n) || (n = m.values(n)), ("number" != typeof r || e) && (r = 0), m.indexOf(n, t, r) >= 0 }, m.invoke = function (n, t) { var r = l.call(arguments, 2), e = m.isFunction(t); return m.map(n, function (n) { var u = e ? t : n[t]; return null == u ? u : u.apply(n, r) }) }, m.pluck = function (n, t) { return m.map(n, m.property(t)) }, m.where = function (n, t) { return m.filter(n, m.matcher(t)) }, m.findWhere = function (n, t) { return m.find(n, m.matcher(t)) }, m.max = function (n, t, r) { var e, u, i = -1 / 0, o = -1 / 0; if (null == t && null != n) { n = k(n) ? n : m.values(n); for (var a = 0, c = n.length; c > a; a++) e = n[a], e > i && (i = e) } else t = x(t, r), m.each(n, function (n, r, e) { u = t(n, r, e), (u > o || u === -1 / 0 && i === -1 / 0) && (i = n, o = u) }); return i }, m.min = function (n, t, r) { var e, u, i = 1 / 0, o = 1 / 0; if (null == t && null != n) { n = k(n) ? n : m.values(n); for (var a = 0, c = n.length; c > a; a++) e = n[a], i > e && (i = e) } else t = x(t, r), m.each(n, function (n, r, e) { u = t(n, r, e), (o > u || 1 / 0 === u && 1 / 0 === i) && (i = n, o = u) }); return i }, m.shuffle = function (n) { for (var t, r = k(n) ? n : m.values(n), e = r.length, u = Array(e), i = 0; e > i; i++) t = m.random(0, i), t !== i && (u[i] = u[t]), u[t] = r[i]; return u }, m.sample = function (n, t, r) { return null == t || r ? (k(n) || (n = m.values(n)), n[m.random(n.length - 1)]) : m.shuffle(n).slice(0, Math.max(0, t)) }, m.sortBy = function (n, t, r) { return t = x(t, r), m.pluck(m.map(n, function (n, r, e) { return {value: n, index: r, criteria: t(n, r, e)} }).sort(function (n, t) { var r = n.criteria, e = t.criteria; if (r !== e) { if (r > e || r === void 0) return 1; if (e > r || e === void 0) return -1 } return n.index - t.index }), "value") }; var F = function (n) { return function (t, r, e) { var u = {}; return r = x(r, e), m.each(t, function (e, i) { var o = r(e, i, t); n(u, e, o) }), u } }; m.groupBy = F(function (n, t, r) { m.has(n, r) ? n[r].push(t) : n[r] = [t] }), m.indexBy = F(function (n, t, r) { n[r] = t }), m.countBy = F(function (n, t, r) { m.has(n, r) ? n[r]++ : n[r] = 1 }), m.toArray = function (n) { return n ? m.isArray(n) ? l.call(n) : k(n) ? m.map(n, m.identity) : m.values(n) : [] }, m.size = function (n) { return null == n ? 0 : k(n) ? n.length : m.keys(n).length }, m.partition = function (n, t, r) { t = x(t, r); var e = [], u = []; return m.each(n, function (n, r, i) { (t(n, r, i) ? e : u).push(n) }), [e, u] }, m.first = m.head = m.take = function (n, t, r) { return null == n ? void 0 : null == t || r ? n[0] : m.initial(n, n.length - t) }, m.initial = function (n, t, r) { return l.call(n, 0, Math.max(0, n.length - (null == t || r ? 1 : t))) }, m.last = function (n, t, r) { return null == n ? void 0 : null == t || r ? n[n.length - 1] : m.rest(n, Math.max(0, n.length - t)) }, m.rest = m.tail = m.drop = function (n, t, r) { return l.call(n, null == t || r ? 1 : t) }, m.compact = function (n) { return m.filter(n, m.identity) }; var S = function (n, t, r, e) { for (var u = [], i = 0, o = e || 0, a = O(n); a > o; o++) { var c = n[o]; if (k(c) && (m.isArray(c) || m.isArguments(c))) { t || (c = S(c, t, r)); var f = 0, l = c.length; for (u.length += l; l > f;) u[i++] = c[f++] } else r || (u[i++] = c) } return u }; m.flatten = function (n, t) { return S(n, t, !1) }, m.without = function (n) { return m.difference(n, l.call(arguments, 1)) }, m.uniq = m.unique = function (n, t, r, e) { m.isBoolean(t) || (e = r, r = t, t = !1), null != r && (r = x(r, e)); for (var u = [], i = [], o = 0, a = O(n); a > o; o++) { var c = n[o], f = r ? r(c, o, n) : c; t ? (o && i === f || u.push(c), i = f) : r ? m.contains(i, f) || (i.push(f), u.push(c)) : m.contains(u, c) || u.push(c) } return u }, m.union = function () { return m.uniq(S(arguments, !0, !0)) }, m.intersection = function (n) { for (var t = [], r = arguments.length, e = 0, u = O(n); u > e; e++) { var i = n[e]; if (!m.contains(t, i)) { for (var o = 1; r > o && m.contains(arguments[o], i); o++) ; o === r && t.push(i) } } return t }, m.difference = function (n) { var t = S(arguments, !0, !0, 1); return m.filter(n, function (n) { return !m.contains(t, n) }) }, m.zip = function () { return m.unzip(arguments) }, m.unzip = function (n) { for (var t = n && m.max(n, O).length || 0, r = Array(t), e = 0; t > e; e++) r[e] = m.pluck(n, e); return r }, m.object = function (n, t) { for (var r = {}, e = 0, u = O(n); u > e; e++) t ? r[n[e]] = t[e] : r[n[e][0]] = n[e][1]; return r }, m.findIndex = t(1), m.findLastIndex = t(-1), m.sortedIndex = function (n, t, r, e) { r = x(r, e, 1); for (var u = r(t), i = 0, o = O(n); o > i;) { var a = Math.floor((i + o) / 2); r(n[a]) < u ? i = a + 1 : o = a } return i }, m.indexOf = r(1, m.findIndex, m.sortedIndex), m.lastIndexOf = r(-1, m.findLastIndex), m.range = function (n, t, r) { null == t && (t = n || 0, n = 0), r = r || 1; for (var e = Math.max(Math.ceil((t - n) / r), 0), u = Array(e), i = 0; e > i; i++, n += r) u[i] = n; return u }; var E = function (n, t, r, e, u) { if (!(e instanceof t)) return n.apply(r, u); var i = j(n.prototype), o = n.apply(i, u); return m.isObject(o) ? o : i }; m.bind = function (n, t) { if (g && n.bind === g) return g.apply(n, l.call(arguments, 1)); if (!m.isFunction(n)) throw new TypeError("Bind must be called on a function"); var r = l.call(arguments, 2), e = function () { return E(n, e, t, this, r.concat(l.call(arguments))) }; return e }, m.partial = function (n) { var t = l.call(arguments, 1), r = function () { for (var e = 0, u = t.length, i = Array(u), o = 0; u > o; o++) i[o] = t[o] === m ? arguments[e++] : t[o]; for (; e < arguments.length;) i.push(arguments[e++]); return E(n, r, this, this, i) }; return r }, m.bindAll = function (n) { var t, r, e = arguments.length; if (1 >= e) throw new Error("bindAll must be passed function names"); for (t = 1; e > t; t++) r = arguments[t], n[r] = m.bind(n[r], n); return n }, m.memoize = function (n, t) { var r = function (e) { var u = r.cache, i = "" + (t ? t.apply(this, arguments) : e); return m.has(u, i) || (u[i] = n.apply(this, arguments)), u[i] }; return r.cache = {}, r }, m.delay = function (n, t) { var r = l.call(arguments, 2); return setTimeout(function () { return n.apply(null, r) }, t) }, m.defer = m.partial(m.delay, m, 1), m.throttle = function (n, t, r) { var e, u, i, o = null, a = 0; r || (r = {}); var c = function () { a = r.leading === !1 ? 0 : m.now(), o = null, i = n.apply(e, u), o || (e = u = null) }; return function () { var f = m.now(); a || r.leading !== !1 || (a = f); var l = t - (f - a); return e = this, u = arguments, 0 >= l || l > t ? (o && (clearTimeout(o), o = null), a = f, i = n.apply(e, u), o || (e = u = null)) : o || r.trailing === !1 || (o = setTimeout(c, l)), i } }, m.debounce = function (n, t, r) { var e, u, i, o, a, c = function () { var f = m.now() - o; t > f && f >= 0 ? e = setTimeout(c, t - f) : (e = null, r || (a = n.apply(i, u), e || (i = u = null))) }; return function () { i = this, u = arguments, o = m.now(); var f = r && !e; return e || (e = setTimeout(c, t)), f && (a = n.apply(i, u), i = u = null), a } }, m.wrap = function (n, t) { return m.partial(t, n) }, m.negate = function (n) { return function () { return !n.apply(this, arguments) } }, m.compose = function () { var n = arguments, t = n.length - 1; return function () { for (var r = t, e = n[t].apply(this, arguments); r--;) e = n[r].call(this, e); return e } }, m.after = function (n, t) { return function () { return --n < 1 ? t.apply(this, arguments) : void 0 } }, m.before = function (n, t) { var r; return function () { return --n > 0 && (r = t.apply(this, arguments)), 1 >= n && (t = null), r } }, m.once = m.partial(m.before, 2); var M = !{toString: null}.propertyIsEnumerable("toString"), I = ["valueOf", "isPrototypeOf", "toString", "propertyIsEnumerable", "hasOwnProperty", "toLocaleString"]; m.keys = function (n) { if (!m.isObject(n)) return []; if (v) return v(n); var t = []; for (var r in n) m.has(n, r) && t.push(r); return M && e(n, t), t }, m.allKeys = function (n) { if (!m.isObject(n)) return []; var t = []; for (var r in n) t.push(r); return M && e(n, t), t }, m.values = function (n) { for (var t = m.keys(n), r = t.length, e = Array(r), u = 0; r > u; u++) e[u] = n[t[u]]; return e }, m.mapObject = function (n, t, r) { t = x(t, r); for (var e, u = m.keys(n), i = u.length, o = {}, a = 0; i > a; a++) e = u[a], o[e] = t(n[e], e, n); return o }, m.pairs = function (n) { for (var t = m.keys(n), r = t.length, e = Array(r), u = 0; r > u; u++) e[u] = [t[u], n[t[u]]]; return e }, m.invert = function (n) { for (var t = {}, r = m.keys(n), e = 0, u = r.length; u > e; e++) t[n[r[e]]] = r[e]; return t }, m.functions = m.methods = function (n) { var t = []; for (var r in n) m.isFunction(n[r]) && t.push(r); return t.sort() }, m.extend = _(m.allKeys), m.extendOwn = m.assign = _(m.keys), m.findKey = function (n, t, r) { t = x(t, r); for (var e, u = m.keys(n), i = 0, o = u.length; o > i; i++) if (e = u[i], t(n[e], e, n)) return e }, m.pick = function (n, t, r) { var e, u, i = {}, o = n; if (null == o) return i; m.isFunction(t) ? (u = m.allKeys(o), e = b(t, r)) : (u = S(arguments, !1, !1, 1), e = function (n, t, r) { return t in r }, o = Object(o)); for (var a = 0, c = u.length; c > a; a++) { var f = u[a], l = o[f]; e(l, f, o) && (i[f] = l) } return i }, m.omit = function (n, t, r) { if (m.isFunction(t)) t = m.negate(t); else { var e = m.map(S(arguments, !1, !1, 1), String); t = function (n, t) { return !m.contains(e, t) } } return m.pick(n, t, r) }, m.defaults = _(m.allKeys, !0), m.create = function (n, t) { var r = j(n); return t && m.extendOwn(r, t), r }, m.clone = function (n) { return m.isObject(n) ? m.isArray(n) ? n.slice() : m.extend({}, n) : n }, m.tap = function (n, t) { return t(n), n }, m.isMatch = function (n, t) { var r = m.keys(t), e = r.length; if (null == n) return !e; for (var u = Object(n), i = 0; e > i; i++) { var o = r[i]; if (t[o] !== u[o] || !(o in u)) return !1 } return !0 }; var N = function (n, t, r, e) { if (n === t) return 0 !== n || 1 / n === 1 / t; if (null == n || null == t) return n === t; n instanceof m && (n = n._wrapped), t instanceof m && (t = t._wrapped); var u = s.call(n); if (u !== s.call(t)) return !1; switch (u) { case"[object RegExp]": case"[object String]": return "" + n == "" + t; case"[object Number]": return +n !== +n ? +t !== +t : 0 === +n ? 1 / +n === 1 / t : +n === +t; case"[object Date]": case"[object Boolean]": return +n === +t } var i = "[object Array]" === u; if (!i) { if ("object" != typeof n || "object" != typeof t) return !1; var o = n.constructor, a = t.constructor; if (o !== a && !(m.isFunction(o) && o instanceof o && m.isFunction(a) && a instanceof a) && "constructor" in n && "constructor" in t) return !1 } r = r || [], e = e || []; for (var c = r.length; c--;) if (r[c] === n) return e[c] === t; if (r.push(n), e.push(t), i) { if (c = n.length, c !== t.length) return !1; for (; c--;) if (!N(n[c], t[c], r, e)) return !1 } else { var f, l = m.keys(n); if (c = l.length, m.keys(t).length !== c) return !1; for (; c--;) if (f = l[c], !m.has(t, f) || !N(n[f], t[f], r, e)) return !1 } return r.pop(), e.pop(), !0 }; m.isEqual = function (n, t) { return N(n, t) }, m.isEmpty = function (n) { return null == n ? !0 : k(n) && (m.isArray(n) || m.isString(n) || m.isArguments(n)) ? 0 === n.length : 0 === m.keys(n).length }, m.isElement = function (n) { return !(!n || 1 !== n.nodeType) }, m.isArray = h || function (n) { return "[object Array]" === s.call(n) }, m.isObject = function (n) { var t = typeof n; return "function" === t || "object" === t && !!n }, m.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function (n) { m["is" + n] = function (t) { return s.call(t) === "[object " + n + "]" } }), m.isArguments(arguments) || (m.isArguments = function (n) { return m.has(n, "callee") }), "function" != typeof/./ && "object" != typeof Int8Array && (m.isFunction = function (n) { return "function" == typeof n || !1 }), m.isFinite = function (n) { return isFinite(n) && !isNaN(parseFloat(n)) }, m.isNaN = function (n) { return m.isNumber(n) && n !== +n }, m.isBoolean = function (n) { return n === !0 || n === !1 || "[object Boolean]" === s.call(n) }, m.isNull = function (n) { return null === n }, m.isUndefined = function (n) { return n === void 0 }, m.has = function (n, t) { return null != n && p.call(n, t) }, m.noConflict = function () { return u._ = i, this }, m.identity = function (n) { return n }, m.constant = function (n) { return function () { return n } }, m.noop = function () { }, m.property = w, m.propertyOf = function (n) { return null == n ? function () { } : function (t) { return n[t] } }, m.matcher = m.matches = function (n) { return n = m.extendOwn({}, n), function (t) { return m.isMatch(t, n) } }, m.times = function (n, t, r) { var e = Array(Math.max(0, n)); t = b(t, r, 1); for (var u = 0; n > u; u++) e[u] = t(u); return e }, m.random = function (n, t) { return null == t && (t = n, n = 0), n + Math.floor(Math.random() * (t - n + 1)) }, m.now = Date.now || function () { return (new Date).getTime() }; var B = {"&": "&", "<": "<", ">": ">", '"': """, "'": "'", "`": "`"}, T = m.invert(B), R = function (n) { var t = function (t) { return n[t] }, r = "(?:" + m.keys(n).join("|") + ")", e = RegExp(r), u = RegExp(r, "g"); return function (n) { return n = null == n ? "" : "" + n, e.test(n) ? n.replace(u, t) : n } }; m.escape = R(B), m.unescape = R(T), m.result = function (n, t, r) { var e = null == n ? void 0 : n[t]; return e === void 0 && (e = r), m.isFunction(e) ? e.call(n) : e }; var q = 0; m.uniqueId = function (n) { var t = ++q + ""; return n ? n + t : t }, m.templateSettings = {evaluate: /<%([\s\S]+?)%>/g, interpolate: /<%=([\s\S]+?)%>/g, escape: /<%-([\s\S]+?)%>/g}; var K = /(.)^/, z = {"'": "'", "\\": "\\", "\r": "r", "\n": "n", "\u2028": "u2028", "\u2029": "u2029"}, D = /\\|'|\r|\n|\u2028|\u2029/g, L = function (n) { return "\\" + z[n] }; m.template = function (n, t, r) { !t && r && (t = r), t = m.defaults({}, t, m.templateSettings); var e = RegExp([(t.escape || K).source, (t.interpolate || K).source, (t.evaluate || K).source].join("|") + "|$", "g"), u = 0, i = "__p+='"; n.replace(e, function (t, r, e, o, a) { return i += n.slice(u, a).replace(D, L), u = a + t.length, r ? i += "'+\n((__t=(" + r + "))==null?'':_.escape(__t))+\n'" : e ? i += "'+\n((__t=(" + e + "))==null?'':__t)+\n'" : o && (i += "';\n" + o + "\n__p+='"), t }), i += "';\n", t.variable || (i = "with(obj||{}){\n" + i + "}\n"), i = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + i + "return __p;\n"; try { var o = new Function(t.variable || "obj", "_", i) } catch (a) { throw a.source = i, a } var c = function (n) { return o.call(this, n, m) }, f = t.variable || "obj"; return c.source = "function(" + f + "){\n" + i + "}", c }, m.chain = function (n) { var t = m(n); return t._chain = !0, t }; var P = function (n, t) { return n._chain ? m(t).chain() : t }; m.mixin = function (n) { m.each(m.functions(n), function (t) { var r = m[t] = n[t]; m.prototype[t] = function () { var n = [this._wrapped]; return f.apply(n, arguments), P(this, r.apply(m, n)) } }) }, m.mixin(m), m.each(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (n) { var t = o[n]; m.prototype[n] = function () { var r = this._wrapped; return t.apply(r, arguments), "shift" !== n && "splice" !== n || 0 !== r.length || delete r[0], P(this, r) } }), m.each(["concat", "join", "slice"], function (n) { var t = o[n]; m.prototype[n] = function () { return P(this, t.apply(this._wrapped, arguments)) } }), m.prototype.value = function () { return this._wrapped }, m.prototype.valueOf = m.prototype.toJSON = m.prototype.value, m.prototype.toString = function () { return "" + this._wrapped }, "function" == typeof define && define.amd && define("underscore", [], function () { return m }) }).call(this); //# sourceMappingURL=underscore-min.map</script> <script type="text/javascript">(function () { var t = this; var e = t.Backbone; var i = []; var r = i.push; var s = i.slice; var n = i.splice; var a; if (typeof exports !== "undefined") { a = exports } else { a = t.Backbone = {} } a.VERSION = "1.1.0"; var h = t._; if (!h && typeof require !== "undefined") h = require("underscore"); a.$ = t.jQuery || t.Zepto || t.ender || t.$; a.noConflict = function () { t.Backbone = e; return this }; a.emulateHTTP = false; a.emulateJSON = false; var o = a.Events = { on: function (t, e, i) { if (!l(this, "on", t, [e, i]) || !e) return this; this._events || (this._events = {}); var r = this._events[t] || (this._events[t] = []); r.push({callback: e, context: i, ctx: i || this}); return this }, once: function (t, e, i) { if (!l(this, "once", t, [e, i]) || !e) return this; var r = this; var s = h.once(function () { r.off(t, s); e.apply(this, arguments) }); s._callback = e; return this.on(t, s, i) }, off: function (t, e, i) { var r, s, n, a, o, u, c, f; if (!this._events || !l(this, "off", t, [e, i])) return this; if (!t && !e && !i) { this._events = {}; return this } a = t ? [t] : h.keys(this._events); for (o = 0, u = a.length; o < u; o++) { t = a[o]; if (n = this._events[t]) { this._events[t] = r = []; if (e || i) { for (c = 0, f = n.length; c < f; c++) { s = n[c]; if (e && e !== s.callback && e !== s.callback._callback || i && i !== s.context) { r.push(s) } } } if (!r.length) delete this._events[t] } } return this }, trigger: function (t) { if (!this._events) return this; var e = s.call(arguments, 1); if (!l(this, "trigger", t, e)) return this; var i = this._events[t]; var r = this._events.all; if (i) c(i, e); if (r) c(r, arguments); return this }, stopListening: function (t, e, i) { var r = this._listeningTo; if (!r) return this; var s = !e && !i; if (!i && typeof e === "object") i = this; if (t) (r = {})[t._listenId] = t; for (var n in r) { t = r[n]; t.off(e, i, this); if (s || h.isEmpty(t._events)) delete this._listeningTo[n] } return this } }; var u = /\s+/; var l = function (t, e, i, r) { if (!i) return true; if (typeof i === "object") { for (var s in i) { t[e].apply(t, [s, i[s]].concat(r)) } return false } if (u.test(i)) { var n = i.split(u); for (var a = 0, h = n.length; a < h; a++) { t[e].apply(t, [n[a]].concat(r)) } return false } return true }; var c = function (t, e) { var i, r = -1, s = t.length, n = e[0], a = e[1], h = e[2]; switch (e.length) { case 0: while (++r < s) (i = t[r]).callback.call(i.ctx); return; case 1: while (++r < s) (i = t[r]).callback.call(i.ctx, n); return; case 2: while (++r < s) (i = t[r]).callback.call(i.ctx, n, a); return; case 3: while (++r < s) (i = t[r]).callback.call(i.ctx, n, a, h); return; default: while (++r < s) (i = t[r]).callback.apply(i.ctx, e) } }; var f = {listenTo: "on", listenToOnce: "once"}; h.each(f, function (t, e) { o[e] = function (e, i, r) { var s = this._listeningTo || (this._listeningTo = {}); var n = e._listenId || (e._listenId = h.uniqueId("l")); s[n] = e; if (!r && typeof i === "object") r = this; e[t](i, r, this); return this } }); o.bind = o.on; o.unbind = o.off; h.extend(a, o); var d = a.Model = function (t, e) { var i = t || {}; e || (e = {}); this.cid = h.uniqueId("c"); this.attributes = {}; if (e.collection) this.collection = e.collection; if (e.parse) i = this.parse(i, e) || {}; i = h.defaults({}, i, h.result(this, "defaults")); this.set(i, e); this.changed = {}; this.initialize.apply(this, arguments) }; h.extend(d.prototype, o, { changed: null, validationError: null, idAttribute: "id", initialize: function () { }, toJSON: function (t) { return h.clone(this.attributes) }, sync: function () { return a.sync.apply(this, arguments) }, get: function (t) { return this.attributes[t] }, escape: function (t) { return h.escape(this.get(t)) }, has: function (t) { return this.get(t) != null }, set: function (t, e, i) { var r, s, n, a, o, u, l, c; if (t == null) return this; if (typeof t === "object") { s = t; i = e } else { (s = {})[t] = e } i || (i = {}); if (!this._validate(s, i)) return false; n = i.unset; o = i.silent; a = []; u = this._changing; this._changing = true; if (!u) { this._previousAttributes = h.clone(this.attributes); this.changed = {} } c = this.attributes, l = this._previousAttributes; if (this.idAttribute in s) this.id = s[this.idAttribute]; for (r in s) { e = s[r]; if (!h.isEqual(c[r], e)) a.push(r); if (!h.isEqual(l[r], e)) { this.changed[r] = e } else { delete this.changed[r] } n ? delete c[r] : c[r] = e } if (!o) { if (a.length) this._pending = true; for (var f = 0, d = a.length; f < d; f++) { this.trigger("change:" + a[f], this, c[a[f]], i) } } if (u) return this; if (!o) { while (this._pending) { this._pending = false; this.trigger("change", this, i) } } this._pending = false; this._changing = false; return this }, unset: function (t, e) { return this.set(t, void 0, h.extend({}, e, {unset: true})) }, clear: function (t) { var e = {}; for (var i in this.attributes) e[i] = void 0; return this.set(e, h.extend({}, t, {unset: true})) }, hasChanged: function (t) { if (t == null) return !h.isEmpty(this.changed); return h.has(this.changed, t) }, changedAttributes: function (t) { if (!t) return this.hasChanged() ? h.clone(this.changed) : false; var e, i = false; var r = this._changing ? this._previousAttributes : this.attributes; for (var s in t) { if (h.isEqual(r[s], e = t[s])) continue; (i || (i = {}))[s] = e } return i }, previous: function (t) { if (t == null || !this._previousAttributes) return null; return this._previousAttributes[t] }, previousAttributes: function () { return h.clone(this._previousAttributes) }, fetch: function (t) { t = t ? h.clone(t) : {}; if (t.parse === void 0) t.parse = true; var e = this; var i = t.success; t.success = function (r) { if (!e.set(e.parse(r, t), t)) return false; if (i) i(e, r, t); e.trigger("sync", e, r, t) }; M(this, t); return this.sync("read", this, t) }, save: function (t, e, i) { var r, s, n, a = this.attributes; if (t == null || typeof t === "object") { r = t; i = e } else { (r = {})[t] = e } i = h.extend({validate: true}, i); if (r && !i.wait) { if (!this.set(r, i)) return false } else { if (!this._validate(r, i)) return false } if (r && i.wait) { this.attributes = h.extend({}, a, r) } if (i.parse === void 0) i.parse = true; var o = this; var u = i.success; i.success = function (t) { o.attributes = a; var e = o.parse(t, i); if (i.wait) e = h.extend(r || {}, e); if (h.isObject(e) && !o.set(e, i)) { return false } if (u) u(o, t, i); o.trigger("sync", o, t, i) }; M(this, i); s = this.isNew() ? "create" : i.patch ? "patch" : "update"; if (s === "patch") i.attrs = r; n = this.sync(s, this, i); if (r && i.wait) this.attributes = a; return n }, destroy: function (t) { t = t ? h.clone(t) : {}; var e = this; var i = t.success; var r = function () { e.trigger("destroy", e, e.collection, t) }; t.success = function (s) { if (t.wait || e.isNew()) r(); if (i) i(e, s, t); if (!e.isNew()) e.trigger("sync", e, s, t) }; if (this.isNew()) { t.success(); return false } M(this, t); var s = this.sync("delete", this, t); if (!t.wait) r(); return s }, url: function () { var t = h.result(this, "urlRoot") || h.result(this.collection, "url") || U(); if (this.isNew()) return t; return t + (t.charAt(t.length - 1) === "/" ? "" : "/") + encodeURIComponent(this.id) }, parse: function (t, e) { return t }, clone: function () { return new this.constructor(this.attributes) }, isNew: function () { return this.id == null }, isValid: function (t) { return this._validate({}, h.extend(t || {}, {validate: true})) }, _validate: function (t, e) { if (!e.validate || !this.validate) return true; t = h.extend({}, this.attributes, t); var i = this.validationError = this.validate(t, e) || null; if (!i) return true; this.trigger("invalid", this, i, h.extend(e, {validationError: i})); return false } }); var p = ["keys", "values", "pairs", "invert", "pick", "omit"]; h.each(p, function (t) { d.prototype[t] = function () { var e = s.call(arguments); e.unshift(this.attributes); return h[t].apply(h, e) } }); var v = a.Collection = function (t, e) { e || (e = {}); if (e.model) this.model = e.model; if (e.comparator !== void 0) this.comparator = e.comparator; this._reset(); this.initialize.apply(this, arguments); if (t) this.reset(t, h.extend({silent: true}, e)) }; var g = {add: true, remove: true, merge: true}; var m = {add: true, remove: false}; h.extend(v.prototype, o, { model: d, initialize: function () { }, toJSON: function (t) { return this.map(function (e) { return e.toJSON(t) }) }, sync: function () { return a.sync.apply(this, arguments) }, add: function (t, e) { return this.set(t, h.extend({merge: false}, e, m)) }, remove: function (t, e) { var i = !h.isArray(t); t = i ? [t] : h.clone(t); e || (e = {}); var r, s, n, a; for (r = 0, s = t.length; r < s; r++) { a = t[r] = this.get(t[r]); if (!a) continue; delete this._byId[a.id]; delete this._byId[a.cid]; n = this.indexOf(a); this.models.splice(n, 1); this.length--; if (!e.silent) { e.index = n; a.trigger("remove", a, this, e) } this._removeReference(a) } return i ? t[0] : t }, set: function (t, e) { e = h.defaults({}, e, g); if (e.parse) t = this.parse(t, e); var i = !h.isArray(t); t = i ? t ? [t] : [] : h.clone(t); var r, s, n, a, o, u, l; var c = e.at; var f = this.model; var p = this.comparator && c == null && e.sort !== false; var v = h.isString(this.comparator) ? this.comparator : null; var m = [], y = [], _ = {}; var w = e.add, b = e.merge, x = e.remove; var E = !p && w && x ? [] : false; for (r = 0, s = t.length; r < s; r++) { o = t[r]; if (o instanceof d) { n = a = o } else { n = o[f.prototype.idAttribute] } if (u = this.get(n)) { if (x) _[u.cid] = true; if (b) { o = o === a ? a.attributes : o; if (e.parse) o = u.parse(o, e); u.set(o, e); if (p && !l && u.hasChanged(v)) l = true } t[r] = u } else if { a = t[r] = this._prepareModel(o, e); if (!a) continue; m.push(a); a.on("all", this._onModelEvent, this); this._byId[a.cid] = a; if (a.id != null) this._byId[a.id] = a } if (E) E.push(u || a) } if (x) { for (r = 0, s = this.length; r < s; ++r) { if (!_[(a = this.models[r]).cid]) y.push(a) } if (y.length) this.remove(y, e) } if (m.length || E && E.length) { if (p) l = true; this.length += m.length; if (c != null) { for (r = 0, s = m.length; r < s; r++) { this.models.splice(c + r, 0, m[r]) } } else { if (E) this.models.length = 0; var T = E || m; for (r = 0, s = T.length; r < s; r++) { this.models.push(T[r]) } } } if (l) this.sort({silent: true}); if (!e.silent) { for (r = 0, s = m.length; r < s; r++) { (a = m[r]).trigger("add", a, this, e) } if (l || E && E.length) this.trigger("sort", this, e) } return i ? t[0] : t }, reset: function (t, e) { e || (e = {}); for (var i = 0, r = this.models.length; i < r; i++) { this._removeReference(this.models[i]) } e.previousModels = this.models; this._reset(); t = this.add(t, h.extend({silent: true}, e)); if (!e.silent) this.trigger("reset", this, e); return t }, push: function (t, e) { return this.add(t, h.extend({at: this.length}, e)) }, pop: function (t) { var e = this.at(this.length - 1); this.remove(e, t); return e }, unshift: function (t, e) { return this.add(t, h.extend({at: 0}, e)) }, shift: function (t) { var e = this.at(0); this.remove(e, t); return e }, slice: function () { return s.apply(this.models, arguments) }, get: function (t) { if (t == null) return void 0; return this._byId[t.id] || this._byId[t.cid] || this._byId[t] }, at: function (t) { return this.models[t] }, where: function (t, e) { if (h.isEmpty(t)) return e ? void 0 : []; return this[e ? "find" : "filter"](function (e) { for (var i in t) { if (t[i] !== e.get(i)) return false } return true }) }, findWhere: function (t) { return this.where(t, true) }, sort: function (t) { if (!this.comparator) throw new Error("Cannot sort a set without a comparator"); t || (t = {}); if (h.isString(this.comparator) || this.comparator.length === 1) { this.models = this.sortBy(this.comparator, this) } else { this.models.sort(h.bind(this.comparator, this)) } if (!t.silent) this.trigger("sort", this, t); return this }, pluck: function (t) { return h.invoke(this.models, "get", t) }, fetch: function (t) { t = t ? h.clone(t) : {}; if (t.parse === void 0) t.parse = true; var e = t.success; var i = this; t.success = function (r) { var s = t.reset ? "reset" : "set"; i[s](r, t); if (e) e(i, r, t); i.trigger("sync", i, r, t) }; M(this, t); return this.sync("read", this, t) }, create: function (t, e) { e = e ? h.clone(e) : {}; if (!(t = this._prepareModel(t, e))) return false; if (!e.wait) this.add(t, e); var i = this; var r = e.success; e.success = function (t, e, s) { if (s.wait) i.add(t, s); if (r) r(t, e, s) }; t.save(null, e); return t }, parse: function (t, e) { return t }, clone: function () { return new this.constructor(this.models) }, _reset: function () { this.length = 0; this.models = []; this._byId = {} }, _prepareModel: function (t, e) { if (t instanceof d) { if (!t.collection) t.collection = this; return t } e = e ? h.clone(e) : {}; e.collection = this; var i = new this.model(t, e); if (!i.validationError) return i; this.trigger("invalid", this, i.validationError, e); return false }, _removeReference: function (t) { if (this === t.collection) delete t.collection; t.off("all", this._onModelEvent, this) }, _onModelEvent: function (t, e, i, r) { if ((t === "add" || t === "remove") && i !== this) return; if (t === "destroy") this.remove(e, r); if (e && t === "change:" + e.idAttribute) { delete this._byId[e.previous(e.idAttribute)]; if (e.id != null) this._byId[e.id] = e } this.trigger.apply(this, arguments) } }); var y = ["forEach", "each", "map", "collect", "reduce", "foldl", "inject", "reduceRight", "foldr", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "max", "min", "toArray", "size", "first", "head", "take", "initial", "rest", "tail", "drop", "last", "without", "difference", "indexOf", "shuffle", "lastIndexOf", "isEmpty", "chain"]; h.each(y, function (t) { v.prototype[t] = function () { var e = s.call(arguments); e.unshift(this.models); return h[t].apply(h, e) } }); var _ = ["groupBy", "countBy", "sortBy"]; h.each(_, function (t) { v.prototype[t] = function (e, i) { var r = h.isFunction(e) ? e : function (t) { return t.get(e) }; return h[t](this.models, r, i) } }); var w = a.View = function (t) { this.cid = h.uniqueId("view"); t || (t = {}); h.extend(this, h.pick(t, x)); this._ensureElement(); this.initialize.apply(this, arguments); this.delegateEvents() }; var b = /^(\S+)\s*(.*)$/; var x = ["model", "collection", "el", "id", "attributes", "className", "tagName", "events"]; h.extend(w.prototype, o, { tagName: "div", $: function (t) { return this.$el.find(t) }, initialize: function () { }, render: function () { return this }, remove: function () { this.$el.remove(); this.stopListening(); return this }, setElement: function (t, e) { if (this.$el) this.undelegateEvents(); this.$el = t instanceof a.$ ? t : a.$(t); this.el = this.$el[0]; if (e !== false) this.delegateEvents(); return this }, delegateEvents: function (t) { if (!(t || (t = h.result(this, "events")))) return this; this.undelegateEvents(); for (var e in t) { var i = t[e]; if (!h.isFunction(i)) i = this[t[e]]; if (!i) continue; var r = e.match(b); var s = r[1], n = r[2]; i = h.bind(i, this); s += ".delegateEvents" + this.cid; if (n === "") { this.$el.on(s, i) } else { this.$el.on(s, n, i) } } return this }, undelegateEvents: function () { this.$el.off(".delegateEvents" + this.cid); return this }, _ensureElement: function () { if (!this.el) { var t = h.extend({}, h.result(this, "attributes")); if (this.id) t.id = h.result(this, "id"); if (this.className) t["class"] = h.result(this, "className"); var e = a.$("<" + h.result(this, "tagName") + ">").attr(t); this.setElement(e, false) } else { this.setElement(h.result(this, "el"), false) } } }); a.sync = function (t, e, i) { var r = T[t]; h.defaults(i || (i = {}), {emulateHTTP: a.emulateHTTP, emulateJSON: a.emulateJSON}); var s = {type: r, dataType: "json"}; if (!i.url) { s.url = h.result(e, "url") || U() } if (i.data == null && e && (t === "create" || t === "update" || t === "patch")) { s.contentType = "application/json"; s.data = JSON.stringify(i.attrs || e.toJSON(i)) } if (i.emulateJSON) { s.contentType = "application/x-www-form-urlencoded"; s.data = s.data ? {model: s.data} : {} } if (i.emulateHTTP && (r === "PUT" || r === "DELETE" || r === "PATCH")) { s.type = "POST"; if (i.emulateJSON) s.data._method = r; var n = i.beforeSend; i.beforeSend = function (t) { t.setRequestHeader("X-HTTP-Method-Override", r); if (n) return n.apply(this, arguments) } } if (s.type !== "GET" && !i.emulateJSON) { s.processData = false } if (s.type === "PATCH" && E) { s.xhr = function () { return new ActiveXObject("Microsoft.XMLHTTP") } } var o = i.xhr = a.ajax(h.extend(s, i)); e.trigger("request", e, o, i); return o }; var E = typeof window !== "undefined" && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent); var T = {create: "POST", update: "PUT", patch: "PATCH", "delete": "DELETE", read: "GET"}; a.ajax = function () { return a.$.ajax.apply(a.$, arguments) }; var k = a.Router = function (t) { t || (t = {}); if (t.routes) this.routes = t.routes; this._bindRoutes(); this.initialize.apply(this, arguments) }; var S = /\((.*?)\)/g; var $ = /(\(\?)?:\w+/g; var H = /\*\w+/g; var A = /[\-{}\[\]+?.,\\\^$|#\s]/g; h.extend(k.prototype, o, { initialize: function () { }, route: function (t, e, i) { if (!h.isRegExp(t)) t = this._routeToRegExp(t); if (h.isFunction(e)) { i = e; e = "" } if (!i) i = this[e]; var r = this; a.history.route(t, function (s) { var n = r._extractParameters(t, s); i && i.apply(r, n); r.trigger.apply(r, ["route:" + e].concat(n)); r.trigger("route", e, n); a.history.trigger("route", r, e, n) }); return this }, navigate: function (t, e) { a.history.navigate(t, e); return this }, _bindRoutes: function () { if (!this.routes) return; this.routes = h.result(this, "routes"); var t, e = h.keys(this.routes); while ((t = e.pop()) != null) { this.route(t, this.routes[t]) } }, _routeToRegExp: function (t) { t = t.replace(A, "\\$&").replace(S, "(?:$1)?").replace($, function (t, e) { return e ? t : "([^/]+)" }).replace(H, "(.*?)"); return new RegExp("^" + t + "$") }, _extractParameters: function (t, e) { var i = t.exec(e).slice(1); return h.map(i, function (t) { return t ? decodeURIComponent(t) : null }) } }); var I = a.History = function () { this.handlers = []; h.bindAll(this, "checkUrl"); if (typeof window !== "undefined") { this.location = window.location; this.history = window.history } }; var N = /^[#\/]|\s+$/g; var O = /^\/+|\/+$/g; var P = /msie [\w.]+/; var C = /\/$/; var j = /[?#].*$/; I.started = false; h.extend(I.prototype, o, { interval: 50, getHash: function (t) { var e = (t || this).location.href.match(/#(.*)$/); return e ? e[1] : "" }, getFragment: function (t, e) { if (t == null) { if (this._hasPushState || !this._wantsHashChange || e) { t = this.location.pathname; var i = this.root.replace(C, ""); if (!t.indexOf(i)) t = t.slice(i.length) } else { t = this.getHash() } } return t.replace(N, "") }, start: function (t) { if (I.started) throw new Error("Backbone.history has already been started"); I.started = true; this.options = h.extend({root: "/"}, this.options, t); this.root = this.options.root; this._wantsHashChange = this.options.hashChange !== false; this._wantsPushState = !!this.options.pushState; this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); var e = this.getFragment(); var i = document.documentMode; var r = P.exec(navigator.userAgent.toLowerCase()) && (!i || i <= 7); this.root = ("/" + this.root + "/").replace(O, "/"); if (r && this._wantsHashChange) { this.iframe = a.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow; this.navigate(e) } if (this._hasPushState) { a.$(window).on("popstate", this.checkUrl) } else if (this._wantsHashChange && "onhashchange" in window && !r) { a.$(window).on("hashchange", this.checkUrl) } else if (this._wantsHashChange) { this._checkUrlInterval = setInterval(this.checkUrl, this.interval) } this.fragment = e; var s = this.location; var n = s.pathname.replace(/[^\/]$/, "$&/") === this.root; if (this._wantsHashChange && this._wantsPushState) { if (!this._hasPushState && !n) { this.fragment = this.getFragment(null, true); this.location.replace(this.root + this.location.search + "#" + this.fragment); return true } else if (this._hasPushState && n && s.hash) { this.fragment = this.getHash().replace(N, ""); this.history.replaceState({}, document.title, this.root + this.fragment + s.search) } } if (!this.options.silent) return this.loadUrl() }, stop: function () { a.$(window).off("popstate", this.checkUrl).off("hashchange", this.checkUrl); clearInterval(this._checkUrlInterval); I.started = false }, route: function (t, e) { this.handlers.unshift({route: t, callback: e}) }, checkUrl: function (t) { var e = this.getFragment(); if (e === this.fragment && this.iframe) { e = this.getFragment(this.getHash(this.iframe)) } if (e === this.fragment) return false; if (this.iframe) this.navigate(e); this.loadUrl() }, loadUrl: function (t) { t = this.fragment = this.getFragment(t); return h.any(this.handlers, function (e) { if (e.route.test(t)) { e.callback(t); return true } }) }, navigate: function (t, e) { if (!I.started) return false; if (!e || e === true) e = {trigger: !!e}; var i = this.root + (t = this.getFragment(t || "")); t = t.replace(j, ""); if (this.fragment === t) return; this.fragment = t; if (t === "" && i !== "/") i = i.slice(0, -1); if (this._hasPushState) { this.history[e.replace ? "replaceState" : "pushState"]({}, document.title, i) } else if (this._wantsHashChange) { this._updateHash(this.location, t, e.replace); if (this.iframe && t !== this.getFragment(this.getHash(this.iframe))) { if (!e.replace) this.iframe.document.open().close(); this._updateHash(this.iframe.location, t, e.replace) } } else { return this.location.assign(i) } if (e.trigger) return this.loadUrl(t) }, _updateHash: function (t, e, i) { if (i) { var r = t.href.replace(/(javascript:|#).*$/, ""); t.replace(r + "#" + e) } else { t.hash = "#" + e } } }); a.history = new I; var R = function (t, e) { var i = this; var r; if (t && h.has(t, "constructor")) { r = t.constructor } else { r = function () { return i.apply(this, arguments) } } h.extend(r, i, e); var s = function () { this.constructor = r }; s.prototype = i.prototype; r.prototype = new s; if (t) h.extend(r.prototype, t); r.__super__ = i.prototype; return r }; d.extend = v.extend = k.extend = w.extend = I.extend = R; var U = function () { throw new Error('A "url" property or function must be specified') }; var M = function (t, e) { var i = e.error; e.error = function (r) { if (i) i(t, r, e); t.trigger("error", t, r, e) } } }).call(this); //# sourceMappingURL=backbone-min.map</script> <script type="text/javascript">// Knockout JavaScript library v3.1.0 // (c) Steven Sanderson - http://knockoutjs.com/ // License: MIT (http://www.opensource.org/licenses/mit-license.php) (function () { (function (p) { var A = this || (0, eval)("this"), w = A.document, K = A.navigator, t = A.jQuery, C = A.JSON; (function (p) { "function" === typeof require && "object" === typeof exports && "object" === typeof module ? p(module.exports || exports) : "function" === typeof define && define.amd ? define(["exports"], p) : p(A.ko = {}) })(function (z) { function G(a, c) { return null === a || typeof a in M ? a === c : !1 } function N(a, c) { var d; return function () { d || (d = setTimeout(function () { d = p; a() }, c)) } } function O(a, c) { var d; return function () { clearTimeout(d); d = setTimeout(a, c) } } function H(b, c, d, e) { a.d[b] = { init: function (b, h, g, k, l) { var n, r; a.ba(function () { var g = a.a.c(h()), k = !d !== !g, s = !r; if (s || c || k !== n) s && a.ca.fa() && (r = a.a.lb(a.e.childNodes(b), !0)), k ? (s || a.e.U(b, a.a.lb(r)), a.gb(e ? e(l, g) : l, b)) : a.e.da(b), n = k }, null, {G: b}); return {controlsDescendantBindings: !0} } }; a.g.aa[b] = !1; a.e.Q[b] = !0 } var a = "undefined" !== typeof z ? z : {}; a.b = function (b, c) { for (var d = b.split("."), e = a, f = 0; f < d.length - 1; f++) e = e[d[f]]; e[d[d.length - 1]] = c }; a.s = function (a, c, d) { a[c] = d }; a.version = "3.1.0"; a.b("version", a.version); a.a = function () { function b(a, b) { for (var c in a) a.hasOwnProperty(c) && b(c, a[c]) } function c(a, b) { if (b) for (var c in b) b.hasOwnProperty(c) && (a[c] = b[c]); return a } function d(a, b) { a.__proto__ = b; return a } var e = {__proto__: []} instanceof Array, f = {}, h = {}; f[K && /Firefox\/2/i.test(K.userAgent) ? "KeyboardEvent" : "UIEvents"] = ["keyup", "keydown", "keypress"]; f.MouseEvents = "click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" "); b(f, function (a, b) { if (b.length) for (var c = 0, d = b.length; c < d; c++) h[b[c]] = a }); var g = {propertychange: !0}, k = w && function () { for (var a = 3, b = w.createElement("div"), c = b.getElementsByTagName("i"); b.innerHTML = "\x3c!--[if gt IE " + ++a + "]><i></i><![endif]--\x3e", c[0];) ; return 4 < a ? a : p }(); return { mb: ["authenticity_token", /^__RequestVerificationToken(_.*)?$/], r: function (a, b) { for (var c = 0, d = a.length; c < d; c++) b(a[c], c) }, l: function (a, b) { if ("function" == typeof Array.prototype.indexOf) return Array.prototype.indexOf.call(a, b); for (var c = 0, d = a.length; c < d; c++) if (a[c] === b) return c; return -1 }, hb: function (a, b, c) { for (var d = 0, e = a.length; d < e; d++) if (b.call(c, a[d], d)) return a[d]; return null }, ma: function (b, c) { var d = a.a.l(b, c); 0 < d ? b.splice(d, 1) : 0 === d && b.shift() }, ib: function (b) { b = b || []; for (var c = [], d = 0, e = b.length; d < e; d++) 0 > a.a.l(c, b[d]) && c.push(b[d]); return c }, ya: function (a, b) { a = a || []; for (var c = [], d = 0, e = a.length; d < e; d++) c.push(b(a[d], d)); return c }, la: function (a, b) { a = a || []; for (var c = [], d = 0, e = a.length; d < e; d++) b(a[d], d) && c.push(a[d]); return c }, $: function (a, b) { if (b instanceof Array) a.push.apply(a, b); else for (var c = 0, d = b.length; c < d; c++) a.push(b[c]); return a }, Y: function (b, c, d) { var e = a.a.l(a.a.Sa(b), c); 0 > e ? d && b.push(c) : d || b.splice(e, 1) }, na: e, extend: c, ra: d, sa: e ? d : c, A: b, Oa: function (a, b) { if (!a) return a; var c = {}, d; for (d in a) a.hasOwnProperty(d) && (c[d] = b(a[d], d, a)); return c }, Fa: function (b) { for (; b.firstChild;) a.removeNode(b.firstChild) }, ec: function (b) { b = a.a.R(b); for (var c = w.createElement("div"), d = 0, e = b.length; d < e; d++) c.appendChild(a.M(b[d])); return c }, lb: function (b, c) { for (var d = 0, e = b.length, g = []; d < e; d++) { var k = b[d].cloneNode(!0); g.push(c ? a.M(k) : k) } return g }, U: function (b, c) { a.a.Fa(b); if (c) for (var d = 0, e = c.length; d < e; d++) b.appendChild(c[d]) }, Bb: function (b, c) { var d = b.nodeType ? [b] : b; if (0 < d.length) { for (var e = d[0], g = e.parentNode, k = 0, h = c.length; k < h; k++) g.insertBefore(c[k], e); k = 0; for (h = d.length; k < h; k++) a.removeNode(d[k]) } }, ea: function (a, b) { if (a.length) { for (b = 8 === b.nodeType && b.parentNode || b; a.length && a[0].parentNode !== b;) a.shift(); if (1 < a.length) { var c = a[0], d = a[a.length - 1]; for (a.length = 0; c !== d;) if (a.push(c), c = c.nextSibling, !c) return; a.push(d) } } return a }, Db: function (a, b) { 7 > k ? a.setAttribute("selected", b) : a.selected = b }, ta: function (a) { return null === a || a === p ? "" : a.trim ? a.trim() : a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, "") }, oc: function (b, c) { for (var d = [], e = (b || "").split(c), g = 0, k = e.length; g < k; g++) { var h = a.a.ta(e[g]); "" !== h && d.push(h) } return d }, kc: function (a, b) { a = a || ""; return b.length > a.length ? !1 : a.substring(0, b.length) === b }, Sb: function (a, b) { if (a === b) return !0; if (11 === a.nodeType) return !1; if (b.contains) return b.contains(3 === a.nodeType ? a.parentNode : a); if (b.compareDocumentPosition) return 16 == (b.compareDocumentPosition(a) & 16); for (; a && a != b;) a = a.parentNode; return !!a }, Ea: function (b) { return a.a.Sb(b, b.ownerDocument.documentElement) }, eb: function (b) { return !!a.a.hb(b, a.a.Ea) }, B: function (a) { return a && a.tagName && a.tagName.toLowerCase() }, q: function (b, c, d) { var e = k && g[c]; if (!e && t) t(b).bind(c, d); else if (e || "function" != typeof b.addEventListener) if ("undefined" != typeof b.attachEvent) { var h = function (a) { d.call(b, a) }, f = "on" + c; b.attachEvent(f, h); a.a.u.ja(b, function () { b.detachEvent(f, h) }) } else throw Error("Browser doesn't support addEventListener or attachEvent"); else b.addEventListener(c, d, !1) }, ha: function (b, c) { if (!b || !b.nodeType) throw Error("element must be a DOM node when calling triggerEvent"); var d; "input" === a.a.B(b) && b.type && "click" == c.toLowerCase() ? (d = b.type, d = "checkbox" == d || "radio" == d) : d = !1; if (t && !d) t(b).trigger(c); else if ("function" == typeof w.createEvent) if ("function" == typeof b.dispatchEvent) d = w.createEvent(h[c] || "HTMLEvents"), d.initEvent(c, !0, !0, A, 0, 0, 0, 0, 0, !1, !1, !1, !1, 0, b), b.dispatchEvent(d); else throw Error("The supplied element doesn't support dispatchEvent"); else if (d && b.click) b.click(); else if ("undefined" != typeof b.fireEvent) b.fireEvent("on" + c); else throw Error("Browser doesn't support triggering events"); }, c: function (b) { return a.v(b) ? b() : b }, Sa: function (b) { return a.v(b) ? b.o() : b }, ua: function (b, c, d) { if (c) { var e = /\S+/g, g = b.className.match(e) || []; a.a.r(c.match(e), function (b) { a.a.Y(g, b, d) }); b.className = g.join(" ") } }, Xa: function (b, c) { var d = a.a.c(c); if (null === d || d === p) d = ""; var e = a.e.firstChild(b); !e || 3 != e.nodeType || a.e.nextSibling(e) ? a.e.U(b, [b.ownerDocument.createTextNode(d)]) : e.data = d; a.a.Vb(b) }, Cb: function (a, b) { a.name = b; if (7 >= k) try { a.mergeAttributes(w.createElement("<input name='" + a.name + "'/>"), !1) } catch (c) { } }, Vb: function (a) { 9 <= k && (a = 1 == a.nodeType ? a : a.parentNode, a.style && (a.style.zoom = a.style.zoom)) }, Tb: function (a) { if (k) { var b = a.style.width; a.style.width = 0; a.style.width = b } }, ic: function (b, c) { b = a.a.c(b); c = a.a.c(c); for (var d = [], e = b; e <= c; e++) d.push(e); return d }, R: function (a) { for (var b = [], c = 0, d = a.length; c < d; c++) b.push(a[c]); return b }, mc: 6 === k, nc: 7 === k, oa: k, ob: function (b, c) { for (var d = a.a.R(b.getElementsByTagName("input")).concat(a.a.R(b.getElementsByTagName("textarea"))), e = "string" == typeof c ? function (a) { return a.name === c } : function (a) { return c.test(a.name) }, g = [], k = d.length - 1; 0 <= k; k--) e(d[k]) && g.push(d[k]); return g }, fc: function (b) { return "string" == typeof b && (b = a.a.ta(b)) ? C && C.parse ? C.parse(b) : (new Function("return " + b))() : null }, Ya: function (b, c, d) { if (!C || !C.stringify) throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"); return C.stringify(a.a.c(b), c, d) }, gc: function (c, d, e) { e = e || {}; var g = e.params || {}, k = e.includeFields || this.mb, h = c; if ("object" == typeof c && "form" === a.a.B(c)) for (var h = c.action, f = k.length - 1; 0 <= f; f--) for (var u = a.a.ob(c, k[f]), D = u.length - 1; 0 <= D; D--) g[u[D].name] = u[D].value; d = a.a.c(d); var y = w.createElement("form"); y.style.display = "none"; y.action = h; y.method = "post"; for (var p in d) c = w.createElement("input"), c.name = p, c.value = a.a.Ya(a.a.c(d[p])), y.appendChild(c); b(g, function (a, b) { var c = w.createElement("input"); c.name = a; c.value = b; y.appendChild(c) }); w.body.appendChild(y); e.submitter ? e.submitter(y) : y.submit(); setTimeout(function () { y.parentNode.removeChild(y) }, 0) } } }(); a.b("utils", a.a); a.b("utils.arrayForEach", a.a.r); a.b("utils.arrayFirst", a.a.hb); a.b("utils.arrayFilter", a.a.la); a.b("utils.arrayGetDistinctValues", a.a.ib); a.b("utils.arrayIndexOf", a.a.l); a.b("utils.arrayMap", a.a.ya); a.b("utils.arrayPushAll", a.a.$); a.b("utils.arrayRemoveItem", a.a.ma); a.b("utils.extend", a.a.extend); a.b("utils.fieldsIncludedWithJsonPost", a.a.mb); a.b("utils.getFormFields", a.a.ob); a.b("utils.peekObservable", a.a.Sa); a.b("utils.postJson", a.a.gc); a.b("utils.parseJson", a.a.fc); a.b("utils.registerEventHandler", a.a.q); a.b("utils.stringifyJson", a.a.Ya); a.b("utils.range", a.a.ic); a.b("utils.toggleDomNodeCssClass", a.a.ua); a.b("utils.triggerEvent", a.a.ha); a.b("utils.unwrapObservable", a.a.c); a.b("utils.objectForEach", a.a.A); a.b("utils.addOrRemoveItem", a.a.Y); a.b("unwrap", a.a.c); Function.prototype.bind || (Function.prototype.bind = function (a) { var c = this, d = Array.prototype.slice.call(arguments); a = d.shift(); return function () { return c.apply(a, d.concat(Array.prototype.slice.call(arguments))) } }); a.a.f = new function () { function a(b, h) { var g = b[d]; if (!g || "null" === g || !e[g]) { if (!h) return p; g = b[d] = "ko" + c++; e[g] = {} } return e[g] } var c = 0, d = "__ko__" + (new Date).getTime(), e = {}; return { get: function (c, d) { var e = a(c, !1); return e === p ? p : e[d] }, set: function (c, d, e) { if (e !== p || a(c, !1) !== p) a(c, !0)[d] = e }, clear: function (a) { var b = a[d]; return b ? (delete e[b], a[d] = null, !0) : !1 }, L: function () { return c++ + d } } }; a.b("utils.domData", a.a.f); a.b("utils.domData.clear", a.a.f.clear); a.a.u = new function () { function b(b, c) { var e = a.a.f.get(b, d); e === p && c && (e = [], a.a.f.set(b, d, e)); return e } function c(d) { var e = b(d, !1); if (e) for (var e = e.slice(0), k = 0; k < e.length; k++) e[k](d); a.a.f.clear(d); a.a.u.cleanExternalData(d); if (f[d.nodeType]) for (e = d.firstChild; d = e;) e = d.nextSibling, 8 === d.nodeType && c(d) } var d = a.a.f.L(), e = {1: !0, 8: !0, 9: !0}, f = {1: !0, 9: !0}; return { ja: function (a, c) { if ("function" != typeof c) throw Error("Callback must be a function"); b(a, !0).push(c) }, Ab: function (c, e) { var k = b(c, !1); k && (a.a.ma(k, e), 0 == k.length && a.a.f.set(c, d, p)) }, M: function (b) { if (e[b.nodeType] && (c(b), f[b.nodeType])) { var d = []; a.a.$(d, b.getElementsByTagName("*")); for (var k = 0, l = d.length; k < l; k++) c(d[k]) } return b }, removeNode: function (b) { a.M(b); b.parentNode && b.parentNode.removeChild(b) }, cleanExternalData: function (a) { t && "function" == typeof t.cleanData && t.cleanData([a]) } } }; a.M = a.a.u.M; a.removeNode = a.a.u.removeNode; a.b("cleanNode", a.M); a.b("removeNode", a.removeNode); a.b("utils.domNodeDisposal", a.a.u); a.b("utils.domNodeDisposal.addDisposeCallback", a.a.u.ja); a.b("utils.domNodeDisposal.removeDisposeCallback", a.a.u.Ab); (function () { a.a.Qa = function (b) { var c; if (t) if (t.parseHTML) c = t.parseHTML(b) || []; else { if ((c = t.clean([b])) && c[0]) { for (b = c[0]; b.parentNode && 11 !== b.parentNode.nodeType;) b = b.parentNode; b.parentNode && b.parentNode.removeChild(b) } } else { var d = a.a.ta(b).toLowerCase(); c = w.createElement("div"); d = d.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] || !d.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] || (!d.indexOf("<td") || !d.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] || [0, "", ""]; b = "ignored<div>" + d[1] + b + d[2] + "</div>"; for ("function" == typeof A.innerShiv ? c.appendChild(A.innerShiv(b)) : c.innerHTML = b; d[0]--;) c = c.lastChild; c = a.a.R(c.lastChild.childNodes) } return c }; a.a.Va = function (b, c) { a.a.Fa(b); c = a.a.c(c); if (null !== c && c !== p) if ("string" != typeof c && (c = c.toString()), t) t(b).html(c); else for (var d = a.a.Qa(c), e = 0; e < d.length; e++) b.appendChild(d[e]) } })(); a.b("utils.parseHtmlFragment", a.a.Qa); a.b("utils.setHtml", a.a.Va); a.w = function () { function b(c, e) { if (c) if (8 == c.nodeType) { var f = a.w.xb(c.nodeValue); null != f && e.push({Rb: c, cc: f}) } else if (1 == c.nodeType) for (var f = 0, h = c.childNodes, g = h.length; f < g; f++) b(h[f], e) } var c = {}; return { Na: function (a) { if ("function" != typeof a) throw Error("You can only pass a function to ko.memoization.memoize()"); var b = (4294967296 * (1 + Math.random()) | 0).toString(16).substring(1) + (4294967296 * (1 + Math.random()) | 0).toString(16).substring(1); c[b] = a; return "\x3c!--[ko_memo:" + b + "]--\x3e" }, Hb: function (a, b) { var f = c[a]; if (f === p) throw Error("Couldn't find any memo with ID " + a + ". Perhaps it's already been unmemoized."); try { return f.apply(null, b || []), !0 } finally { delete c[a] } }, Ib: function (c, e) { var f = []; b(c, f); for (var h = 0, g = f.length; h < g; h++) { var k = f[h].Rb, l = [k]; e && a.a.$(l, e); a.w.Hb(f[h].cc, l); k.nodeValue = ""; k.parentNode && k.parentNode.removeChild(k) } }, xb: function (a) { return (a = a.match(/^\[ko_memo\:(.*?)\]$/)) ? a[1] : null } } }(); a.b("memoization", a.w); a.b("memoization.memoize", a.w.Na); a.b("memoization.unmemoize", a.w.Hb); a.b("memoization.parseMemoText", a.w.xb); a.b("memoization.unmemoizeDomNodeAndDescendants", a.w.Ib); a.Ga = { throttle: function (b, c) { b.throttleEvaluation = c; var d = null; return a.h({ read: b, write: function (a) { clearTimeout(d); d = setTimeout(function () { b(a) }, c) } }) }, rateLimit: function (a, c) { var d, e, f; "number" == typeof c ? d = c : (d = c.timeout, e = c.method); f = "notifyWhenChangesStop" == e ? O : N; a.Ma(function (a) { return f(a, d) }) }, notify: function (a, c) { a.equalityComparer = "always" == c ? null : G } }; var M = {undefined: 1, "boolean": 1, number: 1, string: 1}; a.b("extenders", a.Ga); a.Fb = function (b, c, d) { this.target = b; this.za = c; this.Qb = d; this.sb = !1; a.s(this, "dispose", this.F) }; a.Fb.prototype.F = function () { this.sb = !0; this.Qb() }; a.N = function () { a.a.sa(this, a.N.fn); this.H = {} }; var F = "change"; z = { V: function (b, c, d) { var e = this; d = d || F; var f = new a.Fb(e, c ? b.bind(c) : b, function () { a.a.ma(e.H[d], f) }); e.o && e.o(); e.H[d] || (e.H[d] = []); e.H[d].push(f); return f }, notifySubscribers: function (b, c) { c = c || F; if (this.qb(c)) try { a.k.jb(); for (var d = this.H[c].slice(0), e = 0, f; f = d[e]; ++e) f.sb || f.za(b) } finally { a.k.end() } }, Ma: function (b) { var c = this, d = a.v(c), e, f, h; c.ia || (c.ia = c.notifySubscribers, c.notifySubscribers = function (a, b) { b && b !== F ? "beforeChange" === b ? c.bb(a) : c.ia(a, b) : c.cb(a) }); var g = b(function () { d && h === c && (h = c()); e = !1; c.Ka(f, h) && c.ia(f = h) }); c.cb = function (a) { e = !0; h = a; g() }; c.bb = function (a) { e || (f = a, c.ia(a, "beforeChange")) } }, qb: function (a) { return this.H[a] && this.H[a].length }, Wb: function () { var b = 0; a.a.A(this.H, function (a, d) { b += d.length }); return b }, Ka: function (a, c) { return !this.equalityComparer || !this.equalityComparer(a, c) }, extend: function (b) { var c = this; b && a.a.A(b, function (b, e) { var f = a.Ga[b]; "function" == typeof f && (c = f(c, e) || c) }); return c } }; a.s(z, "subscribe", z.V); a.s(z, "extend", z.extend); a.s(z, "getSubscriptionsCount", z.Wb); a.a.na && a.a.ra(z, Function.prototype); a.N.fn = z; a.tb = function (a) { return null != a && "function" == typeof a.V && "function" == typeof a.notifySubscribers }; a.b("subscribable", a.N); a.b("isSubscribable", a.tb); a.ca = a.k = function () { function b(a) { d.push(e); e = a } function c() { e = d.pop() } var d = [], e, f = 0; return { jb: b, end: c, zb: function (b) { if (e) { if (!a.tb(b)) throw Error("Only subscribable things can act as dependencies"); e.za(b, b.Kb || (b.Kb = ++f)) } }, t: function (a, d, e) { try { return b(), a.apply(d, e || []) } finally { c() } }, fa: function () { if (e) return e.ba.fa() }, pa: function () { if (e) return e.pa } } }(); a.b("computedContext", a.ca); a.b("computedContext.getDependenciesCount", a.ca.fa); a.b("computedContext.isInitial", a.ca.pa); a.m = function (b) { function c() { if (0 < arguments.length) return c.Ka(d, arguments[0]) && (c.P(), d = arguments[0], c.O()), this; a.k.zb(c); return d } var d = b; a.N.call(c); a.a.sa(c, a.m.fn); c.o = function () { return d }; c.O = function () { c.notifySubscribers(d) }; c.P = function () { c.notifySubscribers(d, "beforeChange") }; a.s(c, "peek", c.o); a.s(c, "valueHasMutated", c.O); a.s(c, "valueWillMutate", c.P); return c }; a.m.fn = {equalityComparer: G}; var E = a.m.hc = "__ko_proto__"; a.m.fn[E] = a.m; a.a.na && a.a.ra(a.m.fn, a.N.fn); a.Ha = function (b, c) { return null === b || b === p || b[E] === p ? !1 : b[E] === c ? !0 : a.Ha(b[E], c) }; a.v = function (b) { return a.Ha(b, a.m) }; a.ub = function (b) { return "function" == typeof b && b[E] === a.m || "function" == typeof b && b[E] === a.h && b.Yb ? !0 : !1 }; a.b("observable", a.m); a.b("isObservable", a.v); a.b("isWriteableObservable", a.ub); a.T = function (b) { b = b || []; if ("object" != typeof b || !("length" in b)) throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined."); b = a.m(b); a.a.sa(b, a.T.fn); return b.extend({trackArrayChanges: !0}) }; a.T.fn = { remove: function (b) { for (var c = this.o(), d = [], e = "function" != typeof b || a.v(b) ? function (a) { return a === b } : b, f = 0; f < c.length; f++) { var h = c[f]; e(h) && (0 === d.length && this.P(), d.push(h), c.splice(f, 1), f--) } d.length && this.O(); return d }, removeAll: function (b) { if (b === p) { var c = this.o(), d = c.slice(0); this.P(); c.splice(0, c.length); this.O(); return d } return b ? this.remove(function (c) { return 0 <= a.a.l(b, c) }) : [] }, destroy: function (b) { var c = this.o(), d = "function" != typeof b || a.v(b) ? function (a) { return a === b } : b; this.P(); for (var e = c.length - 1; 0 <= e; e--) d(c[e]) && (c[e]._destroy = !0); this.O() }, destroyAll: function (b) { return b === p ? this.destroy(function () { return !0 }) : b ? this.destroy(function (c) { return 0 <= a.a.l(b, c) }) : [] }, indexOf: function (b) { var c = this(); return a.a.l(c, b) }, replace: function (a, c) { var d = this.indexOf(a); 0 <= d && (this.P(), this.o()[d] = c, this.O()) } }; a.a.r("pop push reverse shift sort splice unshift".split(" "), function (b) { a.T.fn[b] = function () { var a = this.o(); this.P(); this.kb(a, b, arguments); a = a[b].apply(a, arguments); this.O(); return a } }); a.a.r(["slice"], function (b) { a.T.fn[b] = function () { var a = this(); return a[b].apply(a, arguments) } }); a.a.na && a.a.ra(a.T.fn, a.m.fn); a.b("observableArray", a.T); var I = "arrayChange"; a.Ga.trackArrayChanges = function (b) { function c() { if (!d) { d = !0; var c = b.notifySubscribers; b.notifySubscribers = function (a, b) { b && b !== F || ++f; return c.apply(this, arguments) }; var k = [].concat(b.o() || []); e = null; b.V(function (c) { c = [].concat(c || []); if (b.qb(I)) { var d; if (!e || 1 < f) e = a.a.Aa(k, c, {sparse: !0}); d = e; d.length && b.notifySubscribers(d, I) } k = c; e = null; f = 0 }) } } if (!b.kb) { var d = !1, e = null, f = 0, h = b.V; b.V = b.subscribe = function (a, b, d) { d === I && c(); return h.apply(this, arguments) }; b.kb = function (b, c, l) { function h(a, b, c) { return r[r.length] = {status: a, value: b, index: c} } if (d && !f) { var r = [], m = b.length, q = l.length, s = 0; switch (c) { case "push": s = m; case "unshift": for (c = 0; c < q; c++) h("added", l[c], s + c); break; case "pop": s = m - 1; case "shift": m && h("deleted", b[s], s); break; case "splice": c = Math.min(Math.max(0, 0 > l[0] ? m + l[0] : l[0]), m); for (var m = 1 === q ? m : Math.min(c + (l[1] || 0), m), q = c + q - 2, s = Math.max(m, q), B = [], u = [], D = 2; c < s; ++c, ++D) c < m && u.push(h("deleted", b[c], c)), c < q && B.push(h("added", l[D], c)); a.a.nb(u, B); break; default: return } e = r } } } }; a.ba = a.h = function (b, c, d) { function e() { q = !0; a.a.A(v, function (a, b) { b.F() }); v = {}; x = 0; n = !1 } function f() { var a = g.throttleEvaluation; a && 0 <= a ? (clearTimeout(t), t = setTimeout(h, a)) : g.wa ? g.wa() : h() } function h() { if (!r && !q) { if (y && y()) { if (!m) { p(); return } } else m = !1; r = !0; try { var b = v, d = x; a.k.jb({ za: function (a, c) { q || (d && b[c] ? (v[c] = b[c], ++x, delete b[c], --d) : v[c] || (v[c] = a.V(f), ++x)) }, ba: g, pa: !x }); v = {}; x = 0; try { var e = c ? s.call(c) : s() } finally { a.k.end(), d && a.a.A(b, function (a, b) { b.F() }), n = !1 } g.Ka(l, e) && (g.notifySubscribers(l, "beforeChange"), l = e, g.wa && !g.throttleEvaluation || g.notifySubscribers(l)) } finally { r = !1 } x || p() } } function g() { if (0 < arguments.length) { if ("function" === typeof B) B.apply(c, arguments); else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters."); return this } n && h(); a.k.zb(g); return l } function k() { return n || 0 < x } var l, n = !0, r = !1, m = !1, q = !1, s = b; s && "object" == typeof s ? (d = s, s = d.read) : (d = d || {}, s || (s = d.read)); if ("function" != typeof s) throw Error("Pass a function that returns the value of the ko.computed"); var B = d.write, u = d.disposeWhenNodeIsRemoved || d.G || null, D = d.disposeWhen || d.Da, y = D, p = e, v = {}, x = 0, t = null; c || (c = d.owner); a.N.call(g); a.a.sa(g, a.h.fn); g.o = function () { n && !x && h(); return l }; g.fa = function () { return x }; g.Yb = "function" === typeof d.write; g.F = function () { p() }; g.ga = k; var w = g.Ma; g.Ma = function (a) { w.call(g, a); g.wa = function () { g.bb(l); n = !0; g.cb(g) } }; a.s(g, "peek", g.o); a.s(g, "dispose", g.F); a.s(g, "isActive", g.ga); a.s(g, "getDependenciesCount", g.fa); u && (m = !0, u.nodeType && (y = function () { return !a.a.Ea(u) || D && D() })); !0 !== d.deferEvaluation && h(); u && k() && u.nodeType && (p = function () { a.a.u.Ab(u, p); e() }, a.a.u.ja(u, p)); return g }; a.$b = function (b) { return a.Ha(b, a.h) }; z = a.m.hc; a.h[z] = a.m; a.h.fn = {equalityComparer: G}; a.h.fn[z] = a.h; a.a.na && a.a.ra(a.h.fn, a.N.fn); a.b("dependentObservable", a.h); a.b("computed", a.h); a.b("isComputed", a.$b); (function () { function b(a, f, h) { h = h || new d; a = f(a); if ("object" != typeof a || null === a || a === p || a instanceof Date || a instanceof String || a instanceof Number || a instanceof Boolean) return a; var g = a instanceof Array ? [] : {}; h.save(a, g); c(a, function (c) { var d = f(a[c]); switch (typeof d) { case "boolean": case "number": case "string": case "function": g[c] = d; break; case "object": case "undefined": var n = h.get(d); g[c] = n !== p ? n : b(d, f, h) } }); return g } function c(a, b) { if (a instanceof Array) { for (var c = 0; c < a.length; c++) b(c); "function" == typeof a.toJSON && b("toJSON") } else for (c in a) b(c) } function d() { this.keys = []; this.ab = [] } a.Gb = function (c) { if (0 == arguments.length) throw Error("When calling ko.toJS, pass the object you want to convert."); return b(c, function (b) { for (var c = 0; a.v(b) && 10 > c; c++) b = b(); return b }) }; a.toJSON = function (b, c, d) { b = a.Gb(b); return a.a.Ya(b, c, d) }; d.prototype = { save: function (b, c) { var d = a.a.l(this.keys, b); 0 <= d ? this.ab[d] = c : (this.keys.push(b), this.ab.push(c)) }, get: function (b) { b = a.a.l(this.keys, b); return 0 <= b ? this.ab[b] : p } } })(); a.b("toJS", a.Gb); a.b("toJSON", a.toJSON); (function () { a.i = { p: function (b) { switch (a.a.B(b)) { case "option": return !0 === b.__ko__hasDomDataOptionValue__ ? a.a.f.get(b, a.d.options.Pa) : 7 >= a.a.oa ? b.getAttributeNode("value") && b.getAttributeNode("value").specified ? b.value : b.text : b.value; case "select": return 0 <= b.selectedIndex ? a.i.p(b.options[b.selectedIndex]) : p; default: return b.value } }, X: function (b, c, d) { switch (a.a.B(b)) { case "option": switch (typeof c) { case "string": a.a.f.set(b, a.d.options.Pa, p); "__ko__hasDomDataOptionValue__" in b && delete b.__ko__hasDomDataOptionValue__; b.value = c; break; default: a.a.f.set(b, a.d.options.Pa, c), b.__ko__hasDomDataOptionValue__ = !0, b.value = "number" === typeof c ? c : "" } break; case "select": if ("" === c || null === c) c = p; for (var e = -1, f = 0, h = b.options.length, g; f < h; ++f) if (g = a.i.p(b.options[f]), g == c || "" == g && c === p) { e = f; break } if (d || 0 <= e || c === p && 1 < b.size) b.selectedIndex = e; break; default: if (null === c || c === p) c = ""; b.value = c } } } })(); a.b("selectExtensions", a.i); a.b("selectExtensions.readValue", a.i.p); a.b("selectExtensions.writeValue", a.i.X); a.g = function () { function b(b) { b = a.a.ta(b); 123 === b.charCodeAt(0) && (b = b.slice(1, -1)); var c = [], d = b.match(e), g, m, q = 0; if (d) { d.push(","); for (var s = 0, B; B = d[s]; ++s) { var u = B.charCodeAt(0); if (44 === u) { if (0 >= q) { g && c.push(m ? {key: g, value: m.join("")} : {unknown: g}); g = m = q = 0; continue } } else if (58 === u) { if (!m) continue } else if (47 === u && s && 1 < B.length) (u = d[s - 1].match(f)) && !h[u[0]] && (b = b.substr(b.indexOf(B) + 1), d = b.match(e), d.push(","), s = -1, B = "/"); else if (40 === u || 123 === u || 91 === u) ++q; else if (41 === u || 125 === u || 93 === u) --q; else if (!g && !m) { g = 34 === u || 39 === u ? B.slice(1, -1) : B; continue } m ? m.push(B) : m = [B] } } return c } var c = ["true", "false", "null", "undefined"], d = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i, e = RegExp("\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|/(?:[^/\\\\]|\\\\.)*/w*|[^\\s:,/][^,\"'{}()/:[\\]]*[^\\s,\"'{}()/:[\\]]|[^\\s]", "g"), f = /[\])"'A-Za-z0-9_$]+$/, h = {"in": 1, "return": 1, "typeof": 1}, g = {}; return { aa: [], W: g, Ra: b, qa: function (e, l) { function f(b, e) { var l, k = a.getBindingHandler(b); if (k && k.preprocess ? e = k.preprocess(e, b, f) : 1) { if (k = g[b]) l = e, 0 <= a.a.l(c, l) ? l = !1 : (k = l.match(d), l = null === k ? !1 : k[1] ? "Object(" + k[1] + ")" + k[2] : l), k = l; k && m.push("'" + b + "':function(_z){" + l + "=_z}"); q && (e = "function(){return " + e + " }"); h.push("'" + b + "':" + e) } } l = l || {}; var h = [], m = [], q = l.valueAccessors, s = "string" === typeof e ? b(e) : e; a.a.r(s, function (a) { f(a.key || a.unknown, a.value) }); m.length && f("_ko_property_writers", "{" + m.join(",") + " }"); return h.join(",") }, bc: function (a, b) { for (var c = 0; c < a.length; c++) if (a[c].key == b) return !0; return !1 }, va: function (b, c, d, e, g) { if (b && a.v(b)) !a.ub(b) || g && b.o() === e || b(e); else if ((b = c.get("_ko_property_writers")) && b[d]) b[d](e) } } }(); a.b("expressionRewriting", a.g); a.b("expressionRewriting.bindingRewriteValidators", a.g.aa); a.b("expressionRewriting.parseObjectLiteral", a.g.Ra); a.b("expressionRewriting.preProcessBindings", a.g.qa); a.b("expressionRewriting._twoWayBindings", a.g.W); a.b("jsonExpressionRewriting", a.g); a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson", a.g.qa); (function () { function b(a) { return 8 == a.nodeType && h.test(f ? a.text : a.nodeValue) } function c(a) { return 8 == a.nodeType && g.test(f ? a.text : a.nodeValue) } function d(a, d) { for (var e = a, g = 1, k = []; e = e.nextSibling;) { if (c(e) && (g--, 0 === g)) return k; k.push(e); b(e) && g++ } if (!d) throw Error("Cannot find closing comment tag to match: " + a.nodeValue); return null } function e(a, b) { var c = d(a, b); return c ? 0 < c.length ? c[c.length - 1].nextSibling : a.nextSibling : null } var f = w && "\x3c!--test--\x3e" === w.createComment("test").text, h = f ? /^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/ : /^\s*ko(?:\s+([\s\S]+))?\s*$/, g = f ? /^\x3c!--\s*\/ko\s*--\x3e$/ : /^\s*\/ko\s*$/, k = {ul: !0, ol: !0}; a.e = { Q: {}, childNodes: function (a) { return b(a) ? d(a) : a.childNodes }, da: function (c) { if (b(c)) { c = a.e.childNodes(c); for (var d = 0, e = c.length; d < e; d++) a.removeNode(c[d]) } else a.a.Fa(c) }, U: function (c, d) { if (b(c)) { a.e.da(c); for (var e = c.nextSibling, g = 0, k = d.length; g < k; g++) e.parentNode.insertBefore(d[g], e) } else a.a.U(c, d) }, yb: function (a, c) { b(a) ? a.parentNode.insertBefore(c, a.nextSibling) : a.firstChild ? a.insertBefore(c, a.firstChild) : a.appendChild(c) }, rb: function (c, d, e) { e ? b(c) ? c.parentNode.insertBefore(d, e.nextSibling) : e.nextSibling ? c.insertBefore(d, e.nextSibling) : c.appendChild(d) : a.e.yb(c, d) }, firstChild: function (a) { return b(a) ? !a.nextSibling || c(a.nextSibling) ? null : a.nextSibling : a.firstChild }, nextSibling: function (a) { b(a) && (a = e(a)); return a.nextSibling && c(a.nextSibling) ? null : a.nextSibling }, Xb: b, lc: function (a) { return (a = (f ? a.text : a.nodeValue).match(h)) ? a[1] : null }, wb: function (d) { if (k[a.a.B(d)]) { var g = d.firstChild; if (g) { do if (1 === g.nodeType) { var f; f = g.firstChild; var h = null; if (f) { do if (h) h.push(f); else if (b(f)) { var q = e(f, !0); q ? f = q : h = [f] } else c(f) && (h = [f]); while (f = f.nextSibling) } if (f = h) for (h = g.nextSibling, q = 0; q < f.length; q++) h ? d.insertBefore(f[q], h) : d.appendChild(f[q]) } while (g = g.nextSibling) } } } } })(); a.b("virtualElements", a.e); a.b("virtualElements.allowedBindings", a.e.Q); a.b("virtualElements.emptyNode", a.e.da); a.b("virtualElements.insertAfter", a.e.rb); a.b("virtualElements.prepend", a.e.yb); a.b("virtualElements.setDomNodeChildren", a.e.U); (function () { a.J = function () { this.Nb = {} }; a.a.extend(a.J.prototype, { nodeHasBindings: function (b) { switch (b.nodeType) { case 1: return null != b.getAttribute("data-bind"); case 8: return a.e.Xb(b); default: return !1 } }, getBindings: function (a, c) { var d = this.getBindingsString(a, c); return d ? this.parseBindingsString(d, c, a) : null }, getBindingAccessors: function (a, c) { var d = this.getBindingsString(a, c); return d ? this.parseBindingsString(d, c, a, {valueAccessors: !0}) : null }, getBindingsString: function (b) { switch (b.nodeType) { case 1: return b.getAttribute("data-bind"); case 8: return a.e.lc(b); default: return null } }, parseBindingsString: function (b, c, d, e) { try { var f = this.Nb, h = b + (e && e.valueAccessors || ""), g; if (!(g = f[h])) { var k, l = "with($context){with($data||{}){return{" + a.g.qa(b, e) + "}}}"; k = new Function("$context", "$element", l); g = f[h] = k } return g(c, d) } catch (n) { throw n.message = "Unable to parse bindings.\nBindings value: " + b + "\nMessage: " + n.message, n; } } }); a.J.instance = new a.J })(); a.b("bindingProvider", a.J); (function () { function b(a) { return function () { return a } } function c(a) { return a() } function d(b) { return a.a.Oa(a.k.t(b), function (a, c) { return function () { return b()[c] } }) } function e(a, b) { return d(this.getBindings.bind(this, a, b)) } function f(b, c, d) { var e, g = a.e.firstChild(c), k = a.J.instance, f = k.preprocessNode; if (f) { for (; e = g;) g = a.e.nextSibling(e), f.call(k, e); g = a.e.firstChild(c) } for (; e = g;) g = a.e.nextSibling(e), h(b, e, d) } function h(b, c, d) { var e = !0, g = 1 === c.nodeType; g && a.e.wb(c); if (g && d || a.J.instance.nodeHasBindings(c)) e = k(c, null, b, d).shouldBindDescendants; e && !n[a.a.B(c)] && f(b, c, !g) } function g(b) { var c = [], d = {}, e = []; a.a.A(b, function y(g) { if (!d[g]) { var k = a.getBindingHandler(g); k && (k.after && (e.push(g), a.a.r(k.after, function (c) { if (b[c]) { if (-1 !== a.a.l(e, c)) throw Error("Cannot combine the following bindings, because they have a cyclic dependency: " + e.join(", ")); y(c) } }), e.length--), c.push({key: g, pb: k})); d[g] = !0 } }); return c } function k(b, d, k, f) { var h = a.a.f.get(b, r); if (!d) { if (h) throw Error("You cannot apply bindings multiple times to the same element."); a.a.f.set(b, r, !0) } !h && f && a.Eb(b, k); var l; if (d && "function" !== typeof d) l = d; else { var n = a.J.instance, m = n.getBindingAccessors || e, x = a.h(function () { (l = d ? d(k, b) : m.call(n, b, k)) && k.D && k.D(); return l }, null, {G: b}); l && x.ga() || (x = null) } var t; if (l) { var w = x ? function (a) { return function () { return c(x()[a]) } } : function (a) { return l[a] }, z = function () { return a.a.Oa(x ? x() : l, c) }; z.get = function (a) { return l[a] && c(w(a)) }; z.has = function (a) { return a in l }; f = g(l); a.a.r(f, function (c) { var d = c.pb.init, e = c.pb.update, g = c.key; if (8 === b.nodeType && !a.e.Q[g]) throw Error("The binding '" + g + "' cannot be used with virtual elements"); try { "function" == typeof d && a.k.t(function () { var a = d(b, w(g), z, k.$data, k); if (a && a.controlsDescendantBindings) { if (t !== p) throw Error("Multiple bindings (" + t + " and " + g + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element."); t = g } }), "function" == typeof e && a.h(function () { e(b, w(g), z, k.$data, k) }, null, {G: b}) } catch (f) { throw f.message = 'Unable to process binding "' + g + ": " + l[g] + '"\nMessage: ' + f.message, f; } }) } return {shouldBindDescendants: t === p} } function l(b) { return b && b instanceof a.I ? b : new a.I(b) } a.d = {}; var n = {script: !0}; a.getBindingHandler = function (b) { return a.d[b] }; a.I = function (b, c, d, e) { var g = this, k = "function" == typeof b && !a.v(b), f, h = a.h(function () { var f = k ? b() : b, l = a.a.c(f); c ? (c.D && c.D(), a.a.extend(g, c), h && (g.D = h)) : (g.$parents = [], g.$root = l, g.ko = a); g.$rawData = f; g.$data = l; d && (g[d] = l); e && e(g, c, l); return g.$data }, null, { Da: function () { return f && !a.a.eb(f) }, G: !0 }); h.ga() && (g.D = h, h.equalityComparer = null, f = [], h.Jb = function (b) { f.push(b); a.a.u.ja(b, function (b) { a.a.ma(f, b); f.length || (h.F(), g.D = h = p) }) }) }; a.I.prototype.createChildContext = function (b, c, d) { return new a.I(b, this, c, function (a, b) { a.$parentContext = b; a.$parent = b.$data; a.$parents = (b.$parents || []).slice(0); a.$parents.unshift(a.$parent); d && d(a) }) }; a.I.prototype.extend = function (b) { return new a.I(this.D || this.$data, this, null, function (c, d) { c.$rawData = d.$rawData; a.a.extend(c, "function" == typeof b ? b() : b) }) }; var r = a.a.f.L(), m = a.a.f.L(); a.Eb = function (b, c) { if (2 == arguments.length) a.a.f.set(b, m, c), c.D && c.D.Jb(b); else return a.a.f.get(b, m) }; a.xa = function (b, c, d) { 1 === b.nodeType && a.e.wb(b); return k(b, c, l(d), !0) }; a.Lb = function (c, e, g) { g = l(g); return a.xa(c, "function" === typeof e ? d(e.bind(null, g, c)) : a.a.Oa(e, b), g) }; a.gb = function (a, b) { 1 !== b.nodeType && 8 !== b.nodeType || f(l(a), b, !0) }; a.fb = function (a, b) { !t && A.jQuery && (t = A.jQuery); if (b && 1 !== b.nodeType && 8 !== b.nodeType) throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"); b = b || A.document.body; h(l(a), b, !0) }; a.Ca = function (b) { switch (b.nodeType) { case 1: case 8: var c = a.Eb(b); if (c) return c; if (b.parentNode) return a.Ca(b.parentNode) } return p }; a.Pb = function (b) { return (b = a.Ca(b)) ? b.$data : p }; a.b("bindingHandlers", a.d); a.b("applyBindings", a.fb); a.b("applyBindingsToDescendants", a.gb); a.b("applyBindingAccessorsToNode", a.xa); a.b("applyBindingsToNode", a.Lb); a.b("contextFor", a.Ca); a.b("dataFor", a.Pb) })(); var L = {"class": "className", "for": "htmlFor"}; a.d.attr = { update: function (b, c) { var d = a.a.c(c()) || {}; a.a.A(d, function (c, d) { d = a.a.c(d); var h = !1 === d || null === d || d === p; h && b.removeAttribute(c); 8 >= a.a.oa && c in L ? (c = L[c], h ? b.removeAttribute(c) : b[c] = d) : h || b.setAttribute(c, d.toString()); "name" === c && a.a.Cb(b, h ? "" : d.toString()) }) } }; (function () { a.d.checked = { after: ["value", "attr"], init: function (b, c, d) { function e() { return d.has("checkedValue") ? a.a.c(d.get("checkedValue")) : b.value } function f() { var g = b.checked, f = r ? e() : g; if (!a.ca.pa() && (!k || g)) { var h = a.k.t(c); l ? n !== f ? (g && (a.a.Y(h, f, !0), a.a.Y(h, n, !1)), n = f) : a.a.Y(h, f, g) : a.g.va(h, d, "checked", f, !0) } } function h() { var d = a.a.c(c()); b.checked = l ? 0 <= a.a.l(d, e()) : g ? d : e() === d } var g = "checkbox" == b.type, k = "radio" == b.type; if (g || k) { var l = g && a.a.c(c()) instanceof Array, n = l ? e() : p, r = k || l; k && !b.name && a.d.uniqueName.init(b, function () { return !0 }); a.ba(f, null, {G: b}); a.a.q(b, "click", f); a.ba(h, null, {G: b}) } } }; a.g.W.checked = !0; a.d.checkedValue = { update: function (b, c) { b.value = a.a.c(c()) } } })(); a.d.css = { update: function (b, c) { var d = a.a.c(c()); "object" == typeof d ? a.a.A(d, function (c, d) { d = a.a.c(d); a.a.ua(b, c, d) }) : (d = String(d || ""), a.a.ua(b, b.__ko__cssValue, !1), b.__ko__cssValue = d, a.a.ua(b, d, !0)) } }; a.d.enable = { update: function (b, c) { var d = a.a.c(c()); d && b.disabled ? b.removeAttribute("disabled") : d || b.disabled || (b.disabled = !0) } }; a.d.disable = { update: function (b, c) { a.d.enable.update(b, function () { return !a.a.c(c()) }) } }; a.d.event = { init: function (b, c, d, e, f) { var h = c() || {}; a.a.A(h, function (g) { "string" == typeof g && a.a.q(b, g, function (b) { var h, n = c()[g]; if (n) { try { var r = a.a.R(arguments); e = f.$data; r.unshift(e); h = n.apply(e, r) } finally { !0 !== h && (b.preventDefault ? b.preventDefault() : b.returnValue = !1) } !1 === d.get(g + "Bubble") && (b.cancelBubble = !0, b.stopPropagation && b.stopPropagation()) } }) }) } }; a.d.foreach = { vb: function (b) { return function () { var c = b(), d = a.a.Sa(c); if (!d || "number" == typeof d.length) return {foreach: c, templateEngine: a.K.Ja}; a.a.c(c); return { foreach: d.data, as: d.as, includeDestroyed: d.includeDestroyed, afterAdd: d.afterAdd, beforeRemove: d.beforeRemove, afterRender: d.afterRender, beforeMove: d.beforeMove, afterMove: d.afterMove, templateEngine: a.K.Ja } } }, init: function (b, c) { return a.d.template.init(b, a.d.foreach.vb(c)) }, update: function (b, c, d, e, f) { return a.d.template.update(b, a.d.foreach.vb(c), d, e, f) } }; a.g.aa.foreach = !1; a.e.Q.foreach = !0; a.d.hasfocus = { init: function (b, c, d) { function e(e) { b.__ko_hasfocusUpdating = !0; var k = b.ownerDocument; if ("activeElement" in k) { var f; try { f = k.activeElement } catch (h) { f = k.body } e = f === b } k = c(); a.g.va(k, d, "hasfocus", e, !0); b.__ko_hasfocusLastValue = e; b.__ko_hasfocusUpdating = !1 } var f = e.bind(null, !0), h = e.bind(null, !1); a.a.q(b, "focus", f); a.a.q(b, "focusin", f); a.a.q(b, "blur", h); a.a.q(b, "focusout", h) }, update: function (b, c) { var d = !!a.a.c(c()); b.__ko_hasfocusUpdating || b.__ko_hasfocusLastValue === d || (d ? b.focus() : b.blur(), a.k.t(a.a.ha, null, [b, d ? "focusin" : "focusout"])) } }; a.g.W.hasfocus = !0; a.d.hasFocus = a.d.hasfocus; a.g.W.hasFocus = !0; a.d.html = { init: function () { return {controlsDescendantBindings: !0} }, update: function (b, c) { a.a.Va(b, c()) } }; H("if"); H("ifnot", !1, !0); H("with", !0, !1, function (a, c) { return a.createChildContext(c) }); var J = {}; a.d.options = { init: function (b) { if ("select" !== a.a.B(b)) throw Error("options binding applies only to SELECT elements"); for (; 0 < b.length;) b.remove(0); return {controlsDescendantBindings: !0} }, update: function (b, c, d) { function e() { return a.a.la(b.options, function (a) { return a.selected }) } function f(a, b, c) { var d = typeof b; return "function" == d ? b(a) : "string" == d ? a[b] : c } function h(c, d) { if (r.length) { var e = 0 <= a.a.l(r, a.i.p(d[0])); a.a.Db(d[0], e); m && !e && a.k.t(a.a.ha, null, [b, "change"]) } } var g = 0 != b.length && b.multiple ? b.scrollTop : null, k = a.a.c(c()), l = d.get("optionsIncludeDestroyed"); c = {}; var n, r; r = b.multiple ? a.a.ya(e(), a.i.p) : 0 <= b.selectedIndex ? [a.i.p(b.options[b.selectedIndex])] : []; k && ("undefined" == typeof k.length && (k = [k]), n = a.a.la(k, function (b) { return l || b === p || null === b || !a.a.c(b._destroy) }), d.has("optionsCaption") && (k = a.a.c(d.get("optionsCaption")), null !== k && k !== p && n.unshift(J))); var m = !1; c.beforeRemove = function (a) { b.removeChild(a) }; k = h; d.has("optionsAfterRender") && (k = function (b, c) { h(0, c); a.k.t(d.get("optionsAfterRender"), null, [c[0], b !== J ? b : p]) }); a.a.Ua(b, n, function (c, e, g) { g.length && (r = g[0].selected ? [a.i.p(g[0])] : [], m = !0); e = b.ownerDocument.createElement("option"); c === J ? (a.a.Xa(e, d.get("optionsCaption")), a.i.X(e, p)) : (g = f(c, d.get("optionsValue"), c), a.i.X(e, a.a.c(g)), c = f(c, d.get("optionsText"), g), a.a.Xa(e, c)); return [e] }, c, k); a.k.t(function () { d.get("valueAllowUnset") && d.has("value") ? a.i.X(b, a.a.c(d.get("value")), !0) : (b.multiple ? r.length && e().length < r.length : r.length && 0 <= b.selectedIndex ? a.i.p(b.options[b.selectedIndex]) !== r[0] : r.length || 0 <= b.selectedIndex) && a.a.ha(b, "change") }); a.a.Tb(b); g && 20 < Math.abs(g - b.scrollTop) && (b.scrollTop = g) } }; a.d.options.Pa = a.a.f.L(); a.d.selectedOptions = { after: ["options", "foreach"], init: function (b, c, d) { a.a.q(b, "change", function () { var e = c(), f = []; a.a.r(b.getElementsByTagName("option"), function (b) { b.selected && f.push(a.i.p(b)) }); a.g.va(e, d, "selectedOptions", f) }) }, update: function (b, c) { if ("select" != a.a.B(b)) throw Error("values binding applies only to SELECT elements"); var d = a.a.c(c()); d && "number" == typeof d.length && a.a.r(b.getElementsByTagName("option"), function (b) { var c = 0 <= a.a.l(d, a.i.p(b)); a.a.Db(b, c) }) } }; a.g.W.selectedOptions = !0; a.d.style = { update: function (b, c) { var d = a.a.c(c() || {}); a.a.A(d, function (c, d) { d = a.a.c(d); b.style[c] = d || "" }) } }; a.d.submit = { init: function (b, c, d, e, f) { if ("function" != typeof c()) throw Error("The value for a submit binding must be a function"); a.a.q(b, "submit", function (a) { var d, e = c(); try { d = e.call(f.$data, b) } finally { !0 !== d && (a.preventDefault ? a.preventDefault() : a.returnValue = !1) } }) } }; a.d.text = { init: function () { return {controlsDescendantBindings: !0} }, update: function (b, c) { a.a.Xa(b, c()) } }; a.e.Q.text = !0; a.d.uniqueName = { init: function (b, c) { if (c()) { var d = "ko_unique_" + ++a.d.uniqueName.Ob; a.a.Cb(b, d) } } }; a.d.uniqueName.Ob = 0; a.d.value = { after: ["options", "foreach"], init: function (b, c, d) { function e() { g = !1; var e = c(), f = a.i.p(b); a.g.va(e, d, "value", f) } var f = ["change"], h = d.get("valueUpdate"), g = !1; h && ("string" == typeof h && (h = [h]), a.a.$(f, h), f = a.a.ib(f)); !a.a.oa || "input" != b.tagName.toLowerCase() || "text" != b.type || "off" == b.autocomplete || b.form && "off" == b.form.autocomplete || -1 != a.a.l(f, "propertychange") || (a.a.q(b, "propertychange", function () { g = !0 }), a.a.q(b, "focus", function () { g = !1 }), a.a.q(b, "blur", function () { g && e() })); a.a.r(f, function (c) { var d = e; a.a.kc(c, "after") && (d = function () { setTimeout(e, 0) }, c = c.substring(5)); a.a.q(b, c, d) }) }, update: function (b, c, d) { var e = a.a.c(c()); c = a.i.p(b); if (e !== c) if ("select" === a.a.B(b)) { var f = d.get("valueAllowUnset"); d = function () { a.i.X(b, e, f) }; d(); f || e === a.i.p(b) ? setTimeout(d, 0) : a.k.t(a.a.ha, null, [b, "change"]) } else a.i.X(b, e) } }; a.g.W.value = !0; a.d.visible = { update: function (b, c) { var d = a.a.c(c()), e = "none" != b.style.display; d && !e ? b.style.display = "" : !d && e && (b.style.display = "none") } }; (function (b) { a.d[b] = { init: function (c, d, e, f, h) { return a.d.event.init.call(this, c, function () { var a = {}; a[b] = d(); return a }, e, f, h) } } })("click"); a.C = function () { }; a.C.prototype.renderTemplateSource = function () { throw Error("Override renderTemplateSource"); }; a.C.prototype.createJavaScriptEvaluatorBlock = function () { throw Error("Override createJavaScriptEvaluatorBlock"); }; a.C.prototype.makeTemplateSource = function (b, c) { if ("string" == typeof b) { c = c || w; var d = c.getElementById(b); if (!d) throw Error("Cannot find template with ID " + b); return new a.n.j(d) } if (1 == b.nodeType || 8 == b.nodeType) return new a.n.Z(b); throw Error("Unknown template type: " + b); }; a.C.prototype.renderTemplate = function (a, c, d, e) { a = this.makeTemplateSource(a, e); return this.renderTemplateSource(a, c, d) }; a.C.prototype.isTemplateRewritten = function (a, c) { return !1 === this.allowTemplateRewriting ? !0 : this.makeTemplateSource(a, c).data("isRewritten") }; a.C.prototype.rewriteTemplate = function (a, c, d) { a = this.makeTemplateSource(a, d); c = c(a.text()); a.text(c); a.data("isRewritten", !0) }; a.b("templateEngine", a.C); a.Za = function () { function b(b, c, d, g) { b = a.g.Ra(b); for (var k = a.g.aa, l = 0; l < b.length; l++) { var n = b[l].key; if (k.hasOwnProperty(n)) { var r = k[n]; if ("function" === typeof r) { if (n = r(b[l].value)) throw Error(n); } else if (!r) throw Error("This template engine does not support the '" + n + "' binding within its templates"); } } d = "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + a.g.qa(b, {valueAccessors: !0}) + " } })()},'" + d.toLowerCase() + "')"; return g.createJavaScriptEvaluatorBlock(d) + c } var c = /(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi, d = /\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g; return { Ub: function (b, c, d) { c.isTemplateRewritten(b, d) || c.rewriteTemplate(b, function (b) { return a.Za.dc(b, c) }, d) }, dc: function (a, f) { return a.replace(c, function (a, c, d, e, n) { return b(n, c, d, f) }).replace(d, function (a, c) { return b(c, "\x3c!-- ko --\x3e", "#comment", f) }) }, Mb: function (b, c) { return a.w.Na(function (d, g) { var k = d.nextSibling; k && k.nodeName.toLowerCase() === c && a.xa(k, b, g) }) } } }(); a.b("__tr_ambtns", a.Za.Mb); (function () { a.n = {}; a.n.j = function (a) { this.j = a }; a.n.j.prototype.text = function () { var b = a.a.B(this.j), b = "script" === b ? "text" : "textarea" === b ? "value" : "innerHTML"; if (0 == arguments.length) return this.j[b]; var c = arguments[0]; "innerHTML" === b ? a.a.Va(this.j, c) : this.j[b] = c }; var b = a.a.f.L() + "_"; a.n.j.prototype.data = function (c) { if (1 === arguments.length) return a.a.f.get(this.j, b + c); a.a.f.set(this.j, b + c, arguments[1]) }; var c = a.a.f.L(); a.n.Z = function (a) { this.j = a }; a.n.Z.prototype = new a.n.j; a.n.Z.prototype.text = function () { if (0 == arguments.length) { var b = a.a.f.get(this.j, c) || {}; b.$a === p && b.Ba && (b.$a = b.Ba.innerHTML); return b.$a } a.a.f.set(this.j, c, {$a: arguments[0]}) }; a.n.j.prototype.nodes = function () { if (0 == arguments.length) return (a.a.f.get(this.j, c) || {}).Ba; a.a.f.set(this.j, c, {Ba: arguments[0]}) }; a.b("templateSources", a.n); a.b("templateSources.domElement", a.n.j); a.b("templateSources.anonymousTemplate", a.n.Z) })(); (function () { function b(b, c, d) { var e; for (c = a.e.nextSibling(c); b && (e = b) !== c;) b = a.e.nextSibling(e), d(e, b) } function c(c, d) { if (c.length) { var e = c[0], f = c[c.length - 1], h = e.parentNode, m = a.J.instance, q = m.preprocessNode; if (q) { b(e, f, function (a, b) { var c = a.previousSibling, d = q.call(m, a); d && (a === e && (e = d[0] || b), a === f && (f = d[d.length - 1] || c)) }); c.length = 0; if (!e) return; e === f ? c.push(e) : (c.push(e, f), a.a.ea(c, h)) } b(e, f, function (b) { 1 !== b.nodeType && 8 !== b.nodeType || a.fb(d, b) }); b(e, f, function (b) { 1 !== b.nodeType && 8 !== b.nodeType || a.w.Ib(b, [d]) }); a.a.ea(c, h) } } function d(a) { return a.nodeType ? a : 0 < a.length ? a[0] : null } function e(b, e, h, n, r) { r = r || {}; var m = b && d(b), m = m && m.ownerDocument, q = r.templateEngine || f; a.Za.Ub(h, q, m); h = q.renderTemplate(h, n, r, m); if ("number" != typeof h.length || 0 < h.length && "number" != typeof h[0].nodeType) throw Error("Template engine must return an array of DOM nodes"); m = !1; switch (e) { case "replaceChildren": a.e.U(b, h); m = !0; break; case "replaceNode": a.a.Bb(b, h); m = !0; break; case "ignoreTargetNode": break; default: throw Error("Unknown renderMode: " + e); } m && (c(h, n), r.afterRender && a.k.t(r.afterRender, null, [h, n.$data])); return h } var f; a.Wa = function (b) { if (b != p && !(b instanceof a.C)) throw Error("templateEngine must inherit from ko.templateEngine"); f = b }; a.Ta = function (b, c, h, n, r) { h = h || {}; if ((h.templateEngine || f) == p) throw Error("Set a template engine before calling renderTemplate"); r = r || "replaceChildren"; if (n) { var m = d(n); return a.h(function () { var f = c && c instanceof a.I ? c : new a.I(a.a.c(c)), p = a.v(b) ? b() : "function" == typeof b ? b(f.$data, f) : b, f = e(n, r, p, f, h); "replaceNode" == r && (n = f, m = d(n)) }, null, { Da: function () { return !m || !a.a.Ea(m) }, G: m && "replaceNode" == r ? m.parentNode : m }) } return a.w.Na(function (d) { a.Ta(b, c, h, d, "replaceNode") }) }; a.jc = function (b, d, f, h, r) { function m(a, b) { c(b, s); f.afterRender && f.afterRender(b, a) } function q(a, c) { s = r.createChildContext(a, f.as, function (a) { a.$index = c }); var d = "function" == typeof b ? b(a, s) : b; return e(null, "ignoreTargetNode", d, s, f) } var s; return a.h(function () { var b = a.a.c(d) || []; "undefined" == typeof b.length && (b = [b]); b = a.a.la(b, function (b) { return f.includeDestroyed || b === p || null === b || !a.a.c(b._destroy) }); a.k.t(a.a.Ua, null, [h, b, q, f, m]) }, null, {G: h}) }; var h = a.a.f.L(); a.d.template = { init: function (b, c) { var d = a.a.c(c()); "string" == typeof d || d.name ? a.e.da(b) : (d = a.e.childNodes(b), d = a.a.ec(d), (new a.n.Z(b)).nodes(d)); return {controlsDescendantBindings: !0} }, update: function (b, c, d, e, f) { var m = c(), q; c = a.a.c(m); d = !0; e = null; "string" == typeof c ? c = {} : (m = c.name, "if" in c && (d = a.a.c(c["if"])), d && "ifnot" in c && (d = !a.a.c(c.ifnot)), q = a.a.c(c.data)); "foreach" in c ? e = a.jc(m || b, d && c.foreach || [], c, b, f) : d ? (f = "data" in c ? f.createChildContext(q, c.as) : f, e = a.Ta(m || b, f, c, b)) : a.e.da(b); f = e; (q = a.a.f.get(b, h)) && "function" == typeof q.F && q.F(); a.a.f.set(b, h, f && f.ga() ? f : p) } }; a.g.aa.template = function (b) { b = a.g.Ra(b); return 1 == b.length && b[0].unknown || a.g.bc(b, "name") ? null : "This template engine does not support anonymous templates nested within its templates" }; a.e.Q.template = !0 })(); a.b("setTemplateEngine", a.Wa); a.b("renderTemplate", a.Ta); a.a.nb = function (a, c, d) { if (a.length && c.length) { var e, f, h, g, k; for (e = f = 0; (!d || e < d) && (g = a[f]); ++f) { for (h = 0; k = c[h]; ++h) if (g.value === k.value) { g.moved = k.index; k.moved = g.index; c.splice(h, 1); e = h = 0; break } e += h } } }; a.a.Aa = function () { function b(b, d, e, f, h) { var g = Math.min, k = Math.max, l = [], n, p = b.length, m, q = d.length, s = q - p || 1, t = p + q + 1, u, w, y; for (n = 0; n <= p; n++) for (w = u, l.push(u = []), y = g(q, n + s), m = k(0, n - 1); m <= y; m++) u[m] = m ? n ? b[n - 1] === d[m - 1] ? w[m - 1] : g(w[m] || t, u[m - 1] || t) + 1 : m + 1 : n + 1; g = []; k = []; s = []; n = p; for (m = q; n || m;) q = l[n][m] - 1, m && q === l[n][m - 1] ? k.push(g[g.length] = { status: e, value: d[--m], index: m }) : n && q === l[n - 1][m] ? s.push(g[g.length] = { status: f, value: b[--n], index: n }) : (--m, --n, h.sparse || g.push({status: "retained", value: d[m]})); a.a.nb(k, s, 10 * p); return g.reverse() } return function (a, d, e) { e = "boolean" === typeof e ? {dontLimitMoves: e} : e || {}; a = a || []; d = d || []; return a.length <= d.length ? b(a, d, "added", "deleted", e) : b(d, a, "deleted", "added", e) } }(); a.b("utils.compareArrays", a.a.Aa); (function () { function b(b, c, f, h, g) { var k = [], l = a.h(function () { var l = c(f, g, a.a.ea(k, b)) || []; 0 < k.length && (a.a.Bb(k, l), h && a.k.t(h, null, [f, l, g])); k.length = 0; a.a.$(k, l) }, null, { G: b, Da: function () { return !a.a.eb(k) } }); return {S: k, h: l.ga() ? l : p} } var c = a.a.f.L(); a.a.Ua = function (d, e, f, h, g) { function k(b, c) { v = r[c]; u !== c && (z[b] = v); v.Ia(u++); a.a.ea(v.S, d); s.push(v); y.push(v) } function l(b, c) { if (b) for (var d = 0, e = c.length; d < e; d++) c[d] && a.a.r(c[d].S, function (a) { b(a, d, c[d].ka) }) } e = e || []; h = h || {}; var n = a.a.f.get(d, c) === p, r = a.a.f.get(d, c) || [], m = a.a.ya(r, function (a) { return a.ka }), q = a.a.Aa(m, e, h.dontLimitMoves), s = [], t = 0, u = 0, w = [], y = []; e = []; for (var z = [], m = [], v, x = 0, A, C; A = q[x]; x++) switch (C = A.moved, A.status) { case "deleted": C === p && (v = r[t], v.h && v.h.F(), w.push.apply(w, a.a.ea(v.S, d)), h.beforeRemove && (e[x] = v, y.push(v))); t++; break; case "retained": k(x, t++); break; case "added": C !== p ? k(x, C) : (v = {ka: A.value, Ia: a.m(u++)}, s.push(v), y.push(v), n || (m[x] = v)) } l(h.beforeMove, z); a.a.r(w, h.beforeRemove ? a.M : a.removeNode); for (var x = 0, n = a.e.firstChild(d), E; v = y[x]; x++) { v.S || a.a.extend(v, b(d, f, v.ka, g, v.Ia)); for (t = 0; q = v.S[t]; n = q.nextSibling, E = q, t++) q !== n && a.e.rb(d, q, E); !v.Zb && g && (g(v.ka, v.S, v.Ia), v.Zb = !0) } l(h.beforeRemove, e); l(h.afterMove, z); l(h.afterAdd, m); a.a.f.set(d, c, s) } })(); a.b("utils.setDomNodeChildrenFromArrayMapping", a.a.Ua); a.K = function () { this.allowTemplateRewriting = !1 }; a.K.prototype = new a.C; a.K.prototype.renderTemplateSource = function (b) { var c = (9 > a.a.oa ? 0 : b.nodes) ? b.nodes() : null; if (c) return a.a.R(c.cloneNode(!0).childNodes); b = b.text(); return a.a.Qa(b) }; a.K.Ja = new a.K; a.Wa(a.K.Ja); a.b("nativeTemplateEngine", a.K); (function () { a.La = function () { var a = this.ac = function () { if (!t || !t.tmpl) return 0; try { if (0 <= t.tmpl.tag.tmpl.open.toString().indexOf("__")) return 2 } catch (a) { } return 1 }(); this.renderTemplateSource = function (b, e, f) { f = f || {}; if (2 > a) throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."); var h = b.data("precompiled"); h || (h = b.text() || "", h = t.template(null, "{{ko_with $item.koBindingContext}}" + h + "{{/ko_with}}"), b.data("precompiled", h)); b = [e.$data]; e = t.extend({koBindingContext: e}, f.templateOptions); e = t.tmpl(h, b, e); e.appendTo(w.createElement("div")); t.fragments = {}; return e }; this.createJavaScriptEvaluatorBlock = function (a) { return "{{ko_code ((function() { return " + a + " })()) }}" }; this.addTemplate = function (a, b) { w.write("<script type='text/html' id='" + a + "'>" + b + "\x3c/script>") }; 0 < a && (t.tmpl.tag.ko_code = {open: "__.push($1 || '');"}, t.tmpl.tag.ko_with = { open: "with($1) {", close: "} " }) }; a.La.prototype = new a.C; var b = new a.La; 0 < b.ac && a.Wa(b); a.b("jqueryTmplTemplateEngine", a.La) })() }) })(); })(); </script> <!-- Three.js (3d canvas engine) --> <!--script type="text/javascript" src="http://cdn.jsdelivr.net/threejs/r62/three.js"></script--> <!--script type="text/javascript" src="http://cdn.strategiqcommerce.com/ajax/libs/three.js/r57/three.min.js"></script>--> <!--script type="text/javascript" src="http://www.rootcdn.com/libs/three.js/r57/three.min.js"></script>--> <script type="text/javascript">// three.js - http://github.com/mrdoob/three.js 'use strict'; var THREE = THREE || {REVISION: "57"}; self.console = self.console || { info: function () { }, log: function () { }, debug: function () { }, warn: function () { }, error: function () { } }; self.Int32Array = self.Int32Array || Array; self.Float32Array = self.Float32Array || Array; String.prototype.trim = String.prototype.trim || function () { return this.replace(/^\s+|\s+$/g, "") }; THREE.extend = function (a, b) { if (Object.keys) for (var c = Object.keys(b), d = 0, e = c.length; d < e; d++) { var f = c[d]; Object.defineProperty(a, f, Object.getOwnPropertyDescriptor(b, f)) } else for (f in c = {}.hasOwnProperty, b) c.call(b, f) && (a[f] = b[f]); return a }; (function () { for (var a = 0, b = ["ms", "moz", "webkit", "o"], c = 0; c < b.length && !window.requestAnimationFrame; ++c) window.requestAnimationFrame = window[b[c] + "RequestAnimationFrame"], window.cancelAnimationFrame = window[b[c] + "CancelAnimationFrame"] || window[b[c] + "CancelRequestAnimationFrame"]; void 0 === window.requestAnimationFrame && (window.requestAnimationFrame = function (b) { var c = Date.now(), f = Math.max(0, 16 - (c - a)), g = window.setTimeout(function () { b(c + f) }, f); a = c + f; return g }); window.cancelAnimationFrame = window.cancelAnimationFrame || function (a) { window.clearTimeout(a) } })(); THREE.CullFaceNone = 0; THREE.CullFaceBack = 1; THREE.CullFaceFront = 2; THREE.CullFaceFrontBack = 3; THREE.FrontFaceDirectionCW = 0; THREE.FrontFaceDirectionCCW = 1; THREE.BasicShadowMap = 0; THREE.PCFShadowMap = 1; THREE.PCFSoftShadowMap = 2; THREE.FrontSide = 0; THREE.BackSide = 1; THREE.DoubleSide = 2; THREE.NoShading = 0; THREE.FlatShading = 1; THREE.SmoothShading = 2; THREE.NoColors = 0; THREE.FaceColors = 1; THREE.VertexColors = 2; THREE.NoBlending = 0; THREE.NormalBlending = 1; THREE.AdditiveBlending = 2; THREE.SubtractiveBlending = 3; THREE.MultiplyBlending = 4; THREE.CustomBlending = 5; THREE.AddEquation = 100; THREE.SubtractEquation = 101; THREE.ReverseSubtractEquation = 102; THREE.ZeroFactor = 200; THREE.OneFactor = 201; THREE.SrcColorFactor = 202; THREE.OneMinusSrcColorFactor = 203; THREE.SrcAlphaFactor = 204; THREE.OneMinusSrcAlphaFactor = 205; THREE.DstAlphaFactor = 206; THREE.OneMinusDstAlphaFactor = 207; THREE.DstColorFactor = 208; THREE.OneMinusDstColorFactor = 209; THREE.SrcAlphaSaturateFactor = 210; THREE.MultiplyOperation = 0; THREE.MixOperation = 1; THREE.AddOperation = 2; THREE.UVMapping = function () { }; THREE.CubeReflectionMapping = function () { }; THREE.CubeRefractionMapping = function () { }; THREE.SphericalReflectionMapping = function () { }; THREE.SphericalRefractionMapping = function () { }; THREE.RepeatWrapping = 1E3; THREE.ClampToEdgeWrapping = 1001; THREE.MirroredRepeatWrapping = 1002; THREE.NearestFilter = 1003; THREE.NearestMipMapNearestFilter = 1004; THREE.NearestMipMapLinearFilter = 1005; THREE.LinearFilter = 1006; THREE.LinearMipMapNearestFilter = 1007; THREE.LinearMipMapLinearFilter = 1008; THREE.UnsignedByteType = 1009; THREE.ByteType = 1010; THREE.ShortType = 1011; THREE.UnsignedShortType = 1012; THREE.IntType = 1013; THREE.UnsignedIntType = 1014; THREE.FloatType = 1015; THREE.UnsignedShort4444Type = 1016; THREE.UnsignedShort5551Type = 1017; THREE.UnsignedShort565Type = 1018; THREE.AlphaFormat = 1019; THREE.RGBFormat = 1020; THREE.RGBAFormat = 1021; THREE.LuminanceFormat = 1022; THREE.LuminanceAlphaFormat = 1023; THREE.RGB_S3TC_DXT1_Format = 2001; THREE.RGBA_S3TC_DXT1_Format = 2002; THREE.RGBA_S3TC_DXT3_Format = 2003; THREE.RGBA_S3TC_DXT5_Format = 2004; THREE.Color = function (a) { void 0 !== a && this.set(a); return this }; THREE.Color.prototype = { constructor: THREE.Color, r: 1, g: 1, b: 1, set: function (a) { switch (typeof a) { case "number": this.setHex(a); break; case "string": this.setStyle(a) } }, setHex: function (a) { a = Math.floor(a); this.r = (a >> 16 & 255) / 255; this.g = (a >> 8 & 255) / 255; this.b = (a & 255) / 255; return this }, setRGB: function (a, b, c) { this.r = a; this.g = b; this.b = c; return this }, setHSL: function (a, b, c) { if (0 === b) this.r = this.g = this.b = c; else { var d = function (a, b, c) { 0 > c && (c += 1); 1 < c && (c -= 1); return c < 1 / 6 ? a + 6 * (b - a) * c : 0.5 > c ? b : c < 2 / 3 ? a + 6 * (b - a) * (2 / 3 - c) : a }, b = 0.5 >= c ? c * (1 + b) : c + b - c * b, c = 2 * c - b; this.r = d(c, b, a + 1 / 3); this.g = d(c, b, a); this.b = d(c, b, a - 1 / 3) } return this }, setStyle: function (a) { if (/^rgb\((\d+),(\d+),(\d+)\)$/i.test(a)) return a = /^rgb\((\d+),(\d+),(\d+)\)$/i.exec(a), this.r = Math.min(255, parseInt(a[1], 10)) / 255, this.g = Math.min(255, parseInt(a[2], 10)) / 255, this.b = Math.min(255, parseInt(a[3], 10)) / 255, this; if (/^rgb\((\d+)\%,(\d+)\%,(\d+)\%\)$/i.test(a)) return a = /^rgb\((\d+)\%,(\d+)\%,(\d+)\%\)$/i.exec(a), this.r = Math.min(100, parseInt(a[1], 10)) / 100, this.g = Math.min(100, parseInt(a[2], 10)) / 100, this.b = Math.min(100, parseInt(a[3], 10)) / 100, this; if (/^\#([0-9a-f]{6})$/i.test(a)) return a = /^\#([0-9a-f]{6})$/i.exec(a), this.setHex(parseInt(a[1], 16)), this; if (/^\#([0-9a-f])([0-9a-f])([0-9a-f])$/i.test(a)) return a = /^\#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a), this.setHex(parseInt(a[1] + a[1] + a[2] + a[2] + a[3] + a[3], 16)), this; if (/^(\w+)$/i.test(a)) return this.setHex(THREE.ColorKeywords[a]), this }, copy: function (a) { this.r = a.r; this.g = a.g; this.b = a.b; return this }, copyGammaToLinear: function (a) { this.r = a.r * a.r; this.g = a.g * a.g; this.b = a.b * a.b; return this }, copyLinearToGamma: function (a) { this.r = Math.sqrt(a.r); this.g = Math.sqrt(a.g); this.b = Math.sqrt(a.b); return this }, convertGammaToLinear: function () { var a = this.r, b = this.g, c = this.b; this.r = a * a; this.g = b * b; this.b = c * c; return this }, convertLinearToGamma: function () { this.r = Math.sqrt(this.r); this.g = Math.sqrt(this.g); this.b = Math.sqrt(this.b); return this }, getHex: function () { return 255 * this.r << 16 ^ 255 * this.g << 8 ^ 255 * this.b << 0 }, getHexString: function () { return ("000000" + this.getHex().toString(16)).slice(-6) }, getHSL: function () { var a = {h: 0, s: 0, l: 0}; return function () { var b = this.r, c = this.g, d = this.b, e = Math.max(b, c, d), f = Math.min(b, c, d), g, h = (f + e) / 2; if (f === e) f = g = 0; else { var i = e - f, f = 0.5 >= h ? i / (e + f) : i / (2 - e - f); switch (e) { case b: g = (c - d) / i + (c < d ? 6 : 0); break; case c: g = (d - b) / i + 2; break; case d: g = (b - c) / i + 4 } g /= 6 } a.h = g; a.s = f; a.l = h; return a } }(), getStyle: function () { return "rgb(" + (255 * this.r | 0) + "," + (255 * this.g | 0) + "," + (255 * this.b | 0) + ")" }, offsetHSL: function (a, b, c) { var d = this.getHSL(); d.h += a; d.s += b; d.l += c; this.setHSL(d.h, d.s, d.l); return this }, add: function (a) { this.r += a.r; this.g += a.g; this.b += a.b; return this }, addColors: function (a, b) { this.r = a.r + b.r; this.g = a.g + b.g; this.b = a.b + b.b; return this }, addScalar: function (a) { this.r += a; this.g += a; this.b += a; return this }, multiply: function (a) { this.r *= a.r; this.g *= a.g; this.b *= a.b; return this }, multiplyScalar: function (a) { this.r *= a; this.g *= a; this.b *= a; return this }, lerp: function (a, b) { this.r += (a.r - this.r) * b; this.g += (a.g - this.g) * b; this.b += (a.b - this.b) * b; return this }, equals: function (a) { return a.r === this.r && a.g === this.g && a.b === this.b }, clone: function () { return (new THREE.Color).setRGB(this.r, this.g, this.b) } }; THREE.ColorKeywords = { aliceblue: 15792383, antiquewhite: 16444375, aqua: 65535, aquamarine: 8388564, azure: 15794175, beige: 16119260, bisque: 16770244, black: 0, blanchedalmond: 16772045, blue: 255, blueviolet: 9055202, brown: 10824234, burlywood: 14596231, cadetblue: 6266528, chartreuse: 8388352, chocolate: 13789470, coral: 16744272, cornflowerblue: 6591981, cornsilk: 16775388, crimson: 14423100, cyan: 65535, darkblue: 139, darkcyan: 35723, darkgoldenrod: 12092939, darkgray: 11119017, darkgreen: 25600, darkgrey: 11119017, darkkhaki: 12433259, darkmagenta: 9109643, darkolivegreen: 5597999, darkorange: 16747520, darkorchid: 10040012, darkred: 9109504, darksalmon: 15308410, darkseagreen: 9419919, darkslateblue: 4734347, darkslategray: 3100495, darkslategrey: 3100495, darkturquoise: 52945, darkviolet: 9699539, deeppink: 16716947, deepskyblue: 49151, dimgray: 6908265, dimgrey: 6908265, dodgerblue: 2003199, firebrick: 11674146, floralwhite: 16775920, forestgreen: 2263842, fuchsia: 16711935, gainsboro: 14474460, ghostwhite: 16316671, gold: 16766720, goldenrod: 14329120, gray: 8421504, green: 32768, greenyellow: 11403055, grey: 8421504, honeydew: 15794160, hotpink: 16738740, indianred: 13458524, indigo: 4915330, ivory: 16777200, khaki: 15787660, lavender: 15132410, lavenderblush: 16773365, lawngreen: 8190976, lemonchiffon: 16775885, lightblue: 11393254, lightcoral: 15761536, lightcyan: 14745599, lightgoldenrodyellow: 16448210, lightgray: 13882323, lightgreen: 9498256, lightgrey: 13882323, lightpink: 16758465, lightsalmon: 16752762, lightseagreen: 2142890, lightskyblue: 8900346, lightslategray: 7833753, lightslategrey: 7833753, lightsteelblue: 11584734, lightyellow: 16777184, lime: 65280, limegreen: 3329330, linen: 16445670, magenta: 16711935, maroon: 8388608, mediumaquamarine: 6737322, mediumblue: 205, mediumorchid: 12211667, mediumpurple: 9662683, mediumseagreen: 3978097, mediumslateblue: 8087790, mediumspringgreen: 64154, mediumturquoise: 4772300, mediumvioletred: 13047173, midnightblue: 1644912, mintcream: 16121850, mistyrose: 16770273, moccasin: 16770229, navajowhite: 16768685, navy: 128, oldlace: 16643558, olive: 8421376, olivedrab: 7048739, orange: 16753920, orangered: 16729344, orchid: 14315734, palegoldenrod: 15657130, palegreen: 10025880, paleturquoise: 11529966, palevioletred: 14381203, papayawhip: 16773077, peachpuff: 16767673, peru: 13468991, pink: 16761035, plum: 14524637, powderblue: 11591910, purple: 8388736, red: 16711680, rosybrown: 12357519, royalblue: 4286945, saddlebrown: 9127187, salmon: 16416882, sandybrown: 16032864, seagreen: 3050327, seashell: 16774638, sienna: 10506797, silver: 12632256, skyblue: 8900331, slateblue: 6970061, slategray: 7372944, slategrey: 7372944, snow: 16775930, springgreen: 65407, steelblue: 4620980, tan: 13808780, teal: 32896, thistle: 14204888, tomato: 16737095, turquoise: 4251856, violet: 15631086, wheat: 16113331, white: 16777215, whitesmoke: 16119285, yellow: 16776960, yellowgreen: 10145074 }; THREE.Quaternion = function (a, b, c, d) { this.x = a || 0; this.y = b || 0; this.z = c || 0; this.w = void 0 !== d ? d : 1 }; THREE.Quaternion.prototype = { constructor: THREE.Quaternion, set: function (a, b, c, d) { this.x = a; this.y = b; this.z = c; this.w = d; return this }, copy: function (a) { this.x = a.x; this.y = a.y; this.z = a.z; this.w = a.w; return this }, setFromEuler: function (a, b) { var c = Math.cos(a.x / 2), d = Math.cos(a.y / 2), e = Math.cos(a.z / 2), f = Math.sin(a.x / 2), g = Math.sin(a.y / 2), h = Math.sin(a.z / 2); void 0 === b || "XYZ" === b ? (this.x = f * d * e + c * g * h, this.y = c * g * e - f * d * h, this.z = c * d * h + f * g * e, this.w = c * d * e - f * g * h) : "YXZ" === b ? (this.x = f * d * e + c * g * h, this.y = c * g * e - f * d * h, this.z = c * d * h - f * g * e, this.w = c * d * e + f * g * h) : "ZXY" === b ? (this.x = f * d * e - c * g * h, this.y = c * g * e + f * d * h, this.z = c * d * h + f * g * e, this.w = c * d * e - f * g * h) : "ZYX" === b ? (this.x = f * d * e - c * g * h, this.y = c * g * e + f * d * h, this.z = c * d * h - f * g * e, this.w = c * d * e + f * g * h) : "YZX" === b ? (this.x = f * d * e + c * g * h, this.y = c * g * e + f * d * h, this.z = c * d * h - f * g * e, this.w = c * d * e - f * g * h) : "XZY" === b && (this.x = f * d * e - c * g * h, this.y = c * g * e - f * d * h, this.z = c * d * h + f * g * e, this.w = c * d * e + f * g * h); return this }, setFromAxisAngle: function (a, b) { var c = b / 2, d = Math.sin(c); this.x = a.x * d; this.y = a.y * d; this.z = a.z * d; this.w = Math.cos(c); return this }, setFromRotationMatrix: function (a) { var b = a.elements, c = b[0], a = b[4], d = b[8], e = b[1], f = b[5], g = b[9], h = b[2], i = b[6], b = b[10], k = c + f + b; 0 < k ? (c = 0.5 / Math.sqrt(k + 1), this.w = 0.25 / c, this.x = (i - g) * c, this.y = (d - h) * c, this.z = (e - a) * c) : c > f && c > b ? (c = 2 * Math.sqrt(1 + c - f - b), this.w = (i - g) / c, this.x = 0.25 * c, this.y = (a + e) / c, this.z = (d + h) / c) : f > b ? (c = 2 * Math.sqrt(1 + f - c - b), this.w = (d - h) / c, this.x = (a + e) / c, this.y = 0.25 * c, this.z = (g + i) / c) : (c = 2 * Math.sqrt(1 + b - c - f), this.w = (e - a) / c, this.x = (d + h) / c, this.y = (g + i) / c, this.z = 0.25 * c); return this }, inverse: function () { this.conjugate().normalize(); return this }, conjugate: function () { this.x *= -1; this.y *= -1; this.z *= -1; return this }, lengthSq: function () { return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w) }, normalize: function () { var a = this.length(); 0 === a ? (this.z = this.y = this.x = 0, this.w = 1) : (a = 1 / a, this.x *= a, this.y *= a, this.z *= a, this.w *= a); return this }, multiply: function (a, b) { return void 0 !== b ? (console.warn("DEPRECATED: Quaternion's .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."), this.multiplyQuaternions(a, b)) : this.multiplyQuaternions(this, a) }, multiplyQuaternions: function (a, b) { var c = a.x, d = a.y, e = a.z, f = a.w, g = b.x, h = b.y, i = b.z, k = b.w; this.x = c * k + f * g + d * i - e * h; this.y = d * k + f * h + e * g - c * i; this.z = e * k + f * i + c * h - d * g; this.w = f * k - c * g - d * h - e * i; return this }, multiplyVector3: function (a) { console.warn("DEPRECATED: Quaternion's .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead."); return a.applyQuaternion(this) }, slerp: function (a, b) { var c = this.x, d = this.y, e = this.z, f = this.w, g = f * a.w + c * a.x + d * a.y + e * a.z; 0 > g ? (this.w = -a.w, this.x = -a.x, this.y = -a.y, this.z = -a.z, g = -g) : this.copy(a); if (1 <= g) return this.w = f, this.x = c, this.y = d, this.z = e, this; var h = Math.acos(g), i = Math.sqrt(1 - g * g); if (0.001 > Math.abs(i)) return this.w = 0.5 * (f + this.w), this.x = 0.5 * (c + this.x), this.y = 0.5 * (d + this.y), this.z = 0.5 * (e + this.z), this; g = Math.sin((1 - b) * h) / i; h = Math.sin(b * h) / i; this.w = f * g + this.w * h; this.x = c * g + this.x * h; this.y = d * g + this.y * h; this.z = e * g + this.z * h; return this }, equals: function (a) { return a.x === this.x && a.y === this.y && a.z === this.z && a.w === this.w }, clone: function () { return new THREE.Quaternion(this.x, this.y, this.z, this.w) } }; THREE.Quaternion.slerp = function (a, b, c, d) { return c.copy(a).slerp(b, d) }; THREE.Vector2 = function (a, b) { this.x = a || 0; this.y = b || 0 }; THREE.Vector2.prototype = { constructor: THREE.Vector2, set: function (a, b) { this.x = a; this.y = b; return this }, setX: function (a) { this.x = a; return this }, setY: function (a) { this.y = a; return this }, setComponent: function (a, b) { switch (a) { case 0: this.x = b; break; case 1: this.y = b; break; default: throw Error("index is out of range: " + a); } }, getComponent: function (a) { switch (a) { case 0: return this.x; case 1: return this.y; default: throw Error("index is out of range: " + a); } }, copy: function (a) { this.x = a.x; this.y = a.y; return this }, add: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector2's .add() now only accepts one argument. Use .addVectors( a, b ) instead."), this.addVectors(a, b); this.x += a.x; this.y += a.y; return this }, addVectors: function (a, b) { this.x = a.x + b.x; this.y = a.y + b.y; return this }, addScalar: function (a) { this.x += a; this.y += a; return this }, sub: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector2's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."), this.subVectors(a, b); this.x -= a.x; this.y -= a.y; return this }, subVectors: function (a, b) { this.x = a.x - b.x; this.y = a.y - b.y; return this }, multiplyScalar: function (a) { this.x *= a; this.y *= a; return this }, divideScalar: function (a) { 0 !== a ? (this.x /= a, this.y /= a) : this.set(0, 0); return this }, min: function (a) { this.x > a.x && (this.x = a.x); this.y > a.y && (this.y = a.y); return this }, max: function (a) { this.x < a.x && (this.x = a.x); this.y < a.y && (this.y = a.y); return this }, clamp: function (a, b) { this.x < a.x ? this.x = a.x : this.x > b.x && (this.x = b.x); this.y < a.y ? this.y = a.y : this.y > b.y && (this.y = b.y); return this }, negate: function () { return this.multiplyScalar(-1) }, dot: function (a) { return this.x * a.x + this.y * a.y }, lengthSq: function () { return this.x * this.x + this.y * this.y }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y) }, normalize: function () { return this.divideScalar(this.length()) }, distanceTo: function (a) { return Math.sqrt(this.distanceToSquared(a)) }, distanceToSquared: function (a) { var b = this.x - a.x, a = this.y - a.y; return b * b + a * a }, setLength: function (a) { var b = this.length(); 0 !== b && a !== b && this.multiplyScalar(a / b); return this }, lerp: function (a, b) { this.x += (a.x - this.x) * b; this.y += (a.y - this.y) * b; return this }, equals: function (a) { return a.x === this.x && a.y === this.y }, toArray: function () { return [this.x, this.y] }, clone: function () { return new THREE.Vector2(this.x, this.y) } }; THREE.Vector3 = function (a, b, c) { this.x = a || 0; this.y = b || 0; this.z = c || 0 }; THREE.Vector3.prototype = { constructor: THREE.Vector3, set: function (a, b, c) { this.x = a; this.y = b; this.z = c; return this }, setX: function (a) { this.x = a; return this }, setY: function (a) { this.y = a; return this }, setZ: function (a) { this.z = a; return this }, setComponent: function (a, b) { switch (a) { case 0: this.x = b; break; case 1: this.y = b; break; case 2: this.z = b; break; default: throw Error("index is out of range: " + a); } }, getComponent: function (a) { switch (a) { case 0: return this.x; case 1: return this.y; case 2: return this.z; default: throw Error("index is out of range: " + a); } }, copy: function (a) { this.x = a.x; this.y = a.y; this.z = a.z; return this }, add: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector3's .add() now only accepts one argument. Use .addVectors( a, b ) instead."), this.addVectors(a, b); this.x += a.x; this.y += a.y; this.z += a.z; return this }, addScalar: function (a) { this.x += a; this.y += a; this.z += a; return this }, addVectors: function (a, b) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; return this }, sub: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector3's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."), this.subVectors(a, b); this.x -= a.x; this.y -= a.y; this.z -= a.z; return this }, subVectors: function (a, b) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; return this }, multiply: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector3's .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."), this.multiplyVectors(a, b); this.x *= a.x; this.y *= a.y; this.z *= a.z; return this }, multiplyScalar: function (a) { this.x *= a; this.y *= a; this.z *= a; return this }, multiplyVectors: function (a, b) { this.x = a.x * b.x; this.y = a.y * b.y; this.z = a.z * b.z; return this }, applyMatrix3: function (a) { var b = this.x, c = this.y, d = this.z, a = a.elements; this.x = a[0] * b + a[3] * c + a[6] * d; this.y = a[1] * b + a[4] * c + a[7] * d; this.z = a[2] * b + a[5] * c + a[8] * d; return this }, applyMatrix4: function (a) { var b = this.x, c = this.y, d = this.z, a = a.elements; this.x = a[0] * b + a[4] * c + a[8] * d + a[12]; this.y = a[1] * b + a[5] * c + a[9] * d + a[13]; this.z = a[2] * b + a[6] * c + a[10] * d + a[14]; return this }, applyProjection: function (a) { var b = this.x, c = this.y, d = this.z, a = a.elements, e = 1 / (a[3] * b + a[7] * c + a[11] * d + a[15]); this.x = (a[0] * b + a[4] * c + a[8] * d + a[12]) * e; this.y = (a[1] * b + a[5] * c + a[9] * d + a[13]) * e; this.z = (a[2] * b + a[6] * c + a[10] * d + a[14]) * e; return this }, applyQuaternion: function (a) { var b = this.x, c = this.y, d = this.z, e = a.x, f = a.y, g = a.z, a = a.w, h = a * b + f * d - g * c, i = a * c + g * b - e * d, k = a * d + e * c - f * b, b = -e * b - f * c - g * d; this.x = h * a + b * -e + i * -g - k * -f; this.y = i * a + b * -f + k * -e - h * -g; this.z = k * a + b * -g + h * -f - i * -e; return this }, transformDirection: function (a) { var b = this.x, c = this.y, d = this.z, a = a.elements; this.x = a[0] * b + a[4] * c + a[8] * d; this.y = a[1] * b + a[5] * c + a[9] * d; this.z = a[2] * b + a[6] * c + a[10] * d; this.normalize(); return this }, divide: function (a) { this.x /= a.x; this.y /= a.y; this.z /= a.z; return this }, divideScalar: function (a) { 0 !== a ? (this.x /= a, this.y /= a, this.z /= a) : this.z = this.y = this.x = 0; return this }, min: function (a) { this.x > a.x && (this.x = a.x); this.y > a.y && (this.y = a.y); this.z > a.z && (this.z = a.z); return this }, max: function (a) { this.x < a.x && (this.x = a.x); this.y < a.y && (this.y = a.y); this.z < a.z && (this.z = a.z); return this }, clamp: function (a, b) { this.x < a.x ? this.x = a.x : this.x > b.x && (this.x = b.x); this.y < a.y ? this.y = a.y : this.y > b.y && (this.y = b.y); this.z < a.z ? this.z = a.z : this.z > b.z && (this.z = b.z); return this }, negate: function () { return this.multiplyScalar(-1) }, dot: function (a) { return this.x * a.x + this.y * a.y + this.z * a.z }, lengthSq: function () { return this.x * this.x + this.y * this.y + this.z * this.z }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z) }, lengthManhattan: function () { return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) }, normalize: function () { return this.divideScalar(this.length()) }, setLength: function (a) { var b = this.length(); 0 !== b && a !== b && this.multiplyScalar(a / b); return this }, lerp: function (a, b) { this.x += (a.x - this.x) * b; this.y += (a.y - this.y) * b; this.z += (a.z - this.z) * b; return this }, cross: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector3's .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."), this.crossVectors(a, b); var c = this.x, d = this.y, e = this.z; this.x = d * a.z - e * a.y; this.y = e * a.x - c * a.z; this.z = c * a.y - d * a.x; return this }, crossVectors: function (a, b) { this.x = a.y * b.z - a.z * b.y; this.y = a.z * b.x - a.x * b.z; this.z = a.x * b.y - a.y * b.x; return this }, angleTo: function (a) { a = this.dot(a) / (this.length() * a.length()); return Math.acos(THREE.Math.clamp(a, -1, 1)) }, distanceTo: function (a) { return Math.sqrt(this.distanceToSquared(a)) }, distanceToSquared: function (a) { var b = this.x - a.x, c = this.y - a.y, a = this.z - a.z; return b * b + c * c + a * a }, setEulerFromRotationMatrix: function (a, b) { function c(a) { return Math.min(Math.max(a, -1), 1) } var d = a.elements, e = d[0], f = d[4], g = d[8], h = d[1], i = d[5], k = d[9], l = d[2], m = d[6], d = d[10]; void 0 === b || "XYZ" === b ? (this.y = Math.asin(c(g)), 0.99999 > Math.abs(g) ? (this.x = Math.atan2(-k, d), this.z = Math.atan2(-f, e)) : (this.x = Math.atan2(m, i), this.z = 0)) : "YXZ" === b ? (this.x = Math.asin(-c(k)), 0.99999 > Math.abs(k) ? (this.y = Math.atan2(g, d), this.z = Math.atan2(h, i)) : (this.y = Math.atan2(-l, e), this.z = 0)) : "ZXY" === b ? (this.x = Math.asin(c(m)), 0.99999 > Math.abs(m) ? (this.y = Math.atan2(-l, d), this.z = Math.atan2(-f, i)) : (this.y = 0, this.z = Math.atan2(h, e))) : "ZYX" === b ? (this.y = Math.asin(-c(l)), 0.99999 > Math.abs(l) ? (this.x = Math.atan2(m, d), this.z = Math.atan2(h, e)) : (this.x = 0, this.z = Math.atan2(-f, i))) : "YZX" === b ? (this.z = Math.asin(c(h)), 0.99999 > Math.abs(h) ? (this.x = Math.atan2(-k, i), this.y = Math.atan2(-l, e)) : (this.x = 0, this.y = Math.atan2(g, d))) : "XZY" === b && (this.z = Math.asin(-c(f)), 0.99999 > Math.abs(f) ? (this.x = Math.atan2(m, i), this.y = Math.atan2(g, e)) : (this.x = Math.atan2(-k, d), this.y = 0)); return this }, setEulerFromQuaternion: function (a, b) { function c(a) { return Math.min(Math.max(a, -1), 1) } var d = a.x * a.x, e = a.y * a.y, f = a.z * a.z, g = a.w * a.w; void 0 === b || "XYZ" === b ? (this.x = Math.atan2(2 * (a.x * a.w - a.y * a.z), g - d - e + f), this.y = Math.asin(c(2 * (a.x * a.z + a.y * a.w))), this.z = Math.atan2(2 * (a.z * a.w - a.x * a.y), g + d - e - f)) : "YXZ" === b ? (this.x = Math.asin(c(2 * (a.x * a.w - a.y * a.z))), this.y = Math.atan2(2 * (a.x * a.z + a.y * a.w), g - d - e + f), this.z = Math.atan2(2 * (a.x * a.y + a.z * a.w), g - d + e - f)) : "ZXY" === b ? (this.x = Math.asin(c(2 * (a.x * a.w + a.y * a.z))), this.y = Math.atan2(2 * (a.y * a.w - a.z * a.x), g - d - e + f), this.z = Math.atan2(2 * (a.z * a.w - a.x * a.y), g - d + e - f)) : "ZYX" === b ? (this.x = Math.atan2(2 * (a.x * a.w + a.z * a.y), g - d - e + f), this.y = Math.asin(c(2 * (a.y * a.w - a.x * a.z))), this.z = Math.atan2(2 * (a.x * a.y + a.z * a.w), g + d - e - f)) : "YZX" === b ? (this.x = Math.atan2(2 * (a.x * a.w - a.z * a.y), g - d + e - f), this.y = Math.atan2(2 * (a.y * a.w - a.x * a.z), g + d - e - f), this.z = Math.asin(c(2 * (a.x * a.y + a.z * a.w)))) : "XZY" === b && (this.x = Math.atan2(2 * (a.x * a.w + a.y * a.z), g - d + e - f), this.y = Math.atan2(2 * (a.x * a.z + a.y * a.w), g + d - e - f), this.z = Math.asin(c(2 * (a.z * a.w - a.x * a.y)))); return this }, getPositionFromMatrix: function (a) { this.x = a.elements[12]; this.y = a.elements[13]; this.z = a.elements[14]; return this }, getScaleFromMatrix: function (a) { var b = this.set(a.elements[0], a.elements[1], a.elements[2]).length(), c = this.set(a.elements[4], a.elements[5], a.elements[6]).length(), a = this.set(a.elements[8], a.elements[9], a.elements[10]).length(); this.x = b; this.y = c; this.z = a; return this }, getColumnFromMatrix: function (a, b) { var c = 4 * a, d = b.elements; this.x = d[c]; this.y = d[c + 1]; this.z = d[c + 2]; return this }, equals: function (a) { return a.x === this.x && a.y === this.y && a.z === this.z }, toArray: function () { return [this.x, this.y, this.z] }, clone: function () { return new THREE.Vector3(this.x, this.y, this.z) } }; THREE.extend(THREE.Vector3.prototype, { applyEuler: function () { var a = new THREE.Quaternion; return function (b, c) { var d = a.setFromEuler(b, c); this.applyQuaternion(d); return this } }(), applyAxisAngle: function () { var a = new THREE.Quaternion; return function (b, c) { var d = a.setFromAxisAngle(b, c); this.applyQuaternion(d); return this } }(), projectOnVector: function () { var a = new THREE.Vector3; return function (b) { a.copy(b).normalize(); b = this.dot(a); return this.copy(a).multiplyScalar(b) } }(), projectOnPlane: function () { var a = new THREE.Vector3; return function (b) { a.copy(this).projectOnVector(b); return this.sub(a) } }(), reflect: function () { var a = new THREE.Vector3; return function (b) { a.copy(this).projectOnVector(b).multiplyScalar(2); return this.subVectors(a, this) } }() }); THREE.Vector4 = function (a, b, c, d) { this.x = a || 0; this.y = b || 0; this.z = c || 0; this.w = void 0 !== d ? d : 1 }; THREE.Vector4.prototype = { constructor: THREE.Vector4, set: function (a, b, c, d) { this.x = a; this.y = b; this.z = c; this.w = d; return this }, setX: function (a) { this.x = a; return this }, setY: function (a) { this.y = a; return this }, setZ: function (a) { this.z = a; return this }, setW: function (a) { this.w = a; return this }, setComponent: function (a, b) { switch (a) { case 0: this.x = b; break; case 1: this.y = b; break; case 2: this.z = b; break; case 3: this.w = b; break; default: throw Error("index is out of range: " + a); } }, getComponent: function (a) { switch (a) { case 0: return this.x; case 1: return this.y; case 2: return this.z; case 3: return this.w; default: throw Error("index is out of range: " + a); } }, copy: function (a) { this.x = a.x; this.y = a.y; this.z = a.z; this.w = void 0 !== a.w ? a.w : 1; return this }, add: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector4's .add() now only accepts one argument. Use .addVectors( a, b ) instead."), this.addVectors(a, b); this.x += a.x; this.y += a.y; this.z += a.z; this.w += a.w; return this }, addScalar: function (a) { this.x += a; this.y += a; this.z += a; this.w += a; return this }, addVectors: function (a, b) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; this.w = a.w + b.w; return this }, sub: function (a, b) { if (void 0 !== b) return console.warn("DEPRECATED: Vector4's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."), this.subVectors(a, b); this.x -= a.x; this.y -= a.y; this.z -= a.z; this.w -= a.w; return this }, subVectors: function (a, b) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; this.w = a.w - b.w; return this }, multiplyScalar: function (a) { this.x *= a; this.y *= a; this.z *= a; this.w *= a; return this }, applyMatrix4: function (a) { var b = this.x, c = this.y, d = this.z, e = this.w, a = a.elements; this.x = a[0] * b + a[4] * c + a[8] * d + a[12] * e; this.y = a[1] * b + a[5] * c + a[9] * d + a[13] * e; this.z = a[2] * b + a[6] * c + a[10] * d + a[14] * e; this.w = a[3] * b + a[7] * c + a[11] * d + a[15] * e; return this }, divideScalar: function (a) { 0 !== a ? (this.x /= a, this.y /= a, this.z /= a, this.w /= a) : (this.z = this.y = this.x = 0, this.w = 1); return this }, setAxisAngleFromQuaternion: function (a) { this.w = 2 * Math.acos(a.w); var b = Math.sqrt(1 - a.w * a.w); 1E-4 > b ? (this.x = 1, this.z = this.y = 0) : (this.x = a.x / b, this.y = a.y / b, this.z = a.z / b); return this }, setAxisAngleFromRotationMatrix: function (a) { var b, c, d, a = a.elements, e = a[0]; d = a[4]; var f = a[8], g = a[1], h = a[5], i = a[9]; c = a[2]; b = a[6]; var k = a[10]; if (0.01 > Math.abs(d - g) && 0.01 > Math.abs(f - c) && 0.01 > Math.abs(i - b)) { if (0.1 > Math.abs(d + g) && 0.1 > Math.abs(f + c) && 0.1 > Math.abs(i + b) && 0.1 > Math.abs(e + h + k - 3)) return this.set(1, 0, 0, 0), this; a = Math.PI; e = (e + 1) / 2; h = (h + 1) / 2; k = (k + 1) / 2; d = (d + g) / 4; f = (f + c) / 4; i = (i + b) / 4; e > h && e > k ? 0.01 > e ? (b = 0, d = c = 0.707106781) : (b = Math.sqrt(e), c = d / b, d = f / b) : h > k ? 0.01 > h ? (b = 0.707106781, c = 0, d = 0.707106781) : (c = Math.sqrt(h), b = d / c, d = i / c) : 0.01 > k ? (c = b = 0.707106781, d = 0) : (d = Math.sqrt(k), b = f / d, c = i / d); this.set(b, c, d, a); return this } a = Math.sqrt((b - i) * (b - i) + (f - c) * (f - c) + (g - d) * (g - d)); 0.001 > Math.abs(a) && (a = 1); this.x = (b - i) / a; this.y = (f - c) / a; this.z = (g - d) / a; this.w = Math.acos((e + h + k - 1) / 2); return this }, min: function (a) { this.x > a.x && (this.x = a.x); this.y > a.y && (this.y = a.y); this.z > a.z && (this.z = a.z); this.w > a.w && (this.w = a.w); return this }, max: function (a) { this.x < a.x && (this.x = a.x); this.y < a.y && (this.y = a.y); this.z < a.z && (this.z = a.z); this.w < a.w && (this.w = a.w); return this }, clamp: function (a, b) { this.x < a.x ? this.x = a.x : this.x > b.x && (this.x = b.x); this.y < a.y ? this.y = a.y : this.y > b.y && (this.y = b.y); this.z < a.z ? this.z = a.z : this.z > b.z && (this.z = b.z); this.w < a.w ? this.w = a.w : this.w > b.w && (this.w = b.w); return this }, negate: function () { return this.multiplyScalar(-1) }, dot: function (a) { return this.x * a.x + this.y * a.y + this.z * a.z + this.w * a.w }, lengthSq: function () { return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w) }, lengthManhattan: function () { return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w) }, normalize: function () { return this.divideScalar(this.length()) }, setLength: function (a) { var b = this.length(); 0 !== b && a !== b && this.multiplyScalar(a / b); return this }, lerp: function (a, b) { this.x += (a.x - this.x) * b; this.y += (a.y - this.y) * b; this.z += (a.z - this.z) * b; this.w += (a.w - this.w) * b; return this }, equals: function (a) { return a.x === this.x && a.y === this.y && a.z === this.z && a.w === this.w }, toArray: function () { return [this.x, this.y, this.z, this.w] }, clone: function () { return new THREE.Vector4(this.x, this.y, this.z, this.w) } }; THREE.Line3 = function (a, b) { this.start = void 0 !== a ? a : new THREE.Vector3; this.end = void 0 !== b ? b : new THREE.Vector3 }; THREE.Line3.prototype = { constructor: THREE.Line3, set: function (a, b) { this.start.copy(a); this.end.copy(b); return this }, copy: function (a) { this.start.copy(a.start); this.end.copy(a.end); return this }, center: function (a) { return (a || new THREE.Vector3).addVectors(this.start, this.end).multiplyScalar(0.5) }, delta: function (a) { return (a || new THREE.Vector3).subVectors(this.end, this.start) }, distanceSq: function () { return this.start.distanceToSquared(this.end) }, distance: function () { return this.start.distanceTo(this.end) }, at: function (a, b) { var c = b || new THREE.Vector3; return this.delta(c).multiplyScalar(a).add(this.start) }, closestPointToPointParameter: function () { var a = new THREE.Vector3, b = new THREE.Vector3; return function (c, d) { a.subVectors(c, this.start); b.subVectors(this.end, this.start); var e = b.dot(b), e = b.dot(a) / e; d && (e = THREE.Math.clamp(e, 0, 1)); return e } }(), closestPointToPoint: function (a, b, c) { a = this.closestPointToPointParameter(a, b); c = c || new THREE.Vector3; return this.delta(c).multiplyScalar(a).add(this.start) }, applyMatrix4: function (a) { this.start.applyMatrix4(a); this.end.applyMatrix4(a); return this }, equals: function (a) { return a.start.equals(this.start) && a.end.equals(this.end) }, clone: function () { return (new THREE.Line3).copy(this) } }; THREE.Box2 = function (a, b) { this.min = void 0 !== a ? a : new THREE.Vector2(Infinity, Infinity); this.max = void 0 !== b ? b : new THREE.Vector2(-Infinity, -Infinity) }; THREE.Box2.prototype = { constructor: THREE.Box2, set: function (a, b) { this.min.copy(a); this.max.copy(b); return this }, setFromPoints: function (a) { if (0 < a.length) { var b = a[0]; this.min.copy(b); this.max.copy(b); for (var c = 1, d = a.length; c < d; c++) b = a[c], b.x < this.min.x ? this.min.x = b.x : b.x > this.max.x && (this.max.x = b.x), b.y < this.min.y ? this.min.y = b.y : b.y > this.max.y && (this.max.y = b.y) } else this.makeEmpty(); return this }, setFromCenterAndSize: function () { var a = new THREE.Vector2; return function (b, c) { var d = a.copy(c).multiplyScalar(0.5); this.min.copy(b).sub(d); this.max.copy(b).add(d); return this } }(), copy: function (a) { this.min.copy(a.min); this.max.copy(a.max); return this }, makeEmpty: function () { this.min.x = this.min.y = Infinity; this.max.x = this.max.y = -Infinity; return this }, empty: function () { return this.max.x < this.min.x || this.max.y < this.min.y }, center: function (a) { return (a || new THREE.Vector2).addVectors(this.min, this.max).multiplyScalar(0.5) }, size: function (a) { return (a || new THREE.Vector2).subVectors(this.max, this.min) }, expandByPoint: function (a) { this.min.min(a); this.max.max(a); return this }, expandByVector: function (a) { this.min.sub(a); this.max.add(a); return this }, expandByScalar: function (a) { this.min.addScalar(-a); this.max.addScalar(a); return this }, containsPoint: function (a) { return a.x < this.min.x || a.x > this.max.x || a.y < this.min.y || a.y > this.max.y ? !1 : !0 }, containsBox: function (a) { return this.min.x <= a.min.x && a.max.x <= this.max.x && this.min.y <= a.min.y && a.max.y <= this.max.y ? !0 : !1 }, getParameter: function (a) { return new THREE.Vector2((a.x - this.min.x) / (this.max.x - this.min.x), (a.y - this.min.y) / (this.max.y - this.min.y)) }, isIntersectionBox: function (a) { return a.max.x < this.min.x || a.min.x > this.max.x || a.max.y < this.min.y || a.min.y > this.max.y ? !1 : !0 }, clampPoint: function (a, b) { return (b || new THREE.Vector2).copy(a).clamp(this.min, this.max) }, distanceToPoint: function () { var a = new THREE.Vector2; return function (b) { return a.copy(b).clamp(this.min, this.max).sub(b).length() } }(), intersect: function (a) { this.min.max(a.min); this.max.min(a.max); return this }, union: function (a) { this.min.min(a.min); this.max.max(a.max); return this }, translate: function (a) { this.min.add(a); this.max.add(a); return this }, equals: function (a) { return a.min.equals(this.min) && a.max.equals(this.max) }, clone: function () { return (new THREE.Box2).copy(this) } }; THREE.Box3 = function (a, b) { this.min = void 0 !== a ? a : new THREE.Vector3(Infinity, Infinity, Infinity); this.max = void 0 !== b ? b : new THREE.Vector3(-Infinity, -Infinity, -Infinity) }; THREE.Box3.prototype = { constructor: THREE.Box3, set: function (a, b) { this.min.copy(a); this.max.copy(b); return this }, setFromPoints: function (a) { if (0 < a.length) { var b = a[0]; this.min.copy(b); this.max.copy(b); for (var c = 1, d = a.length; c < d; c++) b = a[c], b.x < this.min.x ? this.min.x = b.x : b.x > this.max.x && (this.max.x = b.x), b.y < this.min.y ? this.min.y = b.y : b.y > this.max.y && (this.max.y = b.y), b.z < this.min.z ? this.min.z = b.z : b.z > this.max.z && (this.max.z = b.z) } else this.makeEmpty(); return this }, setFromCenterAndSize: function () { var a = new THREE.Vector3; return function (b, c) { var d = a.copy(c).multiplyScalar(0.5); this.min.copy(b).sub(d); this.max.copy(b).add(d); return this } }(), copy: function (a) { this.min.copy(a.min); this.max.copy(a.max); return this }, makeEmpty: function () { this.min.x = this.min.y = this.min.z = Infinity; this.max.x = this.max.y = this.max.z = -Infinity; return this }, empty: function () { return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z }, center: function (a) { return (a || new THREE.Vector3).addVectors(this.min, this.max).multiplyScalar(0.5) }, size: function (a) { return (a || new THREE.Vector3).subVectors(this.max, this.min) }, expandByPoint: function (a) { this.min.min(a); this.max.max(a); return this }, expandByVector: function (a) { this.min.sub(a); this.max.add(a); return this }, expandByScalar: function (a) { this.min.addScalar(-a); this.max.addScalar(a); return this }, containsPoint: function (a) { return a.x < this.min.x || a.x > this.max.x || a.y < this.min.y || a.y > this.max.y || a.z < this.min.z || a.z > this.max.z ? !1 : !0 }, containsBox: function (a) { return this.min.x <= a.min.x && a.max.x <= this.max.x && this.min.y <= a.min.y && a.max.y <= this.max.y && this.min.z <= a.min.z && a.max.z <= this.max.z ? !0 : !1 }, getParameter: function (a) { return new THREE.Vector3((a.x - this.min.x) / (this.max.x - this.min.x), (a.y - this.min.y) / (this.max.y - this.min.y), (a.z - this.min.z) / (this.max.z - this.min.z)) }, isIntersectionBox: function (a) { return a.max.x < this.min.x || a.min.x > this.max.x || a.max.y < this.min.y || a.min.y > this.max.y || a.max.z < this.min.z || a.min.z > this.max.z ? !1 : !0 }, clampPoint: function (a, b) { return (b || new THREE.Vector3).copy(a).clamp(this.min, this.max) }, distanceToPoint: function () { var a = new THREE.Vector3; return function (b) { return a.copy(b).clamp(this.min, this.max).sub(b).length() } }(), getBoundingSphere: function () { var a = new THREE.Vector3; return function (b) { b = b || new THREE.Sphere; b.center = this.center(); b.radius = 0.5 * this.size(a).length(); return b } }(), intersect: function (a) { this.min.max(a.min); this.max.min(a.max); return this }, union: function (a) { this.min.min(a.min); this.max.max(a.max); return this }, applyMatrix4: function () { var a = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3]; return function (b) { a[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(b); a[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(b); a[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(b); a[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(b); a[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(b); a[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(b); a[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(b); a[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(b); this.makeEmpty(); this.setFromPoints(a); return this } }(), translate: function (a) { this.min.add(a); this.max.add(a); return this }, equals: function (a) { return a.min.equals(this.min) && a.max.equals(this.max) }, clone: function () { return (new THREE.Box3).copy(this) } }; THREE.Matrix3 = function (a, b, c, d, e, f, g, h, i) { this.elements = new Float32Array(9); this.set(void 0 !== a ? a : 1, b || 0, c || 0, d || 0, void 0 !== e ? e : 1, f || 0, g || 0, h || 0, void 0 !== i ? i : 1) }; THREE.Matrix3.prototype = { constructor: THREE.Matrix3, set: function (a, b, c, d, e, f, g, h, i) { var k = this.elements; k[0] = a; k[3] = b; k[6] = c; k[1] = d; k[4] = e; k[7] = f; k[2] = g; k[5] = h; k[8] = i; return this }, identity: function () { this.set(1, 0, 0, 0, 1, 0, 0, 0, 1); return this }, copy: function (a) { a = a.elements; this.set(a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8]); return this }, multiplyVector3: function (a) { console.warn("DEPRECATED: Matrix3's .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead."); return a.applyMatrix3(this) }, multiplyVector3Array: function () { var a = new THREE.Vector3; return function (b) { for (var c = 0, d = b.length; c < d; c += 3) a.x = b[c], a.y = b[c + 1], a.z = b[c + 2], a.applyMatrix3(this), b[c] = a.x, b[c + 1] = a.y, b[c + 2] = a.z; return b } }(), multiplyScalar: function (a) { var b = this.elements; b[0] *= a; b[3] *= a; b[6] *= a; b[1] *= a; b[4] *= a; b[7] *= a; b[2] *= a; b[5] *= a; b[8] *= a; return this }, determinant: function () { var a = this.elements, b = a[0], c = a[1], d = a[2], e = a[3], f = a[4], g = a[5], h = a[6], i = a[7], a = a[8]; return b * f * a - b * g * i - c * e * a + c * g * h + d * e * i - d * f * h }, getInverse: function (a, b) { var c = a.elements, d = this.elements; d[0] = c[10] * c[5] - c[6] * c[9]; d[1] = -c[10] * c[1] + c[2] * c[9]; d[2] = c[6] * c[1] - c[2] * c[5]; d[3] = -c[10] * c[4] + c[6] * c[8]; d[4] = c[10] * c[0] - c[2] * c[8]; d[5] = -c[6] * c[0] + c[2] * c[4]; d[6] = c[9] * c[4] - c[5] * c[8]; d[7] = -c[9] * c[0] + c[1] * c[8]; d[8] = c[5] * c[0] - c[1] * c[4]; c = c[0] * d[0] + c[1] * d[3] + c[2] * d[6]; if (0 === c) { if (b) throw Error("Matrix3.getInverse(): can't invert matrix, determinant is 0"); console.warn("Matrix3.getInverse(): can't invert matrix, determinant is 0"); this.identity(); return this } this.multiplyScalar(1 / c); return this }, transpose: function () { var a, b = this.elements; a = b[1]; b[1] = b[3]; b[3] = a; a = b[2]; b[2] = b[6]; b[6] = a; a = b[5]; b[5] = b[7]; b[7] = a; return this }, getNormalMatrix: function (a) { this.getInverse(a).transpose(); return this }, transposeIntoArray: function (a) { var b = this.elements; a[0] = b[0]; a[1] = b[3]; a[2] = b[6]; a[3] = b[1]; a[4] = b[4]; a[5] = b[7]; a[6] = b[2]; a[7] = b[5]; a[8] = b[8]; return this }, clone: function () { var a = this.elements; return new THREE.Matrix3(a[0], a[3], a[6], a[1], a[4], a[7], a[2], a[5], a[8]) } }; THREE.Matrix4 = function (a, b, c, d, e, f, g, h, i, k, l, m, p, s, r, n) { var q = this.elements = new Float32Array(16); q[0] = void 0 !== a ? a : 1; q[4] = b || 0; q[8] = c || 0; q[12] = d || 0; q[1] = e || 0; q[5] = void 0 !== f ? f : 1; q[9] = g || 0; q[13] = h || 0; q[2] = i || 0; q[6] = k || 0; q[10] = void 0 !== l ? l : 1; q[14] = m || 0; q[3] = p || 0; q[7] = s || 0; q[11] = r || 0; q[15] = void 0 !== n ? n : 1 }; THREE.Matrix4.prototype = { constructor: THREE.Matrix4, set: function (a, b, c, d, e, f, g, h, i, k, l, m, p, s, r, n) { var q = this.elements; q[0] = a; q[4] = b; q[8] = c; q[12] = d; q[1] = e; q[5] = f; q[9] = g; q[13] = h; q[2] = i; q[6] = k; q[10] = l; q[14] = m; q[3] = p; q[7] = s; q[11] = r; q[15] = n; return this }, identity: function () { this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); return this }, copy: function (a) { a = a.elements; this.set(a[0], a[4], a[8], a[12], a[1], a[5], a[9], a[13], a[2], a[6], a[10], a[14], a[3], a[7], a[11], a[15]); return this }, setRotationFromEuler: function (a, b) { var c = this.elements, d = a.x, e = a.y, f = a.z, g = Math.cos(d), d = Math.sin(d), h = Math.cos(e), e = Math.sin(e), i = Math.cos(f), f = Math.sin(f); if (void 0 === b || "XYZ" === b) { var k = g * i, l = g * f, m = d * i, p = d * f; c[0] = h * i; c[4] = -h * f; c[8] = e; c[1] = l + m * e; c[5] = k - p * e; c[9] = -d * h; c[2] = p - k * e; c[6] = m + l * e; c[10] = g * h } else "YXZ" === b ? (k = h * i, l = h * f, m = e * i, p = e * f, c[0] = k + p * d, c[4] = m * d - l, c[8] = g * e, c[1] = g * f, c[5] = g * i, c[9] = -d, c[2] = l * d - m, c[6] = p + k * d, c[10] = g * h) : "ZXY" === b ? (k = h * i, l = h * f, m = e * i, p = e * f, c[0] = k - p * d, c[4] = -g * f, c[8] = m + l * d, c[1] = l + m * d, c[5] = g * i, c[9] = p - k * d, c[2] = -g * e, c[6] = d, c[10] = g * h) : "ZYX" === b ? (k = g * i, l = g * f, m = d * i, p = d * f, c[0] = h * i, c[4] = m * e - l, c[8] = k * e + p, c[1] = h * f, c[5] = p * e + k, c[9] = l * e - m, c[2] = -e, c[6] = d * h, c[10] = g * h) : "YZX" === b ? (k = g * h, l = g * e, m = d * h, p = d * e, c[0] = h * i, c[4] = p - k * f, c[8] = m * f + l, c[1] = f, c[5] = g * i, c[9] = -d * i, c[2] = -e * i, c[6] = l * f + m, c[10] = k - p * f) : "XZY" === b && (k = g * h, l = g * e, m = d * h, p = d * e, c[0] = h * i, c[4] = -f, c[8] = e * i, c[1] = k * f + p, c[5] = g * i, c[9] = l * f - m, c[2] = m * f - l, c[6] = d * i, c[10] = p * f + k); return this }, setRotationFromQuaternion: function (a) { var b = this.elements, c = a.x, d = a.y, e = a.z, f = a.w, g = c + c, h = d + d, i = e + e, a = c * g, k = c * h, c = c * i, l = d * h, d = d * i, e = e * i, g = f * g, h = f * h, f = f * i; b[0] = 1 - (l + e); b[4] = k - f; b[8] = c + h; b[1] = k + f; b[5] = 1 - (a + e); b[9] = d - g; b[2] = c - h; b[6] = d + g; b[10] = 1 - (a + l); return this }, lookAt: function () { var a = new THREE.Vector3, b = new THREE.Vector3, c = new THREE.Vector3; return function (d, e, f) { var g = this.elements; c.subVectors(d, e).normalize(); 0 === c.length() && (c.z = 1); a.crossVectors(f, c).normalize(); 0 === a.length() && (c.x += 1E-4, a.crossVectors(f, c).normalize()); b.crossVectors(c, a); g[0] = a.x; g[4] = b.x; g[8] = c.x; g[1] = a.y; g[5] = b.y; g[9] = c.y; g[2] = a.z; g[6] = b.z; g[10] = c.z; return this } }(), multiply: function (a, b) { return void 0 !== b ? (console.warn("DEPRECATED: Matrix4's .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."), this.multiplyMatrices(a, b)) : this.multiplyMatrices(this, a) }, multiplyMatrices: function (a, b) { var c = a.elements, d = b.elements, e = this.elements, f = c[0], g = c[4], h = c[8], i = c[12], k = c[1], l = c[5], m = c[9], p = c[13], s = c[2], r = c[6], n = c[10], q = c[14], z = c[3], t = c[7], x = c[11], c = c[15], u = d[0], B = d[4], G = d[8], D = d[12], w = d[1], I = d[5], J = d[9], E = d[13], Z = d[2], A = d[6], S = d[10], F = d[14], H = d[3], K = d[7], N = d[11], d = d[15]; e[0] = f * u + g * w + h * Z + i * H; e[4] = f * B + g * I + h * A + i * K; e[8] = f * G + g * J + h * S + i * N; e[12] = f * D + g * E + h * F + i * d; e[1] = k * u + l * w + m * Z + p * H; e[5] = k * B + l * I + m * A + p * K; e[9] = k * G + l * J + m * S + p * N; e[13] = k * D + l * E + m * F + p * d; e[2] = s * u + r * w + n * Z + q * H; e[6] = s * B + r * I + n * A + q * K; e[10] = s * G + r * J + n * S + q * N; e[14] = s * D + r * E + n * F + q * d; e[3] = z * u + t * w + x * Z + c * H; e[7] = z * B + t * I + x * A + c * K; e[11] = z * G + t * J + x * S + c * N; e[15] = z * D + t * E + x * F + c * d; return this }, multiplyToArray: function (a, b, c) { var d = this.elements; this.multiplyMatrices(a, b); c[0] = d[0]; c[1] = d[1]; c[2] = d[2]; c[3] = d[3]; c[4] = d[4]; c[5] = d[5]; c[6] = d[6]; c[7] = d[7]; c[8] = d[8]; c[9] = d[9]; c[10] = d[10]; c[11] = d[11]; c[12] = d[12]; c[13] = d[13]; c[14] = d[14]; c[15] = d[15]; return this }, multiplyScalar: function (a) { var b = this.elements; b[0] *= a; b[4] *= a; b[8] *= a; b[12] *= a; b[1] *= a; b[5] *= a; b[9] *= a; b[13] *= a; b[2] *= a; b[6] *= a; b[10] *= a; b[14] *= a; b[3] *= a; b[7] *= a; b[11] *= a; b[15] *= a; return this }, multiplyVector3: function (a) { console.warn("DEPRECATED: Matrix4's .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead."); return a.applyProjection(this) }, multiplyVector4: function (a) { console.warn("DEPRECATED: Matrix4's .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead."); return a.applyMatrix4(this) }, multiplyVector3Array: function () { var a = new THREE.Vector3; return function (b) { for (var c = 0, d = b.length; c < d; c += 3) a.x = b[c], a.y = b[c + 1], a.z = b[c + 2], a.applyProjection(this), b[c] = a.x, b[c + 1] = a.y, b[c + 2] = a.z; return b } }(), rotateAxis: function (a) { console.warn("DEPRECATED: Matrix4's .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead."); a.transformDirection(this) }, crossVector: function (a) { var b = this.elements, c = new THREE.Vector4; c.x = b[0] * a.x + b[4] * a.y + b[8] * a.z + b[12] * a.w; c.y = b[1] * a.x + b[5] * a.y + b[9] * a.z + b[13] * a.w; c.z = b[2] * a.x + b[6] * a.y + b[10] * a.z + b[14] * a.w; c.w = a.w ? b[3] * a.x + b[7] * a.y + b[11] * a.z + b[15] * a.w : 1; return c }, determinant: function () { var a = this.elements, b = a[0], c = a[4], d = a[8], e = a[12], f = a[1], g = a[5], h = a[9], i = a[13], k = a[2], l = a[6], m = a[10], p = a[14]; return a[3] * (+e * h * l - d * i * l - e * g * m + c * i * m + d * g * p - c * h * p) + a[7] * (+b * h * p - b * i * m + e * f * m - d * f * p + d * i * k - e * h * k) + a[11] * (+b * i * l - b * g * p - e * f * l + c * f * p + e * g * k - c * i * k) + a[15] * (-d * g * k - b * h * l + b * g * m + d * f * l - c * f * m + c * h * k) }, transpose: function () { var a = this.elements, b; b = a[1]; a[1] = a[4]; a[4] = b; b = a[2]; a[2] = a[8]; a[8] = b; b = a[6]; a[6] = a[9]; a[9] = b; b = a[3]; a[3] = a[12]; a[12] = b; b = a[7]; a[7] = a[13]; a[13] = b; b = a[11]; a[11] = a[14]; a[14] = b; return this }, flattenToArray: function (a) { var b = this.elements; a[0] = b[0]; a[1] = b[1]; a[2] = b[2]; a[3] = b[3]; a[4] = b[4]; a[5] = b[5]; a[6] = b[6]; a[7] = b[7]; a[8] = b[8]; a[9] = b[9]; a[10] = b[10]; a[11] = b[11]; a[12] = b[12]; a[13] = b[13]; a[14] = b[14]; a[15] = b[15]; return a }, flattenToArrayOffset: function (a, b) { var c = this.elements; a[b] = c[0]; a[b + 1] = c[1]; a[b + 2] = c[2]; a[b + 3] = c[3]; a[b + 4] = c[4]; a[b + 5] = c[5]; a[b + 6] = c[6]; a[b + 7] = c[7]; a[b + 8] = c[8]; a[b + 9] = c[9]; a[b + 10] = c[10]; a[b + 11] = c[11]; a[b + 12] = c[12]; a[b + 13] = c[13]; a[b + 14] = c[14]; a[b + 15] = c[15]; return a }, getPosition: function () { var a = new THREE.Vector3; return function () { console.warn("DEPRECATED: Matrix4's .getPosition() has been removed. Use Vector3.getPositionFromMatrix( matrix ) instead."); var b = this.elements; return a.set(b[12], b[13], b[14]) } }(), setPosition: function (a) { var b = this.elements; b[12] = a.x; b[13] = a.y; b[14] = a.z; return this }, getInverse: function (a, b) { var c = this.elements, d = a.elements, e = d[0], f = d[4], g = d[8], h = d[12], i = d[1], k = d[5], l = d[9], m = d[13], p = d[2], s = d[6], r = d[10], n = d[14], q = d[3], z = d[7], t = d[11], x = d[15]; c[0] = l * n * z - m * r * z + m * s * t - k * n * t - l * s * x + k * r * x; c[4] = h * r * z - g * n * z - h * s * t + f * n * t + g * s * x - f * r * x; c[8] = g * m * z - h * l * z + h * k * t - f * m * t - g * k * x + f * l * x; c[12] = h * l * s - g * m * s - h * k * r + f * m * r + g * k * n - f * l * n; c[1] = m * r * q - l * n * q - m * p * t + i * n * t + l * p * x - i * r * x; c[5] = g * n * q - h * r * q + h * p * t - e * n * t - g * p * x + e * r * x; c[9] = h * l * q - g * m * q - h * i * t + e * m * t + g * i * x - e * l * x; c[13] = g * m * p - h * l * p + h * i * r - e * m * r - g * i * n + e * l * n; c[2] = k * n * q - m * s * q + m * p * z - i * n * z - k * p * x + i * s * x; c[6] = h * s * q - f * n * q - h * p * z + e * n * z + f * p * x - e * s * x; c[10] = f * m * q - h * k * q + h * i * z - e * m * z - f * i * x + e * k * x; c[14] = h * k * p - f * m * p - h * i * s + e * m * s + f * i * n - e * k * n; c[3] = l * s * q - k * r * q - l * p * z + i * r * z + k * p * t - i * s * t; c[7] = f * r * q - g * s * q + g * p * z - e * r * z - f * p * t + e * s * t; c[11] = g * k * q - f * l * q - g * i * z + e * l * z + f * i * t - e * k * t; c[15] = f * l * p - g * k * p + g * i * s - e * l * s - f * i * r + e * k * r; c = d[0] * c[0] + d[1] * c[4] + d[2] * c[8] + d[3] * c[12]; if (0 == c) { if (b) throw Error("Matrix4.getInverse(): can't invert matrix, determinant is 0"); console.warn("Matrix4.getInverse(): can't invert matrix, determinant is 0"); this.identity(); return this } this.multiplyScalar(1 / c); return this }, extractPosition: function (a) { var b = this.elements, a = a.elements; b[12] = a[12]; b[13] = a[13]; b[14] = a[14]; return this }, extractRotation: function () { var a = new THREE.Vector3; return function (b) { var c = this.elements, b = b.elements, d = 1 / a.set(b[0], b[1], b[2]).length(), e = 1 / a.set(b[4], b[5], b[6]).length(), f = 1 / a.set(b[8], b[9], b[10]).length(); c[0] = b[0] * d; c[1] = b[1] * d; c[2] = b[2] * d; c[4] = b[4] * e; c[5] = b[5] * e; c[6] = b[6] * e; c[8] = b[8] * f; c[9] = b[9] * f; c[10] = b[10] * f; return this } }(), translate: function (a) { var b = this.elements, c = a.x, d = a.y, a = a.z; b[12] = b[0] * c + b[4] * d + b[8] * a + b[12]; b[13] = b[1] * c + b[5] * d + b[9] * a + b[13]; b[14] = b[2] * c + b[6] * d + b[10] * a + b[14]; b[15] = b[3] * c + b[7] * d + b[11] * a + b[15]; return this }, rotateX: function (a) { var b = this.elements, c = b[4], d = b[5], e = b[6], f = b[7], g = b[8], h = b[9], i = b[10], k = b[11], l = Math.cos(a), a = Math.sin(a); b[4] = l * c + a * g; b[5] = l * d + a * h; b[6] = l * e + a * i; b[7] = l * f + a * k; b[8] = l * g - a * c; b[9] = l * h - a * d; b[10] = l * i - a * e; b[11] = l * k - a * f; return this }, rotateY: function (a) { var b = this.elements, c = b[0], d = b[1], e = b[2], f = b[3], g = b[8], h = b[9], i = b[10], k = b[11], l = Math.cos(a), a = Math.sin(a); b[0] = l * c - a * g; b[1] = l * d - a * h; b[2] = l * e - a * i; b[3] = l * f - a * k; b[8] = l * g + a * c; b[9] = l * h + a * d; b[10] = l * i + a * e; b[11] = l * k + a * f; return this }, rotateZ: function (a) { var b = this.elements, c = b[0], d = b[1], e = b[2], f = b[3], g = b[4], h = b[5], i = b[6], k = b[7], l = Math.cos(a), a = Math.sin(a); b[0] = l * c + a * g; b[1] = l * d + a * h; b[2] = l * e + a * i; b[3] = l * f + a * k; b[4] = l * g - a * c; b[5] = l * h - a * d; b[6] = l * i - a * e; b[7] = l * k - a * f; return this }, rotateByAxis: function (a, b) { var c = this.elements; if (1 === a.x && 0 === a.y && 0 === a.z) return this.rotateX(b); if (0 === a.x && 1 === a.y && 0 === a.z) return this.rotateY(b); if (0 === a.x && 0 === a.y && 1 === a.z) return this.rotateZ(b); var d = a.x, e = a.y, f = a.z, g = Math.sqrt(d * d + e * e + f * f), d = d / g, e = e / g, f = f / g, g = d * d, h = e * e, i = f * f, k = Math.cos(b), l = Math.sin(b), m = 1 - k, p = d * e * m, s = d * f * m, m = e * f * m, d = d * l, r = e * l, l = f * l, f = g + (1 - g) * k, g = p + l, e = s - r, p = p - l, h = h + (1 - h) * k, l = m + d, s = s + r, m = m - d, i = i + (1 - i) * k, k = c[0], d = c[1], r = c[2], n = c[3], q = c[4], z = c[5], t = c[6], x = c[7], u = c[8], B = c[9], G = c[10], D = c[11]; c[0] = f * k + g * q + e * u; c[1] = f * d + g * z + e * B; c[2] = f * r + g * t + e * G; c[3] = f * n + g * x + e * D; c[4] = p * k + h * q + l * u; c[5] = p * d + h * z + l * B; c[6] = p * r + h * t + l * G; c[7] = p * n + h * x + l * D; c[8] = s * k + m * q + i * u; c[9] = s * d + m * z + i * B; c[10] = s * r + m * t + i * G; c[11] = s * n + m * x + i * D; return this }, scale: function (a) { var b = this.elements, c = a.x, d = a.y, a = a.z; b[0] *= c; b[4] *= d; b[8] *= a; b[1] *= c; b[5] *= d; b[9] *= a; b[2] *= c; b[6] *= d; b[10] *= a; b[3] *= c; b[7] *= d; b[11] *= a; return this }, getMaxScaleOnAxis: function () { var a = this.elements; return Math.sqrt(Math.max(a[0] * a[0] + a[1] * a[1] + a[2] * a[2], Math.max(a[4] * a[4] + a[5] * a[5] + a[6] * a[6], a[8] * a[8] + a[9] * a[9] + a[10] * a[10]))) }, makeTranslation: function (a, b, c) { this.set(1, 0, 0, a, 0, 1, 0, b, 0, 0, 1, c, 0, 0, 0, 1); return this }, makeRotationX: function (a) { var b = Math.cos(a), a = Math.sin(a); this.set(1, 0, 0, 0, 0, b, -a, 0, 0, a, b, 0, 0, 0, 0, 1); return this }, makeRotationY: function (a) { var b = Math.cos(a), a = Math.sin(a); this.set(b, 0, a, 0, 0, 1, 0, 0, -a, 0, b, 0, 0, 0, 0, 1); return this }, makeRotationZ: function (a) { var b = Math.cos(a), a = Math.sin(a); this.set(b, -a, 0, 0, a, b, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); return this }, makeRotationAxis: function (a, b) { var c = Math.cos(b), d = Math.sin(b), e = 1 - c, f = a.x, g = a.y, h = a.z, i = e * f, k = e * g; this.set(i * f + c, i * g - d * h, i * h + d * g, 0, i * g + d * h, k * g + c, k * h - d * f, 0, i * h - d * g, k * h + d * f, e * h * h + c, 0, 0, 0, 0, 1); return this }, makeScale: function (a, b, c) { this.set(a, 0, 0, 0, 0, b, 0, 0, 0, 0, c, 0, 0, 0, 0, 1); return this }, makeFrustum: function (a, b, c, d, e, f) { var g = this.elements; g[0] = 2 * e / (b - a); g[4] = 0; g[8] = (b + a) / (b - a); g[12] = 0; g[1] = 0; g[5] = 2 * e / (d - c); g[9] = (d + c) / (d - c); g[13] = 0; g[2] = 0; g[6] = 0; g[10] = -(f + e) / (f - e); g[14] = -2 * f * e / (f - e); g[3] = 0; g[7] = 0; g[11] = -1; g[15] = 0; return this }, makePerspective: function (a, b, c, d) { var a = c * Math.tan(THREE.Math.degToRad(0.5 * a)), e = -a; return this.makeFrustum(e * b, a * b, e, a, c, d) }, makeOrthographic: function (a, b, c, d, e, f) { var g = this.elements, h = b - a, i = c - d, k = f - e; g[0] = 2 / h; g[4] = 0; g[8] = 0; g[12] = -((b + a) / h); g[1] = 0; g[5] = 2 / i; g[9] = 0; g[13] = -((c + d) / i); g[2] = 0; g[6] = 0; g[10] = -2 / k; g[14] = -((f + e) / k); g[3] = 0; g[7] = 0; g[11] = 0; g[15] = 1; return this }, clone: function () { var a = this.elements; return new THREE.Matrix4(a[0], a[4], a[8], a[12], a[1], a[5], a[9], a[13], a[2], a[6], a[10], a[14], a[3], a[7], a[11], a[15]) } }; THREE.extend(THREE.Matrix4.prototype, { compose: function () { var a = new THREE.Matrix4, b = new THREE.Matrix4; return function (c, d, e) { var f = this.elements; a.identity(); a.setRotationFromQuaternion(d); b.makeScale(e.x, e.y, e.z); this.multiplyMatrices(a, b); f[12] = c.x; f[13] = c.y; f[14] = c.z; return this } }(), decompose: function () { var a = new THREE.Vector3, b = new THREE.Vector3, c = new THREE.Vector3, d = new THREE.Matrix4; return function (e, f, g) { var h = this.elements; a.set(h[0], h[1], h[2]); b.set(h[4], h[5], h[6]); c.set(h[8], h[9], h[10]); e = e instanceof THREE.Vector3 ? e : new THREE.Vector3; f = f instanceof THREE.Quaternion ? f : new THREE.Quaternion; g = g instanceof THREE.Vector3 ? g : new THREE.Vector3; g.x = a.length(); g.y = b.length(); g.z = c.length(); e.x = h[12]; e.y = h[13]; e.z = h[14]; d.copy(this); d.elements[0] /= g.x; d.elements[1] /= g.x; d.elements[2] /= g.x; d.elements[4] /= g.y; d.elements[5] /= g.y; d.elements[6] /= g.y; d.elements[8] /= g.z; d.elements[9] /= g.z; d.elements[10] /= g.z; f.setFromRotationMatrix(d); return [e, f, g] } }() }); THREE.Ray = function (a, b) { this.origin = void 0 !== a ? a : new THREE.Vector3; this.direction = void 0 !== b ? b : new THREE.Vector3 }; THREE.Ray.prototype = { constructor: THREE.Ray, set: function (a, b) { this.origin.copy(a); this.direction.copy(b); return this }, copy: function (a) { this.origin.copy(a.origin); this.direction.copy(a.direction); return this }, at: function (a, b) { return (b || new THREE.Vector3).copy(this.direction).multiplyScalar(a).add(this.origin) }, recast: function () { var a = new THREE.Vector3; return function (b) { this.origin.copy(this.at(b, a)); return this } }(), closestPointToPoint: function (a, b) { var c = b || new THREE.Vector3; c.subVectors(a, this.origin); var d = c.dot(this.direction); return c.copy(this.direction).multiplyScalar(d).add(this.origin) }, distanceToPoint: function () { var a = new THREE.Vector3; return function (b) { var c = a.subVectors(b, this.origin).dot(this.direction); a.copy(this.direction).multiplyScalar(c).add(this.origin); return a.distanceTo(b) } }(), isIntersectionSphere: function (a) { return this.distanceToPoint(a.center) <= a.radius }, isIntersectionPlane: function (a) { return 0 != a.normal.dot(this.direction) || 0 == a.distanceToPoint(this.origin) ? !0 : !1 }, distanceToPlane: function (a) { var b = a.normal.dot(this.direction); if (0 == b) { if (0 == a.distanceToPoint(this.origin)) return 0 } else return -(this.origin.dot(a.normal) + a.constant) / b }, intersectPlane: function (a, b) { var c = this.distanceToPlane(a); return void 0 === c ? void 0 : this.at(c, b) }, applyMatrix4: function (a) { this.direction.add(this.origin).applyMatrix4(a); this.origin.applyMatrix4(a); this.direction.sub(this.origin); return this }, equals: function (a) { return a.origin.equals(this.origin) && a.direction.equals(this.direction) }, clone: function () { return (new THREE.Ray).copy(this) } }; THREE.Sphere = function (a, b) { this.center = void 0 !== a ? a : new THREE.Vector3; this.radius = void 0 !== b ? b : 0 }; THREE.Sphere.prototype = { constructor: THREE.Sphere, set: function (a, b) { this.center.copy(a); this.radius = b; return this }, setFromCenterAndPoints: function (a, b) { for (var c = 0, d = 0, e = b.length; d < e; d++) var f = a.distanceToSquared(b[d]), c = Math.max(c, f); this.center = a; this.radius = Math.sqrt(c); return this }, copy: function (a) { this.center.copy(a.center); this.radius = a.radius; return this }, empty: function () { return 0 >= this.radius }, containsPoint: function (a) { return a.distanceToSquared(this.center) <= this.radius * this.radius }, distanceToPoint: function (a) { return a.distanceTo(this.center) - this.radius }, intersectsSphere: function (a) { var b = this.radius + a.radius; return a.center.distanceToSquared(this.center) <= b * b }, clampPoint: function (a, b) { var c = this.center.distanceToSquared(a), d = b || new THREE.Vector3; d.copy(a); c > this.radius * this.radius && (d.sub(this.center).normalize(), d.multiplyScalar(this.radius).add(this.center)); return d }, getBoundingBox: function (a) { a = a || new THREE.Box3; a.set(this.center, this.center); a.expandByScalar(this.radius); return a }, applyMatrix4: function (a) { this.center.applyMatrix4(a); this.radius *= a.getMaxScaleOnAxis(); return this }, translate: function (a) { this.center.add(a); return this }, equals: function (a) { return a.center.equals(this.center) && a.radius === this.radius }, clone: function () { return (new THREE.Sphere).copy(this) } }; THREE.Frustum = function (a, b, c, d, e, f) { this.planes = [void 0 !== a ? a : new THREE.Plane, void 0 !== b ? b : new THREE.Plane, void 0 !== c ? c : new THREE.Plane, void 0 !== d ? d : new THREE.Plane, void 0 !== e ? e : new THREE.Plane, void 0 !== f ? f : new THREE.Plane] }; THREE.Frustum.prototype = { constructor: THREE.Frustum, set: function (a, b, c, d, e, f) { var g = this.planes; g[0].copy(a); g[1].copy(b); g[2].copy(c); g[3].copy(d); g[4].copy(e); g[5].copy(f); return this }, copy: function (a) { for (var b = this.planes, c = 0; 6 > c; c++) b[c].copy(a.planes[c]); return this }, setFromMatrix: function (a) { var b = this.planes, c = a.elements, a = c[0], d = c[1], e = c[2], f = c[3], g = c[4], h = c[5], i = c[6], k = c[7], l = c[8], m = c[9], p = c[10], s = c[11], r = c[12], n = c[13], q = c[14], c = c[15]; b[0].setComponents(f - a, k - g, s - l, c - r).normalize(); b[1].setComponents(f + a, k + g, s + l, c + r).normalize(); b[2].setComponents(f + d, k + h, s + m, c + n).normalize(); b[3].setComponents(f - d, k - h, s - m, c - n).normalize(); b[4].setComponents(f - e, k - i, s - p, c - q).normalize(); b[5].setComponents(f + e, k + i, s + p, c + q).normalize(); return this }, intersectsObject: function () { var a = new THREE.Vector3; return function (b) { var c = b.matrixWorld, d = this.planes, b = -b.geometry.boundingSphere.radius * c.getMaxScaleOnAxis(); a.getPositionFromMatrix(c); for (c = 0; 6 > c; c++) if (d[c].distanceToPoint(a) < b) return !1; return !0 } }(), intersectsSphere: function (a) { for (var b = this.planes, c = a.center, a = -a.radius, d = 0; 6 > d; d++) if (b[d].distanceToPoint(c) < a) return !1; return !0 }, containsPoint: function (a) { for (var b = this.planes, c = 0; 6 > c; c++) if (0 > b[c].distanceToPoint(a)) return !1; return !0 }, clone: function () { return (new THREE.Frustum).copy(this) } }; THREE.Plane = function (a, b) { this.normal = void 0 !== a ? a : new THREE.Vector3(1, 0, 0); this.constant = void 0 !== b ? b : 0 }; THREE.Plane.prototype = { constructor: THREE.Plane, set: function (a, b) { this.normal.copy(a); this.constant = b; return this }, setComponents: function (a, b, c, d) { this.normal.set(a, b, c); this.constant = d; return this }, setFromNormalAndCoplanarPoint: function (a, b) { this.normal.copy(a); this.constant = -b.dot(this.normal); return this }, setFromCoplanarPoints: function () { var a = new THREE.Vector3, b = new THREE.Vector3; return function (c, d, e) { d = a.subVectors(e, d).cross(b.subVectors(c, d)).normalize(); this.setFromNormalAndCoplanarPoint(d, c); return this } }(), copy: function (a) { this.normal.copy(a.normal); this.constant = a.constant; return this }, normalize: function () { var a = 1 / this.normal.length(); this.normal.multiplyScalar(a); this.constant *= a; return this }, negate: function () { this.constant *= -1; this.normal.negate(); return this }, distanceToPoint: function (a) { return this.normal.dot(a) + this.constant }, distanceToSphere: function (a) { return this.distanceToPoint(a.center) - a.radius }, projectPoint: function (a, b) { return this.orthoPoint(a, b).sub(a).negate() }, orthoPoint: function (a, b) { var c = this.distanceToPoint(a); return (b || new THREE.Vector3).copy(this.normal).multiplyScalar(c) }, isIntersectionLine: function (a) { var b = this.distanceToPoint(a.start), a = this.distanceToPoint(a.end); return 0 > b && 0 < a || 0 > a && 0 < b }, intersectLine: function () { var a = new THREE.Vector3; return function (b, c) { var d = c || new THREE.Vector3, e = b.delta(a), f = this.normal.dot(e); if (0 == f) { if (0 == this.distanceToPoint(b.start)) return d.copy(b.start) } else return f = -(b.start.dot(this.normal) + this.constant) / f, 0 > f || 1 < f ? void 0 : d.copy(e).multiplyScalar(f).add(b.start) } }(), coplanarPoint: function (a) { return (a || new THREE.Vector3).copy(this.normal).multiplyScalar(-this.constant) }, applyMatrix4: function () { var a = new THREE.Vector3, b = new THREE.Vector3; return function (c, d) { var d = d || (new THREE.Matrix3).getInverse(c).transpose(), e = a.copy(this.normal).applyMatrix3(d), f = this.coplanarPoint(b); f.applyMatrix4(c); this.setFromNormalAndCoplanarPoint(e, f); return this } }(), translate: function (a) { this.constant -= a.dot(this.normal); return this }, equals: function (a) { return a.normal.equals(this.normal) && a.constant == this.constant }, clone: function () { return (new THREE.Plane).copy(this) } }; THREE.Math = { clamp: function (a, b, c) { return a < b ? b : a > c ? c : a }, clampBottom: function (a, b) { return a < b ? b : a }, mapLinear: function (a, b, c, d, e) { return d + (a - b) * (e - d) / (c - b) }, smoothstep: function (a, b, c) { if (a <= b) return 0; if (a >= c) return 1; a = (a - b) / (c - b); return a * a * (3 - 2 * a) }, smootherstep: function (a, b, c) { if (a <= b) return 0; if (a >= c) return 1; a = (a - b) / (c - b); return a * a * a * (a * (6 * a - 15) + 10) }, random16: function () { return (65280 * Math.random() + 255 * Math.random()) / 65535 }, randInt: function (a, b) { return a + Math.floor(Math.random() * (b - a + 1)) }, randFloat: function (a, b) { return a + Math.random() * (b - a) }, randFloatSpread: function (a) { return a * (0.5 - Math.random()) }, sign: function (a) { return 0 > a ? -1 : 0 < a ? 1 : 0 }, degToRad: function () { var a = Math.PI / 180; return function (b) { return b * a } }(), radToDeg: function () { var a = 180 / Math.PI; return function (b) { return b * a } }() }; THREE.Spline = function (a) { function b(a, b, c, d, e, f, g) { a = 0.5 * (c - a); d = 0.5 * (d - b); return (2 * (b - c) + a + d) * g + (-3 * (b - c) - 2 * a - d) * f + a * e + b } this.points = a; var c = [], d = {x: 0, y: 0, z: 0}, e, f, g, h, i, k, l, m, p; this.initFromArray = function (a) { this.points = []; for (var b = 0; b < a.length; b++) this.points[b] = {x: a[b][0], y: a[b][1], z: a[b][2]} }; this.getPoint = function (a) { e = (this.points.length - 1) * a; f = Math.floor(e); g = e - f; c[0] = 0 === f ? f : f - 1; c[1] = f; c[2] = f > this.points.length - 2 ? this.points.length - 1 : f + 1; c[3] = f > this.points.length - 3 ? this.points.length - 1 : f + 2; k = this.points[c[0]]; l = this.points[c[1]]; m = this.points[c[2]]; p = this.points[c[3]]; h = g * g; i = g * h; d.x = b(k.x, l.x, m.x, p.x, g, h, i); d.y = b(k.y, l.y, m.y, p.y, g, h, i); d.z = b(k.z, l.z, m.z, p.z, g, h, i); return d }; this.getControlPointsArray = function () { var a, b, c = this.points.length, d = []; for (a = 0; a < c; a++) b = this.points[a], d[a] = [b.x, b.y, b.z]; return d }; this.getLength = function (a) { var b, c, d, e = b = b = 0, f = new THREE.Vector3, g = new THREE.Vector3, h = [], i = 0; h[0] = 0; a || (a = 100); c = this.points.length * a; f.copy(this.points[0]); for (a = 1; a < c; a++) b = a / c, d = this.getPoint(b), g.copy(d), i += g.distanceTo(f), f.copy(d), b *= this.points.length - 1, b = Math.floor(b), b != e && (h[b] = i, e = b); h[h.length] = i; return {chunks: h, total: i} }; this.reparametrizeByArcLength = function (a) { var b, c, d, e, f, g, h = [], i = new THREE.Vector3, k = this.getLength(); h.push(i.copy(this.points[0]).clone()); for (b = 1; b < this.points.length; b++) { c = k.chunks[b] - k.chunks[b - 1]; g = Math.ceil(a * c / k.total); e = (b - 1) / (this.points.length - 1); f = b / (this.points.length - 1); for (c = 1; c < g - 1; c++) d = e + c * (1 / g) * (f - e), d = this.getPoint(d), h.push(i.copy(d).clone()); h.push(i.copy(this.points[b]).clone()) } this.points = h } }; THREE.Triangle = function (a, b, c) { this.a = void 0 !== a ? a : new THREE.Vector3; this.b = void 0 !== b ? b : new THREE.Vector3; this.c = void 0 !== c ? c : new THREE.Vector3 }; THREE.Triangle.normal = function () { var a = new THREE.Vector3; return function (b, c, d, e) { e = e || new THREE.Vector3; e.subVectors(d, c); a.subVectors(b, c); e.cross(a); b = e.lengthSq(); return 0 < b ? e.multiplyScalar(1 / Math.sqrt(b)) : e.set(0, 0, 0) } }(); THREE.Triangle.barycoordFromPoint = function () { var a = new THREE.Vector3, b = new THREE.Vector3, c = new THREE.Vector3; return function (d, e, f, g, h) { a.subVectors(g, e); b.subVectors(f, e); c.subVectors(d, e); var d = a.dot(a), e = a.dot(b), f = a.dot(c), i = b.dot(b), g = b.dot(c), k = d * i - e * e, h = h || new THREE.Vector3; if (0 == k) return h.set(-2, -1, -1); k = 1 / k; i = (i * f - e * g) * k; d = (d * g - e * f) * k; return h.set(1 - i - d, d, i) } }(); THREE.Triangle.containsPoint = function () { var a = new THREE.Vector3; return function (b, c, d, e) { b = THREE.Triangle.barycoordFromPoint(b, c, d, e, a); return 0 <= b.x && 0 <= b.y && 1 >= b.x + b.y } }(); THREE.Triangle.prototype = { constructor: THREE.Triangle, set: function (a, b, c) { this.a.copy(a); this.b.copy(b); this.c.copy(c); return this }, setFromPointsAndIndices: function (a, b, c, d) { this.a.copy(a[b]); this.b.copy(a[c]); this.c.copy(a[d]); return this }, copy: function (a) { this.a.copy(a.a); this.b.copy(a.b); this.c.copy(a.c); return this }, area: function () { var a = new THREE.Vector3, b = new THREE.Vector3; return function () { a.subVectors(this.c, this.b); b.subVectors(this.a, this.b); return 0.5 * a.cross(b).length() } }(), midpoint: function (a) { return (a || new THREE.Vector3).addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3) }, normal: function (a) { return THREE.Triangle.normal(this.a, this.b, this.c, a) }, plane: function (a) { return (a || new THREE.Plane).setFromCoplanarPoints(this.a, this.b, this.c) }, barycoordFromPoint: function (a, b) { return THREE.Triangle.barycoordFromPoint(a, this.a, this.b, this.c, b) }, containsPoint: function (a) { return THREE.Triangle.containsPoint(a, this.a, this.b, this.c) }, equals: function (a) { return a.a.equals(this.a) && a.b.equals(this.b) && a.c.equals(this.c) }, clone: function () { return (new THREE.Triangle).copy(this) } }; THREE.Vertex = function (a) { console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead."); return a }; THREE.UV = function (a, b) { console.warn("THREE.UV has been DEPRECATED. Use THREE.Vector2 instead."); return new THREE.Vector2(a, b) }; THREE.Clock = function (a) { this.autoStart = void 0 !== a ? a : !0; this.elapsedTime = this.oldTime = this.startTime = 0; this.running = !1 }; THREE.extend(THREE.Clock.prototype, { start: function () { this.oldTime = this.startTime = void 0 !== window.performance && void 0 !== window.performance.now ? window.performance.now() : Date.now(); this.running = !0 }, stop: function () { this.getElapsedTime(); this.running = !1 }, getElapsedTime: function () { this.getDelta(); return this.elapsedTime }, getDelta: function () { var a = 0; this.autoStart && !this.running && this.start(); if (this.running) { var b = void 0 !== window.performance && void 0 !== window.performance.now ? window.performance.now() : Date.now(), a = 0.001 * (b - this.oldTime); this.oldTime = b; this.elapsedTime += a } return a } }); THREE.EventDispatcher = function () { var a = {}; this.addEventListener = function (b, c) { void 0 === a[b] && (a[b] = []); -1 === a[b].indexOf(c) && a[b].push(c) }; this.removeEventListener = function (b, c) { var d = a[b].indexOf(c); -1 !== d && a[b].splice(d, 1) }; this.dispatchEvent = function (b) { var c = a[b.type]; if (void 0 !== c) { b.target = this; for (var d = 0, e = c.length; d < e; d++) c[d].call(this, b) } } }; (function (a) { a.Raycaster = function (b, c, d, e) { this.ray = new a.Ray(b, c); 0 < this.ray.direction.lengthSq() && this.ray.direction.normalize(); this.near = d || 0; this.far = e || Infinity }; var b = new a.Sphere, c = new a.Ray, d = new a.Plane, e = new a.Vector3, f = new a.Vector3, g = new a.Matrix4, h = function (a, b) { return a.distance - b.distance }, i = function (h, i, k) { if (h instanceof a.Particle) { f.getPositionFromMatrix(h.matrixWorld); i = i.ray.distanceToPoint(f); if (i > h.scale.x) return k; k.push({distance: i, point: h.position, face: null, object: h}) } else if (h instanceof a.Mesh) { f.getPositionFromMatrix(h.matrixWorld); b.set(f, h.geometry.boundingSphere.radius * h.matrixWorld.getMaxScaleOnAxis()); if (!i.ray.isIntersectionSphere(b)) return k; var s = h.geometry, r = s.vertices, n = h.material instanceof a.MeshFaceMaterial, q = !0 === n ? h.material.materials : null, z = h.material.side, t, x, u, B = i.precision; h.matrixRotationWorld.extractRotation(h.matrixWorld); g.getInverse(h.matrixWorld); c.copy(i.ray).applyMatrix4(g); for (var G = 0, D = s.faces.length; G < D; G++) { var w = s.faces[G], z = !0 === n ? q[w.materialIndex] : h.material; if (void 0 !== z) { d.setFromNormalAndCoplanarPoint(w.normal, r[w.a]); var I = c.distanceToPlane(d); if (!(Math.abs(I) < B) && !(0 > I)) { z = z.side; if (z !== a.DoubleSide && (t = c.direction.dot(d.normal), !(z === a.FrontSide ? 0 > t : 0 < t))) continue; if (!(I < i.near || I > i.far)) { e = c.at(I, e); if (w instanceof a.Face3) { if (z = r[w.a], t = r[w.b], x = r[w.c], !a.Triangle.containsPoint(e, z, t, x)) continue } else if (w instanceof a.Face4) { if (z = r[w.a], t = r[w.b], x = r[w.c], u = r[w.d], !a.Triangle.containsPoint(e, z, t, u) && !a.Triangle.containsPoint(e, t, x, u)) continue } else throw Error("face type not supported"); k.push({distance: I, point: i.ray.at(I), face: w, faceIndex: G, object: h}) } } } } } }, k = function (a, b, c) { for (var a = a.getDescendants(), d = 0, e = a.length; d < e; d++) i(a[d], b, c) }; a.Raycaster.prototype.precision = 1E-4; a.Raycaster.prototype.set = function (a, b) { this.ray.set(a, b); 0 < this.ray.direction.length() && this.ray.direction.normalize() }; a.Raycaster.prototype.intersectObject = function (a, b) { var c = []; !0 === b && k(a, this, c); i(a, this, c); c.sort(h); return c }; a.Raycaster.prototype.intersectObjects = function (a, b) { for (var c = [], d = 0, e = a.length; d < e; d++) i(a[d], this, c), !0 === b && k(a[d], this, c); c.sort(h); return c } })(THREE); THREE.Object3D = function () { this.id = THREE.Object3DIdCount++; this.name = ""; this.parent = void 0; this.children = []; this.up = new THREE.Vector3(0, 1, 0); this.position = new THREE.Vector3; this.rotation = new THREE.Vector3; this.eulerOrder = THREE.Object3D.defaultEulerOrder; this.scale = new THREE.Vector3(1, 1, 1); this.renderDepth = null; this.rotationAutoUpdate = !0; this.matrix = new THREE.Matrix4; this.matrixWorld = new THREE.Matrix4; this.matrixRotationWorld = new THREE.Matrix4; this.matrixWorldNeedsUpdate = this.matrixAutoUpdate = !0; this.quaternion = new THREE.Quaternion; this.useQuaternion = !1; this.visible = !0; this.receiveShadow = this.castShadow = !1; this.frustumCulled = !0; this.userData = {} }; THREE.Object3D.prototype = { constructor: THREE.Object3D, applyMatrix: function () { var a = new THREE.Matrix4; return function (b) { this.matrix.multiplyMatrices(b, this.matrix); this.position.getPositionFromMatrix(this.matrix); this.scale.getScaleFromMatrix(this.matrix); a.extractRotation(this.matrix); !0 === this.useQuaternion ? this.quaternion.setFromRotationMatrix(a) : this.rotation.setEulerFromRotationMatrix(a, this.eulerOrder) } }(), translate: function () { var a = new THREE.Vector3; return function (b, c) { a.copy(c); !0 === this.useQuaternion ? a.applyQuaternion(this.quaternion) : a.applyEuler(this.rotation, this.eulerOrder); a.multiplyScalar(b); this.position.add(a); return this } }(), translateX: function () { var a = new THREE.Vector3(1, 0, 0); return function (b) { return this.translate(b, a) } }(), translateY: function () { var a = new THREE.Vector3(0, 1, 0); return function (b) { return this.translate(b, a) } }(), translateZ: function () { var a = new THREE.Vector3(0, 0, 1); return function (b) { return this.translate(b, a) } }(), localToWorld: function (a) { return a.applyMatrix4(this.matrixWorld) }, worldToLocal: function () { var a = new THREE.Matrix4; return function (b) { return b.applyMatrix4(a.getInverse(this.matrixWorld)) } }(), lookAt: function () { var a = new THREE.Matrix4; return function (b) { a.lookAt(b, this.position, this.up); !0 === this.useQuaternion ? this.quaternion.setFromRotationMatrix(a) : this.rotation.setEulerFromRotationMatrix(a, this.eulerOrder) } }(), add: function (a) { if (a === this) console.warn("THREE.Object3D.add: An object can't be added as a child of itself."); else if (a instanceof THREE.Object3D) { void 0 !== a.parent && a.parent.remove(a); a.parent = this; this.children.push(a); for (var b = this; void 0 !== b.parent;) b = b.parent; void 0 !== b && b instanceof THREE.Scene && b.__addObject(a) } }, remove: function (a) { var b = this.children.indexOf(a); if (-1 !== b) { a.parent = void 0; this.children.splice(b, 1); for (b = this; void 0 !== b.parent;) b = b.parent; void 0 !== b && b instanceof THREE.Scene && b.__removeObject(a) } }, traverse: function (a) { a(this); for (var b = 0, c = this.children.length; b < c; b++) this.children[b].traverse(a) }, getChildByName: function (a, b) { for (var c = 0, d = this.children.length; c < d; c++) { var e = this.children[c]; if (e.name === a || !0 === b && (e = e.getChildByName(a, b), void 0 !== e)) return e } }, getDescendants: function (a) { void 0 === a && (a = []); Array.prototype.push.apply(a, this.children); for (var b = 0, c = this.children.length; b < c; b++) this.children[b].getDescendants(a); return a }, updateMatrix: function () { this.matrix.setPosition(this.position); !1 === this.useQuaternion ? this.matrix.setRotationFromEuler(this.rotation, this.eulerOrder) : this.matrix.setRotationFromQuaternion(this.quaternion); (1 !== this.scale.x || 1 !== this.scale.y || 1 !== this.scale.z) && this.matrix.scale(this.scale); this.matrixWorldNeedsUpdate = !0 }, updateMatrixWorld: function (a) { !0 === this.matrixAutoUpdate && this.updateMatrix(); if (!0 === this.matrixWorldNeedsUpdate || !0 === a) void 0 === this.parent ? this.matrixWorld.copy(this.matrix) : this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix), this.matrixWorldNeedsUpdate = !1, a = !0; for (var b = 0, c = this.children.length; b < c; b++) this.children[b].updateMatrixWorld(a) }, clone: function (a) { void 0 === a && (a = new THREE.Object3D); a.name = this.name; a.up.copy(this.up); a.position.copy(this.position); a.rotation instanceof THREE.Vector3 && a.rotation.copy(this.rotation); a.eulerOrder = this.eulerOrder; a.scale.copy(this.scale); a.renderDepth = this.renderDepth; a.rotationAutoUpdate = this.rotationAutoUpdate; a.matrix.copy(this.matrix); a.matrixWorld.copy(this.matrixWorld); a.matrixRotationWorld.copy(this.matrixRotationWorld); a.matrixAutoUpdate = this.matrixAutoUpdate; a.matrixWorldNeedsUpdate = this.matrixWorldNeedsUpdate; a.quaternion.copy(this.quaternion); a.useQuaternion = this.useQuaternion; a.visible = this.visible; a.castShadow = this.castShadow; a.receiveShadow = this.receiveShadow; a.frustumCulled = this.frustumCulled; for (var b = 0; b < this.children.length; b++) a.add(this.children[b].clone()); return a } }; THREE.Object3D.defaultEulerOrder = "XYZ"; THREE.Object3DIdCount = 0; THREE.Projector = function () { function a() { if (f === h) { var a = new THREE.RenderableObject; g.push(a); h++; f++; return a } return g[f++] } function b() { if (k === m) { var a = new THREE.RenderableVertex; l.push(a); m++; k++; return a } return l[k++] } function c(a, b) { return b.z - a.z } function d(a, b) { var c = 0, d = 1, e = a.z + a.w, f = b.z + b.w, g = -a.z + a.w, h = -b.z + b.w; if (0 <= e && 0 <= f && 0 <= g && 0 <= h) return !0; if (0 > e && 0 > f || 0 > g && 0 > h) return !1; 0 > e ? c = Math.max(c, e / (e - f)) : 0 > f && (d = Math.min(d, e / (e - f))); 0 > g ? c = Math.max(c, g / (g - h)) : 0 > h && (d = Math.min(d, g / (g - h))); if (d < c) return !1; a.lerp(b, c); b.lerp(a, 1 - d); return !0 } var e, f, g = [], h = 0, i, k, l = [], m = 0, p, s, r = [], n = 0, q, z = [], t = 0, x, u, B = [], G = 0, D, w, I = [], J = 0, E = {objects: [], sprites: [], lights: [], elements: []}, Z = new THREE.Vector3, A = new THREE.Vector4, S = new THREE.Box3(new THREE.Vector3(-1, -1, -1), new THREE.Vector3(1, 1, 1)), F = new THREE.Box3, H = Array(3), K = Array(4), N = new THREE.Matrix4, fa = new THREE.Matrix4, ma, eb = new THREE.Matrix4, M = new THREE.Matrix3, U = new THREE.Matrix3, ja = new THREE.Vector3, L = new THREE.Frustum, ca = new THREE.Vector4, ta = new THREE.Vector4; this.projectVector = function (a, b) { b.matrixWorldInverse.getInverse(b.matrixWorld); fa.multiplyMatrices(b.projectionMatrix, b.matrixWorldInverse); return a.applyProjection(fa) }; this.unprojectVector = function (a, b) { b.projectionMatrixInverse.getInverse(b.projectionMatrix); fa.multiplyMatrices(b.matrixWorld, b.projectionMatrixInverse); return a.applyProjection(fa) }; this.pickingRay = function (a, b) { a.z = -1; var c = new THREE.Vector3(a.x, a.y, 1); this.unprojectVector(a, b); this.unprojectVector(c, b); c.sub(a).normalize(); return new THREE.Raycaster(a, c) }; this.projectScene = function (g, h, m, db) { var La = !1, Oa, ea, ha, V, $, Y, ia, ra, na, Pa, Ba, fb, jb; w = u = q = s = 0; E.elements.length = 0; g.updateMatrixWorld(); void 0 === h.parent && h.updateMatrixWorld(); N.copy(h.matrixWorldInverse.getInverse(h.matrixWorld)); fa.multiplyMatrices(h.projectionMatrix, N); U.getInverse(N); U.transpose(); L.setFromMatrix(fa); f = 0; E.objects.length = 0; E.sprites.length = 0; E.lights.length = 0; var Sa = function (b) { for (var c = 0, d = b.children.length; c < d; c++) { var f = b.children[c]; if (!1 !== f.visible) { if (f instanceof THREE.Light) E.lights.push(f); else if (f instanceof THREE.Mesh || f instanceof THREE.Line) { if (!1 === f.frustumCulled || !0 === L.intersectsObject(f)) e = a(), e.object = f, null !== f.renderDepth ? e.z = f.renderDepth : (Z.getPositionFromMatrix(f.matrixWorld), Z.applyProjection(fa), e.z = Z.z), E.objects.push(e) } else f instanceof THREE.Sprite || f instanceof THREE.Particle ? (e = a(), e.object = f, null !== f.renderDepth ? e.z = f.renderDepth : (Z.getPositionFromMatrix(f.matrixWorld), Z.applyProjection(fa), e.z = Z.z), E.sprites.push(e)) : (e = a(), e.object = f, null !== f.renderDepth ? e.z = f.renderDepth : (Z.getPositionFromMatrix(f.matrixWorld), Z.applyProjection(fa), e.z = Z.z), E.objects.push(e)); Sa(f) } } }; Sa(g); !0 === m && E.objects.sort(c); g = 0; for (m = E.objects.length; g < m; g++) if (ra = E.objects[g].object, ma = ra.matrixWorld, k = 0, ra instanceof THREE.Mesh) { na = ra.geometry; ha = na.vertices; Pa = na.faces; na = na.faceVertexUvs; M.getInverse(ma); M.transpose(); fb = ra.material instanceof THREE.MeshFaceMaterial; jb = !0 === fb ? ra.material : null; Oa = 0; for (ea = ha.length; Oa < ea; Oa++) i = b(), i.positionWorld.copy(ha[Oa]).applyMatrix4(ma), i.positionScreen.copy(i.positionWorld).applyMatrix4(fa), i.positionScreen.x /= i.positionScreen.w, i.positionScreen.y /= i.positionScreen.w, i.positionScreen.z /= i.positionScreen.w, i.visible = !(-1 > i.positionScreen.x || 1 < i.positionScreen.x || -1 > i.positionScreen.y || 1 < i.positionScreen.y || -1 > i.positionScreen.z || 1 < i.positionScreen.z); ha = 0; for (Oa = Pa.length; ha < Oa; ha++) { ea = Pa[ha]; var ob = !0 === fb ? jb.materials[ea.materialIndex] : ra.material; if (void 0 !== ob) { Y = ob.side; if (ea instanceof THREE.Face3) if (V = l[ea.a], $ = l[ea.b], ia = l[ea.c], H[0] = V.positionScreen, H[1] = $.positionScreen, H[2] = ia.positionScreen, !0 === V.visible || !0 === $.visible || !0 === ia.visible || S.isIntersectionBox(F.setFromPoints(H))) if (La = 0 > (ia.positionScreen.x - V.positionScreen.x) * ($.positionScreen.y - V.positionScreen.y) - (ia.positionScreen.y - V.positionScreen.y) * ($.positionScreen.x - V.positionScreen.x), Y === THREE.DoubleSide || La === (Y === THREE.FrontSide)) s === n ? (Ba = new THREE.RenderableFace3, r.push(Ba), n++, s++, p = Ba) : p = r[s++], p.v1.copy(V), p.v2.copy($), p.v3.copy(ia); else continue; else continue; else if (ea instanceof THREE.Face4) if (V = l[ea.a], $ = l[ea.b], ia = l[ea.c], Ba = l[ea.d], K[0] = V.positionScreen, K[1] = $.positionScreen, K[2] = ia.positionScreen, K[3] = Ba.positionScreen, !0 === V.visible || !0 === $.visible || !0 === ia.visible || !0 === Ba.visible || S.isIntersectionBox(F.setFromPoints(K))) if (La = 0 > (Ba.positionScreen.x - V.positionScreen.x) * ($.positionScreen.y - V.positionScreen.y) - (Ba.positionScreen.y - V.positionScreen.y) * ($.positionScreen.x - V.positionScreen.x) || 0 > ($.positionScreen.x - ia.positionScreen.x) * (Ba.positionScreen.y - ia.positionScreen.y) - ($.positionScreen.y - ia.positionScreen.y) * (Ba.positionScreen.x - ia.positionScreen.x), Y === THREE.DoubleSide || La === (Y === THREE.FrontSide)) { if (q === t) { var Gb = new THREE.RenderableFace4; z.push(Gb); t++; q++; p = Gb } else p = z[q++]; p.v1.copy(V); p.v2.copy($); p.v3.copy(ia); p.v4.copy(Ba) } else continue; else continue; p.normalModel.copy(ea.normal); !1 === La && (Y === THREE.BackSide || Y === THREE.DoubleSide) && p.normalModel.negate(); p.normalModel.applyMatrix3(M).normalize(); p.normalModelView.copy(p.normalModel).applyMatrix3(U); p.centroidModel.copy(ea.centroid).applyMatrix4(ma); ia = ea.vertexNormals; V = 0; for ($ = ia.length; V < $; V++) Ba = p.vertexNormalsModel[V], Ba.copy(ia[V]), !1 === La && (Y === THREE.BackSide || Y === THREE.DoubleSide) && Ba.negate(), Ba.applyMatrix3(M).normalize(), p.vertexNormalsModelView[V].copy(Ba).applyMatrix3(U); p.vertexNormalsLength = ia.length; V = 0; for ($ = na.length; V < $; V++) if (Ba = na[V][ha], void 0 !== Ba) { Y = 0; for (ia = Ba.length; Y < ia; Y++) p.uvs[V][Y] = Ba[Y] } p.color = ea.color; p.material = ob; ja.copy(p.centroidModel).applyProjection(fa); p.z = ja.z; E.elements.push(p) } } } else if (ra instanceof THREE.Line) { eb.multiplyMatrices(fa, ma); ha = ra.geometry.vertices; V = b(); V.positionScreen.copy(ha[0]).applyMatrix4(eb); Pa = ra.type === THREE.LinePieces ? 2 : 1; Oa = 1; for (ea = ha.length; Oa < ea; Oa++) V = b(), V.positionScreen.copy(ha[Oa]).applyMatrix4(eb), 0 < (Oa + 1) % Pa || ($ = l[k - 2], ca.copy(V.positionScreen), ta.copy($.positionScreen), !0 === d(ca, ta) && (ca.multiplyScalar(1 / ca.w), ta.multiplyScalar(1 / ta.w), u === G ? (na = new THREE.RenderableLine, B.push(na), G++, u++, x = na) : x = B[u++], x.v1.positionScreen.copy(ca), x.v2.positionScreen.copy(ta), x.z = Math.max(ca.z, ta.z), x.material = ra.material, E.elements.push(x))) } g = 0; for (m = E.sprites.length; g < m; g++) ra = E.sprites[g].object, ma = ra.matrixWorld, ra instanceof THREE.Particle && (A.set(ma.elements[12], ma.elements[13], ma.elements[14], 1), A.applyMatrix4(fa), A.z /= A.w, 0 < A.z && 1 > A.z && (w === J ? (La = new THREE.RenderableParticle, I.push(La), J++, w++, D = La) : D = I[w++], D.object = ra, D.x = A.x / A.w, D.y = A.y / A.w, D.z = A.z, D.rotation = ra.rotation.z, D.scale.x = ra.scale.x * Math.abs(D.x - (A.x + h.projectionMatrix.elements[0]) / (A.w + h.projectionMatrix.elements[12])), D.scale.y = ra.scale.y * Math.abs(D.y - (A.y + h.projectionMatrix.elements[5]) / (A.w + h.projectionMatrix.elements[13])), D.material = ra.material, E.elements.push(D))); !0 === db && E.elements.sort(c); return E } }; THREE.Face3 = function (a, b, c, d, e, f) { this.a = a; this.b = b; this.c = c; this.normal = d instanceof THREE.Vector3 ? d : new THREE.Vector3; this.vertexNormals = d instanceof Array ? d : []; this.color = e instanceof THREE.Color ? e : new THREE.Color; this.vertexColors = e instanceof Array ? e : []; this.vertexTangents = []; this.materialIndex = void 0 !== f ? f : 0; this.centroid = new THREE.Vector3 }; THREE.Face3.prototype = { constructor: THREE.Face3, clone: function () { var a = new THREE.Face3(this.a, this.b, this.c); a.normal.copy(this.normal); a.color.copy(this.color); a.centroid.copy(this.centroid); a.materialIndex = this.materialIndex; var b, c; b = 0; for (c = this.vertexNormals.length; b < c; b++) a.vertexNormals[b] = this.vertexNormals[b].clone(); b = 0; for (c = this.vertexColors.length; b < c; b++) a.vertexColors[b] = this.vertexColors[b].clone(); b = 0; for (c = this.vertexTangents.length; b < c; b++) a.vertexTangents[b] = this.vertexTangents[b].clone(); return a } }; THREE.Face4 = function (a, b, c, d, e, f, g) { this.a = a; this.b = b; this.c = c; this.d = d; this.normal = e instanceof THREE.Vector3 ? e : new THREE.Vector3; this.vertexNormals = e instanceof Array ? e : []; this.color = f instanceof THREE.Color ? f : new THREE.Color; this.vertexColors = f instanceof Array ? f : []; this.vertexTangents = []; this.materialIndex = void 0 !== g ? g : 0; this.centroid = new THREE.Vector3 }; THREE.Face4.prototype = { constructor: THREE.Face4, clone: function () { var a = new THREE.Face4(this.a, this.b, this.c, this.d); a.normal.copy(this.normal); a.color.copy(this.color); a.centroid.copy(this.centroid); a.materialIndex = this.materialIndex; var b, c; b = 0; for (c = this.vertexNormals.length; b < c; b++) a.vertexNormals[b] = this.vertexNormals[b].clone(); b = 0; for (c = this.vertexColors.length; b < c; b++) a.vertexColors[b] = this.vertexColors[b].clone(); b = 0; for (c = this.vertexTangents.length; b < c; b++) a.vertexTangents[b] = this.vertexTangents[b].clone(); return a } }; THREE.Geometry = function () { THREE.EventDispatcher.call(this); this.id = THREE.GeometryIdCount++; this.name = ""; this.vertices = []; this.colors = []; this.normals = []; this.faces = []; this.faceUvs = [[]]; this.faceVertexUvs = [[]]; this.morphTargets = []; this.morphColors = []; this.morphNormals = []; this.skinWeights = []; this.skinIndices = []; this.lineDistances = []; this.boundingSphere = this.boundingBox = null; this.hasTangents = !1; this.dynamic = !0; this.buffersNeedUpdate = this.lineDistancesNeedUpdate = this.colorsNeedUpdate = this.tangentsNeedUpdate = this.normalsNeedUpdate = this.uvsNeedUpdate = this.elementsNeedUpdate = this.verticesNeedUpdate = !1 }; THREE.Geometry.prototype = { constructor: THREE.Geometry, applyMatrix: function (a) { for (var b = (new THREE.Matrix3).getInverse(a).transpose(), c = 0, d = this.vertices.length; c < d; c++) this.vertices[c].applyMatrix4(a); c = 0; for (d = this.faces.length; c < d; c++) { var e = this.faces[c]; e.normal.applyMatrix3(b).normalize(); for (var f = 0, g = e.vertexNormals.length; f < g; f++) e.vertexNormals[f].applyMatrix3(b).normalize(); e.centroid.applyMatrix4(a) } }, computeCentroids: function () { var a, b, c; a = 0; for (b = this.faces.length; a < b; a++) c = this.faces[a], c.centroid.set(0, 0, 0), c instanceof THREE.Face3 ? (c.centroid.add(this.vertices[c.a]), c.centroid.add(this.vertices[c.b]), c.centroid.add(this.vertices[c.c]), c.centroid.divideScalar(3)) : c instanceof THREE.Face4 && (c.centroid.add(this.vertices[c.a]), c.centroid.add(this.vertices[c.b]), c.centroid.add(this.vertices[c.c]), c.centroid.add(this.vertices[c.d]), c.centroid.divideScalar(4)) }, computeFaceNormals: function () { for (var a = new THREE.Vector3, b = new THREE.Vector3, c = 0, d = this.faces.length; c < d; c++) { var e = this.faces[c], f = this.vertices[e.a], g = this.vertices[e.b]; a.subVectors(this.vertices[e.c], g); b.subVectors(f, g); a.cross(b); a.normalize(); e.normal.copy(a) } }, computeVertexNormals: function (a) { var b, c, d, e; if (void 0 === this.__tmpVertices) { e = this.__tmpVertices = Array(this.vertices.length); b = 0; for (c = this.vertices.length; b < c; b++) e[b] = new THREE.Vector3; b = 0; for (c = this.faces.length; b < c; b++) d = this.faces[b], d instanceof THREE.Face3 ? d.vertexNormals = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3] : d instanceof THREE.Face4 && (d.vertexNormals = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3]) } else { e = this.__tmpVertices; b = 0; for (c = this.vertices.length; b < c; b++) e[b].set(0, 0, 0) } if (a) { var f, g, h, i = new THREE.Vector3, k = new THREE.Vector3, l = new THREE.Vector3, m = new THREE.Vector3, p = new THREE.Vector3; b = 0; for (c = this.faces.length; b < c; b++) d = this.faces[b], d instanceof THREE.Face3 ? (a = this.vertices[d.a], f = this.vertices[d.b], g = this.vertices[d.c], i.subVectors(g, f), k.subVectors(a, f), i.cross(k), e[d.a].add(i), e[d.b].add(i), e[d.c].add(i)) : d instanceof THREE.Face4 && (a = this.vertices[d.a], f = this.vertices[d.b], g = this.vertices[d.c], h = this.vertices[d.d], l.subVectors(h, f), k.subVectors(a, f), l.cross(k), e[d.a].add(l), e[d.b].add(l), e[d.d].add(l), m.subVectors(h, g), p.subVectors(f, g), m.cross(p), e[d.b].add(m), e[d.c].add(m), e[d.d].add(m)) } else { b = 0; for (c = this.faces.length; b < c; b++) d = this.faces[b], d instanceof THREE.Face3 ? (e[d.a].add(d.normal), e[d.b].add(d.normal), e[d.c].add(d.normal)) : d instanceof THREE.Face4 && (e[d.a].add(d.normal), e[d.b].add(d.normal), e[d.c].add(d.normal), e[d.d].add(d.normal)) } b = 0; for (c = this.vertices.length; b < c; b++) e[b].normalize(); b = 0; for (c = this.faces.length; b < c; b++) d = this.faces[b], d instanceof THREE.Face3 ? (d.vertexNormals[0].copy(e[d.a]), d.vertexNormals[1].copy(e[d.b]), d.vertexNormals[2].copy(e[d.c])) : d instanceof THREE.Face4 && (d.vertexNormals[0].copy(e[d.a]), d.vertexNormals[1].copy(e[d.b]), d.vertexNormals[2].copy(e[d.c]), d.vertexNormals[3].copy(e[d.d])) }, computeMorphNormals: function () { var a, b, c, d, e; c = 0; for (d = this.faces.length; c < d; c++) { e = this.faces[c]; e.__originalFaceNormal ? e.__originalFaceNormal.copy(e.normal) : e.__originalFaceNormal = e.normal.clone(); e.__originalVertexNormals || (e.__originalVertexNormals = []); a = 0; for (b = e.vertexNormals.length; a < b; a++) e.__originalVertexNormals[a] ? e.__originalVertexNormals[a].copy(e.vertexNormals[a]) : e.__originalVertexNormals[a] = e.vertexNormals[a].clone() } var f = new THREE.Geometry; f.faces = this.faces; a = 0; for (b = this.morphTargets.length; a < b; a++) { if (!this.morphNormals[a]) { this.morphNormals[a] = {}; this.morphNormals[a].faceNormals = []; this.morphNormals[a].vertexNormals = []; var g = this.morphNormals[a].faceNormals, h = this.morphNormals[a].vertexNormals, i, k; c = 0; for (d = this.faces.length; c < d; c++) e = this.faces[c], i = new THREE.Vector3, k = e instanceof THREE.Face3 ? { a: new THREE.Vector3, b: new THREE.Vector3, c: new THREE.Vector3 } : { a: new THREE.Vector3, b: new THREE.Vector3, c: new THREE.Vector3, d: new THREE.Vector3 }, g.push(i), h.push(k) } g = this.morphNormals[a]; f.vertices = this.morphTargets[a].vertices; f.computeFaceNormals(); f.computeVertexNormals(); c = 0; for (d = this.faces.length; c < d; c++) e = this.faces[c], i = g.faceNormals[c], k = g.vertexNormals[c], i.copy(e.normal), e instanceof THREE.Face3 ? (k.a.copy(e.vertexNormals[0]), k.b.copy(e.vertexNormals[1]), k.c.copy(e.vertexNormals[2])) : (k.a.copy(e.vertexNormals[0]), k.b.copy(e.vertexNormals[1]), k.c.copy(e.vertexNormals[2]), k.d.copy(e.vertexNormals[3])) } c = 0; for (d = this.faces.length; c < d; c++) e = this.faces[c], e.normal = e.__originalFaceNormal, e.vertexNormals = e.__originalVertexNormals }, computeTangents: function () { function a(a, b, c, d, e, f, w) { h = a.vertices[b]; i = a.vertices[c]; k = a.vertices[d]; l = g[e]; m = g[f]; p = g[w]; s = i.x - h.x; r = k.x - h.x; n = i.y - h.y; q = k.y - h.y; z = i.z - h.z; t = k.z - h.z; x = m.x - l.x; u = p.x - l.x; B = m.y - l.y; G = p.y - l.y; D = 1 / (x * G - u * B); E.set((G * s - B * r) * D, (G * n - B * q) * D, (G * z - B * t) * D); Z.set((x * r - u * s) * D, (x * q - u * n) * D, (x * t - u * z) * D); I[b].add(E); I[c].add(E); I[d].add(E); J[b].add(Z); J[c].add(Z); J[d].add(Z) } var b, c, d, e, f, g, h, i, k, l, m, p, s, r, n, q, z, t, x, u, B, G, D, w, I = [], J = [], E = new THREE.Vector3, Z = new THREE.Vector3, A = new THREE.Vector3, S = new THREE.Vector3, F = new THREE.Vector3; b = 0; for (c = this.vertices.length; b < c; b++) I[b] = new THREE.Vector3, J[b] = new THREE.Vector3; b = 0; for (c = this.faces.length; b < c; b++) f = this.faces[b], g = this.faceVertexUvs[0][b], f instanceof THREE.Face3 ? a(this, f.a, f.b, f.c, 0, 1, 2) : f instanceof THREE.Face4 && (a(this, f.a, f.b, f.d, 0, 1, 3), a(this, f.b, f.c, f.d, 1, 2, 3)); var H = ["a", "b", "c", "d"]; b = 0; for (c = this.faces.length; b < c; b++) { f = this.faces[b]; for (d = 0; d < f.vertexNormals.length; d++) F.copy(f.vertexNormals[d]), e = f[H[d]], w = I[e], A.copy(w), A.sub(F.multiplyScalar(F.dot(w))).normalize(), S.crossVectors(f.vertexNormals[d], w), e = S.dot(J[e]), e = 0 > e ? -1 : 1, f.vertexTangents[d] = new THREE.Vector4(A.x, A.y, A.z, e) } this.hasTangents = !0 }, computeLineDistances: function () { for (var a = 0, b = this.vertices, c = 0, d = b.length; c < d; c++) 0 < c && (a += b[c].distanceTo(b[c - 1])), this.lineDistances[c] = a }, computeBoundingBox: function () { null === this.boundingBox && (this.boundingBox = new THREE.Box3); this.boundingBox.setFromPoints(this.vertices) }, computeBoundingSphere: function () { null === this.boundingSphere && (this.boundingSphere = new THREE.Sphere); this.boundingSphere.setFromCenterAndPoints(this.boundingSphere.center, this.vertices) }, mergeVertices: function () { var a = {}, b = [], c = [], d, e = Math.pow(10, 4), f, g, h, i, k; this.__tmpVertices = void 0; f = 0; for (g = this.vertices.length; f < g; f++) d = this.vertices[f], d = [Math.round(d.x * e), Math.round(d.y * e), Math.round(d.z * e)].join("_"), void 0 === a[d] ? (a[d] = f, b.push(this.vertices[f]), c[f] = b.length - 1) : c[f] = c[a[d]]; e = []; f = 0; for (g = this.faces.length; f < g; f++) if (a = this.faces[f], a instanceof THREE.Face3) { a.a = c[a.a]; a.b = c[a.b]; a.c = c[a.c]; h = [a.a, a.b, a.c]; d = -1; for (i = 0; 3 > i; i++) if (h[i] == h[(i + 1) % 3]) { e.push(f); break } } else if (a instanceof THREE.Face4) { a.a = c[a.a]; a.b = c[a.b]; a.c = c[a.c]; a.d = c[a.d]; h = [a.a, a.b, a.c, a.d]; d = -1; for (i = 0; 4 > i; i++) h[i] == h[(i + 1) % 4] && (0 <= d && e.push(f), d = i); if (0 <= d) { h.splice(d, 1); var l = new THREE.Face3(h[0], h[1], h[2], a.normal, a.color, a.materialIndex); h = 0; for (i = this.faceVertexUvs.length; h < i; h++) (k = this.faceVertexUvs[h][f]) && k.splice(d, 1); a.vertexNormals && 0 < a.vertexNormals.length && (l.vertexNormals = a.vertexNormals, l.vertexNormals.splice(d, 1)); a.vertexColors && 0 < a.vertexColors.length && (l.vertexColors = a.vertexColors, l.vertexColors.splice(d, 1)); this.faces[f] = l } } for (f = e.length - 1; 0 <= f; f--) { this.faces.splice(f, 1); h = 0; for (i = this.faceVertexUvs.length; h < i; h++) this.faceVertexUvs[h].splice(f, 1) } c = this.vertices.length - b.length; this.vertices = b; return c }, clone: function () { for (var a = new THREE.Geometry, b = this.vertices, c = 0, d = b.length; c < d; c++) a.vertices.push(b[c].clone()); b = this.faces; c = 0; for (d = b.length; c < d; c++) a.faces.push(b[c].clone()); b = this.faceVertexUvs[0]; c = 0; for (d = b.length; c < d; c++) { for (var e = b[c], f = [], g = 0, h = e.length; g < h; g++) f.push(new THREE.Vector2(e[g].x, e[g].y)); a.faceVertexUvs[0].push(f) } return a }, dispose: function () { this.dispatchEvent({type: "dispose"}) } }; THREE.GeometryIdCount = 0; THREE.BufferGeometry = function () { THREE.EventDispatcher.call(this); this.id = THREE.GeometryIdCount++; this.attributes = {}; this.dynamic = !1; this.offsets = []; this.boundingSphere = this.boundingBox = null; this.hasTangents = !1; this.morphTargets = [] }; THREE.BufferGeometry.prototype = { constructor: THREE.BufferGeometry, applyMatrix: function (a) { var b, c; this.attributes.position && (b = this.attributes.position.array); this.attributes.normal && (c = this.attributes.normal.array); void 0 !== b && (a.multiplyVector3Array(b), this.verticesNeedUpdate = !0); void 0 !== c && (b = new THREE.Matrix3, b.getInverse(a).transpose(), b.multiplyVector3Array(c), this.normalizeNormals(), this.normalsNeedUpdate = !0) }, computeBoundingBox: function () { null === this.boundingBox && (this.boundingBox = new THREE.Box3); var a = this.attributes.position.array; if (a) { var b = this.boundingBox, c, d, e; 3 <= a.length && (b.min.x = b.max.x = a[0], b.min.y = b.max.y = a[1], b.min.z = b.max.z = a[2]); for (var f = 3, g = a.length; f < g; f += 3) c = a[f], d = a[f + 1], e = a[f + 2], c < b.min.x ? b.min.x = c : c > b.max.x && (b.max.x = c), d < b.min.y ? b.min.y = d : d > b.max.y && (b.max.y = d), e < b.min.z ? b.min.z = e : e > b.max.z && (b.max.z = e) } if (void 0 === a || 0 === a.length) this.boundingBox.min.set(0, 0, 0), this.boundingBox.max.set(0, 0, 0) }, computeBoundingSphere: function () { null === this.boundingSphere && (this.boundingSphere = new THREE.Sphere); var a = this.attributes.position.array; if (a) { for (var b, c = 0, d, e, f = 0, g = a.length; f < g; f += 3) b = a[f], d = a[f + 1], e = a[f + 2], b = b * b + d * d + e * e, b > c && (c = b); this.boundingSphere.radius = Math.sqrt(c) } }, computeVertexNormals: function () { if (this.attributes.position) { var a, b, c, d; a = this.attributes.position.array.length; if (void 0 === this.attributes.normal) this.attributes.normal = { itemSize: 3, array: new Float32Array(a), numItems: a }; else { a = 0; for (b = this.attributes.normal.array.length; a < b; a++) this.attributes.normal.array[a] = 0 } var e = this.attributes.position.array, f = this.attributes.normal.array, g, h, i, k, l, m, p = new THREE.Vector3, s = new THREE.Vector3, r = new THREE.Vector3, n = new THREE.Vector3, q = new THREE.Vector3; if (this.attributes.index) { var z = this.attributes.index.array, t = this.offsets; c = 0; for (d = t.length; c < d; ++c) { b = t[c].start; g = t[c].count; var x = t[c].index; a = b; for (b += g; a < b; a += 3) g = x + z[a], h = x + z[a + 1], i = x + z[a + 2], k = e[3 * g], l = e[3 * g + 1], m = e[3 * g + 2], p.set(k, l, m), k = e[3 * h], l = e[3 * h + 1], m = e[3 * h + 2], s.set(k, l, m), k = e[3 * i], l = e[3 * i + 1], m = e[3 * i + 2], r.set(k, l, m), n.subVectors(r, s), q.subVectors(p, s), n.cross(q), f[3 * g] += n.x, f[3 * g + 1] += n.y, f[3 * g + 2] += n.z, f[3 * h] += n.x, f[3 * h + 1] += n.y, f[3 * h + 2] += n.z, f[3 * i] += n.x, f[3 * i + 1] += n.y, f[3 * i + 2] += n.z } } else { a = 0; for (b = e.length; a < b; a += 9) k = e[a], l = e[a + 1], m = e[a + 2], p.set(k, l, m), k = e[a + 3], l = e[a + 4], m = e[a + 5], s.set(k, l, m), k = e[a + 6], l = e[a + 7], m = e[a + 8], r.set(k, l, m), n.subVectors(r, s), q.subVectors(p, s), n.cross(q), f[a] = n.x, f[a + 1] = n.y, f[a + 2] = n.z, f[a + 3] = n.x, f[a + 4] = n.y, f[a + 5] = n.z, f[a + 6] = n.x, f[a + 7] = n.y, f[a + 8] = n.z } this.normalizeNormals(); this.normalsNeedUpdate = !0 } }, normalizeNormals: function () { for (var a = this.attributes.normal.array, b, c, d, e = 0, f = a.length; e < f; e += 3) b = a[e], c = a[e + 1], d = a[e + 2], b = 1 / Math.sqrt(b * b + c * c + d * d), a[e] *= b, a[e + 1] *= b, a[e + 2] *= b }, computeTangents: function () { function a(a) { ma.x = d[3 * a]; ma.y = d[3 * a + 1]; ma.z = d[3 * a + 2]; eb.copy(ma); U = i[a]; N.copy(U); N.sub(ma.multiplyScalar(ma.dot(U))).normalize(); fa.crossVectors(eb, U); ja = fa.dot(k[a]); M = 0 > ja ? -1 : 1; h[4 * a] = N.x; h[4 * a + 1] = N.y; h[4 * a + 2] = N.z; h[4 * a + 3] = M } if (void 0 === this.attributes.index || void 0 === this.attributes.position || void 0 === this.attributes.normal || void 0 === this.attributes.uv) console.warn("Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()"); else { var b = this.attributes.index.array, c = this.attributes.position.array, d = this.attributes.normal.array, e = this.attributes.uv.array, f = c.length / 3; if (void 0 === this.attributes.tangent) { var g = 4 * f; this.attributes.tangent = {itemSize: 4, array: new Float32Array(g), numItems: g} } for (var h = this.attributes.tangent.array, i = [], k = [], g = 0; g < f; g++) i[g] = new THREE.Vector3, k[g] = new THREE.Vector3; var l, m, p, s, r, n, q, z, t, x, u, B, G, D, w, f = new THREE.Vector3, g = new THREE.Vector3, I, J, E, Z, A, S, F, H = this.offsets; E = 0; for (Z = H.length; E < Z; ++E) { J = H[E].start; A = H[E].count; var K = H[E].index; I = J; for (J += A; I < J; I += 3) A = K + b[I], S = K + b[I + 1], F = K + b[I + 2], l = c[3 * A], m = c[3 * A + 1], p = c[3 * A + 2], s = c[3 * S], r = c[3 * S + 1], n = c[3 * S + 2], q = c[3 * F], z = c[3 * F + 1], t = c[3 * F + 2], x = e[2 * A], u = e[2 * A + 1], B = e[2 * S], G = e[2 * S + 1], D = e[2 * F], w = e[2 * F + 1], s -= l, l = q - l, r -= m, m = z - m, n -= p, p = t - p, B -= x, x = D - x, G -= u, u = w - u, w = 1 / (B * u - x * G), f.set((u * s - G * l) * w, (u * r - G * m) * w, (u * n - G * p) * w), g.set((B * l - x * s) * w, (B * m - x * r) * w, (B * p - x * n) * w), i[A].add(f), i[S].add(f), i[F].add(f), k[A].add(g), k[S].add(g), k[F].add(g) } var N = new THREE.Vector3, fa = new THREE.Vector3, ma = new THREE.Vector3, eb = new THREE.Vector3, M, U, ja; E = 0; for (Z = H.length; E < Z; ++E) { J = H[E].start; A = H[E].count; K = H[E].index; I = J; for (J += A; I < J; I += 3) A = K + b[I], S = K + b[I + 1], F = K + b[I + 2], a(A), a(S), a(F) } this.tangentsNeedUpdate = this.hasTangents = !0 } }, dispose: function () { this.dispatchEvent({type: "dispose"}) } }; THREE.Camera = function () { THREE.Object3D.call(this); this.matrixWorldInverse = new THREE.Matrix4; this.projectionMatrix = new THREE.Matrix4; this.projectionMatrixInverse = new THREE.Matrix4 }; THREE.Camera.prototype = Object.create(THREE.Object3D.prototype); THREE.Camera.prototype.lookAt = function () { var a = new THREE.Matrix4; return function (b) { a.lookAt(this.position, b, this.up); !0 === this.useQuaternion ? this.quaternion.setFromRotationMatrix(a) : this.rotation.setEulerFromRotationMatrix(a, this.eulerOrder) } }(); THREE.OrthographicCamera = function (a, b, c, d, e, f) { THREE.Camera.call(this); this.left = a; this.right = b; this.top = c; this.bottom = d; this.near = void 0 !== e ? e : 0.1; this.far = void 0 !== f ? f : 2E3; this.updateProjectionMatrix() }; THREE.OrthographicCamera.prototype = Object.create(THREE.Camera.prototype); THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () { this.projectionMatrix.makeOrthographic(this.left, this.right, this.top, this.bottom, this.near, this.far) }; THREE.PerspectiveCamera = function (a, b, c, d) { THREE.Camera.call(this); this.fov = void 0 !== a ? a : 50; this.aspect = void 0 !== b ? b : 1; this.near = void 0 !== c ? c : 0.1; this.far = void 0 !== d ? d : 2E3; this.updateProjectionMatrix() }; THREE.PerspectiveCamera.prototype = Object.create(THREE.Camera.prototype); THREE.PerspectiveCamera.prototype.setLens = function (a, b) { void 0 === b && (b = 24); this.fov = 2 * THREE.Math.radToDeg(Math.atan(b / (2 * a))); this.updateProjectionMatrix() }; THREE.PerspectiveCamera.prototype.setViewOffset = function (a, b, c, d, e, f) { this.fullWidth = a; this.fullHeight = b; this.x = c; this.y = d; this.width = e; this.height = f; this.updateProjectionMatrix() }; THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () { if (this.fullWidth) { var a = this.fullWidth / this.fullHeight, b = Math.tan(THREE.Math.degToRad(0.5 * this.fov)) * this.near, c = -b, d = a * c, a = Math.abs(a * b - d), c = Math.abs(b - c); this.projectionMatrix.makeFrustum(d + this.x * a / this.fullWidth, d + (this.x + this.width) * a / this.fullWidth, b - (this.y + this.height) * c / this.fullHeight, b - this.y * c / this.fullHeight, this.near, this.far) } else this.projectionMatrix.makePerspective(this.fov, this.aspect, this.near, this.far) }; THREE.Light = function (a) { THREE.Object3D.call(this); this.color = new THREE.Color(a) }; THREE.Light.prototype = Object.create(THREE.Object3D.prototype); THREE.Light.prototype.clone = function (a) { void 0 === a && (a = new THREE.Light); THREE.Object3D.prototype.clone.call(this, a); a.color.copy(this.color); return a }; THREE.AmbientLight = function (a) { THREE.Light.call(this, a) }; THREE.AmbientLight.prototype = Object.create(THREE.Light.prototype); THREE.AmbientLight.prototype.clone = function () { var a = new THREE.AmbientLight; THREE.Light.prototype.clone.call(this, a); return a }; THREE.AreaLight = function (a, b) { THREE.Light.call(this, a); this.normal = new THREE.Vector3(0, -1, 0); this.right = new THREE.Vector3(1, 0, 0); this.intensity = void 0 !== b ? b : 1; this.height = this.width = 1; this.constantAttenuation = 1.5; this.linearAttenuation = 0.5; this.quadraticAttenuation = 0.1 }; THREE.AreaLight.prototype = Object.create(THREE.Light.prototype); THREE.DirectionalLight = function (a, b) { THREE.Light.call(this, a); this.position.set(0, 1, 0); this.target = new THREE.Object3D; this.intensity = void 0 !== b ? b : 1; this.onlyShadow = this.castShadow = !1; this.shadowCameraNear = 50; this.shadowCameraFar = 5E3; this.shadowCameraLeft = -500; this.shadowCameraTop = this.shadowCameraRight = 500; this.shadowCameraBottom = -500; this.shadowCameraVisible = !1; this.shadowBias = 0; this.shadowDarkness = 0.5; this.shadowMapHeight = this.shadowMapWidth = 512; this.shadowCascade = !1; this.shadowCascadeOffset = new THREE.Vector3(0, 0, -1E3); this.shadowCascadeCount = 2; this.shadowCascadeBias = [0, 0, 0]; this.shadowCascadeWidth = [512, 512, 512]; this.shadowCascadeHeight = [512, 512, 512]; this.shadowCascadeNearZ = [-1, 0.99, 0.998]; this.shadowCascadeFarZ = [0.99, 0.998, 1]; this.shadowCascadeArray = []; this.shadowMatrix = this.shadowCamera = this.shadowMapSize = this.shadowMap = null }; THREE.DirectionalLight.prototype = Object.create(THREE.Light.prototype); THREE.DirectionalLight.prototype.clone = function () { var a = new THREE.DirectionalLight; THREE.Light.prototype.clone.call(this, a); a.target = this.target.clone(); a.intensity = this.intensity; a.castShadow = this.castShadow; a.onlyShadow = this.onlyShadow; return a }; THREE.HemisphereLight = function (a, b, c) { THREE.Light.call(this, a); this.position.set(0, 100, 0); this.groundColor = new THREE.Color(b); this.intensity = void 0 !== c ? c : 1 }; THREE.HemisphereLight.prototype = Object.create(THREE.Light.prototype); THREE.HemisphereLight.prototype.clone = function () { var a = new THREE.PointLight; THREE.Light.prototype.clone.call(this, a); a.groundColor.copy(this.groundColor); a.intensity = this.intensity; return a }; THREE.PointLight = function (a, b, c) { THREE.Light.call(this, a); this.intensity = void 0 !== b ? b : 1; this.distance = void 0 !== c ? c : 0 }; THREE.PointLight.prototype = Object.create(THREE.Light.prototype); THREE.PointLight.prototype.clone = function () { var a = new THREE.PointLight; THREE.Light.prototype.clone.call(this, a); a.intensity = this.intensity; a.distance = this.distance; return a }; THREE.SpotLight = function (a, b, c, d, e) { THREE.Light.call(this, a); this.position.set(0, 1, 0); this.target = new THREE.Object3D; this.intensity = void 0 !== b ? b : 1; this.distance = void 0 !== c ? c : 0; this.angle = void 0 !== d ? d : Math.PI / 2; this.exponent = void 0 !== e ? e : 10; this.onlyShadow = this.castShadow = !1; this.shadowCameraNear = 50; this.shadowCameraFar = 5E3; this.shadowCameraFov = 50; this.shadowCameraVisible = !1; this.shadowBias = 0; this.shadowDarkness = 0.5; this.shadowMapHeight = this.shadowMapWidth = 512; this.shadowMatrix = this.shadowCamera = this.shadowMapSize = this.shadowMap = null }; THREE.SpotLight.prototype = Object.create(THREE.Light.prototype); THREE.SpotLight.prototype.clone = function () { var a = new THREE.SpotLight; THREE.Light.prototype.clone.call(this, a); a.target = this.target.clone(); a.intensity = this.intensity; a.distance = this.distance; a.angle = this.angle; a.exponent = this.exponent; a.castShadow = this.castShadow; a.onlyShadow = this.onlyShadow; return a }; THREE.Loader = function (a) { this.statusDomElement = (this.showStatus = a) ? THREE.Loader.prototype.addStatusElement() : null; this.onLoadStart = function () { }; this.onLoadProgress = function () { }; this.onLoadComplete = function () { } }; THREE.Loader.prototype = { constructor: THREE.Loader, crossOrigin: "anonymous", addStatusElement: function () { var a = document.createElement("div"); a.style.position = "absolute"; a.style.right = "0px"; a.style.top = "0px"; a.style.fontSize = "0.8em"; a.style.textAlign = "left"; a.style.background = "rgba(0,0,0,0.25)"; a.style.color = "#fff"; a.style.width = "120px"; a.style.padding = "0.5em 0.5em 0.5em 0.5em"; a.style.zIndex = 1E3; a.innerHTML = "Loading ..."; return a }, updateProgress: function (a) { var b = "Loaded ", b = a.total ? b + ((100 * a.loaded / a.total).toFixed(0) + "%") : b + ((a.loaded / 1E3).toFixed(2) + " KB"); this.statusDomElement.innerHTML = b }, extractUrlBase: function (a) { a = a.split("/"); a.pop(); return (1 > a.length ? "." : a.join("/")) + "/" }, initMaterials: function (a, b) { for (var c = [], d = 0; d < a.length; ++d) c[d] = THREE.Loader.prototype.createMaterial(a[d], b); return c }, needsTangents: function (a) { for (var b = 0, c = a.length; b < c; b++) if (a[b] instanceof THREE.ShaderMaterial) return !0; return !1 }, createMaterial: function (a, b) { function c(a) { a = Math.log(a) / Math.LN2; return Math.floor(a) == a } function d(a) { a = Math.log(a) / Math.LN2; return Math.pow(2, Math.round(a)) } function e(a, e, f, h, i, k, q) { var z = /\.dds$/i.test(f), t = b + "/" + f; if (z) { var x = THREE.ImageUtils.loadCompressedTexture(t); a[e] = x } else x = document.createElement("canvas"), a[e] = new THREE.Texture(x); a[e].sourceFile = f; h && (a[e].repeat.set(h[0], h[1]), 1 !== h[0] && (a[e].wrapS = THREE.RepeatWrapping), 1 !== h[1] && (a[e].wrapT = THREE.RepeatWrapping)); i && a[e].offset.set(i[0], i[1]); k && (f = {repeat: THREE.RepeatWrapping, mirror: THREE.MirroredRepeatWrapping}, void 0 !== f[k[0]] && (a[e].wrapS = f[k[0]]), void 0 !== f[k[1]] && (a[e].wrapT = f[k[1]])); q && (a[e].anisotropy = q); if (!z) { var u = a[e], a = new Image; a.onload = function () { if (!c(this.width) || !c(this.height)) { var a = d(this.width), b = d(this.height); u.image.width = a; u.image.height = b; u.image.getContext("2d").drawImage(this, 0, 0, a, b) } else u.image = this; u.needsUpdate = !0 }; a.crossOrigin = g.crossOrigin; a.src = t } } function f(a) { return (255 * a[0] << 16) + (255 * a[1] << 8) + 255 * a[2] } var g = this, h = "MeshLambertMaterial", i = { color: 15658734, opacity: 1, map: null, lightMap: null, normalMap: null, bumpMap: null, wireframe: !1 }; if (a.shading) { var k = a.shading.toLowerCase(); "phong" === k ? h = "MeshPhongMaterial" : "basic" === k && (h = "MeshBasicMaterial") } void 0 !== a.blending && void 0 !== THREE[a.blending] && (i.blending = THREE[a.blending]); if (void 0 !== a.transparent || 1 > a.opacity) i.transparent = a.transparent; void 0 !== a.depthTest && (i.depthTest = a.depthTest); void 0 !== a.depthWrite && (i.depthWrite = a.depthWrite); void 0 !== a.visible && (i.visible = a.visible); void 0 !== a.flipSided && (i.side = THREE.BackSide); void 0 !== a.doubleSided && (i.side = THREE.DoubleSide); void 0 !== a.wireframe && (i.wireframe = a.wireframe); void 0 !== a.vertexColors && ("face" === a.vertexColors ? i.vertexColors = THREE.FaceColors : a.vertexColors && (i.vertexColors = THREE.VertexColors)); a.colorDiffuse ? i.color = f(a.colorDiffuse) : a.DbgColor && (i.color = a.DbgColor); a.colorSpecular && (i.specular = f(a.colorSpecular)); a.colorAmbient && (i.ambient = f(a.colorAmbient)); a.transparency && (i.opacity = a.transparency); a.specularCoef && (i.shininess = a.specularCoef); a.mapDiffuse && b && e(i, "map", a.mapDiffuse, a.mapDiffuseRepeat, a.mapDiffuseOffset, a.mapDiffuseWrap, a.mapDiffuseAnisotropy); a.mapLight && b && e(i, "lightMap", a.mapLight, a.mapLightRepeat, a.mapLightOffset, a.mapLightWrap, a.mapLightAnisotropy); a.mapBump && b && e(i, "bumpMap", a.mapBump, a.mapBumpRepeat, a.mapBumpOffset, a.mapBumpWrap, a.mapBumpAnisotropy); a.mapNormal && b && e(i, "normalMap", a.mapNormal, a.mapNormalRepeat, a.mapNormalOffset, a.mapNormalWrap, a.mapNormalAnisotropy); a.mapSpecular && b && e(i, "specularMap", a.mapSpecular, a.mapSpecularRepeat, a.mapSpecularOffset, a.mapSpecularWrap, a.mapSpecularAnisotropy); a.mapBumpScale && (i.bumpScale = a.mapBumpScale); a.mapNormal ? (h = THREE.ShaderLib.normalmap, k = THREE.UniformsUtils.clone(h.uniforms), k.tNormal.value = i.normalMap, a.mapNormalFactor && k.uNormalScale.value.set(a.mapNormalFactor, a.mapNormalFactor), i.map && (k.tDiffuse.value = i.map, k.enableDiffuse.value = !0), i.specularMap && (k.tSpecular.value = i.specularMap, k.enableSpecular.value = !0), i.lightMap && (k.tAO.value = i.lightMap, k.enableAO.value = !0), k.uDiffuseColor.value.setHex(i.color), k.uSpecularColor.value.setHex(i.specular), k.uAmbientColor.value.setHex(i.ambient), k.uShininess.value = i.shininess, void 0 !== i.opacity && (k.uOpacity.value = i.opacity), h = new THREE.ShaderMaterial({ fragmentShader: h.fragmentShader, vertexShader: h.vertexShader, uniforms: k, lights: !0, fog: !0 }), i.transparent && (h.transparent = !0)) : h = new THREE[h](i); void 0 !== a.DbgName && (h.name = a.DbgName); return h } }; THREE.ImageLoader = function () { THREE.EventDispatcher.call(this); this.crossOrigin = null }; THREE.ImageLoader.prototype = { constructor: THREE.ImageLoader, load: function (a, b) { var c = this; void 0 === b && (b = new Image); b.addEventListener("load", function () { c.dispatchEvent({type: "load", content: b}) }, !1); b.addEventListener("error", function () { c.dispatchEvent({type: "error", message: "Couldn't load URL [" + a + "]"}) }, !1); c.crossOrigin && (b.crossOrigin = c.crossOrigin); b.src = a } }; THREE.JSONLoader = function (a) { THREE.Loader.call(this, a); this.withCredentials = !1 }; THREE.JSONLoader.prototype = Object.create(THREE.Loader.prototype); THREE.JSONLoader.prototype.load = function (a, b, c) { c = c && "string" === typeof c ? c : this.extractUrlBase(a); this.onLoadStart(); this.loadAjaxJSON(this, a, b, c) }; THREE.JSONLoader.prototype.loadAjaxJSON = function (a, b, c, d, e) { var f = new XMLHttpRequest, g = 0; f.onreadystatechange = function () { if (f.readyState === f.DONE) if (200 === f.status || 0 === f.status) { if (f.responseText) { var h = JSON.parse(f.responseText), h = a.parse(h, d); c(h.geometry, h.materials) } else console.warn("THREE.JSONLoader: [" + b + "] seems to be unreachable or file there is empty"); a.onLoadComplete() } else console.error("THREE.JSONLoader: Couldn't load [" + b + "] [" + f.status + "]"); else f.readyState === f.LOADING ? e && (0 === g && (g = f.getResponseHeader("Content-Length")), e({ total: g, loaded: f.responseText.length })) : f.readyState === f.HEADERS_RECEIVED && (g = f.getResponseHeader("Content-Length")) }; f.open("GET", b, !0); f.withCredentials = this.withCredentials; f.send(null) }; THREE.JSONLoader.prototype.parse = function (a, b) { var c = new THREE.Geometry, d = void 0 !== a.scale ? 1 / a.scale : 1, e, f, g, h, i, k, l, m, p, s, r, n, q, z, t, x = a.faces; s = a.vertices; var u = a.normals, B = a.colors, G = 0; for (e = 0; e < a.uvs.length; e++) a.uvs[e].length && G++; for (e = 0; e < G; e++) c.faceUvs[e] = [], c.faceVertexUvs[e] = []; h = 0; for (i = s.length; h < i;) k = new THREE.Vector3, k.x = s[h++] * d, k.y = s[h++] * d, k.z = s[h++] * d, c.vertices.push(k); h = 0; for (i = x.length; h < i;) { s = x[h++]; k = s & 1; g = s & 2; e = s & 4; f = s & 8; m = s & 16; l = s & 32; r = s & 64; s &= 128; k ? (n = new THREE.Face4, n.a = x[h++], n.b = x[h++], n.c = x[h++], n.d = x[h++], k = 4) : (n = new THREE.Face3, n.a = x[h++], n.b = x[h++], n.c = x[h++], k = 3); g && (g = x[h++], n.materialIndex = g); g = c.faces.length; if (e) for (e = 0; e < G; e++) q = a.uvs[e], p = x[h++], t = q[2 * p], p = q[2 * p + 1], c.faceUvs[e][g] = new THREE.Vector2(t, p); if (f) for (e = 0; e < G; e++) { q = a.uvs[e]; z = []; for (f = 0; f < k; f++) p = x[h++], t = q[2 * p], p = q[2 * p + 1], z[f] = new THREE.Vector2(t, p); c.faceVertexUvs[e][g] = z } m && (m = 3 * x[h++], f = new THREE.Vector3, f.x = u[m++], f.y = u[m++], f.z = u[m], n.normal = f); if (l) for (e = 0; e < k; e++) m = 3 * x[h++], f = new THREE.Vector3, f.x = u[m++], f.y = u[m++], f.z = u[m], n.vertexNormals.push(f); r && (l = x[h++], l = new THREE.Color(B[l]), n.color = l); if (s) for (e = 0; e < k; e++) l = x[h++], l = new THREE.Color(B[l]), n.vertexColors.push(l); c.faces.push(n) } if (a.skinWeights) { h = 0; for (i = a.skinWeights.length; h < i; h += 2) x = a.skinWeights[h], u = a.skinWeights[h + 1], c.skinWeights.push(new THREE.Vector4(x, u, 0, 0)) } if (a.skinIndices) { h = 0; for (i = a.skinIndices.length; h < i; h += 2) x = a.skinIndices[h], u = a.skinIndices[h + 1], c.skinIndices.push(new THREE.Vector4(x, u, 0, 0)) } c.bones = a.bones; c.animation = a.animation; if (void 0 !== a.morphTargets) { h = 0; for (i = a.morphTargets.length; h < i; h++) { c.morphTargets[h] = {}; c.morphTargets[h].name = a.morphTargets[h].name; c.morphTargets[h].vertices = []; B = c.morphTargets[h].vertices; G = a.morphTargets[h].vertices; x = 0; for (u = G.length; x < u; x += 3) s = new THREE.Vector3, s.x = G[x] * d, s.y = G[x + 1] * d, s.z = G[x + 2] * d, B.push(s) } } if (void 0 !== a.morphColors) { h = 0; for (i = a.morphColors.length; h < i; h++) { c.morphColors[h] = {}; c.morphColors[h].name = a.morphColors[h].name; c.morphColors[h].colors = []; u = c.morphColors[h].colors; B = a.morphColors[h].colors; d = 0; for (x = B.length; d < x; d += 3) G = new THREE.Color(16755200), G.setRGB(B[d], B[d + 1], B[d + 2]), u.push(G) } } c.computeCentroids(); c.computeFaceNormals(); d = this.initMaterials(a.materials, b); this.needsTangents(d) && c.computeTangents(); return {geometry: c, materials: d} }; THREE.LoadingMonitor = function () { THREE.EventDispatcher.call(this); var a = this, b = 0, c = 0, d = function () { b++; a.dispatchEvent({type: "progress", loaded: b, total: c}); b === c && a.dispatchEvent({type: "load"}) }; this.add = function (a) { c++; a.addEventListener("load", d, !1) } }; THREE.SceneLoader = function () { this.onLoadStart = function () { }; this.onLoadProgress = function () { }; this.onLoadComplete = function () { }; this.callbackSync = function () { }; this.callbackProgress = function () { }; this.geometryHandlerMap = {}; this.hierarchyHandlerMap = {}; this.addGeometryHandler("ascii", THREE.JSONLoader) }; THREE.SceneLoader.prototype.constructor = THREE.SceneLoader; THREE.SceneLoader.prototype.load = function (a, b) { var c = this, d = new XMLHttpRequest; d.onreadystatechange = function () { if (4 === d.readyState) if (200 === d.status || 0 === d.status) { var e = JSON.parse(d.responseText); c.parse(e, b, a) } else console.error("THREE.SceneLoader: Couldn't load [" + a + "] [" + d.status + "]") }; d.open("GET", a, !0); d.send(null) }; THREE.SceneLoader.prototype.addGeometryHandler = function (a, b) { this.geometryHandlerMap[a] = {loaderClass: b} }; THREE.SceneLoader.prototype.addHierarchyHandler = function (a, b) { this.hierarchyHandlerMap[a] = {loaderClass: b} }; THREE.SceneLoader.prototype.parse = function (a, b, c) { function d(a, b) { return "relativeToHTML" == b ? a : m + "/" + a } function e() { f(w.scene, J.objects) } function f(a, b) { var c, e, g, i, k, m, n; for (n in b) if (void 0 === w.objects[n]) { var q = b[n], u = null; if (q.type && q.type in l.hierarchyHandlerMap) { if (void 0 === q.loading) { e = { type: 1, url: 1, material: 1, position: 1, rotation: 1, scale: 1, visible: 1, children: 1, userData: 1, skin: 1, morph: 1, mirroredLoop: 1, duration: 1 }; g = {}; for (var A in q) A in e || (g[A] = q[A]); s = w.materials[q.material]; q.loading = !0; e = l.hierarchyHandlerMap[q.type].loaderObject; e.options ? e.load(d(q.url, J.urlBaseType), h(n, a, s, q)) : e.load(d(q.url, J.urlBaseType), h(n, a, s, q), g) } } else if (void 0 !== q.geometry) { if (p = w.geometries[q.geometry]) { u = !1; s = w.materials[q.material]; u = s instanceof THREE.ShaderMaterial; g = q.position; i = q.rotation; k = q.scale; c = q.matrix; m = q.quaternion; q.material || (s = new THREE.MeshFaceMaterial(w.face_materials[q.geometry])); s instanceof THREE.MeshFaceMaterial && 0 === s.materials.length && (s = new THREE.MeshFaceMaterial(w.face_materials[q.geometry])); if (s instanceof THREE.MeshFaceMaterial) for (e = 0; e < s.materials.length; e++) u = u || s.materials[e] instanceof THREE.ShaderMaterial; u && p.computeTangents(); q.skin ? u = new THREE.SkinnedMesh(p, s) : q.morph ? (u = new THREE.MorphAnimMesh(p, s), void 0 !== q.duration && (u.duration = q.duration), void 0 !== q.time && (u.time = q.time), void 0 !== q.mirroredLoop && (u.mirroredLoop = q.mirroredLoop), s.morphNormals && p.computeMorphNormals()) : u = new THREE.Mesh(p, s); u.name = n; c ? (u.matrixAutoUpdate = !1, u.matrix.set(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15])) : (u.position.set(g[0], g[1], g[2]), m ? (u.quaternion.set(m[0], m[1], m[2], m[3]), u.useQuaternion = !0) : u.rotation.set(i[0], i[1], i[2]), u.scale.set(k[0], k[1], k[2])); u.visible = q.visible; u.castShadow = q.castShadow; u.receiveShadow = q.receiveShadow; a.add(u); w.objects[n] = u } } else "DirectionalLight" === q.type || "PointLight" === q.type || "AmbientLight" === q.type ? (t = void 0 !== q.color ? q.color : 16777215, x = void 0 !== q.intensity ? q.intensity : 1, "DirectionalLight" === q.type ? (g = q.direction, z = new THREE.DirectionalLight(t, x), z.position.set(g[0], g[1], g[2]), q.target && (I.push({ object: z, targetName: q.target }), z.target = null)) : "PointLight" === q.type ? (g = q.position, e = q.distance, z = new THREE.PointLight(t, x, e), z.position.set(g[0], g[1], g[2])) : "AmbientLight" === q.type && (z = new THREE.AmbientLight(t)), a.add(z), z.name = n, w.lights[n] = z, w.objects[n] = z) : "PerspectiveCamera" === q.type || "OrthographicCamera" === q.type ? ("PerspectiveCamera" === q.type ? r = new THREE.PerspectiveCamera(q.fov, q.aspect, q.near, q.far) : "OrthographicCamera" === q.type && (r = new THREE.OrthographicCamera(q.left, q.right, q.top, q.bottom, q.near, q.far)), g = q.position, r.position.set(g[0], g[1], g[2]), a.add(r), r.name = n, w.cameras[n] = r, w.objects[n] = r) : (g = q.position, i = q.rotation, k = q.scale, m = q.quaternion, u = new THREE.Object3D, u.name = n, u.position.set(g[0], g[1], g[2]), m ? (u.quaternion.set(m[0], m[1], m[2], m[3]), u.useQuaternion = !0) : u.rotation.set(i[0], i[1], i[2]), u.scale.set(k[0], k[1], k[2]), u.visible = void 0 !== q.visible ? q.visible : !1, a.add(u), w.objects[n] = u, w.empties[n] = u); if (u) { if (void 0 !== q.userData) for (var B in q.userData) u.userData[B] = q.userData[B]; if (void 0 !== q.groups) for (e = 0; e < q.groups.length; e++) g = q.groups[e], void 0 === w.groups[g] && (w.groups[g] = []), w.groups[g].push(n); void 0 !== q.children && f(u, q.children) } } } function g(a) { return function (b, c) { w.geometries[a] = b; w.face_materials[a] = c; e(); u -= 1; l.onLoadComplete(); k() } } function h(a, b, c, d) { return function (f) { var f = f.content ? f.content : f.dae ? f.scene : f, g = d.position, h = d.rotation, i = d.quaternion, m = d.scale; f.position.set(g[0], g[1], g[2]); i ? (f.quaternion.set(i[0], i[1], i[2], i[3]), f.useQuaternion = !0) : f.rotation.set(h[0], h[1], h[2]); f.scale.set(m[0], m[1], m[2]); c && f.traverse(function (a) { a.material = c }); var p = void 0 !== d.visible ? d.visible : !0; f.traverse(function (a) { a.visible = p }); b.add(f); f.name = a; w.objects[a] = f; e(); u -= 1; l.onLoadComplete(); k() } } function i(a) { return function (b, c) { w.geometries[a] = b; w.face_materials[a] = c } } function k() { l.callbackProgress({totalModels: G, totalTextures: D, loadedModels: G - u, loadedTextures: D - B}, w); l.onLoadProgress(); if (0 === u && 0 === B) { for (var a = 0; a < I.length; a++) { var c = I[a], d = w.objects[c.targetName]; d ? c.object.target = d : (c.object.target = new THREE.Object3D, w.scene.add(c.object.target)); c.object.target.userData.targetInverse = c.object } b(w) } } var l = this, m = THREE.Loader.prototype.extractUrlBase(c), p, s, r, n, q, z, t, x, u, B, G, D, w, I = [], J = a, E; for (E in this.geometryHandlerMap) a = this.geometryHandlerMap[E].loaderClass, this.geometryHandlerMap[E].loaderObject = new a; for (E in this.hierarchyHandlerMap) a = this.hierarchyHandlerMap[E].loaderClass, this.hierarchyHandlerMap[E].loaderObject = new a; B = u = 0; w = { scene: new THREE.Scene, geometries: {}, face_materials: {}, materials: {}, textures: {}, objects: {}, cameras: {}, lights: {}, fogs: {}, empties: {}, groups: {} }; if (J.transform && (E = J.transform.position, a = J.transform.rotation, c = J.transform.scale, E && w.scene.position.set(E[0], E[1], E[2]), a && w.scene.rotation.set(a[0], a[1], a[2]), c && w.scene.scale.set(c[0], c[1], c[2]), E || a || c)) w.scene.updateMatrix(), w.scene.updateMatrixWorld(); E = function (a) { return function () { B -= a; k(); l.onLoadComplete() } }; for (var Z in J.fogs) a = J.fogs[Z], "linear" === a.type ? n = new THREE.Fog(0, a.near, a.far) : "exp2" === a.type && (n = new THREE.FogExp2(0, a.density)), a = a.color, n.color.setRGB(a[0], a[1], a[2]), w.fogs[Z] = n; for (var A in J.geometries) n = J.geometries[A], n.type in this.geometryHandlerMap && (u += 1, l.onLoadStart()); for (var S in J.objects) n = J.objects[S], n.type && n.type in this.hierarchyHandlerMap && (u += 1, l.onLoadStart()); G = u; for (A in J.geometries) if (n = J.geometries[A], "cube" === n.type) p = new THREE.CubeGeometry(n.width, n.height, n.depth, n.widthSegments, n.heightSegments, n.depthSegments), w.geometries[A] = p; else if ("plane" === n.type) p = new THREE.PlaneGeometry(n.width, n.height, n.widthSegments, n.heightSegments), w.geometries[A] = p; else if ("sphere" === n.type) p = new THREE.SphereGeometry(n.radius, n.widthSegments, n.heightSegments), w.geometries[A] = p; else if ("cylinder" === n.type) p = new THREE.CylinderGeometry(n.topRad, n.botRad, n.height, n.radSegs, n.heightSegs), w.geometries[A] = p; else if ("torus" === n.type) p = new THREE.TorusGeometry(n.radius, n.tube, n.segmentsR, n.segmentsT), w.geometries[A] = p; else if ("icosahedron" === n.type) p = new THREE.IcosahedronGeometry(n.radius, n.subdivisions), w.geometries[A] = p; else if (n.type in this.geometryHandlerMap) { S = {}; for (q in n) "type" !== q && "url" !== q && (S[q] = n[q]); this.geometryHandlerMap[n.type].loaderObject.load(d(n.url, J.urlBaseType), g(A), S) } else "embedded" === n.type && (S = J.embeds[n.id], S.metadata = J.metadata, S && (S = this.geometryHandlerMap.ascii.loaderObject.parse(S, ""), i(A)(S.geometry, S.materials))); for (var F in J.textures) if (A = J.textures[F], A.url instanceof Array) { B += A.url.length; for (q = 0; q < A.url.length; q++) l.onLoadStart() } else B += 1, l.onLoadStart(); D = B; for (F in J.textures) { A = J.textures[F]; void 0 !== A.mapping && void 0 !== THREE[A.mapping] && (A.mapping = new THREE[A.mapping]); if (A.url instanceof Array) { S = A.url.length; n = []; for (q = 0; q < S; q++) n[q] = d(A.url[q], J.urlBaseType); q = (q = /\.dds$/i.test(n[0])) ? THREE.ImageUtils.loadCompressedTextureCube(n, A.mapping, E(S)) : THREE.ImageUtils.loadTextureCube(n, A.mapping, E(S)) } else q = /\.dds$/i.test(A.url), S = d(A.url, J.urlBaseType), n = E(1), q = q ? THREE.ImageUtils.loadCompressedTexture(S, A.mapping, n) : THREE.ImageUtils.loadTexture(S, A.mapping, n), void 0 !== THREE[A.minFilter] && (q.minFilter = THREE[A.minFilter]), void 0 !== THREE[A.magFilter] && (q.magFilter = THREE[A.magFilter]), A.anisotropy && (q.anisotropy = A.anisotropy), A.repeat && (q.repeat.set(A.repeat[0], A.repeat[1]), 1 !== A.repeat[0] && (q.wrapS = THREE.RepeatWrapping), 1 !== A.repeat[1] && (q.wrapT = THREE.RepeatWrapping)), A.offset && q.offset.set(A.offset[0], A.offset[1]), A.wrap && (S = { repeat: THREE.RepeatWrapping, mirror: THREE.MirroredRepeatWrapping }, void 0 !== S[A.wrap[0]] && (q.wrapS = S[A.wrap[0]]), void 0 !== S[A.wrap[1]] && (q.wrapT = S[A.wrap[1]])); w.textures[F] = q } var H, K; for (H in J.materials) { F = J.materials[H]; for (K in F.parameters) "envMap" === K || "map" === K || "lightMap" === K || "bumpMap" === K ? F.parameters[K] = w.textures[F.parameters[K]] : "shading" === K ? F.parameters[K] = "flat" === F.parameters[K] ? THREE.FlatShading : THREE.SmoothShading : "side" === K ? F.parameters[K] = "double" == F.parameters[K] ? THREE.DoubleSide : "back" == F.parameters[K] ? THREE.BackSide : THREE.FrontSide : "blending" === K ? F.parameters[K] = F.parameters[K] in THREE ? THREE[F.parameters[K]] : THREE.NormalBlending : "combine" === K ? F.parameters[K] = F.parameters[K] in THREE ? THREE[F.parameters[K]] : THREE.MultiplyOperation : "vertexColors" === K ? "face" == F.parameters[K] ? F.parameters[K] = THREE.FaceColors : F.parameters[K] && (F.parameters[K] = THREE.VertexColors) : "wrapRGB" === K && (E = F.parameters[K], F.parameters[K] = new THREE.Vector3(E[0], E[1], E[2])); void 0 !== F.parameters.opacity && 1 > F.parameters.opacity && (F.parameters.transparent = !0); F.parameters.normalMap ? (E = THREE.ShaderLib.normalmap, A = THREE.UniformsUtils.clone(E.uniforms), q = F.parameters.color, S = F.parameters.specular, n = F.parameters.ambient, Z = F.parameters.shininess, A.tNormal.value = w.textures[F.parameters.normalMap], F.parameters.normalScale && A.uNormalScale.value.set(F.parameters.normalScale[0], F.parameters.normalScale[1]), F.parameters.map && (A.tDiffuse.value = F.parameters.map, A.enableDiffuse.value = !0), F.parameters.envMap && (A.tCube.value = F.parameters.envMap, A.enableReflection.value = !0, A.uReflectivity.value = F.parameters.reflectivity), F.parameters.lightMap && (A.tAO.value = F.parameters.lightMap, A.enableAO.value = !0), F.parameters.specularMap && (A.tSpecular.value = w.textures[F.parameters.specularMap], A.enableSpecular.value = !0), F.parameters.displacementMap && (A.tDisplacement.value = w.textures[F.parameters.displacementMap], A.enableDisplacement.value = !0, A.uDisplacementBias.value = F.parameters.displacementBias, A.uDisplacementScale.value = F.parameters.displacementScale), A.uDiffuseColor.value.setHex(q), A.uSpecularColor.value.setHex(S), A.uAmbientColor.value.setHex(n), A.uShininess.value = Z, F.parameters.opacity && (A.uOpacity.value = F.parameters.opacity), s = new THREE.ShaderMaterial({ fragmentShader: E.fragmentShader, vertexShader: E.vertexShader, uniforms: A, lights: !0, fog: !0 })) : s = new THREE[F.type](F.parameters); w.materials[H] = s } for (H in J.materials) if (F = J.materials[H], F.parameters.materials) { K = []; for (q = 0; q < F.parameters.materials.length; q++) K.push(w.materials[F.parameters.materials[q]]); w.materials[H].materials = K } e(); w.cameras && J.defaults.camera && (w.currentCamera = w.cameras[J.defaults.camera]); w.fogs && J.defaults.fog && (w.scene.fog = w.fogs[J.defaults.fog]); l.callbackSync(w); k() }; THREE.TextureLoader = function () { THREE.EventDispatcher.call(this); this.crossOrigin = null }; THREE.TextureLoader.prototype = { constructor: THREE.TextureLoader, load: function (a) { var b = this, c = new Image; c.addEventListener("load", function () { var a = new THREE.Texture(c); a.needsUpdate = !0; b.dispatchEvent({type: "load", content: a}) }, !1); c.addEventListener("error", function () { b.dispatchEvent({type: "error", message: "Couldn't load URL [" + a + "]"}) }, !1); b.crossOrigin && (c.crossOrigin = b.crossOrigin); c.src = a } }; THREE.Material = function () { THREE.EventDispatcher.call(this); this.id = THREE.MaterialIdCount++; this.name = ""; this.side = THREE.FrontSide; this.opacity = 1; this.transparent = !1; this.blending = THREE.NormalBlending; this.blendSrc = THREE.SrcAlphaFactor; this.blendDst = THREE.OneMinusSrcAlphaFactor; this.blendEquation = THREE.AddEquation; this.depthWrite = this.depthTest = !0; this.polygonOffset = !1; this.alphaTest = this.polygonOffsetUnits = this.polygonOffsetFactor = 0; this.overdraw = !1; this.needsUpdate = this.visible = !0 }; THREE.Material.prototype.setValues = function (a) { if (void 0 !== a) for (var b in a) { var c = a[b]; if (void 0 === c) console.warn("THREE.Material: '" + b + "' parameter is undefined."); else if (b in this) { var d = this[b]; d instanceof THREE.Color && c instanceof THREE.Color ? d.copy(c) : d instanceof THREE.Color ? d.set(c) : d instanceof THREE.Vector3 && c instanceof THREE.Vector3 ? d.copy(c) : this[b] = c } } }; THREE.Material.prototype.clone = function (a) { void 0 === a && (a = new THREE.Material); a.name = this.name; a.side = this.side; a.opacity = this.opacity; a.transparent = this.transparent; a.blending = this.blending; a.blendSrc = this.blendSrc; a.blendDst = this.blendDst; a.blendEquation = this.blendEquation; a.depthTest = this.depthTest; a.depthWrite = this.depthWrite; a.polygonOffset = this.polygonOffset; a.polygonOffsetFactor = this.polygonOffsetFactor; a.polygonOffsetUnits = this.polygonOffsetUnits; a.alphaTest = this.alphaTest; a.overdraw = this.overdraw; a.visible = this.visible; return a }; THREE.Material.prototype.dispose = function () { this.dispatchEvent({type: "dispose"}) }; THREE.MaterialIdCount = 0; THREE.LineBasicMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.linewidth = 1; this.linejoin = this.linecap = "round"; this.vertexColors = !1; this.fog = !0; this.setValues(a) }; THREE.LineBasicMaterial.prototype = Object.create(THREE.Material.prototype); THREE.LineBasicMaterial.prototype.clone = function () { var a = new THREE.LineBasicMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.linewidth = this.linewidth; a.linecap = this.linecap; a.linejoin = this.linejoin; a.vertexColors = this.vertexColors; a.fog = this.fog; return a }; THREE.LineDashedMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.scale = this.linewidth = 1; this.dashSize = 3; this.gapSize = 1; this.vertexColors = !1; this.fog = !0; this.setValues(a) }; THREE.LineDashedMaterial.prototype = Object.create(THREE.Material.prototype); THREE.LineDashedMaterial.prototype.clone = function () { var a = new THREE.LineDashedMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.linewidth = this.linewidth; a.scale = this.scale; a.dashSize = this.dashSize; a.gapSize = this.gapSize; a.vertexColors = this.vertexColors; a.fog = this.fog; return a }; THREE.MeshBasicMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.envMap = this.specularMap = this.lightMap = this.map = null; this.combine = THREE.MultiplyOperation; this.reflectivity = 1; this.refractionRatio = 0.98; this.fog = !0; this.shading = THREE.SmoothShading; this.wireframe = !1; this.wireframeLinewidth = 1; this.wireframeLinejoin = this.wireframeLinecap = "round"; this.vertexColors = THREE.NoColors; this.morphTargets = this.skinning = !1; this.setValues(a) }; THREE.MeshBasicMaterial.prototype = Object.create(THREE.Material.prototype); THREE.MeshBasicMaterial.prototype.clone = function () { var a = new THREE.MeshBasicMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.map = this.map; a.lightMap = this.lightMap; a.specularMap = this.specularMap; a.envMap = this.envMap; a.combine = this.combine; a.reflectivity = this.reflectivity; a.refractionRatio = this.refractionRatio; a.fog = this.fog; a.shading = this.shading; a.wireframe = this.wireframe; a.wireframeLinewidth = this.wireframeLinewidth; a.wireframeLinecap = this.wireframeLinecap; a.wireframeLinejoin = this.wireframeLinejoin; a.vertexColors = this.vertexColors; a.skinning = this.skinning; a.morphTargets = this.morphTargets; return a }; THREE.MeshLambertMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.ambient = new THREE.Color(16777215); this.emissive = new THREE.Color(0); this.wrapAround = !1; this.wrapRGB = new THREE.Vector3(1, 1, 1); this.envMap = this.specularMap = this.lightMap = this.map = null; this.combine = THREE.MultiplyOperation; this.reflectivity = 1; this.refractionRatio = 0.98; this.fog = !0; this.shading = THREE.SmoothShading; this.wireframe = !1; this.wireframeLinewidth = 1; this.wireframeLinejoin = this.wireframeLinecap = "round"; this.vertexColors = THREE.NoColors; this.morphNormals = this.morphTargets = this.skinning = !1; this.setValues(a) }; THREE.MeshLambertMaterial.prototype = Object.create(THREE.Material.prototype); THREE.MeshLambertMaterial.prototype.clone = function () { var a = new THREE.MeshLambertMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.ambient.copy(this.ambient); a.emissive.copy(this.emissive); a.wrapAround = this.wrapAround; a.wrapRGB.copy(this.wrapRGB); a.map = this.map; a.lightMap = this.lightMap; a.specularMap = this.specularMap; a.envMap = this.envMap; a.combine = this.combine; a.reflectivity = this.reflectivity; a.refractionRatio = this.refractionRatio; a.fog = this.fog; a.shading = this.shading; a.wireframe = this.wireframe; a.wireframeLinewidth = this.wireframeLinewidth; a.wireframeLinecap = this.wireframeLinecap; a.wireframeLinejoin = this.wireframeLinejoin; a.vertexColors = this.vertexColors; a.skinning = this.skinning; a.morphTargets = this.morphTargets; a.morphNormals = this.morphNormals; return a }; THREE.MeshPhongMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.ambient = new THREE.Color(16777215); this.emissive = new THREE.Color(0); this.specular = new THREE.Color(1118481); this.shininess = 30; this.metal = !1; this.perPixel = !0; this.wrapAround = !1; this.wrapRGB = new THREE.Vector3(1, 1, 1); this.bumpMap = this.lightMap = this.map = null; this.bumpScale = 1; this.normalMap = null; this.normalScale = new THREE.Vector2(1, 1); this.envMap = this.specularMap = null; this.combine = THREE.MultiplyOperation; this.reflectivity = 1; this.refractionRatio = 0.98; this.fog = !0; this.shading = THREE.SmoothShading; this.wireframe = !1; this.wireframeLinewidth = 1; this.wireframeLinejoin = this.wireframeLinecap = "round"; this.vertexColors = THREE.NoColors; this.morphNormals = this.morphTargets = this.skinning = !1; this.setValues(a) }; THREE.MeshPhongMaterial.prototype = Object.create(THREE.Material.prototype); THREE.MeshPhongMaterial.prototype.clone = function () { var a = new THREE.MeshPhongMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.ambient.copy(this.ambient); a.emissive.copy(this.emissive); a.specular.copy(this.specular); a.shininess = this.shininess; a.metal = this.metal; a.perPixel = this.perPixel; a.wrapAround = this.wrapAround; a.wrapRGB.copy(this.wrapRGB); a.map = this.map; a.lightMap = this.lightMap; a.bumpMap = this.bumpMap; a.bumpScale = this.bumpScale; a.normalMap = this.normalMap; a.normalScale.copy(this.normalScale); a.specularMap = this.specularMap; a.envMap = this.envMap; a.combine = this.combine; a.reflectivity = this.reflectivity; a.refractionRatio = this.refractionRatio; a.fog = this.fog; a.shading = this.shading; a.wireframe = this.wireframe; a.wireframeLinewidth = this.wireframeLinewidth; a.wireframeLinecap = this.wireframeLinecap; a.wireframeLinejoin = this.wireframeLinejoin; a.vertexColors = this.vertexColors; a.skinning = this.skinning; a.morphTargets = this.morphTargets; a.morphNormals = this.morphNormals; return a }; THREE.MeshDepthMaterial = function (a) { THREE.Material.call(this); this.wireframe = !1; this.wireframeLinewidth = 1; this.setValues(a) }; THREE.MeshDepthMaterial.prototype = Object.create(THREE.Material.prototype); THREE.MeshDepthMaterial.prototype.clone = function () { var a = new THREE.MeshDepthMaterial; THREE.Material.prototype.clone.call(this, a); a.wireframe = this.wireframe; a.wireframeLinewidth = this.wireframeLinewidth; return a }; THREE.MeshNormalMaterial = function (a) { THREE.Material.call(this, a); this.shading = THREE.FlatShading; this.wireframe = !1; this.wireframeLinewidth = 1; this.setValues(a) }; THREE.MeshNormalMaterial.prototype = Object.create(THREE.Material.prototype); THREE.MeshNormalMaterial.prototype.clone = function () { var a = new THREE.MeshNormalMaterial; THREE.Material.prototype.clone.call(this, a); a.shading = this.shading; a.wireframe = this.wireframe; a.wireframeLinewidth = this.wireframeLinewidth; return a }; THREE.MeshFaceMaterial = function (a) { this.materials = a instanceof Array ? a : [] }; THREE.MeshFaceMaterial.prototype.clone = function () { return new THREE.MeshFaceMaterial(this.materials.slice(0)) }; THREE.ParticleBasicMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.map = null; this.size = 1; this.sizeAttenuation = !0; this.vertexColors = !1; this.fog = !0; this.setValues(a) }; THREE.ParticleBasicMaterial.prototype = Object.create(THREE.Material.prototype); THREE.ParticleBasicMaterial.prototype.clone = function () { var a = new THREE.ParticleBasicMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.map = this.map; a.size = this.size; a.sizeAttenuation = this.sizeAttenuation; a.vertexColors = this.vertexColors; a.fog = this.fog; return a }; THREE.ParticleCanvasMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.program = function () { }; this.setValues(a) }; THREE.ParticleCanvasMaterial.prototype = Object.create(THREE.Material.prototype); THREE.ParticleCanvasMaterial.prototype.clone = function () { var a = new THREE.ParticleCanvasMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.program = this.program; return a }; THREE.ShaderMaterial = function (a) { THREE.Material.call(this); this.vertexShader = this.fragmentShader = "void main() {}"; this.uniforms = {}; this.defines = {}; this.attributes = null; this.shading = THREE.SmoothShading; this.wireframe = !1; this.wireframeLinewidth = 1; this.lights = this.fog = !1; this.vertexColors = THREE.NoColors; this.morphNormals = this.morphTargets = this.skinning = !1; this.setValues(a) }; THREE.ShaderMaterial.prototype = Object.create(THREE.Material.prototype); THREE.ShaderMaterial.prototype.clone = function () { var a = new THREE.ShaderMaterial; THREE.Material.prototype.clone.call(this, a); a.fragmentShader = this.fragmentShader; a.vertexShader = this.vertexShader; a.uniforms = THREE.UniformsUtils.clone(this.uniforms); a.attributes = this.attributes; a.defines = this.defines; a.shading = this.shading; a.wireframe = this.wireframe; a.wireframeLinewidth = this.wireframeLinewidth; a.fog = this.fog; a.lights = this.lights; a.vertexColors = this.vertexColors; a.skinning = this.skinning; a.morphTargets = this.morphTargets; a.morphNormals = this.morphNormals; return a }; THREE.SpriteMaterial = function (a) { THREE.Material.call(this); this.color = new THREE.Color(16777215); this.map = new THREE.Texture; this.useScreenCoordinates = !0; this.depthTest = !this.useScreenCoordinates; this.sizeAttenuation = !this.useScreenCoordinates; this.scaleByViewport = !this.sizeAttenuation; this.alignment = THREE.SpriteAlignment.center.clone(); this.fog = !1; this.uvOffset = new THREE.Vector2(0, 0); this.uvScale = new THREE.Vector2(1, 1); this.setValues(a); a = a || {}; void 0 === a.depthTest && (this.depthTest = !this.useScreenCoordinates); void 0 === a.sizeAttenuation && (this.sizeAttenuation = !this.useScreenCoordinates); void 0 === a.scaleByViewport && (this.scaleByViewport = !this.sizeAttenuation) }; THREE.SpriteMaterial.prototype = Object.create(THREE.Material.prototype); THREE.SpriteMaterial.prototype.clone = function () { var a = new THREE.SpriteMaterial; THREE.Material.prototype.clone.call(this, a); a.color.copy(this.color); a.map = this.map; a.useScreenCoordinates = this.useScreenCoordinates; a.sizeAttenuation = this.sizeAttenuation; a.scaleByViewport = this.scaleByViewport; a.alignment.copy(this.alignment); a.uvOffset.copy(this.uvOffset); a.uvScale.copy(this.uvScale); a.fog = this.fog; return a }; THREE.SpriteAlignment = {}; THREE.SpriteAlignment.topLeft = new THREE.Vector2(1, -1); THREE.SpriteAlignment.topCenter = new THREE.Vector2(0, -1); THREE.SpriteAlignment.topRight = new THREE.Vector2(-1, -1); THREE.SpriteAlignment.centerLeft = new THREE.Vector2(1, 0); THREE.SpriteAlignment.center = new THREE.Vector2(0, 0); THREE.SpriteAlignment.centerRight = new THREE.Vector2(-1, 0); THREE.SpriteAlignment.bottomLeft = new THREE.Vector2(1, 1); THREE.SpriteAlignment.bottomCenter = new THREE.Vector2(0, 1); THREE.SpriteAlignment.bottomRight = new THREE.Vector2(-1, 1); THREE.Texture = function (a, b, c, d, e, f, g, h, i) { THREE.EventDispatcher.call(this); this.id = THREE.TextureIdCount++; this.name = ""; this.image = a; this.mipmaps = []; this.mapping = void 0 !== b ? b : new THREE.UVMapping; this.wrapS = void 0 !== c ? c : THREE.ClampToEdgeWrapping; this.wrapT = void 0 !== d ? d : THREE.ClampToEdgeWrapping; this.magFilter = void 0 !== e ? e : THREE.LinearFilter; this.minFilter = void 0 !== f ? f : THREE.LinearMipMapLinearFilter; this.anisotropy = void 0 !== i ? i : 1; this.format = void 0 !== g ? g : THREE.RGBAFormat; this.type = void 0 !== h ? h : THREE.UnsignedByteType; this.offset = new THREE.Vector2(0, 0); this.repeat = new THREE.Vector2(1, 1); this.generateMipmaps = !0; this.premultiplyAlpha = !1; this.flipY = !0; this.unpackAlignment = 4; this.needsUpdate = !1; this.onUpdate = null }; THREE.Texture.prototype = { constructor: THREE.Texture, clone: function (a) { void 0 === a && (a = new THREE.Texture); a.image = this.image; a.mipmaps = this.mipmaps.slice(0); a.mapping = this.mapping; a.wrapS = this.wrapS; a.wrapT = this.wrapT; a.magFilter = this.magFilter; a.minFilter = this.minFilter; a.anisotropy = this.anisotropy; a.format = this.format; a.type = this.type; a.offset.copy(this.offset); a.repeat.copy(this.repeat); a.generateMipmaps = this.generateMipmaps; a.premultiplyAlpha = this.premultiplyAlpha; a.flipY = this.flipY; a.unpackAlignment = this.unpackAlignment; return a }, dispose: function () { this.dispatchEvent({type: "dispose"}) } }; THREE.TextureIdCount = 0; THREE.CompressedTexture = function (a, b, c, d, e, f, g, h, i, k, l) { THREE.Texture.call(this, null, f, g, h, i, k, d, e, l); this.image = {width: b, height: c}; this.mipmaps = a; this.generateMipmaps = !1 }; THREE.CompressedTexture.prototype = Object.create(THREE.Texture.prototype); THREE.CompressedTexture.prototype.clone = function () { var a = new THREE.CompressedTexture; THREE.Texture.prototype.clone.call(this, a); return a }; THREE.DataTexture = function (a, b, c, d, e, f, g, h, i, k, l) { THREE.Texture.call(this, null, f, g, h, i, k, d, e, l); this.image = {data: a, width: b, height: c} }; THREE.DataTexture.prototype = Object.create(THREE.Texture.prototype); THREE.DataTexture.prototype.clone = function () { var a = new THREE.DataTexture; THREE.Texture.prototype.clone.call(this, a); return a }; THREE.Particle = function (a) { THREE.Object3D.call(this); this.material = a }; THREE.Particle.prototype = Object.create(THREE.Object3D.prototype); THREE.Particle.prototype.clone = function (a) { void 0 === a && (a = new THREE.Particle(this.material)); THREE.Object3D.prototype.clone.call(this, a); return a }; THREE.ParticleSystem = function (a, b) { THREE.Object3D.call(this); this.geometry = a; this.material = void 0 !== b ? b : new THREE.ParticleBasicMaterial({color: 16777215 * Math.random()}); this.sortParticles = !1; this.geometry && null === this.geometry.boundingSphere && this.geometry.computeBoundingSphere(); this.frustumCulled = !1 }; THREE.ParticleSystem.prototype = Object.create(THREE.Object3D.prototype); THREE.ParticleSystem.prototype.clone = function (a) { void 0 === a && (a = new THREE.ParticleSystem(this.geometry, this.material)); a.sortParticles = this.sortParticles; THREE.Object3D.prototype.clone.call(this, a); return a }; THREE.Line = function (a, b, c) { THREE.Object3D.call(this); this.geometry = a; this.material = void 0 !== b ? b : new THREE.LineBasicMaterial({color: 16777215 * Math.random()}); this.type = void 0 !== c ? c : THREE.LineStrip; this.geometry && (this.geometry.boundingSphere || this.geometry.computeBoundingSphere()) }; THREE.LineStrip = 0; THREE.LinePieces = 1; THREE.Line.prototype = Object.create(THREE.Object3D.prototype); THREE.Line.prototype.clone = function (a) { void 0 === a && (a = new THREE.Line(this.geometry, this.material, this.type)); THREE.Object3D.prototype.clone.call(this, a); return a }; THREE.Mesh = function (a, b) { THREE.Object3D.call(this); this.geometry = a; this.material = void 0 !== b ? b : new THREE.MeshBasicMaterial({color: 16777215 * Math.random(), wireframe: !0}); void 0 !== this.geometry && (null === this.geometry.boundingSphere && this.geometry.computeBoundingSphere(), this.updateMorphTargets()) }; THREE.Mesh.prototype = Object.create(THREE.Object3D.prototype); THREE.Mesh.prototype.updateMorphTargets = function () { if (0 < this.geometry.morphTargets.length) { this.morphTargetBase = -1; this.morphTargetForcedOrder = []; this.morphTargetInfluences = []; this.morphTargetDictionary = {}; for (var a = 0, b = this.geometry.morphTargets.length; a < b; a++) this.morphTargetInfluences.push(0), this.morphTargetDictionary[this.geometry.morphTargets[a].name] = a } }; THREE.Mesh.prototype.getMorphTargetIndexByName = function (a) { if (void 0 !== this.morphTargetDictionary[a]) return this.morphTargetDictionary[a]; console.log("THREE.Mesh.getMorphTargetIndexByName: morph target " + a + " does not exist. Returning 0."); return 0 }; THREE.Mesh.prototype.clone = function (a) { void 0 === a && (a = new THREE.Mesh(this.geometry, this.material)); THREE.Object3D.prototype.clone.call(this, a); return a }; THREE.Bone = function (a) { THREE.Object3D.call(this); this.skin = a; this.skinMatrix = new THREE.Matrix4 }; THREE.Bone.prototype = Object.create(THREE.Object3D.prototype); THREE.Bone.prototype.update = function (a, b) { this.matrixAutoUpdate && (b |= this.updateMatrix()); if (b || this.matrixWorldNeedsUpdate) a ? this.skinMatrix.multiplyMatrices(a, this.matrix) : this.skinMatrix.copy(this.matrix), this.matrixWorldNeedsUpdate = !1, b = !0; var c, d = this.children.length; for (c = 0; c < d; c++) this.children[c].update(this.skinMatrix, b) }; THREE.SkinnedMesh = function (a, b, c) { THREE.Mesh.call(this, a, b); this.useVertexTexture = void 0 !== c ? c : !0; this.identityMatrix = new THREE.Matrix4; this.bones = []; this.boneMatrices = []; var d, e, f; if (this.geometry && void 0 !== this.geometry.bones) { for (a = 0; a < this.geometry.bones.length; a++) c = this.geometry.bones[a], d = c.pos, e = c.rotq, f = c.scl, b = this.addBone(), b.name = c.name, b.position.set(d[0], d[1], d[2]), b.quaternion.set(e[0], e[1], e[2], e[3]), b.useQuaternion = !0, void 0 !== f ? b.scale.set(f[0], f[1], f[2]) : b.scale.set(1, 1, 1); for (a = 0; a < this.bones.length; a++) c = this.geometry.bones[a], b = this.bones[a], -1 === c.parent ? this.add(b) : this.bones[c.parent].add(b); a = this.bones.length; this.useVertexTexture ? (this.boneTextureHeight = this.boneTextureWidth = a = 256 < a ? 64 : 64 < a ? 32 : 16 < a ? 16 : 8, this.boneMatrices = new Float32Array(4 * this.boneTextureWidth * this.boneTextureHeight), this.boneTexture = new THREE.DataTexture(this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType), this.boneTexture.minFilter = THREE.NearestFilter, this.boneTexture.magFilter = THREE.NearestFilter, this.boneTexture.generateMipmaps = !1, this.boneTexture.flipY = !1) : this.boneMatrices = new Float32Array(16 * a); this.pose() } }; THREE.SkinnedMesh.prototype = Object.create(THREE.Mesh.prototype); THREE.SkinnedMesh.prototype.addBone = function (a) { void 0 === a && (a = new THREE.Bone(this)); this.bones.push(a); return a }; THREE.SkinnedMesh.prototype.updateMatrixWorld = function (a) { this.matrixAutoUpdate && this.updateMatrix(); if (this.matrixWorldNeedsUpdate || a) this.parent ? this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix) : this.matrixWorld.copy(this.matrix), this.matrixWorldNeedsUpdate = !1; for (var a = 0, b = this.children.length; a < b; a++) { var c = this.children[a]; c instanceof THREE.Bone ? c.update(this.identityMatrix, !1) : c.updateMatrixWorld(!0) } if (void 0 == this.boneInverses) { this.boneInverses = []; a = 0; for (b = this.bones.length; a < b; a++) c = new THREE.Matrix4, c.getInverse(this.bones[a].skinMatrix), this.boneInverses.push(c) } a = 0; for (b = this.bones.length; a < b; a++) THREE.SkinnedMesh.offsetMatrix.multiplyMatrices(this.bones[a].skinMatrix, this.boneInverses[a]), THREE.SkinnedMesh.offsetMatrix.flattenToArrayOffset(this.boneMatrices, 16 * a); this.useVertexTexture && (this.boneTexture.needsUpdate = !0) }; THREE.SkinnedMesh.prototype.pose = function () { this.updateMatrixWorld(!0); for (var a = 0; a < this.geometry.skinIndices.length; a++) { var b = this.geometry.skinWeights[a], c = 1 / b.lengthManhattan(); Infinity !== c ? b.multiplyScalar(c) : b.set(1) } }; THREE.SkinnedMesh.prototype.clone = function (a) { void 0 === a && (a = new THREE.SkinnedMesh(this.geometry, this.material, this.useVertexTexture)); THREE.Mesh.prototype.clone.call(this, a); return a }; THREE.SkinnedMesh.offsetMatrix = new THREE.Matrix4; THREE.MorphAnimMesh = function (a, b) { THREE.Mesh.call(this, a, b); this.duration = 1E3; this.mirroredLoop = !1; this.currentKeyframe = this.lastKeyframe = this.time = 0; this.direction = 1; this.directionBackwards = !1; this.setFrameRange(0, this.geometry.morphTargets.length - 1) }; THREE.MorphAnimMesh.prototype = Object.create(THREE.Mesh.prototype); THREE.MorphAnimMesh.prototype.setFrameRange = function (a, b) { this.startKeyframe = a; this.endKeyframe = b; this.length = this.endKeyframe - this.startKeyframe + 1 }; THREE.MorphAnimMesh.prototype.setDirectionForward = function () { this.direction = 1; this.directionBackwards = !1 }; THREE.MorphAnimMesh.prototype.setDirectionBackward = function () { this.direction = -1; this.directionBackwards = !0 }; THREE.MorphAnimMesh.prototype.parseAnimations = function () { var a = this.geometry; a.animations || (a.animations = {}); for (var b, c = a.animations, d = /([a-z]+)(\d+)/, e = 0, f = a.morphTargets.length; e < f; e++) { var g = a.morphTargets[e].name.match(d); if (g && 1 < g.length) { g = g[1]; c[g] || (c[g] = {start: Infinity, end: -Infinity}); var h = c[g]; e < h.start && (h.start = e); e > h.end && (h.end = e); b || (b = g) } } a.firstAnimation = b }; THREE.MorphAnimMesh.prototype.setAnimationLabel = function (a, b, c) { this.geometry.animations || (this.geometry.animations = {}); this.geometry.animations[a] = {start: b, end: c} }; THREE.MorphAnimMesh.prototype.playAnimation = function (a, b) { var c = this.geometry.animations[a]; c ? (this.setFrameRange(c.start, c.end), this.duration = 1E3 * ((c.end - c.start) / b), this.time = 0) : console.warn("animation[" + a + "] undefined") }; THREE.MorphAnimMesh.prototype.updateAnimation = function (a) { var b = this.duration / this.length; this.time += this.direction * a; if (this.mirroredLoop) { if (this.time > this.duration || 0 > this.time) this.direction *= -1, this.time > this.duration && (this.time = this.duration, this.directionBackwards = !0), 0 > this.time && (this.time = 0, this.directionBackwards = !1) } else this.time %= this.duration, 0 > this.time && (this.time += this.duration); a = this.startKeyframe + THREE.Math.clamp(Math.floor(this.time / b), 0, this.length - 1); a !== this.currentKeyframe && (this.morphTargetInfluences[this.lastKeyframe] = 0, this.morphTargetInfluences[this.currentKeyframe] = 1, this.morphTargetInfluences[a] = 0, this.lastKeyframe = this.currentKeyframe, this.currentKeyframe = a); b = this.time % b / b; this.directionBackwards && (b = 1 - b); this.morphTargetInfluences[this.currentKeyframe] = b; this.morphTargetInfluences[this.lastKeyframe] = 1 - b }; THREE.MorphAnimMesh.prototype.clone = function (a) { void 0 === a && (a = new THREE.MorphAnimMesh(this.geometry, this.material)); a.duration = this.duration; a.mirroredLoop = this.mirroredLoop; a.time = this.time; a.lastKeyframe = this.lastKeyframe; a.currentKeyframe = this.currentKeyframe; a.direction = this.direction; a.directionBackwards = this.directionBackwards; THREE.Mesh.prototype.clone.call(this, a); return a }; THREE.Ribbon = function (a, b) { THREE.Object3D.call(this); this.geometry = a; this.material = b }; THREE.Ribbon.prototype = Object.create(THREE.Object3D.prototype); THREE.Ribbon.prototype.clone = function (a) { void 0 === a && (a = new THREE.Ribbon(this.geometry, this.material)); THREE.Object3D.prototype.clone.call(this, a); return a }; THREE.LOD = function () { THREE.Object3D.call(this); this.LODs = [] }; THREE.LOD.prototype = Object.create(THREE.Object3D.prototype); THREE.LOD.prototype.addLevel = function (a, b) { void 0 === b && (b = 0); for (var b = Math.abs(b), c = 0; c < this.LODs.length && !(b < this.LODs[c].visibleAtDistance); c++) ; this.LODs.splice(c, 0, {visibleAtDistance: b, object3D: a}); this.add(a) }; THREE.LOD.prototype.update = function (a) { if (1 < this.LODs.length) { a.matrixWorldInverse.getInverse(a.matrixWorld); a = a.matrixWorldInverse; a = -(a.elements[2] * this.matrixWorld.elements[12] + a.elements[6] * this.matrixWorld.elements[13] + a.elements[10] * this.matrixWorld.elements[14] + a.elements[14]); this.LODs[0].object3D.visible = !0; for (var b = 1; b < this.LODs.length; b++) if (a >= this.LODs[b].visibleAtDistance) this.LODs[b - 1].object3D.visible = !1, this.LODs[b].object3D.visible = !0; else break; for (; b < this.LODs.length; b++) this.LODs[b].object3D.visible = !1 } }; THREE.LOD.prototype.clone = function () { }; THREE.Sprite = function (a) { THREE.Object3D.call(this); this.material = void 0 !== a ? a : new THREE.SpriteMaterial; this.rotation3d = this.rotation; this.rotation = 0 }; THREE.Sprite.prototype = Object.create(THREE.Object3D.prototype); THREE.Sprite.prototype.updateMatrix = function () { this.matrix.setPosition(this.position); this.rotation3d.set(0, 0, this.rotation); this.matrix.setRotationFromEuler(this.rotation3d); (1 !== this.scale.x || 1 !== this.scale.y) && this.matrix.scale(this.scale); this.matrixWorldNeedsUpdate = !0 }; THREE.Sprite.prototype.clone = function (a) { void 0 === a && (a = new THREE.Sprite(this.material)); THREE.Object3D.prototype.clone.call(this, a); return a }; THREE.Scene = function () { THREE.Object3D.call(this); this.overrideMaterial = this.fog = null; this.matrixAutoUpdate = !1; this.__objects = []; this.__lights = []; this.__objectsAdded = []; this.__objectsRemoved = [] }; THREE.Scene.prototype = Object.create(THREE.Object3D.prototype); THREE.Scene.prototype.__addObject = function (a) { if (a instanceof THREE.Light) -1 === this.__lights.indexOf(a) && this.__lights.push(a), a.target && void 0 === a.target.parent && this.add(a.target); else if (!(a instanceof THREE.Camera || a instanceof THREE.Bone) && -1 === this.__objects.indexOf(a)) { this.__objects.push(a); this.__objectsAdded.push(a); var b = this.__objectsRemoved.indexOf(a); -1 !== b && this.__objectsRemoved.splice(b, 1) } for (b = 0; b < a.children.length; b++) this.__addObject(a.children[b]) }; THREE.Scene.prototype.__removeObject = function (a) { if (a instanceof THREE.Light) { var b = this.__lights.indexOf(a); -1 !== b && this.__lights.splice(b, 1) } else a instanceof THREE.Camera || (b = this.__objects.indexOf(a), -1 !== b && (this.__objects.splice(b, 1), this.__objectsRemoved.push(a), b = this.__objectsAdded.indexOf(a), -1 !== b && this.__objectsAdded.splice(b, 1))); for (b = 0; b < a.children.length; b++) this.__removeObject(a.children[b]) }; THREE.Fog = function (a, b, c) { this.name = ""; this.color = new THREE.Color(a); this.near = void 0 !== b ? b : 1; this.far = void 0 !== c ? c : 1E3 }; THREE.Fog.prototype.clone = function () { return new THREE.Fog(this.color.getHex(), this.near, this.far) }; THREE.FogExp2 = function (a, b) { this.name = ""; this.color = new THREE.Color(a); this.density = void 0 !== b ? b : 2.5E-4 }; THREE.FogExp2.prototype.clone = function () { return new THREE.FogExp2(this.color.getHex(), this.density) }; THREE.CanvasRenderer = function (a) { function b(a) { D !== a && (D = u.globalAlpha = a) } function c(a) { w !== a && (a === THREE.NormalBlending ? u.globalCompositeOperation = "source-over" : a === THREE.AdditiveBlending ? u.globalCompositeOperation = "lighter" : a === THREE.SubtractiveBlending && (u.globalCompositeOperation = "darker"), w = a) } function d(a) { E !== a && (E = u.lineWidth = a) } function e(a) { Z !== a && (Z = u.lineCap = a) } function f(a) { A !== a && (A = u.lineJoin = a) } function g(a) { I !== a && (I = u.strokeStyle = a) } function h(a) { J !== a && (J = u.fillStyle = a) } function i(a, b) { if (S !== a || F !== b) u.setLineDash([a, b]), S = a, F = b } console.log("THREE.CanvasRenderer", THREE.REVISION); var k = THREE.Math.smoothstep, a = a || {}, l = this, m, p, s, r = new THREE.Projector, n = void 0 !== a.canvas ? a.canvas : document.createElement("canvas"), q, z, t, x, u = n.getContext("2d"), B = new THREE.Color(0), G = 0, D = 1, w = 0, I = null, J = null, E = null, Z = null, A = null, S = null, F = 0, H, K, N, fa, ma = new THREE.RenderableVertex, eb = new THREE.RenderableVertex, M, U, ja, L, ca, ta, kb, $a, lb, db, La, Oa, ea = new THREE.Color, ha = new THREE.Color, V = new THREE.Color, $ = new THREE.Color, Y = new THREE.Color, ia = new THREE.Color, ra = new THREE.Color, na = new THREE.Color, Pa = {}, Ba = {}, fb, jb, Sa, ob, Gb, Mb, wb, Nb, Ob, xb, Hb = new THREE.Box2, Qa = new THREE.Box2, Va = new THREE.Box2, wa = new THREE.Color, xa = new THREE.Color, yb = new THREE.Color, pb = new THREE.Vector3, j, mb, vb, Wa, Ga, zb, Ib = 16; j = document.createElement("canvas"); j.width = j.height = 2; mb = j.getContext("2d"); mb.fillStyle = "rgba(0,0,0,1)"; mb.fillRect(0, 0, 2, 2); vb = mb.getImageData(0, 0, 2, 2); Wa = vb.data; Ga = document.createElement("canvas"); Ga.width = Ga.height = Ib; zb = Ga.getContext("2d"); zb.translate(-Ib / 2, -Ib / 2); zb.scale(Ib, Ib); Ib--; void 0 === u.setLineDash && (u.setLineDash = void 0 !== u.mozDash ? function (a) { u.mozDash = null !== a[0] ? a : null } : function () { }); this.domElement = n; this.devicePixelRatio = void 0 !== a.devicePixelRatio ? a.devicePixelRatio : void 0 !== window.devicePixelRatio ? window.devicePixelRatio : 1; this.sortElements = this.sortObjects = this.autoClear = !0; this.info = {render: {vertices: 0, faces: 0}}; this.supportsVertexTextures = function () { }; this.setFaceCulling = function () { }; this.setSize = function (a, b) { q = a * this.devicePixelRatio; z = b * this.devicePixelRatio; t = Math.floor(q / 2); x = Math.floor(z / 2); n.width = q; n.height = z; n.style.width = a + "px"; n.style.height = b + "px"; Hb.set(new THREE.Vector2(-t, -x), new THREE.Vector2(t, x)); Qa.set(new THREE.Vector2(-t, -x), new THREE.Vector2(t, x)); D = 1; w = 0; A = Z = E = J = I = null }; this.setClearColor = function (a, b) { B.copy(a); G = void 0 !== b ? b : 1; Qa.set(new THREE.Vector2(-t, -x), new THREE.Vector2(t, x)) }; this.setClearColorHex = function (a, b) { B.setHex(a); G = void 0 !== b ? b : 1; Qa.set(new THREE.Vector2(-t, -x), new THREE.Vector2(t, x)) }; this.getMaxAnisotropy = function () { return 0 }; this.clear = function () { u.setTransform(1, 0, 0, -1, t, x); !1 === Qa.empty() && (Qa.intersect(Hb), Qa.expandByScalar(2), 1 > G && u.clearRect(Qa.min.x | 0, Qa.min.y | 0, Qa.max.x - Qa.min.x | 0, Qa.max.y - Qa.min.y | 0), 0 < G && (c(THREE.NormalBlending), b(1), h("rgba(" + Math.floor(255 * B.r) + "," + Math.floor(255 * B.g) + "," + Math.floor(255 * B.b) + "," + G + ")"), u.fillRect(Qa.min.x | 0, Qa.min.y | 0, Qa.max.x - Qa.min.x | 0, Qa.max.y - Qa.min.y | 0)), Qa.makeEmpty()) }; this.render = function (a, n) { function q(a, b, c) { for (var d = 0, e = s.length; d < e; d++) { var f = s[d]; na.copy(f.color); if (f instanceof THREE.DirectionalLight) { var g = pb.getPositionFromMatrix(f.matrixWorld).normalize(), h = b.dot(g); 0 >= h || (h *= f.intensity, c.add(na.multiplyScalar(h))) } else f instanceof THREE.PointLight && (g = pb.getPositionFromMatrix(f.matrixWorld), h = b.dot(pb.subVectors(g, a).normalize()), 0 >= h || (h *= 0 == f.distance ? 1 : 1 - Math.min(a.distanceTo(g) / f.distance, 1), 0 != h && (h *= f.intensity, c.add(na.multiplyScalar(h))))) } } function w(a, d, e, f, g, h, j, i) { l.info.render.vertices += 3; l.info.render.faces++; b(i.opacity); c(i.blending); M = a.positionScreen.x; U = a.positionScreen.y; ja = d.positionScreen.x; L = d.positionScreen.y; ca = e.positionScreen.x; ta = e.positionScreen.y; z(M, U, ja, L, ca, ta); (i instanceof THREE.MeshLambertMaterial || i instanceof THREE.MeshPhongMaterial) && null === i.map ? (ia.copy(i.color), ra.copy(i.emissive), i.vertexColors === THREE.FaceColors && ia.multiply(j.color), !1 === i.wireframe && i.shading == THREE.SmoothShading && 3 == j.vertexNormalsLength ? (ha.copy(wa), V.copy(wa), $.copy(wa), q(j.v1.positionWorld, j.vertexNormalsModel[0], ha), q(j.v2.positionWorld, j.vertexNormalsModel[1], V), q(j.v3.positionWorld, j.vertexNormalsModel[2], $), ha.multiply(ia).add(ra), V.multiply(ia).add(ra), $.multiply(ia).add(ra), Y.addColors(V, $).multiplyScalar(0.5), Sa = Dc(ha, V, $, Y), ab(M, U, ja, L, ca, ta, 0, 0, 1, 0, 0, 1, Sa)) : (ea.copy(wa), q(j.centroidModel, j.normalModel, ea), ea.multiply(ia).add(ra), !0 === i.wireframe ? B(ea, i.wireframeLinewidth, i.wireframeLinecap, i.wireframeLinejoin) : D(ea))) : i instanceof THREE.MeshBasicMaterial || i instanceof THREE.MeshLambertMaterial || i instanceof THREE.MeshPhongMaterial ? null !== i.map ? i.map.mapping instanceof THREE.UVMapping && (ob = j.uvs[0], F(M, U, ja, L, ca, ta, ob[f].x, ob[f].y, ob[g].x, ob[g].y, ob[h].x, ob[h].y, i.map)) : null !== i.envMap ? i.envMap.mapping instanceof THREE.SphericalReflectionMapping && (pb.copy(j.vertexNormalsModelView[f]), Gb = 0.5 * pb.x + 0.5, Mb = 0.5 * pb.y + 0.5, pb.copy(j.vertexNormalsModelView[g]), wb = 0.5 * pb.x + 0.5, Nb = 0.5 * pb.y + 0.5, pb.copy(j.vertexNormalsModelView[h]), Ob = 0.5 * pb.x + 0.5, xb = 0.5 * pb.y + 0.5, F(M, U, ja, L, ca, ta, Gb, Mb, wb, Nb, Ob, xb, i.envMap)) : (ea.copy(i.color), i.vertexColors === THREE.FaceColors && ea.multiply(j.color), !0 === i.wireframe ? B(ea, i.wireframeLinewidth, i.wireframeLinecap, i.wireframeLinejoin) : D(ea)) : i instanceof THREE.MeshDepthMaterial ? (fb = n.near, jb = n.far, ha.r = ha.g = ha.b = 1 - k(a.positionScreen.z * a.positionScreen.w, fb, jb), V.r = V.g = V.b = 1 - k(d.positionScreen.z * d.positionScreen.w, fb, jb), $.r = $.g = $.b = 1 - k(e.positionScreen.z * e.positionScreen.w, fb, jb), Y.addColors(V, $).multiplyScalar(0.5), Sa = Dc(ha, V, $, Y), ab(M, U, ja, L, ca, ta, 0, 0, 1, 0, 0, 1, Sa)) : i instanceof THREE.MeshNormalMaterial && (i.shading == THREE.FlatShading ? (a = j.normalModelView, ea.setRGB(a.x, a.y, a.z).multiplyScalar(0.5).addScalar(0.5), !0 === i.wireframe ? B(ea, i.wireframeLinewidth, i.wireframeLinecap, i.wireframeLinejoin) : D(ea)) : i.shading == THREE.SmoothShading && (a = j.vertexNormalsModelView[f], ha.setRGB(a.x, a.y, a.z).multiplyScalar(0.5).addScalar(0.5), a = j.vertexNormalsModelView[g], V.setRGB(a.x, a.y, a.z).multiplyScalar(0.5).addScalar(0.5), a = j.vertexNormalsModelView[h], $.setRGB(a.x, a.y, a.z).multiplyScalar(0.5).addScalar(0.5), Y.addColors(V, $).multiplyScalar(0.5), Sa = Dc(ha, V, $, Y), ab(M, U, ja, L, ca, ta, 0, 0, 1, 0, 0, 1, Sa))) } function z(a, b, c, d, e, f) { u.beginPath(); u.moveTo(a, b); u.lineTo(c, d); u.lineTo(e, f); u.closePath() } function A(a, b, c, d, e, f, g, h) { u.beginPath(); u.moveTo(a, b); u.lineTo(c, d); u.lineTo(e, f); u.lineTo(g, h); u.closePath() } function B(a, b, c, h) { d(b); e(c); f(h); g(a.getStyle()); u.stroke(); Va.expandByScalar(2 * b) } function D(a) { h(a.getStyle()); u.fill() } function F(a, b, c, d, e, f, g, j, i, k, ab, l, m) { if (!(m instanceof THREE.DataTexture || void 0 === m.image || 0 == m.image.width)) { if (!0 === m.needsUpdate) { var p = m.wrapS == THREE.RepeatWrapping, n = m.wrapT == THREE.RepeatWrapping; Pa[m.id] = u.createPattern(m.image, !0 === p && !0 === n ? "repeat" : !0 === p && !1 === n ? "repeat-x" : !1 === p && !0 === n ? "repeat-y" : "no-repeat"); m.needsUpdate = !1 } void 0 === Pa[m.id] ? h("rgba(0,0,0,1)") : h(Pa[m.id]); var p = m.offset.x / m.repeat.x, n = m.offset.y / m.repeat.y, Jb = m.image.width * m.repeat.x, q = m.image.height * m.repeat.y, g = (g + p) * Jb, j = (1 - j + n) * q, c = c - a, d = d - b, e = e - a, f = f - b, i = (i + p) * Jb - g, k = (1 - k + n) * q - j, ab = (ab + p) * Jb - g, l = (1 - l + n) * q - j, p = i * l - ab * k; 0 === p ? (void 0 === Ba[m.id] && (b = document.createElement("canvas"), b.width = m.image.width, b.height = m.image.height, b = b.getContext("2d"), b.drawImage(m.image, 0, 0), Ba[m.id] = b.getImageData(0, 0, m.image.width, m.image.height).data), b = Ba[m.id], g = 4 * (Math.floor(g) + Math.floor(j) * m.image.width), ea.setRGB(b[g] / 255, b[g + 1] / 255, b[g + 2] / 255), D(ea)) : (p = 1 / p, m = (l * c - k * e) * p, k = (l * d - k * f) * p, c = (i * e - ab * c) * p, d = (i * f - ab * d) * p, a = a - m * g - c * j, g = b - k * g - d * j, u.save(), u.transform(m, k, c, d, a, g), u.fill(), u.restore()) } } function ab(a, b, c, d, e, f, g, h, j, i, k, ab, m) { var l, p; l = m.width - 1; p = m.height - 1; g *= l; h *= p; c -= a; d -= b; e -= a; f -= b; j = j * l - g; i = i * p - h; k = k * l - g; ab = ab * p - h; p = 1 / (j * ab - k * i); l = (ab * c - i * e) * p; i = (ab * d - i * f) * p; c = (j * e - k * c) * p; d = (j * f - k * d) * p; a = a - l * g - c * h; b = b - i * g - d * h; u.save(); u.transform(l, i, c, d, a, b); u.clip(); u.drawImage(m, 0, 0); u.restore() } function Dc(a, b, c, d) { Wa[0] = 255 * a.r | 0; Wa[1] = 255 * a.g | 0; Wa[2] = 255 * a.b | 0; Wa[4] = 255 * b.r | 0; Wa[5] = 255 * b.g | 0; Wa[6] = 255 * b.b | 0; Wa[8] = 255 * c.r | 0; Wa[9] = 255 * c.g | 0; Wa[10] = 255 * c.b | 0; Wa[12] = 255 * d.r | 0; Wa[13] = 255 * d.g | 0; Wa[14] = 255 * d.b | 0; mb.putImageData(vb, 0, 0); zb.drawImage(j, 0, 0); return Ga } function Jb(a, b) { var c = b.x - a.x, d = b.y - a.y, e = c * c + d * d; 0 !== e && (e = 1 / Math.sqrt(e), c *= e, d *= e, b.x += c, b.y += d, a.x -= c, a.y -= d) } if (!1 === n instanceof THREE.Camera) console.error("THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera."); else { !0 === this.autoClear && this.clear(); u.setTransform(1, 0, 0, -1, t, x); l.info.render.vertices = 0; l.info.render.faces = 0; m = r.projectScene(a, n, this.sortObjects, this.sortElements); p = m.elements; s = m.lights; wa.setRGB(0, 0, 0); xa.setRGB(0, 0, 0); yb.setRGB(0, 0, 0); for (var wc = 0, qd = s.length; wc < qd; wc++) { var W = s[wc], ga = W.color; W instanceof THREE.AmbientLight ? wa.add(ga) : W instanceof THREE.DirectionalLight ? xa.add(ga) : W instanceof THREE.PointLight && yb.add(ga) } wc = 0; for (qd = p.length; wc < qd; wc++) { var oa = p[wc], W = oa.material; if (!(void 0 === W || !1 === W.visible)) { Va.makeEmpty(); if (oa instanceof THREE.RenderableParticle) { H = oa; H.x *= t; H.y *= x; var ga = H, gb = oa; b(W.opacity); c(W.blending); var Ab = void 0, G = void 0, Bb = void 0, E = void 0, I = oa = void 0, J = void 0; W instanceof THREE.ParticleBasicMaterial ? null === W.map ? (Bb = gb.object.scale.x, E = gb.object.scale.y, Bb *= gb.scale.x * t, E *= gb.scale.y * x, Va.min.set(ga.x - Bb, ga.y - E), Va.max.set(ga.x + Bb, ga.y + E), !1 !== Hb.isIntersectionBox(Va) && (h(W.color.getStyle()), u.save(), u.translate(ga.x, ga.y), u.rotate(-gb.rotation), u.scale(Bb, E), u.fillRect(-1, -1, 2, 2), u.restore())) : (oa = W.map.image, I = oa.width >> 1, J = oa.height >> 1, Bb = gb.scale.x * t, E = gb.scale.y * x, Ab = Bb * I, G = E * J, Va.min.set(ga.x - Ab, ga.y - G), Va.max.set(ga.x + Ab, ga.y + G), !1 !== Hb.isIntersectionBox(Va) && (u.save(), u.translate(ga.x, ga.y), u.rotate(-gb.rotation), u.scale(Bb, -E), u.translate(-I, -J), u.drawImage(oa, 0, 0), u.restore())) : W instanceof THREE.ParticleCanvasMaterial && (Ab = gb.scale.x * t, G = gb.scale.y * x, Va.min.set(ga.x - Ab, ga.y - G), Va.max.set(ga.x + Ab, ga.y + G), !1 !== Hb.isIntersectionBox(Va) && (g(W.color.getStyle()), h(W.color.getStyle()), u.save(), u.translate(ga.x, ga.y), u.rotate(-gb.rotation), u.scale(Ab, G), W.program(u), u.restore())) } else if (oa instanceof THREE.RenderableLine) H = oa.v1, K = oa.v2, H.positionScreen.x *= t, H.positionScreen.y *= x, K.positionScreen.x *= t, K.positionScreen.y *= x, Va.setFromPoints([H.positionScreen, K.positionScreen]), !0 === Hb.isIntersectionBox(Va) && (ga = H, gb = K, b(W.opacity), c(W.blending), u.beginPath(), u.moveTo(ga.positionScreen.x, ga.positionScreen.y), u.lineTo(gb.positionScreen.x, gb.positionScreen.y), W instanceof THREE.LineBasicMaterial ? (d(W.linewidth), e(W.linecap), f(W.linejoin), g(W.color.getStyle()), u.stroke(), Va.expandByScalar(2 * W.linewidth)) : W instanceof THREE.LineDashedMaterial && (d(W.linewidth), e(W.linecap), f(W.linejoin), g(W.color.getStyle()), i(W.dashSize, W.gapSize), u.stroke(), Va.expandByScalar(2 * W.linewidth), i(null, null))); else if (oa instanceof THREE.RenderableFace3) { H = oa.v1; K = oa.v2; N = oa.v3; if (-1 > H.positionScreen.z || 1 < H.positionScreen.z) continue; if (-1 > K.positionScreen.z || 1 < K.positionScreen.z) continue; if (-1 > N.positionScreen.z || 1 < N.positionScreen.z) continue; H.positionScreen.x *= t; H.positionScreen.y *= x; K.positionScreen.x *= t; K.positionScreen.y *= x; N.positionScreen.x *= t; N.positionScreen.y *= x; !0 === W.overdraw && (Jb(H.positionScreen, K.positionScreen), Jb(K.positionScreen, N.positionScreen), Jb(N.positionScreen, H.positionScreen)); Va.setFromPoints([H.positionScreen, K.positionScreen, N.positionScreen]); w(H, K, N, 0, 1, 2, oa, W) } else if (oa instanceof THREE.RenderableFace4) { H = oa.v1; K = oa.v2; N = oa.v3; fa = oa.v4; if (-1 > H.positionScreen.z || 1 < H.positionScreen.z) continue; if (-1 > K.positionScreen.z || 1 < K.positionScreen.z) continue; if (-1 > N.positionScreen.z || 1 < N.positionScreen.z) continue; if (-1 > fa.positionScreen.z || 1 < fa.positionScreen.z) continue; H.positionScreen.x *= t; H.positionScreen.y *= x; K.positionScreen.x *= t; K.positionScreen.y *= x; N.positionScreen.x *= t; N.positionScreen.y *= x; fa.positionScreen.x *= t; fa.positionScreen.y *= x; ma.positionScreen.copy(K.positionScreen); eb.positionScreen.copy(fa.positionScreen); !0 === W.overdraw && (Jb(H.positionScreen, K.positionScreen), Jb(K.positionScreen, fa.positionScreen), Jb(fa.positionScreen, H.positionScreen), Jb(N.positionScreen, ma.positionScreen), Jb(N.positionScreen, eb.positionScreen)); Va.setFromPoints([H.positionScreen, K.positionScreen, N.positionScreen, fa.positionScreen]); ga = H; gb = K; Ab = N; G = fa; Bb = ma; E = eb; l.info.render.vertices += 4; l.info.render.faces++; b(W.opacity); c(W.blending); void 0 !== W.map && null !== W.map || void 0 !== W.envMap && null !== W.envMap ? (w(ga, gb, G, 0, 1, 3, oa, W), w(Bb, Ab, E, 1, 2, 3, oa, W)) : (M = ga.positionScreen.x, U = ga.positionScreen.y, ja = gb.positionScreen.x, L = gb.positionScreen.y, ca = Ab.positionScreen.x, ta = Ab.positionScreen.y, kb = G.positionScreen.x, $a = G.positionScreen.y, lb = Bb.positionScreen.x, db = Bb.positionScreen.y, La = E.positionScreen.x, Oa = E.positionScreen.y, W instanceof THREE.MeshLambertMaterial || W instanceof THREE.MeshPhongMaterial ? (ia.copy(W.color), ra.copy(W.emissive), W.vertexColors === THREE.FaceColors && ia.multiply(oa.color), !1 === W.wireframe && W.shading == THREE.SmoothShading && 4 == oa.vertexNormalsLength ? (ha.copy(wa), V.copy(wa), $.copy(wa), Y.copy(wa), q(oa.v1.positionWorld, oa.vertexNormalsModel[0], ha), q(oa.v2.positionWorld, oa.vertexNormalsModel[1], V), q(oa.v4.positionWorld, oa.vertexNormalsModel[3], $), q(oa.v3.positionWorld, oa.vertexNormalsModel[2], Y), ha.multiply(ia).add(ra), V.multiply(ia).add(ra), $.multiply(ia).add(ra), Y.multiply(ia).add(ra), Sa = Dc(ha, V, $, Y), z(M, U, ja, L, kb, $a), ab(M, U, ja, L, kb, $a, 0, 0, 1, 0, 0, 1, Sa), z(lb, db, ca, ta, La, Oa), ab(lb, db, ca, ta, La, Oa, 1, 0, 1, 1, 0, 1, Sa)) : (ea.copy(wa), q(oa.centroidModel, oa.normalModel, ea), ea.multiply(ia).add(ra), A(M, U, ja, L, ca, ta, kb, $a), !0 === W.wireframe ? B(ea, W.wireframeLinewidth, W.wireframeLinecap, W.wireframeLinejoin) : D(ea))) : W instanceof THREE.MeshBasicMaterial ? (ea.copy(W.color), W.vertexColors === THREE.FaceColors && ea.multiply(oa.color), A(M, U, ja, L, ca, ta, kb, $a), !0 === W.wireframe ? B(ea, W.wireframeLinewidth, W.wireframeLinecap, W.wireframeLinejoin) : D(ea)) : W instanceof THREE.MeshNormalMaterial ? (ga = void 0, W.shading == THREE.FlatShading ? (ga = oa.normalModelView, ea.setRGB(ga.x, ga.y, ga.z).multiplyScalar(0.5).addScalar(0.5), A(M, U, ja, L, ca, ta, kb, $a), !0 === W.wireframe ? B(ea, W.wireframeLinewidth, W.wireframeLinecap, W.wireframeLinejoin) : D(ea)) : W.shading == THREE.SmoothShading && (ga = oa.vertexNormalsModelView[0], ha.setRGB(ga.x, ga.y, ga.z).multiplyScalar(0.5).addScalar(0.5), ga = oa.vertexNormalsModelView[1], V.setRGB(ga.x, ga.y, ga.z).multiplyScalar(0.5).addScalar(0.5), ga = oa.vertexNormalsModelView[3], $.setRGB(ga.x, ga.y, ga.z).multiplyScalar(0.5).addScalar(0.5), ga = oa.vertexNormalsModelView[2], Y.setRGB(ga.x, ga.y, ga.z).multiplyScalar(0.5).addScalar(0.5), Sa = Dc(ha, V, $, Y), z(M, U, ja, L, kb, $a), ab(M, U, ja, L, kb, $a, 0, 0, 1, 0, 0, 1, Sa), z(lb, db, ca, ta, La, Oa), ab(lb, db, ca, ta, La, Oa, 1, 0, 1, 1, 0, 1, Sa))) : W instanceof THREE.MeshDepthMaterial && (fb = n.near, jb = n.far, ha.r = ha.g = ha.b = 1 - k(ga.positionScreen.z * ga.positionScreen.w, fb, jb), V.r = V.g = V.b = 1 - k(gb.positionScreen.z * gb.positionScreen.w, fb, jb), $.r = $.g = $.b = 1 - k(G.positionScreen.z * G.positionScreen.w, fb, jb), Y.r = Y.g = Y.b = 1 - k(Ab.positionScreen.z * Ab.positionScreen.w, fb, jb), Sa = Dc(ha, V, $, Y), z(M, U, ja, L, kb, $a), ab(M, U, ja, L, kb, $a, 0, 0, 1, 0, 0, 1, Sa), z(lb, db, ca, ta, La, Oa), ab(lb, db, ca, ta, La, Oa, 1, 0, 1, 1, 0, 1, Sa))) } Qa.union(Va) } } u.setTransform(1, 0, 0, 1, 0, 0) } } }; THREE.ShaderChunk = { fog_pars_fragment: "#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif", fog_fragment: "#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n#endif", envmap_pars_fragment: "#ifdef USE_ENVMAP\nuniform float reflectivity;\nuniform samplerCube envMap;\nuniform float flipEnvMap;\nuniform int combine;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nuniform bool useRefract;\nuniform float refractionRatio;\n#else\nvarying vec3 vReflect;\n#endif\n#endif", envmap_fragment: "#ifdef USE_ENVMAP\nvec3 reflectVec;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\nif ( useRefract ) {\nreflectVec = refract( cameraToVertex, normal, refractionRatio );\n} else { \nreflectVec = reflect( cameraToVertex, normal );\n}\n#else\nreflectVec = vReflect;\n#endif\n#ifdef DOUBLE_SIDED\nfloat flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\nvec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#else\nvec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#endif\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\nif ( combine == 1 ) {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );\n} else if ( combine == 2 ) {\ngl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;\n} else {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );\n}\n#endif", envmap_pars_vertex: "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvarying vec3 vReflect;\nuniform float refractionRatio;\nuniform bool useRefract;\n#endif", worldpos_vertex: "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n#ifdef USE_SKINNING\nvec4 worldPosition = modelMatrix * skinned;\n#endif\n#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n#endif\n#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n#endif\n#endif", envmap_vertex: "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;\nworldNormal = normalize( worldNormal );\nvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\nif ( useRefract ) {\nvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n} else {\nvReflect = reflect( cameraToVertex, worldNormal );\n}\n#endif", map_particle_pars_fragment: "#ifdef USE_MAP\nuniform sampler2D map;\n#endif", map_particle_fragment: "#ifdef USE_MAP\ngl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );\n#endif", map_pars_vertex: "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )\nvarying vec2 vUv;\nuniform vec4 offsetRepeat;\n#endif", map_pars_fragment: "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )\nvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\nuniform sampler2D map;\n#endif", map_vertex: "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )\nvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif", map_fragment: "#ifdef USE_MAP\nvec4 texelColor = texture2D( map, vUv );\n#ifdef GAMMA_INPUT\ntexelColor.xyz *= texelColor.xyz;\n#endif\ngl_FragColor = gl_FragColor * texelColor;\n#endif", lightmap_pars_fragment: "#ifdef USE_LIGHTMAP\nvarying vec2 vUv2;\nuniform sampler2D lightMap;\n#endif", lightmap_pars_vertex: "#ifdef USE_LIGHTMAP\nvarying vec2 vUv2;\n#endif", lightmap_fragment: "#ifdef USE_LIGHTMAP\ngl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );\n#endif", lightmap_vertex: "#ifdef USE_LIGHTMAP\nvUv2 = uv2;\n#endif", bumpmap_pars_fragment: "#ifdef USE_BUMPMAP\nuniform sampler2D bumpMap;\nuniform float bumpScale;\nvec2 dHdxy_fwd() {\nvec2 dSTdx = dFdx( vUv );\nvec2 dSTdy = dFdy( vUv );\nfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\nfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\nfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\nreturn vec2( dBx, dBy );\n}\nvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\nvec3 vSigmaX = dFdx( surf_pos );\nvec3 vSigmaY = dFdy( surf_pos );\nvec3 vN = surf_norm;\nvec3 R1 = cross( vSigmaY, vN );\nvec3 R2 = cross( vN, vSigmaX );\nfloat fDet = dot( vSigmaX, R1 );\nvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\nreturn normalize( abs( fDet ) * surf_norm - vGrad );\n}\n#endif", normalmap_pars_fragment: "#ifdef USE_NORMALMAP\nuniform sampler2D normalMap;\nuniform vec2 normalScale;\nvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\nvec3 q0 = dFdx( eye_pos.xyz );\nvec3 q1 = dFdy( eye_pos.xyz );\nvec2 st0 = dFdx( vUv.st );\nvec2 st1 = dFdy( vUv.st );\nvec3 S = normalize( q0 * st1.t - q1 * st0.t );\nvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\nvec3 N = normalize( surf_norm );\nvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\nmapN.xy = normalScale * mapN.xy;\nmat3 tsn = mat3( S, T, N );\nreturn normalize( tsn * mapN );\n}\n#endif", specularmap_pars_fragment: "#ifdef USE_SPECULARMAP\nuniform sampler2D specularMap;\n#endif", specularmap_fragment: "float specularStrength;\n#ifdef USE_SPECULARMAP\nvec4 texelSpecular = texture2D( specularMap, vUv );\nspecularStrength = texelSpecular.r;\n#else\nspecularStrength = 1.0;\n#endif", lights_lambert_pars_vertex: "uniform vec3 ambient;\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\nuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", lights_lambert_vertex: "vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );\nif ( spotEffect > spotLightAngleCos[ i ] ) {\nspotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\nspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\nspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n#ifdef DOUBLE_SIDED\nvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_HEMI_LIGHTS > 0\nfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\nvec3 lVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, lVector );\nfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\nfloat hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;\nvLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n#ifdef DOUBLE_SIDED\nvLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );\n#endif\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n#endif", lights_phong_pars_vertex: "#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )\nvarying vec3 vWorldPosition;\n#endif", lights_phong_vertex: "#ifndef PHONG_PER_PIXEL\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nvSpotLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )\nvWorldPosition = worldPosition.xyz;\n#endif", lights_phong_pars_fragment: "uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\nuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#else\nvarying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];\n#endif\n#endif\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )\nvarying vec3 vWorldPosition;\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", lights_phong_fragment: "vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#ifdef USE_NORMALMAP\nnormal = perturbNormal2Arb( -viewPosition, normal );\n#elif defined( USE_BUMPMAP )\nnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vSpotLight[ i ].xyz );\nfloat lDistance = vSpotLight[ i ].w;\n#endif\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngleCos[ i ] ) {\nspotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n#endif\nspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\nvec3 spotHalfVector = normalize( lVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_HEMI_LIGHTS > 0\nvec3 hemiDiffuse = vec3( 0.0 );\nvec3 hemiSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\nvec3 lVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, lVector );\nfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\nvec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\nhemiDiffuse += diffuse * hemiColor;\nvec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\nfloat hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\nfloat hemiSpecularWeightSky = specularStrength * max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );\nvec3 lVectorGround = -lVector;\nvec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\nfloat hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\nfloat hemiSpecularWeightGround = specularStrength * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat dotProductGround = dot( normal, lVectorGround );\nfloat specularNormalization = ( shininess + 2.0001 ) / 8.0;\nvec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );\nvec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );\nhemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n#else\nhemiSpecular += specular * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_HEMI_LIGHTS > 0\ntotalDiffuse += hemiDiffuse;\ntotalSpecular += hemiSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", color_pars_fragment: "#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif", color_fragment: "#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif", color_pars_vertex: "#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif", color_vertex: "#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif", skinning_pars_vertex: "#ifdef USE_SKINNING\n#ifdef BONE_TEXTURE\nuniform sampler2D boneTexture;\nmat4 getBoneMatrix( const in float i ) {\nfloat j = i * 4.0;\nfloat x = mod( j, N_BONE_PIXEL_X );\nfloat y = floor( j / N_BONE_PIXEL_X );\nconst float dx = 1.0 / N_BONE_PIXEL_X;\nconst float dy = 1.0 / N_BONE_PIXEL_Y;\ny = dy * ( y + 0.5 );\nvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\nvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\nvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\nvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\nmat4 bone = mat4( v1, v2, v3, v4 );\nreturn bone;\n}\n#else\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\nmat4 getBoneMatrix( const in float i ) {\nmat4 bone = boneGlobalMatrices[ int(i) ];\nreturn bone;\n}\n#endif\n#endif", skinbase_vertex: "#ifdef USE_SKINNING\nmat4 boneMatX = getBoneMatrix( skinIndex.x );\nmat4 boneMatY = getBoneMatrix( skinIndex.y );\n#endif", skinning_vertex: "#ifdef USE_SKINNING\n#ifdef USE_MORPHTARGETS\nvec4 skinVertex = vec4( morphed, 1.0 );\n#else\nvec4 skinVertex = vec4( position, 1.0 );\n#endif\nvec4 skinned = boneMatX * skinVertex * skinWeight.x;\nskinned \t += boneMatY * skinVertex * skinWeight.y;\n#endif", morphtarget_pars_vertex: "#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif", morphtarget_vertex: "#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\n#endif", default_vertex: "vec4 mvPosition;\n#ifdef USE_SKINNING\nmvPosition = modelViewMatrix * skinned;\n#endif\n#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )\nmvPosition = modelViewMatrix * vec4( morphed, 1.0 );\n#endif\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )\nmvPosition = modelViewMatrix * vec4( position, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;", morphnormal_vertex: "#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\n#endif", skinnormal_vertex: "#ifdef USE_SKINNING\nmat4 skinMatrix = skinWeight.x * boneMatX;\nskinMatrix \t+= skinWeight.y * boneMatY;\n#ifdef USE_MORPHNORMALS\nvec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );\n#else\nvec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );\n#endif\n#endif", defaultnormal_vertex: "vec3 objectNormal;\n#ifdef USE_SKINNING\nobjectNormal = skinnedNormal.xyz;\n#endif\n#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )\nobjectNormal = morphedNormal;\n#endif\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )\nobjectNormal = normal;\n#endif\n#ifdef FLIP_SIDED\nobjectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;", shadowmap_pars_fragment: "#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif", shadowmap_fragment: "#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#if defined( SHADOWMAP_TYPE_PCF )\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\nfloat shadow = 0.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.0 * xPixelOffset;\nfloat dy0 = -1.0 * yPixelOffset;\nfloat dx1 = 1.0 * xPixelOffset;\nfloat dy1 = 1.0 * yPixelOffset;\nmat3 shadowKernel;\nmat3 depthKernel;\ndepthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( depthKernel[0][0] < shadowCoord.z ) shadowKernel[0][0] = 0.25;\nelse shadowKernel[0][0] = 0.0;\ndepthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( depthKernel[0][1] < shadowCoord.z ) shadowKernel[0][1] = 0.25;\nelse shadowKernel[0][1] = 0.0;\ndepthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( depthKernel[0][2] < shadowCoord.z ) shadowKernel[0][2] = 0.25;\nelse shadowKernel[0][2] = 0.0;\ndepthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( depthKernel[1][0] < shadowCoord.z ) shadowKernel[1][0] = 0.25;\nelse shadowKernel[1][0] = 0.0;\ndepthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( depthKernel[1][1] < shadowCoord.z ) shadowKernel[1][1] = 0.25;\nelse shadowKernel[1][1] = 0.0;\ndepthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( depthKernel[1][2] < shadowCoord.z ) shadowKernel[1][2] = 0.25;\nelse shadowKernel[1][2] = 0.0;\ndepthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( depthKernel[2][0] < shadowCoord.z ) shadowKernel[2][0] = 0.25;\nelse shadowKernel[2][0] = 0.0;\ndepthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( depthKernel[2][1] < shadowCoord.z ) shadowKernel[2][1] = 0.25;\nelse shadowKernel[2][1] = 0.0;\ndepthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( depthKernel[2][2] < shadowCoord.z ) shadowKernel[2][2] = 0.25;\nelse shadowKernel[2][2] = 0.0;\nvec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );\nshadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );\nshadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );\nvec4 shadowValues;\nshadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );\nshadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );\nshadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );\nshadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );\nshadow = dot( shadowValues, vec4( 1.0 ) );\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", shadowmap_pars_vertex: "#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif", shadowmap_vertex: "#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n}\n#endif", alphatest_fragment: "#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", linear_to_gamma_fragment: "#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif" }; THREE.UniformsUtils = { merge: function (a) { var b, c, d, e = {}; for (b = 0; b < a.length; b++) for (c in d = this.clone(a[b]), d) e[c] = d[c]; return e }, clone: function (a) { var b, c, d, e = {}; for (b in a) for (c in e[b] = {}, a[b]) d = a[b][c], e[b][c] = d instanceof THREE.Color || d instanceof THREE.Vector2 || d instanceof THREE.Vector3 || d instanceof THREE.Vector4 || d instanceof THREE.Matrix4 || d instanceof THREE.Texture ? d.clone() : d instanceof Array ? d.slice() : d; return e } }; THREE.UniformsLib = { common: { diffuse: {type: "c", value: new THREE.Color(15658734)}, opacity: {type: "f", value: 1}, map: {type: "t", value: null}, offsetRepeat: {type: "v4", value: new THREE.Vector4(0, 0, 1, 1)}, lightMap: {type: "t", value: null}, specularMap: {type: "t", value: null}, envMap: {type: "t", value: null}, flipEnvMap: {type: "f", value: -1}, useRefract: {type: "i", value: 0}, reflectivity: {type: "f", value: 1}, refractionRatio: {type: "f", value: 0.98}, combine: {type: "i", value: 0}, morphTargetInfluences: {type: "f", value: 0} }, bump: { bumpMap: { type: "t", value: null }, bumpScale: {type: "f", value: 1} }, normalmap: {normalMap: {type: "t", value: null}, normalScale: {type: "v2", value: new THREE.Vector2(1, 1)}}, fog: { fogDensity: {type: "f", value: 2.5E-4}, fogNear: {type: "f", value: 1}, fogFar: {type: "f", value: 2E3}, fogColor: {type: "c", value: new THREE.Color(16777215)} }, lights: { ambientLightColor: {type: "fv", value: []}, directionalLightDirection: {type: "fv", value: []}, directionalLightColor: {type: "fv", value: []}, hemisphereLightDirection: {type: "fv", value: []}, hemisphereLightSkyColor: { type: "fv", value: [] }, hemisphereLightGroundColor: {type: "fv", value: []}, pointLightColor: {type: "fv", value: []}, pointLightPosition: {type: "fv", value: []}, pointLightDistance: {type: "fv1", value: []}, spotLightColor: {type: "fv", value: []}, spotLightPosition: {type: "fv", value: []}, spotLightDirection: {type: "fv", value: []}, spotLightDistance: {type: "fv1", value: []}, spotLightAngleCos: {type: "fv1", value: []}, spotLightExponent: {type: "fv1", value: []} }, particle: { psColor: {type: "c", value: new THREE.Color(15658734)}, opacity: {type: "f", value: 1}, size: { type: "f", value: 1 }, scale: {type: "f", value: 1}, map: {type: "t", value: null}, fogDensity: {type: "f", value: 2.5E-4}, fogNear: {type: "f", value: 1}, fogFar: {type: "f", value: 2E3}, fogColor: {type: "c", value: new THREE.Color(16777215)} }, shadowmap: { shadowMap: {type: "tv", value: []}, shadowMapSize: {type: "v2v", value: []}, shadowBias: {type: "fv1", value: []}, shadowDarkness: {type: "fv1", value: []}, shadowMatrix: {type: "m4v", value: []} } }; THREE.ShaderLib = { basic: { uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib.common, THREE.UniformsLib.fog, THREE.UniformsLib.shadowmap]), vertexShader: [THREE.ShaderChunk.map_pars_vertex, THREE.ShaderChunk.lightmap_pars_vertex, THREE.ShaderChunk.envmap_pars_vertex, THREE.ShaderChunk.color_pars_vertex, THREE.ShaderChunk.morphtarget_pars_vertex, THREE.ShaderChunk.skinning_pars_vertex, THREE.ShaderChunk.shadowmap_pars_vertex, "void main() {", THREE.ShaderChunk.map_vertex, THREE.ShaderChunk.lightmap_vertex, THREE.ShaderChunk.color_vertex, THREE.ShaderChunk.skinbase_vertex, "#ifdef USE_ENVMAP", THREE.ShaderChunk.morphnormal_vertex, THREE.ShaderChunk.skinnormal_vertex, THREE.ShaderChunk.defaultnormal_vertex, "#endif", THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.default_vertex, THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.envmap_vertex, THREE.ShaderChunk.shadowmap_vertex, "}"].join("\n"), fragmentShader: ["uniform vec3 diffuse;\nuniform float opacity;", THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, "void main() {\ngl_FragColor = vec4( diffuse, opacity );", THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, THREE.ShaderChunk.lightmap_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.envmap_fragment, THREE.ShaderChunk.shadowmap_fragment, THREE.ShaderChunk.linear_to_gamma_fragment, THREE.ShaderChunk.fog_fragment, "}"].join("\n") }, lambert: { uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib.common, THREE.UniformsLib.fog, THREE.UniformsLib.lights, THREE.UniformsLib.shadowmap, { ambient: { type: "c", value: new THREE.Color(16777215) }, emissive: {type: "c", value: new THREE.Color(0)}, wrapRGB: {type: "v3", value: new THREE.Vector3(1, 1, 1)} }]), vertexShader: ["#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\nvarying vec3 vLightBack;\n#endif", THREE.ShaderChunk.map_pars_vertex, THREE.ShaderChunk.lightmap_pars_vertex, THREE.ShaderChunk.envmap_pars_vertex, THREE.ShaderChunk.lights_lambert_pars_vertex, THREE.ShaderChunk.color_pars_vertex, THREE.ShaderChunk.morphtarget_pars_vertex, THREE.ShaderChunk.skinning_pars_vertex, THREE.ShaderChunk.shadowmap_pars_vertex, "void main() {", THREE.ShaderChunk.map_vertex, THREE.ShaderChunk.lightmap_vertex, THREE.ShaderChunk.color_vertex, THREE.ShaderChunk.morphnormal_vertex, THREE.ShaderChunk.skinbase_vertex, THREE.ShaderChunk.skinnormal_vertex, THREE.ShaderChunk.defaultnormal_vertex, THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.default_vertex, THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.envmap_vertex, THREE.ShaderChunk.lights_lambert_vertex, THREE.ShaderChunk.shadowmap_vertex, "}"].join("\n"), fragmentShader: ["uniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\nvarying vec3 vLightBack;\n#endif", THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, "void main() {\ngl_FragColor = vec4( vec3 ( 1.0 ), opacity );", THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, "#ifdef DOUBLE_SIDED\nif ( gl_FrontFacing )\ngl_FragColor.xyz *= vLightFront;\nelse\ngl_FragColor.xyz *= vLightBack;\n#else\ngl_FragColor.xyz *= vLightFront;\n#endif", THREE.ShaderChunk.lightmap_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.envmap_fragment, THREE.ShaderChunk.shadowmap_fragment, THREE.ShaderChunk.linear_to_gamma_fragment, THREE.ShaderChunk.fog_fragment, "}"].join("\n") }, phong: { uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib.common, THREE.UniformsLib.bump, THREE.UniformsLib.normalmap, THREE.UniformsLib.fog, THREE.UniformsLib.lights, THREE.UniformsLib.shadowmap, { ambient: {type: "c", value: new THREE.Color(16777215)}, emissive: {type: "c", value: new THREE.Color(0)}, specular: { type: "c", value: new THREE.Color(1118481) }, shininess: {type: "f", value: 30}, wrapRGB: {type: "v3", value: new THREE.Vector3(1, 1, 1)} }]), vertexShader: ["#define PHONG\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", THREE.ShaderChunk.map_pars_vertex, THREE.ShaderChunk.lightmap_pars_vertex, THREE.ShaderChunk.envmap_pars_vertex, THREE.ShaderChunk.lights_phong_pars_vertex, THREE.ShaderChunk.color_pars_vertex, THREE.ShaderChunk.morphtarget_pars_vertex, THREE.ShaderChunk.skinning_pars_vertex, THREE.ShaderChunk.shadowmap_pars_vertex, "void main() {", THREE.ShaderChunk.map_vertex, THREE.ShaderChunk.lightmap_vertex, THREE.ShaderChunk.color_vertex, THREE.ShaderChunk.morphnormal_vertex, THREE.ShaderChunk.skinbase_vertex, THREE.ShaderChunk.skinnormal_vertex, THREE.ShaderChunk.defaultnormal_vertex, "vNormal = normalize( transformedNormal );", THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.default_vertex, "vViewPosition = -mvPosition.xyz;", THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.envmap_vertex, THREE.ShaderChunk.lights_phong_vertex, THREE.ShaderChunk.shadowmap_vertex, "}"].join("\n"), fragmentShader: ["uniform vec3 diffuse;\nuniform float opacity;\nuniform vec3 ambient;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;", THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.lights_phong_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.bumpmap_pars_fragment, THREE.ShaderChunk.normalmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, "void main() {\ngl_FragColor = vec4( vec3 ( 1.0 ), opacity );", THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, THREE.ShaderChunk.lights_phong_fragment, THREE.ShaderChunk.lightmap_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.envmap_fragment, THREE.ShaderChunk.shadowmap_fragment, THREE.ShaderChunk.linear_to_gamma_fragment, THREE.ShaderChunk.fog_fragment, "}"].join("\n") }, particle_basic: { uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib.particle, THREE.UniformsLib.shadowmap]), vertexShader: ["uniform float size;\nuniform float scale;", THREE.ShaderChunk.color_pars_vertex, THREE.ShaderChunk.shadowmap_pars_vertex, "void main() {", THREE.ShaderChunk.color_vertex, "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n#ifdef USE_SIZEATTENUATION\ngl_PointSize = size * ( scale / length( mvPosition.xyz ) );\n#else\ngl_PointSize = size;\n#endif\ngl_Position = projectionMatrix * mvPosition;", THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.shadowmap_vertex, "}"].join("\n"), fragmentShader: ["uniform vec3 psColor;\nuniform float opacity;", THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.map_particle_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, "void main() {\ngl_FragColor = vec4( psColor, opacity );", THREE.ShaderChunk.map_particle_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.shadowmap_fragment, THREE.ShaderChunk.fog_fragment, "}"].join("\n") }, dashed: { uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib.common, THREE.UniformsLib.fog, { scale: { type: "f", value: 1 }, dashSize: {type: "f", value: 1}, totalSize: {type: "f", value: 2} }]), vertexShader: ["uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;", THREE.ShaderChunk.color_pars_vertex, "void main() {", THREE.ShaderChunk.color_vertex, "vLineDistance = scale * lineDistance;\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n}"].join("\n"), fragmentShader: ["uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;", THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, "void main() {\nif ( mod( vLineDistance, totalSize ) > dashSize ) {\ndiscard;\n}\ngl_FragColor = vec4( diffuse, opacity );", THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.fog_fragment, "}"].join("\n") }, depth: { uniforms: { mNear: {type: "f", value: 1}, mFar: {type: "f", value: 2E3}, opacity: { type: "f", value: 1 } }, vertexShader: "void main() {\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}", fragmentShader: "uniform float mNear;\nuniform float mFar;\nuniform float opacity;\nvoid main() {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat color = 1.0 - smoothstep( mNear, mFar, depth );\ngl_FragColor = vec4( vec3( color ), opacity );\n}" }, normal: { uniforms: {opacity: {type: "f", value: 1}}, vertexShader: "varying vec3 vNormal;\nvoid main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalize( normalMatrix * normal );\ngl_Position = projectionMatrix * mvPosition;\n}", fragmentShader: "uniform float opacity;\nvarying vec3 vNormal;\nvoid main() {\ngl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );\n}" }, normalmap: { uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib.fog, THREE.UniformsLib.lights, THREE.UniformsLib.shadowmap, { enableAO: {type: "i", value: 0}, enableDiffuse: {type: "i", value: 0}, enableSpecular: {type: "i", value: 0}, enableReflection: {type: "i", value: 0}, enableDisplacement: {type: "i", value: 0}, tDisplacement: {type: "t", value: null}, tDiffuse: {type: "t", value: null}, tCube: {type: "t", value: null}, tNormal: {type: "t", value: null}, tSpecular: {type: "t", value: null}, tAO: {type: "t", value: null}, uNormalScale: {type: "v2", value: new THREE.Vector2(1, 1)}, uDisplacementBias: {type: "f", value: 0}, uDisplacementScale: {type: "f", value: 1}, uDiffuseColor: {type: "c", value: new THREE.Color(16777215)}, uSpecularColor: {type: "c", value: new THREE.Color(1118481)}, uAmbientColor: {type: "c", value: new THREE.Color(16777215)}, uShininess: {type: "f", value: 30}, uOpacity: {type: "f", value: 1}, useRefract: {type: "i", value: 0}, uRefractionRatio: {type: "f", value: 0.98}, uReflectivity: {type: "f", value: 0.5}, uOffset: {type: "v2", value: new THREE.Vector2(0, 0)}, uRepeat: {type: "v2", value: new THREE.Vector2(1, 1)}, wrapRGB: {type: "v3", value: new THREE.Vector3(1, 1, 1)} }]), fragmentShader: ["uniform vec3 uAmbientColor;\nuniform vec3 uDiffuseColor;\nuniform vec3 uSpecularColor;\nuniform float uShininess;\nuniform float uOpacity;\nuniform bool enableDiffuse;\nuniform bool enableSpecular;\nuniform bool enableAO;\nuniform bool enableReflection;\nuniform sampler2D tDiffuse;\nuniform sampler2D tNormal;\nuniform sampler2D tSpecular;\nuniform sampler2D tAO;\nuniform samplerCube tCube;\nuniform vec2 uNormalScale;\nuniform bool useRefract;\nuniform float uRefractionRatio;\nuniform float uReflectivity;\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\nuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\nuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\nuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\nuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\nuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\nuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\nuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;", THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, "void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\n#ifdef FLIP_SIDED\nfinalNormal = -finalNormal;\n#endif\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 pointVector = lPosition.xyz + vViewPosition.xyz;\nfloat pointDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\npointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );\npointVector = normalize( pointVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n#else\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_SPOT_LIGHTS > 0\nvec3 spotDiffuse = vec3( 0.0 );\nvec3 spotSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\nvec3 spotVector = lPosition.xyz + vViewPosition.xyz;\nfloat spotDistance = 1.0;\nif ( spotLightDistance[ i ] > 0.0 )\nspotDistance = 1.0 - min( ( length( spotVector ) / spotLightDistance[ i ] ), 1.0 );\nspotVector = normalize( spotVector );\nfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\nif ( spotEffect > spotLightAngleCos[ i ] ) {\nspotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );\n#ifdef WRAP_AROUND\nfloat spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );\nfloat spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );\nvec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n#else\nfloat spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );\n#endif\nspotDiffuse += spotDistance * spotLightColor[ i ] * uDiffuseColor * spotDiffuseWeight * spotEffect;\nvec3 spotHalfVector = normalize( spotVector + viewPosition );\nfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\nfloat spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( spotVector, spotHalfVector ), 5.0 );\nspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;\n#else\nspotSpecular += spotDistance * spotLightColor[ i ] * uSpecularColor * spotSpecularWeight * spotDiffuseWeight * spotEffect;\n#endif\n}\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n#else\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\n#if MAX_HEMI_LIGHTS > 0\nvec3 hemiDiffuse = vec3( 0.0 );\nvec3 hemiSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\nvec3 lVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, lVector );\nfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\nvec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\nhemiDiffuse += uDiffuseColor * hemiColor;\nvec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\nfloat hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\nfloat hemiSpecularWeightSky = specularTex.r * max( pow( hemiDotNormalHalfSky, uShininess ), 0.0 );\nvec3 lVectorGround = -lVector;\nvec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\nfloat hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\nfloat hemiSpecularWeightGround = specularTex.r * max( pow( hemiDotNormalHalfGround, uShininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nfloat dotProductGround = dot( normal, lVectorGround );\nfloat specularNormalization = ( uShininess + 2.0001 ) / 8.0;\nvec3 schlickSky = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );\nvec3 schlickGround = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );\nhemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n#else\nhemiSpecular += uSpecularColor * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_HEMI_LIGHTS > 0\ntotalDiffuse += hemiDiffuse;\ntotalSpecular += hemiSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#if MAX_SPOT_LIGHTS > 0\ntotalDiffuse += spotDiffuse;\ntotalSpecular += spotSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor ) + totalSpecular;\n#endif\nif ( enableReflection ) {\nvec3 vReflect;\nvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\nif ( useRefract ) {\nvReflect = refract( cameraToVertex, normal, uRefractionRatio );\n} else {\nvReflect = reflect( cameraToVertex, normal );\n}\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", THREE.ShaderChunk.shadowmap_fragment, THREE.ShaderChunk.linear_to_gamma_fragment, THREE.ShaderChunk.fog_fragment, "}"].join("\n"), vertexShader: ["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\nuniform bool enableDisplacement;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;", THREE.ShaderChunk.skinning_pars_vertex, THREE.ShaderChunk.shadowmap_pars_vertex, "void main() {", THREE.ShaderChunk.skinbase_vertex, THREE.ShaderChunk.skinnormal_vertex, "#ifdef USE_SKINNING\nvNormal = normalize( normalMatrix * skinnedNormal.xyz );\nvec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );\nvTangent = normalize( normalMatrix * skinnedTangent.xyz );\n#else\nvNormal = normalize( normalMatrix * normal );\nvTangent = normalize( normalMatrix * tangent.xyz );\n#endif\nvBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );\nvUv = uv * uRepeat + uOffset;\nvec3 displacedPosition;\n#ifdef VERTEX_TEXTURES\nif ( enableDisplacement ) {\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\ndisplacedPosition = position + normalize( normal ) * df;\n} else {\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned = boneMatX * skinVertex * skinWeight.x;\nskinned \t += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n}\n#else\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned = boneMatX * skinVertex * skinWeight.x;\nskinned \t += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n#endif\nvec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );\nvec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\nvWorldPosition = worldPosition.xyz;\nvViewPosition = -mvPosition.xyz;\n#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n}\n#endif\n}"].join("\n") }, cube: { uniforms: {tCube: {type: "t", value: null}, tFlip: {type: "f", value: -1}}, vertexShader: "varying vec3 vWorldPosition;\nvoid main() {\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\nvWorldPosition = worldPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}", fragmentShader: "uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\nvoid main() {\ngl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n}" }, depthRGBA: { uniforms: {}, vertexShader: [THREE.ShaderChunk.morphtarget_pars_vertex, THREE.ShaderChunk.skinning_pars_vertex, "void main() {", THREE.ShaderChunk.skinbase_vertex, THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.default_vertex, "}"].join("\n"), fragmentShader: "vec4 pack_depth( const in float depth ) {\nconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\nconst vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\nvec4 res = fract( depth * bit_shift );\nres -= res.xxyz * bit_mask;\nreturn res;\n}\nvoid main() {\ngl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n}" } }; THREE.WebGLRenderer = function (a) { function b(a) { if (a.__webglCustomAttributesList) for (var b in a.__webglCustomAttributesList) j.deleteBuffer(a.__webglCustomAttributesList[b].buffer) } function c(a, b) { var c = a.vertices.length, d = b.material; if (d.attributes) { void 0 === a.__webglCustomAttributesList && (a.__webglCustomAttributesList = []); for (var e in d.attributes) { var f = d.attributes[e]; if (!f.__webglInitialized || f.createUniqueBuffers) { f.__webglInitialized = !0; var g = 1; "v2" === f.type ? g = 2 : "v3" === f.type ? g = 3 : "v4" === f.type ? g = 4 : "c" === f.type && (g = 3); f.size = g; f.array = new Float32Array(c * g); f.buffer = j.createBuffer(); f.buffer.belongsToAttribute = e; f.needsUpdate = !0 } a.__webglCustomAttributesList.push(f) } } } function d(a, b) { var c = b.geometry, d = a.faces3, h = a.faces4, i = 3 * d.length + 4 * h.length, k = 1 * d.length + 2 * h.length, h = 3 * d.length + 4 * h.length, d = e(b, a), m = g(d), l = f(d), p = d.vertexColors ? d.vertexColors : !1; a.__vertexArray = new Float32Array(3 * i); l && (a.__normalArray = new Float32Array(3 * i)); c.hasTangents && (a.__tangentArray = new Float32Array(4 * i)); p && (a.__colorArray = new Float32Array(3 * i)); if (m) { if (0 < c.faceUvs.length || 0 < c.faceVertexUvs.length) a.__uvArray = new Float32Array(2 * i); if (1 < c.faceUvs.length || 1 < c.faceVertexUvs.length) a.__uv2Array = new Float32Array(2 * i) } b.geometry.skinWeights.length && b.geometry.skinIndices.length && (a.__skinIndexArray = new Float32Array(4 * i), a.__skinWeightArray = new Float32Array(4 * i)); a.__faceArray = new Uint16Array(3 * k); a.__lineArray = new Uint16Array(2 * h); if (a.numMorphTargets) { a.__morphTargetsArrays = []; c = 0; for (m = a.numMorphTargets; c < m; c++) a.__morphTargetsArrays.push(new Float32Array(3 * i)) } if (a.numMorphNormals) { a.__morphNormalsArrays = []; c = 0; for (m = a.numMorphNormals; c < m; c++) a.__morphNormalsArrays.push(new Float32Array(3 * i)) } a.__webglFaceCount = 3 * k; a.__webglLineCount = 2 * h; if (d.attributes) { void 0 === a.__webglCustomAttributesList && (a.__webglCustomAttributesList = []); for (var n in d.attributes) { var k = d.attributes[n], c = {}, q; for (q in k) c[q] = k[q]; if (!c.__webglInitialized || c.createUniqueBuffers) c.__webglInitialized = !0, h = 1, "v2" === c.type ? h = 2 : "v3" === c.type ? h = 3 : "v4" === c.type ? h = 4 : "c" === c.type && (h = 3), c.size = h, c.array = new Float32Array(i * h), c.buffer = j.createBuffer(), c.buffer.belongsToAttribute = n, k.needsUpdate = !0, c.__original = k; a.__webglCustomAttributesList.push(c) } } a.__inittedArrays = !0 } function e(a, b) { return a.material instanceof THREE.MeshFaceMaterial ? a.material.materials[b.materialIndex] : a.material } function f(a) { return a instanceof THREE.MeshBasicMaterial && !a.envMap || a instanceof THREE.MeshDepthMaterial ? !1 : a && void 0 !== a.shading && a.shading === THREE.SmoothShading ? THREE.SmoothShading : THREE.FlatShading } function g(a) { return a.map || a.lightMap || a.bumpMap || a.normalMap || a.specularMap || a instanceof THREE.ShaderMaterial ? !0 : !1 } function h(a) { xb[a] || (j.enableVertexAttribArray(a), xb[a] = !0) } function i() { for (var a in xb) xb[a] && (j.disableVertexAttribArray(a), xb[a] = !1) } function k(a, b) { return a.z !== b.z ? b.z - a.z : b.id - a.id } function l(a, b) { return b[0] - a[0] } function m(a, b, c) { if (a.length) for (var d = 0, e = a.length; d < e; d++) La = kb = null, lb = db = V = ha = Pa = na = $ = -1, yb = !0, a[d].render(b, c, Nb, Ob), La = kb = null, lb = db = V = ha = Pa = na = $ = -1, yb = !0 } function p(a, b, c, d, e, f, g, h) { var j, i, k, m; b ? (i = a.length - 1, m = b = -1) : (i = 0, b = a.length, m = 1); for (var l = i; l !== b; l += m) if (j = a[l], j.render) { i = j.object; k = j.buffer; if (h) j = h; else { j = j[c]; if (!j) continue; g && L.setBlending(j.blending, j.blendEquation, j.blendSrc, j.blendDst); L.setDepthTest(j.depthTest); L.setDepthWrite(j.depthWrite); I(j.polygonOffset, j.polygonOffsetFactor, j.polygonOffsetUnits) } L.setMaterialFaces(j); k instanceof THREE.BufferGeometry ? L.renderBufferDirect(d, e, f, j, k, i) : L.renderBuffer(d, e, f, j, k, i) } } function s(a, b, c, d, e, f, g) { for (var h, j, i = 0, k = a.length; i < k; i++) if (h = a[i], j = h.object, j.visible) { if (g) h = g; else { h = h[b]; if (!h) continue; f && L.setBlending(h.blending, h.blendEquation, h.blendSrc, h.blendDst); L.setDepthTest(h.depthTest); L.setDepthWrite(h.depthWrite); I(h.polygonOffset, h.polygonOffsetFactor, h.polygonOffsetUnits) } L.renderImmediateObject(c, d, e, h, j) } } function r(a, b, c) { a.push({buffer: b, object: c, opaque: null, transparent: null}) } function n(a) { for (var b in a.attributes) if (a.attributes[b].needsUpdate) return !0; return !1 } function q(a) { for (var b in a.attributes) a.attributes[b].needsUpdate = !1 } function z(a, b) { for (var c = a.length - 1; 0 <= c; c--) a[c].object === b && a.splice(c, 1) } function t(a, b) { for (var c = a.length - 1; 0 <= c; c--) a[c] === b && a.splice(c, 1) } function x(a, b, c, d, e) { ea = 0; d.needsUpdate && (d.program && Yc(d), L.initMaterial(d, b, c, e), d.needsUpdate = !1); d.morphTargets && !e.__webglMorphTargetInfluences && (e.__webglMorphTargetInfluences = new Float32Array(L.maxMorphTargets)); var f = !1, g = d.program, h = g.uniforms, i = d.uniforms; g !== kb && (j.useProgram(g), kb = g, f = !0); d.id !== lb && (lb = d.id, f = !0); if (f || a !== La) j.uniformMatrix4fv(h.projectionMatrix, !1, a.projectionMatrix.elements), a !== La && (La = a); if (d.skinning) if (Cc && e.useVertexTexture) { if (null !== h.boneTexture) { var k = u(); j.uniform1i(h.boneTexture, k); L.setTexture(e.boneTexture, k) } } else null !== h.boneGlobalMatrices && j.uniformMatrix4fv(h.boneGlobalMatrices, !1, e.boneMatrices); if (f) { c && d.fog && (i.fogColor.value = c.color, c instanceof THREE.Fog ? (i.fogNear.value = c.near, i.fogFar.value = c.far) : c instanceof THREE.FogExp2 && (i.fogDensity.value = c.density)); if (d instanceof THREE.MeshPhongMaterial || d instanceof THREE.MeshLambertMaterial || d.lights) { if (yb) { for (var m, l = k = 0, p = 0, n, q, s, r = pb, t = r.directional.colors, x = r.directional.positions, w = r.point.colors, z = r.point.positions, A = r.point.distances, B = r.spot.colors, E = r.spot.positions, I = r.spot.distances, J = r.spot.directions, K = r.spot.anglesCos, M = r.spot.exponents, V = r.hemi.skyColors, N = r.hemi.groundColors, S = r.hemi.positions, ta = 0, U = 0, $ = 0, ha = 0, fa = 0, Oa = 0, ia = 0, $a = 0, ca = m = 0, c = s = ca = 0, f = b.length; c < f; c++) m = b[c], m.onlyShadow || (n = m.color, q = m.intensity, s = m.distance, m instanceof THREE.AmbientLight ? m.visible && (L.gammaInput ? (k += n.r * n.r, l += n.g * n.g, p += n.b * n.b) : (k += n.r, l += n.g, p += n.b)) : m instanceof THREE.DirectionalLight ? (fa += 1, m.visible && (xa.getPositionFromMatrix(m.matrixWorld), wa.getPositionFromMatrix(m.target.matrixWorld), xa.sub(wa), xa.normalize(), 0 === xa.x && 0 === xa.y && 0 === xa.z || (m = 3 * ta, x[m] = xa.x, x[m + 1] = xa.y, x[m + 2] = xa.z, L.gammaInput ? G(t, m, n, q * q) : D(t, m, n, q), ta += 1))) : m instanceof THREE.PointLight ? (Oa += 1, m.visible && (ca = 3 * U, L.gammaInput ? G(w, ca, n, q * q) : D(w, ca, n, q), wa.getPositionFromMatrix(m.matrixWorld), z[ca] = wa.x, z[ca + 1] = wa.y, z[ca + 2] = wa.z, A[U] = s, U += 1)) : m instanceof THREE.SpotLight ? (ia += 1, m.visible && (ca = 3 * $, L.gammaInput ? G(B, ca, n, q * q) : D(B, ca, n, q), wa.getPositionFromMatrix(m.matrixWorld), E[ca] = wa.x, E[ca + 1] = wa.y, E[ca + 2] = wa.z, I[$] = s, xa.copy(wa), wa.getPositionFromMatrix(m.target.matrixWorld), xa.sub(wa), xa.normalize(), J[ca] = xa.x, J[ca + 1] = xa.y, J[ca + 2] = xa.z, K[$] = Math.cos(m.angle), M[$] = m.exponent, $ += 1)) : m instanceof THREE.HemisphereLight && ($a += 1, m.visible && (xa.getPositionFromMatrix(m.matrixWorld), xa.normalize(), 0 === xa.x && 0 === xa.y && 0 === xa.z || (s = 3 * ha, S[s] = xa.x, S[s + 1] = xa.y, S[s + 2] = xa.z, n = m.color, m = m.groundColor, L.gammaInput ? (q *= q, G(V, s, n, q), G(N, s, m, q)) : (D(V, s, n, q), D(N, s, m, q)), ha += 1)))); c = 3 * ta; for (f = Math.max(t.length, 3 * fa); c < f; c++) t[c] = 0; c = 3 * U; for (f = Math.max(w.length, 3 * Oa); c < f; c++) w[c] = 0; c = 3 * $; for (f = Math.max(B.length, 3 * ia); c < f; c++) B[c] = 0; c = 3 * ha; for (f = Math.max(V.length, 3 * $a); c < f; c++) V[c] = 0; c = 3 * ha; for (f = Math.max(N.length, 3 * $a); c < f; c++) N[c] = 0; r.directional.length = ta; r.point.length = U; r.spot.length = $; r.hemi.length = ha; r.ambient[0] = k; r.ambient[1] = l; r.ambient[2] = p; yb = !1 } c = pb; i.ambientLightColor.value = c.ambient; i.directionalLightColor.value = c.directional.colors; i.directionalLightDirection.value = c.directional.positions; i.pointLightColor.value = c.point.colors; i.pointLightPosition.value = c.point.positions; i.pointLightDistance.value = c.point.distances; i.spotLightColor.value = c.spot.colors; i.spotLightPosition.value = c.spot.positions; i.spotLightDistance.value = c.spot.distances; i.spotLightDirection.value = c.spot.directions; i.spotLightAngleCos.value = c.spot.anglesCos; i.spotLightExponent.value = c.spot.exponents; i.hemisphereLightSkyColor.value = c.hemi.skyColors; i.hemisphereLightGroundColor.value = c.hemi.groundColors; i.hemisphereLightDirection.value = c.hemi.positions } if (d instanceof THREE.MeshBasicMaterial || d instanceof THREE.MeshLambertMaterial || d instanceof THREE.MeshPhongMaterial) { i.opacity.value = d.opacity; L.gammaInput ? i.diffuse.value.copyGammaToLinear(d.color) : i.diffuse.value = d.color; i.map.value = d.map; i.lightMap.value = d.lightMap; i.specularMap.value = d.specularMap; d.bumpMap && (i.bumpMap.value = d.bumpMap, i.bumpScale.value = d.bumpScale); d.normalMap && (i.normalMap.value = d.normalMap, i.normalScale.value.copy(d.normalScale)); var Y; d.map ? Y = d.map : d.specularMap ? Y = d.specularMap : d.normalMap ? Y = d.normalMap : d.bumpMap && (Y = d.bumpMap); void 0 !== Y && (c = Y.offset, Y = Y.repeat, i.offsetRepeat.value.set(c.x, c.y, Y.x, Y.y)); i.envMap.value = d.envMap; i.flipEnvMap.value = d.envMap instanceof THREE.WebGLRenderTargetCube ? 1 : -1; i.reflectivity.value = d.reflectivity; i.refractionRatio.value = d.refractionRatio; i.combine.value = d.combine; i.useRefract.value = d.envMap && d.envMap.mapping instanceof THREE.CubeRefractionMapping } d instanceof THREE.LineBasicMaterial ? (i.diffuse.value = d.color, i.opacity.value = d.opacity) : d instanceof THREE.LineDashedMaterial ? (i.diffuse.value = d.color, i.opacity.value = d.opacity, i.dashSize.value = d.dashSize, i.totalSize.value = d.dashSize + d.gapSize, i.scale.value = d.scale) : d instanceof THREE.ParticleBasicMaterial ? (i.psColor.value = d.color, i.opacity.value = d.opacity, i.size.value = d.size, i.scale.value = H.height / 2, i.map.value = d.map) : d instanceof THREE.MeshPhongMaterial ? (i.shininess.value = d.shininess, L.gammaInput ? (i.ambient.value.copyGammaToLinear(d.ambient), i.emissive.value.copyGammaToLinear(d.emissive), i.specular.value.copyGammaToLinear(d.specular)) : (i.ambient.value = d.ambient, i.emissive.value = d.emissive, i.specular.value = d.specular), d.wrapAround && i.wrapRGB.value.copy(d.wrapRGB)) : d instanceof THREE.MeshLambertMaterial ? (L.gammaInput ? (i.ambient.value.copyGammaToLinear(d.ambient), i.emissive.value.copyGammaToLinear(d.emissive)) : (i.ambient.value = d.ambient, i.emissive.value = d.emissive), d.wrapAround && i.wrapRGB.value.copy(d.wrapRGB)) : d instanceof THREE.MeshDepthMaterial ? (i.mNear.value = a.near, i.mFar.value = a.far, i.opacity.value = d.opacity) : d instanceof THREE.MeshNormalMaterial && (i.opacity.value = d.opacity); if (e.receiveShadow && !d._shadowPass && i.shadowMatrix) { c = Y = 0; for (f = b.length; c < f; c++) if (k = b[c], k.castShadow && (k instanceof THREE.SpotLight || k instanceof THREE.DirectionalLight && !k.shadowCascade)) i.shadowMap.value[Y] = k.shadowMap, i.shadowMapSize.value[Y] = k.shadowMapSize, i.shadowMatrix.value[Y] = k.shadowMatrix, i.shadowDarkness.value[Y] = k.shadowDarkness, i.shadowBias.value[Y] = k.shadowBias, Y++ } b = d.uniformsList; i = 0; for (Y = b.length; i < Y; i++) if (f = g.uniforms[b[i][1]]) if (c = b[i][0], l = c.type, k = c.value, "i" === l) j.uniform1i(f, k); else if ("f" === l) j.uniform1f(f, k); else if ("v2" === l) j.uniform2f(f, k.x, k.y); else if ("v3" === l) j.uniform3f(f, k.x, k.y, k.z); else if ("v4" === l) j.uniform4f(f, k.x, k.y, k.z, k.w); else if ("c" === l) j.uniform3f(f, k.r, k.g, k.b); else if ("iv1" === l) j.uniform1iv(f, k); else if ("iv" === l) j.uniform3iv(f, k); else if ("fv1" === l) j.uniform1fv(f, k); else if ("fv" === l) j.uniform3fv(f, k); else if ("v2v" === l) { void 0 === c._array && (c._array = new Float32Array(2 * k.length)); l = 0; for (p = k.length; l < p; l++) r = 2 * l, c._array[r] = k[l].x, c._array[r + 1] = k[l].y; j.uniform2fv(f, c._array) } else if ("v3v" === l) { void 0 === c._array && (c._array = new Float32Array(3 * k.length)); l = 0; for (p = k.length; l < p; l++) r = 3 * l, c._array[r] = k[l].x, c._array[r + 1] = k[l].y, c._array[r + 2] = k[l].z; j.uniform3fv(f, c._array) } else if ("v4v" === l) { void 0 === c._array && (c._array = new Float32Array(4 * k.length)); l = 0; for (p = k.length; l < p; l++) r = 4 * l, c._array[r] = k[l].x, c._array[r + 1] = k[l].y, c._array[r + 2] = k[l].z, c._array[r + 3] = k[l].w; j.uniform4fv(f, c._array) } else if ("m4" === l) void 0 === c._array && (c._array = new Float32Array(16)), k.flattenToArray(c._array), j.uniformMatrix4fv(f, !1, c._array); else if ("m4v" === l) { void 0 === c._array && (c._array = new Float32Array(16 * k.length)); l = 0; for (p = k.length; l < p; l++) k[l].flattenToArrayOffset(c._array, 16 * l); j.uniformMatrix4fv(f, !1, c._array) } else if ("t" === l) { if (r = k, k = u(), j.uniform1i(f, k), r) if (r.image instanceof Array && 6 === r.image.length) { if (c = r, f = k, 6 === c.image.length) if (c.needsUpdate) { c.image.__webglTextureCube || (c.image.__webglTextureCube = j.createTexture(), L.info.memory.textures++); j.activeTexture(j.TEXTURE0 + f); j.bindTexture(j.TEXTURE_CUBE_MAP, c.image.__webglTextureCube); j.pixelStorei(j.UNPACK_FLIP_Y_WEBGL, c.flipY); f = c instanceof THREE.CompressedTexture; k = []; for (l = 0; 6 > l; l++) L.autoScaleCubemaps && !f ? (p = k, r = l, t = c.image[l], w = pd, t.width <= w && t.height <= w || (z = Math.max(t.width, t.height), x = Math.floor(t.width * w / z), w = Math.floor(t.height * w / z), z = document.createElement("canvas"), z.width = x, z.height = w, z.getContext("2d").drawImage(t, 0, 0, t.width, t.height, 0, 0, x, w), t = z), p[r] = t) : k[l] = c.image[l]; l = k[0]; p = 0 === (l.width & l.width - 1) && 0 === (l.height & l.height - 1); r = F(c.format); t = F(c.type); Z(j.TEXTURE_CUBE_MAP, c, p); for (l = 0; 6 > l; l++) if (f) { w = k[l].mipmaps; z = 0; for (A = w.length; z < A; z++) x = w[z], j.compressedTexImage2D(j.TEXTURE_CUBE_MAP_POSITIVE_X + l, z, r, x.width, x.height, 0, x.data) } else j.texImage2D(j.TEXTURE_CUBE_MAP_POSITIVE_X + l, 0, r, r, t, k[l]); c.generateMipmaps && p && j.generateMipmap(j.TEXTURE_CUBE_MAP); c.needsUpdate = !1; if (c.onUpdate) c.onUpdate() } else j.activeTexture(j.TEXTURE0 + f), j.bindTexture(j.TEXTURE_CUBE_MAP, c.image.__webglTextureCube) } else r instanceof THREE.WebGLRenderTargetCube ? (c = r, j.activeTexture(j.TEXTURE0 + k), j.bindTexture(j.TEXTURE_CUBE_MAP, c.__webglTexture)) : L.setTexture(r, k) } else if ("tv" === l) { void 0 === c._array && (c._array = []); l = 0; for (p = c.value.length; l < p; l++) c._array[l] = u(); j.uniform1iv(f, c._array); l = 0; for (p = c.value.length; l < p; l++) r = c.value[l], k = c._array[l], r && L.setTexture(r, k) } if ((d instanceof THREE.ShaderMaterial || d instanceof THREE.MeshPhongMaterial || d.envMap) && null !== h.cameraPosition) wa.getPositionFromMatrix(a.matrixWorld), j.uniform3f(h.cameraPosition, wa.x, wa.y, wa.z); (d instanceof THREE.MeshPhongMaterial || d instanceof THREE.MeshLambertMaterial || d instanceof THREE.ShaderMaterial || d.skinning) && null !== h.viewMatrix && j.uniformMatrix4fv(h.viewMatrix, !1, a.matrixWorldInverse.elements) } j.uniformMatrix4fv(h.modelViewMatrix, !1, e._modelViewMatrix.elements); h.normalMatrix && j.uniformMatrix3fv(h.normalMatrix, !1, e._normalMatrix.elements); null !== h.modelMatrix && j.uniformMatrix4fv(h.modelMatrix, !1, e.matrixWorld.elements); return g } function u() { var a = ea; a >= Ib && console.warn("WebGLRenderer: trying to use " + a + " texture units while this GPU supports only " + Ib); ea += 1; return a } function B(a, b) { a._modelViewMatrix.multiplyMatrices(b.matrixWorldInverse, a.matrixWorld); a._normalMatrix.getInverse(a._modelViewMatrix); a._normalMatrix.transpose() } function G(a, b, c, d) { a[b] = c.r * c.r * d; a[b + 1] = c.g * c.g * d; a[b + 2] = c.b * c.b * d } function D(a, b, c, d) { a[b] = c.r * d; a[b + 1] = c.g * d; a[b + 2] = c.b * d } function w(a) { a !== Sa && (j.lineWidth(a), Sa = a) } function I(a, b, c) { Ba !== a && (a ? j.enable(j.POLYGON_OFFSET_FILL) : j.disable(j.POLYGON_OFFSET_FILL), Ba = a); if (a && (fb !== b || jb !== c)) j.polygonOffset(b, c), fb = b, jb = c } function J(a) { for (var a = a.split("\n"), b = 0, c = a.length; b < c; b++) a[b] = b + 1 + ": " + a[b]; return a.join("\n") } function E(a, b) { var c; "fragment" === a ? c = j.createShader(j.FRAGMENT_SHADER) : "vertex" === a && (c = j.createShader(j.VERTEX_SHADER)); j.shaderSource(c, b); j.compileShader(c); return !j.getShaderParameter(c, j.COMPILE_STATUS) ? (console.error(j.getShaderInfoLog(c)), console.error(J(b)), null) : c } function Z(a, b, c) { c ? (j.texParameteri(a, j.TEXTURE_WRAP_S, F(b.wrapS)), j.texParameteri(a, j.TEXTURE_WRAP_T, F(b.wrapT)), j.texParameteri(a, j.TEXTURE_MAG_FILTER, F(b.magFilter)), j.texParameteri(a, j.TEXTURE_MIN_FILTER, F(b.minFilter))) : (j.texParameteri(a, j.TEXTURE_WRAP_S, j.CLAMP_TO_EDGE), j.texParameteri(a, j.TEXTURE_WRAP_T, j.CLAMP_TO_EDGE), j.texParameteri(a, j.TEXTURE_MAG_FILTER, S(b.magFilter)), j.texParameteri(a, j.TEXTURE_MIN_FILTER, S(b.minFilter))); if (Wa && b.type !== THREE.FloatType && (1 < b.anisotropy || b.__oldAnisotropy)) j.texParameterf(a, Wa.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(b.anisotropy, Wc)), b.__oldAnisotropy = b.anisotropy } function A(a, b) { j.bindRenderbuffer(j.RENDERBUFFER, a); b.depthBuffer && !b.stencilBuffer ? (j.renderbufferStorage(j.RENDERBUFFER, j.DEPTH_COMPONENT16, b.width, b.height), j.framebufferRenderbuffer(j.FRAMEBUFFER, j.DEPTH_ATTACHMENT, j.RENDERBUFFER, a)) : b.depthBuffer && b.stencilBuffer ? (j.renderbufferStorage(j.RENDERBUFFER, j.DEPTH_STENCIL, b.width, b.height), j.framebufferRenderbuffer(j.FRAMEBUFFER, j.DEPTH_STENCIL_ATTACHMENT, j.RENDERBUFFER, a)) : j.renderbufferStorage(j.RENDERBUFFER, j.RGBA4, b.width, b.height) } function S(a) { return a === THREE.NearestFilter || a === THREE.NearestMipMapNearestFilter || a === THREE.NearestMipMapLinearFilter ? j.NEAREST : j.LINEAR } function F(a) { if (a === THREE.RepeatWrapping) return j.REPEAT; if (a === THREE.ClampToEdgeWrapping) return j.CLAMP_TO_EDGE; if (a === THREE.MirroredRepeatWrapping) return j.MIRRORED_REPEAT; if (a === THREE.NearestFilter) return j.NEAREST; if (a === THREE.NearestMipMapNearestFilter) return j.NEAREST_MIPMAP_NEAREST; if (a === THREE.NearestMipMapLinearFilter) return j.NEAREST_MIPMAP_LINEAR; if (a === THREE.LinearFilter) return j.LINEAR; if (a === THREE.LinearMipMapNearestFilter) return j.LINEAR_MIPMAP_NEAREST; if (a === THREE.LinearMipMapLinearFilter) return j.LINEAR_MIPMAP_LINEAR; if (a === THREE.UnsignedByteType) return j.UNSIGNED_BYTE; if (a === THREE.UnsignedShort4444Type) return j.UNSIGNED_SHORT_4_4_4_4; if (a === THREE.UnsignedShort5551Type) return j.UNSIGNED_SHORT_5_5_5_1; if (a === THREE.UnsignedShort565Type) return j.UNSIGNED_SHORT_5_6_5; if (a === THREE.ByteType) return j.BYTE; if (a === THREE.ShortType) return j.SHORT; if (a === THREE.UnsignedShortType) return j.UNSIGNED_SHORT; if (a === THREE.IntType) return j.INT; if (a === THREE.UnsignedIntType) return j.UNSIGNED_INT; if (a === THREE.FloatType) return j.FLOAT; if (a === THREE.AlphaFormat) return j.ALPHA; if (a === THREE.RGBFormat) return j.RGB; if (a === THREE.RGBAFormat) return j.RGBA; if (a === THREE.LuminanceFormat) return j.LUMINANCE; if (a === THREE.LuminanceAlphaFormat) return j.LUMINANCE_ALPHA; if (a === THREE.AddEquation) return j.FUNC_ADD; if (a === THREE.SubtractEquation) return j.FUNC_SUBTRACT; if (a === THREE.ReverseSubtractEquation) return j.FUNC_REVERSE_SUBTRACT; if (a === THREE.ZeroFactor) return j.ZERO; if (a === THREE.OneFactor) return j.ONE; if (a === THREE.SrcColorFactor) return j.SRC_COLOR; if (a === THREE.OneMinusSrcColorFactor) return j.ONE_MINUS_SRC_COLOR; if (a === THREE.SrcAlphaFactor) return j.SRC_ALPHA; if (a === THREE.OneMinusSrcAlphaFactor) return j.ONE_MINUS_SRC_ALPHA; if (a === THREE.DstAlphaFactor) return j.DST_ALPHA; if (a === THREE.OneMinusDstAlphaFactor) return j.ONE_MINUS_DST_ALPHA; if (a === THREE.DstColorFactor) return j.DST_COLOR; if (a === THREE.OneMinusDstColorFactor) return j.ONE_MINUS_DST_COLOR; if (a === THREE.SrcAlphaSaturateFactor) return j.SRC_ALPHA_SATURATE; if (void 0 !== Ga) { if (a === THREE.RGB_S3TC_DXT1_Format) return Ga.COMPRESSED_RGB_S3TC_DXT1_EXT; if (a === THREE.RGBA_S3TC_DXT1_Format) return Ga.COMPRESSED_RGBA_S3TC_DXT1_EXT; if (a === THREE.RGBA_S3TC_DXT3_Format) return Ga.COMPRESSED_RGBA_S3TC_DXT3_EXT; if (a === THREE.RGBA_S3TC_DXT5_Format) return Ga.COMPRESSED_RGBA_S3TC_DXT5_EXT } return 0 } console.log("THREE.WebGLRenderer", THREE.REVISION); var a = a || {}, H = void 0 !== a.canvas ? a.canvas : document.createElement("canvas"), K = void 0 !== a.precision ? a.precision : "highp", N = void 0 !== a.alpha ? a.alpha : !0, fa = void 0 !== a.premultipliedAlpha ? a.premultipliedAlpha : !0, ma = void 0 !== a.antialias ? a.antialias : !1, eb = void 0 !== a.stencil ? a.stencil : !0, M = void 0 !== a.preserveDrawingBuffer ? a.preserveDrawingBuffer : !1, U = void 0 !== a.clearColor ? new THREE.Color(a.clearColor) : new THREE.Color(0), ja = void 0 !== a.clearAlpha ? a.clearAlpha : 0; this.domElement = H; this.context = null; this.devicePixelRatio = void 0 !== a.devicePixelRatio ? a.devicePixelRatio : void 0 !== window.devicePixelRatio ? window.devicePixelRatio : 1; this.autoUpdateScene = this.autoUpdateObjects = this.sortObjects = this.autoClearStencil = this.autoClearDepth = this.autoClearColor = this.autoClear = !0; this.shadowMapEnabled = this.physicallyBasedShading = this.gammaOutput = this.gammaInput = !1; this.shadowMapAutoUpdate = !0; this.shadowMapType = THREE.PCFShadowMap; this.shadowMapCullFace = THREE.CullFaceFront; this.shadowMapCascade = this.shadowMapDebug = !1; this.maxMorphTargets = 8; this.maxMorphNormals = 4; this.autoScaleCubemaps = !0; this.renderPluginsPre = []; this.renderPluginsPost = []; this.info = { memory: { programs: 0, geometries: 0, textures: 0 }, render: {calls: 0, vertices: 0, faces: 0, points: 0} }; var L = this, ca = [], ta = 0, kb = null, $a = null, lb = -1, db = null, La = null, Oa = 0, ea = 0, ha = -1, V = -1, $ = -1, Y = -1, ia = -1, ra = -1, na = -1, Pa = -1, Ba = null, fb = null, jb = null, Sa = null, ob = 0, Gb = 0, Mb = 0, wb = 0, Nb = 0, Ob = 0, xb = {}, Hb = new THREE.Frustum, Qa = new THREE.Matrix4, Va = new THREE.Matrix4, wa = new THREE.Vector3, xa = new THREE.Vector3, yb = !0, pb = { ambient: [0, 0, 0], directional: {length: 0, colors: [], positions: []}, point: {length: 0, colors: [], positions: [], distances: []}, spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [] }, hemi: {length: 0, skyColors: [], groundColors: [], positions: []} }, j, mb, vb, Wa, Ga; try { if (!(j = H.getContext("experimental-webgl", { alpha: N, premultipliedAlpha: fa, antialias: ma, stencil: eb, preserveDrawingBuffer: M }))) throw"Error creating WebGL context."; } catch (zb) { console.error(zb) } mb = j.getExtension("OES_texture_float"); vb = j.getExtension("OES_standard_derivatives"); Wa = j.getExtension("EXT_texture_filter_anisotropic") || j.getExtension("MOZ_EXT_texture_filter_anisotropic") || j.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); Ga = j.getExtension("WEBGL_compressed_texture_s3tc") || j.getExtension("MOZ_WEBGL_compressed_texture_s3tc") || j.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc"); mb || console.log("THREE.WebGLRenderer: Float textures not supported."); vb || console.log("THREE.WebGLRenderer: Standard derivatives not supported."); Wa || console.log("THREE.WebGLRenderer: Anisotropic texture filtering not supported."); Ga || console.log("THREE.WebGLRenderer: S3TC compressed textures not supported."); void 0 === j.getShaderPrecisionFormat && (j.getShaderPrecisionFormat = function () { return {rangeMin: 1, rangeMax: 1, precision: 1} }); j.clearColor(0, 0, 0, 1); j.clearDepth(1); j.clearStencil(0); j.enable(j.DEPTH_TEST); j.depthFunc(j.LEQUAL); j.frontFace(j.CCW); j.cullFace(j.BACK); j.enable(j.CULL_FACE); j.enable(j.BLEND); j.blendEquation(j.FUNC_ADD); j.blendFunc(j.SRC_ALPHA, j.ONE_MINUS_SRC_ALPHA); j.clearColor(U.r, U.g, U.b, ja); this.context = j; var Ib = j.getParameter(j.MAX_TEXTURE_IMAGE_UNITS), a = j.getParameter(j.MAX_VERTEX_TEXTURE_IMAGE_UNITS); j.getParameter(j.MAX_TEXTURE_SIZE); var pd = j.getParameter(j.MAX_CUBE_MAP_TEXTURE_SIZE), Wc = Wa ? j.getParameter(Wa.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0, Bc = 0 < a, Cc = Bc && mb; Ga && j.getParameter(j.COMPRESSED_TEXTURE_FORMATS); fa = j.getShaderPrecisionFormat(j.VERTEX_SHADER, j.HIGH_FLOAT); a = j.getShaderPrecisionFormat(j.VERTEX_SHADER, j.MEDIUM_FLOAT); j.getShaderPrecisionFormat(j.VERTEX_SHADER, j.LOW_FLOAT); ma = j.getShaderPrecisionFormat(j.FRAGMENT_SHADER, j.HIGH_FLOAT); N = j.getShaderPrecisionFormat(j.FRAGMENT_SHADER, j.MEDIUM_FLOAT); j.getShaderPrecisionFormat(j.FRAGMENT_SHADER, j.LOW_FLOAT); j.getShaderPrecisionFormat(j.VERTEX_SHADER, j.HIGH_INT); j.getShaderPrecisionFormat(j.VERTEX_SHADER, j.MEDIUM_INT); j.getShaderPrecisionFormat(j.VERTEX_SHADER, j.LOW_INT); j.getShaderPrecisionFormat(j.FRAGMENT_SHADER, j.HIGH_INT); j.getShaderPrecisionFormat(j.FRAGMENT_SHADER, j.MEDIUM_INT); j.getShaderPrecisionFormat(j.FRAGMENT_SHADER, j.LOW_INT); fa = 0 < fa.precision && 0 < ma.precision; a = 0 < a.precision && 0 < N.precision; "highp" === K && !fa && (a ? (K = "mediump", console.warn("WebGLRenderer: highp not supported, using mediump")) : (K = "lowp", console.warn("WebGLRenderer: highp and mediump not supported, using lowp"))); "mediump" === K && !a && (K = "lowp", console.warn("WebGLRenderer: mediump not supported, using lowp")); this.getContext = function () { return j }; this.supportsVertexTextures = function () { return Bc }; this.supportsFloatTextures = function () { return mb }; this.supportsStandardDerivatives = function () { return vb }; this.supportsCompressedTextureS3TC = function () { return Ga }; this.getMaxAnisotropy = function () { return Wc }; this.getPrecision = function () { return K }; this.setSize = function (a, b) { H.width = a * this.devicePixelRatio; H.height = b * this.devicePixelRatio; H.style.width = a + "px"; H.style.height = b + "px"; this.setViewport(0, 0, H.width, H.height) }; this.setViewport = function (a, b, c, d) { ob = void 0 !== a ? a : 0; Gb = void 0 !== b ? b : 0; Mb = void 0 !== c ? c : H.width; wb = void 0 !== d ? d : H.height; j.viewport(ob, Gb, Mb, wb) }; this.setScissor = function (a, b, c, d) { j.scissor(a, b, c, d) }; this.enableScissorTest = function (a) { a ? j.enable(j.SCISSOR_TEST) : j.disable(j.SCISSOR_TEST) }; this.setClearColorHex = function (a, b) { U.setHex(a); ja = b; j.clearColor(U.r, U.g, U.b, ja) }; this.setClearColor = function (a, b) { U.copy(a); ja = b; j.clearColor(U.r, U.g, U.b, ja) }; this.getClearColor = function () { return U }; this.getClearAlpha = function () { return ja }; this.clear = function (a, b, c) { var d = 0; if (void 0 === a || a) d |= j.COLOR_BUFFER_BIT; if (void 0 === b || b) d |= j.DEPTH_BUFFER_BIT; if (void 0 === c || c) d |= j.STENCIL_BUFFER_BIT; j.clear(d) }; this.clearTarget = function (a, b, c, d) { this.setRenderTarget(a); this.clear(b, c, d) }; this.addPostPlugin = function (a) { a.init(this); this.renderPluginsPost.push(a) }; this.addPrePlugin = function (a) { a.init(this); this.renderPluginsPre.push(a) }; this.updateShadowMap = function (a, b) { kb = null; lb = db = Pa = na = $ = -1; yb = !0; V = ha = -1; this.shadowMapPlugin.update(a, b) }; var Bd = function (a) { a = a.target; a.removeEventListener("dispose", Bd); a.__webglInit = void 0; void 0 !== a.__webglVertexBuffer && j.deleteBuffer(a.__webglVertexBuffer); void 0 !== a.__webglNormalBuffer && j.deleteBuffer(a.__webglNormalBuffer); void 0 !== a.__webglTangentBuffer && j.deleteBuffer(a.__webglTangentBuffer); void 0 !== a.__webglColorBuffer && j.deleteBuffer(a.__webglColorBuffer); void 0 !== a.__webglUVBuffer && j.deleteBuffer(a.__webglUVBuffer); void 0 !== a.__webglUV2Buffer && j.deleteBuffer(a.__webglUV2Buffer); void 0 !== a.__webglSkinIndicesBuffer && j.deleteBuffer(a.__webglSkinIndicesBuffer); void 0 !== a.__webglSkinWeightsBuffer && j.deleteBuffer(a.__webglSkinWeightsBuffer); void 0 !== a.__webglFaceBuffer && j.deleteBuffer(a.__webglFaceBuffer); void 0 !== a.__webglLineBuffer && j.deleteBuffer(a.__webglLineBuffer); void 0 !== a.__webglLineDistanceBuffer && j.deleteBuffer(a.__webglLineDistanceBuffer); if (void 0 !== a.geometryGroups) for (var c in a.geometryGroups) { var d = a.geometryGroups[c]; if (void 0 !== d.numMorphTargets) for (var e = 0, f = d.numMorphTargets; e < f; e++) j.deleteBuffer(d.__webglMorphTargetsBuffers[e]); if (void 0 !== d.numMorphNormals) { e = 0; for (f = d.numMorphNormals; e < f; e++) j.deleteBuffer(d.__webglMorphNormalsBuffers[e]) } b(d) } b(a); L.info.memory.geometries-- }, Zc = function (a) { a = a.target; a.removeEventListener("dispose", Zc); a.image && a.image.__webglTextureCube ? j.deleteTexture(a.image.__webglTextureCube) : a.__webglInit && (a.__webglInit = !1, j.deleteTexture(a.__webglTexture)); L.info.memory.textures-- }, Jc = function (a) { a = a.target; a.removeEventListener("dispose", Jc); if (a && a.__webglTexture) if (j.deleteTexture(a.__webglTexture), a instanceof THREE.WebGLRenderTargetCube) for (var b = 0; 6 > b; b++) j.deleteFramebuffer(a.__webglFramebuffer[b]), j.deleteRenderbuffer(a.__webglRenderbuffer[b]); else j.deleteFramebuffer(a.__webglFramebuffer), j.deleteRenderbuffer(a.__webglRenderbuffer); L.info.memory.textures-- }, Xc = function (a) { a = a.target; a.removeEventListener("dispose", Xc); Yc(a) }, Yc = function (a) { var b = a.program; if (void 0 !== b) { a.program = void 0; var c, d, e = !1, a = 0; for (c = ca.length; a < c; a++) if (d = ca[a], d.program === b) { d.usedTimes--; 0 === d.usedTimes && (e = !0); break } if (!0 === e) { e = []; a = 0; for (c = ca.length; a < c; a++) d = ca[a], d.program !== b && e.push(d); ca = e; j.deleteProgram(b); L.info.memory.programs-- } } }; this.renderBufferImmediate = function (a, b, c) { a.hasPositions && !a.__webglVertexBuffer && (a.__webglVertexBuffer = j.createBuffer()); a.hasNormals && !a.__webglNormalBuffer && (a.__webglNormalBuffer = j.createBuffer()); a.hasUvs && !a.__webglUvBuffer && (a.__webglUvBuffer = j.createBuffer()); a.hasColors && !a.__webglColorBuffer && (a.__webglColorBuffer = j.createBuffer()); a.hasPositions && (j.bindBuffer(j.ARRAY_BUFFER, a.__webglVertexBuffer), j.bufferData(j.ARRAY_BUFFER, a.positionArray, j.DYNAMIC_DRAW), j.enableVertexAttribArray(b.attributes.position), j.vertexAttribPointer(b.attributes.position, 3, j.FLOAT, !1, 0, 0)); if (a.hasNormals) { j.bindBuffer(j.ARRAY_BUFFER, a.__webglNormalBuffer); if (c.shading === THREE.FlatShading) { var d, e, f, g, h, i, k, l, m, p, n, q = 3 * a.count; for (n = 0; n < q; n += 9) p = a.normalArray, d = p[n], e = p[n + 1], f = p[n + 2], g = p[n + 3], i = p[n + 4], l = p[n + 5], h = p[n + 6], k = p[n + 7], m = p[n + 8], d = (d + g + h) / 3, e = (e + i + k) / 3, f = (f + l + m) / 3, p[n] = d, p[n + 1] = e, p[n + 2] = f, p[n + 3] = d, p[n + 4] = e, p[n + 5] = f, p[n + 6] = d, p[n + 7] = e, p[n + 8] = f } j.bufferData(j.ARRAY_BUFFER, a.normalArray, j.DYNAMIC_DRAW); j.enableVertexAttribArray(b.attributes.normal); j.vertexAttribPointer(b.attributes.normal, 3, j.FLOAT, !1, 0, 0) } a.hasUvs && c.map && (j.bindBuffer(j.ARRAY_BUFFER, a.__webglUvBuffer), j.bufferData(j.ARRAY_BUFFER, a.uvArray, j.DYNAMIC_DRAW), j.enableVertexAttribArray(b.attributes.uv), j.vertexAttribPointer(b.attributes.uv, 2, j.FLOAT, !1, 0, 0)); a.hasColors && c.vertexColors !== THREE.NoColors && (j.bindBuffer(j.ARRAY_BUFFER, a.__webglColorBuffer), j.bufferData(j.ARRAY_BUFFER, a.colorArray, j.DYNAMIC_DRAW), j.enableVertexAttribArray(b.attributes.color), j.vertexAttribPointer(b.attributes.color, 3, j.FLOAT, !1, 0, 0)); j.drawArrays(j.TRIANGLES, 0, a.count); a.count = 0 }; this.renderBufferDirect = function (a, b, c, d, e, f) { if (!1 !== d.visible) { var g, k, l; g = x(a, b, c, d, f); a = g.attributes; b = e.attributes; c = !1; g = 16777215 * e.id + 2 * g.id + (d.wireframe ? 1 : 0); g !== db && (db = g, c = !0); c && i(); if (f instanceof THREE.Mesh) if (d = b.index) { e = e.offsets; 1 < e.length && (c = !0); for (var m = 0, p = e.length; m < p; m++) { var n = e[m].index; if (c) { for (k in b) "index" !== k && (g = a[k], f = b[k], l = f.itemSize, 0 <= g && (j.bindBuffer(j.ARRAY_BUFFER, f.buffer), h(g), j.vertexAttribPointer(g, l, j.FLOAT, !1, 0, 4 * n * l))); j.bindBuffer(j.ELEMENT_ARRAY_BUFFER, d.buffer) } j.drawElements(j.TRIANGLES, e[m].count, j.UNSIGNED_SHORT, 2 * e[m].start); L.info.render.calls++; L.info.render.vertices += e[m].count; L.info.render.faces += e[m].count / 3 } } else { if (c) for (k in b) "index" !== k && (g = a[k], f = b[k], l = f.itemSize, 0 <= g && (j.bindBuffer(j.ARRAY_BUFFER, f.buffer), h(g), j.vertexAttribPointer(g, l, j.FLOAT, !1, 0, 0))); k = e.attributes.position; j.drawArrays(j.TRIANGLES, 0, k.numItems / 3); L.info.render.calls++; L.info.render.vertices += k.numItems / 3; L.info.render.faces += k.numItems / 3 / 3 } else if (f instanceof THREE.ParticleSystem) { if (c) { for (k in b) g = a[k], f = b[k], l = f.itemSize, 0 <= g && (j.bindBuffer(j.ARRAY_BUFFER, f.buffer), h(g), j.vertexAttribPointer(g, l, j.FLOAT, !1, 0, 0)); k = b.position; j.drawArrays(j.POINTS, 0, k.numItems / 3); L.info.render.calls++; L.info.render.points += k.numItems / 3 } } else if (f instanceof THREE.Line && c) { for (k in b) g = a[k], f = b[k], l = f.itemSize, 0 <= g && (j.bindBuffer(j.ARRAY_BUFFER, f.buffer), h(g), j.vertexAttribPointer(g, l, j.FLOAT, !1, 0, 0)); w(d.linewidth); k = b.position; j.drawArrays(j.LINE_STRIP, 0, k.numItems / 3); L.info.render.calls++; L.info.render.points += k.numItems } } }; this.renderBuffer = function (a, b, c, d, e, f) { if (!1 !== d.visible) { var g, k, c = x(a, b, c, d, f), a = c.attributes, b = !1, c = 16777215 * e.id + 2 * c.id + (d.wireframe ? 1 : 0); c !== db && (db = c, b = !0); b && i(); if (!d.morphTargets && 0 <= a.position) b && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglVertexBuffer), h(a.position), j.vertexAttribPointer(a.position, 3, j.FLOAT, !1, 0, 0)); else if (f.morphTargetBase) { c = d.program.attributes; -1 !== f.morphTargetBase && 0 <= c.position ? (j.bindBuffer(j.ARRAY_BUFFER, e.__webglMorphTargetsBuffers[f.morphTargetBase]), h(c.position), j.vertexAttribPointer(c.position, 3, j.FLOAT, !1, 0, 0)) : 0 <= c.position && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglVertexBuffer), h(c.position), j.vertexAttribPointer(c.position, 3, j.FLOAT, !1, 0, 0)); if (f.morphTargetForcedOrder.length) { var m = 0; k = f.morphTargetForcedOrder; for (g = f.morphTargetInfluences; m < d.numSupportedMorphTargets && m < k.length;) 0 <= c["morphTarget" + m] && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglMorphTargetsBuffers[k[m]]), h(c["morphTarget" + m]), j.vertexAttribPointer(c["morphTarget" + m], 3, j.FLOAT, !1, 0, 0)), 0 <= c["morphNormal" + m] && d.morphNormals && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglMorphNormalsBuffers[k[m]]), h(c["morphNormal" + m]), j.vertexAttribPointer(c["morphNormal" + m], 3, j.FLOAT, !1, 0, 0)), f.__webglMorphTargetInfluences[m] = g[k[m]], m++ } else { k = []; g = f.morphTargetInfluences; var p, n = g.length; for (p = 0; p < n; p++) m = g[p], 0 < m && k.push([m, p]); k.length > d.numSupportedMorphTargets ? (k.sort(l), k.length = d.numSupportedMorphTargets) : k.length > d.numSupportedMorphNormals ? k.sort(l) : 0 === k.length && k.push([0, 0]); for (m = 0; m < d.numSupportedMorphTargets;) k[m] ? (p = k[m][1], 0 <= c["morphTarget" + m] && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglMorphTargetsBuffers[p]), h(c["morphTarget" + m]), j.vertexAttribPointer(c["morphTarget" + m], 3, j.FLOAT, !1, 0, 0)), 0 <= c["morphNormal" + m] && d.morphNormals && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglMorphNormalsBuffers[p]), h(c["morphNormal" + m]), j.vertexAttribPointer(c["morphNormal" + m], 3, j.FLOAT, !1, 0, 0)), f.__webglMorphTargetInfluences[m] = g[p]) : f.__webglMorphTargetInfluences[m] = 0, m++ } null !== d.program.uniforms.morphTargetInfluences && j.uniform1fv(d.program.uniforms.morphTargetInfluences, f.__webglMorphTargetInfluences) } if (b) { if (e.__webglCustomAttributesList) { g = 0; for (k = e.__webglCustomAttributesList.length; g < k; g++) c = e.__webglCustomAttributesList[g], 0 <= a[c.buffer.belongsToAttribute] && (j.bindBuffer(j.ARRAY_BUFFER, c.buffer), h(a[c.buffer.belongsToAttribute]), j.vertexAttribPointer(a[c.buffer.belongsToAttribute], c.size, j.FLOAT, !1, 0, 0)) } 0 <= a.color && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglColorBuffer), h(a.color), j.vertexAttribPointer(a.color, 3, j.FLOAT, !1, 0, 0)); 0 <= a.normal && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglNormalBuffer), h(a.normal), j.vertexAttribPointer(a.normal, 3, j.FLOAT, !1, 0, 0)); 0 <= a.tangent && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglTangentBuffer), h(a.tangent), j.vertexAttribPointer(a.tangent, 4, j.FLOAT, !1, 0, 0)); 0 <= a.uv && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglUVBuffer), h(a.uv), j.vertexAttribPointer(a.uv, 2, j.FLOAT, !1, 0, 0)); 0 <= a.uv2 && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglUV2Buffer), h(a.uv2), j.vertexAttribPointer(a.uv2, 2, j.FLOAT, !1, 0, 0)); d.skinning && (0 <= a.skinIndex && 0 <= a.skinWeight) && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglSkinIndicesBuffer), h(a.skinIndex), j.vertexAttribPointer(a.skinIndex, 4, j.FLOAT, !1, 0, 0), j.bindBuffer(j.ARRAY_BUFFER, e.__webglSkinWeightsBuffer), h(a.skinWeight), j.vertexAttribPointer(a.skinWeight, 4, j.FLOAT, !1, 0, 0)); 0 <= a.lineDistance && (j.bindBuffer(j.ARRAY_BUFFER, e.__webglLineDistanceBuffer), h(a.lineDistance), j.vertexAttribPointer(a.lineDistance, 1, j.FLOAT, !1, 0, 0)) } f instanceof THREE.Mesh ? (d.wireframe ? (w(d.wireframeLinewidth), b && j.bindBuffer(j.ELEMENT_ARRAY_BUFFER, e.__webglLineBuffer), j.drawElements(j.LINES, e.__webglLineCount, j.UNSIGNED_SHORT, 0)) : (b && j.bindBuffer(j.ELEMENT_ARRAY_BUFFER, e.__webglFaceBuffer), j.drawElements(j.TRIANGLES, e.__webglFaceCount, j.UNSIGNED_SHORT, 0)), L.info.render.calls++, L.info.render.vertices += e.__webglFaceCount, L.info.render.faces += e.__webglFaceCount / 3) : f instanceof THREE.Line ? (f = f.type === THREE.LineStrip ? j.LINE_STRIP : j.LINES, w(d.linewidth), j.drawArrays(f, 0, e.__webglLineCount), L.info.render.calls++) : f instanceof THREE.ParticleSystem ? (j.drawArrays(j.POINTS, 0, e.__webglParticleCount), L.info.render.calls++, L.info.render.points += e.__webglParticleCount) : f instanceof THREE.Ribbon && (j.drawArrays(j.TRIANGLE_STRIP, 0, e.__webglVertexCount), L.info.render.calls++) } }; this.render = function (a, b, c, d) { if (!1 === b instanceof THREE.Camera) console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera."); else { var e, f, g, h, i = a.__lights, l = a.fog; lb = -1; yb = !0; this.autoUpdateScene && a.updateMatrixWorld(); void 0 === b.parent && b.updateMatrixWorld(); b.matrixWorldInverse.getInverse(b.matrixWorld); Qa.multiplyMatrices(b.projectionMatrix, b.matrixWorldInverse); Hb.setFromMatrix(Qa); this.autoUpdateObjects && this.initWebGLObjects(a); m(this.renderPluginsPre, a, b); L.info.render.calls = 0; L.info.render.vertices = 0; L.info.render.faces = 0; L.info.render.points = 0; this.setRenderTarget(c); (this.autoClear || d) && this.clear(this.autoClearColor, this.autoClearDepth, this.autoClearStencil); h = a.__webglObjects; d = 0; for (e = h.length; d < e; d++) if (f = h[d], g = f.object, f.render = !1, g.visible && (!(g instanceof THREE.Mesh || g instanceof THREE.ParticleSystem) || !g.frustumCulled || Hb.intersectsObject(g))) { B(g, b); var n = f, q = n.buffer, r = void 0, t = r = void 0, t = n.object.material; if (t instanceof THREE.MeshFaceMaterial) r = q.materialIndex, r = t.materials[r], r.transparent ? (n.transparent = r, n.opaque = null) : (n.opaque = r, n.transparent = null); else if (r = t) r.transparent ? (n.transparent = r, n.opaque = null) : (n.opaque = r, n.transparent = null); f.render = !0; !0 === this.sortObjects && (null !== g.renderDepth ? f.z = g.renderDepth : (wa.getPositionFromMatrix(g.matrixWorld), wa.applyProjection(Qa), f.z = wa.z), f.id = g.id) } this.sortObjects && h.sort(k); h = a.__webglObjectsImmediate; d = 0; for (e = h.length; d < e; d++) f = h[d], g = f.object, g.visible && (B(g, b), g = f.object.material, g.transparent ? (f.transparent = g, f.opaque = null) : (f.opaque = g, f.transparent = null)); a.overrideMaterial ? (d = a.overrideMaterial, this.setBlending(d.blending, d.blendEquation, d.blendSrc, d.blendDst), this.setDepthTest(d.depthTest), this.setDepthWrite(d.depthWrite), I(d.polygonOffset, d.polygonOffsetFactor, d.polygonOffsetUnits), p(a.__webglObjects, !1, "", b, i, l, !0, d), s(a.__webglObjectsImmediate, "", b, i, l, !1, d)) : (d = null, this.setBlending(THREE.NoBlending), p(a.__webglObjects, !0, "opaque", b, i, l, !1, d), s(a.__webglObjectsImmediate, "opaque", b, i, l, !1, d), p(a.__webglObjects, !1, "transparent", b, i, l, !0, d), s(a.__webglObjectsImmediate, "transparent", b, i, l, !0, d)); m(this.renderPluginsPost, a, b); c && (c.generateMipmaps && c.minFilter !== THREE.NearestFilter && c.minFilter !== THREE.LinearFilter) && (c instanceof THREE.WebGLRenderTargetCube ? (j.bindTexture(j.TEXTURE_CUBE_MAP, c.__webglTexture), j.generateMipmap(j.TEXTURE_CUBE_MAP), j.bindTexture(j.TEXTURE_CUBE_MAP, null)) : (j.bindTexture(j.TEXTURE_2D, c.__webglTexture), j.generateMipmap(j.TEXTURE_2D), j.bindTexture(j.TEXTURE_2D, null))); this.setDepthTest(!0); this.setDepthWrite(!0) } }; this.renderImmediateObject = function (a, b, c, d, e) { var f = x(a, b, c, d, e); db = -1; L.setMaterialFaces(d); e.immediateRenderCallback ? e.immediateRenderCallback(f, j, Hb) : e.render(function (a) { L.renderBufferImmediate(a, f, d) }) }; this.initWebGLObjects = function (a) { a.__webglObjects || (a.__webglObjects = [], a.__webglObjectsImmediate = [], a.__webglSprites = [], a.__webglFlares = []); for (; a.__objectsAdded.length;) { var b = a.__objectsAdded[0], h = a, i = void 0, k = void 0, m = void 0, p = void 0; if (!b.__webglInit && (b.__webglInit = !0, b._modelViewMatrix = new THREE.Matrix4, b._normalMatrix = new THREE.Matrix3, void 0 !== b.geometry && void 0 === b.geometry.__webglInit && (b.geometry.__webglInit = !0, b.geometry.addEventListener("dispose", Bd)), k = b.geometry, void 0 !== k)) if (k instanceof THREE.BufferGeometry) { var s = k, u = void 0, x = void 0, w = void 0; for (u in s.attributes) w = "index" === u ? j.ELEMENT_ARRAY_BUFFER : j.ARRAY_BUFFER, x = s.attributes[u], x.buffer = j.createBuffer(), j.bindBuffer(w, x.buffer), j.bufferData(w, x.array, j.STATIC_DRAW) } else if (b instanceof THREE.Mesh) { m = b.material; if (void 0 === k.geometryGroups) { var A = k, B = void 0, D = void 0, F = void 0, E = void 0, G = void 0, H = void 0, I = {}, J = A.morphTargets.length, K = A.morphNormals.length, M = m instanceof THREE.MeshFaceMaterial; A.geometryGroups = {}; B = 0; for (D = A.faces.length; B < D; B++) F = A.faces[B], E = M ? F.materialIndex : 0, void 0 === I[E] && (I[E] = { hash: E, counter: 0 }), H = I[E].hash + "_" + I[E].counter, void 0 === A.geometryGroups[H] && (A.geometryGroups[H] = { faces3: [], faces4: [], materialIndex: E, vertices: 0, numMorphTargets: J, numMorphNormals: K }), G = F instanceof THREE.Face3 ? 3 : 4, 65535 < A.geometryGroups[H].vertices + G && (I[E].counter += 1, H = I[E].hash + "_" + I[E].counter, void 0 === A.geometryGroups[H] && (A.geometryGroups[H] = { faces3: [], faces4: [], materialIndex: E, vertices: 0, numMorphTargets: J, numMorphNormals: K })), F instanceof THREE.Face3 ? A.geometryGroups[H].faces3.push(B) : A.geometryGroups[H].faces4.push(B), A.geometryGroups[H].vertices += G; A.geometryGroupsList = []; var V = void 0; for (V in A.geometryGroups) A.geometryGroups[V].id = Oa++, A.geometryGroupsList.push(A.geometryGroups[V]) } for (i in k.geometryGroups) if (p = k.geometryGroups[i], !p.__webglVertexBuffer) { var N = p; N.__webglVertexBuffer = j.createBuffer(); N.__webglNormalBuffer = j.createBuffer(); N.__webglTangentBuffer = j.createBuffer(); N.__webglColorBuffer = j.createBuffer(); N.__webglUVBuffer = j.createBuffer(); N.__webglUV2Buffer = j.createBuffer(); N.__webglSkinIndicesBuffer = j.createBuffer(); N.__webglSkinWeightsBuffer = j.createBuffer(); N.__webglFaceBuffer = j.createBuffer(); N.__webglLineBuffer = j.createBuffer(); var S = void 0, ta = void 0; if (N.numMorphTargets) { N.__webglMorphTargetsBuffers = []; S = 0; for (ta = N.numMorphTargets; S < ta; S++) N.__webglMorphTargetsBuffers.push(j.createBuffer()) } if (N.numMorphNormals) { N.__webglMorphNormalsBuffers = []; S = 0; for (ta = N.numMorphNormals; S < ta; S++) N.__webglMorphNormalsBuffers.push(j.createBuffer()) } L.info.memory.geometries++; d(p, b); k.verticesNeedUpdate = !0; k.morphTargetsNeedUpdate = !0; k.elementsNeedUpdate = !0; k.uvsNeedUpdate = !0; k.normalsNeedUpdate = !0; k.tangentsNeedUpdate = !0; k.colorsNeedUpdate = !0 } } else if (b instanceof THREE.Ribbon) { if (!k.__webglVertexBuffer) { var ea = k; ea.__webglVertexBuffer = j.createBuffer(); ea.__webglColorBuffer = j.createBuffer(); ea.__webglNormalBuffer = j.createBuffer(); L.info.memory.geometries++; var U = k, $ = b, ha = U.vertices.length; U.__vertexArray = new Float32Array(3 * ha); U.__colorArray = new Float32Array(3 * ha); U.__normalArray = new Float32Array(3 * ha); U.__webglVertexCount = ha; c(U, $); k.verticesNeedUpdate = !0; k.colorsNeedUpdate = !0; k.normalsNeedUpdate = !0 } } else if (b instanceof THREE.Line) { if (!k.__webglVertexBuffer) { var Z = k; Z.__webglVertexBuffer = j.createBuffer(); Z.__webglColorBuffer = j.createBuffer(); Z.__webglLineDistanceBuffer = j.createBuffer(); L.info.memory.geometries++; var Y = k, ca = b, fa = Y.vertices.length; Y.__vertexArray = new Float32Array(3 * fa); Y.__colorArray = new Float32Array(3 * fa); Y.__lineDistanceArray = new Float32Array(1 * fa); Y.__webglLineCount = fa; c(Y, ca); k.verticesNeedUpdate = !0; k.colorsNeedUpdate = !0; k.lineDistancesNeedUpdate = !0 } } else if (b instanceof THREE.ParticleSystem && !k.__webglVertexBuffer) { var $a = k; $a.__webglVertexBuffer = j.createBuffer(); $a.__webglColorBuffer = j.createBuffer(); L.info.memory.geometries++; var ia = k, kb = b, ra = ia.vertices.length; ia.__vertexArray = new Float32Array(3 * ra); ia.__colorArray = new Float32Array(3 * ra); ia.__sortArray = []; ia.__webglParticleCount = ra; c(ia, kb); k.verticesNeedUpdate = !0; k.colorsNeedUpdate = !0 } if (!b.__webglActive) { if (b instanceof THREE.Mesh) if (k = b.geometry, k instanceof THREE.BufferGeometry) r(h.__webglObjects, k, b); else { if (k instanceof THREE.Geometry) for (i in k.geometryGroups) p = k.geometryGroups[i], r(h.__webglObjects, p, b) } else b instanceof THREE.Ribbon || b instanceof THREE.Line || b instanceof THREE.ParticleSystem ? (k = b.geometry, r(h.__webglObjects, k, b)) : b instanceof THREE.ImmediateRenderObject || b.immediateRenderCallback ? h.__webglObjectsImmediate.push({ object: b, opaque: null, transparent: null }) : b instanceof THREE.Sprite ? h.__webglSprites.push(b) : b instanceof THREE.LensFlare && h.__webglFlares.push(b); b.__webglActive = !0 } a.__objectsAdded.splice(0, 1) } for (; a.__objectsRemoved.length;) { var ja = a.__objectsRemoved[0], La = a; ja instanceof THREE.Mesh || ja instanceof THREE.ParticleSystem || ja instanceof THREE.Ribbon || ja instanceof THREE.Line ? z(La.__webglObjects, ja) : ja instanceof THREE.Sprite ? t(La.__webglSprites, ja) : ja instanceof THREE.LensFlare ? t(La.__webglFlares, ja) : (ja instanceof THREE.ImmediateRenderObject || ja.immediateRenderCallback) && z(La.__webglObjectsImmediate, ja); ja.__webglActive = !1; a.__objectsRemoved.splice(0, 1) } for (var lb = 0, db = a.__webglObjects.length; lb < db; lb++) { var ma = a.__webglObjects[lb].object, la = ma.geometry, Ba = void 0, xa = void 0, na = void 0; if (la instanceof THREE.BufferGeometry) { var Sa = j.DYNAMIC_DRAW, Wa = !la.dynamic, eb = la.attributes, fb = void 0, Pa = void 0; for (fb in eb) Pa = eb[fb], Pa.needsUpdate && ("index" === fb ? (j.bindBuffer(j.ELEMENT_ARRAY_BUFFER, Pa.buffer), j.bufferData(j.ELEMENT_ARRAY_BUFFER, Pa.array, Sa)) : (j.bindBuffer(j.ARRAY_BUFFER, Pa.buffer), j.bufferData(j.ARRAY_BUFFER, Pa.array, Sa)), Pa.needsUpdate = !1), Wa && !Pa.dynamic && delete Pa.array } else if (ma instanceof THREE.Mesh) { for (var jb = 0, ob = la.geometryGroupsList.length; jb < ob; jb++) if (Ba = la.geometryGroupsList[jb], na = e(ma, Ba), la.buffersNeedUpdate && d(Ba, ma), xa = na.attributes && n(na), la.verticesNeedUpdate || la.morphTargetsNeedUpdate || la.elementsNeedUpdate || la.uvsNeedUpdate || la.normalsNeedUpdate || la.colorsNeedUpdate || la.tangentsNeedUpdate || xa) { var sa = Ba, pb = ma, Ga = j.DYNAMIC_DRAW, Hb = !la.dynamic, mb = na; if (sa.__inittedArrays) { var Gb = f(mb), yb = mb.vertexColors ? mb.vertexColors : !1, Ib = g(mb), xb = Gb === THREE.SmoothShading, C = void 0, T = void 0, pc = void 0, O = void 0, vb = void 0, qc = void 0, Pb = void 0, Mb = void 0, jc = void 0, wb = void 0, zb = void 0, P = void 0, Q = void 0, R = void 0, qa = void 0, Qb = void 0, Rb = void 0, Sb = void 0, Nb = void 0, Tb = void 0, Ub = void 0, Vb = void 0, Ob = void 0, Wb = void 0, Xb = void 0, Yb = void 0, Kc = void 0, Zb = void 0, $b = void 0, ac = void 0, Lc = void 0, bc = void 0, cc = void 0, dc = void 0, Mc = void 0, ya = void 0, Bc = void 0, rc = void 0, Ec = void 0, Fc = void 0, Xa = void 0, Cc = void 0, Ta = void 0, Ua = void 0, sc = void 0, kc = void 0, Ma = 0, Ra = 0, lc = 0, mc = 0, Cb = 0, hb = 0, Ca = 0, nb = 0, Na = 0, aa = 0, ka = 0, y = 0, za = void 0, Ya = sa.__vertexArray, Nc = sa.__uvArray, Oc = sa.__uv2Array, Db = sa.__normalArray, Ha = sa.__tangentArray, Za = sa.__colorArray, Ia = sa.__skinIndexArray, Ja = sa.__skinWeightArray, rd = sa.__morphTargetsArrays, sd = sa.__morphNormalsArrays, td = sa.__webglCustomAttributesList, v = void 0, ec = sa.__faceArray, ub = sa.__lineArray, qb = pb.geometry, Wc = qb.elementsNeedUpdate, Jc = qb.uvsNeedUpdate, Xc = qb.normalsNeedUpdate, Yc = qb.tangentsNeedUpdate, Zc = qb.colorsNeedUpdate, pd = qb.morphTargetsNeedUpdate, xc = qb.vertices, ua = sa.faces3, va = sa.faces4, ib = qb.faces, ud = qb.faceVertexUvs[0], vd = qb.faceVertexUvs[1], yc = qb.skinIndices, tc = qb.skinWeights, uc = qb.morphTargets, $c = qb.morphNormals; if (qb.verticesNeedUpdate) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], P = xc[O.a], Q = xc[O.b], R = xc[O.c], Ya[Ra] = P.x, Ya[Ra + 1] = P.y, Ya[Ra + 2] = P.z, Ya[Ra + 3] = Q.x, Ya[Ra + 4] = Q.y, Ya[Ra + 5] = Q.z, Ya[Ra + 6] = R.x, Ya[Ra + 7] = R.y, Ya[Ra + 8] = R.z, Ra += 9; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], P = xc[O.a], Q = xc[O.b], R = xc[O.c], qa = xc[O.d], Ya[Ra] = P.x, Ya[Ra + 1] = P.y, Ya[Ra + 2] = P.z, Ya[Ra + 3] = Q.x, Ya[Ra + 4] = Q.y, Ya[Ra + 5] = Q.z, Ya[Ra + 6] = R.x, Ya[Ra + 7] = R.y, Ya[Ra + 8] = R.z, Ya[Ra + 9] = qa.x, Ya[Ra + 10] = qa.y, Ya[Ra + 11] = qa.z, Ra += 12; j.bindBuffer(j.ARRAY_BUFFER, sa.__webglVertexBuffer); j.bufferData(j.ARRAY_BUFFER, Ya, Ga) } if (pd) { Xa = 0; for (Cc = uc.length; Xa < Cc; Xa++) { C = ka = 0; for (T = ua.length; C < T; C++) sc = ua[C], O = ib[sc], P = uc[Xa].vertices[O.a], Q = uc[Xa].vertices[O.b], R = uc[Xa].vertices[O.c], Ta = rd[Xa], Ta[ka] = P.x, Ta[ka + 1] = P.y, Ta[ka + 2] = P.z, Ta[ka + 3] = Q.x, Ta[ka + 4] = Q.y, Ta[ka + 5] = Q.z, Ta[ka + 6] = R.x, Ta[ka + 7] = R.y, Ta[ka + 8] = R.z, mb.morphNormals && (xb ? (kc = $c[Xa].vertexNormals[sc], Tb = kc.a, Ub = kc.b, Vb = kc.c) : Vb = Ub = Tb = $c[Xa].faceNormals[sc], Ua = sd[Xa], Ua[ka] = Tb.x, Ua[ka + 1] = Tb.y, Ua[ka + 2] = Tb.z, Ua[ka + 3] = Ub.x, Ua[ka + 4] = Ub.y, Ua[ka + 5] = Ub.z, Ua[ka + 6] = Vb.x, Ua[ka + 7] = Vb.y, Ua[ka + 8] = Vb.z), ka += 9; C = 0; for (T = va.length; C < T; C++) sc = va[C], O = ib[sc], P = uc[Xa].vertices[O.a], Q = uc[Xa].vertices[O.b], R = uc[Xa].vertices[O.c], qa = uc[Xa].vertices[O.d], Ta = rd[Xa], Ta[ka] = P.x, Ta[ka + 1] = P.y, Ta[ka + 2] = P.z, Ta[ka + 3] = Q.x, Ta[ka + 4] = Q.y, Ta[ka + 5] = Q.z, Ta[ka + 6] = R.x, Ta[ka + 7] = R.y, Ta[ka + 8] = R.z, Ta[ka + 9] = qa.x, Ta[ka + 10] = qa.y, Ta[ka + 11] = qa.z, mb.morphNormals && (xb ? (kc = $c[Xa].vertexNormals[sc], Tb = kc.a, Ub = kc.b, Vb = kc.c, Ob = kc.d) : Ob = Vb = Ub = Tb = $c[Xa].faceNormals[sc], Ua = sd[Xa], Ua[ka] = Tb.x, Ua[ka + 1] = Tb.y, Ua[ka + 2] = Tb.z, Ua[ka + 3] = Ub.x, Ua[ka + 4] = Ub.y, Ua[ka + 5] = Ub.z, Ua[ka + 6] = Vb.x, Ua[ka + 7] = Vb.y, Ua[ka + 8] = Vb.z, Ua[ka + 9] = Ob.x, Ua[ka + 10] = Ob.y, Ua[ka + 11] = Ob.z), ka += 12; j.bindBuffer(j.ARRAY_BUFFER, sa.__webglMorphTargetsBuffers[Xa]); j.bufferData(j.ARRAY_BUFFER, rd[Xa], Ga); mb.morphNormals && (j.bindBuffer(j.ARRAY_BUFFER, sa.__webglMorphNormalsBuffers[Xa]), j.bufferData(j.ARRAY_BUFFER, sd[Xa], Ga)) } } if (tc.length) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], Zb = tc[O.a], $b = tc[O.b], ac = tc[O.c], Ja[aa] = Zb.x, Ja[aa + 1] = Zb.y, Ja[aa + 2] = Zb.z, Ja[aa + 3] = Zb.w, Ja[aa + 4] = $b.x, Ja[aa + 5] = $b.y, Ja[aa + 6] = $b.z, Ja[aa + 7] = $b.w, Ja[aa + 8] = ac.x, Ja[aa + 9] = ac.y, Ja[aa + 10] = ac.z, Ja[aa + 11] = ac.w, bc = yc[O.a], cc = yc[O.b], dc = yc[O.c], Ia[aa] = bc.x, Ia[aa + 1] = bc.y, Ia[aa + 2] = bc.z, Ia[aa + 3] = bc.w, Ia[aa + 4] = cc.x, Ia[aa + 5] = cc.y, Ia[aa + 6] = cc.z, Ia[aa + 7] = cc.w, Ia[aa + 8] = dc.x, Ia[aa + 9] = dc.y, Ia[aa + 10] = dc.z, Ia[aa + 11] = dc.w, aa += 12; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], Zb = tc[O.a], $b = tc[O.b], ac = tc[O.c], Lc = tc[O.d], Ja[aa] = Zb.x, Ja[aa + 1] = Zb.y, Ja[aa + 2] = Zb.z, Ja[aa + 3] = Zb.w, Ja[aa + 4] = $b.x, Ja[aa + 5] = $b.y, Ja[aa + 6] = $b.z, Ja[aa + 7] = $b.w, Ja[aa + 8] = ac.x, Ja[aa + 9] = ac.y, Ja[aa + 10] = ac.z, Ja[aa + 11] = ac.w, Ja[aa + 12] = Lc.x, Ja[aa + 13] = Lc.y, Ja[aa + 14] = Lc.z, Ja[aa + 15] = Lc.w, bc = yc[O.a], cc = yc[O.b], dc = yc[O.c], Mc = yc[O.d], Ia[aa] = bc.x, Ia[aa + 1] = bc.y, Ia[aa + 2] = bc.z, Ia[aa + 3] = bc.w, Ia[aa + 4] = cc.x, Ia[aa + 5] = cc.y, Ia[aa + 6] = cc.z, Ia[aa + 7] = cc.w, Ia[aa + 8] = dc.x, Ia[aa + 9] = dc.y, Ia[aa + 10] = dc.z, Ia[aa + 11] = dc.w, Ia[aa + 12] = Mc.x, Ia[aa + 13] = Mc.y, Ia[aa + 14] = Mc.z, Ia[aa + 15] = Mc.w, aa += 16; 0 < aa && (j.bindBuffer(j.ARRAY_BUFFER, sa.__webglSkinIndicesBuffer), j.bufferData(j.ARRAY_BUFFER, Ia, Ga), j.bindBuffer(j.ARRAY_BUFFER, sa.__webglSkinWeightsBuffer), j.bufferData(j.ARRAY_BUFFER, Ja, Ga)) } if (Zc && yb) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], Pb = O.vertexColors, Mb = O.color, 3 === Pb.length && yb === THREE.VertexColors ? (Wb = Pb[0], Xb = Pb[1], Yb = Pb[2]) : Yb = Xb = Wb = Mb, Za[Na] = Wb.r, Za[Na + 1] = Wb.g, Za[Na + 2] = Wb.b, Za[Na + 3] = Xb.r, Za[Na + 4] = Xb.g, Za[Na + 5] = Xb.b, Za[Na + 6] = Yb.r, Za[Na + 7] = Yb.g, Za[Na + 8] = Yb.b, Na += 9; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], Pb = O.vertexColors, Mb = O.color, 4 === Pb.length && yb === THREE.VertexColors ? (Wb = Pb[0], Xb = Pb[1], Yb = Pb[2], Kc = Pb[3]) : Kc = Yb = Xb = Wb = Mb, Za[Na] = Wb.r, Za[Na + 1] = Wb.g, Za[Na + 2] = Wb.b, Za[Na + 3] = Xb.r, Za[Na + 4] = Xb.g, Za[Na + 5] = Xb.b, Za[Na + 6] = Yb.r, Za[Na + 7] = Yb.g, Za[Na + 8] = Yb.b, Za[Na + 9] = Kc.r, Za[Na + 10] = Kc.g, Za[Na + 11] = Kc.b, Na += 12; 0 < Na && (j.bindBuffer(j.ARRAY_BUFFER, sa.__webglColorBuffer), j.bufferData(j.ARRAY_BUFFER, Za, Ga)) } if (Yc && qb.hasTangents) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], jc = O.vertexTangents, Qb = jc[0], Rb = jc[1], Sb = jc[2], Ha[Ca] = Qb.x, Ha[Ca + 1] = Qb.y, Ha[Ca + 2] = Qb.z, Ha[Ca + 3] = Qb.w, Ha[Ca + 4] = Rb.x, Ha[Ca + 5] = Rb.y, Ha[Ca + 6] = Rb.z, Ha[Ca + 7] = Rb.w, Ha[Ca + 8] = Sb.x, Ha[Ca + 9] = Sb.y, Ha[Ca + 10] = Sb.z, Ha[Ca + 11] = Sb.w, Ca += 12; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], jc = O.vertexTangents, Qb = jc[0], Rb = jc[1], Sb = jc[2], Nb = jc[3], Ha[Ca] = Qb.x, Ha[Ca + 1] = Qb.y, Ha[Ca + 2] = Qb.z, Ha[Ca + 3] = Qb.w, Ha[Ca + 4] = Rb.x, Ha[Ca + 5] = Rb.y, Ha[Ca + 6] = Rb.z, Ha[Ca + 7] = Rb.w, Ha[Ca + 8] = Sb.x, Ha[Ca + 9] = Sb.y, Ha[Ca + 10] = Sb.z, Ha[Ca + 11] = Sb.w, Ha[Ca + 12] = Nb.x, Ha[Ca + 13] = Nb.y, Ha[Ca + 14] = Nb.z, Ha[Ca + 15] = Nb.w, Ca += 16; j.bindBuffer(j.ARRAY_BUFFER, sa.__webglTangentBuffer); j.bufferData(j.ARRAY_BUFFER, Ha, Ga) } if (Xc && Gb) { C = 0; for (T = ua.length; C < T; C++) if (O = ib[ua[C]], vb = O.vertexNormals, qc = O.normal, 3 === vb.length && xb) for (ya = 0; 3 > ya; ya++) rc = vb[ya], Db[hb] = rc.x, Db[hb + 1] = rc.y, Db[hb + 2] = rc.z, hb += 3; else for (ya = 0; 3 > ya; ya++) Db[hb] = qc.x, Db[hb + 1] = qc.y, Db[hb + 2] = qc.z, hb += 3; C = 0; for (T = va.length; C < T; C++) if (O = ib[va[C]], vb = O.vertexNormals, qc = O.normal, 4 === vb.length && xb) for (ya = 0; 4 > ya; ya++) rc = vb[ya], Db[hb] = rc.x, Db[hb + 1] = rc.y, Db[hb + 2] = rc.z, hb += 3; else for (ya = 0; 4 > ya; ya++) Db[hb] = qc.x, Db[hb + 1] = qc.y, Db[hb + 2] = qc.z, hb += 3; j.bindBuffer(j.ARRAY_BUFFER, sa.__webglNormalBuffer); j.bufferData(j.ARRAY_BUFFER, Db, Ga) } if (Jc && ud && Ib) { C = 0; for (T = ua.length; C < T; C++) if (pc = ua[C], wb = ud[pc], void 0 !== wb) for (ya = 0; 3 > ya; ya++) Ec = wb[ya], Nc[lc] = Ec.x, Nc[lc + 1] = Ec.y, lc += 2; C = 0; for (T = va.length; C < T; C++) if (pc = va[C], wb = ud[pc], void 0 !== wb) for (ya = 0; 4 > ya; ya++) Ec = wb[ya], Nc[lc] = Ec.x, Nc[lc + 1] = Ec.y, lc += 2; 0 < lc && (j.bindBuffer(j.ARRAY_BUFFER, sa.__webglUVBuffer), j.bufferData(j.ARRAY_BUFFER, Nc, Ga)) } if (Jc && vd && Ib) { C = 0; for (T = ua.length; C < T; C++) if (pc = ua[C], zb = vd[pc], void 0 !== zb) for (ya = 0; 3 > ya; ya++) Fc = zb[ya], Oc[mc] = Fc.x, Oc[mc + 1] = Fc.y, mc += 2; C = 0; for (T = va.length; C < T; C++) if (pc = va[C], zb = vd[pc], void 0 !== zb) for (ya = 0; 4 > ya; ya++) Fc = zb[ya], Oc[mc] = Fc.x, Oc[mc + 1] = Fc.y, mc += 2; 0 < mc && (j.bindBuffer(j.ARRAY_BUFFER, sa.__webglUV2Buffer), j.bufferData(j.ARRAY_BUFFER, Oc, Ga)) } if (Wc) { C = 0; for (T = ua.length; C < T; C++) ec[Cb] = Ma, ec[Cb + 1] = Ma + 1, ec[Cb + 2] = Ma + 2, Cb += 3, ub[nb] = Ma, ub[nb + 1] = Ma + 1, ub[nb + 2] = Ma, ub[nb + 3] = Ma + 2, ub[nb + 4] = Ma + 1, ub[nb + 5] = Ma + 2, nb += 6, Ma += 3; C = 0; for (T = va.length; C < T; C++) ec[Cb] = Ma, ec[Cb + 1] = Ma + 1, ec[Cb + 2] = Ma + 3, ec[Cb + 3] = Ma + 1, ec[Cb + 4] = Ma + 2, ec[Cb + 5] = Ma + 3, Cb += 6, ub[nb] = Ma, ub[nb + 1] = Ma + 1, ub[nb + 2] = Ma, ub[nb + 3] = Ma + 3, ub[nb + 4] = Ma + 1, ub[nb + 5] = Ma + 2, ub[nb + 6] = Ma + 2, ub[nb + 7] = Ma + 3, nb += 8, Ma += 4; j.bindBuffer(j.ELEMENT_ARRAY_BUFFER, sa.__webglFaceBuffer); j.bufferData(j.ELEMENT_ARRAY_BUFFER, ec, Ga); j.bindBuffer(j.ELEMENT_ARRAY_BUFFER, sa.__webglLineBuffer); j.bufferData(j.ELEMENT_ARRAY_BUFFER, ub, Ga) } if (td) { ya = 0; for (Bc = td.length; ya < Bc; ya++) if (v = td[ya], v.__original.needsUpdate) { y = 0; if (1 === v.size) if (void 0 === v.boundTo || "vertices" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], v.array[y] = v.value[O.a], v.array[y + 1] = v.value[O.b], v.array[y + 2] = v.value[O.c], y += 3; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], v.array[y] = v.value[O.a], v.array[y + 1] = v.value[O.b], v.array[y + 2] = v.value[O.c], v.array[y + 3] = v.value[O.d], y += 4 } else { if ("faces" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) za = v.value[ua[C]], v.array[y] = za, v.array[y + 1] = za, v.array[y + 2] = za, y += 3; C = 0; for (T = va.length; C < T; C++) za = v.value[va[C]], v.array[y] = za, v.array[y + 1] = za, v.array[y + 2] = za, v.array[y + 3] = za, y += 4 } } else if (2 === v.size) if (void 0 === v.boundTo || "vertices" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], P = v.value[O.a], Q = v.value[O.b], R = v.value[O.c], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = Q.x, v.array[y + 3] = Q.y, v.array[y + 4] = R.x, v.array[y + 5] = R.y, y += 6; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], P = v.value[O.a], Q = v.value[O.b], R = v.value[O.c], qa = v.value[O.d], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = Q.x, v.array[y + 3] = Q.y, v.array[y + 4] = R.x, v.array[y + 5] = R.y, v.array[y + 6] = qa.x, v.array[y + 7] = qa.y, y += 8 } else { if ("faces" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) R = Q = P = za = v.value[ua[C]], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = Q.x, v.array[y + 3] = Q.y, v.array[y + 4] = R.x, v.array[y + 5] = R.y, y += 6; C = 0; for (T = va.length; C < T; C++) qa = R = Q = P = za = v.value[va[C]], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = Q.x, v.array[y + 3] = Q.y, v.array[y + 4] = R.x, v.array[y + 5] = R.y, v.array[y + 6] = qa.x, v.array[y + 7] = qa.y, y += 8 } } else if (3 === v.size) { var X; X = "c" === v.type ? ["r", "g", "b"] : ["x", "y", "z"]; if (void 0 === v.boundTo || "vertices" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], P = v.value[O.a], Q = v.value[O.b], R = v.value[O.c], v.array[y] = P[X[0]], v.array[y + 1] = P[X[1]], v.array[y + 2] = P[X[2]], v.array[y + 3] = Q[X[0]], v.array[y + 4] = Q[X[1]], v.array[y + 5] = Q[X[2]], v.array[y + 6] = R[X[0]], v.array[y + 7] = R[X[1]], v.array[y + 8] = R[X[2]], y += 9; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], P = v.value[O.a], Q = v.value[O.b], R = v.value[O.c], qa = v.value[O.d], v.array[y] = P[X[0]], v.array[y + 1] = P[X[1]], v.array[y + 2] = P[X[2]], v.array[y + 3] = Q[X[0]], v.array[y + 4] = Q[X[1]], v.array[y + 5] = Q[X[2]], v.array[y + 6] = R[X[0]], v.array[y + 7] = R[X[1]], v.array[y + 8] = R[X[2]], v.array[y + 9] = qa[X[0]], v.array[y + 10] = qa[X[1]], v.array[y + 11] = qa[X[2]], y += 12 } else if ("faces" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) R = Q = P = za = v.value[ua[C]], v.array[y] = P[X[0]], v.array[y + 1] = P[X[1]], v.array[y + 2] = P[X[2]], v.array[y + 3] = Q[X[0]], v.array[y + 4] = Q[X[1]], v.array[y + 5] = Q[X[2]], v.array[y + 6] = R[X[0]], v.array[y + 7] = R[X[1]], v.array[y + 8] = R[X[2]], y += 9; C = 0; for (T = va.length; C < T; C++) qa = R = Q = P = za = v.value[va[C]], v.array[y] = P[X[0]], v.array[y + 1] = P[X[1]], v.array[y + 2] = P[X[2]], v.array[y + 3] = Q[X[0]], v.array[y + 4] = Q[X[1]], v.array[y + 5] = Q[X[2]], v.array[y + 6] = R[X[0]], v.array[y + 7] = R[X[1]], v.array[y + 8] = R[X[2]], v.array[y + 9] = qa[X[0]], v.array[y + 10] = qa[X[1]], v.array[y + 11] = qa[X[2]], y += 12 } else if ("faceVertices" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) za = v.value[ua[C]], P = za[0], Q = za[1], R = za[2], v.array[y] = P[X[0]], v.array[y + 1] = P[X[1]], v.array[y + 2] = P[X[2]], v.array[y + 3] = Q[X[0]], v.array[y + 4] = Q[X[1]], v.array[y + 5] = Q[X[2]], v.array[y + 6] = R[X[0]], v.array[y + 7] = R[X[1]], v.array[y + 8] = R[X[2]], y += 9; C = 0; for (T = va.length; C < T; C++) za = v.value[va[C]], P = za[0], Q = za[1], R = za[2], qa = za[3], v.array[y] = P[X[0]], v.array[y + 1] = P[X[1]], v.array[y + 2] = P[X[2]], v.array[y + 3] = Q[X[0]], v.array[y + 4] = Q[X[1]], v.array[y + 5] = Q[X[2]], v.array[y + 6] = R[X[0]], v.array[y + 7] = R[X[1]], v.array[y + 8] = R[X[2]], v.array[y + 9] = qa[X[0]], v.array[y + 10] = qa[X[1]], v.array[y + 11] = qa[X[2]], y += 12 } } else if (4 === v.size) if (void 0 === v.boundTo || "vertices" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) O = ib[ua[C]], P = v.value[O.a], Q = v.value[O.b], R = v.value[O.c], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = P.z, v.array[y + 3] = P.w, v.array[y + 4] = Q.x, v.array[y + 5] = Q.y, v.array[y + 6] = Q.z, v.array[y + 7] = Q.w, v.array[y + 8] = R.x, v.array[y + 9] = R.y, v.array[y + 10] = R.z, v.array[y + 11] = R.w, y += 12; C = 0; for (T = va.length; C < T; C++) O = ib[va[C]], P = v.value[O.a], Q = v.value[O.b], R = v.value[O.c], qa = v.value[O.d], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = P.z, v.array[y + 3] = P.w, v.array[y + 4] = Q.x, v.array[y + 5] = Q.y, v.array[y + 6] = Q.z, v.array[y + 7] = Q.w, v.array[y + 8] = R.x, v.array[y + 9] = R.y, v.array[y + 10] = R.z, v.array[y + 11] = R.w, v.array[y + 12] = qa.x, v.array[y + 13] = qa.y, v.array[y + 14] = qa.z, v.array[y + 15] = qa.w, y += 16 } else if ("faces" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) R = Q = P = za = v.value[ua[C]], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = P.z, v.array[y + 3] = P.w, v.array[y + 4] = Q.x, v.array[y + 5] = Q.y, v.array[y + 6] = Q.z, v.array[y + 7] = Q.w, v.array[y + 8] = R.x, v.array[y + 9] = R.y, v.array[y + 10] = R.z, v.array[y + 11] = R.w, y += 12; C = 0; for (T = va.length; C < T; C++) qa = R = Q = P = za = v.value[va[C]], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = P.z, v.array[y + 3] = P.w, v.array[y + 4] = Q.x, v.array[y + 5] = Q.y, v.array[y + 6] = Q.z, v.array[y + 7] = Q.w, v.array[y + 8] = R.x, v.array[y + 9] = R.y, v.array[y + 10] = R.z, v.array[y + 11] = R.w, v.array[y + 12] = qa.x, v.array[y + 13] = qa.y, v.array[y + 14] = qa.z, v.array[y + 15] = qa.w, y += 16 } else if ("faceVertices" === v.boundTo) { C = 0; for (T = ua.length; C < T; C++) za = v.value[ua[C]], P = za[0], Q = za[1], R = za[2], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = P.z, v.array[y + 3] = P.w, v.array[y + 4] = Q.x, v.array[y + 5] = Q.y, v.array[y + 6] = Q.z, v.array[y + 7] = Q.w, v.array[y + 8] = R.x, v.array[y + 9] = R.y, v.array[y + 10] = R.z, v.array[y + 11] = R.w, y += 12; C = 0; for (T = va.length; C < T; C++) za = v.value[va[C]], P = za[0], Q = za[1], R = za[2], qa = za[3], v.array[y] = P.x, v.array[y + 1] = P.y, v.array[y + 2] = P.z, v.array[y + 3] = P.w, v.array[y + 4] = Q.x, v.array[y + 5] = Q.y, v.array[y + 6] = Q.z, v.array[y + 7] = Q.w, v.array[y + 8] = R.x, v.array[y + 9] = R.y, v.array[y + 10] = R.z, v.array[y + 11] = R.w, v.array[y + 12] = qa.x, v.array[y + 13] = qa.y, v.array[y + 14] = qa.z, v.array[y + 15] = qa.w, y += 16 } j.bindBuffer(j.ARRAY_BUFFER, v.buffer); j.bufferData(j.ARRAY_BUFFER, v.array, Ga) } } Hb && (delete sa.__inittedArrays, delete sa.__colorArray, delete sa.__normalArray, delete sa.__tangentArray, delete sa.__uvArray, delete sa.__uv2Array, delete sa.__faceArray, delete sa.__vertexArray, delete sa.__lineArray, delete sa.__skinIndexArray, delete sa.__skinWeightArray) } } la.verticesNeedUpdate = !1; la.morphTargetsNeedUpdate = !1; la.elementsNeedUpdate = !1; la.uvsNeedUpdate = !1; la.normalsNeedUpdate = !1; la.colorsNeedUpdate = !1; la.tangentsNeedUpdate = !1; la.buffersNeedUpdate = !1; na.attributes && q(na) } else if (ma instanceof THREE.Ribbon) { na = e(ma, la); xa = na.attributes && n(na); if (la.verticesNeedUpdate || la.colorsNeedUpdate || la.normalsNeedUpdate || xa) { var Eb = la, ad = j.DYNAMIC_DRAW, Pc = void 0, Qc = void 0, Rc = void 0, bd = void 0, Aa = void 0, cd = void 0, dd = void 0, ed = void 0, Cd = void 0, bb = void 0, Gc = void 0, Ea = void 0, rb = void 0, Dd = Eb.vertices, Ed = Eb.colors, Fd = Eb.normals, Od = Dd.length, Pd = Ed.length, Qd = Fd.length, fd = Eb.__vertexArray, gd = Eb.__colorArray, hd = Eb.__normalArray, Rd = Eb.colorsNeedUpdate, Sd = Eb.normalsNeedUpdate, wd = Eb.__webglCustomAttributesList; if (Eb.verticesNeedUpdate) { for (Pc = 0; Pc < Od; Pc++) bd = Dd[Pc], Aa = 3 * Pc, fd[Aa] = bd.x, fd[Aa + 1] = bd.y, fd[Aa + 2] = bd.z; j.bindBuffer(j.ARRAY_BUFFER, Eb.__webglVertexBuffer); j.bufferData(j.ARRAY_BUFFER, fd, ad) } if (Rd) { for (Qc = 0; Qc < Pd; Qc++) cd = Ed[Qc], Aa = 3 * Qc, gd[Aa] = cd.r, gd[Aa + 1] = cd.g, gd[Aa + 2] = cd.b; j.bindBuffer(j.ARRAY_BUFFER, Eb.__webglColorBuffer); j.bufferData(j.ARRAY_BUFFER, gd, ad) } if (Sd) { for (Rc = 0; Rc < Qd; Rc++) dd = Fd[Rc], Aa = 3 * Rc, hd[Aa] = dd.x, hd[Aa + 1] = dd.y, hd[Aa + 2] = dd.z; j.bindBuffer(j.ARRAY_BUFFER, Eb.__webglNormalBuffer); j.bufferData(j.ARRAY_BUFFER, hd, ad) } if (wd) { ed = 0; for (Cd = wd.length; ed < Cd; ed++) if (Ea = wd[ed], Ea.needsUpdate && (void 0 === Ea.boundTo || "vertices" === Ea.boundTo)) { Aa = 0; Gc = Ea.value.length; if (1 === Ea.size) for (bb = 0; bb < Gc; bb++) Ea.array[bb] = Ea.value[bb]; else if (2 === Ea.size) for (bb = 0; bb < Gc; bb++) rb = Ea.value[bb], Ea.array[Aa] = rb.x, Ea.array[Aa + 1] = rb.y, Aa += 2; else if (3 === Ea.size) if ("c" === Ea.type) for (bb = 0; bb < Gc; bb++) rb = Ea.value[bb], Ea.array[Aa] = rb.r, Ea.array[Aa + 1] = rb.g, Ea.array[Aa + 2] = rb.b, Aa += 3; else for (bb = 0; bb < Gc; bb++) rb = Ea.value[bb], Ea.array[Aa] = rb.x, Ea.array[Aa + 1] = rb.y, Ea.array[Aa + 2] = rb.z, Aa += 3; else if (4 === Ea.size) for (bb = 0; bb < Gc; bb++) rb = Ea.value[bb], Ea.array[Aa] = rb.x, Ea.array[Aa + 1] = rb.y, Ea.array[Aa + 2] = rb.z, Ea.array[Aa + 3] = rb.w, Aa += 4; j.bindBuffer(j.ARRAY_BUFFER, Ea.buffer); j.bufferData(j.ARRAY_BUFFER, Ea.array, ad) } } } la.verticesNeedUpdate = !1; la.colorsNeedUpdate = !1; la.normalsNeedUpdate = !1; na.attributes && q(na) } else if (ma instanceof THREE.Line) { na = e(ma, la); xa = na.attributes && n(na); if (la.verticesNeedUpdate || la.colorsNeedUpdate || la.lineDistancesNeedUpdate || xa) { var Fb = la, id = j.DYNAMIC_DRAW, Sc = void 0, Tc = void 0, Uc = void 0, jd = void 0, Ka = void 0, kd = void 0, Gd = Fb.vertices, Hd = Fb.colors, Id = Fb.lineDistances, Td = Gd.length, Ud = Hd.length, Vd = Id.length, ld = Fb.__vertexArray, md = Fb.__colorArray, Jd = Fb.__lineDistanceArray, Wd = Fb.colorsNeedUpdate, Xd = Fb.lineDistancesNeedUpdate, xd = Fb.__webglCustomAttributesList, nd = void 0, Kd = void 0, cb = void 0, Hc = void 0, sb = void 0, Fa = void 0; if (Fb.verticesNeedUpdate) { for (Sc = 0; Sc < Td; Sc++) jd = Gd[Sc], Ka = 3 * Sc, ld[Ka] = jd.x, ld[Ka + 1] = jd.y, ld[Ka + 2] = jd.z; j.bindBuffer(j.ARRAY_BUFFER, Fb.__webglVertexBuffer); j.bufferData(j.ARRAY_BUFFER, ld, id) } if (Wd) { for (Tc = 0; Tc < Ud; Tc++) kd = Hd[Tc], Ka = 3 * Tc, md[Ka] = kd.r, md[Ka + 1] = kd.g, md[Ka + 2] = kd.b; j.bindBuffer(j.ARRAY_BUFFER, Fb.__webglColorBuffer); j.bufferData(j.ARRAY_BUFFER, md, id) } if (Xd) { for (Uc = 0; Uc < Vd; Uc++) Jd[Uc] = Id[Uc]; j.bindBuffer(j.ARRAY_BUFFER, Fb.__webglLineDistanceBuffer); j.bufferData(j.ARRAY_BUFFER, Jd, id) } if (xd) { nd = 0; for (Kd = xd.length; nd < Kd; nd++) if (Fa = xd[nd], Fa.needsUpdate && (void 0 === Fa.boundTo || "vertices" === Fa.boundTo)) { Ka = 0; Hc = Fa.value.length; if (1 === Fa.size) for (cb = 0; cb < Hc; cb++) Fa.array[cb] = Fa.value[cb]; else if (2 === Fa.size) for (cb = 0; cb < Hc; cb++) sb = Fa.value[cb], Fa.array[Ka] = sb.x, Fa.array[Ka + 1] = sb.y, Ka += 2; else if (3 === Fa.size) if ("c" === Fa.type) for (cb = 0; cb < Hc; cb++) sb = Fa.value[cb], Fa.array[Ka] = sb.r, Fa.array[Ka + 1] = sb.g, Fa.array[Ka + 2] = sb.b, Ka += 3; else for (cb = 0; cb < Hc; cb++) sb = Fa.value[cb], Fa.array[Ka] = sb.x, Fa.array[Ka + 1] = sb.y, Fa.array[Ka + 2] = sb.z, Ka += 3; else if (4 === Fa.size) for (cb = 0; cb < Hc; cb++) sb = Fa.value[cb], Fa.array[Ka] = sb.x, Fa.array[Ka + 1] = sb.y, Fa.array[Ka + 2] = sb.z, Fa.array[Ka + 3] = sb.w, Ka += 4; j.bindBuffer(j.ARRAY_BUFFER, Fa.buffer); j.bufferData(j.ARRAY_BUFFER, Fa.array, id) } } } la.verticesNeedUpdate = !1; la.colorsNeedUpdate = !1; la.lineDistancesNeedUpdate = !1; na.attributes && q(na) } else if (ma instanceof THREE.ParticleSystem) { na = e(ma, la); xa = na.attributes && n(na); if (la.verticesNeedUpdate || la.colorsNeedUpdate || ma.sortParticles || xa) { var fc = la, yd = j.DYNAMIC_DRAW, Vc = ma, tb = void 0, gc = void 0, hc = void 0, da = void 0, ic = void 0, vc = void 0, od = fc.vertices, zd = od.length, Ad = fc.colors, Ld = Ad.length, zc = fc.__vertexArray, Ac = fc.__colorArray, nc = fc.__sortArray, Md = fc.verticesNeedUpdate, Nd = fc.colorsNeedUpdate, oc = fc.__webglCustomAttributesList, Kb = void 0, Ic = void 0, pa = void 0, Lb = void 0, Da = void 0, ba = void 0; if (Vc.sortParticles) { Va.copy(Qa); Va.multiply(Vc.matrixWorld); for (tb = 0; tb < zd; tb++) hc = od[tb], wa.copy(hc), wa.applyProjection(Va), nc[tb] = [wa.z, tb]; nc.sort(l); for (tb = 0; tb < zd; tb++) hc = od[nc[tb][1]], da = 3 * tb, zc[da] = hc.x, zc[da + 1] = hc.y, zc[da + 2] = hc.z; for (gc = 0; gc < Ld; gc++) da = 3 * gc, vc = Ad[nc[gc][1]], Ac[da] = vc.r, Ac[da + 1] = vc.g, Ac[da + 2] = vc.b; if (oc) { Kb = 0; for (Ic = oc.length; Kb < Ic; Kb++) if (ba = oc[Kb], void 0 === ba.boundTo || "vertices" === ba.boundTo) if (da = 0, Lb = ba.value.length, 1 === ba.size) for (pa = 0; pa < Lb; pa++) ic = nc[pa][1], ba.array[pa] = ba.value[ic]; else if (2 === ba.size) for (pa = 0; pa < Lb; pa++) ic = nc[pa][1], Da = ba.value[ic], ba.array[da] = Da.x, ba.array[da + 1] = Da.y, da += 2; else if (3 === ba.size) if ("c" === ba.type) for (pa = 0; pa < Lb; pa++) ic = nc[pa][1], Da = ba.value[ic], ba.array[da] = Da.r, ba.array[da + 1] = Da.g, ba.array[da + 2] = Da.b, da += 3; else for (pa = 0; pa < Lb; pa++) ic = nc[pa][1], Da = ba.value[ic], ba.array[da] = Da.x, ba.array[da + 1] = Da.y, ba.array[da + 2] = Da.z, da += 3; else if (4 === ba.size) for (pa = 0; pa < Lb; pa++) ic = nc[pa][1], Da = ba.value[ic], ba.array[da] = Da.x, ba.array[da + 1] = Da.y, ba.array[da + 2] = Da.z, ba.array[da + 3] = Da.w, da += 4 } } else { if (Md) for (tb = 0; tb < zd; tb++) hc = od[tb], da = 3 * tb, zc[da] = hc.x, zc[da + 1] = hc.y, zc[da + 2] = hc.z; if (Nd) for (gc = 0; gc < Ld; gc++) vc = Ad[gc], da = 3 * gc, Ac[da] = vc.r, Ac[da + 1] = vc.g, Ac[da + 2] = vc.b; if (oc) { Kb = 0; for (Ic = oc.length; Kb < Ic; Kb++) if (ba = oc[Kb], ba.needsUpdate && (void 0 === ba.boundTo || "vertices" === ba.boundTo)) if (Lb = ba.value.length, da = 0, 1 === ba.size) for (pa = 0; pa < Lb; pa++) ba.array[pa] = ba.value[pa]; else if (2 === ba.size) for (pa = 0; pa < Lb; pa++) Da = ba.value[pa], ba.array[da] = Da.x, ba.array[da + 1] = Da.y, da += 2; else if (3 === ba.size) if ("c" === ba.type) for (pa = 0; pa < Lb; pa++) Da = ba.value[pa], ba.array[da] = Da.r, ba.array[da + 1] = Da.g, ba.array[da + 2] = Da.b, da += 3; else for (pa = 0; pa < Lb; pa++) Da = ba.value[pa], ba.array[da] = Da.x, ba.array[da + 1] = Da.y, ba.array[da + 2] = Da.z, da += 3; else if (4 === ba.size) for (pa = 0; pa < Lb; pa++) Da = ba.value[pa], ba.array[da] = Da.x, ba.array[da + 1] = Da.y, ba.array[da + 2] = Da.z, ba.array[da + 3] = Da.w, da += 4 } } if (Md || Vc.sortParticles) j.bindBuffer(j.ARRAY_BUFFER, fc.__webglVertexBuffer), j.bufferData(j.ARRAY_BUFFER, zc, yd); if (Nd || Vc.sortParticles) j.bindBuffer(j.ARRAY_BUFFER, fc.__webglColorBuffer), j.bufferData(j.ARRAY_BUFFER, Ac, yd); if (oc) { Kb = 0; for (Ic = oc.length; Kb < Ic; Kb++) if (ba = oc[Kb], ba.needsUpdate || Vc.sortParticles) j.bindBuffer(j.ARRAY_BUFFER, ba.buffer), j.bufferData(j.ARRAY_BUFFER, ba.array, yd) } } la.verticesNeedUpdate = !1; la.colorsNeedUpdate = !1; na.attributes && q(na) } } }; this.initMaterial = function (a, b, c, d) { var e, f, g, h; a.addEventListener("dispose", Xc); var i, k, l, m, p; a instanceof THREE.MeshDepthMaterial ? p = "depth" : a instanceof THREE.MeshNormalMaterial ? p = "normal" : a instanceof THREE.MeshBasicMaterial ? p = "basic" : a instanceof THREE.MeshLambertMaterial ? p = "lambert" : a instanceof THREE.MeshPhongMaterial ? p = "phong" : a instanceof THREE.LineBasicMaterial ? p = "basic" : a instanceof THREE.LineDashedMaterial ? p = "dashed" : a instanceof THREE.ParticleBasicMaterial && (p = "particle_basic"); if (p) { var n = THREE.ShaderLib[p]; a.uniforms = THREE.UniformsUtils.clone(n.uniforms); a.vertexShader = n.vertexShader; a.fragmentShader = n.fragmentShader } var q, s, r; e = g = s = r = n = 0; for (f = b.length; e < f; e++) q = b[e], q.onlyShadow || (q instanceof THREE.DirectionalLight && g++, q instanceof THREE.PointLight && s++, q instanceof THREE.SpotLight && r++, q instanceof THREE.HemisphereLight && n++); e = g; f = s; g = r; h = n; n = q = 0; for (r = b.length; n < r; n++) s = b[n], s.castShadow && (s instanceof THREE.SpotLight && q++, s instanceof THREE.DirectionalLight && !s.shadowCascade && q++); m = q; Cc && d && d.useVertexTexture ? l = 1024 : (b = j.getParameter(j.MAX_VERTEX_UNIFORM_VECTORS), b = Math.floor((b - 20) / 4), void 0 !== d && d instanceof THREE.SkinnedMesh && (b = Math.min(d.bones.length, b), b < d.bones.length && console.warn("WebGLRenderer: too many bones - " + d.bones.length + ", this GPU supports just " + b + " (try OpenGL instead of ANGLE)")), l = b); a:{ s = a.fragmentShader; r = a.vertexShader; n = a.uniforms; b = a.attributes; q = a.defines; var c = { map: !!a.map, envMap: !!a.envMap, lightMap: !!a.lightMap, bumpMap: !!a.bumpMap, normalMap: !!a.normalMap, specularMap: !!a.specularMap, vertexColors: a.vertexColors, fog: c, useFog: a.fog, fogExp: c instanceof THREE.FogExp2, sizeAttenuation: a.sizeAttenuation, skinning: a.skinning, maxBones: l, useVertexTexture: Cc && d && d.useVertexTexture, boneTextureWidth: d && d.boneTextureWidth, boneTextureHeight: d && d.boneTextureHeight, morphTargets: a.morphTargets, morphNormals: a.morphNormals, maxMorphTargets: this.maxMorphTargets, maxMorphNormals: this.maxMorphNormals, maxDirLights: e, maxPointLights: f, maxSpotLights: g, maxHemiLights: h, maxShadows: m, shadowMapEnabled: this.shadowMapEnabled && d.receiveShadow, shadowMapType: this.shadowMapType, shadowMapDebug: this.shadowMapDebug, shadowMapCascade: this.shadowMapCascade, alphaTest: a.alphaTest, metal: a.metal, perPixel: a.perPixel, wrapAround: a.wrapAround, doubleSided: a.side === THREE.DoubleSide, flipSided: a.side === THREE.BackSide }, t, u, x, d = []; p ? d.push(p) : (d.push(s), d.push(r)); for (u in q) d.push(u), d.push(q[u]); for (t in c) d.push(t), d.push(c[t]); p = d.join(); t = 0; for (u = ca.length; t < u; t++) if (d = ca[t], d.code === p) { d.usedTimes++; k = d.program; break a } t = "SHADOWMAP_TYPE_BASIC"; c.shadowMapType === THREE.PCFShadowMap ? t = "SHADOWMAP_TYPE_PCF" : c.shadowMapType === THREE.PCFSoftShadowMap && (t = "SHADOWMAP_TYPE_PCF_SOFT"); u = []; for (x in q) d = q[x], !1 !== d && (d = "#define " + x + " " + d, u.push(d)); d = u.join("\n"); x = j.createProgram(); u = ["precision " + K + " float;", d, Bc ? "#define VERTEX_TEXTURES" : "", L.gammaInput ? "#define GAMMA_INPUT" : "", L.gammaOutput ? "#define GAMMA_OUTPUT" : "", L.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "", "#define MAX_DIR_LIGHTS " + c.maxDirLights, "#define MAX_POINT_LIGHTS " + c.maxPointLights, "#define MAX_SPOT_LIGHTS " + c.maxSpotLights, "#define MAX_HEMI_LIGHTS " + c.maxHemiLights, "#define MAX_SHADOWS " + c.maxShadows, "#define MAX_BONES " + c.maxBones, c.map ? "#define USE_MAP" : "", c.envMap ? "#define USE_ENVMAP" : "", c.lightMap ? "#define USE_LIGHTMAP" : "", c.bumpMap ? "#define USE_BUMPMAP" : "", c.normalMap ? "#define USE_NORMALMAP" : "", c.specularMap ? "#define USE_SPECULARMAP" : "", c.vertexColors ? "#define USE_COLOR" : "", c.skinning ? "#define USE_SKINNING" : "", c.useVertexTexture ? "#define BONE_TEXTURE" : "", c.boneTextureWidth ? "#define N_BONE_PIXEL_X " + c.boneTextureWidth.toFixed(1) : "", c.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + c.boneTextureHeight.toFixed(1) : "", c.morphTargets ? "#define USE_MORPHTARGETS" : "", c.morphNormals ? "#define USE_MORPHNORMALS" : "", c.perPixel ? "#define PHONG_PER_PIXEL" : "", c.wrapAround ? "#define WRAP_AROUND" : "", c.doubleSided ? "#define DOUBLE_SIDED" : "", c.flipSided ? "#define FLIP_SIDED" : "", c.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", c.shadowMapEnabled ? "#define " + t : "", c.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "", c.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "", c.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "", "uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n"); t = ["precision " + K + " float;", c.bumpMap || c.normalMap ? "#extension GL_OES_standard_derivatives : enable" : "", d, "#define MAX_DIR_LIGHTS " + c.maxDirLights, "#define MAX_POINT_LIGHTS " + c.maxPointLights, "#define MAX_SPOT_LIGHTS " + c.maxSpotLights, "#define MAX_HEMI_LIGHTS " + c.maxHemiLights, "#define MAX_SHADOWS " + c.maxShadows, c.alphaTest ? "#define ALPHATEST " + c.alphaTest : "", L.gammaInput ? "#define GAMMA_INPUT" : "", L.gammaOutput ? "#define GAMMA_OUTPUT" : "", L.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "", c.useFog && c.fog ? "#define USE_FOG" : "", c.useFog && c.fogExp ? "#define FOG_EXP2" : "", c.map ? "#define USE_MAP" : "", c.envMap ? "#define USE_ENVMAP" : "", c.lightMap ? "#define USE_LIGHTMAP" : "", c.bumpMap ? "#define USE_BUMPMAP" : "", c.normalMap ? "#define USE_NORMALMAP" : "", c.specularMap ? "#define USE_SPECULARMAP" : "", c.vertexColors ? "#define USE_COLOR" : "", c.metal ? "#define METAL" : "", c.perPixel ? "#define PHONG_PER_PIXEL" : "", c.wrapAround ? "#define WRAP_AROUND" : "", c.doubleSided ? "#define DOUBLE_SIDED" : "", c.flipSided ? "#define FLIP_SIDED" : "", c.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", c.shadowMapEnabled ? "#define " + t : "", c.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "", c.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "", "uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"); t = E("fragment", t + s); u = E("vertex", u + r); j.attachShader(x, u); j.attachShader(x, t); j.linkProgram(x); j.getProgramParameter(x, j.LINK_STATUS) || console.error("Could not initialise shader\nVALIDATE_STATUS: " + j.getProgramParameter(x, j.VALIDATE_STATUS) + ", gl error [" + j.getError() + "]"); j.deleteShader(t); j.deleteShader(u); x.uniforms = {}; x.attributes = {}; var w; t = "viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences".split(" "); c.useVertexTexture ? t.push("boneTexture") : t.push("boneGlobalMatrices"); for (w in n) t.push(w); w = t; t = 0; for (u = w.length; t < u; t++) n = w[t], x.uniforms[n] = j.getUniformLocation(x, n); t = "position normal uv uv2 tangent color skinIndex skinWeight lineDistance".split(" "); for (w = 0; w < c.maxMorphTargets; w++) t.push("morphTarget" + w); for (w = 0; w < c.maxMorphNormals; w++) t.push("morphNormal" + w); for (k in b) t.push(k); k = t; w = 0; for (b = k.length; w < b; w++) t = k[w], x.attributes[t] = j.getAttribLocation(x, t); x.id = ta++; ca.push({program: x, code: p, usedTimes: 1}); L.info.memory.programs = ca.length; k = x } a.program = k; w = a.program.attributes; if (a.morphTargets) { a.numSupportedMorphTargets = 0; b = "morphTarget"; for (k = 0; k < this.maxMorphTargets; k++) x = b + k, 0 <= w[x] && a.numSupportedMorphTargets++ } if (a.morphNormals) { a.numSupportedMorphNormals = 0; b = "morphNormal"; for (k = 0; k < this.maxMorphNormals; k++) x = b + k, 0 <= w[x] && a.numSupportedMorphNormals++ } a.uniformsList = []; for (i in a.uniforms) a.uniformsList.push([a.uniforms[i], i]) }; this.setFaceCulling = function (a, b) { a === THREE.CullFaceNone ? j.disable(j.CULL_FACE) : (b === THREE.FrontFaceDirectionCW ? j.frontFace(j.CW) : j.frontFace(j.CCW), a === THREE.CullFaceBack ? j.cullFace(j.BACK) : a === THREE.CullFaceFront ? j.cullFace(j.FRONT) : j.cullFace(j.FRONT_AND_BACK), j.enable(j.CULL_FACE)) }; this.setMaterialFaces = function (a) { var b = a.side === THREE.DoubleSide, a = a.side === THREE.BackSide; ha !== b && (b ? j.disable(j.CULL_FACE) : j.enable(j.CULL_FACE), ha = b); V !== a && (a ? j.frontFace(j.CW) : j.frontFace(j.CCW), V = a) }; this.setDepthTest = function (a) { na !== a && (a ? j.enable(j.DEPTH_TEST) : j.disable(j.DEPTH_TEST), na = a) }; this.setDepthWrite = function (a) { Pa !== a && (j.depthMask(a), Pa = a) }; this.setBlending = function (a, b, c, d) { a !== $ && (a === THREE.NoBlending ? j.disable(j.BLEND) : a === THREE.AdditiveBlending ? (j.enable(j.BLEND), j.blendEquation(j.FUNC_ADD), j.blendFunc(j.SRC_ALPHA, j.ONE)) : a === THREE.SubtractiveBlending ? (j.enable(j.BLEND), j.blendEquation(j.FUNC_ADD), j.blendFunc(j.ZERO, j.ONE_MINUS_SRC_COLOR)) : a === THREE.MultiplyBlending ? (j.enable(j.BLEND), j.blendEquation(j.FUNC_ADD), j.blendFunc(j.ZERO, j.SRC_COLOR)) : a === THREE.CustomBlending ? j.enable(j.BLEND) : (j.enable(j.BLEND), j.blendEquationSeparate(j.FUNC_ADD, j.FUNC_ADD), j.blendFuncSeparate(j.SRC_ALPHA, j.ONE_MINUS_SRC_ALPHA, j.ONE, j.ONE_MINUS_SRC_ALPHA)), $ = a); if (a === THREE.CustomBlending) { if (b !== Y && (j.blendEquation(F(b)), Y = b), c !== ia || d !== ra) j.blendFunc(F(c), F(d)), ia = c, ra = d } else ra = ia = Y = null }; this.setTexture = function (a, b) { if (a.needsUpdate) { a.__webglInit || (a.__webglInit = !0, a.addEventListener("dispose", Zc), a.__webglTexture = j.createTexture(), L.info.memory.textures++); j.activeTexture(j.TEXTURE0 + b); j.bindTexture(j.TEXTURE_2D, a.__webglTexture); j.pixelStorei(j.UNPACK_FLIP_Y_WEBGL, a.flipY); j.pixelStorei(j.UNPACK_PREMULTIPLY_ALPHA_WEBGL, a.premultiplyAlpha); j.pixelStorei(j.UNPACK_ALIGNMENT, a.unpackAlignment); var c = a.image, d = 0 === (c.width & c.width - 1) && 0 === (c.height & c.height - 1), e = F(a.format), f = F(a.type); Z(j.TEXTURE_2D, a, d); var g = a.mipmaps; if (a instanceof THREE.DataTexture) if (0 < g.length && d) { for (var h = 0, i = g.length; h < i; h++) c = g[h], j.texImage2D(j.TEXTURE_2D, h, e, c.width, c.height, 0, e, f, c.data); a.generateMipmaps = !1 } else j.texImage2D(j.TEXTURE_2D, 0, e, c.width, c.height, 0, e, f, c.data); else if (a instanceof THREE.CompressedTexture) { h = 0; for (i = g.length; h < i; h++) c = g[h], j.compressedTexImage2D(j.TEXTURE_2D, h, e, c.width, c.height, 0, c.data) } else if (0 < g.length && d) { h = 0; for (i = g.length; h < i; h++) c = g[h], j.texImage2D(j.TEXTURE_2D, h, e, e, f, c); a.generateMipmaps = !1 } else j.texImage2D(j.TEXTURE_2D, 0, e, e, f, a.image); a.generateMipmaps && d && j.generateMipmap(j.TEXTURE_2D); a.needsUpdate = !1; if (a.onUpdate) a.onUpdate() } else j.activeTexture(j.TEXTURE0 + b), j.bindTexture(j.TEXTURE_2D, a.__webglTexture) }; this.setRenderTarget = function (a) { var b = a instanceof THREE.WebGLRenderTargetCube; if (a && !a.__webglFramebuffer) { void 0 === a.depthBuffer && (a.depthBuffer = !0); void 0 === a.stencilBuffer && (a.stencilBuffer = !0); a.addEventListener("dispose", Jc); a.__webglTexture = j.createTexture(); L.info.memory.textures++; var c = 0 === (a.width & a.width - 1) && 0 === (a.height & a.height - 1), d = F(a.format), e = F(a.type); if (b) { a.__webglFramebuffer = []; a.__webglRenderbuffer = []; j.bindTexture(j.TEXTURE_CUBE_MAP, a.__webglTexture); Z(j.TEXTURE_CUBE_MAP, a, c); for (var f = 0; 6 > f; f++) { a.__webglFramebuffer[f] = j.createFramebuffer(); a.__webglRenderbuffer[f] = j.createRenderbuffer(); j.texImage2D(j.TEXTURE_CUBE_MAP_POSITIVE_X + f, 0, d, a.width, a.height, 0, d, e, null); var g = a, h = j.TEXTURE_CUBE_MAP_POSITIVE_X + f; j.bindFramebuffer(j.FRAMEBUFFER, a.__webglFramebuffer[f]); j.framebufferTexture2D(j.FRAMEBUFFER, j.COLOR_ATTACHMENT0, h, g.__webglTexture, 0); A(a.__webglRenderbuffer[f], a) } c && j.generateMipmap(j.TEXTURE_CUBE_MAP) } else a.__webglFramebuffer = j.createFramebuffer(), a.__webglRenderbuffer = a.shareDepthFrom ? a.shareDepthFrom.__webglRenderbuffer : j.createRenderbuffer(), j.bindTexture(j.TEXTURE_2D, a.__webglTexture), Z(j.TEXTURE_2D, a, c), j.texImage2D(j.TEXTURE_2D, 0, d, a.width, a.height, 0, d, e, null), d = j.TEXTURE_2D, j.bindFramebuffer(j.FRAMEBUFFER, a.__webglFramebuffer), j.framebufferTexture2D(j.FRAMEBUFFER, j.COLOR_ATTACHMENT0, d, a.__webglTexture, 0), a.shareDepthFrom ? a.depthBuffer && !a.stencilBuffer ? j.framebufferRenderbuffer(j.FRAMEBUFFER, j.DEPTH_ATTACHMENT, j.RENDERBUFFER, a.__webglRenderbuffer) : a.depthBuffer && a.stencilBuffer && j.framebufferRenderbuffer(j.FRAMEBUFFER, j.DEPTH_STENCIL_ATTACHMENT, j.RENDERBUFFER, a.__webglRenderbuffer) : A(a.__webglRenderbuffer, a), c && j.generateMipmap(j.TEXTURE_2D); b ? j.bindTexture(j.TEXTURE_CUBE_MAP, null) : j.bindTexture(j.TEXTURE_2D, null); j.bindRenderbuffer(j.RENDERBUFFER, null); j.bindFramebuffer(j.FRAMEBUFFER, null) } a ? (b = b ? a.__webglFramebuffer[a.activeCubeFace] : a.__webglFramebuffer, c = a.width, a = a.height, e = d = 0) : (b = null, c = Mb, a = wb, d = ob, e = Gb); b !== $a && (j.bindFramebuffer(j.FRAMEBUFFER, b), j.viewport(d, e, c, a), $a = b); Nb = c; Ob = a }; this.shadowMapPlugin = new THREE.ShadowMapPlugin; this.addPrePlugin(this.shadowMapPlugin); this.addPostPlugin(new THREE.SpritePlugin); this.addPostPlugin(new THREE.LensFlarePlugin) }; THREE.WebGLRenderTarget = function (a, b, c) { THREE.EventDispatcher.call(this); this.width = a; this.height = b; c = c || {}; this.wrapS = void 0 !== c.wrapS ? c.wrapS : THREE.ClampToEdgeWrapping; this.wrapT = void 0 !== c.wrapT ? c.wrapT : THREE.ClampToEdgeWrapping; this.magFilter = void 0 !== c.magFilter ? c.magFilter : THREE.LinearFilter; this.minFilter = void 0 !== c.minFilter ? c.minFilter : THREE.LinearMipMapLinearFilter; this.anisotropy = void 0 !== c.anisotropy ? c.anisotropy : 1; this.offset = new THREE.Vector2(0, 0); this.repeat = new THREE.Vector2(1, 1); this.format = void 0 !== c.format ? c.format : THREE.RGBAFormat; this.type = void 0 !== c.type ? c.type : THREE.UnsignedByteType; this.depthBuffer = void 0 !== c.depthBuffer ? c.depthBuffer : !0; this.stencilBuffer = void 0 !== c.stencilBuffer ? c.stencilBuffer : !0; this.generateMipmaps = !0; this.shareDepthFrom = null }; THREE.WebGLRenderTarget.prototype.clone = function () { var a = new THREE.WebGLRenderTarget(this.width, this.height); a.wrapS = this.wrapS; a.wrapT = this.wrapT; a.magFilter = this.magFilter; a.minFilter = this.minFilter; a.anisotropy = this.anisotropy; a.offset.copy(this.offset); a.repeat.copy(this.repeat); a.format = this.format; a.type = this.type; a.depthBuffer = this.depthBuffer; a.stencilBuffer = this.stencilBuffer; a.generateMipmaps = this.generateMipmaps; a.shareDepthFrom = this.shareDepthFrom; return a }; THREE.WebGLRenderTarget.prototype.dispose = function () { this.dispatchEvent({type: "dispose"}) }; THREE.WebGLRenderTargetCube = function (a, b, c) { THREE.WebGLRenderTarget.call(this, a, b, c); this.activeCubeFace = 0 }; THREE.WebGLRenderTargetCube.prototype = Object.create(THREE.WebGLRenderTarget.prototype); THREE.RenderableVertex = function () { this.positionWorld = new THREE.Vector3; this.positionScreen = new THREE.Vector4; this.visible = !0 }; THREE.RenderableVertex.prototype.copy = function (a) { this.positionWorld.copy(a.positionWorld); this.positionScreen.copy(a.positionScreen) }; THREE.RenderableFace3 = function () { this.v1 = new THREE.RenderableVertex; this.v2 = new THREE.RenderableVertex; this.v3 = new THREE.RenderableVertex; this.centroidModel = new THREE.Vector3; this.normalModel = new THREE.Vector3; this.normalModelView = new THREE.Vector3; this.vertexNormalsLength = 0; this.vertexNormalsModel = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3]; this.vertexNormalsModelView = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3]; this.material = this.color = null; this.uvs = [[]]; this.z = null }; THREE.RenderableFace4 = function () { this.v1 = new THREE.RenderableVertex; this.v2 = new THREE.RenderableVertex; this.v3 = new THREE.RenderableVertex; this.v4 = new THREE.RenderableVertex; this.centroidModel = new THREE.Vector3; this.normalModel = new THREE.Vector3; this.normalModelView = new THREE.Vector3; this.vertexNormalsLength = 0; this.vertexNormalsModel = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3]; this.vertexNormalsModelView = [new THREE.Vector3, new THREE.Vector3, new THREE.Vector3, new THREE.Vector3]; this.material = this.color = null; this.uvs = [[]]; this.z = null }; THREE.RenderableObject = function () { this.z = this.object = null }; THREE.RenderableParticle = function () { this.rotation = this.z = this.y = this.x = this.object = null; this.scale = new THREE.Vector2; this.material = null }; THREE.RenderableLine = function () { this.z = null; this.v1 = new THREE.RenderableVertex; this.v2 = new THREE.RenderableVertex; this.material = null }; THREE.GeometryUtils = { merge: function (a, b) { var c, d, e = a.vertices.length, f = b instanceof THREE.Mesh ? b.geometry : b, g = a.vertices, h = f.vertices, i = a.faces, k = f.faces, l = a.faceVertexUvs[0], f = f.faceVertexUvs[0]; b instanceof THREE.Mesh && (b.matrixAutoUpdate && b.updateMatrix(), c = b.matrix, d = new THREE.Matrix3, d.getInverse(c), d.transpose()); for (var m = 0, p = h.length; m < p; m++) { var s = h[m].clone(); c && s.applyMatrix4(c); g.push(s) } m = 0; for (p = k.length; m < p; m++) { var s = k[m], r, n, q = s.vertexNormals, z = s.vertexColors; s instanceof THREE.Face3 ? r = new THREE.Face3(s.a + e, s.b + e, s.c + e) : s instanceof THREE.Face4 && (r = new THREE.Face4(s.a + e, s.b + e, s.c + e, s.d + e)); r.normal.copy(s.normal); d && r.normal.applyMatrix3(d).normalize(); g = 0; for (h = q.length; g < h; g++) n = q[g].clone(), d && n.applyMatrix3(d).normalize(), r.vertexNormals.push(n); r.color.copy(s.color); g = 0; for (h = z.length; g < h; g++) n = z[g], r.vertexColors.push(n.clone()); r.materialIndex = s.materialIndex; r.centroid.copy(s.centroid); c && r.centroid.applyMatrix4(c); i.push(r) } m = 0; for (p = f.length; m < p; m++) { c = f[m]; d = []; g = 0; for (h = c.length; g < h; g++) d.push(new THREE.Vector2(c[g].x, c[g].y)); l.push(d) } }, removeMaterials: function (a, b) { for (var c = {}, d = 0, e = b.length; d < e; d++) c[b[d]] = !0; for (var f, g = [], d = 0, e = a.faces.length; d < e; d++) f = a.faces[d], f.materialIndex in c || g.push(f); a.faces = g }, randomPointInTriangle: function (a, b, c) { var d, e, f, g = new THREE.Vector3, h = THREE.GeometryUtils.__v1; d = THREE.GeometryUtils.random(); e = THREE.GeometryUtils.random(); 1 < d + e && (d = 1 - d, e = 1 - e); f = 1 - d - e; g.copy(a); g.multiplyScalar(d); h.copy(b); h.multiplyScalar(e); g.add(h); h.copy(c); h.multiplyScalar(f); g.add(h); return g }, randomPointInFace: function (a, b, c) { var d, e, f; if (a instanceof THREE.Face3) return d = b.vertices[a.a], e = b.vertices[a.b], f = b.vertices[a.c], THREE.GeometryUtils.randomPointInTriangle(d, e, f); if (a instanceof THREE.Face4) { d = b.vertices[a.a]; e = b.vertices[a.b]; f = b.vertices[a.c]; var b = b.vertices[a.d], g; c ? a._area1 && a._area2 ? (c = a._area1, g = a._area2) : (c = THREE.GeometryUtils.triangleArea(d, e, b), g = THREE.GeometryUtils.triangleArea(e, f, b), a._area1 = c, a._area2 = g) : (c = THREE.GeometryUtils.triangleArea(d, e, b), g = THREE.GeometryUtils.triangleArea(e, f, b)); return THREE.GeometryUtils.random() * (c + g) < c ? THREE.GeometryUtils.randomPointInTriangle(d, e, b) : THREE.GeometryUtils.randomPointInTriangle(e, f, b) } }, randomPointsInGeometry: function (a, b) { function c(a) { function b(c, d) { if (d < c) return c; var e = c + Math.floor((d - c) / 2); return k[e] > a ? b(c, e - 1) : k[e] < a ? b(e + 1, d) : e } return b(0, k.length - 1) } var d, e, f = a.faces, g = a.vertices, h = f.length, i = 0, k = [], l, m, p, s; for (e = 0; e < h; e++) d = f[e], d instanceof THREE.Face3 ? (l = g[d.a], m = g[d.b], p = g[d.c], d._area = THREE.GeometryUtils.triangleArea(l, m, p)) : d instanceof THREE.Face4 && (l = g[d.a], m = g[d.b], p = g[d.c], s = g[d.d], d._area1 = THREE.GeometryUtils.triangleArea(l, m, s), d._area2 = THREE.GeometryUtils.triangleArea(m, p, s), d._area = d._area1 + d._area2), i += d._area, k[e] = i; d = []; for (e = 0; e < b; e++) g = THREE.GeometryUtils.random() * i, g = c(g), d[e] = THREE.GeometryUtils.randomPointInFace(f[g], a, !0); return d }, triangleArea: function (a, b, c) { var d = THREE.GeometryUtils.__v1, e = THREE.GeometryUtils.__v2; d.subVectors(b, a); e.subVectors(c, a); d.cross(e); return 0.5 * d.length() }, center: function (a) { a.computeBoundingBox(); var b = a.boundingBox, c = new THREE.Vector3; c.addVectors(b.min, b.max); c.multiplyScalar(-0.5); a.applyMatrix((new THREE.Matrix4).makeTranslation(c.x, c.y, c.z)); a.computeBoundingBox(); return c }, normalizeUVs: function (a) { for (var a = a.faceVertexUvs[0], b = 0, c = a.length; b < c; b++) for (var d = a[b], e = 0, f = d.length; e < f; e++) 1 !== d[e].x && (d[e].x -= Math.floor(d[e].x)), 1 !== d[e].y && (d[e].y -= Math.floor(d[e].y)) }, triangulateQuads: function (a) { var b, c, d, e, f = [], g = [], h = []; b = 0; for (c = a.faceUvs.length; b < c; b++) g[b] = []; b = 0; for (c = a.faceVertexUvs.length; b < c; b++) h[b] = []; b = 0; for (c = a.faces.length; b < c; b++) if (d = a.faces[b], d instanceof THREE.Face4) { e = d.a; var i = d.b, k = d.c, l = d.d, m = new THREE.Face3, p = new THREE.Face3; m.color.copy(d.color); p.color.copy(d.color); m.materialIndex = d.materialIndex; p.materialIndex = d.materialIndex; m.a = e; m.b = i; m.c = l; p.a = i; p.b = k; p.c = l; 4 === d.vertexColors.length && (m.vertexColors[0] = d.vertexColors[0].clone(), m.vertexColors[1] = d.vertexColors[1].clone(), m.vertexColors[2] = d.vertexColors[3].clone(), p.vertexColors[0] = d.vertexColors[1].clone(), p.vertexColors[1] = d.vertexColors[2].clone(), p.vertexColors[2] = d.vertexColors[3].clone()); f.push(m, p); d = 0; for (e = a.faceVertexUvs.length; d < e; d++) a.faceVertexUvs[d].length && (m = a.faceVertexUvs[d][b], i = m[1], k = m[2], l = m[3], m = [m[0].clone(), i.clone(), l.clone()], i = [i.clone(), k.clone(), l.clone()], h[d].push(m, i)); d = 0; for (e = a.faceUvs.length; d < e; d++) a.faceUvs[d].length && (i = a.faceUvs[d][b], g[d].push(i, i)) } else { f.push(d); d = 0; for (e = a.faceUvs.length; d < e; d++) g[d].push(a.faceUvs[d][b]); d = 0; for (e = a.faceVertexUvs.length; d < e; d++) h[d].push(a.faceVertexUvs[d][b]) } a.faces = f; a.faceUvs = g; a.faceVertexUvs = h; a.computeCentroids(); a.computeFaceNormals(); a.computeVertexNormals(); a.hasTangents && a.computeTangents() }, setMaterialIndex: function (a, b, c, d) { a = a.faces; d = d || a.length - 1; for (c = c || 0; c <= d; c++) a[c].materialIndex = b } }; THREE.GeometryUtils.random = THREE.Math.random16; THREE.GeometryUtils.__v1 = new THREE.Vector3; THREE.GeometryUtils.__v2 = new THREE.Vector3; THREE.ImageUtils = { crossOrigin: "anonymous", loadTexture: function (a, b, c, d) { var e = new Image, f = new THREE.Texture(e, b), b = new THREE.ImageLoader; b.addEventListener("load", function (a) { f.image = a.content; f.needsUpdate = !0; c && c(f) }); b.addEventListener("error", function (a) { d && d(a.message) }); b.crossOrigin = this.crossOrigin; b.load(a, e); f.sourceFile = a; return f }, loadCompressedTexture: function (a, b, c, d) { var e = new THREE.CompressedTexture; e.mapping = b; var f = new XMLHttpRequest; f.onload = function () { var a = THREE.ImageUtils.parseDDS(f.response, !0); e.format = a.format; e.mipmaps = a.mipmaps; e.image.width = a.width; e.image.height = a.height; e.generateMipmaps = !1; e.needsUpdate = !0; c && c(e) }; f.onerror = d; f.open("GET", a, !0); f.responseType = "arraybuffer"; f.send(null); return e }, loadTextureCube: function (a, b, c, d) { var e = []; e.loadCount = 0; var f = new THREE.Texture; f.image = e; void 0 !== b && (f.mapping = b); f.flipY = !1; for (var b = 0, g = a.length; b < g; ++b) { var h = new Image; e[b] = h; h.onload = function () { e.loadCount += 1; 6 === e.loadCount && (f.needsUpdate = !0, c && c(f)) }; h.onerror = d; h.crossOrigin = this.crossOrigin; h.src = a[b] } return f }, loadCompressedTextureCube: function (a, b, c, d) { var e = []; e.loadCount = 0; var f = new THREE.CompressedTexture; f.image = e; void 0 !== b && (f.mapping = b); f.flipY = !1; f.generateMipmaps = !1; b = function (a, b) { return function () { var d = THREE.ImageUtils.parseDDS(a.response, !0); b.format = d.format; b.mipmaps = d.mipmaps; b.width = d.width; b.height = d.height; e.loadCount += 1; 6 === e.loadCount && (f.format = d.format, f.needsUpdate = !0, c && c(f)) } }; if (a instanceof Array) for (var g = 0, h = a.length; g < h; ++g) { var i = {}; e[g] = i; var k = new XMLHttpRequest; k.onload = b(k, i); k.onerror = d; i = a[g]; k.open("GET", i, !0); k.responseType = "arraybuffer"; k.send(null) } else k = new XMLHttpRequest, k.onload = function () { var a = THREE.ImageUtils.parseDDS(k.response, !0); if (a.isCubemap) { for (var b = a.mipmaps.length / a.mipmapCount, d = 0; d < b; d++) { e[d] = {mipmaps: []}; for (var g = 0; g < a.mipmapCount; g++) e[d].mipmaps.push(a.mipmaps[d * a.mipmapCount + g]), e[d].format = a.format, e[d].width = a.width, e[d].height = a.height } f.format = a.format; f.needsUpdate = !0; c && c(f) } }, k.onerror = d, k.open("GET", a, !0), k.responseType = "arraybuffer", k.send(null); return f }, parseDDS: function (a, b) { function c(a) { return a.charCodeAt(0) + (a.charCodeAt(1) << 8) + (a.charCodeAt(2) << 16) + (a.charCodeAt(3) << 24) } var d = {mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1}, e = c("DXT1"), f = c("DXT3"), g = c("DXT5"), h = new Int32Array(a, 0, 31); if (542327876 !== h[0]) return console.error("ImageUtils.parseDDS(): Invalid magic number in DDS header"), d; if (!h[20] & 4) return console.error("ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code"), d; var i = h[21]; switch (i) { case e: e = 8; d.format = THREE.RGB_S3TC_DXT1_Format; break; case f: e = 16; d.format = THREE.RGBA_S3TC_DXT3_Format; break; case g: e = 16; d.format = THREE.RGBA_S3TC_DXT5_Format; break; default: return console.error("ImageUtils.parseDDS(): Unsupported FourCC code: ", String.fromCharCode(i & 255, i >> 8 & 255, i >> 16 & 255, i >> 24 & 255)), d } d.mipmapCount = 1; h[2] & 131072 && !1 !== b && (d.mipmapCount = Math.max(1, h[7])); d.isCubemap = h[28] & 512 ? !0 : !1; d.width = h[4]; d.height = h[3]; for (var h = h[1] + 4, f = d.width, g = d.height, i = d.isCubemap ? 6 : 1, k = 0; k < i; k++) { for (var l = 0; l < d.mipmapCount; l++) { var m = Math.max(4, f) / 4 * Math.max(4, g) / 4 * e, p = {data: new Uint8Array(a, h, m), width: f, height: g}; d.mipmaps.push(p); h += m; f = Math.max(0.5 * f, 1); g = Math.max(0.5 * g, 1) } f = d.width; g = d.height } return d }, getNormalMap: function (a, b) { var c = function (a) { var b = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); return [a[0] / b, a[1] / b, a[2] / b] }, b = b | 1, d = a.width, e = a.height, f = document.createElement("canvas"); f.width = d; f.height = e; var g = f.getContext("2d"); g.drawImage(a, 0, 0); for (var h = g.getImageData(0, 0, d, e).data, i = g.createImageData(d, e), k = i.data, l = 0; l < d; l++) for (var m = 0; m < e; m++) { var p = 0 > m - 1 ? 0 : m - 1, s = m + 1 > e - 1 ? e - 1 : m + 1, r = 0 > l - 1 ? 0 : l - 1, n = l + 1 > d - 1 ? d - 1 : l + 1, q = [], z = [0, 0, h[4 * (m * d + l)] / 255 * b]; q.push([-1, 0, h[4 * (m * d + r)] / 255 * b]); q.push([-1, -1, h[4 * (p * d + r)] / 255 * b]); q.push([0, -1, h[4 * (p * d + l)] / 255 * b]); q.push([1, -1, h[4 * (p * d + n)] / 255 * b]); q.push([1, 0, h[4 * (m * d + n)] / 255 * b]); q.push([1, 1, h[4 * (s * d + n)] / 255 * b]); q.push([0, 1, h[4 * (s * d + l)] / 255 * b]); q.push([-1, 1, h[4 * (s * d + r)] / 255 * b]); p = []; r = q.length; for (s = 0; s < r; s++) { var n = q[s], t = q[(s + 1) % r], n = [n[0] - z[0], n[1] - z[1], n[2] - z[2]], t = [t[0] - z[0], t[1] - z[1], t[2] - z[2]]; p.push(c([n[1] * t[2] - n[2] * t[1], n[2] * t[0] - n[0] * t[2], n[0] * t[1] - n[1] * t[0]])) } q = [0, 0, 0]; for (s = 0; s < p.length; s++) q[0] += p[s][0], q[1] += p[s][1], q[2] += p[s][2]; q[0] /= p.length; q[1] /= p.length; q[2] /= p.length; z = 4 * (m * d + l); k[z] = 255 * ((q[0] + 1) / 2) | 0; k[z + 1] = 255 * ((q[1] + 1) / 2) | 0; k[z + 2] = 255 * q[2] | 0; k[z + 3] = 255 } g.putImageData(i, 0, 0); return f }, generateDataTexture: function (a, b, c) { for (var d = a * b, e = new Uint8Array(3 * d), f = Math.floor(255 * c.r), g = Math.floor(255 * c.g), c = Math.floor(255 * c.b), h = 0; h < d; h++) e[3 * h] = f, e[3 * h + 1] = g, e[3 * h + 2] = c; a = new THREE.DataTexture(e, a, b, THREE.RGBFormat); a.needsUpdate = !0; return a } }; THREE.SceneUtils = { createMultiMaterialObject: function (a, b) { for (var c = new THREE.Object3D, d = 0, e = b.length; d < e; d++) c.add(new THREE.Mesh(a, b[d])); return c }, detach: function (a, b, c) { a.applyMatrix(b.matrixWorld); b.remove(a); c.add(a) }, attach: function (a, b, c) { var d = new THREE.Matrix4; d.getInverse(c.matrixWorld); a.applyMatrix(d); b.remove(a); c.add(a) } }; THREE.FontUtils = { faces: {}, face: "helvetiker", weight: "normal", style: "normal", size: 150, divisions: 10, getFace: function () { return this.faces[this.face][this.weight][this.style] }, loadFace: function (a) { var b = a.familyName.toLowerCase(); this.faces[b] = this.faces[b] || {}; this.faces[b][a.cssFontWeight] = this.faces[b][a.cssFontWeight] || {}; this.faces[b][a.cssFontWeight][a.cssFontStyle] = a; return this.faces[b][a.cssFontWeight][a.cssFontStyle] = a }, drawText: function (a) { for (var b = this.getFace(), c = this.size / b.resolution, d = 0, e = String(a).split(""), f = e.length, g = [], a = 0; a < f; a++) { var h = new THREE.Path, h = this.extractGlyphPoints(e[a], b, c, d, h), d = d + h.offset; g.push(h.path) } return {paths: g, offset: d / 2} }, extractGlyphPoints: function (a, b, c, d, e) { var f = [], g, h, i, k, l, m, p, s, r, n, q, z = b.glyphs[a] || b.glyphs["?"]; if (z) { if (z.o) { b = z._cachedOutline || (z._cachedOutline = z.o.split(" ")); k = b.length; for (a = 0; a < k;) switch (i = b[a++], i) { case "m": i = b[a++] * c + d; l = b[a++] * c; e.moveTo(i, l); break; case "l": i = b[a++] * c + d; l = b[a++] * c; e.lineTo(i, l); break; case "q": i = b[a++] * c + d; l = b[a++] * c; s = b[a++] * c + d; r = b[a++] * c; e.quadraticCurveTo(s, r, i, l); if (g = f[f.length - 1]) { m = g.x; p = g.y; g = 1; for (h = this.divisions; g <= h; g++) { var t = g / h; THREE.Shape.Utils.b2(t, m, s, i); THREE.Shape.Utils.b2(t, p, r, l) } } break; case "b": if (i = b[a++] * c + d, l = b[a++] * c, s = b[a++] * c + d, r = b[a++] * -c, n = b[a++] * c + d, q = b[a++] * -c, e.bezierCurveTo(i, l, s, r, n, q), g = f[f.length - 1]) { m = g.x; p = g.y; g = 1; for (h = this.divisions; g <= h; g++) t = g / h, THREE.Shape.Utils.b3(t, m, s, n, i), THREE.Shape.Utils.b3(t, p, r, q, l) } } } return {offset: z.ha * c, path: e} } } }; THREE.FontUtils.generateShapes = function (a, b) { var b = b || {}, c = void 0 !== b.curveSegments ? b.curveSegments : 4, d = void 0 !== b.font ? b.font : "helvetiker", e = void 0 !== b.weight ? b.weight : "normal", f = void 0 !== b.style ? b.style : "normal"; THREE.FontUtils.size = void 0 !== b.size ? b.size : 100; THREE.FontUtils.divisions = c; THREE.FontUtils.face = d; THREE.FontUtils.weight = e; THREE.FontUtils.style = f; c = THREE.FontUtils.drawText(a).paths; d = []; e = 0; for (f = c.length; e < f; e++) Array.prototype.push.apply(d, c[e].toShapes()); return d }; (function (a) { var b = function (a) { for (var b = a.length, e = 0, f = b - 1, g = 0; g < b; f = g++) e += a[f].x * a[g].y - a[g].x * a[f].y; return 0.5 * e }; a.Triangulate = function (a, d) { var e = a.length; if (3 > e) return null; var f = [], g = [], h = [], i, k, l; if (0 < b(a)) for (k = 0; k < e; k++) g[k] = k; else for (k = 0; k < e; k++) g[k] = e - 1 - k; var m = 2 * e; for (k = e - 1; 2 < e;) { if (0 >= m--) { console.log("Warning, unable to triangulate polygon!"); break } i = k; e <= i && (i = 0); k = i + 1; e <= k && (k = 0); l = k + 1; e <= l && (l = 0); var p; a:{ var s = p = void 0, r = void 0, n = void 0, q = void 0, z = void 0, t = void 0, x = void 0, u = void 0, s = a[g[i]].x, r = a[g[i]].y, n = a[g[k]].x, q = a[g[k]].y, z = a[g[l]].x, t = a[g[l]].y; if (1E-10 > (n - s) * (t - r) - (q - r) * (z - s)) p = !1; else { var B = void 0, G = void 0, D = void 0, w = void 0, I = void 0, J = void 0, E = void 0, Z = void 0, A = void 0, S = void 0, A = Z = E = u = x = void 0, B = z - n, G = t - q, D = s - z, w = r - t, I = n - s, J = q - r; for (p = 0; p < e; p++) if (!(p === i || p === k || p === l)) if (x = a[g[p]].x, u = a[g[p]].y, E = x - s, Z = u - r, A = x - n, S = u - q, x -= z, u -= t, A = B * S - G * A, E = I * Z - J * E, Z = D * u - w * x, 0 <= A && 0 <= Z && 0 <= E) { p = !1; break a } p = !0 } } if (p) { f.push([a[g[i]], a[g[k]], a[g[l]]]); h.push([g[i], g[k], g[l]]); i = k; for (l = k + 1; l < e; i++, l++) g[i] = g[l]; e--; m = 2 * e } } return d ? h : f }; a.Triangulate.area = b; return a })(THREE.FontUtils); self._typeface_js = {faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace}; THREE.Curve = function () { }; THREE.Curve.prototype.getPoint = function () { console.log("Warning, getPoint() not implemented!"); return null }; THREE.Curve.prototype.getPointAt = function (a) { a = this.getUtoTmapping(a); return this.getPoint(a) }; THREE.Curve.prototype.getPoints = function (a) { a || (a = 5); var b, c = []; for (b = 0; b <= a; b++) c.push(this.getPoint(b / a)); return c }; THREE.Curve.prototype.getSpacedPoints = function (a) { a || (a = 5); var b, c = []; for (b = 0; b <= a; b++) c.push(this.getPointAt(b / a)); return c }; THREE.Curve.prototype.getLength = function () { var a = this.getLengths(); return a[a.length - 1] }; THREE.Curve.prototype.getLengths = function (a) { a || (a = this.__arcLengthDivisions ? this.__arcLengthDivisions : 200); if (this.cacheArcLengths && this.cacheArcLengths.length == a + 1 && !this.needsUpdate) return this.cacheArcLengths; this.needsUpdate = !1; var b = [], c, d = this.getPoint(0), e, f = 0; b.push(0); for (e = 1; e <= a; e++) c = this.getPoint(e / a), f += c.distanceTo(d), b.push(f), d = c; return this.cacheArcLengths = b }; THREE.Curve.prototype.updateArcLengths = function () { this.needsUpdate = !0; this.getLengths() }; THREE.Curve.prototype.getUtoTmapping = function (a, b) { var c = this.getLengths(), d = 0, e = c.length, f; f = b ? b : a * c[e - 1]; for (var g = 0, h = e - 1, i; g <= h;) if (d = Math.floor(g + (h - g) / 2), i = c[d] - f, 0 > i) g = d + 1; else if (0 < i) h = d - 1; else { h = d; break } d = h; if (c[d] == f) return d / (e - 1); g = c[d]; return c = (d + (f - g) / (c[d + 1] - g)) / (e - 1) }; THREE.Curve.prototype.getTangent = function (a) { var b = a - 1E-4, a = a + 1E-4; 0 > b && (b = 0); 1 < a && (a = 1); b = this.getPoint(b); return this.getPoint(a).clone().sub(b).normalize() }; THREE.Curve.prototype.getTangentAt = function (a) { a = this.getUtoTmapping(a); return this.getTangent(a) }; THREE.LineCurve = function (a, b) { this.v1 = a; this.v2 = b }; THREE.LineCurve.prototype = Object.create(THREE.Curve.prototype); THREE.LineCurve.prototype.getPoint = function (a) { var b = this.v2.clone().sub(this.v1); b.multiplyScalar(a).add(this.v1); return b }; THREE.LineCurve.prototype.getPointAt = function (a) { return this.getPoint(a) }; THREE.LineCurve.prototype.getTangent = function () { return this.v2.clone().sub(this.v1).normalize() }; THREE.QuadraticBezierCurve = function (a, b, c) { this.v0 = a; this.v1 = b; this.v2 = c }; THREE.QuadraticBezierCurve.prototype = Object.create(THREE.Curve.prototype); THREE.QuadraticBezierCurve.prototype.getPoint = function (a) { var b; b = THREE.Shape.Utils.b2(a, this.v0.x, this.v1.x, this.v2.x); a = THREE.Shape.Utils.b2(a, this.v0.y, this.v1.y, this.v2.y); return new THREE.Vector2(b, a) }; THREE.QuadraticBezierCurve.prototype.getTangent = function (a) { var b; b = THREE.Curve.Utils.tangentQuadraticBezier(a, this.v0.x, this.v1.x, this.v2.x); a = THREE.Curve.Utils.tangentQuadraticBezier(a, this.v0.y, this.v1.y, this.v2.y); b = new THREE.Vector2(b, a); b.normalize(); return b }; THREE.CubicBezierCurve = function (a, b, c, d) { this.v0 = a; this.v1 = b; this.v2 = c; this.v3 = d }; THREE.CubicBezierCurve.prototype = Object.create(THREE.Curve.prototype); THREE.CubicBezierCurve.prototype.getPoint = function (a) { var b; b = THREE.Shape.Utils.b3(a, this.v0.x, this.v1.x, this.v2.x, this.v3.x); a = THREE.Shape.Utils.b3(a, this.v0.y, this.v1.y, this.v2.y, this.v3.y); return new THREE.Vector2(b, a) }; THREE.CubicBezierCurve.prototype.getTangent = function (a) { var b; b = THREE.Curve.Utils.tangentCubicBezier(a, this.v0.x, this.v1.x, this.v2.x, this.v3.x); a = THREE.Curve.Utils.tangentCubicBezier(a, this.v0.y, this.v1.y, this.v2.y, this.v3.y); b = new THREE.Vector2(b, a); b.normalize(); return b }; THREE.SplineCurve = function (a) { this.points = void 0 == a ? [] : a }; THREE.SplineCurve.prototype = Object.create(THREE.Curve.prototype); THREE.SplineCurve.prototype.getPoint = function (a) { var b = new THREE.Vector2, c = [], d = this.points, e; e = (d.length - 1) * a; a = Math.floor(e); e -= a; c[0] = 0 == a ? a : a - 1; c[1] = a; c[2] = a > d.length - 2 ? d.length - 1 : a + 1; c[3] = a > d.length - 3 ? d.length - 1 : a + 2; b.x = THREE.Curve.Utils.interpolate(d[c[0]].x, d[c[1]].x, d[c[2]].x, d[c[3]].x, e); b.y = THREE.Curve.Utils.interpolate(d[c[0]].y, d[c[1]].y, d[c[2]].y, d[c[3]].y, e); return b }; THREE.EllipseCurve = function (a, b, c, d, e, f, g) { this.aX = a; this.aY = b; this.xRadius = c; this.yRadius = d; this.aStartAngle = e; this.aEndAngle = f; this.aClockwise = g }; THREE.EllipseCurve.prototype = Object.create(THREE.Curve.prototype); THREE.EllipseCurve.prototype.getPoint = function (a) { var b = this.aEndAngle - this.aStartAngle; this.aClockwise || (a = 1 - a); b = this.aStartAngle + a * b; a = this.aX + this.xRadius * Math.cos(b); b = this.aY + this.yRadius * Math.sin(b); return new THREE.Vector2(a, b) }; THREE.ArcCurve = function (a, b, c, d, e, f) { THREE.EllipseCurve.call(this, a, b, c, c, d, e, f) }; THREE.ArcCurve.prototype = Object.create(THREE.EllipseCurve.prototype); THREE.Curve.Utils = { tangentQuadraticBezier: function (a, b, c, d) { return 2 * (1 - a) * (c - b) + 2 * a * (d - c) }, tangentCubicBezier: function (a, b, c, d, e) { return -3 * b * (1 - a) * (1 - a) + 3 * c * (1 - a) * (1 - a) - 6 * a * c * (1 - a) + 6 * a * d * (1 - a) - 3 * a * a * d + 3 * a * a * e }, tangentSpline: function (a) { return 6 * a * a - 6 * a + (3 * a * a - 4 * a + 1) + (-6 * a * a + 6 * a) + (3 * a * a - 2 * a) }, interpolate: function (a, b, c, d, e) { var a = 0.5 * (c - a), d = 0.5 * (d - b), f = e * e; return (2 * b - 2 * c + a + d) * e * f + (-3 * b + 3 * c - 2 * a - d) * f + a * e + b } }; THREE.Curve.create = function (a, b) { a.prototype = Object.create(THREE.Curve.prototype); a.prototype.getPoint = b; return a }; THREE.LineCurve3 = THREE.Curve.create(function (a, b) { this.v1 = a; this.v2 = b }, function (a) { var b = new THREE.Vector3; b.subVectors(this.v2, this.v1); b.multiplyScalar(a); b.add(this.v1); return b }); THREE.QuadraticBezierCurve3 = THREE.Curve.create(function (a, b, c) { this.v0 = a; this.v1 = b; this.v2 = c }, function (a) { var b, c; b = THREE.Shape.Utils.b2(a, this.v0.x, this.v1.x, this.v2.x); c = THREE.Shape.Utils.b2(a, this.v0.y, this.v1.y, this.v2.y); a = THREE.Shape.Utils.b2(a, this.v0.z, this.v1.z, this.v2.z); return new THREE.Vector3(b, c, a) }); THREE.CubicBezierCurve3 = THREE.Curve.create(function (a, b, c, d) { this.v0 = a; this.v1 = b; this.v2 = c; this.v3 = d }, function (a) { var b, c; b = THREE.Shape.Utils.b3(a, this.v0.x, this.v1.x, this.v2.x, this.v3.x); c = THREE.Shape.Utils.b3(a, this.v0.y, this.v1.y, this.v2.y, this.v3.y); a = THREE.Shape.Utils.b3(a, this.v0.z, this.v1.z, this.v2.z, this.v3.z); return new THREE.Vector3(b, c, a) }); THREE.SplineCurve3 = THREE.Curve.create(function (a) { this.points = void 0 == a ? [] : a }, function (a) { var b = new THREE.Vector3, c = [], d = this.points, e, a = (d.length - 1) * a; e = Math.floor(a); a -= e; c[0] = 0 == e ? e : e - 1; c[1] = e; c[2] = e > d.length - 2 ? d.length - 1 : e + 1; c[3] = e > d.length - 3 ? d.length - 1 : e + 2; e = d[c[0]]; var f = d[c[1]], g = d[c[2]], c = d[c[3]]; b.x = THREE.Curve.Utils.interpolate(e.x, f.x, g.x, c.x, a); b.y = THREE.Curve.Utils.interpolate(e.y, f.y, g.y, c.y, a); b.z = THREE.Curve.Utils.interpolate(e.z, f.z, g.z, c.z, a); return b }); THREE.ClosedSplineCurve3 = THREE.Curve.create(function (a) { this.points = void 0 == a ? [] : a }, function (a) { var b = new THREE.Vector3, c = [], d = this.points, e; e = (d.length - 0) * a; a = Math.floor(e); e -= a; a += 0 < a ? 0 : (Math.floor(Math.abs(a) / d.length) + 1) * d.length; c[0] = (a - 1) % d.length; c[1] = a % d.length; c[2] = (a + 1) % d.length; c[3] = (a + 2) % d.length; b.x = THREE.Curve.Utils.interpolate(d[c[0]].x, d[c[1]].x, d[c[2]].x, d[c[3]].x, e); b.y = THREE.Curve.Utils.interpolate(d[c[0]].y, d[c[1]].y, d[c[2]].y, d[c[3]].y, e); b.z = THREE.Curve.Utils.interpolate(d[c[0]].z, d[c[1]].z, d[c[2]].z, d[c[3]].z, e); return b }); THREE.CurvePath = function () { this.curves = []; this.bends = []; this.autoClose = !1 }; THREE.CurvePath.prototype = Object.create(THREE.Curve.prototype); THREE.CurvePath.prototype.add = function (a) { this.curves.push(a) }; THREE.CurvePath.prototype.checkConnection = function () { }; THREE.CurvePath.prototype.closePath = function () { var a = this.curves[0].getPoint(0), b = this.curves[this.curves.length - 1].getPoint(1); a.equals(b) || this.curves.push(new THREE.LineCurve(b, a)) }; THREE.CurvePath.prototype.getPoint = function (a) { for (var b = a * this.getLength(), c = this.getCurveLengths(), a = 0; a < c.length;) { if (c[a] >= b) return b = c[a] - b, a = this.curves[a], b = 1 - b / a.getLength(), a.getPointAt(b); a++ } return null }; THREE.CurvePath.prototype.getLength = function () { var a = this.getCurveLengths(); return a[a.length - 1] }; THREE.CurvePath.prototype.getCurveLengths = function () { if (this.cacheLengths && this.cacheLengths.length == this.curves.length) return this.cacheLengths; var a = [], b = 0, c, d = this.curves.length; for (c = 0; c < d; c++) b += this.curves[c].getLength(), a.push(b); return this.cacheLengths = a }; THREE.CurvePath.prototype.getBoundingBox = function () { var a = this.getPoints(), b, c, d, e, f, g; b = c = Number.NEGATIVE_INFINITY; e = f = Number.POSITIVE_INFINITY; var h, i, k, l, m = a[0] instanceof THREE.Vector3; l = m ? new THREE.Vector3 : new THREE.Vector2; i = 0; for (k = a.length; i < k; i++) h = a[i], h.x > b ? b = h.x : h.x < e && (e = h.x), h.y > c ? c = h.y : h.y < f && (f = h.y), m && (h.z > d ? d = h.z : h.z < g && (g = h.z)), l.add(h); a = {minX: e, minY: f, maxX: b, maxY: c, centroid: l.divideScalar(k)}; m && (a.maxZ = d, a.minZ = g); return a }; THREE.CurvePath.prototype.createPointsGeometry = function (a) { a = this.getPoints(a, !0); return this.createGeometry(a) }; THREE.CurvePath.prototype.createSpacedPointsGeometry = function (a) { a = this.getSpacedPoints(a, !0); return this.createGeometry(a) }; THREE.CurvePath.prototype.createGeometry = function (a) { for (var b = new THREE.Geometry, c = 0; c < a.length; c++) b.vertices.push(new THREE.Vector3(a[c].x, a[c].y, a[c].z || 0)); return b }; THREE.CurvePath.prototype.addWrapPath = function (a) { this.bends.push(a) }; THREE.CurvePath.prototype.getTransformedPoints = function (a, b) { var c = this.getPoints(a), d, e; b || (b = this.bends); d = 0; for (e = b.length; d < e; d++) c = this.getWrapPoints(c, b[d]); return c }; THREE.CurvePath.prototype.getTransformedSpacedPoints = function (a, b) { var c = this.getSpacedPoints(a), d, e; b || (b = this.bends); d = 0; for (e = b.length; d < e; d++) c = this.getWrapPoints(c, b[d]); return c }; THREE.CurvePath.prototype.getWrapPoints = function (a, b) { var c = this.getBoundingBox(), d, e, f, g, h, i; d = 0; for (e = a.length; d < e; d++) f = a[d], g = f.x, h = f.y, i = g / c.maxX, i = b.getUtoTmapping(i, g), g = b.getPoint(i), h = b.getNormalVector(i).multiplyScalar(h), f.x = g.x + h.x, f.y = g.y + h.y; return a }; THREE.Gyroscope = function () { THREE.Object3D.call(this) }; THREE.Gyroscope.prototype = Object.create(THREE.Object3D.prototype); THREE.Gyroscope.prototype.updateMatrixWorld = function (a) { this.matrixAutoUpdate && this.updateMatrix(); if (this.matrixWorldNeedsUpdate || a) this.parent ? (this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix), this.matrixWorld.decompose(this.translationWorld, this.rotationWorld, this.scaleWorld), this.matrix.decompose(this.translationObject, this.rotationObject, this.scaleObject), this.matrixWorld.compose(this.translationWorld, this.rotationObject, this.scaleWorld)) : this.matrixWorld.copy(this.matrix), this.matrixWorldNeedsUpdate = !1, a = !0; for (var b = 0, c = this.children.length; b < c; b++) this.children[b].updateMatrixWorld(a) }; THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3; THREE.Gyroscope.prototype.translationObject = new THREE.Vector3; THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion; THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion; THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3; THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3; THREE.Path = function (a) { THREE.CurvePath.call(this); this.actions = []; a && this.fromPoints(a) }; THREE.Path.prototype = Object.create(THREE.CurvePath.prototype); THREE.PathActions = { MOVE_TO: "moveTo", LINE_TO: "lineTo", QUADRATIC_CURVE_TO: "quadraticCurveTo", BEZIER_CURVE_TO: "bezierCurveTo", CSPLINE_THRU: "splineThru", ARC: "arc", ELLIPSE: "ellipse" }; THREE.Path.prototype.fromPoints = function (a) { this.moveTo(a[0].x, a[0].y); for (var b = 1, c = a.length; b < c; b++) this.lineTo(a[b].x, a[b].y) }; THREE.Path.prototype.moveTo = function (a, b) { var c = Array.prototype.slice.call(arguments); this.actions.push({action: THREE.PathActions.MOVE_TO, args: c}) }; THREE.Path.prototype.lineTo = function (a, b) { var c = Array.prototype.slice.call(arguments), d = this.actions[this.actions.length - 1].args, d = new THREE.LineCurve(new THREE.Vector2(d[d.length - 2], d[d.length - 1]), new THREE.Vector2(a, b)); this.curves.push(d); this.actions.push({action: THREE.PathActions.LINE_TO, args: c}) }; THREE.Path.prototype.quadraticCurveTo = function (a, b, c, d) { var e = Array.prototype.slice.call(arguments), f = this.actions[this.actions.length - 1].args, f = new THREE.QuadraticBezierCurve(new THREE.Vector2(f[f.length - 2], f[f.length - 1]), new THREE.Vector2(a, b), new THREE.Vector2(c, d)); this.curves.push(f); this.actions.push({action: THREE.PathActions.QUADRATIC_CURVE_TO, args: e}) }; THREE.Path.prototype.bezierCurveTo = function (a, b, c, d, e, f) { var g = Array.prototype.slice.call(arguments), h = this.actions[this.actions.length - 1].args, h = new THREE.CubicBezierCurve(new THREE.Vector2(h[h.length - 2], h[h.length - 1]), new THREE.Vector2(a, b), new THREE.Vector2(c, d), new THREE.Vector2(e, f)); this.curves.push(h); this.actions.push({action: THREE.PathActions.BEZIER_CURVE_TO, args: g}) }; THREE.Path.prototype.splineThru = function (a) { var b = Array.prototype.slice.call(arguments), c = this.actions[this.actions.length - 1].args, c = [new THREE.Vector2(c[c.length - 2], c[c.length - 1])]; Array.prototype.push.apply(c, a); c = new THREE.SplineCurve(c); this.curves.push(c); this.actions.push({action: THREE.PathActions.CSPLINE_THRU, args: b}) }; THREE.Path.prototype.arc = function (a, b, c, d, e, f) { var g = this.actions[this.actions.length - 1].args; this.absarc(a + g[g.length - 2], b + g[g.length - 1], c, d, e, f) }; THREE.Path.prototype.absarc = function (a, b, c, d, e, f) { this.absellipse(a, b, c, c, d, e, f) }; THREE.Path.prototype.ellipse = function (a, b, c, d, e, f, g) { var h = this.actions[this.actions.length - 1].args; this.absellipse(a + h[h.length - 2], b + h[h.length - 1], c, d, e, f, g) }; THREE.Path.prototype.absellipse = function (a, b, c, d, e, f, g) { var h = Array.prototype.slice.call(arguments), i = new THREE.EllipseCurve(a, b, c, d, e, f, g); this.curves.push(i); i = i.getPoint(g ? 1 : 0); h.push(i.x); h.push(i.y); this.actions.push({action: THREE.PathActions.ELLIPSE, args: h}) }; THREE.Path.prototype.getSpacedPoints = function (a) { a || (a = 40); for (var b = [], c = 0; c < a; c++) b.push(this.getPoint(c / a)); return b }; THREE.Path.prototype.getPoints = function (a, b) { if (this.useSpacedPoints) return console.log("tata"), this.getSpacedPoints(a, b); var a = a || 12, c = [], d, e, f, g, h, i, k, l, m, p, s, r, n; d = 0; for (e = this.actions.length; d < e; d++) switch (f = this.actions[d], g = f.action, f = f.args, g) { case THREE.PathActions.MOVE_TO: c.push(new THREE.Vector2(f[0], f[1])); break; case THREE.PathActions.LINE_TO: c.push(new THREE.Vector2(f[0], f[1])); break; case THREE.PathActions.QUADRATIC_CURVE_TO: h = f[2]; i = f[3]; m = f[0]; p = f[1]; 0 < c.length ? (g = c[c.length - 1], s = g.x, r = g.y) : (g = this.actions[d - 1].args, s = g[g.length - 2], r = g[g.length - 1]); for (f = 1; f <= a; f++) n = f / a, g = THREE.Shape.Utils.b2(n, s, m, h), n = THREE.Shape.Utils.b2(n, r, p, i), c.push(new THREE.Vector2(g, n)); break; case THREE.PathActions.BEZIER_CURVE_TO: h = f[4]; i = f[5]; m = f[0]; p = f[1]; k = f[2]; l = f[3]; 0 < c.length ? (g = c[c.length - 1], s = g.x, r = g.y) : (g = this.actions[d - 1].args, s = g[g.length - 2], r = g[g.length - 1]); for (f = 1; f <= a; f++) n = f / a, g = THREE.Shape.Utils.b3(n, s, m, k, h), n = THREE.Shape.Utils.b3(n, r, p, l, i), c.push(new THREE.Vector2(g, n)); break; case THREE.PathActions.CSPLINE_THRU: g = this.actions[d - 1].args; n = [new THREE.Vector2(g[g.length - 2], g[g.length - 1])]; g = a * f[0].length; n = n.concat(f[0]); n = new THREE.SplineCurve(n); for (f = 1; f <= g; f++) c.push(n.getPointAt(f / g)); break; case THREE.PathActions.ARC: h = f[0]; i = f[1]; p = f[2]; k = f[3]; g = f[4]; m = !!f[5]; s = g - k; r = 2 * a; for (f = 1; f <= r; f++) n = f / r, m || (n = 1 - n), n = k + n * s, g = h + p * Math.cos(n), n = i + p * Math.sin(n), c.push(new THREE.Vector2(g, n)); break; case THREE.PathActions.ELLIPSE: h = f[0]; i = f[1]; p = f[2]; l = f[3]; k = f[4]; g = f[5]; m = !!f[6]; s = g - k; r = 2 * a; for (f = 1; f <= r; f++) n = f / r, m || (n = 1 - n), n = k + n * s, g = h + p * Math.cos(n), n = i + l * Math.sin(n), c.push(new THREE.Vector2(g, n)) } d = c[c.length - 1]; 1E-10 > Math.abs(d.x - c[0].x) && 1E-10 > Math.abs(d.y - c[0].y) && c.splice(c.length - 1, 1); b && c.push(c[0]); return c }; THREE.Path.prototype.toShapes = function () { var a, b, c, d, e = [], f = new THREE.Path; a = 0; for (b = this.actions.length; a < b; a++) c = this.actions[a], d = c.args, c = c.action, c == THREE.PathActions.MOVE_TO && 0 != f.actions.length && (e.push(f), f = new THREE.Path), f[c].apply(f, d); 0 != f.actions.length && e.push(f); if (0 == e.length) return []; var g; d = []; a = !THREE.Shape.Utils.isClockWise(e[0].getPoints()); if (1 == e.length) return f = e[0], g = new THREE.Shape, g.actions = f.actions, g.curves = f.curves, d.push(g), d; if (a) { g = new THREE.Shape; a = 0; for (b = e.length; a < b; a++) f = e[a], THREE.Shape.Utils.isClockWise(f.getPoints()) ? (g.actions = f.actions, g.curves = f.curves, d.push(g), g = new THREE.Shape) : g.holes.push(f) } else { a = 0; for (b = e.length; a < b; a++) f = e[a], THREE.Shape.Utils.isClockWise(f.getPoints()) ? (g && d.push(g), g = new THREE.Shape, g.actions = f.actions, g.curves = f.curves) : g.holes.push(f); d.push(g) } return d }; THREE.Shape = function () { THREE.Path.apply(this, arguments); this.holes = [] }; THREE.Shape.prototype = Object.create(THREE.Path.prototype); THREE.Shape.prototype.extrude = function (a) { return new THREE.ExtrudeGeometry(this, a) }; THREE.Shape.prototype.makeGeometry = function (a) { return new THREE.ShapeGeometry(this, a) }; THREE.Shape.prototype.getPointsHoles = function (a) { var b, c = this.holes.length, d = []; for (b = 0; b < c; b++) d[b] = this.holes[b].getTransformedPoints(a, this.bends); return d }; THREE.Shape.prototype.getSpacedPointsHoles = function (a) { var b, c = this.holes.length, d = []; for (b = 0; b < c; b++) d[b] = this.holes[b].getTransformedSpacedPoints(a, this.bends); return d }; THREE.Shape.prototype.extractAllPoints = function (a) { return {shape: this.getTransformedPoints(a), holes: this.getPointsHoles(a)} }; THREE.Shape.prototype.extractPoints = function (a) { return this.useSpacedPoints ? this.extractAllSpacedPoints(a) : this.extractAllPoints(a) }; THREE.Shape.prototype.extractAllSpacedPoints = function (a) { return {shape: this.getTransformedSpacedPoints(a), holes: this.getSpacedPointsHoles(a)} }; THREE.Shape.Utils = { removeHoles: function (a, b) { var c = a.concat(), d = c.concat(), e, f, g, h, i, k, l, m, p, s, r = []; for (i = 0; i < b.length; i++) { k = b[i]; Array.prototype.push.apply(d, k); f = Number.POSITIVE_INFINITY; for (e = 0; e < k.length; e++) { p = k[e]; s = []; for (m = 0; m < c.length; m++) l = c[m], l = p.distanceToSquared(l), s.push(l), l < f && (f = l, g = e, h = m) } e = 0 <= h - 1 ? h - 1 : c.length - 1; f = 0 <= g - 1 ? g - 1 : k.length - 1; var n = [k[g], c[h], c[e]]; m = THREE.FontUtils.Triangulate.area(n); var q = [k[g], k[f], c[h]]; p = THREE.FontUtils.Triangulate.area(q); s = h; l = g; h += 1; g += -1; 0 > h && (h += c.length); h %= c.length; 0 > g && (g += k.length); g %= k.length; e = 0 <= h - 1 ? h - 1 : c.length - 1; f = 0 <= g - 1 ? g - 1 : k.length - 1; n = [k[g], c[h], c[e]]; n = THREE.FontUtils.Triangulate.area(n); q = [k[g], k[f], c[h]]; q = THREE.FontUtils.Triangulate.area(q); m + p > n + q && (h = s, g = l, 0 > h && (h += c.length), h %= c.length, 0 > g && (g += k.length), g %= k.length, e = 0 <= h - 1 ? h - 1 : c.length - 1, f = 0 <= g - 1 ? g - 1 : k.length - 1); m = c.slice(0, h); p = c.slice(h); s = k.slice(g); l = k.slice(0, g); f = [k[g], k[f], c[h]]; r.push([k[g], c[h], c[e]]); r.push(f); c = m.concat(s).concat(l).concat(p) } return { shape: c, isolatedPts: r, allpoints: d } }, triangulateShape: function (a, b) { var c = THREE.Shape.Utils.removeHoles(a, b), d = c.allpoints, e = c.isolatedPts, c = THREE.FontUtils.Triangulate(c.shape, !1), f, g, h, i, k = {}; f = 0; for (g = d.length; f < g; f++) i = d[f].x + ":" + d[f].y, void 0 !== k[i] && console.log("Duplicate point", i), k[i] = f; f = 0; for (g = c.length; f < g; f++) { h = c[f]; for (d = 0; 3 > d; d++) i = h[d].x + ":" + h[d].y, i = k[i], void 0 !== i && (h[d] = i) } f = 0; for (g = e.length; f < g; f++) { h = e[f]; for (d = 0; 3 > d; d++) i = h[d].x + ":" + h[d].y, i = k[i], void 0 !== i && (h[d] = i) } return c.concat(e) }, isClockWise: function (a) { return 0 > THREE.FontUtils.Triangulate.area(a) }, b2p0: function (a, b) { var c = 1 - a; return c * c * b }, b2p1: function (a, b) { return 2 * (1 - a) * a * b }, b2p2: function (a, b) { return a * a * b }, b2: function (a, b, c, d) { return this.b2p0(a, b) + this.b2p1(a, c) + this.b2p2(a, d) }, b3p0: function (a, b) { var c = 1 - a; return c * c * c * b }, b3p1: function (a, b) { var c = 1 - a; return 3 * c * c * a * b }, b3p2: function (a, b) { return 3 * (1 - a) * a * a * b }, b3p3: function (a, b) { return a * a * a * b }, b3: function (a, b, c, d, e) { return this.b3p0(a, b) + this.b3p1(a, c) + this.b3p2(a, d) + this.b3p3(a, e) } }; THREE.AnimationHandler = function () { var a = [], b = {}, c = { update: function (b) { for (var c = 0; c < a.length; c++) a[c].update(b) }, addToUpdate: function (b) { -1 === a.indexOf(b) && a.push(b) }, removeFromUpdate: function (b) { b = a.indexOf(b); -1 !== b && a.splice(b, 1) }, add: function (a) { void 0 !== b[a.name] && console.log("THREE.AnimationHandler.add: Warning! " + a.name + " already exists in library. Overwriting."); b[a.name] = a; if (!0 !== a.initialized) { for (var c = 0; c < a.hierarchy.length; c++) { for (var d = 0; d < a.hierarchy[c].keys.length; d++) if (0 > a.hierarchy[c].keys[d].time && (a.hierarchy[c].keys[d].time = 0), void 0 !== a.hierarchy[c].keys[d].rot && !(a.hierarchy[c].keys[d].rot instanceof THREE.Quaternion)) { var h = a.hierarchy[c].keys[d].rot; a.hierarchy[c].keys[d].rot = new THREE.Quaternion(h[0], h[1], h[2], h[3]) } if (a.hierarchy[c].keys.length && void 0 !== a.hierarchy[c].keys[0].morphTargets) { h = {}; for (d = 0; d < a.hierarchy[c].keys.length; d++) for (var i = 0; i < a.hierarchy[c].keys[d].morphTargets.length; i++) { var k = a.hierarchy[c].keys[d].morphTargets[i]; h[k] = -1 } a.hierarchy[c].usedMorphTargets = h; for (d = 0; d < a.hierarchy[c].keys.length; d++) { var l = {}; for (k in h) { for (i = 0; i < a.hierarchy[c].keys[d].morphTargets.length; i++) if (a.hierarchy[c].keys[d].morphTargets[i] === k) { l[k] = a.hierarchy[c].keys[d].morphTargetsInfluences[i]; break } i === a.hierarchy[c].keys[d].morphTargets.length && (l[k] = 0) } a.hierarchy[c].keys[d].morphTargetsInfluences = l } } for (d = 1; d < a.hierarchy[c].keys.length; d++) a.hierarchy[c].keys[d].time === a.hierarchy[c].keys[d - 1].time && (a.hierarchy[c].keys.splice(d, 1), d--); for (d = 0; d < a.hierarchy[c].keys.length; d++) a.hierarchy[c].keys[d].index = d } d = parseInt(a.length * a.fps, 10); a.JIT = {}; a.JIT.hierarchy = []; for (c = 0; c < a.hierarchy.length; c++) a.JIT.hierarchy.push(Array(d)); a.initialized = !0 } }, get: function (a) { if ("string" === typeof a) { if (b[a]) return b[a]; console.log("THREE.AnimationHandler.get: Couldn't find animation " + a); return null } }, parse: function (a) { var b = []; if (a instanceof THREE.SkinnedMesh) for (var c = 0; c < a.bones.length; c++) b.push(a.bones[c]); else d(a, b); return b } }, d = function (a, b) { b.push(a); for (var c = 0; c < a.children.length; c++) d(a.children[c], b) }; c.LINEAR = 0; c.CATMULLROM = 1; c.CATMULLROM_FORWARD = 2; return c }(); THREE.Animation = function (a, b, c) { this.root = a; this.data = THREE.AnimationHandler.get(b); this.hierarchy = THREE.AnimationHandler.parse(a); this.currentTime = 0; this.timeScale = 1; this.isPlaying = !1; this.loop = this.isPaused = !0; this.interpolationType = void 0 !== c ? c : THREE.AnimationHandler.LINEAR; this.points = []; this.target = new THREE.Vector3 }; THREE.Animation.prototype.play = function (a, b) { if (!1 === this.isPlaying) { this.isPlaying = !0; this.loop = void 0 !== a ? a : !0; this.currentTime = void 0 !== b ? b : 0; var c, d = this.hierarchy.length, e; for (c = 0; c < d; c++) { e = this.hierarchy[c]; this.interpolationType !== THREE.AnimationHandler.CATMULLROM_FORWARD && (e.useQuaternion = !0); e.matrixAutoUpdate = !0; void 0 === e.animationCache && (e.animationCache = {}, e.animationCache.prevKey = { pos: 0, rot: 0, scl: 0 }, e.animationCache.nextKey = {pos: 0, rot: 0, scl: 0}, e.animationCache.originalMatrix = e instanceof THREE.Bone ? e.skinMatrix : e.matrix); var f = e.animationCache.prevKey; e = e.animationCache.nextKey; f.pos = this.data.hierarchy[c].keys[0]; f.rot = this.data.hierarchy[c].keys[0]; f.scl = this.data.hierarchy[c].keys[0]; e.pos = this.getNextKeyWith("pos", c, 1); e.rot = this.getNextKeyWith("rot", c, 1); e.scl = this.getNextKeyWith("scl", c, 1) } this.update(0) } this.isPaused = !1; THREE.AnimationHandler.addToUpdate(this) }; THREE.Animation.prototype.pause = function () { !0 === this.isPaused ? THREE.AnimationHandler.addToUpdate(this) : THREE.AnimationHandler.removeFromUpdate(this); this.isPaused = !this.isPaused }; THREE.Animation.prototype.stop = function () { this.isPaused = this.isPlaying = !1; THREE.AnimationHandler.removeFromUpdate(this) }; THREE.Animation.prototype.update = function (a) { if (!1 !== this.isPlaying) { var b = ["pos", "rot", "scl"], c, d, e, f, g, h, i, k, l; l = this.currentTime += a * this.timeScale; k = this.currentTime %= this.data.length; parseInt(Math.min(k * this.data.fps, this.data.length * this.data.fps), 10); for (var m = 0, p = this.hierarchy.length; m < p; m++) { a = this.hierarchy[m]; i = a.animationCache; for (var s = 0; 3 > s; s++) { c = b[s]; g = i.prevKey[c]; h = i.nextKey[c]; if (h.time <= l) { if (k < l) if (this.loop) { g = this.data.hierarchy[m].keys[0]; for (h = this.getNextKeyWith(c, m, 1); h.time < k;) g = h, h = this.getNextKeyWith(c, m, h.index + 1) } else { this.stop(); return } else { do g = h, h = this.getNextKeyWith(c, m, h.index + 1); while (h.time < k) } i.prevKey[c] = g; i.nextKey[c] = h } a.matrixAutoUpdate = !0; a.matrixWorldNeedsUpdate = !0; d = (k - g.time) / (h.time - g.time); e = g[c]; f = h[c]; if (0 > d || 1 < d) console.log("THREE.Animation.update: Warning! Scale out of bounds:" + d + " on bone " + m), d = 0 > d ? 0 : 1; if ("pos" === c) if (c = a.position, this.interpolationType === THREE.AnimationHandler.LINEAR) c.x = e[0] + (f[0] - e[0]) * d, c.y = e[1] + (f[1] - e[1]) * d, c.z = e[2] + (f[2] - e[2]) * d; else { if (this.interpolationType === THREE.AnimationHandler.CATMULLROM || this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD) this.points[0] = this.getPrevKeyWith("pos", m, g.index - 1).pos, this.points[1] = e, this.points[2] = f, this.points[3] = this.getNextKeyWith("pos", m, h.index + 1).pos, d = 0.33 * d + 0.33, e = this.interpolateCatmullRom(this.points, d), c.x = e[0], c.y = e[1], c.z = e[2], this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD && (d = this.interpolateCatmullRom(this.points, 1.01 * d), this.target.set(d[0], d[1], d[2]), this.target.sub(c), this.target.y = 0, this.target.normalize(), d = Math.atan2(this.target.x, this.target.z), a.rotation.set(0, d, 0)) } else "rot" === c ? THREE.Quaternion.slerp(e, f, a.quaternion, d) : "scl" === c && (c = a.scale, c.x = e[0] + (f[0] - e[0]) * d, c.y = e[1] + (f[1] - e[1]) * d, c.z = e[2] + (f[2] - e[2]) * d) } } } }; THREE.Animation.prototype.interpolateCatmullRom = function (a, b) { var c = [], d = [], e, f, g, h, i, k; e = (a.length - 1) * b; f = Math.floor(e); e -= f; c[0] = 0 === f ? f : f - 1; c[1] = f; c[2] = f > a.length - 2 ? f : f + 1; c[3] = f > a.length - 3 ? f : f + 2; f = a[c[0]]; h = a[c[1]]; i = a[c[2]]; k = a[c[3]]; c = e * e; g = e * c; d[0] = this.interpolate(f[0], h[0], i[0], k[0], e, c, g); d[1] = this.interpolate(f[1], h[1], i[1], k[1], e, c, g); d[2] = this.interpolate(f[2], h[2], i[2], k[2], e, c, g); return d }; THREE.Animation.prototype.interpolate = function (a, b, c, d, e, f, g) { a = 0.5 * (c - a); d = 0.5 * (d - b); return (2 * (b - c) + a + d) * g + (-3 * (b - c) - 2 * a - d) * f + a * e + b }; THREE.Animation.prototype.getNextKeyWith = function (a, b, c) { for (var d = this.data.hierarchy[b].keys, c = this.interpolationType === THREE.AnimationHandler.CATMULLROM || this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ? c < d.length - 1 ? c : d.length - 1 : c % d.length; c < d.length; c++) if (void 0 !== d[c][a]) return d[c]; return this.data.hierarchy[b].keys[0] }; THREE.Animation.prototype.getPrevKeyWith = function (a, b, c) { for (var d = this.data.hierarchy[b].keys, c = this.interpolationType === THREE.AnimationHandler.CATMULLROM || this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ? 0 < c ? c : 0 : 0 <= c ? c : c + d.length; 0 <= c; c--) if (void 0 !== d[c][a]) return d[c]; return this.data.hierarchy[b].keys[d.length - 1] }; THREE.KeyFrameAnimation = function (a, b, c) { this.root = a; this.data = THREE.AnimationHandler.get(b); this.hierarchy = THREE.AnimationHandler.parse(a); this.currentTime = 0; this.timeScale = 0.001; this.isPlaying = !1; this.loop = this.isPaused = !0; this.JITCompile = void 0 !== c ? c : !0; a = 0; for (b = this.hierarchy.length; a < b; a++) { var c = this.data.hierarchy[a].sids, d = this.hierarchy[a]; if (this.data.hierarchy[a].keys.length && c) { for (var e = 0; e < c.length; e++) { var f = c[e], g = this.getNextKeyWith(f, a, 0); g && g.apply(f) } d.matrixAutoUpdate = !1; this.data.hierarchy[a].node.updateMatrix(); d.matrixWorldNeedsUpdate = !0 } } }; THREE.KeyFrameAnimation.prototype.play = function (a, b) { if (!this.isPlaying) { this.isPlaying = !0; this.loop = void 0 !== a ? a : !0; this.currentTime = void 0 !== b ? b : 0; this.startTimeMs = b; this.startTime = 1E7; this.endTime = -this.startTime; var c, d = this.hierarchy.length, e, f; for (c = 0; c < d; c++) e = this.hierarchy[c], f = this.data.hierarchy[c], e.useQuaternion = !0, void 0 === f.animationCache && (f.animationCache = {}, f.animationCache.prevKey = null, f.animationCache.nextKey = null, f.animationCache.originalMatrix = e instanceof THREE.Bone ? e.skinMatrix : e.matrix), e = this.data.hierarchy[c].keys, e.length && (f.animationCache.prevKey = e[0], f.animationCache.nextKey = e[1], this.startTime = Math.min(e[0].time, this.startTime), this.endTime = Math.max(e[e.length - 1].time, this.endTime)); this.update(0) } this.isPaused = !1; THREE.AnimationHandler.addToUpdate(this) }; THREE.KeyFrameAnimation.prototype.pause = function () { this.isPaused ? THREE.AnimationHandler.addToUpdate(this) : THREE.AnimationHandler.removeFromUpdate(this); this.isPaused = !this.isPaused }; THREE.KeyFrameAnimation.prototype.stop = function () { this.isPaused = this.isPlaying = !1; THREE.AnimationHandler.removeFromUpdate(this); for (var a = 0; a < this.data.hierarchy.length; a++) { var b = this.hierarchy[a], c = this.data.hierarchy[a]; if (void 0 !== c.animationCache) { var d = c.animationCache.originalMatrix; b instanceof THREE.Bone ? (d.copy(b.skinMatrix), b.skinMatrix = d) : (d.copy(b.matrix), b.matrix = d); delete c.animationCache } } }; THREE.KeyFrameAnimation.prototype.update = function (a) { if (this.isPlaying) { var b, c, d, e, f = this.data.JIT.hierarchy, g, h, i; h = this.currentTime += a * this.timeScale; g = this.currentTime %= this.data.length; g < this.startTimeMs && (g = this.currentTime = this.startTimeMs + g); e = parseInt(Math.min(g * this.data.fps, this.data.length * this.data.fps), 10); if ((i = g < h) && !this.loop) { for (var a = 0, k = this.hierarchy.length; a < k; a++) { var l = this.data.hierarchy[a].keys, f = this.data.hierarchy[a].sids; d = l.length - 1; e = this.hierarchy[a]; if (l.length) { for (l = 0; l < f.length; l++) g = f[l], (h = this.getPrevKeyWith(g, a, d)) && h.apply(g); this.data.hierarchy[a].node.updateMatrix(); e.matrixWorldNeedsUpdate = !0 } } this.stop() } else if (!(g < this.startTime)) { a = 0; for (k = this.hierarchy.length; a < k; a++) { d = this.hierarchy[a]; b = this.data.hierarchy[a]; var l = b.keys, m = b.animationCache; if (this.JITCompile && void 0 !== f[a][e]) d instanceof THREE.Bone ? (d.skinMatrix = f[a][e], d.matrixWorldNeedsUpdate = !1) : (d.matrix = f[a][e], d.matrixWorldNeedsUpdate = !0); else if (l.length) { this.JITCompile && m && (d instanceof THREE.Bone ? d.skinMatrix = m.originalMatrix : d.matrix = m.originalMatrix); b = m.prevKey; c = m.nextKey; if (b && c) { if (c.time <= h) { if (i && this.loop) { b = l[0]; for (c = l[1]; c.time < g;) b = c, c = l[b.index + 1] } else if (!i) for (var p = l.length - 1; c.time < g && c.index !== p;) b = c, c = l[b.index + 1]; m.prevKey = b; m.nextKey = c } c.time >= g ? b.interpolate(c, g) : b.interpolate(c, c.time) } this.data.hierarchy[a].node.updateMatrix(); d.matrixWorldNeedsUpdate = !0 } } if (this.JITCompile && void 0 === f[0][e]) { this.hierarchy[0].updateMatrixWorld(!0); for (a = 0; a < this.hierarchy.length; a++) f[a][e] = this.hierarchy[a] instanceof THREE.Bone ? this.hierarchy[a].skinMatrix.clone() : this.hierarchy[a].matrix.clone() } } } }; THREE.KeyFrameAnimation.prototype.getNextKeyWith = function (a, b, c) { b = this.data.hierarchy[b].keys; for (c %= b.length; c < b.length; c++) if (b[c].hasTarget(a)) return b[c]; return b[0] }; THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function (a, b, c) { b = this.data.hierarchy[b].keys; for (c = 0 <= c ? c : c + b.length; 0 <= c; c--) if (b[c].hasTarget(a)) return b[c]; return b[b.length - 1] }; THREE.CubeCamera = function (a, b, c) { THREE.Object3D.call(this); var d = new THREE.PerspectiveCamera(90, 1, a, b); d.up.set(0, -1, 0); d.lookAt(new THREE.Vector3(1, 0, 0)); this.add(d); var e = new THREE.PerspectiveCamera(90, 1, a, b); e.up.set(0, -1, 0); e.lookAt(new THREE.Vector3(-1, 0, 0)); this.add(e); var f = new THREE.PerspectiveCamera(90, 1, a, b); f.up.set(0, 0, 1); f.lookAt(new THREE.Vector3(0, 1, 0)); this.add(f); var g = new THREE.PerspectiveCamera(90, 1, a, b); g.up.set(0, 0, -1); g.lookAt(new THREE.Vector3(0, -1, 0)); this.add(g); var h = new THREE.PerspectiveCamera(90, 1, a, b); h.up.set(0, -1, 0); h.lookAt(new THREE.Vector3(0, 0, 1)); this.add(h); var i = new THREE.PerspectiveCamera(90, 1, a, b); i.up.set(0, -1, 0); i.lookAt(new THREE.Vector3(0, 0, -1)); this.add(i); this.renderTarget = new THREE.WebGLRenderTargetCube(c, c, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter }); this.updateCubeMap = function (a, b) { var c = this.renderTarget, p = c.generateMipmaps; c.generateMipmaps = !1; c.activeCubeFace = 0; a.render(b, d, c); c.activeCubeFace = 1; a.render(b, e, c); c.activeCubeFace = 2; a.render(b, f, c); c.activeCubeFace = 3; a.render(b, g, c); c.activeCubeFace = 4; a.render(b, h, c); c.generateMipmaps = p; c.activeCubeFace = 5; a.render(b, i, c) } }; THREE.CubeCamera.prototype = Object.create(THREE.Object3D.prototype); THREE.CombinedCamera = function (a, b, c, d, e, f, g) { THREE.Camera.call(this); this.fov = c; this.left = -a / 2; this.right = a / 2; this.top = b / 2; this.bottom = -b / 2; this.cameraO = new THREE.OrthographicCamera(a / -2, a / 2, b / 2, b / -2, f, g); this.cameraP = new THREE.PerspectiveCamera(c, a / b, d, e); this.zoom = 1; this.toPerspective() }; THREE.CombinedCamera.prototype = Object.create(THREE.Camera.prototype); THREE.CombinedCamera.prototype.toPerspective = function () { this.near = this.cameraP.near; this.far = this.cameraP.far; this.cameraP.fov = this.fov / this.zoom; this.cameraP.updateProjectionMatrix(); this.projectionMatrix = this.cameraP.projectionMatrix; this.inPerspectiveMode = !0; this.inOrthographicMode = !1 }; THREE.CombinedCamera.prototype.toOrthographic = function () { var a = this.cameraP.aspect, b = (this.cameraP.near + this.cameraP.far) / 2, b = Math.tan(this.fov / 2) * b, a = 2 * b * a / 2, b = b / this.zoom, a = a / this.zoom; this.cameraO.left = -a; this.cameraO.right = a; this.cameraO.top = b; this.cameraO.bottom = -b; this.cameraO.updateProjectionMatrix(); this.near = this.cameraO.near; this.far = this.cameraO.far; this.projectionMatrix = this.cameraO.projectionMatrix; this.inPerspectiveMode = !1; this.inOrthographicMode = !0 }; THREE.CombinedCamera.prototype.setSize = function (a, b) { this.cameraP.aspect = a / b; this.left = -a / 2; this.right = a / 2; this.top = b / 2; this.bottom = -b / 2 }; THREE.CombinedCamera.prototype.setFov = function (a) { this.fov = a; this.inPerspectiveMode ? this.toPerspective() : this.toOrthographic() }; THREE.CombinedCamera.prototype.updateProjectionMatrix = function () { this.inPerspectiveMode ? this.toPerspective() : (this.toPerspective(), this.toOrthographic()) }; THREE.CombinedCamera.prototype.setLens = function (a, b) { void 0 === b && (b = 24); var c = 2 * THREE.Math.radToDeg(Math.atan(b / (2 * a))); this.setFov(c); return c }; THREE.CombinedCamera.prototype.setZoom = function (a) { this.zoom = a; this.inPerspectiveMode ? this.toPerspective() : this.toOrthographic() }; THREE.CombinedCamera.prototype.toFrontView = function () { this.rotation.x = 0; this.rotation.y = 0; this.rotation.z = 0; this.rotationAutoUpdate = !1 }; THREE.CombinedCamera.prototype.toBackView = function () { this.rotation.x = 0; this.rotation.y = Math.PI; this.rotation.z = 0; this.rotationAutoUpdate = !1 }; THREE.CombinedCamera.prototype.toLeftView = function () { this.rotation.x = 0; this.rotation.y = -Math.PI / 2; this.rotation.z = 0; this.rotationAutoUpdate = !1 }; THREE.CombinedCamera.prototype.toRightView = function () { this.rotation.x = 0; this.rotation.y = Math.PI / 2; this.rotation.z = 0; this.rotationAutoUpdate = !1 }; THREE.CombinedCamera.prototype.toTopView = function () { this.rotation.x = -Math.PI / 2; this.rotation.y = 0; this.rotation.z = 0; this.rotationAutoUpdate = !1 }; THREE.CombinedCamera.prototype.toBottomView = function () { this.rotation.x = Math.PI / 2; this.rotation.y = 0; this.rotation.z = 0; this.rotationAutoUpdate = !1 }; THREE.CircleGeometry = function (a, b, c, d) { THREE.Geometry.call(this); var a = a || 50, c = void 0 !== c ? c : 0, d = void 0 !== d ? d : 2 * Math.PI, b = void 0 !== b ? Math.max(3, b) : 8, e, f = []; e = new THREE.Vector3; var g = new THREE.Vector2(0.5, 0.5); this.vertices.push(e); f.push(g); for (e = 0; e <= b; e++) { var h = new THREE.Vector3, i = c + e / b * d; h.x = a * Math.cos(i); h.y = a * Math.sin(i); this.vertices.push(h); f.push(new THREE.Vector2((h.x / a + 1) / 2, -(h.y / a + 1) / 2 + 1)) } c = new THREE.Vector3(0, 0, -1); for (e = 1; e <= b; e++) this.faces.push(new THREE.Face3(e, e + 1, 0, [c, c, c])), this.faceVertexUvs[0].push([f[e], f[e + 1], g]); this.computeCentroids(); this.computeFaceNormals(); this.boundingSphere = new THREE.Sphere(new THREE.Vector3, a) }; THREE.CircleGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.CubeGeometry = function (a, b, c, d, e, f) { function g(a, b, c, d, e, f, g, n) { var q, z = h.widthSegments, t = h.heightSegments, x = e / 2, u = f / 2, B = h.vertices.length; if ("x" === a && "y" === b || "y" === a && "x" === b) q = "z"; else if ("x" === a && "z" === b || "z" === a && "x" === b) q = "y", t = h.depthSegments; else if ("z" === a && "y" === b || "y" === a && "z" === b) q = "x", z = h.depthSegments; var G = z + 1, D = t + 1, w = e / z, I = f / t, J = new THREE.Vector3; J[q] = 0 < g ? 1 : -1; for (e = 0; e < D; e++) for (f = 0; f < G; f++) { var E = new THREE.Vector3; E[a] = (f * w - x) * c; E[b] = (e * I - u) * d; E[q] = g; h.vertices.push(E) } for (e = 0; e < t; e++) for (f = 0; f < z; f++) a = new THREE.Face4(f + G * e + B, f + G * (e + 1) + B, f + 1 + G * (e + 1) + B, f + 1 + G * e + B), a.normal.copy(J), a.vertexNormals.push(J.clone(), J.clone(), J.clone(), J.clone()), a.materialIndex = n, h.faces.push(a), h.faceVertexUvs[0].push([new THREE.Vector2(f / z, 1 - e / t), new THREE.Vector2(f / z, 1 - (e + 1) / t), new THREE.Vector2((f + 1) / z, 1 - (e + 1) / t), new THREE.Vector2((f + 1) / z, 1 - e / t)]) } THREE.Geometry.call(this); var h = this; this.width = a; this.height = b; this.depth = c; this.widthSegments = d || 1; this.heightSegments = e || 1; this.depthSegments = f || 1; a = this.width / 2; b = this.height / 2; c = this.depth / 2; g("z", "y", -1, -1, this.depth, this.height, a, 0); g("z", "y", 1, -1, this.depth, this.height, -a, 1); g("x", "z", 1, 1, this.width, this.depth, b, 2); g("x", "z", 1, -1, this.width, this.depth, -b, 3); g("x", "y", 1, -1, this.width, this.height, c, 4); g("x", "y", -1, -1, this.width, this.height, -c, 5); this.computeCentroids(); this.mergeVertices() }; THREE.CubeGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.CylinderGeometry = function (a, b, c, d, e, f) { THREE.Geometry.call(this); var a = void 0 !== a ? a : 20, b = void 0 !== b ? b : 20, c = void 0 !== c ? c : 100, g = c / 2, d = d || 8, e = e || 1, h, i, k = [], l = []; for (i = 0; i <= e; i++) { var m = [], p = [], s = i / e, r = s * (b - a) + a; for (h = 0; h <= d; h++) { var n = h / d, q = new THREE.Vector3; q.x = r * Math.sin(2 * n * Math.PI); q.y = -s * c + g; q.z = r * Math.cos(2 * n * Math.PI); this.vertices.push(q); m.push(this.vertices.length - 1); p.push(new THREE.Vector2(n, 1 - s)) } k.push(m); l.push(p) } c = (b - a) / c; for (h = 0; h < d; h++) { 0 !== a ? (m = this.vertices[k[0][h]].clone(), p = this.vertices[k[0][h + 1]].clone()) : (m = this.vertices[k[1][h]].clone(), p = this.vertices[k[1][h + 1]].clone()); m.setY(Math.sqrt(m.x * m.x + m.z * m.z) * c).normalize(); p.setY(Math.sqrt(p.x * p.x + p.z * p.z) * c).normalize(); for (i = 0; i < e; i++) { var s = k[i][h], r = k[i + 1][h], n = k[i + 1][h + 1], q = k[i][h + 1], z = m.clone(), t = m.clone(), x = p.clone(), u = p.clone(), B = l[i][h].clone(), G = l[i + 1][h].clone(), D = l[i + 1][h + 1].clone(), w = l[i][h + 1].clone(); this.faces.push(new THREE.Face4(s, r, n, q, [z, t, x, u])); this.faceVertexUvs[0].push([B, G, D, w]) } } if (!f && 0 < a) { this.vertices.push(new THREE.Vector3(0, g, 0)); for (h = 0; h < d; h++) s = k[0][h], r = k[0][h + 1], n = this.vertices.length - 1, z = new THREE.Vector3(0, 1, 0), t = new THREE.Vector3(0, 1, 0), x = new THREE.Vector3(0, 1, 0), B = l[0][h].clone(), G = l[0][h + 1].clone(), D = new THREE.Vector2(G.u, 0), this.faces.push(new THREE.Face3(s, r, n, [z, t, x])), this.faceVertexUvs[0].push([B, G, D]) } if (!f && 0 < b) { this.vertices.push(new THREE.Vector3(0, -g, 0)); for (h = 0; h < d; h++) s = k[i][h + 1], r = k[i][h], n = this.vertices.length - 1, z = new THREE.Vector3(0, -1, 0), t = new THREE.Vector3(0, -1, 0), x = new THREE.Vector3(0, -1, 0), B = l[i][h + 1].clone(), G = l[i][h].clone(), D = new THREE.Vector2(G.u, 1), this.faces.push(new THREE.Face3(s, r, n, [z, t, x])), this.faceVertexUvs[0].push([B, G, D]) } this.computeCentroids(); this.computeFaceNormals() }; THREE.CylinderGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.ExtrudeGeometry = function (a, b) { "undefined" !== typeof a && (THREE.Geometry.call(this), a = a instanceof Array ? a : [a], this.shapebb = a[a.length - 1].getBoundingBox(), this.addShapeList(a, b), this.computeCentroids(), this.computeFaceNormals()) }; THREE.ExtrudeGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.ExtrudeGeometry.prototype.addShapeList = function (a, b) { for (var c = a.length, d = 0; d < c; d++) this.addShape(a[d], b) }; THREE.ExtrudeGeometry.prototype.addShape = function (a, b) { function c(a, b, c) { b || console.log("die"); return b.clone().multiplyScalar(c).add(a) } function d(a, b, c) { var d = THREE.ExtrudeGeometry.__v1, e = THREE.ExtrudeGeometry.__v2, f = THREE.ExtrudeGeometry.__v3, g = THREE.ExtrudeGeometry.__v4, h = THREE.ExtrudeGeometry.__v5, i = THREE.ExtrudeGeometry.__v6; d.set(a.x - b.x, a.y - b.y); e.set(a.x - c.x, a.y - c.y); d = d.normalize(); e = e.normalize(); f.set(-d.y, d.x); g.set(e.y, -e.x); h.copy(a).add(f); i.copy(a).add(g); if (h.equals(i)) return g.clone(); h.copy(b).add(f); i.copy(c).add(g); f = d.dot(g); g = i.sub(h).dot(g); 0 === f && (console.log("Either infinite or no solutions!"), 0 === g ? console.log("Its finite solutions.") : console.log("Too bad, no solutions.")); g /= f; return 0 > g ? (b = Math.atan2(b.y - a.y, b.x - a.x), a = Math.atan2(c.y - a.y, c.x - a.x), b > a && (a += 2 * Math.PI), c = (b + a) / 2, a = -Math.cos(c), c = -Math.sin(c), new THREE.Vector2(a, c)) : d.multiplyScalar(g).add(h).sub(a).clone() } function e(c, d) { var e, f; for (M = c.length; 0 <= --M;) { e = M; f = M - 1; 0 > f && (f = c.length - 1); for (var g = 0, h = s + 2 * l, g = 0; g < h; g++) { var i = fa * g, k = fa * (g + 1), m = d + e + i, i = d + f + i, p = d + f + k, k = d + e + k, n = c, q = g, r = h, u = e, w = f, m = m + Z, i = i + Z, p = p + Z, k = k + Z; E.faces.push(new THREE.Face4(m, i, p, k, null, null, t)); m = x.generateSideWallUV(E, a, n, b, m, i, p, k, q, r, u, w); E.faceVertexUvs[0].push(m) } } } function f(a, b, c) { E.vertices.push(new THREE.Vector3(a, b, c)) } function g(c, d, e, f) { c += Z; d += Z; e += Z; E.faces.push(new THREE.Face3(c, d, e, null, null, z)); c = f ? x.generateBottomUV(E, a, b, c, d, e) : x.generateTopUV(E, a, b, c, d, e); E.faceVertexUvs[0].push(c) } var h = void 0 !== b.amount ? b.amount : 100, i = void 0 !== b.bevelThickness ? b.bevelThickness : 6, k = void 0 !== b.bevelSize ? b.bevelSize : i - 2, l = void 0 !== b.bevelSegments ? b.bevelSegments : 3, m = void 0 !== b.bevelEnabled ? b.bevelEnabled : !0, p = void 0 !== b.curveSegments ? b.curveSegments : 12, s = void 0 !== b.steps ? b.steps : 1, r = b.extrudePath, n, q = !1, z = b.material, t = b.extrudeMaterial, x = void 0 !== b.UVGenerator ? b.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator, u, B, G, D; r && (n = r.getSpacedPoints(s), q = !0, m = !1, u = void 0 !== b.frames ? b.frames : new THREE.TubeGeometry.FrenetFrames(r, s, !1), B = new THREE.Vector3, G = new THREE.Vector3, D = new THREE.Vector3); m || (k = i = l = 0); var w, I, J, E = this, Z = this.vertices.length, p = a.extractPoints(p), A = p.shape, p = p.holes; if (r = !THREE.Shape.Utils.isClockWise(A)) { A = A.reverse(); I = 0; for (J = p.length; I < J; I++) w = p[I], THREE.Shape.Utils.isClockWise(w) && (p[I] = w.reverse()); r = !1 } var S = THREE.Shape.Utils.triangulateShape(A, p), r = A; I = 0; for (J = p.length; I < J; I++) w = p[I], A = A.concat(w); var F, H, K, N, fa = A.length, ma = S.length, eb = [], M = 0, U = r.length; F = U - 1; for (H = M + 1; M < U; M++, F++, H++) F === U && (F = 0), H === U && (H = 0), eb[M] = d(r[M], r[F], r[H]); var ja = [], L, ca = eb.concat(); I = 0; for (J = p.length; I < J; I++) { w = p[I]; L = []; M = 0; U = w.length; F = U - 1; for (H = M + 1; M < U; M++, F++, H++) F === U && (F = 0), H === U && (H = 0), L[M] = d(w[M], w[F], w[H]); ja.push(L); ca = ca.concat(L) } for (F = 0; F < l; F++) { w = F / l; K = i * (1 - w); H = k * Math.sin(w * Math.PI / 2); M = 0; for (U = r.length; M < U; M++) N = c(r[M], eb[M], H), f(N.x, N.y, -K); I = 0; for (J = p.length; I < J; I++) { w = p[I]; L = ja[I]; M = 0; for (U = w.length; M < U; M++) N = c(w[M], L[M], H), f(N.x, N.y, -K) } } H = k; for (M = 0; M < fa; M++) N = m ? c(A[M], ca[M], H) : A[M], q ? (G.copy(u.normals[0]).multiplyScalar(N.x), B.copy(u.binormals[0]).multiplyScalar(N.y), D.copy(n[0]).add(G).add(B), f(D.x, D.y, D.z)) : f(N.x, N.y, 0); for (w = 1; w <= s; w++) for (M = 0; M < fa; M++) N = m ? c(A[M], ca[M], H) : A[M], q ? (G.copy(u.normals[w]).multiplyScalar(N.x), B.copy(u.binormals[w]).multiplyScalar(N.y), D.copy(n[w]).add(G).add(B), f(D.x, D.y, D.z)) : f(N.x, N.y, h / s * w); for (F = l - 1; 0 <= F; F--) { w = F / l; K = i * (1 - w); H = k * Math.sin(w * Math.PI / 2); M = 0; for (U = r.length; M < U; M++) N = c(r[M], eb[M], H), f(N.x, N.y, h + K); I = 0; for (J = p.length; I < J; I++) { w = p[I]; L = ja[I]; M = 0; for (U = w.length; M < U; M++) N = c(w[M], L[M], H), q ? f(N.x, N.y + n[s - 1].y, n[s - 1].x + K) : f(N.x, N.y, h + K) } } if (m) { i = 0 * fa; for (M = 0; M < ma; M++) h = S[M], g(h[2] + i, h[1] + i, h[0] + i, !0); i = fa * (s + 2 * l); for (M = 0; M < ma; M++) h = S[M], g(h[0] + i, h[1] + i, h[2] + i, !1) } else { for (M = 0; M < ma; M++) h = S[M], g(h[2], h[1], h[0], !0); for (M = 0; M < ma; M++) h = S[M], g(h[0] + fa * s, h[1] + fa * s, h[2] + fa * s, !1) } h = 0; e(r, h); h += r.length; I = 0; for (J = p.length; I < J; I++) w = p[I], e(w, h), h += w.length }; THREE.ExtrudeGeometry.WorldUVGenerator = { generateTopUV: function (a, b, c, d, e, f) { b = a.vertices[e].x; e = a.vertices[e].y; c = a.vertices[f].x; f = a.vertices[f].y; return [new THREE.Vector2(a.vertices[d].x, a.vertices[d].y), new THREE.Vector2(b, e), new THREE.Vector2(c, f)] }, generateBottomUV: function (a, b, c, d, e, f) { return this.generateTopUV(a, b, c, d, e, f) }, generateSideWallUV: function (a, b, c, d, e, f, g, h) { var b = a.vertices[e].x, c = a.vertices[e].y, e = a.vertices[e].z, d = a.vertices[f].x, i = a.vertices[f].y, f = a.vertices[f].z, k = a.vertices[g].x, l = a.vertices[g].y, g = a.vertices[g].z, m = a.vertices[h].x, p = a.vertices[h].y, a = a.vertices[h].z; return 0.01 > Math.abs(c - i) ? [new THREE.Vector2(b, 1 - e), new THREE.Vector2(d, 1 - f), new THREE.Vector2(k, 1 - g), new THREE.Vector2(m, 1 - a)] : [new THREE.Vector2(c, 1 - e), new THREE.Vector2(i, 1 - f), new THREE.Vector2(l, 1 - g), new THREE.Vector2(p, 1 - a)] } }; THREE.ExtrudeGeometry.__v1 = new THREE.Vector2; THREE.ExtrudeGeometry.__v2 = new THREE.Vector2; THREE.ExtrudeGeometry.__v3 = new THREE.Vector2; THREE.ExtrudeGeometry.__v4 = new THREE.Vector2; THREE.ExtrudeGeometry.__v5 = new THREE.Vector2; THREE.ExtrudeGeometry.__v6 = new THREE.Vector2; THREE.ShapeGeometry = function (a, b) { THREE.Geometry.call(this); !1 === a instanceof Array && (a = [a]); this.shapebb = a[a.length - 1].getBoundingBox(); this.addShapeList(a, b); this.computeCentroids(); this.computeFaceNormals() }; THREE.ShapeGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.ShapeGeometry.prototype.addShapeList = function (a, b) { for (var c = 0, d = a.length; c < d; c++) this.addShape(a[c], b); return this }; THREE.ShapeGeometry.prototype.addShape = function (a, b) { void 0 === b && (b = {}); var c = b.material, d = void 0 === b.UVGenerator ? THREE.ExtrudeGeometry.WorldUVGenerator : b.UVGenerator, e, f, g, h = this.vertices.length; e = a.extractPoints(void 0 !== b.curveSegments ? b.curveSegments : 12); var i = e.shape, k = e.holes; if (!THREE.Shape.Utils.isClockWise(i)) { i = i.reverse(); e = 0; for (f = k.length; e < f; e++) g = k[e], THREE.Shape.Utils.isClockWise(g) && (k[e] = g.reverse()) } var l = THREE.Shape.Utils.triangulateShape(i, k); e = 0; for (f = k.length; e < f; e++) g = k[e], i = i.concat(g); k = i.length; f = l.length; for (e = 0; e < k; e++) g = i[e], this.vertices.push(new THREE.Vector3(g.x, g.y, 0)); for (e = 0; e < f; e++) k = l[e], i = k[0] + h, g = k[1] + h, k = k[2] + h, this.faces.push(new THREE.Face3(i, g, k, null, null, c)), this.faceVertexUvs[0].push(d.generateBottomUV(this, a, b, i, g, k)) }; THREE.LatheGeometry = function (a, b, c, d) { THREE.Geometry.call(this); for (var b = b || 12, c = c || 0, d = d || 2 * Math.PI, e = 1 / (a.length - 1), f = 1 / b, g = 0, h = b; g <= h; g++) for (var i = c + g * f * d, k = Math.cos(i), l = Math.sin(i), i = 0, m = a.length; i < m; i++) { var p = a[i], s = new THREE.Vector3; s.x = k * p.x - l * p.y; s.y = l * p.x + k * p.y; s.z = p.z; this.vertices.push(s) } c = a.length; g = 0; for (h = b; g < h; g++) { i = 0; for (m = a.length - 1; i < m; i++) d = b = i + c * g, l = b + c, k = b + 1 + c, this.faces.push(new THREE.Face4(d, l, k, b + 1)), k = g * f, b = i * e, d = k + f, l = b + e, this.faceVertexUvs[0].push([new THREE.Vector2(k, b), new THREE.Vector2(d, b), new THREE.Vector2(d, l), new THREE.Vector2(k, l)]) } this.mergeVertices(); this.computeCentroids(); this.computeFaceNormals(); this.computeVertexNormals() }; THREE.LatheGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.PlaneGeometry = function (a, b, c, d) { THREE.Geometry.call(this); this.width = a; this.height = b; this.widthSegments = c || 1; this.heightSegments = d || 1; for (var c = a / 2, e = b / 2, d = this.widthSegments, f = this.heightSegments, g = d + 1, h = f + 1, i = this.width / d, k = this.height / f, l = new THREE.Vector3(0, 0, 1), a = 0; a < h; a++) for (b = 0; b < g; b++) this.vertices.push(new THREE.Vector3(b * i - c, -(a * k - e), 0)); for (a = 0; a < f; a++) for (b = 0; b < d; b++) c = new THREE.Face4(b + g * a, b + g * (a + 1), b + 1 + g * (a + 1), b + 1 + g * a), c.normal.copy(l), c.vertexNormals.push(l.clone(), l.clone(), l.clone(), l.clone()), this.faces.push(c), this.faceVertexUvs[0].push([new THREE.Vector2(b / d, 1 - a / f), new THREE.Vector2(b / d, 1 - (a + 1) / f), new THREE.Vector2((b + 1) / d, 1 - (a + 1) / f), new THREE.Vector2((b + 1) / d, 1 - a / f)]); this.computeCentroids() }; THREE.PlaneGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.RingGeometry = function (a, b, c, d, e, f) { THREE.Geometry.call(this); for (var a = a || 0, b = b || 50, e = void 0 !== e ? e : 0, f = void 0 !== f ? f : 2 * Math.PI, c = void 0 !== c ? Math.max(3, c) : 8, d = void 0 !== d ? Math.max(3, d) : 8, g = [], h = a, i = (b - a) / d, a = 0; a <= d; a++) { for (b = 0; b <= c; b++) { var k = new THREE.Vector3, l = e + b / c * f; k.x = h * Math.cos(l); k.y = h * Math.sin(l); this.vertices.push(k); g.push(new THREE.Vector2((k.x / h + 1) / 2, -(k.y / h + 1) / 2 + 1)) } h += i } e = new THREE.Vector3(0, 0, 1); for (a = 0; a < d; a++) { f = a * c; for (b = 0; b <= c; b++) { var l = b + f, i = l + a, k = l + c + a, m = l + c + 1 + a; this.faces.push(new THREE.Face3(i, k, m, [e, e, e])); this.faceVertexUvs[0].push([g[i], g[k], g[m]]); i = l + a; k = l + c + 1 + a; m = l + 1 + a; this.faces.push(new THREE.Face3(i, k, m, [e, e, e])); this.faceVertexUvs[0].push([g[i], g[k], g[m]]) } } this.computeCentroids(); this.computeFaceNormals(); this.boundingSphere = new THREE.Sphere(new THREE.Vector3, h) }; THREE.RingGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.SphereGeometry = function (a, b, c, d, e, f, g) { THREE.Geometry.call(this); this.radius = a || 50; this.widthSegments = Math.max(3, Math.floor(b) || 8); this.heightSegments = Math.max(2, Math.floor(c) || 6); for (var d = void 0 !== d ? d : 0, e = void 0 !== e ? e : 2 * Math.PI, f = void 0 !== f ? f : 0, g = void 0 !== g ? g : Math.PI, h = [], i = [], c = 0; c <= this.heightSegments; c++) { for (var k = [], l = [], b = 0; b <= this.widthSegments; b++) { var m = b / this.widthSegments, p = c / this.heightSegments, s = new THREE.Vector3; s.x = -this.radius * Math.cos(d + m * e) * Math.sin(f + p * g); s.y = this.radius * Math.cos(f + p * g); s.z = this.radius * Math.sin(d + m * e) * Math.sin(f + p * g); this.vertices.push(s); k.push(this.vertices.length - 1); l.push(new THREE.Vector2(m, 1 - p)) } h.push(k); i.push(l) } for (c = 0; c < this.heightSegments; c++) for (b = 0; b < this.widthSegments; b++) { var d = h[c][b + 1], e = h[c][b], f = h[c + 1][b], g = h[c + 1][b + 1], k = this.vertices[d].clone().normalize(), l = this.vertices[e].clone().normalize(), m = this.vertices[f].clone().normalize(), p = this.vertices[g].clone().normalize(), s = i[c][b + 1].clone(), r = i[c][b].clone(), n = i[c + 1][b].clone(), q = i[c + 1][b + 1].clone(); Math.abs(this.vertices[d].y) === this.radius ? (this.faces.push(new THREE.Face3(d, f, g, [k, m, p])), this.faceVertexUvs[0].push([s, n, q])) : Math.abs(this.vertices[f].y) === this.radius ? (this.faces.push(new THREE.Face3(d, e, f, [k, l, m])), this.faceVertexUvs[0].push([s, r, n])) : (this.faces.push(new THREE.Face4(d, e, f, g, [k, l, m, p])), this.faceVertexUvs[0].push([s, r, n, q])) } this.computeCentroids(); this.computeFaceNormals(); this.boundingSphere = new THREE.Sphere(new THREE.Vector3, a) }; THREE.SphereGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.TextGeometry = function (a, b) { var c = THREE.FontUtils.generateShapes(a, b); b.amount = void 0 !== b.height ? b.height : 50; void 0 === b.bevelThickness && (b.bevelThickness = 10); void 0 === b.bevelSize && (b.bevelSize = 8); void 0 === b.bevelEnabled && (b.bevelEnabled = !1); THREE.ExtrudeGeometry.call(this, c, b) }; THREE.TextGeometry.prototype = Object.create(THREE.ExtrudeGeometry.prototype); THREE.TorusGeometry = function (a, b, c, d, e) { THREE.Geometry.call(this); this.radius = a || 100; this.tube = b || 40; this.radialSegments = c || 8; this.tubularSegments = d || 6; this.arc = e || 2 * Math.PI; e = new THREE.Vector3; a = []; b = []; for (c = 0; c <= this.radialSegments; c++) for (d = 0; d <= this.tubularSegments; d++) { var f = d / this.tubularSegments * this.arc, g = 2 * c / this.radialSegments * Math.PI; e.x = this.radius * Math.cos(f); e.y = this.radius * Math.sin(f); var h = new THREE.Vector3; h.x = (this.radius + this.tube * Math.cos(g)) * Math.cos(f); h.y = (this.radius + this.tube * Math.cos(g)) * Math.sin(f); h.z = this.tube * Math.sin(g); this.vertices.push(h); a.push(new THREE.Vector2(d / this.tubularSegments, c / this.radialSegments)); b.push(h.clone().sub(e).normalize()) } for (c = 1; c <= this.radialSegments; c++) for (d = 1; d <= this.tubularSegments; d++) { var e = (this.tubularSegments + 1) * c + d - 1, f = (this.tubularSegments + 1) * (c - 1) + d - 1, g = (this.tubularSegments + 1) * (c - 1) + d, h = (this.tubularSegments + 1) * c + d, i = new THREE.Face4(e, f, g, h, [b[e], b[f], b[g], b[h]]); i.normal.add(b[e]); i.normal.add(b[f]); i.normal.add(b[g]); i.normal.add(b[h]); i.normal.normalize(); this.faces.push(i); this.faceVertexUvs[0].push([a[e].clone(), a[f].clone(), a[g].clone(), a[h].clone()]) } this.computeCentroids() }; THREE.TorusGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.TorusKnotGeometry = function (a, b, c, d, e, f, g) { function h(a, b, c, d, e, f) { var g = Math.cos(a); Math.cos(b); b = Math.sin(a); a *= c / d; c = Math.cos(a); g *= 0.5 * e * (2 + c); b = 0.5 * e * (2 + c) * b; e = 0.5 * f * e * Math.sin(a); return new THREE.Vector3(g, b, e) } THREE.Geometry.call(this); this.radius = a || 100; this.tube = b || 40; this.radialSegments = c || 64; this.tubularSegments = d || 8; this.p = e || 2; this.q = f || 3; this.heightScale = g || 1; this.grid = Array(this.radialSegments); c = new THREE.Vector3; d = new THREE.Vector3; e = new THREE.Vector3; for (a = 0; a < this.radialSegments; ++a) { this.grid[a] = Array(this.tubularSegments); for (b = 0; b < this.tubularSegments; ++b) { var i = 2 * (a / this.radialSegments) * this.p * Math.PI, g = 2 * (b / this.tubularSegments) * Math.PI, f = h(i, g, this.q, this.p, this.radius, this.heightScale), i = h(i + 0.01, g, this.q, this.p, this.radius, this.heightScale); c.subVectors(i, f); d.addVectors(i, f); e.crossVectors(c, d); d.crossVectors(e, c); e.normalize(); d.normalize(); i = -this.tube * Math.cos(g); g = this.tube * Math.sin(g); f.x += i * d.x + g * e.x; f.y += i * d.y + g * e.y; f.z += i * d.z + g * e.z; this.grid[a][b] = this.vertices.push(new THREE.Vector3(f.x, f.y, f.z)) - 1 } } for (a = 0; a < this.radialSegments; ++a) for (b = 0; b < this.tubularSegments; ++b) { var e = (a + 1) % this.radialSegments, f = (b + 1) % this.tubularSegments, c = this.grid[a][b], d = this.grid[e][b], e = this.grid[e][f], f = this.grid[a][f], g = new THREE.Vector2(a / this.radialSegments, b / this.tubularSegments), i = new THREE.Vector2((a + 1) / this.radialSegments, b / this.tubularSegments), k = new THREE.Vector2((a + 1) / this.radialSegments, (b + 1) / this.tubularSegments), l = new THREE.Vector2(a / this.radialSegments, (b + 1) / this.tubularSegments); this.faces.push(new THREE.Face4(c, d, e, f)); this.faceVertexUvs[0].push([g, i, k, l]) } this.computeCentroids(); this.computeFaceNormals(); this.computeVertexNormals() }; THREE.TorusKnotGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.TubeGeometry = function (a, b, c, d, e, f) { THREE.Geometry.call(this); this.path = a; this.segments = b || 64; this.radius = c || 1; this.radiusSegments = d || 8; this.closed = e || !1; f && (this.debug = new THREE.Object3D); this.grid = []; var g, h, e = this.segments + 1, i, k, l, f = new THREE.Vector3, m, p, s, b = new THREE.TubeGeometry.FrenetFrames(this.path, this.segments, this.closed); m = b.tangents; p = b.normals; s = b.binormals; this.tangents = m; this.normals = p; this.binormals = s; for (b = 0; b < e; b++) { this.grid[b] = []; d = b / (e - 1); l = a.getPointAt(d); d = m[b]; g = p[b]; h = s[b]; this.debug && (this.debug.add(new THREE.ArrowHelper(d, l, c, 255)), this.debug.add(new THREE.ArrowHelper(g, l, c, 16711680)), this.debug.add(new THREE.ArrowHelper(h, l, c, 65280))); for (d = 0; d < this.radiusSegments; d++) i = 2 * (d / this.radiusSegments) * Math.PI, k = -this.radius * Math.cos(i), i = this.radius * Math.sin(i), f.copy(l), f.x += k * g.x + i * h.x, f.y += k * g.y + i * h.y, f.z += k * g.z + i * h.z, this.grid[b][d] = this.vertices.push(new THREE.Vector3(f.x, f.y, f.z)) - 1 } for (b = 0; b < this.segments; b++) for (d = 0; d < this.radiusSegments; d++) e = this.closed ? (b + 1) % this.segments : b + 1, f = (d + 1) % this.radiusSegments, a = this.grid[b][d], c = this.grid[e][d], e = this.grid[e][f], f = this.grid[b][f], m = new THREE.Vector2(b / this.segments, d / this.radiusSegments), p = new THREE.Vector2((b + 1) / this.segments, d / this.radiusSegments), s = new THREE.Vector2((b + 1) / this.segments, (d + 1) / this.radiusSegments), g = new THREE.Vector2(b / this.segments, (d + 1) / this.radiusSegments), this.faces.push(new THREE.Face4(a, c, e, f)), this.faceVertexUvs[0].push([m, p, s, g]); this.computeCentroids(); this.computeFaceNormals(); this.computeVertexNormals() }; THREE.TubeGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.TubeGeometry.FrenetFrames = function (a, b, c) { new THREE.Vector3; var d = new THREE.Vector3; new THREE.Vector3; var e = [], f = [], g = [], h = new THREE.Vector3, i = new THREE.Matrix4, b = b + 1, k, l, m; this.tangents = e; this.normals = f; this.binormals = g; for (k = 0; k < b; k++) l = k / (b - 1), e[k] = a.getTangentAt(l), e[k].normalize(); f[0] = new THREE.Vector3; g[0] = new THREE.Vector3; a = Number.MAX_VALUE; k = Math.abs(e[0].x); l = Math.abs(e[0].y); m = Math.abs(e[0].z); k <= a && (a = k, d.set(1, 0, 0)); l <= a && (a = l, d.set(0, 1, 0)); m <= a && d.set(0, 0, 1); h.crossVectors(e[0], d).normalize(); f[0].crossVectors(e[0], h); g[0].crossVectors(e[0], f[0]); for (k = 1; k < b; k++) f[k] = f[k - 1].clone(), g[k] = g[k - 1].clone(), h.crossVectors(e[k - 1], e[k]), 1E-4 < h.length() && (h.normalize(), d = Math.acos(e[k - 1].dot(e[k])), f[k].applyMatrix4(i.makeRotationAxis(h, d))), g[k].crossVectors(e[k], f[k]); if (c) { d = Math.acos(f[0].dot(f[b - 1])); d /= b - 1; 0 < e[0].dot(h.crossVectors(f[0], f[b - 1])) && (d = -d); for (k = 1; k < b; k++) f[k].applyMatrix4(i.makeRotationAxis(e[k], d * k)), g[k].crossVectors(e[k], f[k]) } }; THREE.PolyhedronGeometry = function (a, b, c, d) { function e(a) { var b = a.normalize().clone(); b.index = i.vertices.push(b) - 1; var c = Math.atan2(a.z, -a.x) / 2 / Math.PI + 0.5, a = Math.atan2(-a.y, Math.sqrt(a.x * a.x + a.z * a.z)) / Math.PI + 0.5; b.uv = new THREE.Vector2(c, 1 - a); return b } function f(a, b, c, d) { 1 > d ? (d = new THREE.Face3(a.index, b.index, c.index, [a.clone(), b.clone(), c.clone()]), d.centroid.add(a).add(b).add(c).divideScalar(3), d.normal = d.centroid.clone().normalize(), i.faces.push(d), d = Math.atan2(d.centroid.z, -d.centroid.x), i.faceVertexUvs[0].push([h(a.uv, a, d), h(b.uv, b, d), h(c.uv, c, d)])) : (d -= 1, f(a, g(a, b), g(a, c), d), f(g(a, b), b, g(b, c), d), f(g(a, c), g(b, c), c, d), f(g(a, b), g(b, c), g(a, c), d)) } function g(a, b) { m[a.index] || (m[a.index] = []); m[b.index] || (m[b.index] = []); var c = m[a.index][b.index]; void 0 === c && (m[a.index][b.index] = m[b.index][a.index] = c = e((new THREE.Vector3).addVectors(a, b).divideScalar(2))); return c } function h(a, b, c) { 0 > c && 1 === a.x && (a = new THREE.Vector2(a.x - 1, a.y)); 0 === b.x && 0 === b.z && (a = new THREE.Vector2(c / 2 / Math.PI + 0.5, a.y)); return a } THREE.Geometry.call(this); for (var c = c || 1, d = d || 0, i = this, k = 0, l = a.length; k < l; k++) e(new THREE.Vector3(a[k][0], a[k][1], a[k][2])); for (var m = [], a = this.vertices, k = 0, l = b.length; k < l; k++) f(a[b[k][0]], a[b[k][1]], a[b[k][2]], d); this.mergeVertices(); k = 0; for (l = this.vertices.length; k < l; k++) this.vertices[k].multiplyScalar(c); this.computeCentroids(); this.boundingSphere = new THREE.Sphere(new THREE.Vector3, c) }; THREE.PolyhedronGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.IcosahedronGeometry = function (a, b) { var c = (1 + Math.sqrt(5)) / 2; THREE.PolyhedronGeometry.call(this, [[-1, c, 0], [1, c, 0], [-1, -c, 0], [1, -c, 0], [0, -1, c], [0, 1, c], [0, -1, -c], [0, 1, -c], [c, 0, -1], [c, 0, 1], [-c, 0, -1], [-c, 0, 1]], [[0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11], [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8], [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9], [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1]], a, b) }; THREE.IcosahedronGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.OctahedronGeometry = function (a, b) { THREE.PolyhedronGeometry.call(this, [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], [[0, 2, 4], [0, 4, 3], [0, 3, 5], [0, 5, 2], [1, 2, 5], [1, 5, 3], [1, 3, 4], [1, 4, 2]], a, b) }; THREE.OctahedronGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.TetrahedronGeometry = function (a, b) { THREE.PolyhedronGeometry.call(this, [[1, 1, 1], [-1, -1, 1], [-1, 1, -1], [1, -1, -1]], [[2, 1, 0], [0, 3, 2], [1, 3, 0], [2, 3, 1]], a, b) }; THREE.TetrahedronGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.ParametricGeometry = function (a, b, c, d) { THREE.Geometry.call(this); var e = this.vertices, f = this.faces, g = this.faceVertexUvs[0], d = void 0 === d ? !1 : d, h, i, k, l, m = b + 1; for (h = 0; h <= c; h++) { l = h / c; for (i = 0; i <= b; i++) k = i / b, k = a(k, l), e.push(k) } var p, s, r, n; for (h = 0; h < c; h++) for (i = 0; i < b; i++) a = h * m + i, e = h * m + i + 1, l = (h + 1) * m + i, k = (h + 1) * m + i + 1, p = new THREE.Vector2(i / b, h / c), s = new THREE.Vector2((i + 1) / b, h / c), r = new THREE.Vector2(i / b, (h + 1) / c), n = new THREE.Vector2((i + 1) / b, (h + 1) / c), d ? (f.push(new THREE.Face3(a, e, l)), f.push(new THREE.Face3(e, k, l)), g.push([p, s, r]), g.push([s, n, r])) : (f.push(new THREE.Face4(a, e, k, l)), g.push([p, s, n, r])); this.computeCentroids(); this.computeFaceNormals(); this.computeVertexNormals() }; THREE.ParametricGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.ConvexGeometry = function (a) { function b(a) { var b = a.length(); return new THREE.Vector2(a.x / b, a.y / b) } THREE.Geometry.call(this); for (var c = [[0, 1, 2], [0, 2, 1]], d = 3; d < a.length; d++) { var e = d, f = a[e].clone(), g = f.length(); f.x += g * 2E-6 * (Math.random() - 0.5); f.y += g * 2E-6 * (Math.random() - 0.5); f.z += g * 2E-6 * (Math.random() - 0.5); for (var g = [], h = 0; h < c.length;) { var i = c[h], k = f, l = a[i[0]], m; m = l; var p = a[i[1]], s = a[i[2]], r = new THREE.Vector3, n = new THREE.Vector3; r.subVectors(s, p); n.subVectors(m, p); r.cross(n); r.normalize(); m = r; l = m.dot(l); if (m.dot(k) >= l) { for (k = 0; 3 > k; k++) { l = [i[k], i[(k + 1) % 3]]; m = !0; for (p = 0; p < g.length; p++) if (g[p][0] === l[1] && g[p][1] === l[0]) { g[p] = g[g.length - 1]; g.pop(); m = !1; break } m && g.push(l) } c[h] = c[c.length - 1]; c.pop() } else h++ } for (p = 0; p < g.length; p++) c.push([g[p][0], g[p][1], e]) } e = 0; f = Array(a.length); for (d = 0; d < c.length; d++) { g = c[d]; for (h = 0; 3 > h; h++) void 0 === f[g[h]] && (f[g[h]] = e++, this.vertices.push(a[g[h]])), g[h] = f[g[h]] } for (d = 0; d < c.length; d++) this.faces.push(new THREE.Face3(c[d][0], c[d][1], c[d][2])); for (d = 0; d < this.faces.length; d++) g = this.faces[d], this.faceVertexUvs[0].push([b(this.vertices[g.a]), b(this.vertices[g.b]), b(this.vertices[g.c])]); this.computeCentroids(); this.computeFaceNormals(); this.computeVertexNormals() }; THREE.ConvexGeometry.prototype = Object.create(THREE.Geometry.prototype); THREE.AxisHelper = function (a) { var b = new THREE.Geometry; b.vertices.push(new THREE.Vector3, new THREE.Vector3(a || 1, 0, 0), new THREE.Vector3, new THREE.Vector3(0, a || 1, 0), new THREE.Vector3, new THREE.Vector3(0, 0, a || 1)); b.colors.push(new THREE.Color(16711680), new THREE.Color(16755200), new THREE.Color(65280), new THREE.Color(11206400), new THREE.Color(255), new THREE.Color(43775)); a = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors}); THREE.Line.call(this, b, a, THREE.LinePieces) }; THREE.AxisHelper.prototype = Object.create(THREE.Line.prototype); THREE.ArrowHelper = function (a, b, c, d) { THREE.Object3D.call(this); void 0 === c && (c = 20); void 0 === d && (d = 16776960); var e = new THREE.Geometry; e.vertices.push(new THREE.Vector3(0, 0, 0)); e.vertices.push(new THREE.Vector3(0, 1, 0)); this.line = new THREE.Line(e, new THREE.LineBasicMaterial({color: d})); this.add(this.line); e = new THREE.CylinderGeometry(0, 0.05, 0.25, 5, 1); this.cone = new THREE.Mesh(e, new THREE.MeshBasicMaterial({color: d})); this.cone.position.set(0, 1, 0); this.add(this.cone); b instanceof THREE.Vector3 && (this.position = b); this.setDirection(a); this.setLength(c) }; THREE.ArrowHelper.prototype = Object.create(THREE.Object3D.prototype); THREE.ArrowHelper.prototype.setDirection = function (a) { var b = THREE.ArrowHelper.__v1.copy(a).normalize(); 0.999 < b.y ? this.rotation.set(0, 0, 0) : -0.999 > b.y ? this.rotation.set(Math.PI, 0, 0) : (a = THREE.ArrowHelper.__v2.set(b.z, 0, -b.x).normalize(), b = Math.acos(b.y), a = THREE.ArrowHelper.__q1.setFromAxisAngle(a, b), this.rotation.setEulerFromQuaternion(a, this.eulerOrder)) }; THREE.ArrowHelper.prototype.setLength = function (a) { this.scale.set(a, a, a) }; THREE.ArrowHelper.prototype.setColor = function (a) { this.line.material.color.setHex(a); this.cone.material.color.setHex(a) }; THREE.ArrowHelper.__v1 = new THREE.Vector3; THREE.ArrowHelper.__v2 = new THREE.Vector3; THREE.ArrowHelper.__q1 = new THREE.Quaternion; THREE.CameraHelper = function (a) { function b(a, b, d) { c(a, d); c(b, d) } function c(a, b) { d.geometry.vertices.push(new THREE.Vector3); d.geometry.colors.push(new THREE.Color(b)); void 0 === d.pointMap[a] && (d.pointMap[a] = []); d.pointMap[a].push(d.geometry.vertices.length - 1) } THREE.Line.call(this); var d = this; this.geometry = new THREE.Geometry; this.material = new THREE.LineBasicMaterial({color: 16777215, vertexColors: THREE.FaceColors}); this.type = THREE.LinePieces; this.matrixWorld = a.matrixWorld; this.matrixAutoUpdate = !1; this.pointMap = {}; b("n1", "n2", 16755200); b("n2", "n4", 16755200); b("n4", "n3", 16755200); b("n3", "n1", 16755200); b("f1", "f2", 16755200); b("f2", "f4", 16755200); b("f4", "f3", 16755200); b("f3", "f1", 16755200); b("n1", "f1", 16755200); b("n2", "f2", 16755200); b("n3", "f3", 16755200); b("n4", "f4", 16755200); b("p", "n1", 16711680); b("p", "n2", 16711680); b("p", "n3", 16711680); b("p", "n4", 16711680); b("u1", "u2", 43775); b("u2", "u3", 43775); b("u3", "u1", 43775); b("c", "t", 16777215); b("p", "c", 3355443); b("cn1", "cn2", 3355443); b("cn3", "cn4", 3355443); b("cf1", "cf2", 3355443); b("cf3", "cf4", 3355443); this.camera = a; this.update(a) }; THREE.CameraHelper.prototype = Object.create(THREE.Line.prototype); THREE.CameraHelper.prototype.update = function () { function a(a, d, e, f) { THREE.CameraHelper.__v.set(d, e, f); THREE.CameraHelper.__projector.unprojectVector(THREE.CameraHelper.__v, THREE.CameraHelper.__c); a = b.pointMap[a]; if (void 0 !== a) { d = 0; for (e = a.length; d < e; d++) b.geometry.vertices[a[d]].copy(THREE.CameraHelper.__v) } } var b = this; THREE.CameraHelper.__c.projectionMatrix.copy(this.camera.projectionMatrix); a("c", 0, 0, -1); a("t", 0, 0, 1); a("n1", -1, -1, -1); a("n2", 1, -1, -1); a("n3", -1, 1, -1); a("n4", 1, 1, -1); a("f1", -1, -1, 1); a("f2", 1, -1, 1); a("f3", -1, 1, 1); a("f4", 1, 1, 1); a("u1", 0.7, 1.1, -1); a("u2", -0.7, 1.1, -1); a("u3", 0, 2, -1); a("cf1", -1, 0, 1); a("cf2", 1, 0, 1); a("cf3", 0, -1, 1); a("cf4", 0, 1, 1); a("cn1", -1, 0, -1); a("cn2", 1, 0, -1); a("cn3", 0, -1, -1); a("cn4", 0, 1, -1); this.geometry.verticesNeedUpdate = !0 }; THREE.CameraHelper.__projector = new THREE.Projector; THREE.CameraHelper.__v = new THREE.Vector3; THREE.CameraHelper.__c = new THREE.Camera; THREE.DirectionalLightHelper = function (a, b) { THREE.Object3D.call(this); this.light = a; var c = new THREE.SphereGeometry(b, 4, 2), d = new THREE.MeshBasicMaterial({fog: !1, wireframe: !0}); d.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.lightSphere = new THREE.Mesh(c, d); this.lightSphere.position = this.light.position; this.add(this.lightSphere); c = new THREE.Geometry; c.vertices.push(this.light.position); c.vertices.push(this.light.target.position); c.computeLineDistances(); d = new THREE.LineDashedMaterial({ dashSize: 4, gapSize: 4, opacity: 0.75, transparent: !0, fog: !1 }); d.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.targetLine = new THREE.Line(c, d); this.add(this.targetLine) }; THREE.DirectionalLightHelper.prototype = Object.create(THREE.Object3D.prototype); THREE.DirectionalLightHelper.prototype.update = function () { this.lightSphere.material.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.targetLine.geometry.computeLineDistances(); this.targetLine.geometry.verticesNeedUpdate = !0; this.targetLine.material.color.copy(this.light.color).multiplyScalar(this.light.intensity) }; THREE.GridHelper = function (a, b) { for (var c = new THREE.Geometry, d = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors}), e = new THREE.Color(4473924), f = new THREE.Color(8947848), g = -a; g <= a; g += b) { c.vertices.push(new THREE.Vector3(-a, 0, g)); c.vertices.push(new THREE.Vector3(a, 0, g)); c.vertices.push(new THREE.Vector3(g, 0, -a)); c.vertices.push(new THREE.Vector3(g, 0, a)); var h = 0 === g ? e : f; c.colors.push(h, h, h, h) } THREE.Line.call(this, c, d, THREE.LinePieces) }; THREE.GridHelper.prototype = Object.create(THREE.Line.prototype); THREE.HemisphereLightHelper = function (a, b) { THREE.Object3D.call(this); this.light = a; var c = new THREE.SphereGeometry(b, 4, 2); c.applyMatrix((new THREE.Matrix4).makeRotationX(-Math.PI / 2)); for (var d = 0; 8 > d; d++) c.faces[d].materialIndex = 4 > d ? 0 : 1; d = new THREE.MeshBasicMaterial({fog: !1, wireframe: !0}); d.color.copy(a.color).multiplyScalar(a.intensity); var e = new THREE.MeshBasicMaterial({fog: !1, wireframe: !0}); e.color.copy(a.groundColor).multiplyScalar(a.intensity); this.lightSphere = new THREE.Mesh(c, new THREE.MeshFaceMaterial([d, e])); this.lightSphere.position = a.position; this.lightSphere.lookAt(new THREE.Vector3); this.add(this.lightSphere) }; THREE.HemisphereLightHelper.prototype = Object.create(THREE.Object3D.prototype); THREE.HemisphereLightHelper.prototype.update = function () { this.lightSphere.lookAt(new THREE.Vector3); this.lightSphere.material.materials[0].color.copy(this.light.color).multiplyScalar(this.light.intensity); this.lightSphere.material.materials[1].color.copy(this.light.groundColor).multiplyScalar(this.light.intensity) }; THREE.PointLightHelper = function (a, b) { THREE.Object3D.call(this); this.light = a; var c = new THREE.SphereGeometry(b, 4, 2), d = new THREE.MeshBasicMaterial({fog: !1, wireframe: !0}); d.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.lightSphere = new THREE.Mesh(c, d); this.lightSphere.position = this.light.position; this.add(this.lightSphere) }; THREE.PointLightHelper.prototype = Object.create(THREE.Object3D.prototype); THREE.PointLightHelper.prototype.update = function () { this.lightSphere.material.color.copy(this.light.color).multiplyScalar(this.light.intensity) }; THREE.SpotLightHelper = function (a, b) { THREE.Object3D.call(this); this.light = a; var c = new THREE.SphereGeometry(b, 4, 2), d = new THREE.MeshBasicMaterial({fog: !1, wireframe: !0}); d.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.lightSphere = new THREE.Mesh(c, d); this.lightSphere.position = this.light.position; this.add(this.lightSphere); c = new THREE.CylinderGeometry(1E-4, 1, 1, 8, 1, !0); c.applyMatrix((new THREE.Matrix4).makeRotationX(-Math.PI / 2).translate(new THREE.Vector3(0, -0.5, 0))); d = new THREE.MeshBasicMaterial({ fog: !1, wireframe: !0, opacity: 0.3, transparent: !0 }); d.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.lightCone = new THREE.Mesh(c, d); this.lightCone.position = this.light.position; c = a.distance ? a.distance : 1E4; d = 2 * c * Math.tan(0.5 * a.angle); this.lightCone.scale.set(d, d, c); this.lightCone.lookAt(this.light.target.position); this.add(this.lightCone) }; THREE.SpotLightHelper.prototype = Object.create(THREE.Object3D.prototype); THREE.SpotLightHelper.prototype.update = function () { var a = this.light.distance ? this.light.distance : 1E4, b = 2 * a * Math.tan(0.5 * this.light.angle); this.lightCone.scale.set(b, b, a); this.lightCone.lookAt(this.light.target.position); this.lightSphere.material.color.copy(this.light.color).multiplyScalar(this.light.intensity); this.lightCone.material.color.copy(this.light.color).multiplyScalar(this.light.intensity) }; THREE.ImmediateRenderObject = function () { THREE.Object3D.call(this); this.render = function () { } }; THREE.ImmediateRenderObject.prototype = Object.create(THREE.Object3D.prototype); THREE.LensFlare = function (a, b, c, d, e) { THREE.Object3D.call(this); this.lensFlares = []; this.positionScreen = new THREE.Vector3; this.customUpdateCallback = void 0; void 0 !== a && this.add(a, b, c, d, e) }; THREE.LensFlare.prototype = Object.create(THREE.Object3D.prototype); THREE.LensFlare.prototype.add = function (a, b, c, d, e, f) { void 0 === b && (b = -1); void 0 === c && (c = 0); void 0 === f && (f = 1); void 0 === e && (e = new THREE.Color(16777215)); void 0 === d && (d = THREE.NormalBlending); c = Math.min(c, Math.max(0, c)); this.lensFlares.push({ texture: a, size: b, distance: c, x: 0, y: 0, z: 0, scale: 1, rotation: 1, opacity: f, color: e, blending: d }) }; THREE.LensFlare.prototype.updateLensFlares = function () { var a, b = this.lensFlares.length, c, d = 2 * -this.positionScreen.x, e = 2 * -this.positionScreen.y; for (a = 0; a < b; a++) c = this.lensFlares[a], c.x = this.positionScreen.x + d * c.distance, c.y = this.positionScreen.y + e * c.distance, c.wantedRotation = 0.25 * c.x * Math.PI, c.rotation += 0.25 * (c.wantedRotation - c.rotation) }; THREE.MorphBlendMesh = function (a, b) { THREE.Mesh.call(this, a, b); this.animationsMap = {}; this.animationsList = []; var c = this.geometry.morphTargets.length; this.createAnimation("__default", 0, c - 1, c / 1); this.setAnimationWeight("__default", 1) }; THREE.MorphBlendMesh.prototype = Object.create(THREE.Mesh.prototype); THREE.MorphBlendMesh.prototype.createAnimation = function (a, b, c, d) { b = { startFrame: b, endFrame: c, length: c - b + 1, fps: d, duration: (c - b) / d, lastFrame: 0, currentFrame: 0, active: !1, time: 0, direction: 1, weight: 1, directionBackwards: !1, mirroredLoop: !1 }; this.animationsMap[a] = b; this.animationsList.push(b) }; THREE.MorphBlendMesh.prototype.autoCreateAnimations = function (a) { for (var b = /([a-z]+)(\d+)/, c, d = {}, e = this.geometry, f = 0, g = e.morphTargets.length; f < g; f++) { var h = e.morphTargets[f].name.match(b); if (h && 1 < h.length) { var i = h[1]; d[i] || (d[i] = {start: Infinity, end: -Infinity}); h = d[i]; f < h.start && (h.start = f); f > h.end && (h.end = f); c || (c = i) } } for (i in d) h = d[i], this.createAnimation(i, h.start, h.end, a); this.firstAnimation = c }; THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function (a) { if (a = this.animationsMap[a]) a.direction = 1, a.directionBackwards = !1 }; THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function (a) { if (a = this.animationsMap[a]) a.direction = -1, a.directionBackwards = !0 }; THREE.MorphBlendMesh.prototype.setAnimationFPS = function (a, b) { var c = this.animationsMap[a]; c && (c.fps = b, c.duration = (c.end - c.start) / c.fps) }; THREE.MorphBlendMesh.prototype.setAnimationDuration = function (a, b) { var c = this.animationsMap[a]; c && (c.duration = b, c.fps = (c.end - c.start) / c.duration) }; THREE.MorphBlendMesh.prototype.setAnimationWeight = function (a, b) { var c = this.animationsMap[a]; c && (c.weight = b) }; THREE.MorphBlendMesh.prototype.setAnimationTime = function (a, b) { var c = this.animationsMap[a]; c && (c.time = b) }; THREE.MorphBlendMesh.prototype.getAnimationTime = function (a) { var b = 0; if (a = this.animationsMap[a]) b = a.time; return b }; THREE.MorphBlendMesh.prototype.getAnimationDuration = function (a) { var b = -1; if (a = this.animationsMap[a]) b = a.duration; return b }; THREE.MorphBlendMesh.prototype.playAnimation = function (a) { var b = this.animationsMap[a]; b ? (b.time = 0, b.active = !0) : console.warn("animation[" + a + "] undefined") }; THREE.MorphBlendMesh.prototype.stopAnimation = function (a) { if (a = this.animationsMap[a]) a.active = !1 }; THREE.MorphBlendMesh.prototype.update = function (a) { for (var b = 0, c = this.animationsList.length; b < c; b++) { var d = this.animationsList[b]; if (d.active) { var e = d.duration / d.length; d.time += d.direction * a; if (d.mirroredLoop) { if (d.time > d.duration || 0 > d.time) d.direction *= -1, d.time > d.duration && (d.time = d.duration, d.directionBackwards = !0), 0 > d.time && (d.time = 0, d.directionBackwards = !1) } else d.time %= d.duration, 0 > d.time && (d.time += d.duration); var f = d.startFrame + THREE.Math.clamp(Math.floor(d.time / e), 0, d.length - 1), g = d.weight; f !== d.currentFrame && (this.morphTargetInfluences[d.lastFrame] = 0, this.morphTargetInfluences[d.currentFrame] = 1 * g, this.morphTargetInfluences[f] = 0, d.lastFrame = d.currentFrame, d.currentFrame = f); e = d.time % e / e; d.directionBackwards && (e = 1 - e); this.morphTargetInfluences[d.currentFrame] = e * g; this.morphTargetInfluences[d.lastFrame] = (1 - e) * g } } }; THREE.LensFlarePlugin = function () { function a(a, c) { var d = b.createProgram(), e = b.createShader(b.FRAGMENT_SHADER), f = b.createShader(b.VERTEX_SHADER), g = "precision " + c + " float;\n"; b.shaderSource(e, g + a.fragmentShader); b.shaderSource(f, g + a.vertexShader); b.compileShader(e); b.compileShader(f); b.attachShader(d, e); b.attachShader(d, f); b.linkProgram(d); return d } var b, c, d, e, f, g, h, i, k, l, m, p, s; this.init = function (r) { b = r.context; c = r; d = r.getPrecision(); e = new Float32Array(16); f = new Uint16Array(6); r = 0; e[r++] = -1; e[r++] = -1; e[r++] = 0; e[r++] = 0; e[r++] = 1; e[r++] = -1; e[r++] = 1; e[r++] = 0; e[r++] = 1; e[r++] = 1; e[r++] = 1; e[r++] = 1; e[r++] = -1; e[r++] = 1; e[r++] = 0; e[r++] = 1; r = 0; f[r++] = 0; f[r++] = 1; f[r++] = 2; f[r++] = 0; f[r++] = 2; f[r++] = 3; g = b.createBuffer(); h = b.createBuffer(); b.bindBuffer(b.ARRAY_BUFFER, g); b.bufferData(b.ARRAY_BUFFER, e, b.STATIC_DRAW); b.bindBuffer(b.ELEMENT_ARRAY_BUFFER, h); b.bufferData(b.ELEMENT_ARRAY_BUFFER, f, b.STATIC_DRAW); i = b.createTexture(); k = b.createTexture(); b.bindTexture(b.TEXTURE_2D, i); b.texImage2D(b.TEXTURE_2D, 0, b.RGB, 16, 16, 0, b.RGB, b.UNSIGNED_BYTE, null); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S, b.CLAMP_TO_EDGE); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_T, b.CLAMP_TO_EDGE); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_MAG_FILTER, b.NEAREST); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_MIN_FILTER, b.NEAREST); b.bindTexture(b.TEXTURE_2D, k); b.texImage2D(b.TEXTURE_2D, 0, b.RGBA, 16, 16, 0, b.RGBA, b.UNSIGNED_BYTE, null); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_S, b.CLAMP_TO_EDGE); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_WRAP_T, b.CLAMP_TO_EDGE); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_MAG_FILTER, b.NEAREST); b.texParameteri(b.TEXTURE_2D, b.TEXTURE_MIN_FILTER, b.NEAREST); 0 >= b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS) ? (l = !1, m = a(THREE.ShaderFlares.lensFlare, d)) : (l = !0, m = a(THREE.ShaderFlares.lensFlareVertexTexture, d)); p = {}; s = {}; p.vertex = b.getAttribLocation(m, "position"); p.uv = b.getAttribLocation(m, "uv"); s.renderType = b.getUniformLocation(m, "renderType"); s.map = b.getUniformLocation(m, "map"); s.occlusionMap = b.getUniformLocation(m, "occlusionMap"); s.opacity = b.getUniformLocation(m, "opacity"); s.color = b.getUniformLocation(m, "color"); s.scale = b.getUniformLocation(m, "scale"); s.rotation = b.getUniformLocation(m, "rotation"); s.screenPosition = b.getUniformLocation(m, "screenPosition") }; this.render = function (a, d, e, f) { var a = a.__webglFlares, t = a.length; if (t) { var x = new THREE.Vector3, u = f / e, B = 0.5 * e, G = 0.5 * f, D = 16 / f, w = new THREE.Vector2(D * u, D), I = new THREE.Vector3(1, 1, 0), J = new THREE.Vector2(1, 1), E = s, D = p; b.useProgram(m); b.enableVertexAttribArray(p.vertex); b.enableVertexAttribArray(p.uv); b.uniform1i(E.occlusionMap, 0); b.uniform1i(E.map, 1); b.bindBuffer(b.ARRAY_BUFFER, g); b.vertexAttribPointer(D.vertex, 2, b.FLOAT, !1, 16, 0); b.vertexAttribPointer(D.uv, 2, b.FLOAT, !1, 16, 8); b.bindBuffer(b.ELEMENT_ARRAY_BUFFER, h); b.disable(b.CULL_FACE); b.depthMask(!1); var Z, A, S, F, H; for (Z = 0; Z < t; Z++) if (D = 16 / f, w.set(D * u, D), F = a[Z], x.set(F.matrixWorld.elements[12], F.matrixWorld.elements[13], F.matrixWorld.elements[14]), x.applyMatrix4(d.matrixWorldInverse), x.applyProjection(d.projectionMatrix), I.copy(x), J.x = I.x * B + B, J.y = I.y * G + G, l || 0 < J.x && J.x < e && 0 < J.y && J.y < f) { b.activeTexture(b.TEXTURE1); b.bindTexture(b.TEXTURE_2D, i); b.copyTexImage2D(b.TEXTURE_2D, 0, b.RGB, J.x - 8, J.y - 8, 16, 16, 0); b.uniform1i(E.renderType, 0); b.uniform2f(E.scale, w.x, w.y); b.uniform3f(E.screenPosition, I.x, I.y, I.z); b.disable(b.BLEND); b.enable(b.DEPTH_TEST); b.drawElements(b.TRIANGLES, 6, b.UNSIGNED_SHORT, 0); b.activeTexture(b.TEXTURE0); b.bindTexture(b.TEXTURE_2D, k); b.copyTexImage2D(b.TEXTURE_2D, 0, b.RGBA, J.x - 8, J.y - 8, 16, 16, 0); b.uniform1i(E.renderType, 1); b.disable(b.DEPTH_TEST); b.activeTexture(b.TEXTURE1); b.bindTexture(b.TEXTURE_2D, i); b.drawElements(b.TRIANGLES, 6, b.UNSIGNED_SHORT, 0); F.positionScreen.copy(I); F.customUpdateCallback ? F.customUpdateCallback(F) : F.updateLensFlares(); b.uniform1i(E.renderType, 2); b.enable(b.BLEND); A = 0; for (S = F.lensFlares.length; A < S; A++) H = F.lensFlares[A], 0.001 < H.opacity && 0.001 < H.scale && (I.x = H.x, I.y = H.y, I.z = H.z, D = H.size * H.scale / f, w.x = D * u, w.y = D, b.uniform3f(E.screenPosition, I.x, I.y, I.z), b.uniform2f(E.scale, w.x, w.y), b.uniform1f(E.rotation, H.rotation), b.uniform1f(E.opacity, H.opacity), b.uniform3f(E.color, H.color.r, H.color.g, H.color.b), c.setBlending(H.blending, H.blendEquation, H.blendSrc, H.blendDst), c.setTexture(H.texture, 1), b.drawElements(b.TRIANGLES, 6, b.UNSIGNED_SHORT, 0)) } b.enable(b.CULL_FACE); b.enable(b.DEPTH_TEST); b.depthMask(!0) } } }; THREE.ShadowMapPlugin = function () { var a, b, c, d, e, f, g = new THREE.Frustum, h = new THREE.Matrix4, i = new THREE.Vector3, k = new THREE.Vector3, l = new THREE.Vector3; this.init = function (g) { a = g.context; b = g; var g = THREE.ShaderLib.depthRGBA, h = THREE.UniformsUtils.clone(g.uniforms); c = new THREE.ShaderMaterial({fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h}); d = new THREE.ShaderMaterial({ fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h, morphTargets: !0 }); e = new THREE.ShaderMaterial({ fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h, skinning: !0 }); f = new THREE.ShaderMaterial({ fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h, morphTargets: !0, skinning: !0 }); c._shadowPass = !0; d._shadowPass = !0; e._shadowPass = !0; f._shadowPass = !0 }; this.render = function (a, c) { b.shadowMapEnabled && b.shadowMapAutoUpdate && this.update(a, c) }; this.update = function (m, p) { var s, r, n, q, z, t, x, u, B, G = []; q = 0; a.clearColor(1, 1, 1, 1); a.disable(a.BLEND); a.enable(a.CULL_FACE); a.frontFace(a.CCW); b.shadowMapCullFace === THREE.CullFaceFront ? a.cullFace(a.FRONT) : a.cullFace(a.BACK); b.setDepthTest(!0); s = 0; for (r = m.__lights.length; s < r; s++) if (n = m.__lights[s], n.castShadow) if (n instanceof THREE.DirectionalLight && n.shadowCascade) for (z = 0; z < n.shadowCascadeCount; z++) { var D; if (n.shadowCascadeArray[z]) D = n.shadowCascadeArray[z]; else { B = n; x = z; D = new THREE.DirectionalLight; D.isVirtual = !0; D.onlyShadow = !0; D.castShadow = !0; D.shadowCameraNear = B.shadowCameraNear; D.shadowCameraFar = B.shadowCameraFar; D.shadowCameraLeft = B.shadowCameraLeft; D.shadowCameraRight = B.shadowCameraRight; D.shadowCameraBottom = B.shadowCameraBottom; D.shadowCameraTop = B.shadowCameraTop; D.shadowCameraVisible = B.shadowCameraVisible; D.shadowDarkness = B.shadowDarkness; D.shadowBias = B.shadowCascadeBias[x]; D.shadowMapWidth = B.shadowCascadeWidth[x]; D.shadowMapHeight = B.shadowCascadeHeight[x]; D.pointsWorld = []; D.pointsFrustum = []; u = D.pointsWorld; t = D.pointsFrustum; for (var w = 0; 8 > w; w++) u[w] = new THREE.Vector3, t[w] = new THREE.Vector3; u = B.shadowCascadeNearZ[x]; B = B.shadowCascadeFarZ[x]; t[0].set(-1, -1, u); t[1].set(1, -1, u); t[2].set(-1, 1, u); t[3].set(1, 1, u); t[4].set(-1, -1, B); t[5].set(1, -1, B); t[6].set(-1, 1, B); t[7].set(1, 1, B); D.originalCamera = p; t = new THREE.Gyroscope; t.position = n.shadowCascadeOffset; t.add(D); t.add(D.target); p.add(t); n.shadowCascadeArray[z] = D; console.log("Created virtualLight", D) } x = n; u = z; B = x.shadowCascadeArray[u]; B.position.copy(x.position); B.target.position.copy(x.target.position); B.lookAt(B.target); B.shadowCameraVisible = x.shadowCameraVisible; B.shadowDarkness = x.shadowDarkness; B.shadowBias = x.shadowCascadeBias[u]; t = x.shadowCascadeNearZ[u]; x = x.shadowCascadeFarZ[u]; B = B.pointsFrustum; B[0].z = t; B[1].z = t; B[2].z = t; B[3].z = t; B[4].z = x; B[5].z = x; B[6].z = x; B[7].z = x; G[q] = D; q++ } else G[q] = n, q++; s = 0; for (r = G.length; s < r; s++) { n = G[s]; n.shadowMap || (z = THREE.LinearFilter, b.shadowMapType === THREE.PCFSoftShadowMap && (z = THREE.NearestFilter), n.shadowMap = new THREE.WebGLRenderTarget(n.shadowMapWidth, n.shadowMapHeight, { minFilter: z, magFilter: z, format: THREE.RGBAFormat }), n.shadowMapSize = new THREE.Vector2(n.shadowMapWidth, n.shadowMapHeight), n.shadowMatrix = new THREE.Matrix4); if (!n.shadowCamera) { if (n instanceof THREE.SpotLight) n.shadowCamera = new THREE.PerspectiveCamera(n.shadowCameraFov, n.shadowMapWidth / n.shadowMapHeight, n.shadowCameraNear, n.shadowCameraFar); else if (n instanceof THREE.DirectionalLight) n.shadowCamera = new THREE.OrthographicCamera(n.shadowCameraLeft, n.shadowCameraRight, n.shadowCameraTop, n.shadowCameraBottom, n.shadowCameraNear, n.shadowCameraFar); else { console.error("Unsupported light type for shadow"); continue } m.add(n.shadowCamera); b.autoUpdateScene && m.updateMatrixWorld() } n.shadowCameraVisible && !n.cameraHelper && (n.cameraHelper = new THREE.CameraHelper(n.shadowCamera), n.shadowCamera.add(n.cameraHelper)); if (n.isVirtual && D.originalCamera == p) { z = p; q = n.shadowCamera; t = n.pointsFrustum; B = n.pointsWorld; i.set(Infinity, Infinity, Infinity); k.set(-Infinity, -Infinity, -Infinity); for (x = 0; 8 > x; x++) u = B[x], u.copy(t[x]), THREE.ShadowMapPlugin.__projector.unprojectVector(u, z), u.applyMatrix4(q.matrixWorldInverse), u.x < i.x && (i.x = u.x), u.x > k.x && (k.x = u.x), u.y < i.y && (i.y = u.y), u.y > k.y && (k.y = u.y), u.z < i.z && (i.z = u.z), u.z > k.z && (k.z = u.z); q.left = i.x; q.right = k.x; q.top = k.y; q.bottom = i.y; q.updateProjectionMatrix() } q = n.shadowMap; t = n.shadowMatrix; z = n.shadowCamera; z.position.getPositionFromMatrix(n.matrixWorld); l.getPositionFromMatrix(n.target.matrixWorld); z.lookAt(l); z.updateMatrixWorld(); z.matrixWorldInverse.getInverse(z.matrixWorld); n.cameraHelper && (n.cameraHelper.visible = n.shadowCameraVisible); n.shadowCameraVisible && n.cameraHelper.update(); t.set(0.5, 0, 0, 0.5, 0, 0.5, 0, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0, 1); t.multiply(z.projectionMatrix); t.multiply(z.matrixWorldInverse); h.multiplyMatrices(z.projectionMatrix, z.matrixWorldInverse); g.setFromMatrix(h); b.setRenderTarget(q); b.clear(); B = m.__webglObjects; n = 0; for (q = B.length; n < q; n++) if (x = B[n], t = x.object, x.render = !1, t.visible && t.castShadow && (!(t instanceof THREE.Mesh || t instanceof THREE.ParticleSystem) || !t.frustumCulled || g.intersectsObject(t))) t._modelViewMatrix.multiplyMatrices(z.matrixWorldInverse, t.matrixWorld), x.render = !0; n = 0; for (q = B.length; n < q; n++) x = B[n], x.render && (t = x.object, x = x.buffer, w = t.material instanceof THREE.MeshFaceMaterial ? t.material.materials[0] : t.material, u = 0 < t.geometry.morphTargets.length && w.morphTargets, w = t instanceof THREE.SkinnedMesh && w.skinning, u = t.customDepthMaterial ? t.customDepthMaterial : w ? u ? f : e : u ? d : c, x instanceof THREE.BufferGeometry ? b.renderBufferDirect(z, m.__lights, null, u, x, t) : b.renderBuffer(z, m.__lights, null, u, x, t)); B = m.__webglObjectsImmediate; n = 0; for (q = B.length; n < q; n++) x = B[n], t = x.object, t.visible && t.castShadow && (t._modelViewMatrix.multiplyMatrices(z.matrixWorldInverse, t.matrixWorld), b.renderImmediateObject(z, m.__lights, null, c, t)) } s = b.getClearColor(); r = b.getClearAlpha(); a.clearColor(s.r, s.g, s.b, r); a.enable(a.BLEND); b.shadowMapCullFace === THREE.CullFaceFront && a.cullFace(a.BACK) } }; THREE.ShadowMapPlugin.__projector = new THREE.Projector; THREE.SpritePlugin = function () { function a(a, b) { return a.z !== b.z ? b.z - a.z : b.id - a.id } var b, c, d, e, f, g, h, i, k, l; this.init = function (a) { b = a.context; c = a; d = a.getPrecision(); e = new Float32Array(16); f = new Uint16Array(6); a = 0; e[a++] = -1; e[a++] = -1; e[a++] = 0; e[a++] = 0; e[a++] = 1; e[a++] = -1; e[a++] = 1; e[a++] = 0; e[a++] = 1; e[a++] = 1; e[a++] = 1; e[a++] = 1; e[a++] = -1; e[a++] = 1; e[a++] = 0; e[a++] = 1; a = 0; f[a++] = 0; f[a++] = 1; f[a++] = 2; f[a++] = 0; f[a++] = 2; f[a++] = 3; g = b.createBuffer(); h = b.createBuffer(); b.bindBuffer(b.ARRAY_BUFFER, g); b.bufferData(b.ARRAY_BUFFER, e, b.STATIC_DRAW); b.bindBuffer(b.ELEMENT_ARRAY_BUFFER, h); b.bufferData(b.ELEMENT_ARRAY_BUFFER, f, b.STATIC_DRAW); var a = THREE.ShaderSprite.sprite, p = b.createProgram(), s = b.createShader(b.FRAGMENT_SHADER), r = b.createShader(b.VERTEX_SHADER), n = "precision " + d + " float;\n"; b.shaderSource(s, n + a.fragmentShader); b.shaderSource(r, n + a.vertexShader); b.compileShader(s); b.compileShader(r); b.attachShader(p, s); b.attachShader(p, r); b.linkProgram(p); i = p; k = {}; l = {}; k.position = b.getAttribLocation(i, "position"); k.uv = b.getAttribLocation(i, "uv"); l.uvOffset = b.getUniformLocation(i, "uvOffset"); l.uvScale = b.getUniformLocation(i, "uvScale"); l.rotation = b.getUniformLocation(i, "rotation"); l.scale = b.getUniformLocation(i, "scale"); l.alignment = b.getUniformLocation(i, "alignment"); l.color = b.getUniformLocation(i, "color"); l.map = b.getUniformLocation(i, "map"); l.opacity = b.getUniformLocation(i, "opacity"); l.useScreenCoordinates = b.getUniformLocation(i, "useScreenCoordinates"); l.sizeAttenuation = b.getUniformLocation(i, "sizeAttenuation"); l.screenPosition = b.getUniformLocation(i, "screenPosition"); l.modelViewMatrix = b.getUniformLocation(i, "modelViewMatrix"); l.projectionMatrix = b.getUniformLocation(i, "projectionMatrix"); l.fogType = b.getUniformLocation(i, "fogType"); l.fogDensity = b.getUniformLocation(i, "fogDensity"); l.fogNear = b.getUniformLocation(i, "fogNear"); l.fogFar = b.getUniformLocation(i, "fogFar"); l.fogColor = b.getUniformLocation(i, "fogColor"); l.alphaTest = b.getUniformLocation(i, "alphaTest") }; this.render = function (d, e, f, r) { var n = d.__webglSprites, q = n.length; if (q) { var z = k, t = l, x = r / f, f = 0.5 * f, u = 0.5 * r; b.useProgram(i); b.enableVertexAttribArray(z.position); b.enableVertexAttribArray(z.uv); b.disable(b.CULL_FACE); b.enable(b.BLEND); b.bindBuffer(b.ARRAY_BUFFER, g); b.vertexAttribPointer(z.position, 2, b.FLOAT, !1, 16, 0); b.vertexAttribPointer(z.uv, 2, b.FLOAT, !1, 16, 8); b.bindBuffer(b.ELEMENT_ARRAY_BUFFER, h); b.uniformMatrix4fv(t.projectionMatrix, !1, e.projectionMatrix.elements); b.activeTexture(b.TEXTURE0); b.uniform1i(t.map, 0); var B = z = 0, G = d.fog; G ? (b.uniform3f(t.fogColor, G.color.r, G.color.g, G.color.b), G instanceof THREE.Fog ? (b.uniform1f(t.fogNear, G.near), b.uniform1f(t.fogFar, G.far), b.uniform1i(t.fogType, 1), B = z = 1) : G instanceof THREE.FogExp2 && (b.uniform1f(t.fogDensity, G.density), b.uniform1i(t.fogType, 2), B = z = 2)) : (b.uniform1i(t.fogType, 0), B = z = 0); for (var D, w, I = [], G = 0; G < q; G++) D = n[G], w = D.material, D.visible && 0 !== w.opacity && (w.useScreenCoordinates ? D.z = -D.position.z : (D._modelViewMatrix.multiplyMatrices(e.matrixWorldInverse, D.matrixWorld), D.z = -D._modelViewMatrix.elements[14])); n.sort(a); for (G = 0; G < q; G++) D = n[G], w = D.material, D.visible && 0 !== w.opacity && (w.map && w.map.image && w.map.image.width) && (b.uniform1f(t.alphaTest, w.alphaTest), !0 === w.useScreenCoordinates ? (b.uniform1i(t.useScreenCoordinates, 1), b.uniform3f(t.screenPosition, (D.position.x * c.devicePixelRatio - f) / f, (u - D.position.y * c.devicePixelRatio) / u, Math.max(0, Math.min(1, D.position.z))), I[0] = c.devicePixelRatio, I[1] = c.devicePixelRatio) : (b.uniform1i(t.useScreenCoordinates, 0), b.uniform1i(t.sizeAttenuation, w.sizeAttenuation ? 1 : 0), b.uniformMatrix4fv(t.modelViewMatrix, !1, D._modelViewMatrix.elements), I[0] = 1, I[1] = 1), e = d.fog && w.fog ? B : 0, z !== e && (b.uniform1i(t.fogType, e), z = e), e = 1 / (w.scaleByViewport ? r : 1), I[0] *= e * x * D.scale.x, I[1] *= e * D.scale.y, b.uniform2f(t.uvScale, w.uvScale.x, w.uvScale.y), b.uniform2f(t.uvOffset, w.uvOffset.x, w.uvOffset.y), b.uniform2f(t.alignment, w.alignment.x, w.alignment.y), b.uniform1f(t.opacity, w.opacity), b.uniform3f(t.color, w.color.r, w.color.g, w.color.b), b.uniform1f(t.rotation, D.rotation), b.uniform2fv(t.scale, I), c.setBlending(w.blending, w.blendEquation, w.blendSrc, w.blendDst), c.setDepthTest(w.depthTest), c.setDepthWrite(w.depthWrite), c.setTexture(w.map, 0), b.drawElements(b.TRIANGLES, 6, b.UNSIGNED_SHORT, 0)); b.enable(b.CULL_FACE) } } }; THREE.DepthPassPlugin = function () { this.enabled = !1; this.renderTarget = null; var a, b, c, d, e, f, g = new THREE.Frustum, h = new THREE.Matrix4; this.init = function (g) { a = g.context; b = g; var g = THREE.ShaderLib.depthRGBA, h = THREE.UniformsUtils.clone(g.uniforms); c = new THREE.ShaderMaterial({fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h}); d = new THREE.ShaderMaterial({ fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h, morphTargets: !0 }); e = new THREE.ShaderMaterial({ fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h, skinning: !0 }); f = new THREE.ShaderMaterial({ fragmentShader: g.fragmentShader, vertexShader: g.vertexShader, uniforms: h, morphTargets: !0, skinning: !0 }); c._shadowPass = !0; d._shadowPass = !0; e._shadowPass = !0; f._shadowPass = !0 }; this.render = function (a, b) { this.enabled && this.update(a, b) }; this.update = function (i, k) { var l, m, p, s, r, n; a.clearColor(1, 1, 1, 1); a.disable(a.BLEND); b.setDepthTest(!0); b.autoUpdateScene && i.updateMatrixWorld(); k.matrixWorldInverse.getInverse(k.matrixWorld); h.multiplyMatrices(k.projectionMatrix, k.matrixWorldInverse); g.setFromMatrix(h); b.setRenderTarget(this.renderTarget); b.clear(); n = i.__webglObjects; l = 0; for (m = n.length; l < m; l++) if (p = n[l], r = p.object, p.render = !1, r.visible && (!(r instanceof THREE.Mesh || r instanceof THREE.ParticleSystem) || !r.frustumCulled || g.intersectsObject(r))) r._modelViewMatrix.multiplyMatrices(k.matrixWorldInverse, r.matrixWorld), p.render = !0; var q; l = 0; for (m = n.length; l < m; l++) if (p = n[l], p.render && (r = p.object, p = p.buffer, !(r instanceof THREE.ParticleSystem) || r.customDepthMaterial)) (q = r.material instanceof THREE.MeshFaceMaterial ? r.material.materials[0] : r.material) && b.setMaterialFaces(r.material), s = 0 < r.geometry.morphTargets.length && q.morphTargets, q = r instanceof THREE.SkinnedMesh && q.skinning, s = r.customDepthMaterial ? r.customDepthMaterial : q ? s ? f : e : s ? d : c, p instanceof THREE.BufferGeometry ? b.renderBufferDirect(k, i.__lights, null, s, p, r) : b.renderBuffer(k, i.__lights, null, s, p, r); n = i.__webglObjectsImmediate; l = 0; for (m = n.length; l < m; l++) p = n[l], r = p.object, r.visible && (r._modelViewMatrix.multiplyMatrices(k.matrixWorldInverse, r.matrixWorld), b.renderImmediateObject(k, i.__lights, null, c, r)); l = b.getClearColor(); m = b.getClearAlpha(); a.clearColor(l.r, l.g, l.b, m); a.enable(a.BLEND) } }; THREE.ShaderFlares = { lensFlareVertexTexture: { vertexShader: "uniform lowp int renderType;\nuniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nuniform sampler2D occlusionMap;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\nvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.5 ) );\nvVisibility = ( visibility.r / 9.0 ) *\n( 1.0 - visibility.g / 9.0 ) *\n( visibility.b / 9.0 ) *\n( 1.0 - visibility.a / 9.0 );\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}", fragmentShader: "uniform lowp int renderType;\nuniform sampler2D map;\nuniform float opacity;\nuniform vec3 color;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * vVisibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}" }, lensFlare: { vertexShader: "uniform lowp int renderType;\nuniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}", fragmentShader: "precision mediump float;\nuniform lowp int renderType;\nuniform sampler2D map;\nuniform sampler2D occlusionMap;\nuniform float opacity;\nuniform vec3 color;\nvarying vec2 vUV;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nfloat visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;\nvisibility = ( 1.0 - visibility / 4.0 );\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * visibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}" } }; THREE.ShaderSprite = { sprite: { vertexShader: "uniform int useScreenCoordinates;\nuniform int sizeAttenuation;\nuniform vec3 screenPosition;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform float rotation;\nuniform vec2 scale;\nuniform vec2 alignment;\nuniform vec2 uvOffset;\nuniform vec2 uvScale;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uvOffset + uv * uvScale;\nvec2 alignedPosition = position + alignment;\nvec2 rotatedPosition;\nrotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;\nrotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;\nvec4 finalPosition;\nif( useScreenCoordinates != 0 ) {\nfinalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );\n} else {\nfinalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\nfinalPosition.xy += rotatedPosition * ( sizeAttenuation == 1 ? 1.0 : finalPosition.z );\n}\ngl_Position = finalPosition;\n}", fragmentShader: "uniform vec3 color;\nuniform sampler2D map;\nuniform float opacity;\nuniform int fogType;\nuniform vec3 fogColor;\nuniform float fogDensity;\nuniform float fogNear;\nuniform float fogFar;\nuniform float alphaTest;\nvarying vec2 vUV;\nvoid main() {\nvec4 texture = texture2D( map, vUV );\nif ( texture.a < alphaTest ) discard;\ngl_FragColor = vec4( color * texture.xyz, texture.a * opacity );\nif ( fogType > 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}" } }; </script> <!-- pack me --> <!-- jQuery extenders --> <script type="text/javascript">/* Copyright (c) 2006 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net) * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. * * $LastChangedDate: 2007-06-20 16:24:37 -0500 (Wed, 20 Jun 2007) $ * $Rev: 2124 $ * * Version: 2.2 */ (function ($) { $.fn.extend({ /** * Apply the mousewheel event to the elements in the jQuery object. * The handler function should be prepared to take the event object * and a param called 'delta'. The 'delta' param is a number * either > 0 or < 0. > 0 = up and < 0 = down. * * The pageX, pageY, clientX and clientY event properties * are fixed in Firefox. * * @example $("p").mousewheel(function(event, delta){ * if (delta > 0) * // do something on mousewheel scroll up * else if (delta < 0) * //do something on mousewheel scroll down * }); * * @name mousewheel * @type jQuery * @param Function handler A function to call when onmousewheel fires. Should take two params: event and delta. * @cat Plugins/Mousewheel * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net) */ mousewheel: function (f) { if (!f.guid) f.guid = $.event.guid++; if (!$.event._mwCache) $.event._mwCache = []; return this.each(function () { if (this._mwHandlers) return this._mwHandlers.push(f); else this._mwHandlers = []; this._mwHandlers.push(f); var s = this; this._mwHandler = function (e) { e = $.event.fix(e || window.event); $.extend(e, this._mwCursorPos || {}); var delta = 0, returnValue = true; if (e.wheelDelta) delta = e.wheelDelta / 120; if (e.detail) delta = -e.detail / 3; if (window.opera) delta = -e.wheelDelta; for (var i = 0; i < s._mwHandlers.length; i++) if (s._mwHandlers[i]) if (s._mwHandlers[i].call(s, e, delta) === false) { returnValue = false; e.preventDefault(); e.stopPropagation(); } return returnValue; }; if ($.browser.mozilla && !this._mwFixCursorPos) { // fix pageX, pageY, clientX and clientY for mozilla this._mwFixCursorPos = function (e) { this._mwCursorPos = { pageX: e.pageX, pageY: e.pageY, clientX: e.clientX, clientY: e.clientY }; }; $(this).bind('mousemove', this._mwFixCursorPos); } if (this.addEventListener) if ($.browser.mozilla) this.addEventListener('DOMMouseScroll', this._mwHandler, false); else this.addEventListener('mousewheel', this._mwHandler, false); else this.onmousewheel = this._mwHandler; $.event._mwCache.push($(this)); }); }, /** * This method removes one or all applied mousewheel events from the elements. * You can remove a single handler function by passing it as the first param. * If you do not pass anything, it will remove all handlers. * * @name unmousewheel * @param Function handler The handler function to remove from the mousewheel event. * @type jQuery * @cat Plugins/Mousewheel * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net) */ unmousewheel: function (f) { return this.each(function () { if (f && this._mwHandlers) { for (var i = 0; i < this._mwHandlers.length; i++) if (this._mwHandlers[i] && this._mwHandlers[i].guid == f.guid) delete this._mwHandlers[i]; } else { if ($.browser.mozilla && !this._mwFixCursorPos) $(this).unbind('mousemove', this._mwFixCursorPos); if (this.addEventListener) if ($.browser.mozilla) this.removeEventListener('DOMMouseScroll', this._mwHandler, false); else this.removeEventListener('mousewheel', this._mwHandler, false); else this.onmousewheel = null; this._mwHandlers = this._mwHandler = this._mwFixCursorPos = this._mwCursorPos = null; } }); } }); // clean-up $(window) .one('unload', function () { var els = $.event._mwCache || []; for (var i = 0; i < els.length; i++) els[i].unmousewheel(); }); })(jQuery);</script> <!-- tracker --> <script type="text/javascript">Tracker = function () { // detect local session var isLocal = (location.protocol === 'file:'); // save logs on unload calc window $(window).on('unload', function () { trackerData["endAt"] = +new Date; $.ajax({ type: 'POST', url: 'http://acidome.ru/lab/calc/logs/track.php', data: trackerData, async: false }); }); // tracker data // key with value equals [empty array] will not be transfered var trackerData = { // identify client: isLocal ? [] : // undefined client (we can't to recognize local client) cookie('client', rand, 'expires=Fri, 09 Apr 2038 15:04:40 GMT;'), session: cookie('session', isLocal ? 'local' : rand), page: rand(), // geo info geo: '', // usage history initial: {}, flow: [], iframe: IS_IFRAME, // relative timing started here startAt: +new Date, // start url url: isLocal ? document.location.href.replace(/^[^#]*[\/\\](.*)$/, '$1') : // get no local path to file (security issue) document.location.href, // referrer to this domain, including one redirect referrer: function () { var ref = decodeURIComponent(cookie('strong-redirect-referrer')); if (ref) { // remove temporary cookie document.cookie = 'strong-redirect-referrer=; expires=' + (new Date).toUTCString(); return ref; } // simple referrer return document.referrer || [] }() }, timings = {}; return { push: push, extend: function (data) { _.extend(trackerData, data); }, time: function (key) { timings[key] = +new Date; }, timeEnd: function (key, started) { trackerData[key] = (+new Date) - (started || timings[key]); console.log(key + ' at: ' + trackerData[key] + 'ms'); }, updateGeo: function (providerName, data) { var geo = trackerData["geo"] = trackerData["geo"] || {provided: []}; var hasReceived = _.reduce(data, function (hasReceived, value, key) { if (value && !geo[key]) { geo[key] = (value + '') // remove text artefacts .replace(/\\(['"\\])/g, '$1'); return true; } return hasReceived; }, false); if (hasReceived) { trackerData["geo"].provided.push(providerName); } return geo; } }; // push log function push(type, data, extra) { if (typeof data == 'object') { // map boolean values to string (else will be wrong mapped to string in POST body) data = _.reduce(data, function (memo, value, key) { memo[key] = (typeof value == 'boolean') ? value ? '1' : '' : value; return memo; }, {}); } // detect first push for this key if (!trackerData.initial.hasOwnProperty(type)) { trackerData.initial[type] = _.extend({ time: time(), data: data }, extra); } else { trackerData.flow.push( _.extend({ type: type, time: time(), data: data }, extra) ); } } // relative time from started function time() { return +new Date - trackerData.startAt; } // helpers function cookie(key, defaults, extra) { // get var value = (document.cookie.split(key)[1] || '=;').replace(/^=([^;]*);.*$/, '$1'); if (!value && defaults) { // set & save value = extracted(defaults); document.cookie = key + "=" + value + ';' + extracted(extra || ''); } return value; function extracted(defaults) { return (typeof defaults == 'function') ? defaults() : defaults; } } function rand() { return random(1e+9, 1e+12).toString(36).toUpperCase(); function random(min, max) { if (max == null) { max = min; min = 0; } return min + Math.floor(Math.random() * (max - min + 1)); } } }(); // geo info request $(function () { var providers = [/* offline from 14.01.2015 { name: 'freegeoip.net', request: 'http://freegeoip.net/json/?callback=__geoDataReceiver', access: function(data) { if (typeof data !== 'object') return {}; // ignore ip, in order to privacy return { countryCode: data.country_code, country: data.country_name, regionCode: data.region_code, region: data.region_name, city: data.city, lat: data.latitude, long: data.longitude }; } },*/ /* payment required from 14.01.2015 { name: 'maxmind.com', request: 'http://j.maxmind.com/app/geoip.js', access: function() { if (typeof geoip_country_code != 'function') return {}; return { countryCode: geoip_country_code(), country: geoip_country_name(), regionCode: geoip_region(), region: geoip_region_name(), city: geoip_city(), lat: geoip_latitude(), long: geoip_longitude() }; } },*/ { name: 'telize.com', request: 'http://www.telize.com/geoip?callback=__geoDataReceiver', access: function (data) { if (typeof data !== 'object') return {}; // ignore ip, in order to privacy return { continentCode: data.continent_code, countryCode: data.country_code, country: data.country_name, regionCode: data.region_code, region: data.region, city: data.city, lat: data.latitude, long: data.longitude }; } }], requiredKeys = ['countryCode', 'city']; if (!IS_OFFLINE) { nextProvider(); } function nextProvider() { var provider = providers.pop(); // right-to-left if (!provider) return; window.__geoDataReceiver = function (data) { var geo = Tracker.updateGeo(provider.name, provider.access(data)); var allFilled = _.any(requiredKeys, function (key) { return !!geo[key]; }); delete window.__geoDataReceiver; if (allFilled) { // geo provided $(document).trigger('geo-complete', geo); } else { // try to run more, after script's onload called _.defer(nextProvider); } }; if (provider.request) { var script = $('<script>')[0]; script.type = 'text/javascript'; script.async = true; script.src = provider.request; script.onload = function () { if (window.__geoDataReceiver) { // error happens OR receiver-function was not called in JSONP response code // handle provider.access() this window.__geoDataReceiver(); } }; script.onerror = nextProvider; document.body.appendChild(script); } else { // without-request method used O_O window.__geoDataReceiver(); } } });</script> <!-- calc basic --> <script type="text/javascript">// Универсальная функция наследования Function.prototype.inherits = function (superClass) { var Inheritance = function () { }; Inheritance.prototype = superClass.prototype; this.prototype = new Inheritance(); this.prototype.constructor = this; this.superClass = superClass; // доступ к родительскому классу из инстанса this.prototype.superClass = superClass.prototype; return this; } // переопределение свойств/методов Function.prototype.override = function (proto) { for (var k in proto) this.prototype[k] = proto[k]; return this; } // статические свойства/методы Function.prototype.statics = function (proto) { for (var k in proto) this[k] = proto[k]; return this; } </script> <script type="text/javascript">/* * Palette is the js class. * * Legalize Cannabis Licence */ Palette = function (hex) { this.rgb = Palette.hex2rgb(hex); } .override({ hl: function (inc) { this.rgb || console.log('!this.rgb'); this.rgb[0] += inc; this.rgb[1] += inc; this.rgb[2] += inc; return this; }, color: function () { return Palette.rgb(this.rgb[0], this.rgb[1], this.rgb[2]); } }); Palette.HEX = '0123456789ABCDEF'; Palette.hex2 = function (i) { i = i < 0 ? 0 : i; i = i > 255 ? 255 : i; var l = i % 16, h = (i - l) / 16; return '' + Palette.HEX[h] + Palette.HEX[l]; }; Palette.hex2int = function (hex) { if (hex.length > 1) return Palette.hex2int(hex.substr(0, hex.length - 1)) * 16 + Palette.hex2int(hex.substr(hex.length - 1)) for (var i = Palette.HEX.indexOf(hex.toUpperCase()); i >= 0;) return i; return console.log('Palette.hex2int(): unknown', hex); }; Palette.hex2rgb = function (hex) { var result = /^#?(\w\w?)(\w\w?)(\w\w?)$/.exec(hex); if (result) return [Palette.hex2int(result[1]), Palette.hex2int(result[2]), Palette.hex2int(result[3])]; return console.log('Palette.hex2rgb(): unknown', hex); }; Palette.rgb = function (r, g, b) { return '#' + Palette.hex2(r) + Palette.hex2(g) + Palette.hex2(b); }; Palette.collections = { vertex: [], line: ['#CC2222', '#CCCC22', '#22CC22'], face: [] }; (function () { var cube = function (dim, fn) { var shifting = [], pos, collection = []; for (var steps = [], i = 0; i < dim; i++) { steps.push(255 - Math.floor((255 / dim) * i)); i % 2 && shifting.push(i); } for (i = 0; i < dim; i++) i % 2 || shifting.push(i); for (var k = 0; k < steps.length; k++) { var b = steps[shifting[k]]; for (var j = 0; j < steps.length; j++) { var g = steps[shifting[j]]; for (i = 0; i < steps.length; i++) { var r = steps[shifting[i]]; fn(r, g, b, shifting[i], shifting[j], shifting[k], pos++); } } } } Palette._colors = []; var steps = 10; cube(steps, function (r, g, b, i, j, k, pos) { if ((i + j + k) % 2 == 0 && (i + j + k) > 2 && (i + j + k) < steps * 3 - 2) { var rgb = Palette.rgb(r, g, b); Palette._colors.push(rgb); // collections var mod = (i + j + k) / 2; //mod = if (mod % 3 == 2) Palette.collections.vertex.push(rgb); else if (mod % 2) Palette.collections.face.push(rgb); else Palette.collections.line.push(rgb); } }); })(); 0 && $(function () { $.each(Palette.collections, function (key, colors) { $(colors.length).prependTo('body'); $(colors).each(function () { $('<span style="background-color:' + this + '"> ' + key + ' </span> ').prependTo('body'); }); $('<br>').prependTo('body'); }); }); </script> <script type="text/javascript">//############################################################################## // File: // metrics.js // Dependencies: // utils.js // Description: // Defines a Vector object for position, distance and dimensions in 3D, a // Rectangle object for neatly packaging position and dimensions together and // several utility functions for working with dimensions and/or positions of // DOM objects, the document, the window and the viewport. //############################################################################## // (c)2005-2006 Jeff Lau //############################################################################## function Metrics() { }; //############################################################################## Vector = Metrics.Vector = function (x, y, z) { if (y === undefined && z === undefined && x === 0) { return new Vector(); } this.x = isNaN(x) ? 0 : x.valueOf(); this.y = isNaN(y) ? 0 : y.valueOf(); this.z = isNaN(z) ? 0 : z.valueOf(); }; //using("Metrics.Vector"); Metrics.Vector.prototype.clone = function () { return new Metrics.Vector(this.x, this.y, this.z); }; Metrics.Vector.prototype.equals = function (to) { return Math.abs(this.x - to.x) + Math.abs(this.y - to.y) + Math.abs(this.z - to.z) < .000001; } Metrics.Vector.prototype.add = function (vector) { this.x += vector.x; this.y += vector.y; this.z += vector.z; return this; }; Metrics.Vector.add = function (vector1, vector2) { return new Metrics.Vector(vector1.x + vector2.x, vector1.y + vector2.y, vector1.z + vector2.z); }; Metrics.Vector.prototype.subtract = function (vector) { this.x -= vector.x; this.y -= vector.y; this.z -= vector.z; return this; }; Metrics.Vector.subtract = function (vector1, vector2) { return new Metrics.Vector(vector1.x - vector2.x, vector1.y - vector2.y, vector1.z - vector2.z); }; Metrics.Vector.prototype.scale = function (scalar) { this.x *= scalar; this.y *= scalar; this.z *= scalar; return this; }; Metrics.Vector.scale = function (vector, scalar) { return new Metrics.Vector(vector.x * scalar, vector.y * scalar, vector.z * scalar); }; Metrics.Vector.prototype.length = function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); }; Metrics.Vector.prototype.isZero = function () { return Vector.dotProduct(this, this) < 1e-20; }; Metrics.Vector.prototype.normalize = function () { var length = this.x * this.x + this.y * this.y + this.z * this.z; //if (length && Math.abs(length - 1) > 0.01) { length = Math.sqrt(length); this.x /= length; this.y /= length; this.z /= length; //} return this; }; Metrics.Vector.normalize = function (vector) { return (new Metrics.Vector(vector.x, vector.y, vector.z)).normalize(); }; Metrics.Vector.dotProduct = function (vector1, vector2) { return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z; }; Metrics.Vector.crossProduct = function (vector1, vector2) { return new Metrics.Vector( vector1.y * vector2.z - vector1.z * vector2.y, vector1.z * vector2.x - vector1.x * vector2.z, vector1.x * vector2.y - vector1.y * vector2.x ); }; // проекция вектора1 на вектор2, вдоль вектора2 Metrics.Vector.project = function (vector1, vector2) { var square2 = Metrics.Vector.dotProduct(vector2, vector2); if (square2) { return Metrics.Vector.scale(vector2, Metrics.Vector.dotProduct(vector1, vector2) / square2); } return new Metrics.Vector(); }; Metrics.Vector.component = function (vector1, vector2) { return Metrics.Vector.dotProduct(vector1, Metrics.Vector.normalize(vector2)); }; Metrics.Vector.perpendicular = function (vector1, vector2) { return Metrics.Vector.subtract(vector1, Metrics.Vector.project(vector1, vector2)); }; Metrics.Vector.rotate = function (vector, angle, axis) { var cosAngle = Math.cos(angle); var sinAngle = Math.sin(angle); switch (axis) { case "x": return new Metrics.Vector( vector.x, vector.y * cosAngle + vector.z * sinAngle, vector.z * cosAngle - vector.y * sinAngle ); case "y": return new Metrics.Vector( vector.x * cosAngle + vector.z * sinAngle, vector.y, vector.z * cosAngle - vector.x * sinAngle ); default: return new Metrics.Vector( vector.x * cosAngle + vector.y * sinAngle, vector.y * cosAngle - vector.x * sinAngle, vector.z ); } }; Metrics.Vector.prototype.toString = function () { return "(" + (this._enum ? 'enum:' + this._enum + ', ' : '') + this.x + ", " + this.y + ", " + this.z + ")"; }; Metrics.Vector.prototype.cosWith = function (B) { var a2 = this.x * this.x + this.y * this.y + this.z * this.z; var b2 = B.x * B.x + B.y * B.y + B.z * B.z; var c = this.clone().subtract(B); var c2 = c.x * c.x + c.y * c.y + c.z * c.z; var cos = (a2 + b2 - c2) / Math.sqrt(4 * a2 * b2); return Math.abs(cos + 1) > 1e-9 ? Math.abs(cos - 1) > 1e-9 ? cos : 1 : -1; } Metrics.Vector.prototype.angleWith = function (B, precision) { var angle = Math.acos(this.cosWith(B)); return precision ? Math.round(angle * 180 / Math.PI / precision) * precision : angle; } Metrics.Vector.angle = function (A, B, C, precision) { return C ? A.clone().subtract(B).angleWith(C.clone().subtract(B), precision) : A.angleWith(B, precision); } Metrics.Vector.distance = function (A, B, precision) { var d = A.clone().subtract(B).length(); return precision ? Math.round(d / precision) * precision : d; } Metrics.Vector.prototype.distance = function (B, precision) { return Metrics.Vector.distance(this, B, precision); } Vector.prototype.carousel = function () { var t = this.x; this.x = this.y; this.y = this.z; this.z = t; return this; } //############################################################################## plane Plane = Metrics.Plane = function (A, B, C, D) { if (arguments.length == 2) { Plane.apply(this, [A.x, A.y, A.z, B || 0]); return; } if (typeof D != 'number') { Plane.apply(this, [A, B, C, 0]); this.D = -this.result(D); return; } this.A = A; this.B = B; this.C = C; this.D = D; } Plane.prototype = { normal: function () { return new Vector(this.A, this.B, this.C); }, normalize: function () { var length = Math.sqrt(this.A * this.A + this.B * this.B + this.C * this.C); this.A /= length; this.B /= length; this.C /= length; this.D /= length; return this; }, result: function (p) { return this.A * p.x + this.B * p.y + this.C * p.z + this.D; }, clone: function () { return new Plane(this.A, this.B, this.C, this.D); }, revert: function () { this.A = -this.A; this.B = -this.B; this.C = -this.C; this.D = -this.D; return this; }, crossWithRay: function (point, vector) { return point.clone().add( vector.clone().scale( -(Vector.dotProduct(this.normal(), point) + this.D) / Vector.dotProduct(this.normal(), vector) ) ); }, _add: function (p) { this.A += p.A; this.B += p.B; this.C += p.C; this.D += p.D; return this; } }; Plane.average = function (p1, p2, acute, // true/false = разбивать острый/тупой угол impossibleResult // вернется если результат не определен ) { if (arguments.length < 3) { return [ Plane.average(p1, p2, false), Plane.average(p1, p2, true) ]; } p1 = p1.clone().normalize(); p2 = p2.clone().normalize(); var cos = p1.normal().cosWith(p2.normal()); // cos > 0 => сумма нормалей внутри тупого угла => сумма нормальных плоскостей внутри острого var revert = cos > 0 ^ acute; var ret = p1._add(revert ? p2.revert() : p2).normalize(); if (isNaN(ret.A) || isNaN(ret.B) || isNaN(ret.C) || isNaN(ret.D)) ret = (arguments.length == 4) ? typeof(impossibleResult) == 'function' ? impossibleResult() : impossibleResult : console.warn('Plane.average(): impossible'); return ret; } //############################################################################## not linear solutions Solutions = { planesCross: function (p0, p1, p2) { var A = [p0.A, p1.A, p2.A]; var B = [p0.B, p1.B, p2.B]; var C = [p0.C, p1.C, p2.C]; var D = [p0.D, p1.D, p2.D]; return new Vector( -h3(B, C, D) / h3(B, C, A), -h3(C, A, D) / h3(C, A, B), -h3(A, B, D) / h3(A, B, C) ); function h3(A, B, C) { return 0 + C[0] * (A[2] * B[1] - A[1] * B[2]) + C[1] * (A[0] * B[2] - A[2] * B[0]) + C[2] * (A[1] * B[0] - A[0] * B[1]); } }, twoPlanesAndSphere: function (plane0, plane1/*, radius, center*/) { //center = center || Vector(0); //radius = radius || 1; /** * вычел 1) из 2, 3) получается такая система: * 5) Px*A + Py*B + Pz*C = Pd * 6) Qx*A + Qy*B + Qz*C = Qd * +4) A*A + B*B + C*C = 1 */ var P = plane0.normal(), //.subtract(center), Pd = -plane0.D; var Q = plane1.normal(), //.subtract(center), Qd = -plane1.D; // крутанем var mapi = 0, value = 0; for (var i = 0; i < 3; i++) { P.carousel(); Q.carousel(); //mapi++; /** * 5 => 7) A = (Pd - Py*B - Pz*C) / Px * 6 => 8) A = (Qd - Qy*B - Qz*C) / Qx * 7,8 => 9) (Pd - Py*B - Pz*C) * Qx = (Qd - Qy*B - Qz*C) * Px * 9 => 10) (Qy*Px - Py*Qx)*B + (Qz*Px - Pz*Qx)*C = Qd*Px - Pd*Qx * 5,6 => 11) (Qx*Py - Px*Qy)*A + (Qz*Py - Pz*Qy)*C = Qd*Py - Pd*Qy * => переход к новым буквам */ var _Ry = Q.y * P.x - P.y * Q.x, _Rz = Q.z * P.x - P.z * Q.x, _Rd = Qd * P.x - Pd * Q.x; var _Sx = Q.x * P.y - P.x * Q.y, _Sz = Q.z * P.y - P.z * Q.y, _Sd = Qd * P.y - Pd * Q.y; var val = Math.min(Math.abs(_Ry), Math.abs(_Sx)); if (val > value) { var Ry = _Ry, Rz = _Rz, Rd = _Rd; var Sx = _Sx, Sz = _Sz, Sd = _Sd; mapi = i + 1; value = val; } ; } for (var i = 0; i < mapi; i++) { P.carousel(); Q.carousel(); } if (value < 1e-4) console.log('twoPlanesAndSphere(): error'); for (var i = 0; i < mapi; i++) { P.carousel(); Q.carousel(); } /** * 12) Ry*B + Rz*C = Rd * 13) Sx*A + + Sz*C = Sd * +4) A*A + B*B + C*C = 1 */ var Ry2 = Ry * Ry, Sx2 = Sx * Sx, Ry2Sx2 = Sx2 * Ry2; var Sz2 = Sz * Sz, Rz2 = Rz * Rz; /** * 12 => 14) B = (Rd - Rz*C) / Ry * 13 => 15) A = (Sd - Sz*C) / Sx * 12,13,4=>16) Ry2*(Sd - Sz*C)^2 + Sx2*(Rd - Rz*C)^2 + Ry2Sx2*C^2 = Ry2Sx2 * 16 => 17) (Ry2*Sz2 + Sx2*Rz2 + Ry2Sx2)*C^2 - 2*(Ry2*Sd*Sz + Sx2*Rd*Rz)*C + (Ry2*Sd^2 + Sx2*Rd^2 - Ry2Sx2) = 0 */ var a = Ry2 * Sz2 + Sx2 * Rz2 + Ry2Sx2, b = -2 * (Ry2 * Sd * Sz + Sx2 * Rd * Rz), c = Ry2 * Sd * Sd + Sx2 * Rd * Rd - Ry2Sx2; var d = b * b / 4 - a * c; if (d < -1e-16) return []; else if (d < 1e-16) d = 0; d = Math.sqrt(d); //console.log(d); var sols = d ? [(-b / 2 - d) / a, (-b / 2 + d) / a] : [(-b / 2) / a]; if (sols.length != 2) console.log('sols.length=' + sols.length); //console.log([(-b/2 - d)/a, (-b/2 + d)/a]); // var lineNormal = Vector.crossProduct( // pp[0].subtract(pp[0].center || Vector(0)), // pp[1].subtract(pp[1].center || Vector(0))); for (var i = 0; i < sols.length; i++) { var C = sols[i], A = (Sd - Sz * C) / Sx, // 15) B = (Rd - Rz * C) / Ry, // 14) n = new Vector(A, B, C); // debug n.mapi = mapi; n.sols = sols; // крутим обратно (через вперед))) for (var j = mapi; j < 3; j++) { n.carousel(); } sols[i] = n; } return sols; } }; //############################################################################## Orientation = Metrics.Orientation = function () { this.right = new Metrics.Vector(1, 0, 0); this.up = new Metrics.Vector(0, 1, 0); this.forward = new Metrics.Vector(0, 0, 1); }; //using("Metrics.Orientation"); Metrics.Orientation.prototype.clone = function () { var clone = new Metrics.Orientation(); clone.right = this.right.clone(); clone.up = this.up.clone(); clone.forward = this.forward.clone(); return clone; } Metrics.Orientation.prototype.translateVector = function (v) { var x = this.right.x * v.x + this.up.x * v.y + this.forward.x * v.z, y = this.right.y * v.x + this.up.y * v.y + this.forward.y * v.z, z = this.right.z * v.x + this.up.z * v.y + this.forward.z * v.z; if (isNaN(x) || isNaN(y) || isNaN(z)) //alert('Orientation'+this+'.translateVector('+v+'): NaN result ('+x+','+y+','+z+')'); //alert('x = '+this.right.x+' * '+v.x+' + '+this.up.x+' * '+v.y+' + '+this.forward.x+' * '+v.z); //alert('v='+v+', v.x='+v.x+' , v.y='+v.y+' , v.z='+v.z); { var rep = []; for (var i in v) rep[rep.length] = i; error.error.error.error } return new Metrics.Vector( //this.right.x * v.x + this.right.y * v.y + this.right.z * v.z, //this.up.x * v.x + this.up.y * v.y + this.up.z * v.z, //this.forward.x * v.x + this.forward.y * v.y + this.forward.z * v.z x, y, z ); }; Metrics.Orientation.prototype.rotate = function (angle, axis) { this.right = Metrics.Vector.rotate(this.right, angle, axis).normalize(); this.up = Metrics.Vector.rotate(this.up, angle, axis).normalize(); this.forward = Metrics.Vector.rotate(this.forward, angle, axis).normalize(); return this; }; Metrics.Orientation.prototype.rotateFrom = function (vector1, vector2) { vector1 = vector1.normalize(); vector2 = vector2.normalize(); axis = Vector.crossProduct(vector1, vector2); var l12 = Vector.subtract(vector1, vector2).length(); if (l12 < 0.0001) return false; axis.normalize(); var alpha = (Math.PI - Math.atan2(axis.y, axis.z)); // -patched axis = Vector.rotate(axis, alpha, 'x'); var betta = (Math.PI - Math.atan2(axis.x, axis.z)); var gamma = Math.acos((2 - l12 * l12) / 2); this.rotate(alpha, 'x'); this.rotate(betta, 'y'); this.rotate(gamma / 1.4142, 'z'); this.rotate(-betta, 'y'); this.rotate(-alpha, 'x'); return true; }; Metrics.Orientation.prototype.toString = function () { return "(" + this.right + ", " + this.up + ", " + this.forward + ")"; }; //############################################################################## Quat = Metrics.Quat = function (w, x, y, z) { if (arguments.length == 4) { this.w = w; this.x = x; this.y = y; this.z = z; } else { this.w = 1; this.x = 0; this.y = 0; this.z = 0; } }; //using("Metrics.Quat"); Metrics.Quat.prototype.clone = function () { return new Metrics.Quat(this.w, this.x, this.y, this.z); }; Metrics.Quat.prototype.normalize = function () { var length = this.w * this.w + this.x * this.x + this.y * this.y + this.z * this.z; if (Math.abs(length - 1) > 0.001) { length = Math.sqrt(length); this.w /= length; this.x /= length; this.y /= length; this.z /= length; } }; Metrics.Quat.prototype.translateVector = function (v) { var xx = 2 * this.x * this.x; var yy = 2 * this.y * this.y; var zz = 2 * this.z * this.z; var xw = 2 * this.x * this.w; var xy = 2 * this.x * this.y; var xz = 2 * this.x * this.z; var yw = 2 * this.y * this.w; var yz = 2 * this.y * this.z; var zw = 2 * this.z * this.w; return new Metrics.Vector( v.x * (1 - yy - zz) + v.y * (xy + zw) + v.z * (xz - yw), v.x * (xy - zw) + v.y * (1 - xx - zz) + v.z * (yz + xw), v.x * (xz + yw) + v.y * (yz - xw) + v.z * (1 - xx - yy) ); }; Metrics.Quat.multiply = function (q1, q2) { var result = new Quat( q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x, q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w ); result.normalize(); return result; }; Metrics.Quat.fromAxisRotation = function (axisVector, angle) { var sinAngle = Math.sin(angle / 2); return new Metrics.Quat( Math.cos(angle / 2), axisVector.x * sinAngle, axisVector.y * sinAngle, axisVector.z * sinAngle ); }; Metrics.Quat.rotate = function (quat, axisVector, angle) { return Metrics.Quat.multiply(Metrics.Quat.fromAxisRotation(axisVector, angle), quat); }; //############################################################################## Rectangle = Metrics.Rectangle = function (pos, dims) { this.pos = pos.clone(); this.dims = dims.clone(); }; //using("Metrics.Rectangle"); Metrics.Rectangle.prototype.clone = function () { return new Metrics.Rectangle(this.pos, this.dims); }; Metrics.Rectangle.prototype.getPos = function () { return this.pos.clone(); }; Metrics.Rectangle.prototype.getDims = function () { return this.dims.clone(); }; Metrics.Rectangle.prototype.getTopLeft = function () { return this.pos.clone(); }; Metrics.Rectangle.prototype.getTopRight = function () { return new Metrics.Vector(this.pos.x + this.dims.x - 1, this.pos.y); }; Metrics.Rectangle.prototype.getBottomLeft = function () { return new Metrics.Vector(this.pos.x, this.pos.y + this.dims.y - 1); }; Metrics.Rectangle.prototype.getBottomRight = function () { return new Metrics.Vector(this.pos.x + this.dims.x - 1, this.pos.y + this.dims.y - 1); }; Metrics.Rectangle.prototype.overlaps = function (rect) { return (this.pos.x + this.dims.x > rect.pos.x) && (this.pos.y + this.dims.y > rect.pos.y) && (rect.pos.x + rect.dims.x > this.pos.x) && (rect.pos.y + rect.dims.y > this.pos.y); }; Metrics.Rectangle.prototype.containsPoint = function (point) { return point.x >= this.pos.x && point.x + this.pos.x < this.dims.x && point.y >= this.pos.y && point.y + this.pos.y < this.dims.y; }; Metrics.Rectangle.prototype.containsRect = function (rect) { return rect.pos.x >= this.pos.x && rect.pos.x + rect.dims.x <= this.pos.x + this.dims.x && rect.pos.y >= this.pos.y && rect.pos.y + rect.dims.y <= this.pos.y + this.dims.y; }; Metrics.Rectangle.prototype.clipPoint = function (point) { var result = point.clone(); if (result.x < this.pos.x) { result.x = this.pos.x; } else if (result.x >= this.pos.x + this.dims.x) { result.x = this.pos.x + this.dims.x - 1; } if (result.y < this.pos.y) { result.y = this.pos.y; } else if (result.y >= this.pos.y + this.dims.y) { result.y = this.pos.y + this.dims.y - 1; } return result; }; Metrics.Rectangle.prototype.clipRect = function (rect) { var x = Math.max(this.pos.x, rect.pos.x); var y = Math.max(this.pos.y, rect.pos.y); var w = Math.min(this.pos.x + this.dims.x, rect.pos.x + rect.dims.x) - x; var h = Math.min(this.pos.y + this.dims.y, rect.pos.y + rect.dims.y) - y; if (w > 0 && h > 0) { return new Rectangle(new Vector(x, y), new Vector(w, h)); } else { return null; } }; Metrics.Rectangle.prototype.toString = function () { return this.pos + ", " + this.dims; }; //############################################################################## Metrics.getViewportWidth = function (win) { win = win || self; if (win.innerWidth) { // all except IE return win.innerWidth; } if (win.document.documentElement && win.document.documentElement.clientWidth) { // IE6 strict return Math.min(win.document.documentElement.clientWidth, win.document.body.clientWidth); } // other IE return win.document.body.clientWidth; }; Metrics.getViewportHeight = function (win) { win = win || self; if (win.innerHeight) { // all except IE return win.innerHeight; } if (win.document.documentElement && win.document.documentElement.clientHeight) { // IE6 strict return Math.min(win.document.documentElement.clientHeight, win.document.body.clientHeight); } // other IE return win.document.body.clientHeight; }; Metrics.getViewportDims = function (win) { win = win || self; var width, height; if (win.innerWidth) { width = win.innerWidth; height = win.innerHeight; } else if (win.document.documentElement && win.document.documentElement.clientWidth) { // IE6 strict if (win.document.documentElement.clientWidth < win.document.body.clientWidth) { width = win.document.documentElement.clientWidth; height = win.document.documentElement.clientHeight; } else { width = win.document.body.clientWidth; height = win.document.body.clientHeight; } } else { // other IE width = win.document.body.clientWidth; height = win.document.body.clientHeight; } return new Metrics.Vector(width, height); }; Metrics.getViewportTop = function (win) { win = win || self; if (win.pageYOffset !== undefined) { return win.pageYOffset; } if (win.document.documentElement && win.document.documentElement.scrollTop) { return win.document.documentElement.scrollTop; } return win.document.body.scrollTop; }; Metrics.getViewportLeft = function (win) { win = win || self; if (win.pageXOffset !== undefined) { return win.pageXOffset; } if (win.document.documentElement && win.document.documentElement.scrollLeft) { return win.document.documentElement.scrollLeft; } return win.document.body.scrollLeft; }; Metrics.getViewportPos = function (win) { win = win || self; var x, y; if (win.pageYOffset !== undefined) { x = win.pageXOffset; y = win.pageYOffset; } else if (win.document.documentElement && win.document.documentElement.scrollTop) { x = win.document.documentElement.scrollLeft; y = win.document.documentElement.scrollTop; } else { x = win.document.body.scrollLeft; y = win.document.body.scrollTop; } return new Metrics.Vector(x, y); }; Metrics.getViewportRect = function (win) { return new Metrics.Rectangle(Metrics.getViewportPos(win), Metrics.getViewportDims(win)); }; Metrics.getDocumentWidth = function (win) { win = win || self; return Math.max(win.document.body.scrollWidth, win.document.offsetWidth); }; Metrics.getDocumentHeight = function (win) { win = win || self; return Math.max(win.document.body.scrollHeight, win.document.offsetHeight); }; Metrics.getDocumentDims = function (win) { win = win || self; var width, height; if (win.document.body.scrollHeight > win.document.body.offsetHeight) { width = win.document.body.scrollWidth; height = win.document.body.scrollHeight; } else { width = win.document.body.offsetWidth; height = win.document.body.offsetHeight; } return new Metrics.Vector(width, height); }; Metrics.getWidth = function (node) { if (node.offsetWidth !== undefined) { return node.offsetWidth; } else if (node.clientWidth !== undefined) { return node.clientWidth; } else if (node.width !== undefined) { return node.width; } else { throw "Metrics.getWidth doesn't work in this browser"; } }; Metrics.getHeight = function (node) { if (node.offsetHeight !== undefined) { return node.offsetHeight; } else if (node.clientHeight !== undefined) { return node.clientHeight; } else if (node.height !== undefined) { return node.height; } else { throw "Metrics.getHeight doesn't work in this browser"; } }; Metrics.getDims = function (node) { var width, height; if (node.offsetWidth !== undefined) { width = node.offsetWidth; height = node.offsetHeight; } else if (node.clientWidth !== undefined) { width = node.clientWidth; height = node.clientHeight; } else if (node.width !== undefined) { width = node.width; height = node.height; } else { throw "Metrics.getDims doesn't work in this browser"; } return new Metrics.Vector(width, height); }; Metrics.setDims = function (node, dims) { node.style.width = dims.x + "px"; node.style.height = dims.y + "px"; var adjustment = Vector.subtract(dims, Metrics.getDims(node)); if (!adjustment.isZero()) { dims = Vector.add(dims, adjustment); node.style.width = dims.x + "px"; node.style.height = dims.y + "px"; } }; Metrics.getInnerWidth = function (node) { if (node.clientWidth !== undefined) { return node.clientWidth; } else if (node.width !== undefined) { return node.width; } else { throw "Metrics.getInnerWidth doesn't work in this browser"; } }; Metrics.getInnerHeight = function (node) { if (node.clientHeight !== undefined) { return node.clientHeight; } else if (node.height !== undefined) { return node.height; } else { throw "Metrics.getInnerHeight doesn't work in this browser"; } }; Metrics.getInnerDims = function (node) { var width, height; if (node.clientWidth !== undefined) { width = node.clientWidth; height = node.clientHeight; } else if (node.width !== undefined) { width = node.width; height = node.height; } else { throw "Metrics.getInnerDims doesn't work in this browser"; } return new Metrics.Vector(width, height); }; Metrics.getOffsetLeft = function (node) { return node.offsetLeft; }; Metrics.getOffsetTop = function (node) { return node.offsetTop; }; Metrics.getOffsetPos = function (node) { return new Metrics.Vector(node.offsetLeft, node.offsetTop); }; Metrics.getOffsetRect = function (node) { return new Metrics.Rectangle(Metrics.getOffsetPos(node), Metrics.getDims(node)); }; Metrics.setOffsetPos = function (node, pos) { node.style.left = pos.x + "px"; node.style.top = pos.y + "px"; }; Metrics.setOffsetRect = function (node, rect) { Metrics.setOffsetPos(node, rect.pos); Metrics.setDims(node, rect.dims); }; Metrics.getLeft = function (node) { var x = 0; do { x += node.offsetLeft; node = node.offsetParent; } while (node); return x; }; Metrics.getTop = function (node) { var y = 0; do { y += node.offsetTop; node = node.offsetParent; } while (node); return y; }; Metrics.getPos = function (node) { var x = 0; var y = 0; do { x += node.offsetLeft; y += node.offsetTop; node = node.offsetParent; } while (node); return new Metrics.Vector(x, y); }; Metrics.getRect = function (node) { return new Metrics.Rectangle(Metrics.getPos(node), Metrics.getDims(node)); }; Metrics.setPos = function (node, pos) { if (node.offsetParent) { var offsetPos = Vector.subtract(pos, Metrics.getPos(node.offsetParent)); Metrics.setOffsetPos(node, offsetPos); } else { Metrics.setOffsetPos(node, pos); } }; Metrics.setRect = function (node, rect) { Metrics.setPos(node, rect.pos); Metrics.setDims(node, rect.dims); }; </script> <script type="text/javascript">/** * Figure is an object with properties: * .$points $([points]) * .type string * * Vertex, Line, Face and Polygon definition. * * @author popitch@yandex.ru */ function Figure(params) { // self as origin this.origin = this; // origin may be updated here $.extend(this, params); // базовые точки this.$points = $(params.$points || params.points || console.log('Figure(): points not present')); this.$points.length > 0 || console.log('Figure(): wrong count of points'); // тип this.type = this.type || (this.$points.length < 4 ? [null, 'vertex', 'line', 'face'][this.$points.length] : 'polygon'); this.removed = false; this._enum = Figure.__enum++; } Figure.__enum = 0; Figure.prototype = { // поворот точек фигуры вокруг оси rotate: function (angle, axis) { this.$points.each(function () { var v = Vector.rotate(this, angle, axis); this.x = v.x; this.y = v.y; this.z = v.z; }); return this; }, // возвращает массив примитивов primitives: function () { return $([this]); }, /** * Деление фейсов фигуры (равные хорды) * @return this */ splitFaces: function (N) { N = N || 2; var figure = this; var points = {}; figure.$points.each(function (i) { points[this._enum = this._enum || i] = this; }); var $faces = $([]); function addFace(a, b, c) { $faces.push(new Figure({ type: 'face', $points: $([a, b, c]).map(function () { return points[this] }) })); addLine(a, b); addLine(b, c); addLine(c, a); } var lines = {}; function addLine(a, b) { var uniq = [a, b].sort().join('-'); lines[uniq] = lines[uniq] || new Figure({ type: 'line', $points: $([a, b]).map(function () { return points[this] }) }); } var verts = {}, $splitted = $([]); figure.$primitives.each(function (i) { if (this.type == 'face') { var face = this; var f = face.$points.map(function () { return this._enum; }).get(); var mini = f.slice(0).sort(function (a, b) { return a - b })[0]; while (f[0] != mini) f.push(f.shift()); var ai = f[0], bi = f[1], ci = f[2]; var up = [ai]; for (var n = 1; n <= N; n++) { var lu = [ai, bi, n].join('-'), li = verts[lu] || (verts[lu] = figure.splitFaces_middlePointEnum(ai, bi, n / N, points)); var ru = [ai, ci, n].join('-'), ri = verts[ru] || (verts[ru] = figure.splitFaces_middlePointEnum(ai, ci, n / N, points)); var down = [], i; for (i = 0; i <= n; i++) { var mu = (li < ri) ? '' + li + '-' + ri + '-' + i : '' + ri + '-' + li + '-' + (n - i); var mi = verts[mu] ? verts[mu] : (verts[mu] = figure.splitFaces_middlePointEnum(li, ri, i / n, points)); down.push(mi); } addFace(up[0], down[0], down[1]); for (i = 1; i < up.length; i++) { addFace(up[i], up[i - 1], down[i]); addFace(up[i], down[i], down[i + 1]); } up = down; } $splitted.push(face); } }); // заливаем новую форму figure.$primitives = $faces; figure.$points.each(function () { figure.$primitives.push(new Figure({ type: 'vertex', points: [this], center: this.center })); }); for (var i in lines) { figure.$primitives.push(lines[i]); } // добавляем преобразование к названию фигуры this.type += '.' + 'v(' + N + ')'; return this; }, splitFaces_middlePointEnum: function (ai, bi, q, enum2point) { if (q == 0) return ai; if (q == 1) return bi; var a = enum2point[ai], b = enum2point[bi]; // определение центра кривизны var center, selvage = a.center && (center = b.center); center = selvage ? center : new Vector(); /*selvage || (center.radius = 1);*/ var point = Vector.add( Vector.subtract(a, center).scale(1 - q), Vector.subtract(b, center).scale(q) ).normalize()./*scale(center.radius).*/add(center); selvage && (point.center = center); point._enum = this.$points.length; this.$points.push(point); enum2point[point._enum] = point; return point._enum; }, /** * срез фигуры по координате * @return this */ sliceByAxis: function (axis, partial, filtrate) { if (partial == '1' || partial == '1/1') { _.each(this.$primitives, function (p) { p.live = true; }); return this; } var threshold = 1 - 2 * eval(partial); this.$points.each(function () { this._remain = 0; }); this.$primitives.each(function () { var $pp = this.$points, centroid = 0; if ($pp.length >= 3) { $.map($pp, function (p) { centroid += p[axis]; }); centroid /= $pp.length; if (Math.abs(centroid - threshold) > 1e-6 && centroid > threshold) { $.map($pp, function (p) { p._remain = 1; }); } } }); this.$primitives = this.$primitives.map(function () { var saved = 0; this.$points.each(function () { saved += this._remain || 0; }); this.live = (saved == this.$points.length); return (filtrate === false) || this.live ? this : null; }); this.$points = this.$points.map(function () { var live = (filtrate === false) || this._remain; delete this._remain; return live ? this : null }); this.points = this.$points.get(); return this; }, /** * срез фигуры по остающейся доле фейсов в результате */ sliceByFraction: function (startVertex, fraction, filtrate) { if (fraction == '1' || fraction == '1/1') { _.each(this.$primitives, function (p) { p.live = true; }); return this; } fraction = eval(fraction); var $all = this.$primitives; var facesTotal = this.subs('face').length; var $wave = startVertex.$super.face; for (var faces = 0; faces / facesTotal < fraction;) { $wave.each(function () { $(this).add(this.$sub.line).add(this.$sub.vertex).each(function () { this.live = true; }); this.$sub.line.each(function () { this.$super.face.each(function () { this._ready = true; }); this.$points.each(function () { this.live = true; }); }); faces++; }); $wave = $all.filter(function () { return this._ready && !this.live; }); } // live if live origin $all.each(function () { this.live = this.origin.live; delete this._ready; }); if (filtrate !== false) { this.$primitives = $all.filter(function () { return this.live; }); this.$points = this.$points.filter(function () { var leave = this.live; delete this.live; return leave; }); this.points = this.$points.get(); } return this; }, /** * Making a (inscribed) fulleren */ fulleren: function () { var pointsBefore = this.$points.length; var fig = this, newVertexByLine = {}, fullerPrimitives = [], nil = Vector(0); function divideLine(near, far, line) {/* var vertex; if (!near.H) { near.H = _.reduce(near.$super.line, function(H, line) { var l = Vector.distance(line.$points[0], line.$points[1]); line.H = l * l / 2; return H + line.H; }, 0); near.H = near.H / near.$super.line.length; */ /*Math.pow(near.H, 1 / near.$super.line.length);*/ /* } var q = near.H / line.H / 3; // 1/3; var mid = near.$points[0].clone().scale(1 - q).add(far.$points[0].clone().scale(q)); //mid.scale(1 / mid.length()).add(line.center);*/ var Near = near, vertex; near = near.$points[0].clone().subtract(near.center); far = far.$points[0].clone().subtract(far.center); //var alfa = near.angleWith(far); var q = 1 / 3;//0.5 - Math.tan(alfa / 6) * ( 0.5 / Math.tan(alfa / 2) ); var mid = Vector.add(near.scale(1 - q), far.scale(q)); mid.scale(1 / mid.length()).add(line.center); mid.center = line.center; mid.selvage = line.selvage; mid.sliced = line.sliced; // вершины рождаются здесь fig.$points.push(mid); fullerPrimitives.push(vertex = new Figure({ type: 'vertex', points: [mid], center: near.center || nil, selvage: near.selvage, sliced: near.sliced })); return vertex; } // вершины образуются из ребер, по две на каждое fig.$primitives.each(function () { if (this.type == 'line') { var le = this._enum, vv = this.$sub.vertex; var vA = divideLine(vv[0], vv[1], this); var vB = divideLine(vv[1], vv[0], this); newVertexByLine[le] = [vA, vB]; // ребра-остатки (середина базовых), половина всех ребер fullerPrimitives.push(new Figure({ type: 'line', points: [vA.$points[0], vB.$points[0]], center: this.center, selvage: this.selvage, sliced: this.sliced/*, baseLineLength: Math.round(Vector.distance(vv[0].$points[0], vv[1].$points[0]) * 1e-6)*/ })); } }); // ищет в фейсе новые вершины, образованные от заданных, возвращает в том же порядке function getNewPoints(p0, p1, face) { var ret; face.$sub.line.each(function () { var vv = this.$sub.vertex; var nvv = newVertexByLine[this._enum]; ret = ret || (vv[0].$points[0] == p0 && vv[1].$points[0] == p1 && nvv) || (vv[0].$points[0] == p1 && vv[1].$points[0] == p0 && [nvv[1], nvv[0]]); }); return [ret[0].$points[0], ret[1].$points[0]]; } // для вершинных фейсов var newVertexesByVertex = {}; // грани и половина ребер fig.$primitives.each(function () { if (this.type == 'face') { var face = this; var p0 = face.$points[1], p1 = face.$points[2]; var v6 = []; face.$points.each(function () { var p2 = this; /*var baseLine = face.$sub.line.filter(function() { return (this.$points[0] === p0 && this.$points[1] === p2) || (this.$points[1] === p0 && this.$points[0] === p2); })[ 0 ];*/ // точки нового фейса-остатка var nvv01 = getNewPoints(p0, p1, face); v6.push(nvv01[0]); v6.push(nvv01[1]); // ребра-скосы (образованные срезанием вершины), половина всех ребер var nvv12 = getNewPoints(p1, p2, face); fullerPrimitives.push(new Figure({ type: 'line', points: [nvv01[1], nvv12[0]]/*, baseLineLength: Math.round(Vector.distance(baseLine.$points[0], baseLine.$points[1]) * 1e+6)*/ })); // для вершинных фейсов newVertexesByVertex[p1._enum] = newVertexesByVertex[p1._enum] || {}; newVertexesByVertex[p1._enum][p2._enum] = { point: nvv12[0], next: p0._enum }; p0 = p1; p1 = p2; }); if (v6.length != 6) console.log('v6.length != 6'); // фейсы-остатки (середина фейсов-предшественников), столько же сколько было фейсов fullerPrimitives.push(new Figure({ type: 'face', points: v6 })); } }); // фейсы-скосы (при вершинах, кроме крайних пока) fig.$primitives.each(function () { if (this.type == 'vertex' && !this.selvage) { var aster = newVertexesByVertex[this.$points[0]._enum], c = 0; for (var i in aster) c++; if (c >= 5) { var last = i, pp = []; do { pp.push(aster[i].point); i = aster[i].next; } while (i != last); if (pp.length < 5) console.log('face points.length < 5'); // фейсы-скосы (при вершинах), столько же сколько было вершин fullerPrimitives.push(new Figure({ type: 'face', points: pp })); } } }); this.$primitives = $(fullerPrimitives); this.$points = $(Array.prototype.slice.call(this.$points, pointsBefore)); /*Figure.equalizeLineGroups( _.groupBy(_.where(this.$primitives, { type: 'line' }), 'baseLineLength') );*/ return this; }, /** * @required prepareUnify() before */ outerFulleren: function () { var prevVertexes = this.subs('vertex'), prevFaces = this.subs('face'), nextLines = {}, center = new Vector; // todo: remove center from project var nextVertexes = _.map(prevFaces, function (face) { face.newPoint = Solutions.planesCross.apply(this, _.map(face.$points, function (point) { return new Plane(point, point); }) ); var nextVertex = new Figure({ type: 'vertex', points: [face.newPoint], center: center }); face.newPoint._enum = nextVertex._enum; return nextVertex; }); var nextFaces = _.map(prevVertexes, function (vertex) { var points = _.compact(_.map(vertex.$scheme, function (mem) { return mem.isFace && mem.source.newPoint; })); var prevPoint = _.last(points); _.each(points, function (point) { var lineIndex = [point._enum, prevPoint._enum].sort().join(); nextLines[lineIndex] = nextLines[lineIndex] || new Figure({ type: 'line', points: [prevPoint, point] }); prevPoint = point; }); return new Figure({ type: 'face', points: points, _protoPoint: vertex.$points[0] }); }); this.$primitives = $(nextFaces.concat(_.values(nextLines)).concat(nextVertexes)); this.$points = $(_.pluck(_.pluck(nextVertexes, '$points'), '0')); return this; }, /** * Устанавливает отношения (вложенность) примитивов фигуры * @return this */ relations: function () { var $primitives = this.$primitives; // sub & super $primitives.each(function () { var prim = this; prim.$sub = {vertex: $([]), line: $([])}; var a = this.$points; this.$subsets = $primitives.map(function (pi) { var b = this.$points; if (b.length < a.length) { for (var i = 0, length = b.length; i < length; i++) if (-1 == $.inArray(b[i], a)) { return null; } if (!prim.$sub[this.type]) console.log('!prim.$sub[this.type]'); prim.$sub[this.type].push(this); return this; } return null; }); this.$supersets = $([]); this.$super = {line: $([]), face: $([])}; }); $primitives.each(function () { var prim = this; this.$subsets.each(function () { this.$supersets.push(prim); this.$super[prim.type].push(prim); }); }); // figure subsets, supersets is null this.$subsets = $primitives; this.$supersets = null; // sort face's sub-vertexes in self-points order this.subs('face').each(function () { var face = this; face.$sub.vertex = $( _.sortBy(face.$sub.vertex, function (vertex) { return _.indexOf(face.$points, vertex.$points[0]); }) ); }); // selvage detection this.detectSelvage(); // why this? return this; }, // selvage detection detectSelvage: function (advAttr) { this.$primitives.each(function () { this.selvage = false; if (this.type == 'line') this.faceCount = 0; }); this.$primitives.each(function () { if (this.type == 'face') this.$sub.line.each(function () { this.faceCount++; }); }); this.$primitives.each(function () { if (this.type == 'line') if (this.selvage = (this.faceCount == 1)) { this.$subsets.each(function () { this.selvage = true; if (advAttr) { this[advAttr] = true; } }); if (advAttr) { this[advAttr] = true; } } }); return this; }, // adv relations prepareUnify: function () { // order line/face/line/face/.. around vertex this.subs('vertex').each(function () { var vertex = this; var point = vertex.$points[0]; var chain = []; // список звеньев цепочки, с указанием остальных составляющих звено точек vertex.$supersets.each(function (i) { var pp = this.$points.get(); var pos = $.inArray(point, pp); var others = pp.slice(pos + 1).concat(pp.slice(0, pos)); var isFace = (others.length > 1); chain[i] = { i: i, source: this, others: others, isFace: isFace }; if (isFace) chain[i].faceAngle = Vector.angle(others[0], point, others[others.length - 1]); else {// line chain[i].length = point.distance(others[0]); if (chain[i].length < 1e-6) console.log('rib length is nil'); } }); var iLost = undefined, countNext = 0, countLost = 0; // каждому звену прописывается индекс следующего vertex.$supersets.each(function (i) { var iOthers = chain[i].others; var iFace = iOthers.length > 1; var found = vertex.$supersets.map(function (j) { var jOthers = chain[j].others; return (jOthers.length > 1 ^ iOthers.length > 1) ? ( iOthers[iOthers.length - 1] === jOthers[0] ? ++countNext && j : null ) : null; }); if (found.length > 1) console.log('gt one next chain nodes this'); var h = found[0]; if (h !== undefined) { chain[i]._next = h; } else { iLost = i; ++countLost; } }); // asserts if (countNext > vertex.$supersets.length) console.log(countNext + ' countNext > vertex.$supersets.length'); if ((countNext == vertex.$supersets.length) == vertex.selvage) console.log('(countNext == vertex.$supersets.length) == vertex.selvage'); if ((countNext == vertex.$supersets.length - 1) != vertex.selvage) console.log('(countNext == vertex.$supersets.length - 1) != vertex.selvage'); if (countNext < vertex.$supersets.length - 1) console.log('countNext < vertex.$supersets.length - 1'); if (countLost > 1) console.log({countLost: countLost, countNext: countNext, chain: chain}); (iLost !== undefined) === vertex.selvage || console.log('selvage is not salve: ' + iLost + ', ' + countLost); (iLost !== undefined) === (countLost == 1) || console.log('selvage is not salve2: ' + iLost + ', ' + countLost); // break the chain var sortChains = []; $(chain).each(function (i) { var start = this, curr = this; for (sortChains[i] = []; curr && sortChains[i].push(curr) && (curr = chain[curr._next]) !== start; ) ; }); sortChains.sort(function (a, b) { if (b.length - a.length) return b.length - a.length; for (var i = 0, l = a.length, d; i < l; i++) { d = (b[i].faceAngle - a[i].faceAngle) || (b[i].length - a[i].length); if (Math.abs(d) > 1e-3) return d; } return 0; }); // сохраняем упорядоченный, выбранный список надмножеств vertex.$scheme = $(sortChains[0]); }); // для линий: вершины, дополняющие соседние фейсы this.subs('line').each(function () { var line = this; line.$vertexes = line.$sub.vertex; line.$adjoinVertexes = $([]); line.$adjoinPoints = $([]); line.$super.face.each(function () { this.$sub.vertex.each(function () { if (-1 == $.inArray(this, line.$vertexes)) line.$adjoinVertexes.push(this); line.$adjoinPoints.push(this.$points[0]); }); }); // для линий: для каждой вершины список линий соседних к линии-сабжу line.$nearLinesByVertex = $([]); line.$vertexes.each(function () { var vertex = this, point = this.$points[0], cont = $([]); vertex.$super.line.each(function () { if (this === line) return; if (this.$points[0] === point && -1 != $.inArray(this.$points[1], line.$adjoinPoints)) cont.push(this); if (this.$points[1] === point && -1 != $.inArray(this.$points[0], line.$adjoinPoints)) cont.push(this); }); line.$nearLinesByVertex.push(cont); }); if (line.$nearLinesByVertex.length != 2) console.log('line.$nearLinesByVertex.length != 2'); if (-1 == $.inArray(line.$nearLinesByVertex[0].length, [1, 2])) console.log('line.$nearLinesByVertex.length[0].length: ' + line.$nearLinesByVertex[0].length); if (-1 == $.inArray(line.$nearLinesByVertex[1].length, [1, 2])) console.log('line.$nearLinesByVertex.length[1].length: ' + line.$nearLinesByVertex[1].length); }); // фейсам выстроим sub- отрезки и вершины по-порядку this.subs('face').each(function () { var $vv = this.$sub.vertex; var mid = new Vector; $vv.each(function () { mid.add(this.$points[0]); }); mid.scale(1 / $vv.length); function orderedVertexes(line) { var $vv = line.$sub.vertex; var dir = Vector.crossProduct( Vector.subtract($vv[0].$points[0], mid), Vector.subtract($vv[1].$points[0], mid) ); return Vector.dotProduct(dir, mid) > 0 ? $vv : $([$vv[1], $vv[0]]); } var order = {}, i; this.$sub.line.each(function () { var vv = orderedVertexes(this); order[vv[0]._enum] = { line: this, vv: vv, next: i = vv[1]._enum }; }); var vertexes = []; var lines = []; for (var end = i; lines.push(order[i].line) && vertexes.push(order[i].vv[0]) && order[i].next != end; i = order[i].next) ; this.$sub.line = $(lines); this.$sub.vertex = $(vertexes); }); return this; }, // pseudo-self-remove the member remove: function () { if (this.removed) return []; var removed = [this]; this.removed = true; this.$supersets.each(function () { removed = removed.concat(this.remove()); }); this.$subsets.each(function () { var superPresent = this.$supersets.filter(function () { return !this.removed; }); if (!superPresent.length) removed = removed.concat(this.remove()); }); return removed; }, // restore pseudo-removed member restore: function () { if (!this.removed) return []; var restored = [this]; this.removed = false; this.$subsets.each(function () { restored = restored.concat(this.restore()); }); return restored; }, subs: function (type) { return type ? this.$subsets.filter(function () { return this.type === type; }) : this.$subsets; }, supers: function (type) { return type ? this.$supersets.filter(function () { return this.type === type; }) : this.$supersets; }, /** * Приземление кромки фигуры */ groundSliced: function (axis) { var points = $.map(this.$primitives, function (p) { if (p.type !== 'vertex' || !p.live) return null; return _.some(p.$supersets, function (s) { return !s.live }) ? p.$points[0] : null; }); var aval = false; // find minimal-absolute value by axis _.each(points, function (p) { aval = aval && Math.abs(aval) < Math.abs(p[axis]) ? aval : p[axis]; }); _.each(points, function (p) { if (Math.abs(p[axis] - aval) > 1e-6) { p[axis] = aval; var len = p.length(), q = Math.sqrt((1 - aval * aval) / (len * len - aval * aval)); if (axis != 'x') p.x *= q; if (axis != 'y') p.y *= q; if (axis != 'z') p.z *= q; } }); }, /** * Унификация примитивов, поиск одинаковых * @return Object stat * * $todo insert product eacher */ unify: function () { var result = {total: {}, count: {}}; // для некоторых соединений, перед унификацией "крайних" узлов // требуется аккумулятор для накопление инфы об остальных узлах var accum = {}; // сначала те, что не на краю, // и в порядке: коннекторы, ребра, грани var hashOrder = _.where(this.$primitives, {removed: false}); _.each(['vertex', 'line', 'face'], function (type) { var stat = {}; var ordered = $.map(hashOrder, function (f) { return f.type == type && f.live ? f : null }) .sort(function (a, b) { if (a.selvage != b.selvage) return (a.selvage ? 1 : 0) - (b.selvage ? 1 : 0); if (a.type == 'vertex') return a.$points[0].y - b.$points[0].y; return 0; }); $(ordered).each(function (i) { var unifier = this.unifier = this.unifier || (this.product ? this.product.unify(accum) : '<unkn>'); unifier = unifier.replace(/\(\d+\)/g, ''); stat[unifier] = stat[unifier] || []; stat[unifier].push(this); }); // сортировка коллекции по убыванию кол-ва элементов данного типа var keys = []; $.each(stat, function (key, cont) { keys.push({key: key, cont: cont}); }); // сортировка keys.sort(function (a, b) { // по убыванию кол-ва элементов данного типа if (b.cont.length != a.cont.length) return (b.cont.length - a.cont.length); // line: compare lengths if (type == 'line') { var diff = b.cont[0].product.maxLength() - a.cont[0].product.maxLength(); if (diff) return diff; } // сравнение строк-унификаторов if (a.key !== b.key) { return ([a.key, b.key].sort()[0] === a.key) ? 1 : -1; } console.warn('Undefined sort order detected'); }); result[type] = {}; result.total[type] = 0; result.count[type] = 0; $.each(keys, function (order) { var index = Product.index(this.cont[0].type, order); result[type][index] = { count: this.cont.length, unifier: this.key, index: index, order: order, collect: this.cont }; $(this.cont).each(function () { this.index = index; this.order = order; //this.groups = result[type]; }); result.total[type] += this.cont.length; result.count[type]++; }); }); // вычисление максимальной длины ребра var maxOuter = 0, minOuter = Infinity, minInner = null; $.each(result.line, function (index, stat) { var outer = stat.collect[0].product.maxLength(); var inner = stat.collect[0].product.minLength(); maxOuter = outer > maxOuter ? outer : maxOuter; minOuter = outer < minOuter ? outer : minOuter; minInner = inner < minInner || minInner === null ? inner : minInner; }); $.each(result.line, function (index, stat) { stat.collect[0].product.maxOuterLength = maxOuter; stat.collect[0].product.minOuterLength = minOuter; stat.collect[0].product.minInnerLength = minInner; }); return this.stat = result; }, visible: function () { if (this.type == 'polygon' || this.type == 'face') { var $p = this.$points.map(function () { return this.plane }); return 0 < $p[1].x * $p[2].y - $p[1].y * $p[2].x + $p[2].x * $p[0].y - $p[2].y * $p[0].x + $p[0].x * $p[1].y - $p[0].y * $p[1].x; } return true; }, prepareVisibility: function () { this.$primitives.each(function () { this.isVisible = false; }); this.$primitives.each(function () { if (this.type == 'face') { if (this.isVisible = this.visible()) { this.$subsets.each(function () { this.isVisible = true; }); } } }); } } // делает точки окружности равноудаленными с соседями (точки в начале должны быть в одной плоскости) Figure.pointsEquidistant = function ($points, center, radius) { // приведение точек к окружности function circle() { $points.each(function () { this.subtract(center); this.scale(radius / this.length()); this.add(center); }); } // соседи var $near = []; $points.each(function (i) { var point = this, arr, $dist = []; $near[i] = ( (arr = $points.get() .sort(function (a, b) { return a.distance(point) - b.distance(point); })) .slice(1, 3) ); }); // итерируем пока не понравится результат function aberration() { return $points.map(function (i) { return Math.abs($near[i][0].distance(this) - $near[i][1].distance(this)); }).get().sort(function (a, b) { return a - b; }).pop(); } do { // уводим точки в сторону более удаленного соседа var $dirs = $points.map(function (i) { return $near[i][0].clone().subtract(this).add($near[i][1]).subtract(this); }); $points.each(function (i) { this.add( $dirs[i].scale(1 / 5) ); }); circle(); } while (aberration() > 1e-15); } /** * @constructor Container */ Figure.Container = function (params) { params = params || {}; var $points = params.points ? $(params.points) : $params.points || $([]); var $figures = params.figures ? $(params.figures) : $params.figures || $([]); var $primitives = $([]); $figures.each(function (i) { $primitives = $.merge($primitives, this.primitives()); //this.source = params.source || console.log('Figure.Container: !source'); }); // parent::construct() Figure.apply(this, [$.extend({ type: 'container', $points: $points, $figures: $figures, $primitives: $.unique($primitives) }, params)]); } .inherits(Figure); /** * @constructor Icosahedron */ Figure.Icosahedron = function (params) { var center = Vector(0); // defaults params = $.extend( { symmetry: 'Pentad' }, params || {} ); // золотой ключик var a = 4 / Math.sqrt(2 * (5 + Math.sqrt(5))) / 2, b = Math.sqrt(1 - a * a), primitives = []; // вершины var points = [ [-a, 0.0, b], [a, 0.0, b], [-a, 0.0, -b], [a, 0.0, -b], [0.0, b, a], [0.0, b, -a], [0.0, -b, a], [0.0, -b, -a], [b, a, 0.0], [-b, a, 0.0], [b, -a, 0.0], [-b, -a, 0.0] ]; for (var i = 0; i < points.length; i++) { points[i] = $.extend( new Vector(points[i][0], points[i][1], points[i][2]), { _enum: i, pptPoint: true } ); // вершина primitives.push(new Figure({ type: 'vertex', points: [points[i]], center: center })); } // грани & ребра var faces = [ [0, 4, 1], [0, 9, 4], [9, 5, 4], [4, 5, 8], [4, 8, 1], [8, 10, 1], [8, 3, 10], [5, 3, 8], [5, 2, 3], [2, 7, 3], [7, 10, 3], [7, 6, 10], [7, 11, 6], [11, 0, 6], [0, 1, 6], [6, 1, 10], [9, 0, 11], [9, 11, 2], [9, 2, 5], [7, 2, 11] ], snakeTail = {0: 1, 1: 2, 2: 0}; for (var i = 0; i < faces.length; i++) { var f = faces[i]; // грань primitives.push(new Figure({ type: 'face', points: [points[f[0]], points[f[1]], points[f[2]]] })); for (var m in snakeTail) { var n = snakeTail[m]; if (f[m] < f[n]) { // ребро primitives.push(new Figure({ type: 'line', points: [points[f[m]], points[f[n]]] })); } } } // parent::construct() Figure.apply(this, [$.extend({ type: 'Icosahedron', $points: $(points), $primitives: $(primitives) }, params)]); // orientate figure for given rotational symmetry around given axis switch (params.symmetry) { case 'Pentad': this.rotate(Math.atan(a / b), {y: 'x', z: 'y', x: 'z'}[params.axis]); break; case 'Cross': break case 'Triad': this.rotate(Math.asin(2 / (Math.sqrt(3) + Math.sqrt(15))), {y: 'z', z: 'x', x: 'y'}[params.axis]); break; } } .inherits(Figure) .override({ primitives: function () { return this.$primitives; } }); /** * @constructor http://en.wikipedia.org/wiki/Pentakis_dodecahedron */ Figure.PentakisDodecahedron = function (params) { Figure.Icosahedron.call(this, params); this.relations(); var base = this; var points = this.$points; primitives = this.subs('vertex'); _.each(this.subs('face'), function (f) { var p = _.reduce(f.$points, Vector.add, new Vector).normalize(); points.push(p); p._enum = primitives.length; primitives.push(new Figure({points: [p]})); f._dodCenter = p; }); _.each(this.subs('face'), function (f) { var C = f._dodCenter; var lines = f.subs('line'); var B = f.$points[2]; _.each(f.$points, function (A) { var line = _.filter(lines, function (l) { var pair = l.$points; return (pair[0] === A && pair[1] === B) || (pair[1] === A && pair[0] === B); })[0]; var anotherFace = _.difference(line.supers('face'), [f])[0]; addFace([C, anotherFace._dodCenter, A]) B = A; }); }); this.$points = $(this.points = points); this.$primitives = $(primitives); this.type = 'PentakisDodecahedron'; function addFace(tri) { primitives.push(new Figure({points: tri})); for (var i = 0, j = 2; i < 3; j = i++) { var A = tri[j], B = tri[i]; if (A._enum < B._enum) { // ребро primitives.push(new Figure({points: [A, B]})); } } } } .inherits(Figure); </script> <script type="text/javascript">/** * Абстракция изделия, необходимого для постройки кислосферы. * * @author popitch@yandex.ru */ Product = function (params) { $.extend(this, params); this.cache = {}; } .override({ // точность вычислений //PRECISION: 10000, //round: function(value) { // return Math.round(value * this.PRECISION) / this.PRECISION; //}, // @return string that defines the product unify: function () { console.log(['abstract method unify()', this]); }, // @return figure that defines the product model: function () { //console.log(['abstract method model()', this]); //alcohol yad // default null model return null; }, // draw product scheme on canvas //plot: function(canvas){}, // product meter meter: function () { return {}; } }) .statics({ characters: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), index: function (type, order) { if (type == 'line') return (order >= 26 ? Product.index(type, Math.floor(order / 26) - 1) : '') + Product.characters[order % 26]; else return order + 1; }, selectChain: function (chain, nodeAttrScalar, cyclic, bilateral) { chain = $(chain).get(); function breaked(i) { var sample = chain.slice(i).concat(chain.slice(0, i)); var arr = sample.slice(); var forward = [], el, i = 0; do { if (el = arr.shift()) { forward.push({ forward: true, sequence: forward, i: i++, node: el }); } } while (el && !el.terminate); forward[0].node.dontStart || list.push(forward); if (!bilateral) { arr = sample.slice(); var reversed = []; i = 0; do { if (el = arr.pop()) { reversed.push({ forward: false, sequence: reversed, i: i++, node: el }); } } while (el && !el.terminate); reversed[0].node.dontStart || list.push(reversed); } }; var list = []; cyclic ? $(chain).each(breaked) : breaked(0); function zeroDetector(v) { return (Math.abs(v) < 1e-5) ? 0 : v; } var cmp; switch (typeof nodeAttrScalar) { case 'string': cmp = function (a, b) { return zeroDetector(b.node[nodeAttrScalar] - a.node[nodeAttrScalar]); }; break; case 'function': cmp = function (a, b) { return zeroDetector( nodeAttrScalar.call(b.node, b.i, b.sequence, b.forward) - nodeAttrScalar.call(a.node, a.i, a.sequence, a.forward)); }; break; default: console.log('Product.selectChain(): wrong comparator') } // caching sequences of actual values $.map(list, function (seq) { seq.used = $.map(seq, function (a) { return a.node.sortIgnore ? null : a; }); }); // get sorted first // TODO: use one-cicle algorithm to search var selected = list.sort(function (A, B) { if (B.used.length - A.used.length) return (B.used.length - A.used.length); for ( var i = 0, res = 0; i < A.used.length && !(res = cmp(A.used[i], B.used[i])); i++ ) ; return res; })[0]; return $(selected).map(function () { this.node.forward = this.forward; return this.node; }).get(); }, // number unifiers ANGLE_PRECISION: 0.1, // degrees LENGTH_PRECISION: 0.001, // m (to 1 mm) angleUnify: function (angle) { angle = angle * 180 / Math.PI; return Math.round(angle / Product.ANGLE_PRECISION); }, lengthUnify: function (length) { return Math.round(length / Product.LENGTH_PRECISION); } });</script> <script type="text/javascript">/** * Определение продукта многоугольник * * @author popitch [at yandex.ru] */ Product.Polygon = function () { Product.apply(this, arguments); // expected this.face || console.log('face not specified'); } .inherits(Product) .override({ /** отдает вершины продуктового полигона * в сложном случае (например, Joint) вершины не совпадают с вершинами базовой фигуры, задающей форму купола */ realPoints: function () { var face = this.face; return this.cache.$reals = this.cache.$reals || face.$sub.vertex.map(function () { var vertex = this, point = vertex.$points[0]; var planes = $.map(face.bindedLines || face.$sub.line, function (line) { line = line.origin; return (line.$points[0] == point || line.$points[1] == point) ? line.product.getPlane() : null; }); var sols = $(Solutions.twoPlanesAndSphere(planes[0], planes[1])).each(function () { this._offset = this.distance(point); }); sols.length == 2 || console.log('polygon unify(): sols.length=' + sols.length); var result = sols[0]._offset < sols[1]._offset ? sols[0] : sols[1]; // ~ result.scale(point.length()); result.vertex = vertex; vertex.real = result; return result; }); }, realCenter: function () { if (this.cache.realCenter) return this.cache.realCenter; var center = new Vector, $points = this.realPoints(); $.map($points, function (p) { center.add(p); }); return this.cache.realCenter = center.scale(1 / $points.length); } }); Product.Polygon.Simple = function (face, params) { // parent() Product.Polygon.apply(this, [$.extend({ type: 'Polygon', title: 'Многоугольник', bilateral: false, face: face }, params || {})]); } .inherits(Product.Polygon) .override({ unify: function (accum) { var product = this; var $reals = this.realPoints(); if (this.face._protoPoint) { var center = this.face._protoPoint; } else { center = new Vector; $reals.each(function () { center.add(this); }); center.scale(1 / $reals.length); } // normal this.normal = Vector.crossProduct( Vector.subtract($reals[0], center), Vector.subtract($reals[1], center) ); if (Vector.dotProduct(this.normal, $reals[0]) < 0) this.normal.scale(-1); var prevPoint = $reals[$reals.length - 1], prevVertex = product.face.$sub.vertex[$reals.length - 1], chain = []; var angleSum = 0; product.maxR = 0; $reals.each(function (vertexIter) { // vertex raduis var R = prevPoint.distance(center) * product.R; chain.push({ value: R, mark: 'R', vertex: prevVertex, center: center }); // side angle var prevAngle = Vector.subtract(this, center).angleWith(Vector.subtract(prevPoint, center)); chain.push({ dontStart: true, value: prevAngle, mark: 'A' }); angleSum += prevAngle; // max R product.maxR = Math.max(product.maxR, R); // side length chain.push({ sortIgnore: true, dontStart: true, vertex: this.vertex, value: this.distance(prevPoint) * product.R, line: _.findWhere(product.face.bindedLines || product.face.$sub.line, { origin: this.vertex.$super.line.map(function () { return this.$vertexes[0] === prevVertex || this.$vertexes[1] === prevVertex ? this : null; })[0] }), mark: 'L' }); if (!_.last(chain).line) { console.warn('binded line not found'); } prevVertex = this.vertex; prevPoint = this; }); // assert: polygon on plane if (Math.abs(angleSum - 2 * Math.PI) > 1e-3) { console.log('Polygon.unify(): sum of polygon angles is not equal full circle (' + angleSum + ' != 2*PI)'); } // select chain this.chain = Product.selectChain(chain, 'value', true, product.bilateral); return $(this.chain).map(function () { if (this.mark == 'L') return null; return this.mark + Product.lengthUnify(this.value); }).get().join('-'); }, model: function (onExport) { if (!onExport) return // console.error(this, 'on export only'); var face = this.face.$points.get(); // todo: resolve std orientation var reverted = []; for (var i = 0, p; p = face.pop(); reverted.push(p)) ; // one reverted face return [reverted]; }, plot: function (canvas) { var product = this; var R = this.maxR; var plotter = new Plotter(canvas, { width: 2 * R, height: 2 * R, margin: 20, // px resize: true, offset: {x: R, y: R} }); //plotter.circle({x: 0, y: 0}, R, ['gray']); // plotter point by angle & R function pos(a, r) { return { x: r * Math.cos(a), y: r * Math.sin(a) }; } var center = {x: 0, y: 0}; // draw polygon var a = Math.PI / 2, prev = {}; // previous (last) segment data for (var i = 1; i <= 3; i++) { var match = this.chain[this.chain.length - i]; prev[match.mark] = match.line || match.value; } // set last plotter-point as previous prev.point = pos(a - prev.A, prev.R); $(this.chain).each(function () { switch (this.mark) { case 'L': prev.L = this.line; break; case 'A': a += this.value; break; case 'R': var point = pos(a, this.value); var worldPoints = $.map(prev.L.$sub.vertex, function (v) { return v.$points[0] }); // side var length = Product.lengthUnify(plotter.distance(point, prev.point)); var basedOnLineNormal = Vector.crossProduct(worldPoints[0], worldPoints[1]); var segmentNormal = Vector.crossProduct( Vector.subtract(worldPoints[0], product.realCenter()), Vector.subtract(worldPoints[1], product.realCenter()) ); var byLineAngle = Math.round(segmentNormal.angleWith(basedOnLineNormal) * 1800 / Math.PI) / 10; // basedOnLineNormal orientation unknown byLineAngle = (byLineAngle > 90) ? 180 - byLineAngle : byLineAngle; plotter.line(prev.point, point, { strokeStyle: "black", lineWidth: 3, strokeStyle: productPalette.line[prev.L.order].css }); plotter.textByLine(length + ' (' + prev.L.index + ') ∟' + byLineAngle + '°', point, prev.point, { fontSize: 1.2, fillStyle: productPalette.line[prev.L.order].css }); // R plotter.line(center, point, 'division'); plotter.textByLine(Product.lengthUnify(plotter.distance(point, center)), point, center, {fontSize: 1}); // vertex label var vertex = this.vertex; setTimeout(function () { plotter.vertexLabel(vertex.index, point, vertex.$super.line.length); }); prev.point = point; break; } }); }, meter: function () { var res = {}; // res['Многоугольники'] = { // }; return res; } }); </script> <script type="text/javascript">/** * Определение продукта треугольник * * @author popitch [at yandex.ru] */ Product.Triangle = {}; Product.Triangle.Simple = function (face, params) { // parent() Product.Polygon.Simple.call(this, face, $.extend({ type: 'Triangle', title: 'Треугольник' }, params || {})); } .inherits(Product.Polygon.Simple) .override({ unify: function () { var product = this; var unifier = Product.Polygon.Simple.prototype.unify.call(this, 'without radius, brother'); /* stats */ var $reals = this.realPoints(); // длины сторон a, b, c var abc = this.abc = new Array(3); var lines = this.lines = new Array(3); // для углов var abcEdges = this.abcEdges = new Array(3); var n = Vector.crossProduct( $reals[0].clone().subtract($reals[1]), $reals[2].clone().subtract($reals[1]) ); $reals.each(function (i) { var A = this, B = $reals[(i + 1) % 3]; abc[(i + 2) % 3] = product.R * A.distance(B); lines[(i + 2) % 3] = _.find(product.face.bindedLines || product.face.$sub.line, function (line) { var vv = line.origin.$sub.vertex; return 0 || (vv[0] == A.vertex && vv[1] == B.vertex) || (vv[1] == A.vertex && vv[0] == B.vertex); }); // угол между плоскостью треугольника и смотрящей в центр var r = A.vertex.points[0].clone().add(B.vertex.points[0]).scale(.5); abcEdges[(i + 2) % 3] = Math.asin(Math.abs(r.cosWith(n))); }); // Формула Герона позволяет вычислить площадь треугольника (S) по его сторонам var p = this.p = (abc[0] + abc[1] + abc[2]) / 2; this.S = Math.sqrt(p * (p - abc[0]) * (p - abc[1]) * (p - abc[2])); // углы this.angles = new Array(3); for (var a = 0; a < 3; a++) { var b = (a + 1) % 3, c = (a + 2) % 3; product.angles[a] = Math.acos((abc[b] * abc[b] + abc[c] * abc[c] - abc[a] * abc[a]) / (2 * abc[b] * abc[c])); } // S = abc/4R this.triR = abc[0] * abc[1] * abc[2] / (4 * this.S); /* end for stats */ return unifier; }, model: function (onExport) { if (!onExport) return // console.error(this, 'on export only'); var face = this.face.$points.get(); // todo: resolve std orientation face = [face[2], face[1], face[0]]; // one reverted face return [face]; }, plot: function (canvas) { var product = this; new Plotter.Triangle(canvas, { $points: this.realPoints(), $vertexes: product.face.$sub.vertex, $lines: this.lines, R: this.R, angles: this.angles, radiuses: [this.triR, this.triR, this.triR], abcEdges: this.abcEdges, textZoom: 2 }) .triangle() .vertexes(); }, meter: function () { var meter = {}; meter[__('Coverage area, m2')] = this.S; meter[__('Triangles')] = {}; meter[__('Triangles')]['range:' + __('Min. height, mm')] = Product.lengthUnify( _.min([ 2 * this.S / this.abc[0], 2 * this.S / this.abc[1], 2 * this.S / this.abc[2] ]) ); meter[__('Triangles')]['range:' + __('Max. side, mm')] = Product.lengthUnify( _.max(this.abc) ); return meter; } }); </script> <script type="text/javascript">/** * Определение продукта коннекторов * * @author popitch [at yandex.ru] */ Product.Connector = function () { Product.apply(this, arguments); // expected this.vertex || console.log('vertex not specified'); this.point || console.log('point not specified'); } .inherits(Product) .override({ // расстояние от вершины коннектора до плоскости ребра (средняя его плоскость) ribPlaneOffset: function (line) { return console.log('Product.Connector.ribPlaneOffset() abstract called', this) & 0; }, // ребро, в которое упирается заданное ребро ribWall: function (line) { return null; }, // расстояние от вершины коннектора до плоскости стены (в которую ребро упирается) ribWallOffset: function (line) { return 0; }, // вектор от текущей точки вдоль line toOtherTail: function (line) { var OTHER = (line.$points[0] != this.point) ? (line.$points[1] != this.point) ? console.log('Product.Connector.toOtherTail: wrong line') : 0 : 1; return line.$points[OTHER].clone().subtract(this.point); }, otherVertex: function (line) { var vertex = this.vertex; return line.$vertexes.map(function () { return this !== vertex ? this : null; })[0]; }, // вектор к центру от тукущей точки toCenter: function () { return this.point.center ? Vector.subtract(this.point.center, this.point) : (new Vector).subtract(this.point); }, // угол к радиусу в тукущей точке angleByRaduis: function (line) { return this.toOtherTail(line).angleWith(this.toCenter()); }, // коллекция ребер данного фейса linesByFace: function (face) { var point = this.vertex.$points[0]; return face.$sub.line.map(function () { return this.$points[0] === point || this.$points[1] === point ? this : null; }); }, afterTailsGiven: function (tail, i, line) { return tail; }, unify: function () { var product = this; // подготовка схемы this.vertex.$scheme.each(function () { if (this.isFace) { /** * @todo брать не угол реал-фейса, а угол к остальным вершинам */ var reals = this.source.product.realPoints().get(); var i = this.source.$sub.vertex.index(product.vertex); this.faceAngle = Vector.angle(reals[(i - 1 + reals.length) % reals.length], reals[i], reals[(i + 1) % reals.length]); } else { this.radiusAngle = product.angleByRaduis(this.source); } }); // прокрутим цепочку и выберем единственный вариант if (!this.vertex.selvage) { var chain = this.vertex.$scheme.get(); var sortChains = []; $(chain).each(function (i) { sortChains.push(chain.slice(i).concat(chain.slice(0, i))); }); sortChains.sort(function (a, b) { for (var i = 0, l = a.length, d; i < l; i++) { d = (b[i].faceAngle || b[i].radiusAngle) - (a[i].faceAngle || a[i].radiusAngle); if (-1e-6 > d || d > 1e-6) return d; } return 0; }); this.vertex.$scheme = $(sortChains[0]); } // цепочка уголов ребра_к_радиусу - треугольника ... // префикс "ground " означает что это край return (this.vertex.selvage ? 'Ground ' : '') + this.vertex.$scheme.map(function () { return this.isFace ? 'F' + Product.angleUnify(this.faceAngle) : 'R' + Product.angleUnify(this.radiusAngle); }).get().join(' '); }, meter: function () { var p = this.vertex.$points[0]; var meter = {}; meter['swing:' + __('Height from base, m')] = p.y * this.R; if (this.vertex.selvage) meter['range:' + __('Base radius, m')] = Math.sqrt(p.x * p.x + p.z * p.z) * this.R; return meter; } }); /** * Joint connector http://popitch1.livejournal.com/1840.html */ Product.Connector.Joint = function (vertex, params) { Product.Connector.apply(this, [$.extend({ type: 'Joint', vertex: vertex, point: vertex.$points[0], whirlAsClock: '1' }, params || {})]); } .inherits(Product.Connector) .override({ ribPlaneOffset: function (line) { if (line.sliced || this.vertex.sliced) return 0; return (this.whirlAsClock != 0 ? 1 : -1) * line.product.thickness / 2; // @todo any product }, // ребро, в которое упирается заданное ребро ribWall: function (line) { var vertexIndex = $.inArray(this.vertex, line.$vertexes); vertexIndex >= 0 || console.log('its not my line', this); var $nearLines = line.$nearLinesByVertex[vertexIndex]; var nearSlicedLines = $nearLines.filter(function () { return this.sliced }); return nearSlicedLines[0]; }, // оконцовщик хвоста ребра getTail: function (line) { var vertex = this.vertex, point = vertex.$points[0], plane = line.product.getPlane(), // @todo outer; var vertexIter = (line.origin.$vertexes[0] == vertex) ? 0 : 1; // todo: copypasted from Rib.getTails() by refactor getTail mechanism var anotherPoint = line.origin.$sub.vertex.filter(function () { return this !== vertex })[0].$points[0]; var center = line.origin.center || vertex.center || Vector(0); var result = plane.result(point); if (Math.abs(result) > 1e-6) { // базовая плоскость смещена (Joint + GoodKarma, Semicone) var $nearLines = line.origin.$nearLinesByVertex[vertexIter]; var wall; $nearLines.each(function () { var otherVertex = this.$sub.vertex.filter(function () { return this !== vertex })[0]; var otherPoint = otherVertex.$points[0]; var otherResult = plane.result(otherPoint); if (otherResult * result < 0) { wall && console.log('too many walls for one tail'); // по другую сторону от плоскости ребра, значит сюда уперлись wall = { plane: this.product.getPlane().clone(), line: this }; // ориентируем плоскость стены относительно незадействованной здесь вершины лайна if (wall.plane.result(anotherPoint) < 0) wall.plane.revert(); } }); if (!wall) console.log(['Product.Rib::model(): no wall', this]); // двигаем стену в сторону сабжевого ребра, учитывая толщину ребра wall.plane.D -= wall.line.product.thickness / 2; var sols = Solutions.twoPlanesAndSphere(plane, wall.plane); sols.length == 2 || console.log(['Product.Rib::model(): not two solutions', this]); outer = sols[0].distance(point) < sols[1].distance(point) ? sols[0] : sols[1]; // refactor candidate //outer = Solutions.planesCross(line.product.getOuterPlane(), plane, wallPlane); // for points placed out of sphere (outer Fulleren) // ~ outer.scale(point.length()); return { // точка внешней поверхности outer: outer, center: center, wall: wall.plane, vertex: vertex }; } // смещения нет if (!line.sliced) { wallLine = vertex.product.ribWall(line); // ребро не на краю if (wallLine) { // есть ребро, в которое упирается данное (Joint) var wall = { plane: wallLine.product.getPlane().clone(), line: wallLine }; // ориентируем плоскость стены относительно незадействованной здесь вершины лайна if (wall.plane.result(anotherPoint) < 0) wall.plane.revert(); // двигаем стену в сторону сабжевого ребра, учитывая толщину ребра wall.plane.D -= wall.line.product.thickness / 2; } else { console.error('This code branch must no usage'); // нет ребра в которое упирается данное (Piped) center = vertex.center || line.center || center; var lineVector = Vector.subtract(point, anotherPoint); var pointVector = Vector.subtract(point, center); var sideVector = Vector.crossProduct(lineVector, pointVector); var wallNormal = Vector.crossProduct(sideVector, pointVector).normalize(); var wall = { plane: new Plane(wallNormal, point) }; } // двигаем стену на радиус трубы var offset = vertex.product.ribWallOffset(line); if (offset) { wall.plane.D += (wall.plane.result(anotherPoint) > 0 ? -offset : offset); } var sols = Solutions.twoPlanesAndSphere(plane, wall.plane); sols.length == 2 || console.log(['Product.Rib->getTails()', 'not 2 solutions', this]); outer = sols[0].distance(point) < sols[1].distance(point) ? sols[0] : sols[1]; // for points placed out of sphere (outer Fulleren) // ~ outer.scale(point.length()); return { // точка внешней поверхности outer: outer, center: center, wall: wall.plane, vertex: vertex }; } // В НОВОЙ ВЕРСИИ СЮДА НЕ ПОПАДАЕМ console.error('// В НОВОЙ ВЕРСИИ СЮДА НЕ ПОПАДАЕМ'); }, unify: function () { return 'Joint ' + Product.Connector.prototype.unify.apply(this); } }); // Труба (расположена вдоль радиуса) с лучами для крепления ребер, классика для любителей сварки и стыков металл+дерево Product.Connector.Piped = function (vertex, params) { Product.Connector.apply(this, [$.extend({ type: 'Piped', vertex: vertex, point: vertex.$points[0], bilateral: false }, params || {})]); // габариты приводим к долям радиуса, а получаем в неких единицах измерения this.Dpipe *= (this.measure || 1) / this.R; } .inherits(Product.Connector) .override({ ribPlaneOffset: function (line) { return 0; }, // расстояние от вершины коннектора до плоскости стены (в которую ребро упирается) ribWallOffset: function (line) { return this.Dpipe / 2; }, // оконцовщик хвоста ребра getTail: function (line) { // take origin line figure line = line.origin; // cache this.cache.pipedTail = this.cache.pipedTail || {}; if (this.cache.pipedTail[line._enum]) return this.cache.pipedTail[line._enum]; var vertex = this.vertex, point = vertex.$points[0]; var plane = line.product.getPlane(); var vertexIter = line.$vertexes[0] == vertex ? 0 : 1; var anotherPoint = line.$vertexes[1 - vertexIter].$points[0]; var center = line.center || vertex.center || Vector(0); if (!line.sliced) { // ребро не на краю center = vertex.center || line.center || center; var lineVector = Vector.subtract(point, anotherPoint); var pointVector = Vector.subtract(point, center); var sideVector = Vector.crossProduct(lineVector, pointVector); var wallNormal = Vector.crossProduct(sideVector, pointVector).normalize(); var wall = { plane: new Plane(wallNormal, point) }; // двигаем стену на радиус трубы var offset = vertex.product.ribWallOffset(line); wall.plane.D += (wall.plane.result(anotherPoint) > 0 ? -offset : offset); return this.cache.pipedTail[line._enum] = { // точка внешней поверхности outer: Solutions.planesCross(line.product.getOuterPlane(), plane, wall.plane), center: center, wall: wall.plane, vertex: vertex }; } // ребро целиком на краю (Piped, Joint) line.sliced || console.log(['Product.Rib->getTails()', 'fail']); var $anotherSelvageLines = vertex.$super.line.filter(function () { return this.selvage && this !== line }); if ($anotherSelvageLines.length != 1) console.log(['Product.Rib->getTails()', 'not 1 anotherSelvageLines: ', $anotherSelvageLines]); var linePlane = line.product.getPlane(), line2Plane = $anotherSelvageLines[0].product.getPlane(); Vector.dotProduct(linePlane.normal(), line2Plane.normal()) < 0 && line2Plane.revert(); var outer = point, offset = this.ribWallOffset(line); center = vertex.center || line.center || center; var lineVector = Vector.subtract(point, anotherPoint); var pointVector = Vector.subtract(point, center); var sideVector = Vector.crossProduct(lineVector, pointVector); var wallNormal = Vector.crossProduct(sideVector, pointVector).normalize(); var wallPlane = new Plane(wallNormal, point); // двигаем стену на радиус трубы if (offset) { wallPlane.D += (wallPlane.result(anotherPoint) > 0 ? -offset : offset); outer = Solutions.planesCross(line.product.getOuterPlane(), plane, wallPlane); } return this.cache.pipedTail[line._enum] = { outer: outer, wall: wallPlane, center: center, vertex: vertex }; }, unify: function () { var product = this; // проекция ребер на основание радиус-вектора вершины var prev, pinAngleSum = 0; var radius = Vector.subtract(this.vertex.$points[0], this.vertex.center); this.$hedgehog = this.vertex.$scheme.map(function () { if (this.source.type == 'line') { var vector = product.toOtherTail(this.source); return prev = { vector: vector, source: this.source, pin: Vector.subtract(vector, Vector.project(vector, radius)), terminate: this.selvage //product: product }; } return null; }); // углы this.$hedgehog.each(function () { var angle = (Vector.add(prev.pin, this.pin).length() < 1e-9) ? Math.PI : prev.pin.angleWith(this.pin); if (Vector.dotProduct(Vector.crossProduct(this.pin, prev.pin), radius) < 0) angle = Math.PI * 2 - angle; pinAngleSum += ( prev.forwardAngle = this.backAngle = angle); prev = this; }); // total control if (Math.abs(pinAngleSum - Math.PI * 2) > 1e-7) console.log('Piped.unify(): pin angles sum is not full circle ' + pinAngleSum); // sort & select this.$hedgehog = $( Product.selectChain( this.$hedgehog, function (i, arr, forward) { return forward ? this.backAngle : this.forwardAngle; }, true, product.bilateral ) ); return this.$hedgehog.map( function () { return Product.angleUnify(this.forward ? this.backAngle : this.forwardAngle); } ).get().join('-'); }, // draw product scheme on canvas // @param DomElement canvas // @param Object plotter options plot: function (canvas, opts) { var product = this; var C = {x: 1, y: 1}; var plotter = new Plotter(canvas, $.extend(opts, { width: 2, height: 2, margin: 20, // px resize: true, R: this.R, textZoom: 2 })) .circle(C, .8, ['solid', 'fillWhite']); var angle = 0, prev;//Math.PI; this.$hedgehog.each(function () { prev = angle; angle += this.forward ? this.backAngle : this.forwardAngle; var A = {x: 1 + Math.cos(angle), y: 1 + Math.sin(angle)}; // line plotter.line(C, A, 'bbb'); // index plotter.textByLine(this.source.index, C, A, {q: .9, sup: true}); // degree var mid = (prev + angle) / 2; var degree = Math.round(1800 * (angle - prev) / Math.PI) / 10 + '°'; plotter.text( {x: 1 + .38 * Math.cos(mid), y: 1 + .38 * Math.sin(mid)}, degree ); }); } }); /** * Корабль, карандаш, конус... ибо шишка */ Product.Connector.Cone = function (vertex, params) { Product.Connector.apply(this, [$.extend({ type: 'Cone', vertex: vertex, point: vertex.$points[0], bilateral: false }, params || {})]); } .inherits(Product.Connector.Piped) .override({ ribPlaneOffset: function (line) { return 0; }, // расстояние от вершины коннектора до плоскости стены (в которую ребро упирается) ribWallOffset: function (line) { return 0; }, // ключ аккумулятора pinAccumKey: function (pin, finaly) { var back = pin.forward ? pin.backAngle : pin.forwardAngle; var forward = pin.forward ? pin.forwardAngle : pin.backAngle; var pp = pin.source.$points; var length = Product.lengthUnify(pp[0].distance(pp[1]) * this.R); var suffix; if (!finaly) { var otherProduct = this.otherVertex(pin.source).product; if (otherProduct === this) console.log('otherProduct === this product'); // prepare other hedgehog if (!otherProduct.$hedgehog) Product.Connector.Piped.prototype.unify.call(otherProduct); var otherHedgehog = otherProduct.$hedgehog; var otherPin = otherHedgehog.map(function () { return this.source === pin.source ? this : null; })[0]; suffix = otherProduct.pinAccumKey(otherPin, true); } return (back >= Math.PI ? 'none' : Product.angleUnify(back)) + ' ' + length + ' ' + (forward >= Math.PI ? 'none' : Product.angleUnify(forward)) + (suffix ? ' => ' + suffix : ''); }, unify: function (accum) { if (this.cache.coneUnifier) return this.cache.coneUnifier; var product = this; var unifier = Product.Connector.Piped.prototype.unify.apply(this, arguments); accum.cone = accum.cone || {}; function mirrorKey(key) { //key = key.replace(/(\S+) (\S+) (\S+)$/g, '$3 $2 $1'); key = key.replace(/^(\S+) (\S+) (\S+)/g, '$3 $2 $1'); return key; } function AngleSet() { } AngleSet.prototype = { add: function (angle, weight) { // sense a near value for (var a in this) if (this.hasOwnProperty(a)) angle = Math.abs(a - angle) > 1e-6 ? angle : a; // increment this[angle] = (this[angle] || 0) + weight; return angle; }, merge: function (set, maxus) { for (var a in set) if (set.hasOwnProperty(a)) { this.add(a, set[a]); maxus = Math.max(maxus, this[a]); } return maxus; } }; if (!this.vertex.selvage) { // решение зацикленной системы линейных уравнений if (this.$hedgehog.length % 2) { // единственно, если лучей нечетное кол-во this.$hedgehog.each(function () { this.coneAngle = 0; }); this.$hedgehog.each(function (i) { var subj = this; product.$hedgehog.each(function (j) { var pin = product.$hedgehog[(i + j) % product.$hedgehog.length]; subj.coneAngle += (j % 2 ? -1 : 1) * pin[pin.forward ? 'forwardAngle' : 'backAngle']; // assertion if (isNaN(subj.coneAngle)) console.log('isNaN(subj.coneAngle)'); }); }); this.$hedgehog.each(function (i) { if (this.coneAngle < 0) console.log('<0'); this.coneAngle = Math.abs(this.coneAngle / 2); // assertion if (isNaN(this.coneAngle)) console.log('isNaN(this.coneAngle)'); }); } else { // при четном кол-ве сходящихся лучей (ребер) var sum = [0, 0]; this.$hedgehog.each(function (i) { sum[i % 2] += this.forwardAngle; }); if (Math.abs(sum[0] - sum[1]) < 1e-6 && Math.abs(sum[0] - Math.PI) < 1e-6) { // если сумма углов через один равна Пи, то беск. кол-во решений // выбираем лучшее... var alfa = 0; var mins = [9, 9]; this.$hedgehog.each(function (i) { this.coneAngle = alfa; mins[i % 2] = Math.min(mins[i % 2], alfa); var forwardAngle = this.forward ? this.forwardAngle : this.backAngle; alfa = forwardAngle - alfa; // assertion if (isNaN(alfa)) console.log('isNaN(alfa)'); }); var mid = (mins[0] + mins[1]) / 2; this.$hedgehog.each(function (i) { this.coneAngle += mid - mins[i % 2]; // assertion if (isNaN(this.coneAngle)) console.log('isNaN(this.coneAngle)'); }); } else { // иначе решений нет console.log('Cone.unify(): zero solution'); } } // аккумуляция значений вычисленых coneAngle для различных соседних углов лучу (ребру) this.$hedgehog.each(function (i) { var angle = this.coneAngle; var key = product.pinAccumKey(this); accum.cone[key] = accum.cone[key] || new AngleSet; accum.cone[key].add(angle, 1000); var revLeft = mirrorKey(key); accum.cone[revLeft] = accum.cone[revLeft] || new AngleSet; accum.cone[revLeft].add(angle, 1); }); //console.log('direct', this.$hedgehog.map(function(){ return this.coneAngle })) } else { // край фигуры // попытка вытащить из аккумулятора var found, foundMaxus; this.$hedgehog.each(function (i) { var curr = this; var key = product.pinAccumKey(curr); var keySense = new RegExp( key .replace(/none/g, '(?:\\d+|none)') .replace(/(\d+)/g, '(?:$1|none)') ); var angle, maxus = 0; var angleSols = new AngleSet; for (var k in accum.cone) if (keySense.test(k)) maxus = angleSols.merge(accum.cone[k], maxus); var solus = 0; for (var a in angleSols) { if (angleSols[a] == maxus) { solus++; angle = a; } } if (solus == 1 && (!found || maxus > foundMaxus)) { curr.coneAngle = parseFloat(angle); // registration //accum.cone[key] = accum.cone[key] || new AngleSet; //accum.cone[key].add(angle, 1000); //var left = mirrorKey(key); //accum.cone[left] = accum.cone[left] || new AngleSet; //accum.cone[left].add(angle, 1); //console.log('add solution for key', key, 'with solutions set', angleSols) // assertion if (isNaN(curr.coneAngle)) console.log('isNaN(curr.coneAngle)'); // order founded found = i; foundMaxus = maxus; //return false; } else { //console.log('Cone.unify():', solus, 'solutions for ', key, angleSols, 'by', accum.cone); } }); if (found !== undefined) { var length = this.$hedgehog.length; //if (length == 2) //console.log('found', found, 'length', length); for (var incr = 1, back = 0; incr >= -1; incr -= 2, back = 1) { var i = found; var curr = this.$hedgehog[i]; while ((i = (i + incr + length) % length) != found) { var prev = curr; curr = this.$hedgehog[i]; var sum = back ? (prev.forward ? prev.backAngle : prev.forwardAngle) : (prev.forward ? prev.forwardAngle : prev.backAngle); // hardcode for situation when non-fuller must be breaked (PI * 4 / 5 gt 2.5) if (sum > 2.5) { //console.log('cones sum > 2.5, sum is', sum); break; } curr.coneAngle = (sum > Math.PI ? Math.PI * 2 - sum : sum) - prev.coneAngle; if (curr.source.selvage && prev.source.selvage) break; } } } else { var keys = this.$hedgehog.map(function (i) { return product.pinAccumKey(this) }); var lens = $.map(keys, function (key) { return key.replace(/^\S+ (\d+).*/, '$1') }); var acc = {}; $.each(accum.cone, function (key, as) { for (var i = 0, l = lens.length; i < l; i++) if (key.split(lens[i]).length > 1) acc[key] = as; }); console.log('Cone angle for keys', keys, 'not found in accum', acc); } } // control shot if (this.$hedgehog.filter(function () { return isNaN(this.coneAngle) }).length) console.log('Cone-' + unifier, 'cone without angle detected', this.$hedgehog); if (this.$hedgehog.filter(function () { return this.coneAngle > Math.PI / 2 }).length) console.log('Cone-' + unifier, 'cone with angle gt PI/2', this.$hedgehog); return this.cache.coneUnifier = 'Cone-' + unifier; }, // оконцовщик ребра getTail: function (line) { // take origin line figure line = line.origin; $.inArray(this.vertex, line.$vertexes) >= 0 || console.log('its not my line', this); var tail = Product.Connector.Piped.prototype.getTail.apply(this, arguments); this.unify(); var vertex = this.vertex, product = this, pinIndex, pinCount = this.$hedgehog.length; this.$hedgehog.each(function (i) { if (this.source == line) { pinIndex = i; tail.coneAngle = this.coneAngle; tail.coneSide = (i != 0) ? (i != pinCount - 1) ? 'both' : 'left' : 'right'; return false; } }); //var $nearLines = line.$nearLinesByVertex[vertexIndex]; return tail; }, plot: function (canvas, opts) { Product.Connector.Piped.prototype.plot.apply(this, arguments); var plotter = new Plotter(canvas, $.extend(opts, { width: 2, height: 2, margin: 20, // px R: this.R, textZoom: 2 })); var angle = 0; this.$hedgehog.each(function () { angle += this.forward ? this.backAngle : this.forwardAngle; // degree var degree = Math.round(1800 * this.coneAngle / Math.PI) / 10; plotter.text( {x: 1 + .618 * Math.cos(angle), y: 1 + .618 * Math.sin(angle)}, degree * 2 + '°' ); }); } }); /** * Пол-шишки тоже шишка * - это просто нос, полуконус дальше будет */ Product.Connector.Nose = function (vertex, params) { Product.Connector.apply(this, [$.extend({ type: 'Nose', vertex: vertex, point: vertex.$points[0], //bilateral: true, whirlAsClock: 0 }, params || {})]); // type cast this.whirlAsClock = (1 == this.whirlAsClock); // no pipe this.Dpipe = 0; } .inherits(Product.Connector.Piped) .override({ afterTailsGiven: function (tail, i, line) { var product = this; var wall = this.$hedgehog.map(function () { if (this.source === line) return null; //if (!this.pin || !tail.backDir) // console.error('must to be'); if (this.pin.cosWith(tail.backDir) > 0) // angle must be < 90 degrees return null; var is = Vector.dotProduct( Vector.crossProduct(this.pin, tail.backDir), product.point // strangen center not found ) > 0; if (is ^ !product.whirlAsClock) return null; return product.getTail(this.source).wall; })[0]; if (wall) { //var oi = Vector.subtract(tail.inner, tail.outer); //tail.walker0clone = tail.walker0clone || tail.walkers[0].clone(); //var revert = Vector.dotProduct(Vector.crossProduct(tail.walker0clone, oi), tail.backDir) < 0 ? 0 : 1; var pp = [], dd = $.map(tail.walkers, function (w, j) { pp[j] = Vector.add(product.point, w); return wall.result(pp[j]) //Math.abs( wall.result(pp[j]) ); }), index = (dd[0] > dd[1]) ? 0 : 1, p = pp[index], d = dd[index], walker = tail.walkers[index]; // wall.result(p + X * tail.backDir) = 0 var td = wall.result(Vector.add(p, tail.backDir)); var X = d / (d - td); tail.walkers[index].add(Vector.scale(tail.backDir, X)); } return tail; } }); /** * GoodKarma */ Product.Connector.GoodKarma = function (vertex, params) { Product.Connector.apply(this, [$.extend({ type: 'GoodKarma', vertex: vertex, point: vertex.$points[0], whirlAsClock: 0 }, params || {})]); // type cast this.whirlAsClock = (1 == this.whirlAsClock); // no pipe this.Dpipe = 0; } .statics({ lineSeparatelyForFaces: true }) .inherits(Product.Connector.Joint) .override({ ribPlaneOffset: function (line) { return 0; }, // ребро, в которое упирается заданное ребро // ribWall: function(line) { // var product = this; // // return _.filter(figure.$primitives, function(p) { // return 1 // && p.bindedFace === line.bindedFace // && p !== line // && _.indexOf(p.origin.$vertexes, product.vertex) > -1; // })[0]; // }, // оконцовщик хвоста ребра getTail: function (line) { var vertex = this.vertex, point = vertex.$points[0], secondVertex = line.origin.$vertexes[line.origin.$vertexes[0] === vertex ? 1 : 0], secondPoint = secondVertex.$points[0], plane = line.product.getPlane(true), planeNormal = plane.normal(); var wallLine = _.find(line.bindedFace.bindedLines, function (any) { return 1 && any !== line && _.contains(any.origin.$vertexes, vertex); }), wallPlane = wallLine.product.getPlane(true).clone().normalize(), thirdVertex = wallLine.origin.$vertexes[wallLine.origin.$vertexes[0] === vertex ? 1 : 0], thirdPoint = thirdVertex.$points[0]; // ориентируем плоскость стены относительно незадействованной здесь вершины лайна if (wallPlane.result(secondPoint) < 0) wallPlane.revert(); // двигаем стену в сторону сабжевого ребра, учитывая толщину ребра wallPlane.D += ( this.whirlAsClock ^ (Vector.dotProduct( Vector.crossProduct( secondPoint.clone().subtract(point), thirdPoint.clone().subtract(point) ), point ) > 0) ? -1 : 1) * wallLine.product.thickness / 2; var outer = plane.crossWithRay( wallPlane.crossWithRay( point, secondPoint.clone().subtract(point) ), Vector.crossProduct(line.product.getOuterPlane().normal(), wallPlane.normal()) ); return { // точка внешней поверхности outer: outer, center: Vector(0), wall: wallPlane, vertex: vertex }; }, unify: function () { return 'GoodKarma ' + Product.Connector.prototype.unify.apply(this); } }); /** * Semicone */ Product.Connector.Semicone = function (vertex, params) { Product.Connector.apply(this, [$.extend({ type: 'Semicone', vertex: vertex, point: vertex.$points[0] }, params || {})]); // no pipe ? //this.Dpipe = 0; } .statics({ lineSeparatelyForFaces: true }) .inherits(Product.Connector.Joint) .override({ ribPlaneOffset: function (line) { return 0; }, // оконцовщик хвоста ребра getTail: function (line) { var vertex = this.vertex, point = vertex.$points[0], secondVertex = line.origin.$vertexes[line.origin.$vertexes[0] === vertex ? 1 : 0], secondPoint = secondVertex.$points[0], plane = line.product.getPlane(true), planeNormal = plane.normal(), thirdVertex = _.difference(line.bindedFace.$sub.vertex.get(), [vertex, secondVertex])[0], thirdPoint = thirdVertex.$points[0], wallPlane = new Plane( Vector.crossProduct( // bisectrix Vector.add( Vector.subtract(secondPoint, point).normalize(), Vector.subtract(thirdPoint, point).normalize() ), // radius vector point ), point ).normalize(); // ориентируем плоскость стены относительно незадействованной здесь вершины лайна // if (wallPlane.result(secondPoint) < 0) // wallPlane.revert(); var outer = plane.crossWithRay( wallPlane.crossWithRay( point, secondPoint.clone().subtract(point) ), Vector.crossProduct(line.product.getOuterPlane().normal(), wallPlane.normal()) ); return { // точка внешней поверхности outer: outer, center: Vector(0), wall: wallPlane, vertex: vertex }; }, unify: function () { return 'Semicone ' + Product.Connector.prototype.unify.apply(this); } }); </script> <script type="text/javascript">/** * Определение продукта "ребро" * * @author popitch [at yandex.ru] */ Product.Rib = function () { Product.apply(this, arguments); // expected this.line || console.log('no line specified'); // init plane cache this.cache.plane = {}; } .inherits(Product) .override({ // отдает плоскость, рассекающую ребро пополам и проходящую через центры радиусов вершин getPlane: function (useBindedFace) { if (this.cache.plane[useBindedFace]) return this.cache.plane[useBindedFace]; var line = this.line, vv = line.origin.$subsets.get(), pp = [vv[0].$points[0], vv[1].$points[0]], center = line.origin.center || pp[0].center || Vector(0);// ? pp[1].center ? pp[0].center.equals(pp[1].center) ? pp[0].center : /** * 1) A*cx + B*cy + C*cz + D = 0 * 2) A*x0 + B*y0 + C*z0 + D = d0 * 3) A*x1 + B*y1 + C*z1 + D = -d1 * 4) A*A + B*B + C*C = 1 */ // если line на краю, либо данный конец на краю, то смещение 0 var d0 = vv[0].product.ribPlaneOffset(line), d1 = -vv[1].product.ribPlaneOffset(line); var sols = Solutions.twoPlanesAndSphere( new Plane(Vector.subtract(pp[0], center), -d0), new Plane(Vector.subtract(pp[1], center), -d1) ); sols.length || console.log('no plane no cry'); var lineNormal = Vector.crossProduct(Vector.subtract(pp[0], center), Vector.subtract(pp[1], center)); for (var i = 0; i < sols.length; i++) { var n = sols[i], D = -Vector.dotProduct(n, center); // 1) D var pl = sols[i] = new Plane(n, D); pl.sign = n.cosWith(lineNormal) > 0 ? 1 : -1; // debug pl.reflect = vv[i].reflection; pl.mapi = n.mapi; pl.solutions = n.solutions; /** tests * 1) A*cx + B*cy + C*cz + D = 0 * 2) A*x0 + B*y0 + C*z0 + D = d0 * 3) A*x1 + B*y1 + C*z1 + D = -d1 */ var testc = pl.A * center.x + pl.B * center.y + pl.C * center.z + pl.D; var test0 = pl.A * pp[0].x + pl.B * pp[0].y + pl.C * pp[0].z + pl.D; var test1 = pl.A * pp[1].x + pl.B * pp[1].y + pl.C * pp[1].z + pl.D; if (testc != 0) console.warn('!' + testc); if (Math.abs(d0 - test0) > 1e-6) console.warn('d0:' + d0 + ' != ' + test0); if (Math.abs(d1 - test1) > 1e-6) console.warn('d1:' + d1 + ' != ' + test1); } if (sols.length == 2 && sols[0].sign == sols[1].sign) console.log({sols: sols, lineNormal: lineNormal}); // выбор решения var plane = (sols.length == 2 ? sols[0].sign == 1 ? sols[0] : sols[1] : sols[0]).normalize(); // Good Karma's (+Semicone) workaround if (useBindedFace === true && line.bindedFace) { // move plane to side of binded face var testPoint = _.filter(line.bindedFace.$sub.vertex, function (vertex) { return !_.contains(line.origin.$vertexes, vertex); })[0].$points[0]; plane.D += (plane.result(testPoint) < 0 ? 1 : -1) * this.thickness / 2; } return this.cache.plane[useBindedFace] = plane; }, // отдает конфигурацию оконцовок /*final*/ getTails: function () { var line = this.line; if (this.cache.tails) return this.cache.tails; // 1. get tails separately var tails = line.origin.$vertexes.map(function () { var vertex = this, tail = vertex.product.getTail(line); tail.product = vertex.product; return tail; }); // 2. common calculator tails = this.afterGetTails(tails); // 3. separate again tails = tails.map(function (i) { if (!this.iwas) { this.product.afterTailsGiven(this, i, line); this.iwas = 1; } return this; }); return this.cache.tails = tails; }, afterGetTails: function (tails) { return tails; }, getOuterPlane: function () { // !! допущения: // 1. both centers is (0,0,0) var A = this.line.$points[0], a = A.length(), B = this.line.$points[1], b = B.length(), AB = B.clone().subtract(A).normalize(); //var doubleSquare = Vector.crossProduct(A, B); var comp = Vector.dotProduct(A, AB); var P = AB.scale(-comp).add(A); return new Plane(P, P); }, // максимальная длина продукта, maxLength: function () { } }); /** * Брус * @param Figure line * @param {} params */ Product.Rib.Beam = function (params) { Product.Rib.apply(this, [ $.extend({ type: 'Beam', title: 'Брус', width: 0, // ширина бруса (в радиусах) - параллельна радиусу thickness: 0, // толщина R: 0 // радиус сферы должен быть известен! }, params || {}) ]); // габариты приводим к долям радиуса, а получаем в неких единицах измерения this.width *= (this.measure || 1) / this.R; this.thickness *= (this.measure || 1) / this.R; } .inherits(Product.Rib) .override({ afterGetTails: function (tails) { var product = this; var outerPlane = this.getOuterPlane(); var plane = this.getPlane(true); return tails.each(function (i) { var dir = Vector.subtract(tails[1 - i].outer, this.outer); // save for given this.backDir = dir.clone(); // .outer принадлежат срединной плоскости (ориентирующей продукт) // .inner считаем var vect = Vector.crossProduct(plane.normal(), this.wall.normal()); vect.scale( Vector.dotProduct(Vector.subtract(this.outer, this.center), vect) > 0 ? -1 : 1 ); var cos = vect.cosWith(dir), sin = Math.sqrt(1 - cos * cos); vect.normalize().scale(product.width / sin); this.inner = Vector.add(this.outer, vect); // для определения отреза требуются вектора отклонения вершин от этой плоскости к бокам бруса this.walkers = [Vector.crossProduct(this.wall.normal(), outerPlane.normal())]; this.walkers[0].normalize(); this.walkers[0].scale(0.5 * product.thickness / plane.normal().cosWith(this.walkers[0])); this.walkers[1] = this.walkers[0].clone().scale(-1); if (this.coneAngle) { // Cone this dir.normalize().scale(product.thickness / 2 / Math.tan(this.coneAngle) / sin); this.walkers[0].add(dir); this.walkers[1].add(dir); } }); }, unify: function () { var product = this; var tails = this.getTails(); var unifiers = tails.map(function (i) { var tail = this; var dir = Vector.subtract(tails[1 - i].outer, this.outer).normalize(); var hOI = Vector.subtract(this.inner, this.outer).scale(.5); this.middle = Vector.add(tail.outer, hOI); var direct = Vector.dotProduct(Vector.crossProduct(this.walkers[0], hOI), dir) > 0; // [left, right] bevels this.bevelSides = [ Vector.component(this.walkers[direct ? 0 : 1], dir), Vector.component(this.walkers[direct ? 1 : 0], dir) ]; // если меньше градуса отклонение, то считаем что его нет for (var j = 0; j < 2; j++) { if (Math.abs(this.bevelSides[j] * 50) < product.thickness / 2) this.bevelSides[j] = 0; } // left = right = 0 this.bevelZero = !this.bevelSides[0] && !this.bevelSides[1]; // left + right = 0 this.bevelStraight = Math.abs(this.bevelSides[0] + this.bevelSides[1]) < 1e-6; // left = right this.bevelsEquals = Math.abs(this.bevelSides[0] - this.bevelSides[1]) < 1e-6; // else this.bevelChaos = !this.bevelZero && !this.bevelStraight && !this.bevelsEquals; // inner bevel (outer bevel = 0) this.bevelInner = Vector.component(hOI, dir); var PI2 = Math.PI / 2; var inner = Math.atan2(this.bevelInner, product.width / 2); var left = Math.atan2(this.bevelSides[0], product.thickness / 2); var right = Math.atan2(this.bevelSides[1], product.thickness / 2); return (!Math.round(inner * 500) ? 'T' : (inner < PI2 ? 'A' : 'B') + Product.angleUnify(inner < PI2 ? PI2 - inner : inner - PI2)) + (this.bevelZero ? 'Piped' : (this.bevelStraight ? 'Joint/GoodKarma/Semicone' + (left > 0 ? 'L' : 'R') + Product.angleUnify(left > 0 ? left : -left) : (this.coneAngle ? 'Cone' + Product.angleUnify(this.coneAngle) : // Nose only (Math.round(left * 500) ? '-L' + Product.angleUnify(left) + dihedralMark(left, inner) : '') + (Math.round(right * 500) ? '-R' + Product.angleUnify(right) + dihedralMark(right, inner) : '') ))) + '(' + tail.vertex.index + ')'; function dihedralMark(side, inner) { var normalOuter = new Vector(0, 0, 1); var byOuter = new Vector(Math.sin(side), Math.cos(side), 0); var toInner = new Vector(Math.sin(inner), 0, Math.cos(inner)); var normalCut = Vector.crossProduct(toInner, byOuter); var dihedral = normalCut.angleWith(normalOuter); var mark = Product.angleUnify(PI2 - dihedral); return mark == 0 ? '' : '-I' + mark; } }); unifiers.sort(); // for calc min/max this.midLength = tails[0].middle.distance(tails[1].middle); return 'Length' + Product.lengthUnify(this.maxLength() * product.R) + ' ' + unifiers.get().join(' '); }, maxLength: function () { var maxLength = this.midLength; this.getTails().each(function () { if (_.contains(['Joint', 'GoodKarma', 'Semicone'], this.vertex.product.type)) maxLength += Math.abs(this.bevelSides[0]); //if (this.bevelInner < 0) maxLength += Math.abs(this.bevelInner); }); return maxLength; }, minLength: function () { var minLength = this.midLength; this.getTails().each(function () { if (_.contains(['Joint', 'GoodKarma', 'Semicone'], this.vertex.product.type)) minLength -= Math.abs(this.bevelSides[0]); //if (this.bevelInner > 0) minLength -= Math.abs(this.bevelInner); }); return minLength; }, model: function (onExport) { var product = this; var tails = this.getTails(); var pp = []; $([tails[0].outer, tails[0].inner, tails[1].inner, tails[1].outer]).each(function (i) { var tail = tails[i >> 1]; if (isNaN(tail.walkers[0].x) || isNaN(tail.inner.x) || isNaN(tail.outer.x)) console.log('isNaN(tail.walker.x) || isNaN(tail.inner.x) || isNaN(tail.outer.x)'); pp.push(this.clone().add(tail.walkers[0])); pp.push(this.clone()); pp.push(this.clone().add(tail.walkers[1])); }); var faces = [ [pp[1], pp[0], pp[3], pp[4]], // one tail sides [pp[2], pp[1], pp[4], pp[5]], [pp[10], pp[11], pp[8], pp[7]], // second tail sides [pp[9], pp[10], pp[7], pp[6]], [pp[4], pp[3], pp[6], pp[7], pp[8], pp[5]], // inner face [pp[0], pp[9], pp[6], pp[3]], // side [pp[2], pp[5], pp[8], pp[11]], // side [pp[1], pp[2], pp[11], pp[10], pp[9], pp[0]], // outer face ]; // model on export if (onExport) { return faces; } var cont = new Figure.Container({ figures: $([ faces.pop() // outer only ]).map(function () { // ориентация полигона var polypp = this, outerp; $(pp).each(function () { if (-1 == $.inArray(this, polypp)) outerp = this; }); var normal = Vector.crossProduct( Vector.subtract(polypp[1], polypp[0]), Vector.subtract(polypp[2], polypp[0])); if (Vector.dotProduct(Vector.subtract(outerp, polypp[0]), normal) < 0) { var reverted = [], p; while (p = polypp.shift()) reverted.push(p); polypp = reverted; } return new Figure({ type: 'polygon', points: polypp }); }), points: pp, source: this.line }); cont.$primitives.each(function () { this.figure = product.line.figure; }); return cont; }, // draw product scheme on canvas // @param DomElement canvas // @param Object opts plotter options plot: function (canvas, opts) { var product = this; var tails = this.getTails(); var sizeOfTail = _.map(tails, function (tail) { return 2 * _.max(_.map(tail.bevelSides, Math.abs)) + Math.abs(tail.bevelInner); }), xGaps = []; var margin = 20, // px milkRight = 20, // px xyRatio = ($(canvas).width() - 2 * margin - milkRight) / ($(canvas).height() - 2 * margin), maxLength = product.maxLength(), maxVisibleLength = xyRatio * product.thickness, gapVisibleWidth = product.thickness / 4; if (maxLength > maxVisibleLength) { var productDelta = product.maxOuterLength - product.minOuterLength; if (productDelta) { var visibleProductLength = maxVisibleLength * (.6 + .4 * (maxLength - product.minOuterLength) / productDelta), gapDelta = maxLength - visibleProductLength; } else { var gapDelta = maxLength - maxVisibleLength; } var gapStart = sizeOfTail[0] + (maxLength - sizeOfTail[0] - sizeOfTail[1]) / 2 - gapDelta / 2; if (gapStart > sizeOfTail[0]) { xGaps.push({ x: gapStart, from: gapDelta + gapVisibleWidth, to: gapVisibleWidth }); } else { gapDelta = maxLength - sizeOfTail[0] - sizeOfTail[1]; xGaps.push({ x: sizeOfTail[0], from: gapDelta + gapVisibleWidth, to: gapVisibleWidth }); } //console.log(product.line.index, maxVisibleLength, maxLength, xGaps[0]) } var plotter = new Plotter.Beam(canvas, $.extend(opts, { depth: this.width, width: this.maxOuterLength, length: this.maxLength(), height: this.thickness, // толщина доски (бруса) рисуется в высоту margin: margin, milkRight: milkRight, resize: false, R: this.R, xGaps: xGaps, textZoom: 2, fixOutXProportion: true })) .ydivision(0, 'left', 'top') .ydivision(this.thickness, 'left', 'bottom') .start(this, tails[0]) .tail(tails[0], false, 'left', this) .offset({x: this.midLength}) .tail(tails[1], true, 'right', this) .end(); // side angles of face var line = this.line; var byLineNormal = Vector.crossProduct(tails[0].vertex.$points[0], tails[1].vertex.$points[0]); $.each(line.origin.$super.face, function (i, face) { if (line.bindedFace && line.bindedFace !== face) return; var a = Product.angleUnify(face.product.normal.angleWith(byLineNormal)) / 10; a = (a > 90) ? 180 - a : a; // figure is convex var outer = face.$points.not(line.$points)[0]; var y = (outer.cosWith(byLineNormal) <= 0) ? product.thickness : 0; plotter.textByLine( '∟' + a + '°', {y: y, x: 0}, {y: y, x: xGaps[0] ? xGaps[0].x + product.thickness * 3 : product.thickness * 5}, { otherSide: !y } ); }); }, materialName: function () { return __('Beams') + ' ' + Math.round(this.width * this.R / .001) + 'x' + Math.round(this.thickness * this.R / .001) + __('mm'); }, meter: function () { var mat = this.materialName(), meter = {}; // площадь основания (допущение: срез был по оси Y) if (this.line.selvage) { var pp = this.line.$points; meter[__('Base area, m2')] = Math.abs((pp[0].x * pp[1].z - pp[1].x * pp[0].z) * this.R * this.R / 2); } meter[mat] = {}; meter[mat][__('Total length of beams, m')] = this.maxLength() * this.R; meter[mat][__('Total volume of beams, m3')] = this.midLength * this.width * this.thickness * this.R * this.R * this.R; meter[mat]['max:' + __('Max. beam length, mm')] = Product.lengthUnify(this.maxLength() * this.R); // угол сопряжения граней var $faces = this.line.origin.$super.face; var $normals = $faces.length == 2 ? $faces.map(function () { return Vector.crossProduct( Vector.subtract(this.$points[0], this.$points[1]), Vector.subtract(this.$points[2], this.$points[1]) ); }) : false; var edgel = $normals ? $normals[0].angleWith($normals[1]) : false; if (edgel) { meter[mat]['range:' + __('Angle between faces, °')] = 180 - 180 * edgel / Math.PI; } return meter; } }); </script> <script type="text/javascript">/** * Доска для чертежей */ Plotter = function (canvas, opts) { var plotter = this; // canvas this._$canvas = $(canvas); this._context = this._$canvas[0].getContext('2d'); this._width = this._$canvas.width() - (opts.milkRight || 0); this._height = this._$canvas.height(); // canvas style this._context.lineCap = 'round', this._context.lineJoin = 'bevel', this._context.miterLimit = 10; this._context.globalAlpha = .9; // styles this._styles = { solid: { strokeStyle: "black", lineWidth: 2 }, backside: { strokeStyle: "gray", lineWidth: 2 }, division: { strokeStyle: "rgba(141,141,141,.5)", lineWidth: 1 }, white: { strokeStyle: "white", lineWidth: 2 }, fillWhite: { fillStyle: 'white' } }; this._dashedLine = false; this._dashedStep = 5; this._currentStyle = { line: {}, point: {} }; // props & defaults $.extend(this, opts); // text zooming this.textZoom = this.textZoom || 1; this.R = opts.R || 1; this.margin = opts.margin || 16; // px // input frame (data) this._frameIn = { l: 0, t: 0, w: opts.width || console.log('Plotter: no width'), h: opts.height || console.log('Plotter: no height') }; // output frame (canvas) this._frameOut = { l: this.margin, t: this.margin, w: this._width - 2 * this.margin, h: this._height - 2 * this.margin }; // plot current offset this._offset = { x: opts.offset && opts.offset.x || 0, y: opts.offset && opts.offset.x || 0 }; // gaps on x this.xGaps = opts.xGaps || []; this.xGapDelta = 0; $(this.xGaps).each(function () { plotter.xGapDelta += this.to - this.from; }); this._frameIn.w += this.xGapDelta; // пропорции if (opts.fixOutXProportion) { this._frameOut.w = this._frameOut.h * (this._frameIn.w / this._frameIn.h); } else { this._frameOut.h = this._frameOut.w * (this._frameIn.h / this._frameIn.w); } // resize if (opts.resize) { var of = this._offset; this._offset = {x: 0, y: 0}; this.resizeCanvasHeightByInputProportion(); this._offset = of; } // ratio this.ratio = { x: this._frameOut.w / this._frameIn.w, y: this._frameOut.h / this._frameIn.h }; this.ratio.l = Math.sqrt(this.ratio.x * this.ratio.y); } .override({ resizeCanvasHeightByInputProportion: function () { var height = this._plane({x: 0, y: this._frameIn.h}, {y: this.margin}).y; this._frameOut.h = height - 2 * this.margin; this._$canvas[0].height = height; }, _setStyle: function (subj, style) { if (style instanceof Array) { for (var i = 0; i < style.length; i++) { this._setStyle(subj, style[i]); } return; } var values = typeof style == 'object' ? style : this._styles[style] || {}; for (var k in values) { this._context[k] = values[k]; } if (subj == 'line') { this._dashedLine = (style == 'backside' || style == 'dashed'); } }, _plane: function (p, offset) { var plotter = this; var xGapDelta = 0; $(this.xGaps).each(function () { if (plotter._offset.x + p.x > this.x + this.from) xGapDelta += this.to - this.from; }); return { x: Math.round( this._frameOut.l + ((this._offset.x + p.x + xGapDelta) - this._frameIn.l) * this._frameOut.w / this._frameIn.w + (offset && offset.x || 0) ), y: Math.round( this._frameOut.t + ((this._offset.y + p.y) - this._frameIn.t) * this._frameOut.h / this._frameIn.h + (offset && offset.y || 0) ) }; }, _moveTo: function (p) { this._context.moveTo(p.x + .5, p.y + .5); }, _lineTo: function (p) { this._context.lineTo(p.x + .5, p.y + .5); }, offset: function (o) { if (!o) return this._offset; this._offset.x += o.x || 0; this._offset.y += o.y || 0; return this; }, line: function (p1, p2, style, outputXY) { var ctx = this._context; ctx.save(); this._setStyle('line', style); ctx.beginPath(); if (this._dashedLine) { var s = outputXY ? p1 : this._plane(p1); var f = outputXY ? p2 : this._plane(p2); var length = Math.sqrt((s.x - f.x) * (s.x - f.x) + (s.y - f.y) * (s.y - f.y)); var step = this._dashedStep; var v = {x: (f.x - s.x) * step / length, y: (f.y - s.y) * step / length}; var p = {x: s.x + v.x / 2, y: s.y + v.y / 2}; for (var i = 0, l = 0; l < length; i++) { this[(i % 2) ? '_lineTo' : '_moveTo'](p); l += step; p.x += l < length - 1 ? v.x : v.x / 2; p.y += l < length - 1 ? v.y : v.y / 2; } } else { this._moveTo(outputXY ? p1 : this._plane(p1)); this._lineTo(outputXY ? p2 : this._plane(p2)); } ctx.closePath(); ctx.stroke(); ctx.restore(); return this; }, circle: function (pos, r, style) { pos = this._plane(pos); r *= this.ratio.l; var ctx = this._context; ctx.save(); this._setStyle('circle', style); ctx.beginPath(); ctx.arc(pos.x, pos.y, r, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); ctx.stroke(); ctx.restore(); return this; }, text: function (pos, text, opts) { opts = $.extend({ planePos: true, fillStyle: 'black', strokeStyle: 'black' }, opts || {}); pos = opts.planePos ? this._plane(pos) : pos; var ctx = this._context; ctx.save(); ctx.textBaseline = opts.valign || 'middle'; ctx.textAlign = opts.align || 'center'; ctx.font = (opts.fontSize || 0.5) * this.textZoom + "em monospace, Optimer, verdana"; ctx.fillStyle = opts.fillStyle; ctx.strokeStyle = opts.strokeStyle; ctx.strokeWidth = 2; ctx.translate(pos.x, pos.y); ctx.rotate(opts.rotate || 0); ctx.fillText(text, 0, 0); ctx.restore(); return this; }, textByLine: function (text, A, B, opts) { if (text === undefined) { debugger; } opts = opts || {}; var pos = this.average(A, B, opts.q || 1 / 2), length = Math.sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)), normal = {x: (A.y - B.y) / length, y: (B.x - A.x) / length}; var rev = (opts.sup && normal.y) ^ opts.otherSide > 0 ? -1 : 1; pos.x += rev * normal.x * 10 / this.ratio.x; pos.y += rev * normal.y * 10 / this.ratio.y; var angle = Math.atan2(A.y - B.y, A.x - B.x); this.text(pos, text, $.extend({ rotate: angle < Math.PI / 2 ? angle > -Math.PI / 2 ? angle : angle + Math.PI : angle - Math.PI, fontSize: 0.6 }, opts)); }, vertical: function (x, style) { this.line( this._plane({x: x, y: 0}, {y: -this.margin}), this._plane({x: x, y: this._frameIn.h}, {y: this.margin}), style, true // dont plane again ); return this; }, xdivision: function (x, align, valign, anchor) { this.vertical(x, 'division'); // division var floatDiv = (x + this._offset.x) * this.R / 0.001; // rounding var div = Math.round( (typeof anchor != 'undefined') ? anchor + Math.round(floatDiv - anchor) : floatDiv ); var pos = this._plane({ x: x, y: (valign == 'top') ? 0 : this._frameIn.h }, { y: (valign == 'top') ? -this.margin : this.margin }); //this.text(pos, div, {valign: valign, align: align}); var ctx = this._context; ctx.textBaseline = valign; ctx.textAlign = align; ctx.font = "14px monospace, Optimer, verdana";//(0.5) * this.textZoom + "em Optimer, verdana"; ctx.fillStyle = "black"; ctx.strokeStyle = "black"; ctx.strokeWidth = 2; ctx.fillText(div, pos.x, pos.y); return floatDiv; }, horizontal: function (y, style) { this.line( this._plane( {x: 0, y: y}, {x: -this.margin} ), this._plane( {x: this._frameIn.xmax || this._frameIn.w, y: y}, {x: this.margin} ), style, true // dont plane coordinates again ); // gaps on x var plotter = this; setTimeout(function () { $(plotter.xGaps).each(function () { plotter.line( {x: this.x, y: y}, {x: this.x + this.from + 0.00001, y: y}, ['white', 'dashed'] ); }); }, 1); return this; }, ydivision: function (y, align, valign) { this.horizontal(y, 'division'); // division var div = Math.round((y + this._offset.y) * this.R / 0.001); var pos = this._plane({ x: (align == 'left') ? 0 : this._frameIn.w, y: y }, { x: (align == 'left') ? -this.margin : this.margin }); var ctx = this._context; ctx.textBaseline = valign; ctx.textAlign = align; ctx.font = "14px monospace, Optimer, verdana"; //(0.5) * this.textZoom + "em Optimer, verdana"; ctx.fillStyle = "black"; this._context.fillText(div, pos.x, pos.y); return this; }, vertexLabel: function (index, pos, ribs) { var rayCount = _.filter(ribs, function (rib) { return rib === rib.origin; }).length; pos = this._plane(pos); // sun-connector var ctx = this._context, r = 12; ctx.strokeStyle = "#ccc"; ctx.strokeWidth = 1; ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(pos.x, pos.y, r, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); ctx.stroke(); // rays rayCount = rayCount || 6; for (var i = 0.3; i < rayCount; i++) { var offset = { x: r * Math.cos(i * 2 * Math.PI / rayCount), y: r * Math.sin(i * 2 * Math.PI / rayCount) }; ctx.beginPath(); ctx.moveTo(pos.x + offset.x, pos.y + offset.y); ctx.lineTo(pos.x + 2 * offset.x, pos.y + 2 * offset.y); ctx.closePath(); ctx.stroke(); } // index ctx.fillStyle = "#000"; ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; ctx.textWeight = 'bold'; ctx.font = "12px monospace, Optimer, verdana"; ctx.fillText(index, pos.x, pos.y); }, planeAngle: function (A, B, C, style) { style = $.extend({ strokeStyle: 'gray', fillStyle: 'black' }, style); var AB = this.distance(A, B); var BC = this.distance(B, C); var CA = this.distance(C, A); var angle = Math.acos((AB * AB + BC * BC - CA * CA) / (2 * AB * BC)); angle = Math.round(angle * 180 * 5 / Math.PI) / 5; var Ar = Math.atan2(A.y - B.y, A.x - B.x); var Cr = Math.atan2(C.y - B.y, C.x - B.x); var R = 62; A = this._plane(A); B = this._plane(B); C = this._plane(C); var ctx = this._context; ctx.save(); this._setStyle('circle', style); ctx.beginPath(); ctx.arc(B.x, B.y, R, Ar, Cr, true); ctx.stroke(); ctx.restore(); // degrees var bstx = (Ar + Cr) / 2 + (Math.abs(Ar - Cr) > Math.PI ? Math.PI : 0); //bstx += bstx > Math.PI + 1e-5 ? -Math.PI : 0; if (angle) { this.text( { x: B.x + (R + 10) * Math.cos(bstx), y: B.y + (R + 10) * Math.sin(bstx) }, angle + '°', _.extend({ rotate: bstx + Math.PI / 2 + (bstx > 0 ? Math.PI : 0), planePos: false, fontSize: 0.6 }, style) ); } return this; }, average: function (a, b, q) { q = (q === undefined) ? .5 : q; return { x: a.x * (1 - q) + b.x * q, y: a.y * (1 - q) + b.y * q }; }, distance: function (A, B) { return Math.sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); } }); /** * Чертеж отрезов бруса */ Plotter.Beam = function (canvas, opts) { Plotter.apply(this, arguments); this._frameIn.xmax = opts.length || opts.width; } .inherits(Plotter) .override({ start: function (product, tail) { this._offset = { x: tail.coneAngle ? Math.abs(tail.bevelInner) : Math.max( Math.abs(tail.bevelInner + (!tail.bevelChaos && tail.bevelSides[0])), Math.abs(tail.bevelInner + (!tail.bevelChaos && tail.bevelSides[1]))), y: 0 }; this._left = [null, null]; this._right = [null, null]; return this; }, tail: function (tail, turnMe, whichSide/*nothing*/, product) { var TURN = turnMe ? -1 : 1; var outerLink, innerLink; var outerCenter = {x: -TURN * tail.bevelInner, y: this._frameIn.h / 2}, innerCenter = {x: TURN * tail.bevelInner, y: this._frameIn.h / 2}; if (tail.bevelZero || tail.bevelsEquals || tail.bevelChaos) { outerLink = this.xdivision(outerCenter.x, turnMe ? 'left' : 'right', 'top'); innerLink = this.xdivision(innerCenter.x, turnMe ? 'right' : 'left', 'bottom'); } var outerBevels = []; for (var i = 0; i < 2; i++) { var TOP = (turnMe ^ i) ? 1 : 0; var outerBevel = {x: outerCenter.x + TURN * tail.bevelSides[i], y: TOP ? 0 : this._frameIn.h}, innerBevel = {x: innerCenter.x + TURN * tail.bevelSides[i], y: TOP ? 0 : this._frameIn.h}; outerBevels.push(outerBevel); if (!tail.bevelZero && tail.bevelsEquals && i || tail.bevelChaos) { outerLink = this.xdivision(outerBevel.x, turnMe ? 'left' : 'right', 'top', outerLink); innerLink = this.xdivision(innerBevel.x, turnMe ? 'right' : 'left', 'bottom', innerLink); } if (tail.bevelStraight && !tail.bevelsEquals) { outerLink = this.xdivision(outerBevel.x, turnMe ? 'left' : 'right', TOP ? 'top' : 'bottom', outerLink); innerLink = this.xdivision(innerBevel.x, turnMe ? 'right' : 'left', TOP ? 'top' : 'bottom', innerLink); } //var style = (whichSide == 'middle') || (whichSide == 'right' ^ outerCenter.x < innerCenter.x) ? 'backside' : 'solid'; this.line(outerCenter, outerBevel, 'solid'); this.line(innerCenter, innerBevel, 'dashed'); function accum(accum, val, method) { return accum == null ? val : Math[method](accum, val); } this._left[TOP] = accum(this._left[TOP], this._offset.x + outerBevel.x, 'min'); this._right[TOP] = accum(this._left[TOP], this._offset.x + outerBevel.x, 'max'); // angle between outer plane and plane to cut if ( (tail.bevelZero && !i) || // Piped (once) (!tail.bevelStraight && !i) || // Cone (once) (!tail.bevelZero && tail.bevelStraight && (turnMe ^ outerBevel.x > outerCenter.x)) // side what near to rub center (Joint, GoodKarma, Semicone) ) { var byOuter = new Vector(outerBevel.x - outerCenter.x, outerBevel.y - outerCenter.y, 0); var toInner = new Vector(innerCenter.x - outerCenter.x, innerCenter.y - outerCenter.y, this.depth); var normalCut = Vector.crossProduct(byOuter, toInner).scale(i ? 1 : -1); var normalOuter = new Vector(0, 0, this.depth); var angleBetween = normalOuter.angleWith(normalCut); var pp = i ? [outerBevel, outerCenter] : [outerCenter, outerBevel]; this.textByLine( '∟' + Math.round(1800 * angleBetween / Math.PI) / 10 + '°', pp[0], pp[1], { q: turnMe ? 0.382 : 0.618, fillStyle: 'blue' } ); } else if ( tail.bevelStraight && // side what far from rib center (Joint, GoodKarma) (!tail.bevelZero || i) // <exclude> Piped (once) ) { // angle on outer plane var planeAngle = [outerCenter, outerBevel, {x: outerBevel.x, y: outerCenter.y}]; if (turnMe ^ i ^ outerBevel.x > outerCenter.x) planeAngle.reverse(); this.planeAngle.apply(this, planeAngle.concat([{fillStyle: 'red', strokeStyle: 'gray'}])); } } if (!tail.bevelZero && tail.bevelsEquals || tail.bevelChaos) { this.line(innerCenter, outerCenter, 'dashed'); } // label this.vertexLabel(tail.vertex.index, outerCenter, tail.vertex.$super.line); // angle on outer plane (Cone) if (!tail.bevelStraight) { var planeAngle = [outerBevels[0], outerCenter, outerBevels[1]]; if (!tail.bevelChaos ^ tail.bevelsEquals) planeAngle = planeAngle.reverse(); this.planeAngle.apply(this, planeAngle.concat([{fillStyle: 'red', strokeStyle: 'gray'}])); } return this; }, end: function () { this._offset = {x: 0, y: 0}; this.line({x: this._left[1], y: 0}, {x: this._right[1], y: 0}, 'solid'); this.line({x: this._left[0], y: this._frameIn.h}, {x: this._right[0], y: this._frameIn.h}, 'solid'); return this; } }); /** * Чертеж треугольника */ Plotter.Triangle = function (canvas, opts) { var plotter = this; var angles = this.angles = opts.angles; var radiuses = this.radiuses = opts.radiuses; this.maxR = Math.max.apply(null, radiuses); this.$lines = opts.$lines; // вершины A, B, C var ABC = this.ABC = []; a = -Math.PI / 2; for (var i = 0; i < 3; i++) { ABC[i] = { x: radiuses[i] * Math.cos(a), y: radiuses[i] * Math.sin(a) } a -= 2 * angles[(i + 2) % 3]; } // основания высот от вершин на чертеже Ah, Bh, Ch var ABCh = this.ABCh = []; for (var a = 0; a < 3; a++) { var b = (a + 1) % 3, c = (a + 2) % 3; ABCh[a] = Vector.project( Vector.subtract(ABC[a], ABC[c]), Vector.subtract(ABC[b], ABC[c]) ).add(ABC[c]); } // размер полотна opts = $.extend({ width: 2 * this.maxR, height: 2 * this.maxR, margin: 20, // px resize: true, offset: {x: this.maxR, y: this.maxR} }, opts); // parent::constructor() Plotter.apply(this, [canvas, opts]); } .inherits(Plotter) .override({ outerCircle: function () { return this.circle({x: 0, y: 0}, this.maxR, ['gray', 'fillWhite']); }, triangle: function () { for (var i = 0; i < 3; i++) { var A = this.ABC[i], B = this.ABC[(i + 1) % 3], C = this.ABC[(i + 2) % 3]; var Ah = this.ABCh[i]; this.line(B, C, { strokeStyle: productPalette.line[this.$lines[i].order].css, lineWidth: 3 }); this.line(A, Ah, { strokeStyle: '#bbb' }); } for (var i = 0; i < 3; i++) { var A = this.ABC[i], B = this.ABC[(i + 1) % 3], C = this.ABC[(i + 2) % 3]; var Ah = this.ABCh[i]; this.textByLine(Product.lengthUnify(this.distance(B, Ah)), B, Ah, {q: .38}); this.textByLine(Product.lengthUnify(this.distance(Ah, C)), Ah, C, {q: .62}); var edge = Math.round(this.abcEdges[i] * 180 * 10 / Math.PI) / 10; this.textByLine(this.$lines[i].index + ' ∟' + edge + '°', B, C, { fontSize: 0.9, fillStyle: productPalette.line[this.$lines[i].order].css }); this.textByLine(Product.lengthUnify(this.distance(A, Ah)), A, Ah, {q: .9}); } return this; }, heights: function () { }, vertexes: function () { var plotter = this; $(this.ABC).each(function (i) { // todo: странная проблема разной направленности массивов angles и $vertexes, хотя источник у них один.. // подогнал в ручную сверяя со схемой var n = 2 - i; plotter.vertexLabel(plotter.$vertexes[n].index, this, plotter.$vertexes[n].$super.line) }); } });</script> <script type="text/javascript">/** * Накопитель значений и их статистика * * var meter = new Meter; * * meter.push( [ groupKey ], { key: value, .. } ); * */ Meter = function () { this.values = {}; } .override({ // push() push: function (map, context) { if (typeof map == 'string') { var h = {}, args = [].slice.call(arguments, 0); h[args[0]] = args[1]; args[1] = h; return this.push.apply(this, args.slice(1)); } context = context || this.values; for (var k in map) { var matchFn = /^(\w+):(.*)$/.exec(k), fn = (matchFn && this.operators[matchFn[1]]) ? matchFn[1] : 'default'; if (fn == 'default' && typeof(map[k]) == 'object') { context[k] = context[k] || {}; this.push(map[k], context[k]); } else { context[k] = this.operators[fn](context[k], map[k]); } } }, operators: { default: function (accum, value) { // sum return (accum || (isNaN(value) ? '' : 0)) + value; }, min: function (accum, value) { return (accum == undefined) ? value : Math.min(accum, value); }, max: function (accum, value) { return (accum == undefined) ? value : Math.max(accum, value); }, swing: function (accum, value) { return { min: (accum && accum.min != undefined) ? Math.min(accum.min, value) : value, max: (accum && accum.max != undefined) ? Math.max(accum.max, value) : value }; }, range: function (accum, value) { return { min: (accum && accum.min != undefined) ? Math.min(accum.min, value) : value, max: (accum && accum.max != undefined) ? Math.max(accum.max, value) : value }; } }, reporters: { swing: function (value) { return (value.max || 0) - (value.min || 0); }, range: function (value) { return (value.max - value.min < 1e-6) ? value.min : [value.min, '-', value.max]; } }, reportText: function (context, indent, report) { indent = indent || ''; context = context || this.values; report = report || []; var objects = []; for (var k in context) { var matchFn = /^(\w+):(.*)$/.exec(k), key = k, value = context[k]; if (matchFn) { if (this.reporters[matchFn[1]]) value = this.reporters[matchFn[1]](value); key = matchFn[2]; } if (typeof value == 'object' && !(value instanceof Array)) { objects.push({ key: '\n' + indent + key.bold(), val: false }); this.reportText(value, indent + ' ', objects); } else { report.push({ key: indent + key, val: value }); } } $.each(objects, function () { report.push(this); }); var maxKeyLength = 0; return (arguments.length == 3) ? 0 : $(report).each(function () { maxKeyLength = Math.max(this.key.length, maxKeyLength); return this; }).map(function () { while (this.key.length < maxKeyLength) this.key += ' '; var key = this.key.replace(/(,\s*.)(\d)(\D|$)/, '$1&sup$2;$3'); return key + ' ' + (this.val ? $.map( $.makeArray(this.val), function (val) { return typeof val == 'number' ? Meter.numberFormat(val) : val; } ).join('') : ''); }).get().join('\n'); } }); Meter.numberFormat = function (val) { if (!val) return ''; var val100 = Math.round(val / .01); return Math.floor(val100 / 100) + ( (val100 % 100) ? '.' + ( (val100 % 100) < 10 ? '0' : '' ) + (val100 % 100) : '' ); }</script> <!-- extra --> <script type="text/javascript">!function () { var __pointsEnum, __points, __faces, __lines; /** * Деление фейсов фигуры (равные дуги) * @return this */ Figure.prototype.splitFaces_EA = function (N) { var figure = this; // init __faces = []; __lines = {}; __points = {}; __pointsEnum = 0; // save prev points _.each(figure.$points, function (p) { __points[p._enum = __pointsEnum++] = p; }); var triIndex = 0; _.each(this.$primitives, function (p) { if (p.type == 'face') { // init edge points var A = p.points[0], B = p.points[1], C = p.points[2]; var AB = [A, B], BC = [B, C], CA = [C, A]; _.each([AB, BC, CA], function (segment) { var a = segment[0], b = segment.pop(); for (var i = 1; i < N; i++) segment.push(edgePoint(a, b, i, N)); segment.push(b); }); // main var up = [A], down; for (var n = 1; n <= N; n++) { down = [CA[N - n]]; for (var i = 1; i < n; i++) { if (n == N) { down.push(BC[N - i]); } else { var point = findPoint( AB[n], CA[N - n], BC[N - i], AB[i], CA[N - n + i], BC[n - i], A, i ); down.push(point); } } down.push(AB[n]); // collect faces for (i = 0; i < n; i++) { addFace(up[i], down[i + 1], down[i], [n, N - i, N - n + i + 1], triIndex); if (i > 0) addFace(down[i], up[i - 1], up[i], [n - 1, N - i, N - n + i], triIndex); } up = down; } triIndex++; } }); __points = _.map(_.values(__points), function (point) { return new Figure({ type: 'vertex', points: [point], center: point.center }); }); console.log('points', __points.length, 'lines', _.values(__lines).length, 'faces', __faces.length); this.$primitives = $(__points.concat(_.values(__lines)).concat(__faces)); return this; } Figure.prototype.splitFaces_EA_updateToMexican = function (N) { var lines = _.filter(this.$primitives, function (p) { return (p.type == 'line') // && (2 <= p.sideDistance && p.sideDistance < N); }); Figure.equalizeLineGroups( _.groupBy(lines, 'sideDistance') ); return this; } Figure.prototype.splitFaces_updateToClassII = function () { console.time('Update to Class II'); // prepare relations this.relations(); // first wave var prevVertexWave = this.$primitives.map(function () { this.sideDistance = 0; this.underWave = (this.type == 'vertex') && this.$points[0].pptPoint; this.underLine = this.underWave ? 5 : 0; this.underLine1 = 0; return this.underWave ? this : null; }); var lines = []; do { var vertexWave = [], lineWave = []; _.each(prevVertexWave, function (prevVertex) { var prevSideDistance = prevVertex.sideDistance; _.each(prevVertex.$super.line, function (line) { if (!line.underWave) { lineWave.push(line); _.each(line.$sub.vertex, function (vertex) { if (vertex != prevVertex && !vertex.lastWave) { if (!vertex.underLine) vertexWave.push(vertex); vertex.sideDistance += prevSideDistance; if (1 == prevSideDistance) vertex.underLine1++; vertex.underLine++; } }); line.underWave = true; } }); }); _.each(vertexWave, function (vertex) { vertex.sideDistance /= vertex.underLine; if (vertex.underLine % 2) vertex.sideDistance++; else if (vertex.underLine == vertex.underLine1) vertex.sideDistance = 0; vertex.lastWave = true; }); _.each(lineWave, function (line) { var lengths = _.pluck(line.$sub.vertex, 'sideDistance'); if (lengths[0] == lengths[1] && lengths[0] == 1) line.sideDistance = 0; else line.sideDistance = lengths[0] + lengths[1]; }); lines = lines.concat(lineWave); prevVertexWave = vertexWave; } while (lineWave.length); console.log(_.groupBy(lines, 'sideDistance')); Figure.equalizeLineGroups( _.groupBy(lines, 'sideDistance') ); // clean _.each(this.$primitives, function (f) { delete f.sideDistance; delete f.underLine; delete f.underWave; delete f.lastWave; }); console.timeEnd('Update to Class II'); return this; }; Figure.prototype.splitFaces_updateToClassIII = function (M, N) { var figure = this, subdivisionScheme = [], pointsEnum = _.chain(this.$points).pluck('_enum').max().value(); isNaN(pointsEnum) && console.error('points enum is', pointsEnum); M = Number(M); N = Number(N); var S = M * M + M * N + N * N; // prepare entities relation info this.relations(); // make a Class III M,N subdivision scheme !function () { var base = [ [-M - N, N, M], // n vector [-M, M + N, -N] // m vector ], trio = [[0, 0], [N, M], [M + N, -N]], trioSquare = square.apply(null, trio); for (var y = -N; y < M; y++) { for (var x = 0; x < M + N; x++) { triangle([x, y], [x, y + 1], [x + 1, y]); triangle([x + 1, y + 1], [x + 1, y], [x, y + 1]); } } // assertions if (subdivisionScheme.length != S) { console.error('Class III: bad scheme with size', subdivisionScheme.length, 'expected', S); } var integer = _.chain(subdivisionScheme).map(function (f) { return _.map(f, roundS); }).value(), stat = _.chain(integer).flatten(true).map(function (p) { return _.sortBy(p).join() }).countBy().value(); _.each(stat, function (count) { if (count % 3) { console.error('Class III: wrong symmetry on scheme', integer); } }); // end function triangle(A, B, C) { var center = alter2base([(A[0] + B[0] + C[0]) / 3, (A[1] + B[1] + C[1]) / 3]), points = _.map([A, B, C], alter2base), inFace = _.countBy(points, function (p) { return _.all(p, positive) }); if ( _.all(center, positive) // center belongs to face || ( !_.some(center, negative) && // center belongs to edge of face inFace["true"] > inFace["false"] // inner vertices GT outer ) ) { subdivisionScheme.push(points); /*if (inFace["false"] == 2 || (!_.some(center, negative) && !_.all(center, positive))) { console.log( 'scheme face: center', center, //_.map(center, function(c){ return Math.round(c*S*3) / 3 }), inFace, '=>', points ); }*/ } } // translate coords to face-based function alter2base(alter) { var coords = _.reduce(base, function (result, axis, axisIndex) { _.each(axis, function (axisCoord, axisCoordIndex) { result[axisCoordIndex] += axisCoord * alter[axisIndex] / S; }); return result; }, [1, 0, 0]); // assertions Math.abs(_.reduce(coords, sum, 0) - 1) < 1e-9 || console.error('Class III: bad coords of subdivision point', coords); _.filter(coords, negative).length <= 1 || console.error('Class III: bad coords with greater than 1 negative', coords); return coords; } // 2d function diff(B, A) { return [B[0] - A[0], B[1] - A[1]]; } function square(A, B, C) { A = diff(A, C); B = diff(B, C); return A[0] * B[1] - A[1] * B[0]; } }(); //console.log(_.map(faces, function(pp) { return _.map(pp, function(p) { return p[0] + p[1] + p[2] }) })); // subdivision each face by scheme !function () { var prevPrimitivesLength = figure.$primitives.length, addedLines = {}; _.each(_.where(figure.$primitives, {type: 'vertex'}), function (vertex) { vertex.$points[0].vertex = vertex; }); _.each(_.where(figure.$primitives, {type: 'face'}), function (face) { var facePoints = face.$points; _.each(subdivisionScheme, function (pointsCoords) { var points = _.map(pointsCoords, coords2point); figure.$primitives.push(new Figure({ type: 'face', points: points })); //console.log('+ face'); _.each([1, 2, 0], function (p1, p2) { var lineIndex = [points[p1].vertex._enum, points[p2].vertex._enum].sort().join(); if (!addedLines[lineIndex]) { if (_.find(figure.$primitives, function (p) { return p.type == 'line' && ( (points[p1] === p.$points[0] && points[p2] === p.$points[1]) || (points[p1] === p.$points[1] && points[p2] === p.$points[0]) ); })) { console.error('doublet line detected for', points[p1], points[p2]); } figure.$primitives.push(new Figure({ type: 'line', points: [points[p1], points[p2]], __enums: [points[p1].vertex._enum, points[p2].vertex._enum] })); addedLines[lineIndex] = true; //console.log('+ line'); } else { //console.log('- decline line', points[p1].vertex._enum, points[p2].vertex._enum); } }); }); function coords2point(coords) { var baseIndex = _.indexOf(coords, 1); if (baseIndex != -1) { // PPT point //console.log('PPT point happens') return facePoints[baseIndex]; } var negativeIndex = _.indexOf(coords, _.filter(coords, negative)[0]); if (negativeIndex != -1) { // point outside of the face var linePoints = _.filter(facePoints, function (point, index) { return index !== negativeIndex; }), negativeLine = _.find(face.$sub.line, function (line) { var points = line.$points; return 0 || (points[0] === linePoints[0] && points[1] === linePoints[1]) || (points[0] === linePoints[1] && points[1] === linePoints[0]); }), negativeFace = _.find(negativeLine.$super.face, function (f) { return f !== face }), negativePoint = _.difference(negativeFace.$points.get(), face.$points.get())[0], negativeOrdinate = coords[negativeIndex], base = []; /** * Translate coordinates to other face by negative ordinate * * (A, B, C) * (a, b, c) === (A, B, A + B - C) * (x, y, z) * => * z = -c * y = b + c * x = a + c * where * (A + B - C) new base ordinate */ coords = _.map(coords, function (coord, index) { base[index] = (negativeIndex === index) ? negativePoint : facePoints[index]; return (negativeIndex === index) ? -coord : coord + negativeOrdinate; }); // assert Math.abs(_.reduce(coords, sum, 0) - 1) < 1e-9 || console.error('Class III: bad coords for negative face', coords); } // find or calc new point return (function (face, base) { face.classIIIPoints = face.classIIIPoints || []; // make stamp of face-based coordinates of point var stamp = _.map(base, function (point, index) { return { order: point.vertex._enum, value: coords[index] }; }); stamp = _.pluck(_.sortBy(stamp, 'order'), 'value'); // try to find similar class III point produced previous to var found = _.find(face.classIIIPoints, function (memo) { return _.all(memo.stamp, function (memoOrdinate, index) { return Math.abs(memoOrdinate - stamp[index]) < 1e-9; }); }); if (found) { //console.log('memoized point happens') return found.point; } // else calc new point var point = _.reduce(base, function (absolute, axis, index) { absolute.x += axis.x * coords[index]; absolute.y += axis.y * coords[index]; absolute.z += axis.z * coords[index]; return absolute; }, new Vector); // memoize face.classIIIPoints.push({ stamp: stamp, coords: coords, point: point }); // new vertex promitive point.vertex = new Figure({ type: 'vertex', points: [point.normalize()], negative: !!negativeFace }); figure.$primitives.push(point.vertex); //console.log('+ vertex'); point._enum = ++pointsEnum; return point; })(negativeIndex != -1 ? negativeFace : face, negativeIndex != -1 ? base : facePoints); } }); // remove previous primitives figure.$primitives = $( _.filter(figure.$primitives, function (primitive, index) { // clear points memo delete primitive.classIIIPoints; return index >= prevPrimitivesLength || primitive.type == 'vertex'; // save PPT points only }) ); // figure points figure.$points = $( _.chain(figure.$primitives).pluck('$points').invoke('get').flatten().uniq().value() ); }(); return this; // any helpers function positive(v) { return v > 1e-9 } function negative(v) { return v < -1e-9 } function zero(v) { return Math.abs(v) < 1e-9 } function sum(a, b) { return a + b } function roundS(p) { return _.map(p, function (c) { return Math.round(c * S) }) } }; /** * Lines length equalizer * @static * @return undefined */ Figure.equalizeLineGroups = function (lineGroups, diffPrecision, stepLimit) { console.time('Lengths equalizer'); diffPrecision = diffPrecision || 1e-12; stepLimit = stepLimit || 300; var usedPoints = _.chain(lineGroups).flatten().pluck('$points').invoke('get').flatten().uniq().value(); var step = 0; do { var delta = 0; // prepare _.each(lineGroups, function (lines, group) { _.each(lines, function (line) { line.__dirs = [ Vector.subtract(line.$points[0], line.$points[1]), Vector.subtract(line.$points[1], line.$points[0]) ]; line.length = line.__dirs[0].length(); }); }); // change _.each(lineGroups, function (lines, group) { var lengths = _.pluck(lines, 'length'), diff = _.max(lengths) - _.min(lengths); if (diff < diffPrecision) return; delta = Math.max(delta, diff); var avgLength = _.reduce(lengths, function (a, l) { return a + l }, 0) / lengths.length; // try to move points _.each(lines, function (line) { var q = (avgLength - line.length) / line.length / 4; _.each(line.$points, function (point, i) { point.add(Vector.scale(line.__dirs[i], q)); }); }); }); // normalize _.each(usedPoints, function (point) { point.normalize(); }); } while (delta && ++step < stepLimit); // clean _.each(lineGroups, function (lines, group) { _.each(lines, function (line) { delete line.__dirs; }); }); console.log('Lengths equalizer: lines reduced by', step, 'steps, final delta', delta); console.timeEnd('Lengths equalizer'); } // private helpers function findPoint(a1, a2, b1, b2, c1, c2, control, step) { var planes = _.map([[a1, a2], [b1, b2], [c1, c2]], function (pair) { var normal = Vector.crossProduct(pair[0], pair[1]).normalize(); return new Plane(normal, 0); }); var ABC = []; for (var i = 0, j = 2; i < 3; j = i, i++) { var vars = $.map(Solutions.twoPlanesAndSphere(planes[i], planes[j]), function (v) { return Vector.dotProduct(v, control) > 0 ? v : null; }); if (vars.length != 1) console.log('super bug'); ABC.push(vars[0]); } // todo: calc triangle's center point optionally (Euler set) // 1) in-center +normalize //var point = incenter.apply(this, ABC).normalize(); // 2) in-center3d var point = incenter3d(planes[0], planes[1], planes[2], control); // 3) centeroid + normalize // V6 {vertex: 11, line: 10, face: 12} //var point = ABC[0].add(ABC[1]).add(ABC[2]).scale(1/3).normalize(); // 4) out-center3d // var pl = []; // for (var i = 0, j = 2; i < 3; j = i++) { // var ACmid = Vector.add(ABC[i], ABC[j]).scale(1/2); // var ACnorm = Vector.subtract(ABC[i], ABC[j]).normalize(); // pl.push( new Plane(ACnorm, ACmid).normalize() ); // } // // var solpp = []; // for (var i = 0, j = 2; i < 3; j = i++) { // var vars = $.map(Solutions.twoPlanesAndSphere(pl[i], pl[j]), function(v) { // return Vector.dotProduct(v, control) > 0 ? v : null; // }); // if (vars.length != 1) // console.log('super bug'); // solpp.push( vars[0] ); // } //var point = solpp[0]; // equals distances assertion //var testDist = _.map(planes, function(pl) { return pl.result(point) }); //console.log( testDist, _.max(testDist) - _.min(testDist) ); point._enum = __pointsEnum++; var key = [a1._enum, a2._enum, step].join(); __points[key] = point; //console.log(key) return point; } function edgePoint(A, B, i, N, key) { key = key || ( A._enum < B._enum ? [A._enum, B._enum, i].join() : [B._enum, A._enum, N - i].join() ); if (i * 2 > N) return edgePoint(B, A, N - i, N, key); if (__points[key]) return __points[key]; var cos = A.cosWith(B); var Y = Vector.subtract(B, A.clone().scale(cos)).normalize(); var angle = Math.acos(cos) * i / N; var point = Y.scale(Math.sin(angle)).add(A.clone().scale(Math.cos(angle))); point._enum = __pointsEnum++; point.triSide = true; __points[key] = point; //console.log(key) return point; } function addFace(A, B, C, sideDistances, triIndex) { __faces.push(new Figure({ type: 'face', points: [A, B, C] })); _.each([[B, C], [C, A], [A, B]], function (pair, i) { var key = _.pluck(pair, '_enum').sort().join(); //console.log(key); __lines[key] = __lines[key] || new Figure({ type: 'line', points: pair, sideDistance: sideDistances[i], sideIndex: i, triIndex: triIndex }); }); } // plain incenter function incenter(A, B, C) { var AB = Vector.subtract(B, A); var AC = Vector.subtract(C, A); var BC = Vector.subtract(C, B); var Ab = AB.clone().normalize().add(AC.clone().normalize()); var angle = AB.angleWith(AC); var l = [AB.length(), AC.length(), BC.length()]; var p = (l[0] + l[1] + l[2]) / 2 var S = Math.sqrt(p * (p - l[0]) * (p - l[1]) * (p - l[2])); var r = S / p; var incenter = Ab.scale( (r / Math.sin(angle / 2)) / Ab.length() ).add(A); // assertion var a = Vector.distance(B, C), b = Vector.distance(A, C), c = Vector.distance(A, B); _.each([[A, B, C], [B, C, A], [C, A, B]], function (test) { var v1 = Vector.subtract(test[0], test[1]); var v2 = Vector.subtract(test[2], test[1]); var bisect = v1.clone().normalize().add(v2.clone().normalize()); var angle = v1.angleWith(v2); var a1 = v1.angleWith(bisect); var a2 = v2.angleWith(bisect); if (Math.abs(a1 + a2 - angle) > 1e-13) console.warn('a1 + a2 != angle'); if (Math.abs(a1 - a2) > 1e-13) console.warn('a1 != a2'); }); return incenter; } // spherically incenter function incenter3d(p1, p2, p3, control) { var bisect1 = new Plane(p1.A - p2.A, p1.B - p2.B, p1.C - p2.C, p1.D - p2.D); var bisect2 = new Plane(p3.A - p2.A, p3.B - p2.B, p3.C - p2.C, p3.D - p2.D); var vars = $.map(Solutions.twoPlanesAndSphere(bisect1, bisect2), function (v) { return Vector.dotProduct(v, control) > 0 ? v : null; }); if (vars.length != 1) console.error('incenter3d bug'); return vars[0]; } }();</script> <script type="text/javascript">Figure.prototype.clientDownload = function () { var figureUnifier = document.location.href.split('#').pop() || ""; var figureName = figureUnifier.replace(/[^\w\.]/g, '_'); var obj = { points: [], faces: [], add: function (what, entity) { what += 's'; if (!entity.index) { this[what].push(entity); entity.index = this[what].length; } return entity.index; }, output: [] }, R = parseFloat(window.form.state.radius), lines = _.unique(_.flatten( _.map(figure.subs('face'), function (face) { return face.bindedLines || face.subs('line').get(); }) )), ribs = _.compact(_.map(lines, function (line) { return line.removed ? null : { faces: line.product.model(true), unifier: line.product.unify().replace(/\s/g, '_') + ' ' + line.index } })); $.each(ribs, function (r, rib) { obj.output.push('g ' + figureName + ' ' + rib.unifier); var faces = $.map(rib.faces, function (face) { var points = $.map(face, function (vect) { if (!vect.index) { vect.scale(R); obj.output.push('v ' + vect.x + ' ' + vect.y + ' ' + vect.z); } return obj.add('point', vect); }); obj.output.push('f ' + points.join(' ')); return obj.add('face', points); }); obj.output.push('surf 0.0 1.0 0.0 1.0 ' + faces.join(' ')); obj.output.push('end'); }); // with header obj = [ '#', '# http://acidome.ru/lab/calc/#' + figureUnifier, '#', '# (c) ' + (new Date).getFullYear() + ' acidome.ru/lab/calc', '# Under CC-BY-SA license', '#', '' ].concat(obj.output).join('\r\n'); // output var form = $('<form>').attr({ action: 'fileback.php?filename=' + figureName + '.obj', method: 'POST'/*, target: '_blank'*/ }) .appendTo('body').hide(); $('<textarea name="content">').val(obj) .appendTo(form); form.submit(); //$.post('fileback.php?filename=' + figureName, { content: obj }); };</script> <!-- calc ui --> <script type="text/javascript">/** * Helper for usage url's #fragment as source of params. * * @license Legalize Cannabis License * @author popitch ya ru */ function Stringifier(options) { this.options = options = $.extend(true, { // format: string, // mapping: hashmap }, options); var format = (options.format instanceof Array) ? options.format.join('') : options.format; this._compile(format); // Backbone.Events _.extend(this, Backbone.Events); } (function (root, _, $, undefined) { Stringifier.prototype = { fromString: function (string) { var matches = this.fullRegexp.exec(string); if (!matches) return {}; var params = {}; var options = this.options, i = 1; $.each(this.compiled, function (j, chunk) { if (typeof chunk == 'string') return; var mapper = options.mapping[chunk.name]; if (mapper) value = mapper.value.apply(params, matches.slice(i, i + chunk.argc + 1)); else value = matches[i]; i += chunk.argc + 1; if (typeof value == 'object') params = $.extend(true, params, value); else params[chunk.name] = value; }); // fire event var moreArgs = [].slice.call(arguments, 1); this.trigger.apply(this, ['params', params].concat(moreArgs)); return params; }, fromParams: function (params) { var options = this.options; var string = _.map(this.compiled, function (chunk) { if (typeof chunk == 'string') return chunk; var mapper = options.mapping[chunk.name]; return mapper ? mapper.string.call(params, params[chunk.name]) : params[chunk.name] || ''; }).join(''); // fire event var moreArgs = [].slice.call(arguments, 1); this.trigger.apply(this, ['string', string].concat(moreArgs)); return string; }, _compile: function (formatString) { // reg exp helpers function rescape(str) { return str.replace(/[\\\/\.\-+*?^$|{}\[\]]/g, '\\$&'); } var reGroups = /\([^?][^\)]*\)/g; var compiled = this.compiled = [], pose = 1; // make chain formatString.replace(/([^<]+)|<([\w.]+):([^>]+)>/g, function (frag, simple, name, find) { if (simple) { compiled.push(simple); return; } var argc = find.split(reGroups).length - 1; compiled.push({ name: name, find: find, produce: function (argv) { var i = 0; return find.replace(reGroups, function () { return argv[i++]; }); }, argc: argc, pose: pose + 1 }); pose += argc + 1; } ); // make full string regexp this.fullRegexp = new RegExp('^' + $.map(this.compiled, function (frag) { return (typeof frag == 'string') ? rescape(frag) : '(' + frag.find + ')'; }).join('') + '$'); return compiled; } }; })(this, _, jQuery); </script> <script type="text/javascript">// exports __ = i18n; // simple text translater function i18n(text, lang, translate) { lang = lang ? lang.toLowerCase() : i18n.lang(); text = String(text); // translate, if present translate = translate || i18n.translate[lang]; if (translate) { var namespace = text.replace(/^(\w+:)\S.*$|^.*$/, '$1'); if (namespace) { text = text.replace(/^\w+:(\S.*)$/, '$1'); return _.has(translate, namespace) && _.has(translate[namespace], text) ? translate[namespace][text] : i18n(text, lang, translate[namespace]); } return _.has(translate, text) ? translate[text] : text; } return text; } _.extend(i18n, { BASE_LANG: 'en' }); _.extend(i18n, { lang: (function () { var lang = ko.observable(null); // try to get lang from cookie var cookieLang = (document.cookie.split('i18n')[1] || '=;').replace(/^=([^;]*);.*$/, '$1'); if (cookieLang) { lang(cookieLang); } // listen observable, set cookie lang.subscribe(function () { document.cookie = 'i18n=' + lang(); }); return lang; }()), langList: [], translate: {}, addLang: function (lang, data) { this.translate[lang] = data; this.langList.push(lang); }, isLangKnown: function (lang) { return _.has(this.translate, lang.toLowerCase()); }, langOptions: function () { return _.chain(this.langList) .map(function (lang) { return { id: lang, name: __(':lang', lang) }; }) .sortBy('name') .value(); } }); // ko.binding "text" adapter ko.bindingHandlers.text = (function (textBinding) { return { /*init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { return textBinding.init.apply(this, arguments); },*/ update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { $(element).text( i18n( ko.unwrap(valueAccessor()) ) ); } }; })(ko.bindingHandlers.text); /** Translate extensions */ i18n.addLang('en', { ':lang': 'English', "budget:": { "title:": { "line": "Edges", "face": "Faces", "vertex": "Vertices" } } }); /** Translate extensions */ i18n.addLang('ru', { ':lang': 'Русский', "Carcass": "Каркас", "Schema": "Схема", "Cover": "Кровля", "Base": "План", "Figure options": "Исходная форма", "Level of detail, V": "Частота, V", "Subdivision class": "Класс разбиения", "Subdivision method": "Метод разбиения", "method:": { "Equal Chords": 'Равные хорды', "Equal Arcs": 'Равные дуги', "Mexican": 'Мексиканец' }, "Rotational symmetry": "Осевая симметрия", "Fullerene": "Фуллерен", "fulleren:": { "None": 'Нет', "Inscribed in": 'Вписанный', "Described around": 'Описанный' }, "Part of full sphere": "Часть сферы", "Align the base": "Выравнивать основание", "Product options": "Продукция", "Sphere radius, m": "Радиус сферы, м", "Connection type": "Способ соединения", "Pipe diameter, mm": "Диаметр трубы, мм", "Spinning clockwise": "По-часовой", "else counter": "или против", "Timber size": "Материал ребер", "Width, mm": "Ширина, мм", "Thickness, mm": "Толщина, мм", "Resulting": "В результате имеем", "Height from base, m": "Высота от основания, м", "Base radius, m": "Радиус основания, м", "Sizes (units)": "Размеры", "Faces": "Граней", "Edges": "Ребер", "Vertices": "Вершин", "Beams": "Балки (ребра)", "Total length of beams, m": "Суммарная длина, м", "Total volume of beams, m3": "Объем ребер, м3", "Max. beam length, mm": "Макс. длина ребра, мм", "Angle between faces, °": "Угол смежных граней, °", "Base area, m2": "Площадь основания, м2", "Coverage area, m2": "Площадь покрытия, м2", "Triangles": "Треугольники", "Min. height, mm": "Мин. высота, мм", "Max. side, mm": "Макс. сторона, mm", "mm": "мм", "pcs": "шт.", "buyme:": { "Product offering": "Предложения продукции", "Buy it": "Купить", "Sorry, error happens while we trying to order. Please, try again later.": 'К сожалению, при попытке заказать происходит ошибка. Пожалуйста, попробуйте повторить заказ позже.', "Thank you, the order has been successfully created.": 'Спасибо, заказ успешно создан. Проверьте вашу электронную почту.', "Check your email, if the letter is marked as spam, mark it as not spam.": 'Проверьте почту, если письмо случайно попало в папку "Спам", вытащите его оттуда.', "E-mail is not valid": "Вы ввели неправильный e-mail" }, "share:": { "Share": 'Поделиться', "from acidome.ru": 'от acidome.ru' }, "Donate": 'Помочь проекту', "modified": 'изменен', "budget:": { "title:": { "line": "Ребра", "face": "Грани", "vertex": "Вершины" } }, "clothier:": { "Clothier": "Портной" } }); /** * @thanks https://www.facebook.com/enrique.desanjulian */ i18n.addLang('es', { ':lang': 'Español', "Carcass": "Carcasa", "Schema": "Esquema", "Cover": "Cubierta", "Base": "Base", "Figure options": "Opciones de geometría", "Level of detail, V": "Frecuencia, V", "Subdivision class": "Tipo de subdivisión", "Subdivision method": "Método de subdivisión", "method:": { "Equal Chords": 'Cuerdas iguales', "Equal Arcs": 'Arcos iguales', "Mexican": 'Mexicano' }, "Rotational symmetry": "Simetría rotacional", "Fullerene": "Circunscripción", "fulleren:": { "None": 'Ninguna', "Inscribed in": 'Inscrita dentro', "Described around": 'Descrita alrededor' }, "Part of full sphere": "Porción de la esfera", "Align the base": "Alinear la base", "Product options": "Opciones de Proyecto", "Sphere radius, m": "Radio de la esfera, m", "Connection type": "Tipo de conexión", "Pipe diameter, mm": "Diámetro del tubo, mm", "Spinning clockwise": "Girando en sentido horario", "else counter": "sentido contrario", "Timber size": "Tamaño de las piezas", "Width, mm": "Anchura, mm", "Thickness, mm": "Grosor, mm", "Resulting": "Resultados", "Height from base, m": "Altura desde la base, m", "Base radius, m": "Radio de la base, m", "Sizes (units)": "Tamaños (unidades)", "Faces": "Caras", "Edges": "Aristas", "Vertices": "Vértices", "Beams": "Travesaños", "Total length of beams, m": "Longitud total de los travesaños, m", "Total volume of beams, m3": "Volumen total de los travesaños, m3", "Max. beam length, mm": "Longitud máx. del travesaño, mm", "Angle between faces, °": "Ángulo entre caras, °", "Base area, m2": "Área de la base, m2", "Coverage area, m2": "Área de la cubierta, m2", "Triangles": "Triángulos", "Min. height, mm": "Altura mín., mm", "Max. side, mm": "Longitud máx. del lado, mm", "mm": "mm", "pcs": "piezas" }); /** * @thanks https://www.facebook.com/bezruchko.arkadiy */ i18n.addLang('ua', { ':lang': 'Українська', "Carcass": "Каркас", "Schema": "Схема", "Cover": "Покрівля", "Base": "План", "Figure options": "Вихідна форма", "Level of detail, V": "Частота, V", "Subdivision class": "Клас розбивки", "Subdivision method": "Метод розбивки", "method:": { "Equal Chords": 'Рівні хорди', "Equal Arcs": 'Рівні дуги', "Mexican": 'Мексиканський' }, "Rotational symmetry": "Осьова симетрія", "Fullerene": "Фуллерен", "fulleren:": { "None": 'Немає', "Inscribed in": 'Вписаний', "Described around": 'Описаний' }, "Part of full sphere": "Частина сфери", "Align the base": "Вирівнювати основу", "Product options": "Продукція", "Sphere radius, m": "Радіус сфери, м", "Connection type": "Спосіб з'єднаня", "Pipe diameter, mm": "Діаметр труби, мм", "Spinning clockwise": "За-годинниковою", "else counter": "або проти", "Timber size": "Матеріал ребер", "Width, mm": "Ширина, мм", "Thickness, mm": "Товщина, мм", "Resulting": "В результаті маємо", "Height from base, m": "Висота від основи, м", "Base radius, m": "Радіус основи, м", "Sizes (units)": "Разміри", "Faces": "Граней", "Edges": "Ребер", "Vertices": "Вершин", "Beams": "Балки (ребра)", "Total length of beams, m": "Сумарна довжина, м", "Total volume of beams, m3": "Об'єм ребер, м3", "Max. beam length, mm": "Макс. довжина ребра, мм", "Angle between faces, °": "Кут суміжних граней, °", "Base area, m2": "Площа основи, м2", "Coverage area, m2": "Площа покриття, м2", "Triangles": "Трикутники", "Min. height, mm": "Мін. висота, мм", "Max. side, mm": "Макс. сторона, mm", "mm": "мм", "pcs": "шт." }); /** * @thanks https://www.facebook.com/pascal.belzunce */ i18n.addLang('fr', { ':lang': 'Français', "Carcass": "Squelette", "Schema": "Schéma", "Cover": "Couverture", "Base": "Sol", "Figure options": "Paramètres de la forme", "Level of detail, V": "Fréquence, V", "Subdivision class": "Classe de subdivision", "Subdivision method": "Méthode de subdivision", "method:": { "Equal Chords": 'Cordes égales', "Equal Arcs": 'Arcs égaux', "Mexican": 'Mexicaine' }, "Rotational symmetry": "Axe de symétrie", "Fullerene": "Fullerène", "fulleren:": { "None": 'Aucune', "Inscribed in": 'Intérieur', "Described around": 'Extérieur' }, "Part of full sphere": "Découpage de la sphère", "Align the base": "Aligner le bas", "Product options": "Caractéristiques du matériel", "Sphere radius, m": "Rayon de la sphère, m", "Connection type": "Type de connecteur", "Pipe diameter, mm": "Diamètre du tube, mm", "Spinning clockwise": "Sens horaire", "else counter": "antihoraire", "Timber size": "Taille des montants", "Width, mm": "Largeur, mm", "Thickness, mm": "Epaisseur, mm", "Resulting": "Résultats", "Height from base, m": "Hauteur au sol, m", "Base radius, m": "Rayon au sol, m", "Sizes (units)": "Quantités", "Faces": "Faces", "Edges": "Montants", "Vertices": "Nœuds", "Beams": "Montants", "Total length of beams, m": "Longueur totale des montants, м", "Total volume of beams, m3": "Volume total des montants, м3", "Max. beam length, mm": "Montant le plus grand, мм", "Angle between faces, °": "Angle entre les faces, °", "Base area, m2": "Surface au sol, м2", "Coverage area, m2": "Surface de la couverture, м2", "Triangles": "Triangles", "Min. height, mm": "Hauteur mini, мм", "Max. side, mm": "Côté maxi, mm", "mm": "mm", "pcs": "pcs", "Donate": 'Donation', "modified": 'modifié', "budget:": { "title:": { "line": "Montants", "face": "Faces", "vertex": "Nœuds" } } }); /** * @thanks https://www.facebook.com/gencho.genchev.50 */ i18n.addLang('bg', { ':lang': 'Български', "Carcass": "Конструкция", "Schema": "Схема", "Cover": "Покрив", "Base": "Основа", "Figure options": "Изходна форма", "Level of detail, V": "Честота V", "Subdivision class": "Делови клас", "Subdivision method": "Метод на делене", "method:": { "Equal Chords": "Равни Хорди", "Equal Arcs": "Равни дъги", "Mexican": "Мексикански" }, "Rotational symmetry": "Осева симетрия", "Fullerene": "Фулерен", "fulleren:": { "None": "Не", "Inscribed in": "Вписан", "Described around": "Описан" }, "Part of full sphere": "Част от сферата", "Align the base": "Изравни на основата", "Product options": "Параметри на купола", "Sphere radius, m": "Радиус на сферата, м", "Connection type": "Тип връзки", "Pipe diameter, mm": "Диаметър на тръбата, мм", "Spinning clockwise": "По часовата стрелка", "else counter": "Обратно на ч.с.", "Timber size": "Материал на ребрата", "Width, mm": "Ширина, мм", "Thickness, mm": "Дебелина, мм", "Resulting": "Резултат", "Height from base, m": "Височина от основата, м", "Base radius, m": "Радиус на основата, м", "Sizes (units)": "Размери (бройки)", "Faces": "Лица", "Edges": "Краища", "Vertices": "Върхове", "Beams": "Греди", "Total length of beams, m": "Обща дължина греди, м", "Total volume of beams, m3": "Обем греди, м3", "Max. beam length, mm": "Максимална дължина греда, мм", "Angle between faces, °": "Ъгъл между съседни повърхности", "Base area, m2": "Площ на основата, м2", "Coverage area, m2": "Покривна площ, м2", "Triangles": "Триъгълници", "Min. height, mm": "Мин. Височина, мм", "Max. side, mm": "Минимална страна, мм", "mm": "мм", "pcs": "бр." }); i18n.addLang('pl', { ':lang': 'Polski', "Carcass": "Konstrukcja", "Schema": "Schemat", "Cover": "Pokrycie", "Base": "Podstawa", "Figure options": "Opcje kształtu", "Level of detail, V": "Stopień aproksymacji, V", "Subdivision class": "Klasa podziału", "Subdivision method": "Metoda podziału", "method:": { "Equal Chords": 'Równych cięciw', "Equal Arcs": 'Równych łuków', "Mexican": 'Meksykańska' }, "Rotational symmetry": "Оś symetrii", "Fullerene": "Wzór fulerenu", "fulleren:": { "None": 'Nie', "Inscribed in": 'Wpisany', "Described around": 'Opisany' }, "Part of full sphere": "Część sfery", "Align the base": "Wyrównaj do podstawy", "Product options": "Opcje produktu", "Sphere radius, m": "Promień sfery, m", "Connection type": "Typ łączenia", "Pipe diameter, mm": "Średnica rury, mm", "Spinning clockwise": "Obrót w prawo ", "else counter": "lub w lewo", "Timber size": "Rozmiar belki", "Width, mm": "Szerokość, mm", "Thickness, mm": "Grubość, mm", "Resulting": "W wyniku otrzymujemy", "Height from base, m": "Wysokość od podstawy, m", "Base radius, m": "Promień podstawy, m", "Sizes (units)": "Elementy", "Faces": "Ścianki", "Edges": "Krawędzie", "Vertices": "Wierzchołki", "Beams": "Belki", "Total length of beams, m": "Całkowita długość belek, m", "Total volume of beams, m3": "Całkowita objętość belek, m3", "Max. beam length, mm": "Maksymalna długość belki, mm", "Angle between faces, °": "Kąt pomiędzy ściankami, °", "Base area, m2": "Powierzchnia podstawy, m2", "Coverage area, m2": "Powierzchnia pokrycia, m2", "Triangles": "Тrójkąty", "Min. height, mm": "Maksymalna wysokość, mm", "Max. side, mm": "Maksymalna długość boku, mm", "mm": "mm", "pcs": "szt.", "budget:": { "title:": { "line": "Belki", "face": "Ścianki", "vertex": "Wierzchołki" } } }); </script> <script type="text/javascript">var viewer = (function () { var zoom = {current: 3, progress: 1, target: 4}, ZOOM_RANGE = [0, 16], ZOOM_LATENCY = 400, // ms NEAR = 1, FAR = 5; var viewer = _.clone(Backbone.Events); var $dom = viewer.$dom = $('.geodesic'), $canvas = $dom.find('canvas.preview'), $form = $dom.find('form.options'); // resize spy !function () { $(window).resize(_.debounce(function () { var w = $(window).width(), h = $(window).height(), fb = $form.outerHeight(true) + $form.offset().top; if (w != canvasW || h != canvasH) { canvasH = Math.max(fb, h * (IS_IFRAME ? 1 : 1.2)); canvasW = w; viewer.trigger('render'); } }, 300)); // init $(function () { $dom.show(); $(window).resize(); }); }(); // mouse spy !function () { var touchStart, touchCurrent, overObject, hasRotate; $canvas .bind('mousedown touchstart', function (e) { if (!commonGroup) return; touchStart = touchScene(e); }) .bind('mouseup touchend', function (e) { touchStart = null; _.defer(function () { hasRotate = false; }); }) .bind('mousemove touchmove', function (e) { touchCurrent = touchScene(e); if (touchStart) { // rotate startTouch.matrix, from startTouch.sphereCross to touch.sphereCross rotateSphere(touchStart, touchCurrent); hasRotate = true; } return false; }) .click(function (e) { if (!hasRotate) { trigger('click', e); } }); // mouse wheel / zooming $canvas[0].addEventListener('DOMMouseScroll', handleScroll, false); $canvas[0].addEventListener('mousewheel', handleScroll, false); function handleScroll(e) { var evt = e || window.event; var delta = (evt.detail < 0 || evt.wheelDelta > 0) ? 1 : -1; if (delta) { var before = touchScene(e); if (!before.sphereTouch) return; zoom.target = Math.min(Math.max(zoom.target + delta, ZOOM_RANGE[0]), ZOOM_RANGE[1]); if (zoom.progress == 1) { zoom = _.extend(zoom, { progress: 0, start: zoom.current, startTouch: before, startAt: new Date, startEvent: e }); } } return e.preventDefault() && false; } // auto zoom progresser zoomProgress(); function zoomProgress() { var now = (new Date).getTime(), timeout = 100, current = zoom.current; if (zoom.startAt) { zoom.progress = Math.min(now - zoom.startAt.getTime(), ZOOM_LATENCY) / ZOOM_LATENCY; zoom.current = zoom.start + (zoom.target - zoom.start) * zoom.progress; if (zoom.current != current) { viewer.trigger('render'); var touch = touchScene(zoom.startEvent); rotateSphere(zoom.startTouch, touch); timeout = 0; } } _.delay(zoomProgress, timeout); } function rotateSphere(touch1, touch2) { var axis = touch1.sphereCross.clone().cross(touch2.sphereCross); var angle = touch1.sphereCross.angleTo(touch2.sphereCross); if (Math.abs(angle) < 1e-4 || Math.abs(axis.length()) < 1e-9) return; commonGroup.matrix = (new THREE.Matrix4).rotateByAxis(axis, angle) .multiply(touch1.matrix); viewer.trigger('render'); } function touchScene(e) { var raycaster = getRaycaster(e); // fix Threejs: prepare mesh's vertices position to world coordinates _.each(scene.getDescendants(), function (mesh) { if (mesh instanceof THREE.Mesh) { mesh._geometryVertices = mesh.geometry.vertices; mesh.geometry.vertices = mesh._geometryWorldVertices = mesh._geometryWorldVertices || _.map(mesh.geometry.vertices, function (v) { return v.clone().add(mesh.position); }); } }); var intersects = raycaster.intersectObjects(scene.children, true); // from fix _.each(scene.getDescendants(), function (mesh) { if (mesh instanceof THREE.Mesh) { mesh.geometry.vertices = mesh._geometryVertices; } }); // cross with shere var R = SCALE * form.state.radius, p = raycaster.ray.origin, v = raycaster.ray.direction, a = v.dot(v), b = v.dot(p) * 2, c = p.dot(p) - R * R, D = b * b - 4 * a * c, q = -b / 2 / a; if (D > 0) { D = Math.sqrt(D) / 2 / a; q = (c > 0) ? q - D : q + D; } var sphereCross = v.clone().multiplyScalar(q).add(p); if (_.isEmpty(intersects)) { trigger('mouseout', e); overObject = null; } else { if (overObject === intersects[0].object) { trigger('mousemove', e); } else { trigger('mouseout', e); overObject = intersects[0].object; trigger('mousein', e); } } return { raycaster: raycaster, intersect: intersects[0], product: intersects[0] && intersects[0].object._product, sphereCross: sphereCross, sphereTouch: D > 0, matrix: commonGroup && commonGroup.matrix }; } function trigger(eventName, e) { if (overObject && overObject.trigger && overObject._events[eventName]) { // handler present overObject.trigger(eventName, e); viewer.trigger('render'); } } var projectionMatrixInverse = new THREE.Matrix4; function getRaycaster(e) { // ray // FF fix: used page's [X,Y] with canvas position [0,0] var oe = e.originalEvent || e, x = (e.offsetX || e.pageX) || (oe.touches && oe.touches[0] && oe.touches[0].pageX) || 0, y = (e.offsetY || e.pageY) || (oe.touches && oe.touches[0] && oe.touches[0].pageY) || 0, v = new THREE.Vector3( (x / canvasW) * 2 - 1, -(y / canvasH) * 2 + 1, 0.5 ); //v = projector.unprojectVector(v, camera); projectionMatrixInverse.getInverse(camera.projectionMatrix); v.applyProjection(projectionMatrixInverse).applyMatrix4(camera.matrixWorld); var p = camera.position; v.sub(p).normalize(); return new THREE.Raycaster(p, v); } }(); // view mode switcher var activeMode, currentFigure; !function () { var $modeList = $('.mode', $dom), $activeMode = $modeList.filter('.active'); activeMode = $activeMode.data('mode'); // track initial mode Tracker.push('view', activeMode); $modeList.click(function () { var $mode = $(this); if (this != $activeMode[0]) { $activeMode.removeClass('active'); $activeMode = $mode; $activeMode.addClass('active'); activeMode = $activeMode.data('mode'); // track mode switched Tracker.push('view', activeMode); updateCameraPosition(); viewer.trigger('render', currentFigure); } }); }(); // stat switcher !function () { var active; $('.stat .toggle', $dom).click(function () { active = !active; $('.stat', $dom).add(this).toggleClass('active', active); }); }(); // adapt to tree.js var canvasW, canvasH, camera, scene, light, renderer, commonGroup; // const var SCALE = 1000; // projection helper var projector = new THREE.Projector(); function updateCameraPosition() { var pos = (ZOOM_RANGE[1] - zoom.current) / ZOOM_RANGE[1], // [0..1] R = form.state.radius; // todo: zoom by logarithmic scale //pos = Math.pow(2, pos * 10) / 1025; pos = NEAR + (FAR - NEAR) * pos; // (NEAR..FAR] pos = new THREE.Vector3( 0, 0, // man's eyes average height R * pos //form.state.radius * 5 ); pos[AXIS] = (figure ? _.min(_.pluck(figure.$points, AXIS)) : 0) * R + // dome base 1.6; // avg eyes height var part = viewer.drivers[activeMode].particle; var dist = (pos.length() + (part * 3 - 1) * R) * SCALE; camera.far = dist; camera.position.copy(pos.multiplyScalar(SCALE)); camera.updateMatrixWorld(); // light distance light.distance = dist; } // renderer init !function () { canvasW = $canvas.innerWidth(); canvasH = $canvas.innerHeight(); window.camera = // debug camera = new THREE.PerspectiveCamera(30, canvasW / canvasH, 10, 1e+5); scene = new THREE.Scene(); window.renderer = // debug renderer = new THREE.CanvasRenderer({canvas: $canvas[0], antialias: true}); window.light = // debug light = new THREE.PointLight(0xffffff, 1.5); scene.add(light); }(); // renderer viewer.on('render', function (figure) { var startAt = new Date; camera.aspect = canvasW / canvasH; renderer.setSize(canvasW, canvasH); camera.updateProjectionMatrix(); //console.log(canvasW, canvasH);; // set camera distance position updateCameraPosition(); // actualize light position light.position.copy(camera.position); // update figure, if required if (figure) { // renew common group object, with saving matrix rotation if (commonGroup) { var prevMatrix = commonGroup.matrix.clone(); scene.remove(commonGroup); } window.commonGroup = // debug commonGroup = new THREE.Object3D(); commonGroup.matrixAutoUpdate = false; commonGroup.matrix.copy(prevMatrix || commonGroup.matrix); var mel = commonGroup.matrix.elements; commonGroup.matrix.multiplyScalar(SCALE * form.state.radius / Math.sqrt(mel[0] * mel[0] + mel[4] * mel[4] + mel[8] * mel[8])); //commonGroup.matrix.getColumnX().length()); scene.add(commonGroup); // refill common group _.each(figure.$primitives, function (f) { var showRemoved = viewer.drivers[activeMode].showRemoved; if (!showRemoved && f.removed) return; var color = productPalette[f.type][f.order].integer; var object = viewer.drivers[activeMode].present(f, color); var objects = _.compact(object instanceof Array ? object : [object]); _.each(objects, function (object) { if (object.geometry) { // vertices relatively center averageVertex3(object.position, object.geometry.vertices); _.each(object.geometry.vertices, function (v) { v.sub(object.position); }); } // back link object.sourceFigure = f; commonGroup.add(object); }); }); currentFigure = figure; } // update matrixWorld scene.updateMatrixWorld(true); camera.lookAt(scene.position); renderer.render(scene, camera); }); return viewer; function averageVertex3(target, vertices) { target.x = target.y = target.z = 0; _.reduce(vertices, function (center, v) { return center.add(v); }, target) .multiplyScalar(1 / vertices.length); } })(); </script> <script type="text/javascript">// any methods how figure may be present viewer.drivers = (function () { var geometry; // new vertices registration helper function pushVertex(v) { var index = _.indexOf(_.pluck(geometry.vertices, 'source'), v); if (-1 != index) return index; var vertice = new THREE.Vector3().copy(v); //vertice.w = 1; vertice.source = v; geometry.vertices.push(vertice); return geometry.vertices.length - 1; } function pushFace(face, appendRevertedVersion) { if (appendRevertedVersion) { pushFace(_.reduceRight(face, function (memo, p) { return memo.concat([p]) }, [])); } face = _.map(face, pushVertex); if (face.length == 3) { geometry.faces.push(new THREE.Face3(face[0], face[1], face[2])); } else if (face.length >= 4) { for (var i = 1, l = face.length; i < l - 2; i += 2) { var face4 = new THREE.Face4(face[0], face[i + 0], face[i + 1], face[i + 2]); geometry.faces.push(face4); if (face.length > 4) { face4._source = face; (face._collect = face._collect || []).push(face4); } } if (face.length % 2) { var face3 = new THREE.Face3(face[0], face[i + 0], face[i + 1]); geometry.faces.push(face3); if (face.length > 4) { face3._source = face; (face._collect = face._collect || []).push(face3); } } } else { console.error('wrong face', face); } } function averageVertex3(target, vertices) { target.x = target.y = target.z = 0; _.reduce(vertices, function (center, v) { return center.add(v); }, target) .multiplyScalar(1 / vertices.length); } function makeParticleLabelProgram(options) { var font = options.fontSize + 'px ' + options.fontFamily; return function (ctx) { ctx.transform(1, 0, 0, -1, 0, 0); if (options.bgRadius) { ctx.beginPath(); var gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, options.bgRadius); gradient.addColorStop(0, 'rgba(255, 255, 255, 1)'); gradient.addColorStop(1, 'rgba(255, 255, 255, 0)'); ctx.arc(0, 0, options.bgRadius, 0, Math.PI * 2); ctx.closePath(); ctx.fillStyle = gradient; ctx.fill(); } ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; ctx.fillStyle = 'black'; ctx.font = font; ctx.fillText(options.text, 0, 0); }; } return { "carcass": { particle: 1, present: function (figure, color) { // lines only if (figure.type != 'line') return null; geometry = new THREE.Geometry(); // get product model var model = figure.product.model(true); var material = new THREE.MeshLambertMaterial({ color: color, shading: THREE.FlatShading, overdraw: true, wireframe: false, opacity: 0.95 }); _.each(model, function (face) { pushFace(face, false); }); //geometry.normalsNeedUpdate = true; geometry.computeFaceNormals(); // restore normals of face4 like face3 _.each(geometry.faces, function (face) { var sface = face._source; if (sface) { var normal = _.filter(sface._collect, function (face4) { return face4.normal.length() > 0; })[0].normal; _.each(sface._collect, function (face4) { face4.normal.copy(normal); }); } }); return new THREE.Mesh(geometry, material); } }, "cover": { showRemoved: true, particle: 1, present: function (figure, color) { if (figure.type != 'face') return null; geometry = new THREE.Geometry(); // get product model var model = figure.product.model(true); _.each(model, function (face) { pushFace(face, true); }); //geometry.normalsNeedUpdate = true; geometry.computeFaceNormals(); // restore normals of face4 like face3 _.each(geometry.faces, function (face) { var sface = face._source; if (sface) { var normal = _.filter(sface._collect, function (face4) { return face4.normal.length() > 0; })[0].normal; _.each(sface._collect, function (face4) { face4.normal.copy(normal); }); } }); var material = new THREE.MeshLambertMaterial({ color: color, shading: THREE.FlatShading, overdraw: true, wireframe: false }), contourMaterial = new THREE.LineDashedMaterial({ color: 0, linewidth: 5, dashSize: 8, gapSize: 5, vertexColors: THREE.VertexColors }), contourGeometry = new THREE.Geometry(); _.each(geometry.vertices, function (vertice) { contourGeometry.vertices.push( vertice.clone().multiplyScalar(1000 * form.state.radius) ); }); contourGeometry.vertices.push( geometry.vertices[0].clone().multiplyScalar(1000 * form.state.radius) ); var contour = new THREE.Line(contourGeometry, contourMaterial); updateOpacity(); var object = new THREE.Mesh(geometry, material), over = false; _.extend(object, Backbone.Events) .on('mousein', function (e) { over = true; updateOpacity(); }) .on('mouseout', function (e) { over = false; updateOpacity(); }) .on('click', function (e) { if (figure.removed) { var restored = _.pluck(figure.restore(), 'removeIndex'); form.removedList.removeAll(restored); } else { var removed = _.pluck(figure.remove(), 'removeIndex'); form.removedList.push.apply(form.removedList, removed); } updateOpacity(); }); return [object, contour]; function updateOpacity() { material.opacity = figure.removed ? .03 : (over ? 1 : .97); contourMaterial.opacity = over ? .5 : 0; } } }, "schema": { particle: 1 / 3, present: function (figure, color) { geometry = new THREE.Geometry(); _.each(figure.$points, pushVertex); var object = new THREE.Object3D(); // if (this[figure.type]) { // var adv = this[figure.type](figure, color); // if (adv) object.add(adv); // } // product index var fontSize = (form.state.radius / form.state.detail * 100) * (form.state.subdivClass == 'I' ? 1 : 1.33), particle = new THREE.Particle(new THREE.ParticleCanvasMaterial({ color: color, program: makeParticleLabelProgram({ fontSize: fontSize, fontFamily: 'Optimer, verdana', bgRadius: fontSize, text: figure.index }) })); if (figure.type == 'vertex') { averageVertex3(particle.position, figure.$points); particle.position.multiplyScalar(1 + 0.1 / figure.product.R); // 1cm to outside } else { var points = _.unique(_.flatten(figure.product.model(true))); if (figure.type == 'line' && /^GoodKarma|Semicone$/.test(form.state.connType)) { //points = points.concat() points = points.concat(figure.bindedFace.$points.get()); } averageVertex3(particle.position, points); particle.position.normalize(); } particle.position.multiplyScalar(1.001); //particle.updateMatrix(); object.add(particle); return [viewer.drivers["carcass"].present(figure, color), object]; } }, "base": { particle: 1 / 3, present: function () { return function (figure, color) { if (figure.type != 'line' || figure.origin.removed || (figure.bindedFace && figure.bindedFace.removed)) return; var isActive = (_.where(figure.origin.$super.face, {removed: false}).length == 1), // basically isBase = isActive; var lineObject = viewer.drivers["carcass"].present(figure, color), objects = [lineObject]; begin(objects); if (isBase) { baseLines.push(figure); } lineObject.material.opacity = isActive ? .5 : .027; _.extend(lineObject, Backbone.Events) .on('mousein', function (e) { this.material.opacity = .263; }) .on('mouseout', function (e) { this.material.opacity = isActive ? .5 : .027; }) .on('click', function (e) { // toggle activity isActive = !isActive; if (isActive) { activeLines.push(figure); } else { activeLines = _.difference(activeLines, [figure]); } if (isBase) { recalcBaseMetricContainer(); } _.each(figure.origin.$sub.vertex, updateVertexMetric); this.material.opacity = isActive ? .5 : .027; }); _.each(figure.origin.$sub.vertex, function (vertex) { if (once(vertex)) { vertex.metricObjects = vertexMetric(vertex); objects = objects.concat(vertex.metricObjects); } updateVertexMetric(vertex); }); if (isActive) { activeLines.push(figure) } return objects; }; var inited, axisDown, R, vertexRegister, activeLines, baseLines, baseVertexes, baseMetricContainer; function begin(objects) { if (inited) return; vertexRegister = []; activeLines = []; baseLines = []; // release mem _.each(figure.subs('vertex'), function (vertex) { delete vertex.metricObjects; }); // init base metric container baseMetricContainer = new THREE.Object3D(); objects.push(baseMetricContainer); R = form.state.radius; // get down position by axis uses global figure object axisDown = _.chain(figure.subs('vertex')).where({removed: false}).pluck('$points').pluck('0').pluck(AXIS).min().value(); // destroy inited state after driver been fully applied by current runtime _.defer(end); inited = true; } function end() { // order base vertexes collection as polygon var lines = _.tail(baseLines, 0), line = lines[0], vertex = line.$sub.vertex[0]; baseVertexes = []; while (line) { baseVertexes.push(vertex); lines = _.difference(lines, [line]); line = _.find(lines, function (l) { return _.contains(l.$sub.vertex, vertex); }); vertex = line && line.$sub.vertex[line.$sub.vertex[0] === vertex ? 1 : 0]; } _.isEmpty(lines) || console.error('Achtung happens'); recalcBaseMetricContainer(); viewer.trigger('render'); inited = false; 2 } function once(entity) { if (!_.contains(vertexRegister, entity)) { vertexRegister.push(entity); return true; } } function recalcBaseMetricContainer() { var cont = baseMetricContainer; // clear for (var i = cont.children.length - 1; i >= 0; i--) cont.remove(cont.children[i]); // fill var vertexes = _.intersection(baseVertexes, _.chain(activeLines).pluck('origin').unique().pluck('$sub').pluck('vertex').invoke('get').flatten().value()); if (vertexes.length > 1) { var lineColor = 0x808080, lineMaterial = new THREE.LineBasicMaterial({ color: lineColor, opacity: 1, linewidth: 1, vertexColors: THREE.VertexColors }), prevVertex = _.last(vertexes); _.each(vertexes, function (vertex) { var lineGeometry = new THREE.Geometry, vertices = _.map([prevVertex, vertex], function (vertex) { var point = vertex.$points[0], vertice = new THREE.Vector3(point.x, point.y, point.z); vertice[AXIS] = axisDown; lineGeometry.vertices.push(vertice.multiplyScalar(1000 * R)); return vertice; }); baseMetricContainer.add(new THREE.Line(lineGeometry, lineMaterial)); // line length, mm var lineParticle = new THREE.Particle(new THREE.ParticleCanvasMaterial({ color: 'black', program: makeParticleLabelProgram({ fontSize: (24 * R), fontFamily: 'monospace, Optimer, verdana', text: Math.round(vertices[0].clone().sub(vertices[1]).length()) }) })); lineParticle.position.addVectors(vertices[0], vertices[1]).multiplyScalar(.5 / 1000 / R); // todo: refactor for no coords magic baseMetricContainer.add(lineParticle); prevVertex = vertex; }); } // metric polygon members var members = _.intersection() } function updateVertexMetric(vertex) { _.each(vertex.metricObjects, function (object) { object.visible = _.any(vertex.$super.line, function (line) { return _.contains(activeLines, line); }); }); } function vertexMetric(vertex) { var point = vertex.$points[0], baseDelta = Math.abs(point[AXIS] - axisDown) * R; // radius var vertexColor = productPalette[vertex.type][vertex.order].integer, radiusGeometry = new THREE.Geometry, radiusVertice = new THREE.Vector3(point.x, point.y, point.z), radiusCenter = new THREE.Vector3, vertexMaterial = new THREE.LineBasicMaterial({ color: vertexColor, opacity: 1, linewidth: 1, vertexColors: THREE.VertexColors }); radiusCenter[AXIS] = axisDown; radiusVertice[AXIS] = axisDown; radiusGeometry.vertices.push(radiusCenter.multiplyScalar(1000 * R)); radiusGeometry.vertices.push(radiusVertice.multiplyScalar(1000 * R)); var radiusLine = new THREE.Line(radiusGeometry, vertexMaterial); // radius length, mm var radiusParticle = new THREE.Particle(new THREE.ParticleCanvasMaterial({ color: 'black', program: makeParticleLabelProgram({ fontSize: (24 * R), fontFamily: 'monospace, Optimer, verdana', text: Math.round(radiusVertice.clone().sub(radiusCenter).length()) }) })); radiusParticle.position.addVectors(radiusCenter, radiusVertice).multiplyScalar(.5 / 1000 / R); // todo: refactor for no coords magic if (baseDelta > 1e-6) { var deltaBase = new THREE.Vector3(point.x, point.y, point.z), deltaVertice = deltaBase.clone(), deltaGeometry = new THREE.Geometry; deltaBase[AXIS] = axisDown; deltaGeometry.vertices.push(deltaBase.multiplyScalar(1000 * R)); deltaGeometry.vertices.push(deltaVertice.multiplyScalar(1000 * R)); var deltaLine = new THREE.Line(deltaGeometry, vertexMaterial); // delta, mm var deltaParticle = new THREE.Particle(new THREE.ParticleCanvasMaterial({ color: 'black', program: makeParticleLabelProgram({ fontSize: (24 * R), fontFamily: 'monospace, Optimer, verdana', text: Math.round(deltaBase.clone().sub(deltaVertice).length()) }) })); deltaParticle.position.subVectors(deltaVertice, deltaBase).setLength(32 * R).add(deltaVertice).multiplyScalar(1 / 1000 / R); } return _.compact([radiusLine, radiusParticle, deltaLine, deltaParticle]); } }() } }; })();</script> <script type="text/javascript">var form = (function () { // teach knockout to animate visibility toggling (function (visible) { var originUpdate = visible.update; visible.update = function (element, valueAccessor) { if (!form.animate || !$(element).closest('.slow-toggle-visibility').length) return originUpdate.apply(this, arguments); var show = ko.utils.unwrapObservable(valueAccessor()); show ? $(element).slideDown('fast') : $(element).slideUp('fast'); } })(ko.bindingHandlers.visible); // teach knockout to plot product on canvas ko.bindingHandlers.plot = { update: function (canvas, valueAccessor) { // get bound callback (don't care about context, it's ready-to-use ref to function) var product = valueAccessor(); // fire callback with new value of an observable bound via 'html' binding _.defer(_.bind(product.plot, product, canvas)); } } // figure defaults FigureOptionsVM.defaults = { radius: '4.2', connType: 'Piped', pipeD: '108', clockwise: true, detail: 3, subdivClass: 'I', M: 0, N: 0, subdivMethod: 'Chords', symmetry: 'Pentad', fullerenType: 'none', partial: '7/12', alignTheBase: false, beamsWidth: '150', beamsThickness: '50', clothier: { width: 2100, height: 12000 } }; var form = new FigureOptionsVM(_.throttle(function (state) { form.trigger('change', state); }, 100, {leading: false})); // used as dependency by reporting product statistics form.resultFigure = ko.observable(); form.resultMeter = ko.computed(function () { var meter = new Meter, figure = form.resultFigure(), removed = form.removedList(); // depends if (!figure) return; meter.push(__('Sizes (units)'), _.reduce({ face: 'Faces', line: 'Edges', vertex: 'Vertices' }, function (stat, title, type) { var sizes = 0, total = 0; _.chain(figure.$primitives) .where({type: type, removed: false}) .countBy('index') .each(function (count, index) { sizes += count > 0; total += count; }); stat[__(title)] = sizes + ' (' + total + ')'; return stat; }, {})); _.each(['vertex', 'line', 'face'], function (type) { _.chain(figure.$primitives) .where({type: type, removed: false}) .groupBy('index') .each(function (list, index) { _.each(list, function (figure) { meter.push(figure.product.meter()); }); }); }); return meter; }, null, {deferEvaluation: true}); form.reportText = ko.computed(function () { var meter = form.resultMeter(); return meter ? meter.reportText() : 'Please, wait...'; }, null, {deferEvaluation: true}); // set flag $('form.options').addClass('slow-toggle-visibility'); // flag to animate form elements form.animate = true; form.update = function (data) { _.each(data, function (value, key) { if (ko.isObservable(form[key])) { form[key](value); } }); }; return form; // view model of form function FigureOptionsVM(stateReceiver, timeout) { // const this.FULLEREN_TYPE_LIST = ko.computed(function () { return [{ id: 'inscribed', name: __('fulleren:Inscribed in') }, { id: 'described', name: __('fulleren:Described around') }]; }); var form = this; this.state = {}; // of current // manual/auto mode !function () { var forcibly = 0; // counter for non-manual value change detection form.forceBegin = function () { forcibly++ }; form.forceEnd = function () { forcibly-- }; form.isModeForcibly = function () { return !!forcibly }; }(); // common observables _.each(FigureOptionsVM.defaults, function (value, key) { form[key] = ko.observable(); form[key].subscribe(function (value) { form.state[key] = value; // protect the values of the change is not manually if (!form.isModeForcibly()) form[key].manual = value; fireChange(); }); }); // deferred state-changed firer var lastFiredState; fireChange = _.debounce(fireChange, timeout || 300); function fireChange() { var state = _.values(form.state).join(' '); if (state != lastFiredState) { stateReceiver(form.state); } lastFiredState = state; } // option lists _.each('connTypeList detailList partialList subdivClassList'.split(' '), function (key) { form[key] = ko.observable(); }); // true subdivMethodList this.subdivMethodList = ko.computed(function () { var options = [{ id: 'Chords', name: __('method:Equal Chords') }].concat( form.subdivClass() == 'I' && form.detail() > 2 ? [ { id: 'Arcs', name: __('method:Equal Arcs') }, { id: 'Mexican', name: __('method:Mexican') } ] : [] ); form.subdivMethod(maybe(form.subdivMethod.manual, _.pluck(options, 'id'))); return options; }, this, {deferEvaluation: true}); // option lists fresher function refreshList(what) { form.forceBegin(); _.each(what.split(/\s+/), function (what) { refreshList[what](); }); form.forceEnd(); } _.extend(refreshList, { detail: function () { var list = form.fullerenType() ? _.range(1, 9) : _.range(1, 11); if (form.subdivClass() == 'II') { list = _.filter(list, function (v) { return v % 2 != 1; }); } form.detailList(list); form.detail(luckyNumber(form.detail.manual, list)); }, subdivClass: function () { var classes = [{ id: 'I', name: 'I' }], V = form.detail(); for (var p = 1, q = V - p; p < V / 2; p++, q--) { classes.push({ id: 'III_' + p + ',' + q, name: 'III ' + p + ',' + q }); } if (V % 2 == 0) { classes.push({ id: 'II', name: 'II' }); } for (var p = Math.floor(V / 2 + 1), q = V - p; p < V; p++, q--) { classes.push({ id: 'III_' + p + ',' + q, name: 'III ' + p + ',' + q }); } form.subdivClassList(classes); form.subdivClass(maybe(form.subdivClass.manual, _.pluck(classes, 'id'))); }, partial: function () { var partialList = partialList_ClassI(form.detail()); form.partialList(partialList); form.partial(nearestRational(form.partial.manual, partialList)); }, connType: function () { var list = ['Piped', 'GoodKarma', 'Semicone']; if (form.fullerenType() || form.subdivClass() == 'II' || form.subdivMethod() == 'Chords') list.push('Cone'); list.push(form.fullerenType() ? 'Nose' : 'Joint'); form.connTypeList(list); form.connType(maybe(form.connType.manual, list)); } }); // lists binding form.detail.subscribe(function () { refreshList('partial subdivClass'); }); form.fullerenType.subscribe(function () { refreshList('partial connType detail'); }); form.subdivClass.subscribe(function () { refreshList('detail'); }); form.subdivMethod.subscribe(function () { refreshList('connType'); }); form.canAlignTheBase = ko.computed(function () { var can = (form.subdivClass() == 'I') && !form.fullerenType() && !/^1\/[12]$/.test(form.partial()) && /Piped|Joint|GoodKarma|Semicone/.test(form.connType()); // force set align form.forceBegin(); form.alignTheBase(can && form.alignTheBase.manual); form.forceEnd(); return can; }); // clothier form.clothier = { width: ko.observable(), height: ko.observable(), onRun: ko.observable(false), onPause: ko.observable(false), run: function () { form.clothier.onRun(true); form.clothier.onPause(false); }, pause: function () { form.clothier.onPause(true); }, stop: function () { form.clothier.onPause(false); form.clothier.onRun(false); } }; // removed figure entities form.removedList = ko.observableArray([]); form.removedList.subscribe(function (list) { form.state.removedList = list; fireChange(); }); // figure budget form.budgetList = ko.observable(); // set defaults !function () { defaults(FigureOptionsVM.defaults, form); function defaults(object, subject) { _.each(object, function (value, key) { _.isObject(value) && !_.isArray(value) ? defaults(value, subject[key]) : subject[key](value); }); } }(); // events support _.extend(this, Backbone.Events); } // helpers function maybe(value, list) { return _.contains(list, value) ? value : list[0]; } function luckyNumber(best, variants) { var lucky, quality = -1; _.each(variants, function (number) { var distance = Math.abs(number - best); if (-1 == quality || distance < quality) { lucky = number; quality = distance; } }); return lucky; } function partialList_ClassI(V) { for (var list = [], p = V, q = V * 4; p <= V * 4; p += (p != V * 3) ? 2 : V) list.push(rational(p, q)); return list; } function partialList_ClassII(V, symmetry) { console.warn('partialList_ClassII') var v = V / 2, faceCount = 60 * v * v; switch (symmetry) { case 'Cross': case 'Triad': case 'Pentad': } } function rational(p, q) { var pp = p, qq = q; // simplify rational fraction for (var m = 2; m <= pp && m <= qq;) if (pp % m == 0 && qq % m == 0) { pp /= m; qq /= m; } else m++; return pp + '/' + qq; } function nearestRational(rational, list) { var result, lastValue, target = eval(rational); _.each(list, function (rational) { var value = eval(rational); if (!result || Math.abs(value - target) < Math.abs(lastValue - target)) { result = rational; lastValue = value; } }); return result; } })(); </script> <script type="text/javascript">// calculation process !function (root) { var chain = [], io, startLength, timeout; var proc = root.calcProc = _.extend({ stop: function () { if (chain.length) { proc.trigger('cancel', chain); } chain = []; io = null; clearTimeout(timeout); return this; }, start: function (stages) { this.stop(); chain = chain.concat(_.compact(_.flatten(stages))); startLength = chain.length; proc.trigger('start', chain); _.defer(tick); return this; }, length: function () { return chain.length; } }, Backbone.Events); function tick() { var progress = startLength - chain.length; var stage = chain.shift(); if (stage) { proc.trigger('stage', stage, progress, io); timeout = _.defer(function () { io = stage.process(io); proc.trigger('stageOk', stage, progress, io); _.defer(tick); }); } else { proc.trigger('complete', chain); } } }(window); </script> <script type="text/javascript">// offline version $('body').toggleClass('offline', IS_OFFLINE); // iframe version $('body').toggleClass('iframe', IS_IFRAME); if (IS_IFRAME) { $('html').css({overflow: 'hidden'}); $('.geodesic').height($(window).height()); } // download var downloadUrl; $('.download').click(function () { downloadUrl = downloadUrl || $(this).attr('href') $(this).attr('href', downloadUrl + '?figure=' + encodeURIComponent(fragmentRouter.fromParams(form.state, 'prevent #hash update')) ); }); // product color palettes var productPalette = _.reduce(Palette.collections, function (memo, colors, type) { memo[type] = _.map(/*colors*/Palette.collections.line, function (cssColor) { return { integer: (new Function('return 0x' + cssColor.substr(1)))(), css: cssColor }; }); return memo; }, {}); // const var CALC_PATH = document.location.pathname; var DEFAULT_SYMMETRY_BY_CLASS = {I: 'Pentad', II: 'Cross', III: 'Pentad'}; // url#fragment router * * * var fragmentRouter = new Stringifier({ format: [ '<alignTheBase:ground_|[Aa]lign_|>', '<partial:[1-9]\\d*/[1-9]\\d*|1>_', '<subdivClass:|Class_(II)_|Class_III_(\\d+),(\\d+)_>', '<subdivMethod:|(Chords|Arcs|Mexican)_>', '<symmetry:|(Pentad|Cross|Triad)_>', '<fullerenType:|(Described_|Inscribed_|)Fuller(?:ene?)?_(?:with|in|on|of|smoke)_>', '<connType:Piped_D(?:0|[1-9]\\d*)(?:\\.\\d+)?|(?:Joint|Nose|GoodKarma)(?:_back|_counter)?|Cone|Semicone|>_', '<detail:[1-9]\\d?>V', '<radius:|_R(?:0|[1-9]\\d*)(?:\\.\\d+)?>', '<material:|_beams_?(\\d+(?:\\.\\d+)?)x(\\d+(?:\\.\\d+)?)>', '<removedList:|~([vlf]\\d+)+>' ], mapping: { alignTheBase: { value: function (align) { return !!align; }, string: function (align) { return align && this.partial != '1/1' && this.partial != '1/2' ? 'Align_' : ''; } }, subdivClass: { value: function (string, II, III_M, III_N) { return III_M ? { subdivClass: 'III_' + III_M + ',' + III_N, M: III_M, N: III_N } : { subdivClass: II || 'I' }; }, string: function (klass) { var all = klass.split(/_|,/), subdivClass = all[0]; switch (subdivClass) { case 'I': return ''; case 'II': return 'Class_II_'; case 'III': return 'Class_III_' + all[1] + ',' + all[2] + '_'; } console.error('unknown subdivision class', klass); } }, subdivMethod: { value: function (string, method) { return method || 'Chords'; }, string: function (method) { return method == 'Chords' ? '' : method + '_'; } }, symmetry: { value: function (string, symmetry) { var subdivClass = this.subdivClass.split('_')[0]; return symmetry || DEFAULT_SYMMETRY_BY_CLASS[subdivClass]; }, string: function (symmetry) { var subdivClass = this.subdivClass.split('_')[0]; return symmetry != DEFAULT_SYMMETRY_BY_CLASS[subdivClass] ? symmetry + '_' : ''; } }, // partial is simple fullerenType: { value: function (fulleren, type) { return fulleren ? type.match(/^descr/i) ? 'described' : 'inscribed' : false; }, string: function (type) { if (type) return (type == 'inscribed' ? 'Inscribed_' : 'Described_') + 'Fullerene_on_'; return ''; } }, connType: { value: function (string) { var matches = /^(Piped|Joint|Cone|Semicone|Nose|GoodKarma|)(.*)?$/.exec(string); var value = { connType: matches[1] }; if (value.connType == 'Piped') value.pipeD = matches[2].replace(/\D/g, ''); else if (/^Joint|Nose|GoodKarma$/.test(value.connType)) value.clockwise = !matches[2]; return value; }, string: function (connType) { switch (connType) { case 'Piped': connType += '_D' + this.pipeD; break; case 'Joint': case 'Nose': case 'GoodKarma': connType += this.clockwise ? '' : '_counter'; break; } return connType; } }, // detail is simple radius: { value: function (string) { return new Number(string.substr(2)).valueOf() || 69; }, string: function (value) { return '_R' + value; } }, material: { value: function (string, width, height) { return { beamsWidth: width, beamsThickness: height }; }, string: function () { return '_beams_' + this.beamsWidth + 'x' + this.beamsThickness; } }, removedList: { value: function (string) { if (!string) return []; var list = []; string.replace(/[vlf]\d+/g, function (index) { list.push(index); }); return { removedList: list }; }, string: function (list) { if (!figure) return _.isEmpty(list) ? '' : '~' + list.join(''); // pack a list var removing = _.pluck(_.where(figure.$primitives, {removed: true, type: 'face'}), 'removeIndex'), groups = _.reduce(figure.$primitives, function (memo, item) { if (item.removed && (item.type == 'face' || _.all(item.$super.face, _.property('removed')))) { memo.push({ index: item.removeIndex, faces: item.type == 'face' ? [item.removeIndex] : _.pluck(item.$super.face, 'removeIndex') }); } return memo; }, []), packed = [], removed = []; while (removing.length > 0) { var group = _.reduce(groups, function (best, group) { return (best && best.faces.length >= group.faces.length) ? best : group; }, null), removedFaces = group.faces; // filter groups groups = _.filter(groups, function (group) { return _.all(group.faces, function (face) { return !_.contains(removedFaces, face); }); }); // release removed removing = _.difference(removing, removedFaces); packed.push(group.index); } return _.isEmpty(list) ? '' : '~' + packed.join('') } } } }); // binding url fragment with form * * * $(window).on('popstate', function (e) { if (CALC_PATH == document.location.pathname) { var string = document.location.hash.substr(1); // try to restore figure configuration from file:path if (!string && IS_OFFLINE) { document.location.pathname.replace(/^.*\$(\d+)_([^$/]+)(?:\$([^ %/]+))?(?:(?: |%20)\(\d+\))?\.html$/, function (pathname, numerator, more, removed) { string = numerator + '/' + more + (removed && '~' + removed); }); } fragmentRouter.fromString(string); // auto map params correction to url #fragment string = fragmentRouter.fromParams(form.state); // update page title updateTitle(string); return false; } }); // router params => form state fragmentRouter.on('params', function (state) { form.animate = false; // mark values as setted manually _.each(state, function (value, key) { form[key].manual = value; }); // set form values _.each(state, function (value, key) { form[key](value); }); // lame-force, todo: resolve depends in any way form.partial(state.partial); form.animate = true; }); form.urlFragment = ko.observable(''); form.figureUrl = ko.computed(function () { return 'http://acidome.ru/lab/calc/' + (form.urlFragment() ? '#' + form.urlFragment() : ''); }); form.figureName = ko.computed(function () { return form.urlFragment().replace(/_/g, ' '); }); form.on('change', function (state) { // form state => router string var string = fragmentRouter.fromParams(state); form.urlFragment(string); }); // router string => url fragment fragmentRouter.on('string', function (string) { var currFragment = document.location.hash.substr(1); if (currFragment == string) { // prevent history repeating return; } // update history if (!IS_OFFLINE) { history.replaceState(null, 'no effect', '#' + string); console.log('* push state with', string); } // update page title updateTitle(string); }); // page title helper var initialTitle = $('head title').text(); function updateTitle(spec) { if (!spec) return; var hasRemoved = /~/.test(spec), title = spec.split('~')[0].replace(/_/g, ' ') + (hasRemoved ? ' (' + __('modified') + ')' : ''); $('head title').text([title, initialTitle].join(' - ')); // update figure dowload name var $link = $('#js-download-link'); $link.attr({ href: $link.data('href-base') + '?figure=' + encodeURIComponent(spec) }); } // init form params from url fragment // called before form been bounded with figure calculation process $(window).trigger('popstate'); // figure calculator var AXIS = 'y', CENTER = new Vector, figure; form._lastState = {}; form.on('change', function () { if (_.isEqual( _.omit(form.state, 'removedList'), _.omit(form._lastState, 'removedList') )) return; if (!_.isEmpty(form._lastState) && !_.isEqual( _.omit(form.state, 'radius', 'connType', 'pipeD', 'beamsWidth', 'beamsThickness', 'removedList'), _.omit(form._lastState, 'radius', 'connType', 'pipeD', 'beamsWidth', 'beamsThickness', 'removedList') ) ) { // reset removed on figure form option was changed form.removedList([]); } var state = _.clone(form.state); var mm = (1 / 1000); // state.radius; // mm/R var calcStartedAt = +new Date; calcProc.start(_.compact([ { name: 'base figure', process: function () { if (state.subdivClass == 'II') { figure = new Figure.PentakisDodecahedron({ axis: AXIS, symmetry: state.symmetry }); } else { figure = new Figure.Icosahedron({ axis: AXIS, symmetry: state.symmetry }); } return figure; } }, { name: 'subdivision', process: function (figure) { var V = state.detail, subdivAll = state.subdivClass.split(/_|,/), subdivClass = subdivAll[0]; switch (subdivClass) { case 'I': switch (state.subdivMethod) { case 'Chords': return figure.splitFaces(V); case 'Arcs': return figure.splitFaces_EA(V); case 'Mexican': return figure .splitFaces_EA(V) .splitFaces_EA_updateToMexican(V); default: throw 'Unknown subdivision method: ' + state.subdivMethod; } case 'II': figure.splitFaces(V / 2); return figure.splitFaces_updateToClassII(); case 'III': return figure.splitFaces_updateToClassIII(subdivAll[1], subdivAll[2]); default: throw 'Unknown subdivision class: ' + state.subdivClass; } } }, { name: 'primitive relations', process: function (figure) { // figure primitives initial figure.$primitives.each(function () { // radius-center of points this.center = CENTER; this.$points.each(function () { this.center = CENTER; }); }); return figure.relations(); } }, (state.fullerenType) && { name: 'transmutation figure to fulleren', // if required process: function (figure) { switch (state.fullerenType) { case 'inscribed': figure.fulleren(); break; case 'described': figure.prepareUnify(); figure.outerFulleren(); break; default: console.error('strange fulleren type:', state.fullerenType); } // recalc relations figure.relations(); // assert faces vertexes has common plane var badFactor = 0; _.each(figure.subs('face'), function (face) { var points = face.$points, bad = _.filter( _.map(points, function (a, i) { var b = points[(i - 1 + points.length) % points.length], c = points[(i + 2) % points.length], normal = Vector.crossProduct( Vector.subtract(b, a), Vector.subtract(c, a) ), plane = new Plane(normal, a).normalize(); plane.badMax = _.max(_.map(points, function (point) { var result = Math.abs(plane.result(point)); return result < 1e-9 ? 0 : result; })); return plane; }), function (plane) { return plane.badMax; } ); if (!_.isEmpty(bad)) { console.error('bad face'); badFactor = Math.max(badFactor, _.min(_.compact(_.pluck(bad, 'badMax')))); } }); if (badFactor) { console.error('bad factor', badFactor * state.radius); } return figure; } }, { name: 'set items remove indexes', process: function (figure) { // set items remove indexes _.each(_.groupBy(figure.$primitives, 'type'), function (collection, type) { var typeIndex = type.substr(0, 1).toLowerCase(); _.each(collection, function (figure, index) { figure.removeIndex = typeIndex + index; }); }); return figure; } }, { name: 'pre-slice', process: function (figure) { if (state.subdivClass == 'I' && !state.fullerenType && state.symmetry == 'Pentad') { var upper = _.sortBy(figure.subs('vertex'), function (v) { return v.$points[0][AXIS]; }).pop(); //console.log(upper); // wrong: .sliceByFraction() call .relations() too figure.sliceByFraction(upper, state.partial, false); } else { figure.sliceByAxis(AXIS, state.partial, false); } return figure; //.detectSelvage('sliced'); } }, state.alignTheBase && { name: 'align the base', // if required process: function (figure) { figure.groundSliced(AXIS); return figure; } }, { name: 'init product objects', process: function (figure) { var Connector = Product.Connector[state.connType], Rib = Product.Rib["Beam"], Face = Product[state.fullerenType ? 'Polygon' : 'Triangle']["Simple"]; figure.$primitives = $(_.flatten(_.map(figure.$primitives, function (primitive) { switch (primitive.type) { case 'vertex': primitive.product = new Connector(primitive, { R: state.radius, Dpipe: state.pipeD * mm, whirlAsClock: state.clockwise }); break; case 'line': if (Connector.lineSeparatelyForFaces) { // GoodKarma, Semicone var lineData = { $points: primitive.$points, origin: primitive }; primitive = _.map(primitive.$super.face, function (face, i) { if (i > 0) { // clone primitive related to origin primitive = new Figure(lineData); } primitive.bindedFace = face; primitive.live = face.live; primitive.product = new Rib({ R: state.radius, width: state.beamsWidth * mm, thickness: state.beamsThickness * mm, line: primitive }); face.bindedLines = face.bindedLines || []; face.bindedLines.push(primitive); return primitive; }); } else { primitive.product = new Rib({ R: state.radius, width: state.beamsWidth * mm, thickness: state.beamsThickness * mm, line: primitive }); } break; case 'face': primitive.product = new Face(primitive, { R: state.radius, bilateral: _.contains(['GoodKarma', 'Semicone'], state.connType) }); break; default: throw 'Product type unknown: ' + primitive.type; } return primitive; }))); return figure; } }, { name: 'preparing to unify', process: function (figure) { figure.prepareUnify(); return figure; } }, { name: 'unify', process: function (figure) { figure.unify(); return figure; } }, { name: 'slice', process: function (figure) { figure.$points = $([]); figure.$primitives = figure.$primitives.filter(function () { if (this.type == 'vertex' && this.live) { figure.$points.push(this.$points[0]); } return this.bindedFace ? this.bindedFace.live : this.live; }); figure.relations(); // GoodKarma/Semicone workaround, slice dark-side clones binded to removed face if (state.connType == 'GoodKarma' || state.connType == 'Semicone') { // filter lines binded to removed face var faces = _.filter(figure.$primitives, function (prim) { return !prim.removed && prim.type == 'face'; }); figure.$primitives = figure.$primitives.filter(function () { return 0 || this.type != 'line' || _.contains(faces, this.bindedFace); }); } return figure; //.detectSelvage('sliced'); } }, { name: 'statistics', process: function (figure) { // remove items _.each(figure.$primitives, function (figure, index) { if (_.contains(state.removedList, figure.removeIndex)) { figure.remove(); } }); // translate figure value to start compute report form.resultFigure(figure); return figure; } }, { name: 'plot product', process: function (figure) { // по типам var productAreaWidth = $('.budget-list').width(); form.budgetList(_.compact(_.map([ { type: 'line', canvasAttr: {width: productAreaWidth, height: state.connType == 'Semicone' ? 150 : 220} }, {type: 'face', canvasAttr: {width: productAreaWidth / 3}}, {type: 'vertex', canvasAttr: {width: productAreaWidth / 4}} ], function (budget) { budget.units = ko.computed(function () { var dependsFrom = form.removedList(); return _.where(figure.$primitives, {type: budget.type, removed: false}); }); budget.sizeList = _.compact(_.map(figure.stat[budget.type], function (size) { /*_.chain(size.collect) todo: implement plot for fullfilled instances (wrong lines plot) .sortBy(function(inst) { return inst.$subsets.length + inst.$supersets.length; }) .last() .value()*/ switch (budget.type) { case 'vertex': var sample = _.sortBy(size.collect, function (one) { return - // find with max count of live lines around _.chain(one.product.$hedgehog) .pluck('source') .where({live: true}) .value().length; })[0]; break; default: sample = size.collect[0]; } var product = sample.product; if (product.plot) { return { index: size.index, color: productPalette[budget.type][size.order].css, product: product, units: ko.computed(function () { return _.filter(budget.units(), function (unit) { return unit.index === size.index; }); }) }; } })); return _.isEmpty(budget.sizeList) ? null : budget; }))); return figure; } }, { name: 'render scene', process: function (figure) { viewer.trigger('render', figure); return figure; } }, { name: 'push log', process: function (figure) { // state and last state diff var diff = _.reduce(state, function (diff, value, key) { if (form._lastState[key] !== state[key]) diff[key] = value; return diff; }, {}); // save last form._lastState = _.clone(state); // track figure change Tracker.push('figure', diff, { dura: (+new Date) - calcStartedAt }); // fix initial page height (auto scroll position refreshed page issue) $('body').css('height', 'auto'); console.log('figure diff:', diff); return figure; } } ])); form._lastState = state; }); // progress bar of calculation process !function () { var $progress = $('.geodesic .progress'), progressTotal; function progress(step, msg) { $progress.text(msg + ' ' + (step + 1) + '/' + progressTotal); } calcProc .on('start', function (chain) { $progress.show(); progressTotal = chain.length; progress(0, 'calculation started...'); console.time && console.time('process time'); }) .on('cancel', function (chain) { progress(null, 'calculation was brutal cancelled'); console.timeEnd && console.timeEnd('process time'); }) .on('complete', function (chain) { progress(chain.length, 'calculation complete'); console.timeEnd && console.timeEnd('process time'); $progress.hide(); }) .on('stage', function (stage, step) { progress(step, stage.name); }) .on('stageOk', function (stage, step) { progress(step, stage.name + ' ok'); }); }(); // geo receiver $(document).bind('geo-complete', function (event, geo) { console.log('geo complete with', geo); }); // bind form layout with view-model instance $(function () { ko.applyBindings(form); }); // ad //$.getScript('./js/offer.js');</script> <!-- /pack me --> <!-- service offer --> <script type="text/javascript">OfferFactory = (function () { var list = []; function OfferFactory(options) { _.extend(this, options); } OfferFactory.add = function (options) { list.push(new OfferFactory(options)); }; OfferFactory.resultList = ko.computed(function () { if (!form.resultMeter()) return; form.removedList(); // depends var R = form.state.radius, R2 = R * R, live = _.where(figure.$primitives, {removed: false}), total = _.groupBy(live, 'type'), sizes = _.reduce(total, function (sizes, list, type) { sizes[type] = _.union(_.pluck(list, 'index')).length; return sizes; }, {}), context = _.extend({ R: R, all: live, total: total, sizes: sizes, ribMaxLengthSum: _.reduce(total.line, function (sum, line) { return sum + line.product.maxLength(); }, 0) * R, // => m maxRibProductLength: _.max(_.map(total.line, function (line) { return line.product.maxLength(); })) * R * 1000, // => mm ribVolume: _.reduce(total.line, function (memo, line) { return memo + line.product.midLength * line.product.R * line.product.thickness * line.product.R * line.product.width * line.product.R; }, 0), // => m3 skinArea: _.reduce(figure.stat.face, function (area, stat) { var sample = stat.collect[0], count = _.where(stat.collect, {removed: false}).length, pp = sample.$points, square = 0; for (var i = 1; i <= pp.length - 2; i++) { square += Vector.crossProduct(Vector.subtract(pp[i], pp[0]), Vector.subtract(pp[i + 1], pp[0])).length() / 2 } return area + count * square * R2; }, 0), // => m2 baseArea: _.reduce(total.line, function (area, line) { if (_.where(line.origin.$super.face, {removed: false}).length == 1) { var pp = _.invoke(line.$points, 'clone'); _.each(pp, function (p) { p[figure.axis] = 0; }); area += Vector.crossProduct(pp[0], pp[1]).length() / 2 * R2; } return area; }, 0), beamSection: form.state.beamsWidth + 'x' + form.state.beamsThickness }, form.state); return _.compact(_.flatten( _.map(list, function (offer) { var producer = !offer.condition || offer.condition(context) ? offer.result(context) : null; if (producer && !_.isEmpty(producer.offer)) return producer; }) )); }, null, {deferEvaluation: true}); OfferFactory.Offer = Offer; function Offer(data) { _.extend(this, data); } OfferFactory.formatPrice = function (number) { number = String(Math.round(number)); for (var prev; number != prev; prev = number, number = number.replace(/(\S)(\d{3})(\s|$)/, '$1 $2$3')) ; return number; }; OfferFactory.Order = function (producer) { var order = this; this.email = ko.observable(localStorage["client-email"] || ''); this.producer = producer; this.selectedPositions = ko.observableArray(); this.pending = ko.observable(false); this.submit = function (order, event) { var $email = $(event.target).siblings('input[type="email"]'), email = order.email(); if (!/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(email)) { alert(__('buyme:E-mail is not valid') + ': ' + email); $email.focus(); return; } localStorage["client-email"] = email; order.pending(true); $.ajax({ url: 'http://acidome.ru/lab/calc/order-flow/?action=create', type: 'POST', data: { order: _.pick(ko.toJS(order), 'email', 'producer', 'selectedPositions'), url: 'http://acidome.ru/lab/calc/' + location.hash, form: form.state }, dataType: 'JSON', complete: function () { order.pending(false); }, error: function () { alert(__('buyme:Sorry, error happens while we trying to order. Please, try again later.')); }, success: function (error) { if (error) { alert(__('buyme:' + error)); } else { alert( __('buyme:Thank you, the order has been successfully created.') + '\n-------\n' + __('buyme:Check your email, if the letter is marked as spam, mark it as not spam.') ); } if (!error) { // reset selected positions order.selectedPositions([]); } } }); }; }; return OfferFactory; })(); /* OfferFactory.add({ price: { singleSlice: 35, // per item sliceTuning: 2000, // per size cutEdgePair: 25, sosnaCube: 20000, // RUR berezaCube: 18000, // RUR nalogIP: 0.06, nalogNDS: 0.20 }, condition: function(data) { return 1 && 20 <= data.beamsWidth && data.beamsWidth <= 300 && 20 <= data.beamsThickness && data.beamsThickness <= 300 && 500 <= data.maxRibProductLength && data.maxRibProductLength <= 3000 //&& _.contains(['ru', 'ua'], i18n.lang()); }, result: function(data) { var q1 = Math.max(data.beamsWidth, 100) / 200 + 0.5, // mm q2 = Math.max(data.beamsThickness, 30) / 120 + 0.75, // mm q3 = Math.max(data.maxRibProductLength, 1000) / 2400 + 0.5, // mm cutsPerTail = { Piped: 1, Cone: 2, Joint: 1, Semicone: 1, GoodKarma: 1 }[ data.connType ], cutCost = this.price.singleSlice * q1 * q2 * q3 * cutsPerTail * 2 // 2 tails * data.total.line.length // ribs total * 1 / (1 - this.price.nalogNDS), // НДС tuningCost = this.price.sliceTuning * data.sizes.line // sizes / ( data.connType == 'GoodKarma' ? 2 : 1 ) // тоесть гуд карма на 3 частоту настройка угла 3 пары * 2000, или 6 ребер / 2 * 2000 * 1 / (1 - this.price.nalogNDS), // НДС cutEdgeCost = this.price.cutEdgePair * q3 * data.total.line.length * 1 / (1 - this.price.nalogNDS); // НДС return new OfferFactory.Offer({ producerName: 'Мастер гео дом', offer: [{ name: (data.connType == 'Piped' ? 'Ребра каркаса' : 'Каркас') + ', сосна', price: cutCost + tuningCost + data.ribVolume * this.price.sosnaCube * 1 / (1 - this.price.nalogIP), // material (ИП) currency: 'RUR' }, { name: (data.connType == 'Piped' ? 'Ребра каркаса' : 'Каркас') + ', береза', price: cutCost + tuningCost + data.ribVolume * this.price.berezaCube * 1 / (1 - this.price.nalogIP), // material (ИП) currency: 'RUR' }], feedback: { email: 'beethowen@mail.ru' } }); } }); */ // Kupolok.com OfferFactory.add({ price: { rib: { Piped: 5, // 200x50, 150х50 GoodKarma: 4, Semicone: 5, Cone: 5, Joint: 5 }, connectors: { "Сокол": { url: 'https://vk.com/market-50380859?w=product-50380859_13147%2Fquery', price: 19, // 200x50 only! conditions: [{ beamsWidth: "200", beamsThickness: "50", pipeD: "108" }] }, "Клешня-партизан": { price: 23, url: 'https://vk.com/market-50380859?w=product-50380859_13201%2Fquery', conditions: [{ beamsWidth: "150", beamsThickness: "50", pipeD: "118" }, { beamsWidth: "200", beamsThickness: "50", pipeD: "118" }] } }, wood: 140, // m3 КРОВЛЯ_ФАНЕРА_ФСФ_15мм: 10, КРОВЛЯ_ДОСКА_25мм: 9 }, result: function (data) { var ribsCost = this.price.rib[data.connType] * data.total.line.length + data.ribVolume * this.price.wood, offer = [{ name: (data.connType == 'Piped' ? 'Ребра каркаса' : 'Каркас'), price: ribsCost, currency: 'USD' }]; if (data.connType == 'Piped') { offer = offer.concat(_.map(this.price.connectors, function (connector, connectorName) { var name = '«' + connectorName + '»', price = connector.price * data.total.vertex.length; if (connector.url) { name = '<a href="' + connector.url + '" target="_blank">' + name + '</a>'; } name = 'Комплект коннекторов ' + name; if (_.some(connector.conditions, _.bind(_.findWhere, null, [data]))) { // any condition is met return { name: name, price: price, currency: 'USD' }; } else { return { name: name, price: price, currency: 'USD', conditions: _.map(connector.conditions, function (condition) { return { condition: condition, name: '∅' + condition.pipeD + ' ' + condition.beamsWidth + 'x' + condition.beamsThickness }; }) }; } })); } offer.push({ name: 'Кровля, фанера ФСФ 15мм', price: this.price.КРОВЛЯ_ФАНЕРА_ФСФ_15мм * data.skinArea, currency: 'USD' }); offer.push({ name: 'Кровля, доска 25мм', price: this.price.КРОВЛЯ_ДОСКА_25мм * data.skinArea, currency: 'USD' }); return new OfferFactory.Offer({ producerName: 'Kupolok.com', producerLink: 'http://kupolok.com/', offer: offer, feedback: { email: 'kotiara82@gmail.com' } }); } }); // Geosota.ru OfferFactory.add({ price: { //ИЗГОТОВЛЕНИЕ_ТРЕУГОЛЬНИКА_ОБШИВКИ: 400, М2_ОБШИВКИ: 900, ИЗГОТОВЛЕНИЕ_РЕБРА: { Piped: 400/*, Cone: 600*/ }, М3_ДЕРЕВА: { Piped: 10000, Cone: 18000 }, КОННЕКТОР_ГЕОСОТА: 230 }, result: function (form) { var offer = []; // I. "Обшивка из треугольников" if ( true /*!form.fullerenType && 1.5 <= form.R && form.R <= 16*/ ) { offer.push({ name: 'Кровля, фанера ФСФ 15–18мм', price: /*form.total.face.length * this.price.ИЗГОТОВЛЕНИЕ_ТРЕУГОЛЬНИКА_ОБШИВКИ + */form.skinArea * this.price.М2_ОБШИВКИ, currency: 'RUR' }); } // II. Ребра (балки) каркаса: if ( _.has(this.price.ИЗГОТОВЛЕНИЕ_РЕБРА, form.connType) /*&& form.maxRibProductLength <= 2200 && 1.5 <= form.R && form.R <= 16 && form.detail <= 7*/ ) { offer.push({ name: 'Ребра каркаса', price: form.total.line.length * this.price.ИЗГОТОВЛЕНИЕ_РЕБРА[form.connType] + form.ribVolume * this.price.М3_ДЕРЕВА[form.connType], currency: 'RUR' }); } // III. Комплект коннекторов "Партизан" if ( form.connType == 'Piped' /*&& 3 <= form.R && form.R <= 10*/ ) { var conditions = [{ beamsWidth: "150", beamsThickness: "50", pipeD: "118" }, { beamsWidth: "200", beamsThickness: "50", pipeD: "118" }], connectorName = 'Комплект коннекторов <a href="http://geosota.ru/solutions/kit/2-x/" target="_blank">«Партизан»</a>'; if (_.some(conditions, _.bind(_.findWhere, null, [form]))) { // any condition is met offer.push({ name: connectorName, price: form.total.line.length * 2 * (194 + 43) + form.total.vertex.length * 300, // magic prices? currency: 'RUR' }); } else { offer.push({ name: connectorName, conditions: _.map(conditions, function (condition) { return { condition: condition, name: '∅' + condition.pipeD + ' ' + condition.beamsWidth + 'x' + condition.beamsThickness }; }) }); } } // Комплект коннекторов "Геосота" var conditions = [{ pipeD: "90" }], connectorName = 'Комплект коннекторов <a href="http://geosota.ru/solutions/kit/1-3" target="_blank">«Геосота»</a>'; if ( form.connType == 'Piped' && 1.5 <= form.R && form.R <= 10 && 45 <= form.beamsWidth && form.beamsWidth <= 195 && 45 <= form.beamsThickness && form.beamsThickness <= 50 ) { if (_.some(conditions, _.bind(_.findWhere, null, [form]))) { offer.push({ name: connectorName, price: form.total.vertex.length * this.price.КОННЕКТОР_ГЕОСОТА, currency: 'RUR' }); } else { offer.push({ name: connectorName, conditions: _.map(conditions, function (condition) { return { condition: condition, name: '∅' + condition.pipeD }; }) }); } } else if ( form.connType == 'Piped' && 1.5 <= form.R && form.R <= 10 ) { offer.push({ name: connectorName, conditions: _.map(conditions, function (condition) { return condition.pipeD == form.pipeD ? { condition: { beamsWidth: (45 <= form.beamsWidth ? form.beamsWidth <= 195 ? form.beamsWidth : 195 : 45), beamsThickness: (45 <= form.beamsThickness ? form.beamsThickness <= 50 ? form.beamsThickness : 50 : 45) }, name: (45 <= form.beamsWidth ? form.beamsWidth <= 195 ? form.beamsWidth : 195 : 45) + 'x' + (45 <= form.beamsThickness ? form.beamsThickness <= 50 ? form.beamsThickness : 50 : 45) } : { condition: condition, name: '∅' + condition.pipeD }; }) }); } return new OfferFactory.Offer({ producerName: 'Geosota.ru', producerLink: 'http://geosota.ru/', offer: offer, feedback: { email: 'mail@geosota.ru' } }); } }); // Геодом BY OfferFactory.add({ price: { V: { 3: { '5/12': [90155, 120005], // without / with 2nd floor '7/12': [115580, 145430] }, 4: { '1/2': [164255, 204055] } }, beam: { '150x50': 240, '200x50': 300 } }, result: function (form) { if (form.connType != 'Piped') return; // коннекторы var offer = _.map( this.price.V[form.detail] && this.price.V[form.detail][form.partial], function (price, with2dnFloor) { return { name: '<a href="https://pp.vk.me/c624220/v624220318/16d1c/OTysMlOtGoE.jpg" target="_blank">Комплект коннекторов</a>' + (with2dnFloor ? ' + коннекторы перекрытия 2-го этажа' : ''), price: price, currency: 'RUR' }; } ); // ребра if (form.connType == 'Piped') { if (this.price.beam[form.beamSection]) { offer.push({ name: 'Ребра каркаса', price: form.ribMaxLengthSum * this.price.beam[form.beamSection], currency: 'RUR' }); } else { offer.push({ name: 'Ребра каркаса', conditions: [{ condition: { beamsWidth: "150", beamsThickness: "50", pipeD: "133" }, name: '∅133 150x50' }, { condition: { beamsWidth: "200", beamsThickness: "50", pipeD: "133" }, name: '∅133 200x50' }], currency: 'RUR' }); } } return new OfferFactory.Offer({ producerName: 'Геодом BY', producerLink: 'http://www.dome-by.com/', offer: offer, feedback: { email: 'sabishy@gmail.com' } }); } }); // www.ecodome.com.ua OfferFactory.add({ price: { carcassAndCover: 150, carcass: 100, calc: Math.E / 100 }, result: function (form) { var offer = []; /* Предложение #1 - Каркас + обшивка * GoodKarma (до диаметра 8м) и Piped (все размеры) * V2-4 * Максимальная длинна ребра - 1900 * Брус может быть любым, но можно показывать псевдолинк где размер будет - 46х150 * Диаметр трубы - 100. Хотя коннектор у нас не на базе трубы 🙂 * Цена: площадь_основания * $150 + 2.718% */ if ( ((form.connType == 'GoodKarma' && form.R <= 4) || form.connType == 'Piped') && 2 <= form.detail && form.detail <= 4 && form.maxRibProductLength <= 1900 ) { if (form.beamSection == '150x46' && form.pipeD == 100) { offer.push({ name: 'Каркас + обшивка', price: form.baseArea * this.price.carcassAndCover * (1 + this.price.calc), currency: 'USD' }); } else { offer.push({ name: 'Каркас + обшивка', conditions: [{ condition: { beamsWidth: "150", beamsThickness: "46", pipeD: "100" }, name: '∅100 150x46' }], currency: 'RUR' }); } } /* Предложение #2 - Каркас Фильтр: любой размер, любая доска * Piped * V2-5 Цена: площадь_основания * $100 */ if ( form.connType == 'Piped' && 2 <= form.detail && form.detail <= 5 ) { offer.push({ name: 'Каркас', price: form.baseArea * this.price.carcass * (1 + this.price.calc), currency: 'USD' }); } return new OfferFactory.Offer({ producerName: 'ecodome.com.ua', producerLink: 'http://ecodome.com.ua/', offer: offer, feedback: { email: 'mail@ecodome.com.ua' } }); } }); </script> <script type="text/javascript">/** * Clothier helper * * With figure #1/4_Class_III_1,2_Triad_Semicone_3V_R3.5_beams_200x30: * * OPERATION USEC MEMORY * create + start with face + applying 1 transition ~20ms 25 Kb * create * start with one face 32-53 * applying 1 transition 256-274 * */ !function (exports) { var IS_LIVE = {live: true, removed: false}, // condition for used figure primitives min = Math.min, max = Math.max, pointsCounter = 0; // exports /** * Gives graph of figure surface (cutting helper) */ Figure.prototype.createSurfaceGraph = function () { return (new Graph).initFromFigure(this); }; exports.FigureSurfaceGraph = Graph; Graph.validator = { Sheet: (function () { function DirectedRangeValidator(directionSegment) { this.matrix = segment2matrix(directionSegment); this.xrange = [Infinity, -Infinity]; this.yrange = [Infinity, -Infinity]; Rollable(this); } DirectedRangeValidator.prototype = { pushPoint: function (axisSizes, point) { var M = this.matrix, x = point[0] * M[0] + point[1] * M[2], y = point[0] * M[1] + point[1] * M[3],// todo: catch valid x,y here (speed) xrange = [min(this.xrange[0], x), max(this.xrange[1], x)], yrange = [min(this.yrange[0], y), max(this.yrange[1], y)], sizes = [xrange[1] - xrange[0], yrange[1] - yrange[0]].sort(), valid = sizes[0] < axisSizes[0] && sizes[1] < axisSizes[1]; if (valid) { this.xrange = xrange; this.yrange = yrange; } return valid && (sizes[0] * sizes[1]) / (axisSizes[0] * axisSizes[1]); }, begin: function () { return { xrange: this.xrange, yrange: this.yrange }; }, rollback: function (state) { this.xrange = state.xrange; this.yrange = state.yrange; } }; function SheetValidator(axisSizes) { this._axisSizes = axisSizes; this._rangeValidators = []; this._weight = undefined; Rollable(this); } SheetValidator.prototype = { pushPoint: function (point) { var sheet = this, weight = Infinity; if (!this._rangeValidators.every(function (rangeValidator, index) { var validWeight = rangeValidator.begin().pushPoint(sheet._axisSizes, point); if (false === validWeight) { // auto-rollback previous validators _.invoke(sheet._rangeValidators.slice(0, index + 1), 'rollback'); return false; } weight = min(validWeight, weight); return true; })) return false; _.invoke(this._rangeValidators, 'end'); return weight; }, pushSegment: function (segment, graphPoints) { var axisSizes = this._axisSizes, rangeValidator = new DirectedRangeValidator(segment), valid = graphPoints.every(function (point) { return false !== rangeValidator.pushPoint(axisSizes, point); }); return valid && !!this._rangeValidators.push(rangeValidator.begin()); }, applyTransition: function (overSegment, nextPoint, graphPoints) { var sheet = this; // add new segments if (!overSegment.every(function (segmentPoint, index) { if (!sheet.pushSegment([segmentPoint, nextPoint], graphPoints)) { // rollback segments sheet._rangeValidators.splice(-index, index); return false; } return true; })) return false; // add new point var resultWeight = this.pushPoint(nextPoint); if (!resultWeight) { // auto-rollback segments sheet._rangeValidators.splice(-2, 2); return false; } this._weight = resultWeight; return true; }, begin: function () { return { length: _.invoke(this._rangeValidators, 'begin').length, weight: this._weight }; }, rollback: function (state) { this._rangeValidators.length = state.length; _.invoke(this._rangeValidators, 'rollback'); this._weight = state.weight; }, end: function () { _.invoke(this._rangeValidators, 'end'); }, getWeight: function () { return this._weight; } }; return function (width, height) { var axisSizes = [width, height].sort(); return new SheetValidator(axisSizes); }; })(), HasNoCross: (function () { function HasNoCrossValidator() { this._segments = []; Rollable(this); } HasNoCrossValidator.prototype = { pushSegment: function (segment) { var x1 = segment[0][0], y1 = segment[0][1], x2 = segment[1][0], y2 = segment[1][1]; return this._segments.every(validateSegment) && !!this._segments.push(segment); // http://algolist.manual.ru/maths/geom/intersect/lineline2d.php function validateSegment(segment) { var x3 = segment[0][0], y3 = segment[0][1], x4 = segment[1][0], y4 = segment[1][1]; var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); if (!denom) return true; var result = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; if (result < -1e-9 && (1 + 1e-9) < result) return false; return true; } }, applyTransition: function (overSegment, nextPoint) { var segments = this._segments; return overSegment.every(function (segmentPoint, index) { if (!this.pushSegment([segmentPoint, nextPoint])) { // auto-rollback segments.splice(-index, index); return false; } return true; }, this); }, begin: function () { return this._segments.length; }, rollback: function (state) { this._segments.length = state; } }; return function () { return new HasNoCrossValidator(); }; })() }; function Graph() { this.reset(); this.validators = [ Graph.validator.HasNoCross(), Graph.validator.Sheet(2.1 / form.state.radius, 6 / form.state.radius) ]; Rollable(this); } _.extend(Graph.prototype, { reset: function () { this.front = []; this.group = []; this.points = []; this.faces = []; }, begin: function () { return { front: _.clone(this.front), group: _.clone(this.group), points: _.clone(this.points) }; }, rollback: function (state) { this.front = state.front; this.group = state.group; this.points = state.points; }, startWith: function (face) { var // first triangle points lengths = _.pluck(face.borders, 'length'), lengths2 = _.map(lengths, square), cos0 = (lengths2[2] + lengths2[1] - lengths2[0]) / (2 * lengths[1] * lengths[2]), facePoints = [ [0, 0], [cos0 * lengths[2], Math.sqrt(1 - cos0 * cos0) * lengths[2]], [lengths[1], 0] ]; _.each(facePoints, function (point, i) { point.index = pointsCounter++ }) this.validators.forEach(function (validator) { for (var i = 0, j = 2; i < 3; j = i++) { validator.pushSegment([facePoints[j], facePoints[i]], []); } }); this.validators.forEach(function (validator) { if (!validator.pushPoint) return; for (var i = 0; i < 3; i++) { validator.pushPoint(facePoints[i]); } }); this.addGroupFace(face, facePoints); return this; }, addGroupFace: function (face, facePoints) { var graph = this; //console.log('++', face.borders, facePoints); //this.faces.splice(this.faces.indexOf(face), 1); this.group.push({ face: face, points: facePoints }); _.each(facePoints, function (point) { if (!point.addedToGraph) { graph.points.push(point); point.addedToGraph = true; } }); // update front _.each(face.borders, function (border, index) { if (border.nextFacePoint && !_.findWhere(graph.group, {face: border.nextFace})) { // calc segment of border var segment = shiftIndex(facePoints, index).reverse(); // copy // var segment = facePoints.slice(0); // copy // segment.splice(index, 1); // remove point from previous face // segment.reverse(); // reverse order graph.front.push({ facePoints: facePoints, border: border, segment: segment, nextFace: border.nextFace }); } }); }, applyTransition: function (transition) { var graph = this, segment = transition.segment, point = transition.border.nextFacePoint(transition.facePoints), nextFacePoints = pushOrderIndex(segment, point, transition.border.nextPointIndex), graphPoints = this.points, validators = this.validators, weight, valid = validators.every(function (validator, index) { validator.begin(); if (!validator.applyTransition(segment, point, graphPoints)) { // auto-rollback _.invoke(validators.slice(0, index + 1), 'rollback'); return false; } weight = validator.getWeight ? validator.getWeight() : weight; // todo: what if not happens? return true; }); point.index = pointsCounter++; if (valid) { _.invoke(validators, 'end'); this.addGroupFace(transition.border.nextFace, nextFacePoints); // filter front from happy recieved transitions this.front = this.front.filter(function (tr) { return !_.findWhere(graph.group, {face: tr.border.nextFace}); }); } return valid && weight; }, initFromFigure: function (figure) { this.reset(); this.faces = _.chain(figure.subs('face')).where(IS_LIVE) // init faces/borders .reduce(function (faceById, face) { var borders = _.chain(face.$sub.line) .filter(function (line) { return !line.bindedFace || line.bindedFace === face; }) .sortBy(function (line) { var thirdPoint = _.difference(face.$points.get(), line.$points.get())[0]; return _.indexOf(face.$points, thirdPoint); }) .map(function (line) { var points = line.origin.$points.get(); return { lineOriginIndex: line.origin._enum, length: points[0].distance(points[1]), nextFace: _.find(line.origin.$super.face, function (f) { return f !== face && f.live && !f.removed; }), line: line }; }) .value(), // area of triangle by Heron p = _.reduce(borders, function (P, line) { return P + line.length }, 0) / 2, area = Math.sqrt(p * (p - borders[0].length) * (p - borders[1].length) * (p - borders[2].length)); faceById[face._enum] = { borders: borders, area: area, origin: face }; return faceById; }, {}) // direct links between graph faces / border mirrors .reduce(function (faces, face, index, faceById) { _.each(face.borders, function (border) { if (!border.nextFace) return; border.nextFace = faceById[border.nextFace._enum]; border.overBorder = _.findWhere(border.nextFace.borders, {lineOriginIndex: border.lineOriginIndex}); }); faces.push(face); return faces; }, []) // transitions beyond border handlers .each(function (face, faceIndex) { _.each(face.borders, function (border, index) { if (!border.nextFace) return; var length2 = border.length * border.length, self2 = _.chain(shiftIndex(face.borders, index)) .pluck('length').map(square).value(), overIndex = _.indexOf(border.nextFace.borders, border.overBorder), over2 = _.chain(shiftIndex(border.nextFace.borders, overIndex)) .pluck('length').map(square).value(); var // matrix of transition from self- to over-points matrix = pushOrderIndex([ // height base by self-face // height base by over-face ((length2 + self2[0] - self2[1]) + (length2 + over2[1] - over2[0]) * border.nextFace.area / face.area) / (2 * length2), ((length2 - self2[0] + self2[1]) + (length2 - over2[1] + over2[0]) * border.nextFace.area / face.area) / (2 * length2) ], -border.nextFace.area / face.area, index); border.nextFacePoint = function (points) { return [ points[0][0] * matrix[0] + points[1][0] * matrix[1] + points[2][0] * matrix[2], points[0][1] * matrix[0] + points[1][1] * matrix[1] + points[2][1] * matrix[2] ]; }; border.nextPointIndex = overIndex; border.selfIndex = index; border.matrix = matrix; }); }) .value(); return this; } }); // rollable mixin function Rollable(object) { var stack = []; object.begin = (function (beginState) { return function () { stack.push(beginState.call(object)); //console.log('roll begin ' + stack.length); Rollable.stat.begin++; return object; }; })(object.begin); object.rollback = (function (rollbackState) { return function () { rollbackState.call(object, stack.pop()); //console.log('roll back ' + stack.length); Rollable.stat.back++; return object; }; })(object.rollback); object.end = (function (endState) { return function () { endState && endState.call(object, stack.pop()); //console.log('roll end ' + stack.length); Rollable.stat.end++; return object; }; })(object.end); }; Rollable.stat = { begin: 0, back: 0, end: 0 }; exports.Rollable = Rollable; // some helpers function segment2matrix(segment) { var O = segment[0], V = [segment[1][0] - segment[0][0], segment[1][1] - segment[0][1]], Vlength = Math.sqrt(V[0] * V[0] + V[1] * V[1]), X = [V[0] / Vlength, V[1] / Vlength], Y = [-X[1], X[0]]; return [Y[1], -X[1], -Y[0], X[0]]; // inverse 2x2 matrix } function pushOrderIndex(array, item, index) { // worked only for array.length === 2 if (index < 0) console.error('bad index'); if (array.length !== 2) console.error('bad array'); switch (index) { case 0: return [item].concat(array); case 1: return [array[1], item, array[0]]; case 2: return array.concat([item]); } // array.push(item); // insert new last // return array.slice(2 - index).concat(array.slice(0, 2 - index)); // rotate to be inserted item placed by index } function shiftIndex(array, index) { if (index < 0) console.error('bad index'); var length = array.length; return array.concat(array).slice(index + 1, index + length); } function square(a) { return a * a } }(this); // debug $canvas = $('<canvas>').appendTo('body').attr({width: $(window).width(), height: $(window).height()}); canvas = $canvas.get(0); function trp(p) { return [ canvas.width / 2 + p[0] * 160, canvas.height / 2 - p[1] * 160 ]; } FigureSurfaceGraph.prototype.show = function () { var context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); sg.group.forEach(function (node) { node.face.borders.forEach(function (border, index) { var points = node.points.slice(0); points.splice(index, 1); points = points.map(trp); context.beginPath(); context.moveTo(points[0][0], points[0][1]); context.lineTo(points[1][0], points[1][1]); if (_.findWhere(sg.front, {border: border})) { context.lineWidth = 3; context.strokeStyle = 'red'; } else { context.lineWidth = 2; context.strokeStyle = 'lightblue'; } context.stroke(); context.font = '16px Arial'; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillText(border.line.index, (points[0][0] + points[1][0]) / 2, (points[0][1] + points[1][1]) / 2); }); }); return this; }; /** sg = figure.createSurfaceGraph(); sg.startWith(sg.faces[0]).show(); w = sg.applyTransition(sg.front[0]); w === false && sg.front.splice(0, 1); console.log(sg); sg.show(); w */</script> <!-- timing end --> <script type="text/javascript"> Tracker.timeEnd('js-loading', _jsLoadingStartAt); delete window._jsLoadingStartAt; </script> <!-- Google Analytics --> <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> try { var pageTracker = _gat._getTracker("UA-7847979-1"); pageTracker._trackPageview(); } catch (err) { } </script> <!-- timing end --> <script type="text/javascript"> Tracker.timeEnd('page-loading', _pageLoadingStartAt); delete window._pageLoadingStartAt; </script> </body> </html>