diff --git a/AUTHORS.md b/AUTHORS.md index 202f2c1296..59e31f90f6 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -15,7 +15,12 @@ A list of much-appreciated contributors who have submitted patches and reported * Loic Bonavent, University of Montpellier * Guillaume Condesse, University of Bordeaux * Franck Charneau and Joshua Baubry, University of La Rochelle -* Olivier Bado, University Cote d'Azur +* Olivier Bado-Faustin, University Cote d'Azur * Frederic Sene, INSA Rennes * Nicolas Lahoche, University of Lille (design and template) * Charlotte Benard (Logo and color) + +Pictures credits +---------------- +* default.svg: adapted from Play button Icon by [Freepik](https://www.freepik.com/free-vector) - Freepik License +* cookie.svg: [Broken oatmeal cookie created by pch.vector](https://www.freepik.com/vectors/logo) - Freepik License diff --git a/README.md b/README.md index 0a16da4d80..9ff2843ffc 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,3 @@ Le projet et la plateforme qui porte le même nom ont pour but de faciliter la m | | Ministère de lʼEnseignement supérieur, de la Recherche et de lʼInnovation :-----:|:-----:|:----: - -## Crédits tiers -* static/default.svg : Icon made by [Freepik](https://www.freepik.com) diff --git a/pod/authentication/shibmiddleware.py b/pod/authentication/shibmiddleware.py index c00bb04657..5bd85cdb53 100644 --- a/pod/authentication/shibmiddleware.py +++ b/pod/authentication/shibmiddleware.py @@ -3,6 +3,93 @@ REMOTE_USER_HEADER = getattr(settings, "REMOTE_USER_HEADER", "REMOTE_USER") +SHIBBOLETH_ATTRIBUTE_MAP = getattr( + settings, + "SHIBBOLETH_ATTRIBUTE_MAP", + { + "REMOTE_USER": (True, "username"), + "Shibboleth-givenName": (True, "first_name"), + "Shibboleth-sn": (False, "last_name"), + "Shibboleth-mail": (False, "email"), + "Shibboleth-primary-affiliation": (False, "affiliation"), + "Shibboleth-unscoped-affiliation": (False, "affiliations"), + }, +) + +SHIBBOLETH_STAFF_ALLOWED_DOMAINS = getattr( + settings, "SHIBBOLETH_STAFF_ALLOWED_DOMAINS", None +) + +AFFILIATION = getattr( + settings, + "AFFILIATION", + ( + ("student", ""), + ("faculty", ""), + ("staff", ""), + ("employee", ""), + ("member", ""), + ("affiliate", ""), + ("alum", ""), + ("library-walk-in", ""), + ("researcher", ""), + ("retired", ""), + ("emeritus", ""), + ("teacher", ""), + ("registered-reader", ""), + ), +) + +AFFILIATION_STAFF = getattr( + settings, "AFFILIATION_STAFF", ("employee", "faculty", "staff") +) + class ShibbMiddleware(ShibbolethRemoteUserMiddleware): header = REMOTE_USER_HEADER + + def check_user_meta(self, user, shib_meta): + """Check shibboleth access rights with user's meta + + Args: + user: User, + shib_meta dict + Returns: + bool + """ + return ( + user + and user.owner + and shib_meta["affiliation"] in [A[0] for A in AFFILIATION] + and user.owner.affiliation != shib_meta["affiliation"] + ) + + def is_staffable(self, user): + """Check that given user, his domain is in authorized domains of shibboleth staff + + Args: + user: User + Returns: + bool + """ + if ( + SHIBBOLETH_STAFF_ALLOWED_DOMAINS is None + or len(SHIBBOLETH_STAFF_ALLOWED_DOMAINS) == 0 + ): + return True + for d in SHIBBOLETH_STAFF_ALLOWED_DOMAINS: + if user.username.endswith("@" + d): + return True + return False + + def make_profile(self, user, shib_meta): + if ("affiliation" in shib_meta) and self.check_user_meta(user, shib_meta): + user.owner.affiliation = shib_meta["affiliation"] + user.owner.save() + if self.is_staffable(user) and "affiliations" in shib_meta: + for affiliation in shib_meta["affiliations"].split(";"): + if affiliation in AFFILIATION_STAFF: + user.is_staff = True + user.save() + break + return diff --git a/pod/authentication/templates/authentication/login.html b/pod/authentication/templates/authentication/login.html index da92835aa5..63fe9b8bd8 100644 --- a/pod/authentication/templates/authentication/login.html +++ b/pod/authentication/templates/authentication/login.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% load i18n static custom_tags %} {% block page_extra_head %} - + {% endblock %} {% block page_title %}{% trans 'Authentication' %}{% endblock %} diff --git a/pod/authentication/templates/registration/login.html b/pod/authentication/templates/registration/login.html index 4096349e45..e08300ef12 100644 --- a/pod/authentication/templates/registration/login.html +++ b/pod/authentication/templates/registration/login.html @@ -2,8 +2,10 @@ {% load i18n static %} {% block page_extra_head %} -{{ block.super }} -{{ form.media }} + {{ block.super }} + + + {{ form.media }} {% endblock %} {% block page_title %}{% trans 'Log in' %}{% endblock %} diff --git a/pod/authentication/tests/test_populated.py b/pod/authentication/tests/test_populated.py index 435be36a46..45dad80bc5 100644 --- a/pod/authentication/tests/test_populated.py +++ b/pod/authentication/tests/test_populated.py @@ -3,6 +3,9 @@ from django.test import TestCase, override_settings from pod.authentication.models import Owner, AccessGroup from pod.authentication import populatedCASbackend +from pod.authentication import shibmiddleware +from pod.authentication.backends import ShibbBackend +from django.test import RequestFactory from django.contrib.auth.models import User from importlib import reload from xml.etree import ElementTree as ET @@ -46,6 +49,35 @@ }, ) +REMOTE_USER_HEADER = getattr(settings, "REMOTE_USER_HEADER", "REMOTE_USER") + +SHIBBOLETH_ATTRIBUTE_MAP = getattr( + settings, + "SHIBBOLETH_ATTRIBUTE_MAP", + { + "REMOTE_USER": (True, "username"), + "Shibboleth-givenName": (True, "first_name"), + "Shibboleth-sn": (False, "last_name"), + "Shibboleth-mail": (False, "email"), + "Shibboleth-primary-affiliation": (False, "affiliation"), + "Shibboleth-unscoped-affiliation": (False, "affiliations"), + }, +) + +SHIBBOLETH_STAFF_ALLOWED_DOMAINS = getattr( + settings, "SHIBBOLETH_STAFF_ALLOWED_DOMAINS", None +) + +AFFILIATION_STAFF = getattr( + settings, "AFFILIATION_STAFF", ("employee", "faculty", "staff") +) + +SHIB_URL = getattr(settings, "SHIB_URL", "https://univ.fr/Shibboleth.sso/WAYF") + +SHIB_LOGOUT_URL = getattr( + settings, "SHIB_LOGOUT_URL", "https://univ.fr/Shibboleth.sso/Logout" +) + class PopulatedCASTestCase(TestCase): # populate_user_from_tree(user, owner, tree) @@ -276,3 +308,137 @@ def test_populate_user_from_entry_affiliation_group(self): " ---> test_populate_user_from_entry_affiliation_group" " of PopulatedLDAPTestCase : OK !" ) + + +class PopulatedShibTestCase(TestCase): + def setUp(self): + """setUp PopulatedShibTestCase create user pod""" + self.hmap = {} + for a in SHIBBOLETH_ATTRIBUTE_MAP: + self.hmap[SHIBBOLETH_ATTRIBUTE_MAP[a][1]] = a + # print(SHIBBOLETH_ATTRIBUTE_MAP[a][1] + ' > ' + a) + + print(" ---> SetUp of PopulatedShibTestCase : OK !") + + def _authenticate_shib_user(self, u): + """Simulate shibboleth header""" + fake_shib_header = { + "REMOTE_USER": u["username"], + self.hmap["username"]: u["username"], + self.hmap["email"]: u["email"], + self.hmap["first_name"]: u["first_name"], + self.hmap["last_name"]: u["last_name"], + } + if "groups" in u.keys(): + fake_shib_header[self.hmap["groups"]] = u["groups"] + if "affiliations" in u.keys(): + fake_shib_header[self.hmap["affiliation"]] = u["affiliations"].split(";")[0] + fake_shib_header[self.hmap["affiliations"]] = u["affiliations"] + + """ Get valid shib_meta from simulated shibboleth header """ + request = RequestFactory().get("/", REMOTE_USER=u["username"]) + request.META.update(**fake_shib_header) + shib_meta, error = shibmiddleware.ShibbMiddleware.parse_attributes(request) + self.assertFalse(error, "Generating shibboleth attribute mapping contains errors") + + """ Check user authentication """ + user = ShibbBackend.authenticate( + ShibbBackend(), + request=request, + remote_user=u["username"], + shib_meta=shib_meta, + ) + self.assertTrue(user.is_authenticated()) + + return (user, shib_meta) + + @override_settings(DEBUG=False) + def test_make_profile(self): + """Test if user attributes are retreived""" + user, shib_meta = self._authenticate_shib_user( + { + "username": "jdo@univ.fr", + "first_name": "John", + "last_name": "Do", + "email": "john.do@univ.fr", + "affiliations": "teacher;staff;member", + } + ) + self.assertEqual(user.username, "jdo@univ.fr") + self.assertEqual(user.email, "john.do@univ.fr") + self.assertEqual(user.first_name, "John") + self.assertEqual(user.last_name, "Do") + + """ Test if user can be staff if SHIBBOLETH_STAFF_ALLOWED_DOMAINS is None """ + settings.SHIBBOLETH_STAFF_ALLOWED_DOMAINS = None + reload(shibmiddleware) + shibmiddleware.ShibbMiddleware.make_profile( + shibmiddleware.ShibbMiddleware(), user, shib_meta + ) + self.assertTrue(user.is_staff) + + owner = Owner.objects.get(user__username="jdo@univ.fr") + self.assertEqual(owner.affiliation, "teacher") + + """ Test if user can be staff when SHIBBOLETH_STAFF_ALLOWED_DOMAINS + is restricted """ + settings.SHIBBOLETH_STAFF_ALLOWED_DOMAINS = ( + "univ-a.fr", + "univ-b.fr", + ) + user.is_staff = False # Staff status is not remove + user.save() + reload(shibmiddleware) + shibmiddleware.ShibbMiddleware.make_profile( + shibmiddleware.ShibbMiddleware(), user, shib_meta + ) + self.assertFalse(user.is_staff) + + """ Test if user become staff when SHIBBOLETH_STAFF_ALLOWED_DOMAINS + is restrict and contains his domain """ + settings.SHIBBOLETH_STAFF_ALLOWED_DOMAINS = ("univ.fr",) + reload(shibmiddleware) + shibmiddleware.ShibbMiddleware.make_profile( + shibmiddleware.ShibbMiddleware(), user, shib_meta + ) + self.assertTrue(user.is_staff) + + """ Test if same user with new unstaffable affiliation keep his staff status """ + unstaffable_affiliation = ["member", "unprobable"] + for a in unstaffable_affiliation: + self.assertFalse(a in AFFILIATION_STAFF) + user, shib_meta = self._authenticate_shib_user( + { + "username": "jdo@univ.fr", + "first_name": "Jean", + "last_name": "Do", + "email": "jean.do@univ.fr", + "affiliations": ";".join(unstaffable_affiliation), + } + ) + shibmiddleware.ShibbMiddleware.make_profile( + shibmiddleware.ShibbMiddleware(), user, shib_meta + ) + self.assertTrue(user.is_staff) # Staff status is not remove + + """ Test if the main affiliation of this same user + with new unstaffable affiliation has changed """ + owner = Owner.objects.get(user__username="jdo@univ.fr") + self.assertEqual(owner.affiliation, "member") + + """ Test if a new user with same unstaffable affiliations has no staff status""" + user, shib_meta = self._authenticate_shib_user( + { + "username": "ada@univ.fr", + "first_name": "Ada", + "last_name": "Da", + "email": "ada.da@univ.fr", + "affiliations": ";".join(unstaffable_affiliation), + } + ) + shibmiddleware.ShibbMiddleware.make_profile( + shibmiddleware.ShibbMiddleware(), user, shib_meta + ) + self.assertFalse(user.is_staff) + + print(" ---> test_make_profile" " of PopulatedShibTestCase : OK !") diff --git a/pod/authentication/tests/test_views.py b/pod/authentication/tests/test_views.py index 699d3a1894..549f2a18d9 100644 --- a/pod/authentication/tests/test_views.py +++ b/pod/authentication/tests/test_views.py @@ -1,9 +1,12 @@ -""" -Unit tests for authentication views +"""Unit tests for authentication views. + +* run with 'python manage.py test pod.authentication.tests.test_views' """ from django.test import TestCase from django.test import Client from django.contrib.auth.models import User +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ class authenticationViewsTestCase(TestCase): @@ -13,7 +16,7 @@ class authenticationViewsTestCase(TestCase): def setUp(self): User.objects.create(username="pod", password="podv2") - print(" ---> SetUp of authenticationViewsTestCase : OK !") + print(" ---> SetUp of authenticationViewsTestCase: OK!") def test_authentication_login_gateway(self): self.client = Client() @@ -27,26 +30,28 @@ def test_authentication_login_gateway(self): print( " ---> test_authentication_login_gateway \ - of authenticationViewsTestCase : OK !" + of authenticationViewsTestCase: OK!" ) def test_authentication_login(self): + """Test authentication login page.""" self.client = Client() self.user = User.objects.get(username="pod") + login_url = settings.LOGIN_URL # User already authenticated self.client.force_login(self.user) - response = self.client.get("/authentication_login/") + response = self.client.get(login_url) self.assertRedirects(response, "/") # User not authenticated and CAS are valued to False self.client.logout() - response = self.client.get("/authentication_login/") + response = self.client.get(login_url) self.assertRedirects(response, "/accounts/login/?next=/") print( " ---> test_authentication_login \ - of authenticationViewsTestCase : OK !" + of authenticationViewsTestCase: OK!" ) def test_authentication_logout(self): @@ -57,7 +62,7 @@ def test_authentication_logout(self): print( " ---> test_authentication_logout \ - of authenticationViewsTestCase : OK !" + of authenticationViewsTestCase: OK!" ) def test_userpicture(self): @@ -89,9 +94,9 @@ def test_userpicture(self): messages = list(response.wsgi_request._messages) self.assertEqual(len(messages), 1) self.assertEqual( - str(messages[0]), "One or more errors have been found in the form." + str(messages[0]), _("One or more errors have been found in the form.") ) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "userpicture/userpicture.html") - print(" ---> test_userpicture of authenticationViewsTestCase : OK !") + print(" ---> test_userpicture of authenticationViewsTestCase: OK!") diff --git a/pod/authentication/utils.py b/pod/authentication/utils.py index 70a6226ab0..74f5f62e9d 100644 --- a/pod/authentication/utils.py +++ b/pod/authentication/utils.py @@ -6,7 +6,8 @@ def get_owners(search, limit, offset): - """Return owners filtered by GET parameters 'q' + """Return owners filtered by GET parameters 'q'. + With limit and offset Args: diff --git a/pod/authentication/views.py b/pod/authentication/views.py index a38f652cd5..2f994b2f71 100644 --- a/pod/authentication/views.py +++ b/pod/authentication/views.py @@ -1,3 +1,4 @@ +"""Authentication views.""" from django.http import HttpResponse from django.shortcuts import render from django.shortcuts import redirect @@ -49,10 +50,12 @@ def authentication_login_gateway(request): else: def authentication_login_gateway(request): + """Login gateway when CAS_GATEWAY is not defined.""" return HttpResponse("You must set CAS_GATEWAY to True to use this view") def authentication_login(request): + """Handle authentication login attempt.""" referrer = request.GET["referrer"] if request.GET.get("referrer") else "/" host = ( "https://%s" % request.get_host() @@ -66,7 +69,7 @@ def authentication_login(request): return redirect(referrer) if USE_CAS and CAS_GATEWAY: url = reverse("authentication_login_gateway") - url += "?%snext=%s" % (iframe_param, referrer) + url += "?%snext=%s" % (iframe_param, referrer.replace("&", "%26")) return redirect(url) elif USE_CAS or USE_SHIB or USE_OIDC: return render( @@ -83,17 +86,19 @@ def authentication_login(request): ) else: url = reverse("local-login") - url += "?%snext=%s" % (iframe_param, referrer) + url += "?%snext=%s" % (iframe_param, referrer.replace("&", "%26")) return redirect(url) def local_logout(request): + """Logout a user connected locally.""" url = reverse("local-logout") url += "?next=/" return redirect(url) def authentication_logout(request): + """Logout a user.""" if request.user.is_anonymous(): return local_logout(request) if request.user.owner.auth_type == "CAS": diff --git a/pod/chapter/templates/video_chapter.html b/pod/chapter/templates/video_chapter.html index 313f622513..6e8769b0d6 100644 --- a/pod/chapter/templates/video_chapter.html +++ b/pod/chapter/templates/video_chapter.html @@ -8,7 +8,7 @@ {% include 'videos/video-header.html' %} {% endblock page_extra_head %} {% block breadcrumbs %} @@ -55,9 +55,9 @@ {% endblock page_content %} {% block page_aside %} {% if video.owner == request.user or request.user.is_superuser or perms.chapter.add_chapter or request.user in video.additional_owners.all %} -
-
 {% trans "Manage video"%}
-
+
+
 {% trans "Manage video"%}
+
{% include "videos/link_video.html" %}
diff --git a/pod/completion/static/css/caption_maker.css b/pod/completion/static/css/caption_maker.css index 21ac498797..a95e98237b 100644 --- a/pod/completion/static/css/caption_maker.css +++ b/pod/completion/static/css/caption_maker.css @@ -48,11 +48,41 @@ textarea { border-radius: 4px; } +.shortcutKey { + display: inline-block; + border: 2px solid #222; + border-radius: 6px; + padding: 3px 8px; + font-weight: 600; + margin-right: 8px; + margin-left: 8px; + min-width: 35px; + text-align: center; +} + +.shortcutKey svg { + transform: translateY(-2px); +} + /* the list of captions */ .gray_no_video{ display: flex; flex-wrap: wrap; + border-top: 1px solid #E1E1E1; } + +.videoSection { + float: left; + min-height: 425px; + width: 49%; + padding: 24px 0px; + padding-right: 24px; +} + +.caption_content { + border-left: 1px solid #E1E1E1; +} + .caption_content .caption_title{ display: flex; position: relative; @@ -79,9 +109,165 @@ textarea { line-height: 1.4; } +.captions_editor { + height: 470px; + overflow: auto; + resize: none; + width: 100%; + padding: 0; +} + +#newCaptionsEditor { + margin-bottom: 6px; +} + +.newEditorBlock { + border-bottom: 1px solid #E1E1E1; + padding: 8px; + transition: 0.2s; +} + +.newEditorBlock:hover { + background-color: rgba(223, 230, 246, 0.4); +} + +.newEditorBlock > textarea { + width: 77%; + height: 80px; + border-style: hidden; + background-color: transparent; + padding: 8px; + transition: 0.4s; +} + +.captionBeingEdited { + border-left: 3px solid var(--primary); + background-color: rgba(223, 230, 246, 0.4); +} + +.captionBeingEdited > textarea { + border: 1px solid var(--primary); + border-radius: 4px; + background-color: #FFF5FB; +} + +.captionTimestamps { + float: right; + line-height: 32px; +} + +.newEditorBlock a { + margin: 6px 0px; + max-width: 78px; + display: block; + color: #3EA6FF; + font-weight: 400; +} + +.newEditorBlock input { + margin: 6px 0px; + max-width: 78px; + height: 32px; + padding: 0; + display: block; + padding: 0px 2px; +} + +.captionButtons { + float: left; +} + +.captionButtons button { + margin: 9px 2px 2px 2px; + display: block; + left: 0px; + left: 16px; + width: 28px; + height: 28px; + padding: 0; + border: 0; + border-radius: 50%; + background: #fff; + box-shadow: 0px 0px 4px rgba(0,0,0,.15); + transition: 0.2s; +} + +.captionButtons button:hover { + background: var(--primary); +} + +.captionButtons button:hover svg { + color: #fff; +} + +.captionButtons svg{ + color: #707070; + margin: 0; +} + +#addSubtitle svg { + color: var(--link-color); +} + +.makerNavbarRight { + float: right; +} + +@media only screen and (max-width: 1000px) { + .makerNavbarRight { + float: none; + } +} + +#captionFilename { + width: 280px; + margin-left: 32px; + transform: translateY(-4px); + border-top-style: hidden; + border-right-style: hidden; + border-left-style: hidden; + border-bottom-style: groove; + background-color: transparent; +} + +#switchOldEditMode { + margin-bottom: 8px; +} + +#captionLanguageSelect { + margin-right: 10px; + height: 31px; + width: 120px; + background: none; + border: none; + color: var(--primary); + font-weight: 600; + font-size: 20px; +} + +#captionLanguageSelect:hover { + cursor: pointer; +} + +#captionLanguageSelect option { + color: black; + text-align: left; + font-size: 16px; +} + #captionmakerModal.save > .modal-dialog { max-width: 1000px; } + +#editorTipsAndGoBack { + width: 100%; + clear: both; + padding-top: 24px; + padding-bottom: 24px; + display: block; + border-top: 1px solid #E1E1E1; +} + @media only screen and (max-width: 800px){ .gray_no_video{ display: flex; @@ -96,4 +282,43 @@ textarea { margin-bottom: 1em; min-height: unset !important; } + + .newEditorBlock > textarea { + width: 60%; + } } + +.keyframe { + position: absolute; + z-index: 2; + height: 11px; +} + +.keyframe-left { + transform: translate(-6px, -11px); +} + +.keyframe-right { + transform: translate(0px, -11px); +} + +.regionHighligh { + position: absolute; + z-index: 1; + background-color: rgba(173, 50, 122, 0.5); + height: 3px; +} + +::-webkit-scrollbar { + padding: 2px; + width: 4px; +} + +::-webkit-scrollbar-track { + background: none; +} + +::-webkit-scrollbar-thumb { + background: var(--primary); + border-radius: 2px; +} \ No newline at end of file diff --git a/pod/completion/static/js/caption_maker.js b/pod/completion/static/js/caption_maker.js index 39a24b38e2..e6e4df372e 100644 --- a/pod/completion/static/js/caption_maker.js +++ b/pod/completion/static/js/caption_maker.js @@ -21,7 +21,10 @@ $(document).ready(function () { csrfmiddlewaretoken: Cookies.get("csrftoken"), }; send_form_data(url, data, "ProcessProxyVttResponse"); + } else { + $("#captionFilename").val(`${file_prefix}_captions_${Date.now()}`); } + let placeholder = gettext( "WEBVTT\n\nstart time(00:00.000) --> end time(00:00.000)\ncaption text" ); @@ -33,10 +36,25 @@ $(document).ready(function () { .substring(this.selectionStart, this.selectionEnd); playSelectedCaption(selectedText.trim()); }); + + captionContent.bind("input propertychange", function () { + captionsArray.length = 0; + $(".newEditorBlock").each(function () { + this.remove(); + }); + if (this.value.match(/^WEBVTT/)) { + ParseAndLoadWebVTT(this.value); + } else { + alert(gettext("Unrecognized caption file format.")); + } + }); }); $(document).on("submit", "#form_save_captions", function (e) { e.preventDefault(); + + if (!oldModeSelected) $("#captionContent").val(GenerateWEBVTT()); + if ($("#captionContent").val().trim() === "") { showalert(gettext("There is no captions to save"), "alert-danger"); return; @@ -45,32 +63,39 @@ $(document).on("submit", "#form_save_captions", function (e) { $("#saveCaptionsModal").modal("show"); } else { $(this).find('input[name="file_id"]').val(""); - send_form_save_captions(`${file_prefix}_captions_${Date.now()}`); + send_form_save_captions(); } }); $(document).on("click", "#modal-btn-new, #modal-btn-override", function () { + if (!oldModeSelected) $("#captionContent").val(GenerateWEBVTT()); + $("#saveCaptionsModal").modal("hide"); if (this.id == "modal-btn-override") { $("#form_save_captions").find('input[name="file_id"]').val(file_loaded_id); updateCaptionsArray($("#captionContent").val()); - send_form_save_captions(file_loaded_name); + send_form_save_captions(); } else if (this.id == "modal-btn-new") { $("#form_save_captions").find('input[name="file_id"]').val(""); - send_form_save_captions(`${file_prefix}_captions_${Date.now()}`); + send_form_save_captions(); } }); -var send_form_save_captions = function (name) { +const send_form_save_captions = function () { + let fileName = $("#captionFilename").val(); + if (fileName.length == 0) { + fileName = `${file_prefix}_captions_${Date.now()}`; + } + rxSignatureLine = /^WEBVTT(?:\s.*)?$/; vttContent = $("#captionContent").val().trim(); vttLines = vttContent.split(/\r\n|\r|\n/); if (!rxSignatureLine.test(vttLines[0])) { - alert("Not a valid time track file."); + alert(gettext("Not a valid time track file.")); return; } - let n = name; - let f = new File([vttContent], n + ".vtt", { type: "text/vtt" }); + + let f = new File([vttContent], fileName + ".vtt", { type: "text/vtt" }); let data_form = new FormData($("#form_save_captions")[0]); data_form.append("folder", current_folder); data_form.append("file", f); @@ -101,6 +126,8 @@ $("#podvideoplayer").on("error", function (event) { var vh = $(this).height(); // error handling straight from the HTML5 video spec (http://dev.w3.org/html5/spec-author-view/video.html) + if (!event.originalEvent.target.error) return; + switch (event.originalEvent.target.error.code) { case event.originalEvent.target.error.MEDIA_ERR_ABORTED: $("#videoError").text("You aborted the video playback."); @@ -128,18 +155,52 @@ $("#podvideoplayer").on("error", function (event) { $(this).css("display", "none"); }); +let shortcutsDisplayed = false; +$("#showShortcutTips").on("click", function (e) { + if (shortcutsDisplayed) { + $("#shortcutsBlock").hide(); + } else { + $("#shortcutsBlock").show(); + } + + shortcutsDisplayed = !shortcutsDisplayed; +}); + +$("#addSubtitle").on("click", function (e) { + var playTime = $("#podvideoplayer").get(0).player.currentTime(); + var captionsEndTime = existingCaptionsEndTime(); + AddCaption( + captionsEndTime, + playTime > captionsEndTime ? playTime : parseInt(captionsEndTime) + 2, + "" + ); +}); + $("#clearAllCaptions").on("click", function (e) { e.preventDefault(); - var deleteConfirm = confirm( - gettext("Are you sure you want to delete all caption?") - ); - if (deleteConfirm) { + if (confirm(gettext("Are you sure you want to delete all caption?"))) { captionsArray.length = 0; autoPauseAtTime = -1; + $("#captionContent").val(""); $("#captionTitle").html(" "); $("#textCaptionEntry").val(""); + $(".newEditorBlock").each(function () { + this.remove(); + }); + } +}); + +let oldModeSelected = false; + +$("#switchOldEditMode").on("click", function (e) { + oldModeSelected = !oldModeSelected; + + if (oldModeSelected) { + $("#captionContent").val(GenerateWEBVTT()); } + $("#captionContent").toggle(oldModeSelected); + $("#newCaptionsEditor").toggle(!oldModeSelected); }); // index into captionsArray of the caption being displayed. -1 if none. @@ -177,15 +238,21 @@ function existingCaptionsEndTime() { let updateCaptionsArray = (vtt) => { let arr = vtt.split("\n\n"); captionsArray = []; + $(".newEditorBlock").each(function () { + this.remove(); + }); arr.forEach((text) => { if (text.trim().toLowerCase() !== "webvtt") { let data = text.split("\n"); let times = data[0].split("-->"); - captionsArray.push({ + let newCaption = { start: ParseTime(times[0]), end: ParseTime(times[1]), caption: data[1], - }); + }; + + captionsArray.push(newCaption); + CreateCaptionBlock(newCaption); } }); }; @@ -243,7 +310,7 @@ function videoPauseEventHandler() { captionBeingDisplayed = -1; } - $("#textCaptionEntry").focus().get(0).setSelectionRange(1000, 1000); // set focus and selection point to end + //$("#textCaptionEntry").focus().get(0).setSelectionRange(1000, 1000); // set focus and selection point to end } function videoTimeUpdateEventHandler() { @@ -265,6 +332,10 @@ function videoTimeUpdateEventHandler() { FormatTime(playTime) + ":" ); + + let divs = document.querySelectorAll(".vjs-text-track-display div"); + divs[divs.length - 1].innerText = ""; + if (captionBeingDisplayed != -1) { $("#textCaptionEntry").val(""); captionBeingDisplayed = -1; @@ -302,6 +373,21 @@ $("#pauseButton").on("click", function () { $("#podvideoplayer").get(0).player.pause(); }); +function GenerateWEBVTT() { + let vtt = ""; + $("#newCaptionsEditor > .newEditorBlock").each(function () { + let captionText = this.querySelector(".captionTextInput").value; + let startTime = this.querySelector(".startTimeBtn").text; + let endTime = this.querySelector(".endTimeBtn").text; + + vtt += `\n\n${startTime} --> ${endTime}\n${captionText}`; + }); + + if (vtt.length > 0) vtt = "WEBVTT" + vtt; + + return vtt; +} + function SaveCurrentCaption() { var playTime = $("#podvideoplayer").get(0).player.currentTime(); var captionsEndTime = existingCaptionsEndTime(); @@ -325,6 +411,14 @@ $("#saveCaptionAndPlay").on("click", function () { $("#podvideoplayer").get(0).player.play(); }); +$("#textCaptionEntry").keypress(function (e) { + var code = e.keyCode ?? e.which; + if (code == 13 && !e.shiftKey) { + $("#saveCaptionAndPlay").click(); + return false; + } +}); + /** * Updat caption html content */ @@ -344,7 +438,291 @@ function UpdateCaption(ci, captionText) { updateCaptionHtmlContent(); } -function AddCaptionListRow(ci) { +let lastEditedBlock = null; + +function CreateCaptionBlock(newCaption, spawnFunction) { + let captionText = newCaption.caption; + let start = FormatTime(newCaption.start); + let end = FormatTime(newCaption.end); + + let block = { + // parent + div: $(`
`), + + // circle buttons + buttonsDiv: $("
"), + insertBtn: $( + `` + ), + deleteBtn: $( + `` + ), + + // textarea + captionTextInput: $(``), + + // time editable + timeBlockEditable: $( + `"` + ), + startTimeInput: $(``), + endTimeInput: $(``), + + // time links + timeBlock: $(`
`), + startTimeBtn: $(`${start}`), + endTimeBtn: $(`${end}`), + + // flags + isEditEnabled: false, + + // methods + enableEdit: function () { + if (!this.isEditEnabled) { + if (lastEditedBlock) { + lastEditedBlock.disableEdit(); + } + + this.startTimeInput.val(this.startTimeBtn.text()); + + this.endTimeInput.val(this.endTimeBtn.text()); + + this.timeBlockEditable.css("display", ""); + this.timeBlock.css("display", "none"); + this.div.addClass("captionBeingEdited"); + + lastEditedBlock = this; + + this.isEditEnabled = true; + } + }, + + disableEdit: function () { + if (this.isEditEnabled) { + let newStartTime = ParseTime(this.startTimeInput.val()); + let newEndTime = ParseTime(this.endTimeInput.val()); + + newCaption.start = newStartTime; + newCaption.end = newEndTime; + + this.startTimeBtn.text(FormatTime(newStartTime)); + this.endTimeBtn.text(FormatTime(newEndTime)); + + this.timeBlockEditable.css("display", "none"); + this.timeBlock.css("display", ""); + this.div.removeClass("captionBeingEdited"); + + this.placeInOrder(); + + this.isEditEnabled = false; + } + }, + + placeInOrder: function () { + for (let i in captionsArray) { + let cap = captionsArray[i]; + if (cap.start > newCaption.start) { + // move caption object in captionsArray + let fromI = this.div.index(); + let toI = fromI < i ? i - 1 : i; + captionsArray.splice(fromI, 1); + captionsArray.splice(toI, 0, newCaption); + + // move the element in DOM + this.div.detach().insertBefore(cap.blockObject.div); + return; + } + } + + // if this caption is the last, move it to the end + captionsArray.splice(this.div.index(), 1); + captionsArray.push(newCaption); + $("#addSubtitle").before(this.div); + }, + + spawnNew: function () { + let playTime = $("#podvideoplayer").get(0).player.currentTime(); + let captionObj = { + start: newCaption.end, + end: + playTime > newCaption.end ? playTime : parseInt(newCaption.end) + 2, + caption: "", + }; + + captionsArray.splice(this.div.index() + 1, 0, captionObj); + CreateCaptionBlock(captionObj, (newDiv) => this.div.after(newDiv)); + }, + + delete: function () { + captionsArray.splice(this.div.index(), 1); + this.div.remove(); + }, + + init: function () { + this.div.captionBlockObject = this; + this.captionTextInput.val(captionText); + + this.insertBtn.click(() => this.spawnNew()); + this.deleteBtn.click(() => this.delete()); + this.startTimeBtn.click(() => seekVideoTo(newCaption.start)); + this.endTimeBtn.click(() => seekVideoTo(newCaption.end)); + this.captionTextInput.focus(() => this.enableEdit()); + + this.timeBlock.append(this.startTimeBtn, this.endTimeBtn); + this.timeBlockEditable.append(this.startTimeInput, this.endTimeInput); + this.buttonsDiv.append(this.insertBtn, this.deleteBtn); + + this.div.append( + this.buttonsDiv, + this.captionTextInput, + this.timeBlock, + this.timeBlockEditable + ); + + this.startTimeInput.keypress((e) => { + if (e.which == 13) this.disableEdit(); + }); + + this.endTimeInput.keypress((e) => { + if (e.which == 13) this.disableEdit(); + }); + + $(document).click((e) => { + var target = $(e.target); + if (!target.closest(this.div).length) this.disableEdit(); + }); + }, + }; + + block.init(); + newCaption.blockObject = block; + + if (spawnFunction) { + spawnFunction(block.div); + } else { + $("#addSubtitle").before(block.div); + } + + feather.replace(); + + block.captionTextInput.bind("input propertychange", function () { + captionsArray[block.div.index()].caption = this.value; + }); + + block.div.hover( + function () { + highlightVideoRegion(newCaption.start, newCaption.end); + }, + function () { + clearVideoRegion(); + } + ); + + $("#noCaptionsText").remove(); + + return block; +} + +let editorShortcuts = { + Delete: function (e) { + if (e.altKey && lastEditedBlock) { + lastEditedBlock.delete(); + return false; + } + }, + PageUp: function (e) { + if (lastEditedBlock) { + let prev = lastEditedBlock.div.prev(); + if (prev) { + let textarea = prev.find("textarea"); + textarea.focus(); + return false; + } + } + }, + PageDown: function (e) { + if (lastEditedBlock) { + let next = lastEditedBlock.div.next(); + if (next) { + let textarea = next.find("textarea"); + textarea.focus(); + return false; + } + } + }, + ArrowLeft: function (e) { + if (this.notFocused()) { + seekVideo(-10); + return false; + } + }, + ArrowRight: function (e) { + if (this.notFocused()) { + seekVideo(10); + return false; + } + }, + " ": function (e) { + // space + if (this.notFocused()) { + let player = $("#podvideoplayer").get(0).player; + if (player.paused()) player.play(); + else player.pause(); + + return false; + } + }, + m: function (e) { + if (this.notFocused()) { + let player = $("#podvideoplayer").get(0).player; + player.muted(!player.muted()); + return false; + } + }, + "?": function (e) { + if (this.notFocused()) { + $("#showShortcutTips").click(); + return false; + } + }, + Insert: function (e) { + if (lastEditedBlock) { + lastEditedBlock.spawnNew(); + } else { + $("#addSubtitle").click(); + } + + return false; + }, + s: function (e) { + if (e.ctrlKey) { + $("#justSaveCaption").click(); + return false; + } + }, + End: function (e) { + $("#saveCaptionAndPlay").click(); + return false; + }, + + notFocused: function () { + var focused = $(":focus"); + return focused.length == 0; + }, + + init: function () { + let self = this; + $(document).bind("keydown", function (e) { + if (self[e.key]) { + return self[e.key](e); + } + }); + }, +}; + +editorShortcuts.init(); + +function AddCaptionListRow(ci, newCaption) { let vtt = $("#captionContent"); let vtt_entry = $("#textCaptionEntry").val().trim(); let start = caption_memories.start_time; @@ -357,17 +735,25 @@ function AddCaptionListRow(ci) { } else { vtt.val(`${vtt.val()}\n\n${caption_text}`); } - caption_memories.start_time = end; } + + CreateCaptionBlock(newCaption); + caption_memories.start_time = end; } function AddCaption(captionStart, captionEnd, captionText) { - captionsArray.push({ + let videoDuration = $("#podvideoplayer").get(0).player.duration(); + captionStart = Math.max(Math.min(captionStart, videoDuration), 0); + captionEnd = Math.max(Math.min(captionEnd, videoDuration), 0); + + let newCaption = { start: captionStart, end: captionEnd, caption: captionText.trim(), - }); - AddCaptionListRow(captionsArray.length - 1); + }; + + captionsArray.push(newCaption); + AddCaptionListRow(captionsArray.length - 1, newCaption); } function hmsToSecondsOnly(str) { @@ -375,7 +761,7 @@ function hmsToSecondsOnly(str) { s = 0, m = 1; while (p.length > 0) { - s += m * parseInt(p.pop(), 10); + s += m * (parseInt(p.pop(), 10) || 0); m *= 60; } return s; @@ -384,7 +770,7 @@ function hmsToSecondsOnly(str) { // parses webvtt time string format into floating point seconds function ParseTime(sTime) { let seconds = hmsToSecondsOnly(sTime); - return seconds + "." + sTime.split(".")[1]; + return parseFloat(seconds + "." + (sTime.split(".")[1] || 0)); /*// parse time formatted as hours:mm:ss.sss where hours are optional if (sTime) { if (m != null) { @@ -478,34 +864,42 @@ function LoadCaptionFile(fileObject) { }; reader.onerror = function (evt) { - alert("Error reading caption file. Code = " + evt.code); + alert(gettext("Error reading caption file. Code = ") + evt.code); }; try { reader.readAsText(fileObject); } catch (exc) { - alert("Exception thrown reading caption file. Code = " + exc.code); + alert( + gettext("Exception thrown reading caption file. Code = ") + exc.code + ); } } else { - alert("Your browser does not support FileReader."); + alert(gettext("Your browser does not support FileReader.")); } } // invoked by script insertion of proxyvtt.ashx function ProcessProxyVttResponse(obj) { if (obj.status == "error") - alert("Error loading caption file: " + obj.message); + alert(gettext("Error loading caption file: ") + obj.message); else if (obj.status == "success") { // delete any captions we've got captionsArray.length = 0; file_loaded = true; - file_loaded_name = obj.file_name; file_loaded_id = obj.id_file; current_folder = obj.id_folder; + $(".newEditorBlock").each(function () { + this.remove(); + }); + + // strip file extension and set as title + $("#captionFilename").val(obj.file_name.replace(/\.[^/.]+$/, "")); + if (obj.response.match(/^WEBVTT/)) { ParseAndLoadWebVTT(obj.response); } else { - alert("Unrecognized caption file format."); + alert(gettext("Unrecognized caption file format.")); } } } @@ -519,10 +913,14 @@ function ParseAndLoadWebVTT(vtt) { if (vttLines[0].trim().toLowerCase() != "webvtt") { // must start with a signature line - alert("Not a valid time track file."); + alert(gettext("Not a valid time track file.")); return; } + $(".newEditorBlock").each(function () { + this.remove(); + }); + var rxTimeLine = /^([\d\.:]+)\s+-->\s+([\d\.:]+)(?:\s.*)?$/; var rxCaptionLine = /^(?:]+)>)?([^\r\n]+)$/; var rxBlankLine = /^\s*$/; @@ -534,11 +932,13 @@ function ParseAndLoadWebVTT(vtt) { function appendCurrentCaption() { if (cueStart && cueEnd && cueText) { - captionsArray.push({ + let newCaption = { start: cueStart, end: cueEnd, caption: cueText.trim(), - }); + }; + captionsArray.push(newCaption); + CreateCaptionBlock(newCaption); } cueStart = cueEnd = cueText = null; } @@ -574,6 +974,82 @@ function ParseAndLoadWebVTT(vtt) { } } appendCurrentCaption(); - $("#captionContent").val(""); $("#captionContent").val(vtt); } + +// videojs region highlighting + +var highlightVideoRegion; +var clearVideoRegion; + +const registerPlugin = videojs.registerPlugin || videojs.plugin; + +const onPlayerReady = function (player, options) { + let startKeyframe; + let endKeyframe; + let regionHighlight; + + const clearVideoRegion = () => { + startKeyframe?.remove(); + + endKeyframe?.remove(); + + regionHighlight?.remove(); + + player.userActive(false); + }; + + highlightVideoRegion = function (startTime, endTime) { + clearVideoRegion(); + player.userActive(true); + + let startPercent = (startTime / player.duration()) * 100; + let endPercent = (endTime / player.duration()) * 100; + + startPercent = Math.max(Math.min(startPercent, 100), 0); + endPercent = Math.max(Math.min(endPercent, 100), 0); + + startKeyframe = + $(` + + `); + startKeyframe.css("left", `${startPercent}%`); + $(player.controlBar.progressControl.seekBar.playProgressBar.el_).before( + startKeyframe + ); + + regionHighlight = $("
"); + regionHighlight.css("left", `${startPercent}%`); + regionHighlight.css("width", `${endPercent - startPercent}%`); + startKeyframe.after(regionHighlight); + + endKeyframe = + $(` + + `); + endKeyframe.css("left", `${endPercent}%`); + regionHighlight.after(endKeyframe); + }; + + seekVideoTo = function (time) { + player.userActive(true); + player.currentTime(time); + }; + + seekVideo = function (time) { + player.userActive(true); + player.currentTime(player.currentTime() + time); + }; +}; + +const timelineRegions = function (options) { + this.ready(function () { + onPlayerReady(this, options); + }); +}; + +registerPlugin("timelineRegions", timelineRegions); + +videojs.hook("setup", function (player) { + player.timelineRegions(); +}); diff --git a/pod/completion/templates/video_caption_maker.html b/pod/completion/templates/video_caption_maker.html index d337421d8f..7abadfbce7 100644 --- a/pod/completion/templates/video_caption_maker.html +++ b/pod/completion/templates/video_caption_maker.html @@ -27,7 +27,21 @@ {% block page_content %} -

{% trans "Video Caption Maker" %}

+
+

{% trans "Video Caption Maker" %}

+ +
+ + +
+
@@ -49,36 +63,10 @@

{% trans "Video Caption Maker" %}

{% endif %} -

{% trans "Load Existing Caption File [optional]:" %} -

- {% csrf_token %} -
- {% if form_make_caption.errors %}

{% trans "One or more errors have been found in the form." %}

{% endif %} - {% comment %} {% for field_hidden in form_make_caption.hidden_fields %} {{field_hidden}} {% endfor %} {% endcomment %} - {% comment %} {% for field in form_make_caption.visible_fields %} {% endcomment %} - {% for field in form_make_caption.visible_fields %} - {% if field.name == 'src' %} - {% spaceless %} -
- {{ field.errors }} - {{ field }} - {% if field.help_text %} {{ field.help_text|safe }} {% endif %} - {% if field.field.required %}
{% trans "Please provide a valid value for this field" %}.
{%endif%} -
- {% endspaceless %} - {% endif %} - {% endfor %} - {% comment %} {% endfor %} {% endcomment %} - {% if form_make_caption.instance.id %} {% endif %} -
- {{form_make_caption.media}} -
-
-
- {% trans "Video" %} : +
+ {% include 'videos/video-element.html' %}
@@ -93,20 +81,69 @@

{% trans "Video Caption Maker" %}

- {% trans "Caption list" %} :{% trans "Use the Play and Pause buttons to determine when the subtitles appear, enter the text in the field below the video then click the Save / (Save & Continue) button to complete your subtitles and finally click the Save Subtitles button to create a subtitle file." %} - -
-
- {% csrf_token %} - - - - -
+ + +
+
{% trans "No captions" %}
+ +
+
+ +
+ {% csrf_token %} +
+ {% if form_make_caption.errors %}

{% trans "One or more errors have been found in the form." %}

{% endif %} + {% for field in form_make_caption.visible_fields %} + {% if field.name == 'src' %} + {% spaceless %} +
+ {{ field.errors }} + {{ field }} + {% if field.help_text %} {{ field.help_text|safe }} {% endif %} + {% if field.field.required %}
{% trans "Please provide a valid value for this field" %}.
{%endif%} +
+ {% endspaceless %} + {% endif %} + {% endfor %} + {% if form_make_caption.instance.id %} {% endif %} +
+ {{form_make_caption.media}} +
+
+ {% csrf_token %} + + + + +
+
-
+
+ + + +  {% trans "Back to the completion"%} diff --git a/pod/completion/templates/video_completion.html b/pod/completion/templates/video_completion.html index 8b1904b75c..c29cf3a486 100644 --- a/pod/completion/templates/video_completion.html +++ b/pod/completion/templates/video_completion.html @@ -122,8 +122,8 @@ {% if video.owner == request.user or request.user.is_superuser or perms.video.change_video or request.user in video.additional_owners.all %}
-
 {% trans "Manage video"%}
-
+
 {% trans "Manage video"%}
+
{% include "videos/link_video.html" %}
diff --git a/pod/completion/views.py b/pod/completion/views.py index bf7b8dca62..ce612549d9 100644 --- a/pod/completion/views.py +++ b/pod/completion/views.py @@ -18,8 +18,11 @@ from .forms import TrackForm from .models import Overlay from .forms import OverlayForm +from .models import CustomFileModel from pod.podfile.models import UserFolder from pod.podfile.views import get_current_session_folder, file_edit_save +from pod.main.lang_settings import ALL_LANG_CHOICES, PREF_LANG_CHOICES +from pod.main.settings import LANGUAGE_CODE import re import json from django.contrib.sites.shortcuts import get_current_site @@ -27,13 +30,18 @@ LINK_SUPERPOSITION = getattr(settings, "LINK_SUPERPOSITION", False) ACTION = ["new", "save", "modify", "delete"] CAPTION_MAKER_ACTION = ["save"] +LANG_CHOICES = getattr( + settings, + "LANG_CHOICES", + ((" ", PREF_LANG_CHOICES), ("----------", ALL_LANG_CHOICES)), +) +LANG_CHOICES_DICT = {key: value for key, value in LANG_CHOICES[0][1] + LANG_CHOICES[1][1]} @csrf_protect @staff_member_required(redirect_field_name="referrer") def video_caption_maker(request, slug): video = get_object_or_404(Video, slug=slug, sites=get_current_site(request)) - video_folder, created = UserFolder.objects.get_or_create( name=video.slug, owner=request.user ) @@ -53,8 +61,17 @@ def video_caption_maker(request, slug): if request.method == "POST" and request.POST.get("action"): action = request.POST.get("action") if action in CAPTION_MAKER_ACTION: - return eval("video_caption_maker_{0}(request, video)".format(action)) + return eval("video_caption_maker_{0}".format(action))(request, video) else: + track_language = LANGUAGE_CODE + captionFileId = request.GET.get("src") + if captionFileId: + captionFile = CustomFileModel.objects.filter(id=captionFileId).first() + if captionFile: + track = Track.objects.filter(video=video, src=captionFile).first() + if track: + track_language = track.lang + form_caption = TrackForm(initial={"video": video}) return render( request, @@ -63,6 +80,8 @@ def video_caption_maker(request, slug): "current_folder": video_folder, "form_make_caption": form_caption, "video": video, + "languages": LANG_CHOICES, + "track_language": track_language, }, ) @@ -74,9 +93,24 @@ def video_caption_maker_save(request, video): name=video.slug, owner=request.user ) if request.method == "POST": + lang = request.POST.get("lang") cur_folder = get_current_session_folder(request) response = file_edit_save(request, cur_folder) - if b"list_element" in response.content: + response_data = json.loads(response.content) + if ("list_element" in response_data) and (lang in LANG_CHOICES_DICT): + captFile = get_object_or_404(CustomFileModel, id=response_data["file_id"]) + + # immediately assign the newly created captions file to the video + desired = Track.objects.filter(video=video, src=captFile) + if desired.exists(): + desired.update(lang=lang, src=captFile) + else: + Track( + video=video, + kind="captions", + lang=lang, + src=captFile, + ).save() messages.add_message(request, messages.INFO, _(u"The file has been saved.")) else: messages.add_message( diff --git a/pod/custom/settings_local.py.example b/pod/custom/settings_local.py.example index 20a6cbde50..22c910dc32 100644 --- a/pod/custom/settings_local.py.example +++ b/pod/custom/settings_local.py.example @@ -659,6 +659,7 @@ ENCODE_VIDEO = "start_encode" # REMOTE ENCODING SETTINGS # SSH_REMOTE_USER = "" # SSH_REMOTE_HOST = "xxx.univ.fr" +# SSH_REMOTE_PORT = "22" # SSH_REMOTE_KEY = "/home/pod/.ssh/id_rsa" # Remote command to launch, it will be call with this arguments : # -n encoding- -i -v -u -d @@ -1016,8 +1017,16 @@ SHIBBOLETH_ATTRIBUTE_MAP = { "shib-given-name": (True, "first_name"), "shib-sn": (True, "last_name"), "shib-mail": (False, "email"), + "shib-primary-affiliation": (False, "affiliation"), + "shib-unscoped-affiliation": (False, "affiliations"), } +""" +# Custom variable to allow user of somme domain to be staff +# If empty all domains will be allowed +""" +SHIBBOLETH_STAFF_ALLOWED_DOMAINS = ('univ-domain.fr',) + """ # Nom de l'attribut dans les headers qui sert à identifier # l'utilisateur connecté avec Shibboleth @@ -1197,7 +1206,7 @@ BBB_NUMBER_MAX_LIVES = 4 # Version de BigBlueButton utilisée. # Si les URLs de présentations Web contiennent /2.3/ (et non /2.0/), # il est nécessaire de mettre ce paramètre à True. -# Remarque : si vous utilisez Scalelite, il est possible que les URLS générés soient +# Remarque : si vous utilisez Scalelite, il est possible que les URLS générées soient # au format 2.3 même si la version de BigBlueButton est une 2.2.X. """ BBB_VERSION_IS_23 = False diff --git a/pod/enrichment/forms.py b/pod/enrichment/forms.py index 6c4d3535ea..685b09ad15 100644 --- a/pod/enrichment/forms.py +++ b/pod/enrichment/forms.py @@ -42,7 +42,10 @@ class Meta(object): class EnrichmentForm(forms.ModelForm): + """Define edit forms for all enrichments types.""" + def __init__(self, *args, **kwargs): + """Init an EnrichmentForm.""" super(EnrichmentForm, self).__init__(*args, **kwargs) self.fields["video"].widget = HiddenInput() self.fields["start"].widget.attrs["min"] = 0 @@ -54,7 +57,6 @@ def __init__(self, *args, **kwargs): self.fields["start"].widget.attrs["max"] = 36000 self.fields["end"].widget.attrs["max"] = 36000 for myField in self.fields: - self.fields[myField].widget.attrs["placeholder"] = self.fields[myField].label if self.fields[myField].required or myField == "type": self.fields[myField].widget.attrs["class"] = "form-control required" label_unicode = u"{0}".format(self.fields[myField].label) diff --git a/pod/enrichment/models.py b/pod/enrichment/models.py index ed3ef5b0f2..e278f51999 100755 --- a/pod/enrichment/models.py +++ b/pod/enrichment/models.py @@ -149,15 +149,15 @@ class Enrichment(models.Model): verbose_name=_("Document"), null=True, blank=True, - help_text=_(u"Integrate an document (PDF, text, html)"), + help_text=_(u"Integrate a document (PDF, text, html)"), ) richtext = RichTextField(_("Richtext"), config_name="complete", blank=True) weblink = models.URLField(_(u"Web link"), max_length=200, null=True, blank=True) embed = models.TextField( - _("Embed"), + _("Embed code"), null=True, blank=True, - help_text=_(u"Integrate an external source."), + help_text=_(u"Paste here a code from an external source to embed it."), ) class Meta: diff --git a/pod/enrichment/static/css/enrichment.css b/pod/enrichment/static/css/enrichment.css index 9737cb455f..75ee3e1311 100644 --- a/pod/enrichment/static/css/enrichment.css +++ b/pod/enrichment/static/css/enrichment.css @@ -1,3 +1,6 @@ +/* + * CSS for enrichment editing + **/ /*** Table scroll ***/ table.scroll { @@ -30,11 +33,8 @@ table.scroll thead th { white-space: nowrap; line-height: 20px; } -table.scroll thead th.enrich_title, -table.scroll thead th.enrich_type, -table.scroll thead th.enrich_start, -table.scroll thead th.enrich_end { - white-space: nowrap; +.enrich_type{ + text-transform: capitalize; } #list_enrich .panel-heading, #form_enrich .panel-heading { @@ -49,6 +49,7 @@ table.scroll thead th.enrich_end { form#form_enrich { background-color: rgba(0, 0, 0, .05); } + /* #form_new, .video_back { diff --git a/pod/enrichment/static/css/videojs-slides.css b/pod/enrichment/static/css/videojs-slides.css index 57dc9608c0..c952275676 100644 --- a/pod/enrichment/static/css/videojs-slides.css +++ b/pod/enrichment/static/css/videojs-slides.css @@ -1,6 +1,6 @@ /* Main */ -.vjs-poster {z-index:2} -.video-js .vjs-tech {padding:0 10px 0 10px} +.vjs-poster {z-index: 2} +.video-js .vjs-tech {padding: 0 10px 0 10px} .vjs-slides { display: block; } @@ -10,7 +10,7 @@ width: 100%; height: 100%; bottom: 0; - padding:0; + padding: 0; } .video-slides>li { background-size: contain; @@ -24,7 +24,7 @@ bottom: 15%; width: 50%; padding: 0; - border-right:8px solid transparent;/*make margin for contain background-attachment*/ + border-right: 8px solid transparent;/*make margin for contain background-attachment*/ /*padding-bottom: 35px;*//*Works but maybe not usable because plyer menu is hidden duriong playing */ } .video-slides>li>div { @@ -33,6 +33,9 @@ color: #000; padding: 1em; } +.video-slides>li>.slide_embed { + overflow: auto; +} .video-slides>li>img { max-width: 100%; -webkit-user-select: none; @@ -41,20 +44,20 @@ /********* Default *********/ .vjs-tech { - width:50% !important; - height:100%; + width: 50% !important; + height: 100%; } /********* Pip slide -> pip-slide *********/ .vjs-tech.pip-slide { - width:80% !important; - height:100%; + width: 80% !important; + height: 100%; } .video-slides li.pip-slide { left: 80% !important; top: 35% !important; bottom: 35% !important; - width:20%; + width: 20%; } /*.pip-slide img { height: 30% !important; @@ -71,8 +74,8 @@ /********* Pip video -> big-slides *********/ .vjs-tech.big-slide { - width:20% !important; - height:100%; + width: 20% !important; + height: 100%; } .video-slides li.big-slide { position: relative !important; @@ -175,3 +178,13 @@ position: absolute; background-color: #ffe800; } + +.vjs-big-play-button {z-index: 2} +.vjs-control-bar {z-index: 3} + +/* Enrich types colors */ +.enrich_image{color:var(--purple)} +.enrich_document{color:var(--orange)} +.enrich_richtext{color:var(--blue)} +.enrich_weblink{color:var(--red)} +.enrich_embed{color:var(--green)} diff --git a/pod/enrichment/static/js/enrichment.js b/pod/enrichment/static/js/enrichment.js index a2cac7fb79..2b0a1adbd6 100644 --- a/pod/enrichment/static/js/enrichment.js +++ b/pod/enrichment/static/js/enrichment.js @@ -505,7 +505,7 @@ function overlaptest() { $(this).attr("data-title") + '"'; text += ", " + gettext("please change start and/or end values."); - msg += "
" + text; + msg += '
' + text + "
"; } }); if (msg) { diff --git a/pod/enrichment/static/js/videojs-slides.js b/pod/enrichment/static/js/videojs-slides.js index c4c4dc7e83..9c9d9a70ea 100644 --- a/pod/enrichment/static/js/videojs-slides.js +++ b/pod/enrichment/static/js/videojs-slides.js @@ -42,13 +42,9 @@ var loadEnrichmentVTTfile = function (url, callback) { stop_video: 0, start: start, end: end, - //startTime: start, - //endTime: end, }; }, setCue = function (index, data) { - //console.log('setCue '+index) - //console.log('start: '+cues[index].start+', end:'+cues[index].end) cues[index].title = data.title; cues[index].url = data.url; cues[index].type = data.type; @@ -83,8 +79,6 @@ var loadEnrichmentVTTfile = function (url, callback) { //// Read next lines, feed first, create and feed next cues for (let i = fisrtcueline + 1; i < nbl; i++) { if ((m = lines[i].match(reg))) { - console.log("Match " + m[0] + " " + m[1] + " " + m[2]); - console.log("txtdata: " + txtdata.split("}")[0]); setCue(c, JSON.parse(txtdata.split("}")[0] + "}")); txtdata = ""; c++; @@ -108,8 +102,8 @@ var loadEnrichmentVTTfile = function (url, callback) { var videojs = window.videojs; -const defaults = {}; -const registerPlugin = videojs.registerPlugin || videojs.plugin; +const slides_defaults = {}; +const registerSlidePlugin = videojs.registerPlugin || videojs.plugin; const slide_color = { document: "var(--orange)", image: "var(--purple)", @@ -189,6 +183,7 @@ var VideoSlides = function (items) { slide.height = player.currentDimensions().height / 2; } else if (type == "embed") { slide = document.createElement("div"); + slide.classList.add("slide_embed"); slide.innerHTML = this.slidesItems[i].url; } const li = document.createElement("li"); @@ -266,7 +261,6 @@ var VideoSlides = function (items) { } } if (!active) { - //console.log('In slideShow : '+active) player.trigger("changemode", "slide off"); } return false; @@ -462,9 +456,9 @@ const onPlayerReady = function (player, options) { */ const slides = function (options) { this.ready(function () { - onPlayerReady(this, videojs.mergeOptions(defaults, options)); + onPlayerReady(this, videojs.mergeOptions(slides_defaults, options)); }); }; // Register the plugin with video.js. -registerPlugin("slides", slides); +registerSlidePlugin("slides", slides); diff --git a/pod/enrichment/templates/enrichment/edit_enrichment.html b/pod/enrichment/templates/enrichment/edit_enrichment.html index 010037b47c..87b5ff4833 100644 --- a/pod/enrichment/templates/enrichment/edit_enrichment.html +++ b/pod/enrichment/templates/enrichment/edit_enrichment.html @@ -32,19 +32,9 @@ {% block video-element %}
-

- {%blocktrans%}To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video{%endblocktrans%} -

- - - - {% for track in video.track_set.all%} - - {%endfor%} - + {% include 'enrichment/video-element-enrichment.html' %}
+
{% include 'enrichment/list_enrichment.html' %} @@ -75,11 +65,11 @@ {% endblock video-element %} {% block page_aside %} -
-
-  {% trans 'Informations' %} +
+
+  {% trans 'Editing enrichments' %}
-
+
{% if video.owner == request.user or request.user.is_superuser or perms.enrichment.change_enrichment or request.user in video.additional_owners.all %}

 {% trans 'You can specify the group(s) of users who can access this page' %}

{% endif %} diff --git a/pod/enrichment/templates/enrichment/form_enrichment.html b/pod/enrichment/templates/enrichment/form_enrichment.html index 62f0fdc605..f5c4853050 100644 --- a/pod/enrichment/templates/enrichment/form_enrichment.html +++ b/pod/enrichment/templates/enrichment/form_enrichment.html @@ -3,31 +3,38 @@ {% load staticfiles %} {{form_enrichment.media}}
-

{% trans 'Create / Edit enrichments' %}

+

{% trans 'Create / Edit enrichment' %}

- {% csrf_token %} -
- {% if form_enrichment.errors or form_enrichment.non_field_errors %} - {% trans 'One or more errors have been found in the form:' %}
- {% for error in form_enrichment.non_field_errors %} - - {{error}}
- {% endfor %} - {% endif %} - {% for field_hidden in form_enrichment.hidden_fields %} - {{field_hidden}} - {% endfor %} - {% for field in form_enrichment.visible_fields %} -
- -
{{field}}
-
- {% endfor %} - {% if form_enrichment.instance %} - - {% endif %} - - - -
-
\ No newline at end of file + {% csrf_token %} +
+ {% if form_enrichment.errors or form_enrichment.non_field_errors %} +
+ {% trans 'One or more errors have been found in the form:' %} +
    {% for error in form_enrichment.non_field_errors %} +
  • {{error}}
  • + {% endfor %}
+
+ {% endif %} + {% for field_hidden in form_enrichment.hidden_fields %} + {{field_hidden}} + {% endfor %} + {% for field in form_enrichment.visible_fields %} +
+ +
+ {{field}} + {% if field.help_text %} + {{ field.help_text|safe }} + {% endif %} +
+
+ {% endfor %} + {% if form_enrichment.instance %} + + {% endif %} + + + +
+ diff --git a/pod/enrichment/templates/enrichment/group_enrichment.html b/pod/enrichment/templates/enrichment/group_enrichment.html index 5267ecddb5..38fdb8a6b7 100644 --- a/pod/enrichment/templates/enrichment/group_enrichment.html +++ b/pod/enrichment/templates/enrichment/group_enrichment.html @@ -67,12 +67,12 @@

{% trans "Editing group for the enrichment of the video" %} "{{video.title}} {% block page_aside %} {% if video.owner == request.user or request.user.is_superuser or perms.video.change_video or request.user in video.additional_owners.all %} -
-
 {% trans "Manage video"%}
-
- {% include "videos/link_video.html" %} +
+
 {% trans "Manage video"%}
+
+ {% include "videos/link_video.html" %} +
-
{% endif %} {% endblock page_aside %} @@ -83,4 +83,4 @@
 {% trans "Manag {{form.media}} -{% endblock more_script %} \ No newline at end of file +{% endblock more_script %} diff --git a/pod/enrichment/templates/enrichment/list_enrichment.html b/pod/enrichment/templates/enrichment/list_enrichment.html index bffa21f567..0c81120c58 100644 --- a/pod/enrichment/templates/enrichment/list_enrichment.html +++ b/pod/enrichment/templates/enrichment/list_enrichment.html @@ -18,7 +18,7 @@

{% trans 'List of the enrichments' %} ({{list_enrich {% for enrich in list_enrichment %} {{enrich.title}} - {% if enrich.type %}{{enrich.type}}{% endif %} + {% if enrich.type %}{% trans enrich.type %}{% endif %} {{enrich.start}} {{enrich.end}} diff --git a/pod/enrichment/templates/enrichment/video-element-enrichment.html b/pod/enrichment/templates/enrichment/video-element-enrichment.html new file mode 100644 index 0000000000..7c9835a5f3 --- /dev/null +++ b/pod/enrichment/templates/enrichment/video-element-enrichment.html @@ -0,0 +1,6 @@ +{% extends 'videos/video-element.html' %} +{% block extratrack %} +{% if video.enrichment_set.all %} + +{% endif %} +{% endblock extratrack %} \ No newline at end of file diff --git a/pod/enrichment/templates/enrichment/video_enrichment-iframe.html b/pod/enrichment/templates/enrichment/video_enrichment-iframe.html index 184025c15c..0df48262aa 100644 --- a/pod/enrichment/templates/enrichment/video_enrichment-iframe.html +++ b/pod/enrichment/templates/enrichment/video_enrichment-iframe.html @@ -3,9 +3,9 @@ {% load staticfiles %} {% block page_extra_head %} -{% include 'videos/video-header.html' with enrichment=True %} - - +{% include 'videos/video-header.html' %} + + {% endblock page_extra_head %} {% block page_title %}{%if channel %}{{channel.title}} - {%endif%}{%if theme %}{{theme.title}} - {%endif%}({% trans 'Enriched' %}) {{video.title}}{% endblock %} @@ -14,93 +14,11 @@ {% if form %} {% include 'videos/video-form.html' %} {% else %} - - -
- {% csrf_token %} -
- - {% if video.chapter_set.all %} - -
    - {% for chapter in video.chapter_set.all %} -
  • - {{chapter.title}} -
  • - {% endfor %} -
- {% endif %} - -{% endif %} + {% include 'enrichment/video-element-enrichment.html' %} +{%endif%} {% endblock video-element %} - {% block more_script %} {{block.super}} - +{% include 'enrichment/video_enrichment-script.html' %} {% endblock more_script %} diff --git a/pod/enrichment/templates/enrichment/video_enrichment-script.html b/pod/enrichment/templates/enrichment/video_enrichment-script.html new file mode 100644 index 0000000000..94ef7814e5 --- /dev/null +++ b/pod/enrichment/templates/enrichment/video_enrichment-script.html @@ -0,0 +1,50 @@ + diff --git a/pod/enrichment/templates/enrichment/video_enrichment.html b/pod/enrichment/templates/enrichment/video_enrichment.html index 49914614cb..773d326455 100644 --- a/pod/enrichment/templates/enrichment/video_enrichment.html +++ b/pod/enrichment/templates/enrichment/video_enrichment.html @@ -3,9 +3,9 @@ {% load staticfiles %} {% block page_extra_head %} - {% include 'videos/video-header.html' with enrichment=True %} - - + {% include 'videos/video-header.html' %} + + {% endblock page_extra_head %} {% block breadcrumbs %}{{ block.super }} @@ -16,130 +16,28 @@ {% block video-element %} {% if form %} - {% include 'videos/video-form.html' %} + {% include 'videos/video-form.html' %} {% else %} - - -
- {% csrf_token %} -
- - {% if video.chapter_set.all %} - -
    - {% for chapter in video.chapter_set.all %} -
  • - {{chapter.title}} -
  • - {% endfor %} -
- {% endif %} - -

- {% if video.licence %}{% endif %} - {{video.title|title}} - {% if video.date_evt %}[{{ video.date_evt }}]{% endif %} - - - -

- -
- - {% include 'videos/video-info.html' with enrichment=True %} -
+ {% include 'enrichment/video-element-enrichment.html' %} +
{% include 'videos/video-all-info.html' with third_app=True %}
{%endif%} {% endblock video-element %} {% block page_aside %} -
-
+
+
 {% trans 'Informations' %}
-
+

{% trans 'To help you, the different types of enrichments have specific colors:' %}

    -
  • {% trans 'Image' %}
  • -
  • {% trans 'Document' %}
  • -
  • {% trans 'Richtext' %}
  • -
  • {% trans 'Weblink' %}
  • -
  • {% trans 'Embed' %}
  • +
  • {% trans 'Image' %}
  • +
  • {% trans 'Document' %}
  • +
  • {% trans 'Richtext' %}
  • + +
  • {% trans 'Embed' %}

{% trans 'They are visible on the video playback bar.' %}

@@ -149,61 +47,6 @@
{% endblock page_aside %} {% block more_script %} - {{block.super}} - -{% if video.enrichment_set.all %} - -{% endif %} - +{% include 'enrichment/video_enrichment-script.html' %} {% endblock more_script %} diff --git a/pod/interactive/templates/interactive/edit_interactive.html b/pod/interactive/templates/interactive/edit_interactive.html index 947bc557c9..4df6ff4324 100644 --- a/pod/interactive/templates/interactive/edit_interactive.html +++ b/pod/interactive/templates/interactive/edit_interactive.html @@ -124,9 +124,9 @@
{% if video.owner == request.user or request.user.is_superuser or request.user in video.additional_owners.all %} -
-
 {% trans "Manage video"%}
-
+
+
 {% trans "Manage video"%}
+
{% include "videos/link_video.html" %}
diff --git a/pod/interactive/templates/interactive/group_interactive.html b/pod/interactive/templates/interactive/group_interactive.html index 06491e9ceb..66d4d6334e 100644 --- a/pod/interactive/templates/interactive/group_interactive.html +++ b/pod/interactive/templates/interactive/group_interactive.html @@ -65,13 +65,13 @@

{% trans "Editing group for the interactivity of the video" %} "{{video.titl {% block page_aside %} {% if video.owner == request.user or request.user.is_superuser or request.user in video.additional_owners.all %} -
-
 {% trans "Manage video"%}
-
- {% include "videos/link_video.html" %} +
+
 {% trans "Manage video"%}
+
+ {% include "videos/link_video.html" %} +
-
-{% endif %} + {% endif %} {% endblock page_aside %} {% block more_script %} diff --git a/pod/locale/fr/LC_MESSAGES/django.mo b/pod/locale/fr/LC_MESSAGES/django.mo index 51d72fcb9e..9c512d10e2 100644 Binary files a/pod/locale/fr/LC_MESSAGES/django.mo and b/pod/locale/fr/LC_MESSAGES/django.mo differ diff --git a/pod/locale/fr/LC_MESSAGES/django.po b/pod/locale/fr/LC_MESSAGES/django.po index 4115b04f9b..bfbf7acd39 100644 --- a/pod/locale/fr/LC_MESSAGES/django.po +++ b/pod/locale/fr/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-09-16 11:50+0000\n" +"POT-Creation-Date: 2021-10-17 19:30+0000\n" "PO-Revision-Date: \n" "Last-Translator: obado \n" "Language-Team: Pod Team pod@esup-portail.org\n" @@ -16,7 +16,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 2.4.2\n" -#: pod/authentication/admin.py:93 pod/main/forms.py:47 +#: pod/authentication/admin.py:93 pod/main/forms.py:51 msgid "Email" msgstr "Courriel" @@ -149,18 +149,18 @@ msgid "Change your picture" msgstr "Changer votre image de profil" #: pod/authentication/templates/userpicture/userpicture.html:29 -#: pod/authentication/views.py:111 +#: pod/authentication/views.py:130 #: pod/bbb/templates/bbb/live_publish_meeting.html:45 #: pod/bbb/templates/bbb/publish_meeting.html:37 pod/bbb/views.py:127 -#: pod/bbb/views.py:254 pod/completion/templates/video_caption_maker.html:56 +#: pod/bbb/views.py:254 pod/completion/templates/video_caption_maker.html:96 #: pod/enrichment/templates/enrichment/group_enrichment.html:29 #: pod/interactive/templates/interactive/group_interactive.html:27 #: pod/live/templates/live/live-form.html:10 -#: pod/main/templates/contact_us.html:20 pod/main/views.py:296 +#: pod/main/templates/contact_us.html:20 pod/main/views.py:297 #: pod/playlist/views.py:136 #: pod/recorder/templates/recorder/add_recording.html:36 #: pod/recorder/templates/recorder/record_delete.html:31 -#: pod/recorder/views.py:145 pod/recorder/views.py:338 +#: pod/recorder/views.py:146 pod/recorder/views.py:346 #: pod/video/templates/channel/channel_edit.html:47 #: pod/video/templates/videos/video-form.html:10 #: pod/video/templates/videos/video_delete.html:32 @@ -179,7 +179,7 @@ msgstr "Une ou plusieurs erreurs ont été trouvées dans le formulaire." #: pod/authentication/templates/userpicture/userpicture.html:42 #: pod/bbb/templates/bbb/live_publish_meeting.html:73 #: pod/bbb/templates/bbb/publish_meeting.html:65 -#: pod/completion/templates/video_caption_maker.html:68 +#: pod/completion/templates/video_caption_maker.html:104 #: pod/enrichment/templates/enrichment/group_enrichment.html:51 #: pod/interactive/templates/interactive/group_interactive.html:49 #: pod/live/templates/live/live-form.html:25 @@ -809,6 +809,7 @@ msgid "Chapter" msgstr "Chapitre" #: pod/chapter/models.py:35 pod/chapter/templates/video_chapter.html:67 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:50 #: pod/enrichment/templates/enrichment/video_enrichment-iframe.html:35 #: pod/enrichment/templates/enrichment/video_enrichment.html:39 #: pod/video/templates/videos/video-element.html:37 @@ -842,14 +843,14 @@ msgstr "Créer / Éditer les chapitres" #: pod/chapter/templates/chapter/form_chapter.html:12 #: pod/chapter/templates/chapter/form_chapter.html:43 -#: pod/enrichment/templates/enrichment/form_enrichment.html:12 +#: pod/enrichment/templates/enrichment/form_enrichment.html:13 #: pod/video/templates/channel/form_theme.html:11 msgid "One or more errors have been found in the form:" msgstr "Une ou plusieurs erreurs ont été trouvées dans le formulaire :" #: pod/chapter/templates/chapter/form_chapter.html:30 -#: pod/completion/templates/video_caption_maker.html:94 -#: pod/enrichment/templates/enrichment/form_enrichment.html:30 +#: pod/completion/templates/video_caption_maker.html:77 +#: pod/enrichment/templates/enrichment/form_enrichment.html:37 #: pod/enrichment/templates/enrichment/group_enrichment.html:60 #: pod/interactive/templates/interactive/group_interactive.html:58 #: pod/playlist/templates/playlist.html:69 @@ -863,7 +864,7 @@ msgid "Save" msgstr "Sauvegarder" #: pod/chapter/templates/chapter/form_chapter.html:31 -#: pod/enrichment/templates/enrichment/form_enrichment.html:31 +#: pod/enrichment/templates/enrichment/form_enrichment.html:38 #: pod/video/templates/channel/form_theme.html:47 #: pod/video/templates/videos/category_modal.html:45 #: pod/video/templates/videos/category_modal.html:65 @@ -886,7 +887,7 @@ msgstr "Liste des chapitres" #: pod/completion/models.py:251 #: pod/completion/templates/overlay/list_overlay.html:10 #: pod/enrichment/templates/enrichment/list_enrichment.html:10 -#: pod/main/models.py:121 pod/main/views.py:184 pod/playlist/models.py:12 +#: pod/main/models.py:121 pod/main/views.py:185 pod/playlist/models.py:12 #: pod/playlist/templates/playlist/playlist_element_list.html:11 #: pod/video/models.py:254 pod/video/models.py:396 pod/video/models.py:518 #: pod/video/models.py:599 pod/video/templates/channel/list_theme.html:9 @@ -950,7 +951,7 @@ msgid "My videos" msgstr "Mes vidéos" #: pod/chapter/templates/video_chapter.html:42 -#: pod/completion/templates/video_caption_maker.html:114 +#: pod/completion/templates/video_caption_maker.html:144 #: pod/video/templates/videos/video_collaborate.html:66 #: pod/video/templates/videos/video_delete.html:20 #: pod/video/templates/videos/video_edit.html:38 @@ -1067,7 +1068,7 @@ msgstr "sous-titres" #: pod/completion/models.py:44 msgid "captions" -msgstr "légendes" +msgstr "sous titres" #: pod/completion/models.py:59 msgid "lastname / firstname" @@ -1119,7 +1120,7 @@ msgstr "" #: pod/completion/models.py:124 pod/completion/models.py:171 #: pod/completion/models.py:250 -#: pod/completion/templates/video_caption_maker.html:84 +#: pod/completion/templates/video_caption_maker.html:67 #: pod/enrichment/models.py:322 pod/enrichment/models.py:356 #: pod/interactive/models.py:18 pod/interactive/models.py:48 #: pod/playlist/models.py:85 pod/recorder/models.py:90 pod/video/models.py:593 @@ -1451,27 +1452,27 @@ msgstr "menu" msgid "Video Caption Maker" msgstr "Outil de création de fichier de sous-titres" -#: pod/completion/templates/video_caption_maker.html:52 -msgid "Load Existing Caption File [optional]:" -msgstr "Charger un fichier de sous-titres existant [facultatif] :" +#: pod/completion/templates/video_caption_maker.html:33 +msgid "Change mode" +msgstr "Changer le mode d'édition" -#: pod/completion/templates/video_caption_maker.html:92 +#: pod/completion/templates/video_caption_maker.html:75 msgid "Play" msgstr "Lecture" -#: pod/completion/templates/video_caption_maker.html:93 +#: pod/completion/templates/video_caption_maker.html:76 msgid "Pause" msgstr "Pause" -#: pod/completion/templates/video_caption_maker.html:95 +#: pod/completion/templates/video_caption_maker.html:78 msgid "Save & Continue" msgstr "Sauvegarder & continuer" -#: pod/completion/templates/video_caption_maker.html:99 +#: pod/completion/templates/video_caption_maker.html:82 msgid "Caption list" -msgstr "Légendes" +msgstr "Liste des sous titres" -#: pod/completion/templates/video_caption_maker.html:99 +#: pod/completion/templates/video_caption_maker.html:82 msgid "" "Use the Play and Pause buttons to determine when the subtitles appear, enter " "the text in the field below the video then click the Save / (Save & " @@ -1484,31 +1485,100 @@ msgstr "" "sous-titres et enfin cliquez sur le bouton Enregistrer les sous-titres pour " "créer un fichier de sous-titre." -#: pod/completion/templates/video_caption_maker.html:106 +#: pod/completion/templates/video_caption_maker.html:85 +msgid "No captions" +msgstr "Pas de sous-titres" + +#: pod/completion/templates/video_caption_maker.html:88 +#| msgid "subtitles" +msgid "Add subtitle" +msgstr "Ajouter un sous titre" + +#: pod/completion/templates/video_caption_maker.html:92 +msgid "You can load and existing caption file below :" +msgstr "Vous pouvez charger un fichier de sous titre existant ci dessous :" + +#: pod/completion/templates/video_caption_maker.html:117 msgid "Save Captions" msgstr "Enregistrer les sous-titres" -#: pod/completion/templates/video_caption_maker.html:107 +#: pod/completion/templates/video_caption_maker.html:118 msgid "Clear All" msgstr "Tout effacer" -#: pod/completion/templates/video_caption_maker.html:115 +#: pod/completion/templates/video_caption_maker.html:126 +msgid "Key Schortcuts" +msgstr "Raccourcis clavier" + +#: pod/completion/templates/video_caption_maker.html:128 +msgid "Video Player" +msgstr "Lecteur vidéo" + +#: pod/completion/templates/video_caption_maker.html:129 +msgid "Space" +msgstr "Espace" + +#: pod/completion/templates/video_caption_maker.html:129 +msgid "Pause / unpause" +msgstr "Pause / reprendre" + +#: pod/completion/templates/video_caption_maker.html:130 +msgid "Rewind the video 10 seconds back" +msgstr "Rembobiner la vidéo 10 secondes en arrière" + +#: pod/completion/templates/video_caption_maker.html:131 +msgid "Skip 10 seconds" +msgstr "Sauter 10 secondes" + +#: pod/completion/templates/video_caption_maker.html:132 +msgid "Mute/unmute video" +msgstr "Enlever/remettre le son de la video" + +#: pod/completion/templates/video_caption_maker.html:134 +msgid "Captions Editor" +msgstr "Editeur de sous titre" + +#: pod/completion/templates/video_caption_maker.html:135 +msgid "Select previous caption" +msgstr "Sélectionner le sous-titre précédent" + +#: pod/completion/templates/video_caption_maker.html:136 +msgid "Select next caption" +msgstr "Sélectionner le sous-titre suivant" + +#: pod/completion/templates/video_caption_maker.html:137 +msgid "Del" +msgstr "SUPPR" + +#: pod/completion/templates/video_caption_maker.html:137 +msgid "Delete selected caption" +msgstr "Supprimer le sous-titre" + +#: pod/completion/templates/video_caption_maker.html:138 +msgid "Add new caption" +msgstr "Ajouter nouvelle légende" + +#: pod/completion/templates/video_caption_maker.html:140 +msgid "Show/hide this window" +msgstr "Afficher / masquer cette fenêtre" + +#: pod/completion/templates/video_caption_maker.html:145 msgid "Back to the completion" msgstr "Retour à la complétion" -#: pod/completion/templates/video_caption_maker.html:126 +#: pod/completion/templates/video_caption_maker.html:156 msgid "Save captions file." msgstr "Sauvegarder le fichier de sous-titres." -#: pod/completion/templates/video_caption_maker.html:130 +#: pod/completion/templates/video_caption_maker.html:160 msgid "You have loaded a file. Do you want to override it?" msgstr "Vous avez chargé un fichier. Voulez-vous le remplacer ?" -#: pod/completion/templates/video_caption_maker.html:133 +#: pod/completion/templates/video_caption_maker.html:163 msgid "New" msgstr "Nouveau" -#: pod/completion/templates/video_caption_maker.html:134 +#: pod/completion/templates/video_caption_maker.html:164 msgid "Override" msgstr "Remplacer" @@ -1660,22 +1730,22 @@ msgstr "" "Vous pouvez ajouter un fond opaque ou transparent au texte que vous voulez " "afficher avec l'option \"Afficher le fond\"" -#: pod/completion/views.py:50 pod/completion/views.py:115 -#: pod/completion/views.py:156 pod/completion/views.py:355 -#: pod/completion/views.py:547 pod/completion/views.py:790 +#: pod/completion/views.py:54 pod/completion/views.py:146 +#: pod/completion/views.py:187 pod/completion/views.py:386 +#: pod/completion/views.py:578 pod/completion/views.py:821 msgid "You cannot complement this video." msgstr "Vous ne pouvez pas compléter cette vidéo." -#: pod/completion/views.py:80 +#: pod/completion/views.py:111 msgid "The file has been saved." msgstr "Le fichier a été sauvegardé." -#: pod/completion/views.py:83 +#: pod/completion/views.py:114 msgid "The file has not been saved." msgstr "Le fichier n’a pas été enregistré." -#: pod/completion/views.py:263 pod/completion/views.py:452 -#: pod/completion/views.py:890 pod/podfile/views.py:492 +#: pod/completion/views.py:294 pod/completion/views.py:483 +#: pod/completion/views.py:921 pod/podfile/views.py:492 #: pod/podfile/views.py:536 pod/video/views.py:443 pod/video/views.py:1645 msgid "Please correct errors" msgstr "Veuillez corriger les erreurs" @@ -1755,8 +1825,8 @@ msgid "Image" msgstr "Image" #: pod/enrichment/models.py:152 -msgid "Integrate an document (PDF, text, html)" -msgstr "Intégrer un document (PDF, text, html)" +msgid "Integrate a document (PDF, text, html)" +msgstr "Intégrer un document (PDF, texte, html)" #: pod/enrichment/models.py:154 #: pod/enrichment/templates/enrichment/video_enrichment.html:140 @@ -1764,13 +1834,12 @@ msgid "Richtext" msgstr "Texte riche" #: pod/enrichment/models.py:157 -#: pod/enrichment/templates/enrichment/video_enrichment.html:142 -msgid "Embed" -msgstr "Intégrer" +msgid "Embed code" +msgstr "Code d’intégration" #: pod/enrichment/models.py:160 -msgid "Integrate an external source." -msgstr "Intégrer une source externe." +msgid "Paste here a code from an external source to embed it." +msgstr "Collez ici un code d’une source externe pour l’intégrer." #: pod/enrichment/models.py:165 msgid "Enrichments" @@ -1856,38 +1925,36 @@ msgstr "" "passer à un navigateur Web qui prend en charge la vidéo HTML5" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:61 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:78 msgid "Add a new enrichment" msgstr "Ajouter un nouvel enrichissement" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:66 -#: pod/enrichment/templates/enrichment/edit_enrichment.html:67 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:83 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:84 #: pod/video/templates/videos/add_video.html:59 #: pod/video/templates/videos/add_video.html:60 msgid "Back to video edit" msgstr "Retour à l'édition de la vidéo" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:69 -#: pod/enrichment/templates/enrichment/edit_enrichment.html:70 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:86 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:87 msgid "See the enrich video" msgstr "Voir la vidéo enrichie" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:80 -#: pod/enrichment/templates/enrichment/video_enrichment.html:132 -#: pod/interactive/templates/interactive/edit_interactive.html:113 -msgid "Informations" -msgstr "Informations" +#: pod/enrichment/templates/enrichment/edit_enrichment.html:97 +msgid "Editing enrichments" +msgstr "Éditer les enrichissements" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:84 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:101 #: pod/interactive/templates/interactive/edit_interactive.html:117 msgid "You can specify the group(s) of users who can access this page" msgstr "Spécifier des groupes d'utilisateur qui peuvent accéder à cette page" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:86 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:103 msgid "The title field is required and must contains from 2 to 100 characters." msgstr "Le champ de titre est requis et doit contenir de 2 à 100 caractères." -#: pod/enrichment/templates/enrichment/edit_enrichment.html:87 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:104 msgid "" "The fields \"Start\" and \"End\" must contain an indication value in " "seconds. Start playback of the video, pause the video and click on \"Get " @@ -1899,17 +1966,17 @@ msgstr "" "le temps depuis le lecteur\" pour renseigner automatiquement le champ \"Début" "\". Vous pouvez le faire également pour remplir le champ \"Fin\"." -#: pod/enrichment/templates/enrichment/edit_enrichment.html:88 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:105 msgid "You cannot overlap enrichments." msgstr "Vous ne pouvez faire des enrichissements qui se chevauchent." -#: pod/enrichment/templates/enrichment/edit_enrichment.html:89 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:106 msgid "You must save your enrichments to view the result." msgstr "Vous devez sauvegarder vos enrichissements pour voir le résultat." #: pod/enrichment/templates/enrichment/form_enrichment.html:6 -msgid "Create / Edit enrichments" -msgstr "Créer / Éditer des enrichissements" +msgid "Create / Edit enrichment" +msgstr "Créer / Éditer un enrichissement" #: pod/enrichment/templates/enrichment/group_enrichment.html:11 #: pod/enrichment/templates/enrichment/group_enrichment.html:14 @@ -2020,6 +2087,11 @@ msgstr "Ajouter une vidéo à une liste de lecture" msgid "My playlists" msgstr "Mes listes de lecture" +#: pod/enrichment/templates/enrichment/video_enrichment.html:132 +#: pod/interactive/templates/interactive/edit_interactive.html:113 +msgid "Informations" +msgstr "Informations" + #: pod/enrichment/templates/enrichment/video_enrichment.html:135 msgid "To help you, the different types of enrichments have specific colors:" msgstr "" @@ -2030,6 +2102,10 @@ msgstr "" msgid "Weblink" msgstr "Lien web" +#: pod/enrichment/templates/enrichment/video_enrichment.html:142 +msgid "Embed" +msgstr "Intégrer" + #: pod/enrichment/templates/enrichment/video_enrichment.html:145 msgid "They are visible on the video playback bar." msgstr "Ils sont visibles sur la barre de lecture de la vidéo." @@ -2469,64 +2545,64 @@ msgstr "L'identifiant de la vidéo n'est pas valide." msgid "Advanced options" msgstr "Options avancées" -#: pod/main/forms.py:12 +#: pod/main/forms.py:13 msgid "Request more information" msgstr "Demander plus d'informations" -#: pod/main/forms.py:13 +#: pod/main/forms.py:14 msgid "Learn more about how to contribute" msgstr "En savoir plus sur comment contribuer" -#: pod/main/forms.py:14 +#: pod/main/forms.py:15 msgid "Password request for a video" msgstr "Demande de mot de passe pour cette vidéo" -#: pod/main/forms.py:15 +#: pod/main/forms.py:16 msgid "Report inappropriate content" msgstr "Signaler un contenu inapproprié" -#: pod/main/forms.py:16 +#: pod/main/forms.py:17 msgid "Correction or bug report" msgstr "Correctif ou signalement de bug" -#: pod/main/forms.py:17 +#: pod/main/forms.py:18 msgid "Other (please specify)" msgstr "Autre (spécifiez)" -#: pod/main/forms.py:46 pod/podfile/models.py:25 pod/podfile/models.py:117 +#: pod/main/forms.py:50 pod/podfile/models.py:25 pod/podfile/models.py:117 #: pod/podfile/templates/podfile/home_content.html:32 pod/video/models.py:1366 #: pod/video/models.py:1437 pod/video/models.py:1498 msgid "Name" msgstr "Nom" -#: pod/main/forms.py:50 +#: pod/main/forms.py:54 msgid "Subject" msgstr "Sujet" -#: pod/main/forms.py:51 -msgid "Please choose a subjects related your request" +#: pod/main/forms.py:55 +msgid "Please choose a subject related to your request" msgstr "Veuillez choisir un sujet en lien avec votre requête" -#: pod/main/forms.py:58 pod/main/models.py:167 pod/playlist/models.py:26 +#: pod/main/forms.py:62 pod/main/models.py:167 pod/playlist/models.py:26 #: pod/video/forms.py:135 pod/video/forms.py:352 pod/video/forms.py:403 #: pod/video/models.py:274 pod/video/models.py:414 pod/video/models.py:642 #: pod/video/templates/channel/list_theme.html:10 msgid "Description" msgstr "Description" -#: pod/main/forms.py:59 +#: pod/main/forms.py:63 msgid "Provide a full description for your request" msgstr "Renseignez une description complète pour votre requête" -#: pod/main/forms.py:65 +#: pod/main/forms.py:69 msgid "Please indicate the result of the following operation" msgstr "Veuillez indiquer le résultat de l'opération suivante" -#: pod/main/forms.py:72 +#: pod/main/forms.py:76 msgid "Check this box if you are a metal human (required)" msgstr "Cocher cette case si vous êtes un humain en métal (obligatoire)" -#: pod/main/forms.py:91 +#: pod/main/forms.py:97 msgid "Please specify a subject" msgstr "Veuillez spécifier un sujet" @@ -3165,22 +3241,16 @@ msgid "Description of the configuration" msgstr "Description de la configuration" #: pod/main/models.py:175 -#, fuzzy -#| msgid "Name of the BBB meeting." msgid "Name of the tab" -msgstr "Nom de la session BBB." +msgstr "Nom de l’onglet" #: pod/main/models.py:181 -#, fuzzy -#| msgid "Additional owners" -msgid "Additional Channels Tab" -msgstr "Onglet de chaines additionel" +msgid "Additional channels Tab" +msgstr "Onglet additionnel de chaînes" #: pod/main/models.py:182 -#, fuzzy -#| msgid "Additional owners" -msgid "Additional Channel Tabs" -msgstr "Onglets de chaines additionnels" +msgid "Additional channel Tabs" +msgstr "Onglets additionnels de chaînes" #: pod/main/templates/403.html:4 pod/main/templates/403.html:9 #: pod/main/templates/403.html:14 @@ -3481,18 +3551,18 @@ msgstr "Types de vidéos" msgid "Use the input to filter user by last name." msgstr "Utiliser le champ pour filtrer les utilisateurs par nom de famille." -#: pod/main/views.py:186 +#: pod/main/tests/test_views.py:80 pod/main/views.py:291 +msgid "Your message has been sent." +msgstr "Votre message a été envoyé." + +#: pod/main/views.py:190 msgid "Link" msgstr "Lien" -#: pod/main/views.py:267 +#: pod/main/views.py:271 msgid "your message untitled" msgstr "votre message intitulé" -#: pod/main/views.py:287 -msgid "Your message have been sent." -msgstr "Votre message a été envoyé." - #: pod/playlist/models.py:24 #: pod/playlist/templates/playlist/playlist_element_list.html:12 #: pod/podfile/models.py:28 pod/video/admin.py:193 pod/video/models.py:623 @@ -3579,10 +3649,10 @@ msgstr "" #: pod/playlist/templates/my_playlists.html:28 msgid "" "A playlist with the eye symbol means that this playlist is visible to " -"authenticated users when they view this page." +"all users when they view this page." msgstr "" "Une liste de lecture avec un symbole œil signifie que cette liste est " -"visible aux utilisateurs authentifiés qui visiteront cette page." +"visible à tous les utilisateurs qui visiteront cette page." #: pod/playlist/templates/playlist.html:21 #: pod/playlist/templates/playlist/playlist_list.html:18 @@ -3812,7 +3882,7 @@ msgstr "" msgid "Shared folders" msgstr "Dossiers partagés" -#: pod/podfile/views.py:164 pod/podfile/views.py:572 +#: pod/podfile/views.py:164 pod/podfile/views.py:570 msgid "You cannot see this folder." msgstr "Vous ne pouvez pas voir ce dossier." @@ -4246,30 +4316,30 @@ msgstr "Pour supprimer la vidéo, veuillez cocher et cliquer sur envoyer." msgid "Agree required" msgstr "Accord requis" -#: pod/recorder/views.py:62 +#: pod/recorder/views.py:63 msgid "Recorder should be indicated." msgstr "L'enregistreur doit être indiqué." -#: pod/recorder/views.py:67 +#: pod/recorder/views.py:68 msgid "Recorder not found." msgstr "Enregistreur non trouvé." -#: pod/recorder/views.py:81 +#: pod/recorder/views.py:82 msgid "The selected record has been deleted." msgstr "L'enregistrement a été supprimé." -#: pod/recorder/views.py:115 +#: pod/recorder/views.py:116 msgid "Mediapath should be indicated." msgstr "La source du fichier doit être indiquée." -#: pod/recorder/views.py:138 +#: pod/recorder/views.py:139 msgid "" "Your publication is saved. Adding it to your videos will be in a few minutes." msgstr "" "Votre publication est sauvegardée, elle sera ajoutée à vos vidéos dans " "quelques minutes." -#: pod/recorder/views.py:215 +#: pod/recorder/views.py:223 #, python-format msgid "" "Hello, \n" @@ -4294,7 +4364,7 @@ msgstr "" "\n" "Cordialement" -#: pod/recorder/views.py:229 +#: pod/recorder/views.py:237 #, python-format msgid "" "Hello,

a new recording has just be added on %(title_site)s from the " @@ -4308,11 +4378,11 @@ msgstr "" "%(link_url)s
Si le lien n'est pas actif, il faut le copier-coller " "dans la barre d'adresse de votre navigateur.

Cordialement

" -#: pod/recorder/views.py:248 +#: pod/recorder/views.py:256 msgid "New recording added." msgstr "Nouvel enregistrement ajouté." -#: pod/recorder/views.py:331 +#: pod/recorder/views.py:339 msgid "The record has been deleted." msgstr "L’enregistrement a été supprimé." @@ -4722,16 +4792,14 @@ msgstr "" "Si coché, la chaîne apparaîtra dans la liste des chaînes de la plateforme." #: pod/video/models.py:340 -msgid "Select one or more groups who can upload video to this channel" +msgid "Select one or more groups who can upload video to this channel." msgstr "" -"Groupes : Sélectionnez un ou plusieurs groupes qui peuvent ajouter des " -"vidéos à cette chaîne." +"Sélectionnez un ou plusieurs groupes qui peuvent ajouter des vidéos à cette " +"chaîne." #: pod/video/models.py:343 -#, fuzzy -#| msgid "Additional owners" msgid "Additionals channels tab" -msgstr "Propriétaires additionels" +msgstr "Onglet additionnel de chaînes" #: pod/video/models.py:349 pod/video/models.py:433 #: pod/video_search/templates/search/search.html:124 @@ -5726,7 +5794,7 @@ msgstr "Ajouter une nouvelle vidéo" msgid "Delete the video" msgstr "Supprimer la vidéo" -#: pod/video/templates/videos/video_edit.html:115 +#: pod/video/templates/videos/video_edit.html:114 #: pod/video/templates/videos/video_record.html:77 msgid "Sending, please wait." msgstr "Envoi, veuillez patienter." @@ -6132,10 +6200,13 @@ msgstr "Recherche avancée" msgid "Remove this filter" msgstr "Retirer ce filtre" -#: pod/video_search/views.py:91 +#: pod/video_search/views.py:93 msgid "Sorry, video search is limited to 500 pages max." msgstr "Désolé, la recherche de vidéos est limitée à 500 pages maximum." +#~ msgid "Load Existing Caption File [optional]:" +#~ msgstr "Charger un fichier de sous-titres existant [facultatif] :" + #~ msgid "My BigBlueButton records and lives" #~ msgstr "Mes sessions et directs BigBlueButton" diff --git a/pod/locale/fr/LC_MESSAGES/djangojs.mo b/pod/locale/fr/LC_MESSAGES/djangojs.mo index ea5ed6983b..e7f3ecd828 100644 Binary files a/pod/locale/fr/LC_MESSAGES/djangojs.mo and b/pod/locale/fr/LC_MESSAGES/djangojs.mo differ diff --git a/pod/locale/fr/LC_MESSAGES/djangojs.po b/pod/locale/fr/LC_MESSAGES/djangojs.po index 57d99f5534..016d01d462 100644 --- a/pod/locale/fr/LC_MESSAGES/djangojs.po +++ b/pod/locale/fr/LC_MESSAGES/djangojs.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: Esup-Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-24 10:13+0200\n" +"POT-Creation-Date: 2021-10-14 19:18+0000\n" "PO-Revision-Date: 2021-03-26 17:58+0100\n" "Last-Translator: obado \n" "Language-Team: \n" @@ -55,6 +55,10 @@ msgstr "Le formulaire ne peut pas être récupéré." msgid "You are no longer authenticated. Please log in again." msgstr "Vous n'êtes plus authentifié. Veuillez vous reconnectez." +#: pod/playlist/static/js/playlist.js:168 +msgid "The video can not be added from this page." +msgstr "La vidéo ne peut être ajoutée depuis cette page" + #: pod/chapter/static/js/chapters.js:199 #: pod/enrichment/static/js/enrichment.js:193 pod/main/static/js/main.js:415 #: pod/main/static/js/main.js:501 @@ -96,22 +100,50 @@ msgstr "" "temps début(00:00.000) --> temps fin(00:00.000)\n" "texte de sous-titre" -#: pod/completion/static/js/caption_maker.js:41 +#: pod/completion/static/js/caption_maker.js:42 +#: pod/completion/static/js/caption_maker.js:740 +msgid "Unrecognized caption file format." +msgstr "Format de fichier de traduction non reconnu" + +#: pod/completion/static/js/caption_maker.js:54 msgid "There is no captions to save" msgstr "Il n’y a aucun sous-titre à sauvegarder" -#: pod/completion/static/js/caption_maker.js:90 +#: pod/completion/static/js/caption_maker.js:85 +#: pod/completion/static/js/caption_maker.js:754 +msgid "Not a valid time track file." +msgstr "Fichier de traduction invalide" + +#: pod/completion/static/js/caption_maker.js:106 msgid "error during exchange" msgstr "erreur durant le téléversement" -#: pod/completion/static/js/caption_maker.js:94 +#: pod/completion/static/js/caption_maker.js:110 msgid "no data could be stored." msgstr "aucune donnée ne peut être stockée." -#: pod/completion/static/js/caption_maker.js:134 +#: pod/completion/static/js/caption_maker.js:162 msgid "Are you sure you want to delete all caption?" msgstr "Êtes-vous sûr(e) de vouloir supprimer les sous-titre ?" +#: pod/completion/static/js/caption_maker.js:713 +msgid "Error reading caption file. Code = " +msgstr "Erreur durant la lecture du fichier de traduction, Code = " + +#: pod/completion/static/js/caption_maker.js:719 +msgid "Exception thrown reading caption file. Code = " +msgstr "Une exception a été levée durant la lecture du fichier. Code = " + +#: pod/completion/static/js/caption_maker.js:722 +msgid "Your browser does not support FileReader." +msgstr "Votre navigateur ne supporte pas FileReader" + +#: pod/completion/static/js/caption_maker.js:729 +#, fuzzy +#| msgid "Error during exchange" +msgid "Error loading caption file: " +msgstr "Erreur durant le téléversement" + #: pod/completion/static/js/completion.js:175 #: pod/podfile/static/podfile/js/filewidget.js:277 msgid "Are you sure you want to delete this file?" @@ -368,11 +400,13 @@ msgid "Are you sure you want to delete this element?" msgstr "Êtes-vous sûr(e) de vouloir supprimer cet élément ?" #: pod/main/static/js/main.js:454 +#: pod/podfile/static/podfile/js/filewidget.js:114 #: pod/podfile/static/podfile/js/filewidget.js:391 msgid "Error during exchange" msgstr "Erreur durant le téléversement" #: pod/main/static/js/main.js:458 +#: pod/podfile/static/podfile/js/filewidget.js:114 msgid "No data could be stored." msgstr "Aucune donnée ne peut être stockée." @@ -431,6 +465,10 @@ msgstr "Changer" msgid "Enter new name of folder" msgstr "Indiquer un nouveau nom au dossier" +#: pod/podfile/static/podfile/js/filewidget.js:167 +msgid "Remove" +msgstr "Retirer" + #: pod/podfile/static/podfile/js/filewidget.js:180 #: pod/podfile/static/podfile/js/filewidget.js:202 #: pod/podfile/static/podfile/js/filewidget.js:235 @@ -450,15 +488,15 @@ msgstr "Êtes-vous sûr(e) de vouloir supprimer ce dossier ?" msgid "See more" msgstr "Voir plus" -#: pod/video/static/js/change_video_owner.js:117 +#: pod/video/static/js/change_video_owner.js:104 msgid "No element found" msgstr "Aucun élément trouvé" -#: pod/video/static/js/change_video_owner.js:717 +#: pod/video/static/js/change_video_owner.js:637 msgid "An error occurred during the change of owner" msgstr "Une erreur s'est produite lors du changement de propriétaire" -#: pod/video/static/js/change_video_owner.js:730 +#: pod/video/static/js/change_video_owner.js:648 msgid "Please complete all fields correctly" msgstr "Veuillez remplir tous les champs correctement" @@ -504,6 +542,10 @@ msgstr "Répondre" msgid "Remove this comment" msgstr "Supprimer ce commentaire" +#: pod/video/static/js/comment-script.js:259 +msgid "Add a public comment" +msgstr "Ajouter un commentaire public" + #: pod/video/static/js/comment-script.js:383 msgid "Show answers" msgstr "Afficher les réponses" @@ -513,6 +555,7 @@ msgid "Comment has been deleted successfully." msgstr "Commentaire a été supprimé avec succès." #: pod/video/static/js/regroup_videos_by_theme.js:51 +#: pod/video/static/js/video_category.js:530 msgid "This content is password protected." msgstr "Ce contenu est protégé par mot de passe." @@ -526,11 +569,38 @@ msgstr "Ce contenu est chapitré." msgid "This content is in draft." msgstr "Ce contenu est en brouillon." +#: pod/video/static/js/regroup_videos_by_theme.js:76 +#: pod/video/static/js/video_category.js:436 +#: pod/video/static/js/video_category.js:555 +msgid "Video content." +msgstr "Contenu vidéo." + #: pod/video/static/js/regroup_videos_by_theme.js:81 +#: pod/video/static/js/video_category.js:437 #: pod/video/static/js/video_category.js:560 msgid "Audio content." msgstr "Contenu audio." +#: pod/video/static/js/regroup_videos_by_theme.js:86 +#: pod/video/static/js/video_category.js:565 +msgid "Edit the video" +msgstr "Éditer la vidéo" + +#: pod/video/static/js/regroup_videos_by_theme.js:87 +#: pod/video/static/js/video_category.js:566 +msgid "Complete the video" +msgstr "Compléter la vidéo" + +#: pod/video/static/js/regroup_videos_by_theme.js:88 +#: pod/video/static/js/video_category.js:567 +msgid "Chapter the video" +msgstr "Chapitrer la vidéo" + +#: pod/video/static/js/regroup_videos_by_theme.js:89 +#: pod/video/static/js/video_category.js:568 +msgid "Delete the video" +msgstr "Supprimer la vidéo" + #: pod/video/static/js/regroup_videos_by_theme.js:270 msgid "Loading videos.." msgstr "Chargement videos.." @@ -584,6 +654,14 @@ msgstr "Éditer la catégorie" msgid "Delete the category" msgstr "Supprimer la catégorie" +#: pod/video/static/js/video_category.js:636 +msgid "Success.." +msgstr "Succès.." + +#: pod/video/static/js/video_category.js:637 +msgid "Error.." +msgstr "Erreur.." + #: pod/video/static/js/video_category.js:907 msgid "Category created successfully" msgstr "Catégorie créée avec succès" @@ -615,30 +693,3 @@ msgstr "Vue totale depuis création" #: pod/video/static/js/video_stats_view.js:24 msgid "Slug" msgstr "Titre court" - -#~ msgid "Remove" -#~ msgstr "Retirer" - -#~ msgid "Add a public comment" -#~ msgstr "Ajouter un commentaire public" - -#~ msgid "Video content." -#~ msgstr "Contenu vidéo." - -#~ msgid "Edit the video" -#~ msgstr "Éditer la vidéo" - -#~ msgid "Complete the video" -#~ msgstr "Compléter la vidéo" - -#~ msgid "Chapter the video" -#~ msgstr "Chapitrer la vidéo" - -#~ msgid "Delete the video" -#~ msgstr "Supprimer la vidéo" - -#~ msgid "Success.." -#~ msgstr "Succès.." - -#~ msgid "Error.." -#~ msgstr "Erreur.." diff --git a/pod/locale/nl/LC_MESSAGES/django.mo b/pod/locale/nl/LC_MESSAGES/django.mo index 6cd02ab317..5f4127dddb 100644 Binary files a/pod/locale/nl/LC_MESSAGES/django.mo and b/pod/locale/nl/LC_MESSAGES/django.mo differ diff --git a/pod/locale/nl/LC_MESSAGES/django.po b/pod/locale/nl/LC_MESSAGES/django.po index 4788304057..b3fa8a2d61 100644 --- a/pod/locale/nl/LC_MESSAGES/django.po +++ b/pod/locale/nl/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-09-16 11:50+0000\n" +"POT-Creation-Date: 2021-10-17 19:30+0000\n" "PO-Revision-Date: 2021-01-22 12:27+0100\n" "Last-Translator: obado \n" "Language-Team: \n" @@ -16,7 +16,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.4.2\n" -#: pod/authentication/admin.py:93 pod/main/forms.py:47 +#: pod/authentication/admin.py:93 pod/main/forms.py:51 msgid "Email" msgstr "E-mail" @@ -147,18 +147,18 @@ msgid "Change your picture" msgstr "" #: pod/authentication/templates/userpicture/userpicture.html:29 -#: pod/authentication/views.py:111 +#: pod/authentication/views.py:130 #: pod/bbb/templates/bbb/live_publish_meeting.html:45 #: pod/bbb/templates/bbb/publish_meeting.html:37 pod/bbb/views.py:127 -#: pod/bbb/views.py:254 pod/completion/templates/video_caption_maker.html:56 +#: pod/bbb/views.py:254 pod/completion/templates/video_caption_maker.html:96 #: pod/enrichment/templates/enrichment/group_enrichment.html:29 #: pod/interactive/templates/interactive/group_interactive.html:27 #: pod/live/templates/live/live-form.html:10 -#: pod/main/templates/contact_us.html:20 pod/main/views.py:296 +#: pod/main/templates/contact_us.html:20 pod/main/views.py:297 #: pod/playlist/views.py:136 #: pod/recorder/templates/recorder/add_recording.html:36 #: pod/recorder/templates/recorder/record_delete.html:31 -#: pod/recorder/views.py:145 pod/recorder/views.py:338 +#: pod/recorder/views.py:146 pod/recorder/views.py:346 #: pod/video/templates/channel/channel_edit.html:47 #: pod/video/templates/videos/video-form.html:10 #: pod/video/templates/videos/video_delete.html:32 @@ -177,7 +177,7 @@ msgstr "" #: pod/authentication/templates/userpicture/userpicture.html:42 #: pod/bbb/templates/bbb/live_publish_meeting.html:73 #: pod/bbb/templates/bbb/publish_meeting.html:65 -#: pod/completion/templates/video_caption_maker.html:68 +#: pod/completion/templates/video_caption_maker.html:104 #: pod/enrichment/templates/enrichment/group_enrichment.html:51 #: pod/interactive/templates/interactive/group_interactive.html:49 #: pod/live/templates/live/live-form.html:25 @@ -758,6 +758,7 @@ msgid "Chapter" msgstr "" #: pod/chapter/models.py:35 pod/chapter/templates/video_chapter.html:67 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:50 #: pod/enrichment/templates/enrichment/video_enrichment-iframe.html:35 #: pod/enrichment/templates/enrichment/video_enrichment.html:39 #: pod/video/templates/videos/video-element.html:37 @@ -787,14 +788,14 @@ msgstr "" #: pod/chapter/templates/chapter/form_chapter.html:12 #: pod/chapter/templates/chapter/form_chapter.html:43 -#: pod/enrichment/templates/enrichment/form_enrichment.html:12 +#: pod/enrichment/templates/enrichment/form_enrichment.html:13 #: pod/video/templates/channel/form_theme.html:11 msgid "One or more errors have been found in the form:" msgstr "" #: pod/chapter/templates/chapter/form_chapter.html:30 -#: pod/completion/templates/video_caption_maker.html:94 -#: pod/enrichment/templates/enrichment/form_enrichment.html:30 +#: pod/completion/templates/video_caption_maker.html:77 +#: pod/enrichment/templates/enrichment/form_enrichment.html:37 #: pod/enrichment/templates/enrichment/group_enrichment.html:60 #: pod/interactive/templates/interactive/group_interactive.html:58 #: pod/playlist/templates/playlist.html:69 @@ -808,7 +809,7 @@ msgid "Save" msgstr "" #: pod/chapter/templates/chapter/form_chapter.html:31 -#: pod/enrichment/templates/enrichment/form_enrichment.html:31 +#: pod/enrichment/templates/enrichment/form_enrichment.html:38 #: pod/video/templates/channel/form_theme.html:47 #: pod/video/templates/videos/category_modal.html:45 #: pod/video/templates/videos/category_modal.html:65 @@ -831,7 +832,7 @@ msgstr "" #: pod/completion/models.py:251 #: pod/completion/templates/overlay/list_overlay.html:10 #: pod/enrichment/templates/enrichment/list_enrichment.html:10 -#: pod/main/models.py:121 pod/main/views.py:184 pod/playlist/models.py:12 +#: pod/main/models.py:121 pod/main/views.py:185 pod/playlist/models.py:12 #: pod/playlist/templates/playlist/playlist_element_list.html:11 #: pod/video/models.py:254 pod/video/models.py:396 pod/video/models.py:518 #: pod/video/models.py:599 pod/video/templates/channel/list_theme.html:9 @@ -895,7 +896,7 @@ msgid "My videos" msgstr "" #: pod/chapter/templates/video_chapter.html:42 -#: pod/completion/templates/video_caption_maker.html:114 +#: pod/completion/templates/video_caption_maker.html:144 #: pod/video/templates/videos/video_collaborate.html:66 #: pod/video/templates/videos/video_delete.html:20 #: pod/video/templates/videos/video_edit.html:38 @@ -1056,7 +1057,7 @@ msgstr "" #: pod/completion/models.py:124 pod/completion/models.py:171 #: pod/completion/models.py:250 -#: pod/completion/templates/video_caption_maker.html:84 +#: pod/completion/templates/video_caption_maker.html:67 #: pod/enrichment/models.py:322 pod/enrichment/models.py:356 #: pod/interactive/models.py:18 pod/interactive/models.py:48 #: pod/playlist/models.py:85 pod/recorder/models.py:90 pod/video/models.py:593 @@ -1384,27 +1385,27 @@ msgstr "" msgid "Video Caption Maker" msgstr "" -#: pod/completion/templates/video_caption_maker.html:52 -msgid "Load Existing Caption File [optional]:" +#: pod/completion/templates/video_caption_maker.html:33 +msgid "Change mode" msgstr "" -#: pod/completion/templates/video_caption_maker.html:92 +#: pod/completion/templates/video_caption_maker.html:75 msgid "Play" msgstr "" -#: pod/completion/templates/video_caption_maker.html:93 +#: pod/completion/templates/video_caption_maker.html:76 msgid "Pause" msgstr "" -#: pod/completion/templates/video_caption_maker.html:95 +#: pod/completion/templates/video_caption_maker.html:78 msgid "Save & Continue" msgstr "" -#: pod/completion/templates/video_caption_maker.html:99 +#: pod/completion/templates/video_caption_maker.html:82 msgid "Caption list" msgstr "" -#: pod/completion/templates/video_caption_maker.html:99 +#: pod/completion/templates/video_caption_maker.html:82 msgid "" "Use the Play and Pause buttons to determine when the subtitles appear, enter " "the text in the field below the video then click the Save / (Save & " @@ -1412,31 +1413,99 @@ msgid "" "Subtitles button to create a subtitle file." msgstr "" -#: pod/completion/templates/video_caption_maker.html:106 +#: pod/completion/templates/video_caption_maker.html:85 +msgid "No captions" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:88 +msgid "Add subtitle" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:92 +msgid "You can load and existing caption file below :" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:117 msgid "Save Captions" msgstr "" -#: pod/completion/templates/video_caption_maker.html:107 +#: pod/completion/templates/video_caption_maker.html:118 msgid "Clear All" msgstr "" -#: pod/completion/templates/video_caption_maker.html:115 +#: pod/completion/templates/video_caption_maker.html:126 +msgid "Key Schortcuts" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:128 +msgid "Video Player" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:129 +msgid "Space" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:129 +msgid "Pause / unpause" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:130 +msgid "Rewind the video 10 seconds back" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:131 +msgid "Skip 10 seconds" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:132 +msgid "Mute/unmute video" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:134 +msgid "Captions Editor" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:135 +msgid "Select previous caption" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:136 +msgid "Select next caption" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:137 +msgid "Del" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:137 +msgid "Delete selected caption" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:138 +msgid "Add new caption" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:140 +msgid "Show/hide this window" +msgstr "" + +#: pod/completion/templates/video_caption_maker.html:145 msgid "Back to the completion" msgstr "" -#: pod/completion/templates/video_caption_maker.html:126 +#: pod/completion/templates/video_caption_maker.html:156 msgid "Save captions file." msgstr "" -#: pod/completion/templates/video_caption_maker.html:130 +#: pod/completion/templates/video_caption_maker.html:160 msgid "You have loaded a file. Do you want to override it?" msgstr "" -#: pod/completion/templates/video_caption_maker.html:133 +#: pod/completion/templates/video_caption_maker.html:163 msgid "New" msgstr "" -#: pod/completion/templates/video_caption_maker.html:134 +#: pod/completion/templates/video_caption_maker.html:164 msgid "Override" msgstr "" @@ -1568,22 +1637,22 @@ msgid "" "want to display with the option \"Show background\"" msgstr "" -#: pod/completion/views.py:50 pod/completion/views.py:115 -#: pod/completion/views.py:156 pod/completion/views.py:355 -#: pod/completion/views.py:547 pod/completion/views.py:790 +#: pod/completion/views.py:54 pod/completion/views.py:146 +#: pod/completion/views.py:187 pod/completion/views.py:386 +#: pod/completion/views.py:578 pod/completion/views.py:821 msgid "You cannot complement this video." msgstr "" -#: pod/completion/views.py:80 +#: pod/completion/views.py:111 msgid "The file has been saved." msgstr "" -#: pod/completion/views.py:83 +#: pod/completion/views.py:114 msgid "The file has not been saved." msgstr "" -#: pod/completion/views.py:263 pod/completion/views.py:452 -#: pod/completion/views.py:890 pod/podfile/views.py:492 +#: pod/completion/views.py:294 pod/completion/views.py:483 +#: pod/completion/views.py:921 pod/podfile/views.py:492 #: pod/podfile/views.py:536 pod/video/views.py:443 pod/video/views.py:1645 msgid "Please correct errors" msgstr "" @@ -1663,7 +1732,7 @@ msgid "Image" msgstr "" #: pod/enrichment/models.py:152 -msgid "Integrate an document (PDF, text, html)" +msgid "Integrate a document (PDF, text, html)" msgstr "" #: pod/enrichment/models.py:154 @@ -1672,12 +1741,11 @@ msgid "Richtext" msgstr "" #: pod/enrichment/models.py:157 -#: pod/enrichment/templates/enrichment/video_enrichment.html:142 -msgid "Embed" +msgid "Embed code" msgstr "" #: pod/enrichment/models.py:160 -msgid "Integrate an external source." +msgid "Paste here a code from an external source to embed it." msgstr "" #: pod/enrichment/models.py:165 @@ -1757,38 +1825,36 @@ msgid "" "\"_blank\">supports HTML5 video" msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:61 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:78 msgid "Add a new enrichment" msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:66 -#: pod/enrichment/templates/enrichment/edit_enrichment.html:67 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:83 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:84 #: pod/video/templates/videos/add_video.html:59 #: pod/video/templates/videos/add_video.html:60 msgid "Back to video edit" msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:69 -#: pod/enrichment/templates/enrichment/edit_enrichment.html:70 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:86 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:87 msgid "See the enrich video" msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:80 -#: pod/enrichment/templates/enrichment/video_enrichment.html:132 -#: pod/interactive/templates/interactive/edit_interactive.html:113 -msgid "Informations" +#: pod/enrichment/templates/enrichment/edit_enrichment.html:97 +msgid "Editing enrichments" msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:84 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:101 #: pod/interactive/templates/interactive/edit_interactive.html:117 msgid "You can specify the group(s) of users who can access this page" msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:86 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:103 msgid "The title field is required and must contains from 2 to 100 characters." msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:87 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:104 msgid "" "The fields \"Start\" and \"End\" must contain an indication value in " "seconds. Start playback of the video, pause the video and click on \"Get " @@ -1796,16 +1862,16 @@ msgid "" "same to fill in the field untitled \"End\"." msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:88 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:105 msgid "You cannot overlap enrichments." msgstr "" -#: pod/enrichment/templates/enrichment/edit_enrichment.html:89 +#: pod/enrichment/templates/enrichment/edit_enrichment.html:106 msgid "You must save your enrichments to view the result." msgstr "" #: pod/enrichment/templates/enrichment/form_enrichment.html:6 -msgid "Create / Edit enrichments" +msgid "Create / Edit enrichment" msgstr "" #: pod/enrichment/templates/enrichment/group_enrichment.html:11 @@ -1917,6 +1983,11 @@ msgstr "" msgid "My playlists" msgstr "" +#: pod/enrichment/templates/enrichment/video_enrichment.html:132 +#: pod/interactive/templates/interactive/edit_interactive.html:113 +msgid "Informations" +msgstr "" + #: pod/enrichment/templates/enrichment/video_enrichment.html:135 msgid "To help you, the different types of enrichments have specific colors:" msgstr "" @@ -1925,6 +1996,10 @@ msgstr "" msgid "Weblink" msgstr "" +#: pod/enrichment/templates/enrichment/video_enrichment.html:142 +msgid "Embed" +msgstr "" + #: pod/enrichment/templates/enrichment/video_enrichment.html:145 msgid "They are visible on the video playback bar." msgstr "" @@ -2340,64 +2415,64 @@ msgstr "" msgid "Advanced options" msgstr "" -#: pod/main/forms.py:12 +#: pod/main/forms.py:13 msgid "Request more information" msgstr "" -#: pod/main/forms.py:13 +#: pod/main/forms.py:14 msgid "Learn more about how to contribute" msgstr "" -#: pod/main/forms.py:14 +#: pod/main/forms.py:15 msgid "Password request for a video" msgstr "" -#: pod/main/forms.py:15 +#: pod/main/forms.py:16 msgid "Report inappropriate content" msgstr "" -#: pod/main/forms.py:16 +#: pod/main/forms.py:17 msgid "Correction or bug report" msgstr "" -#: pod/main/forms.py:17 +#: pod/main/forms.py:18 msgid "Other (please specify)" msgstr "" -#: pod/main/forms.py:46 pod/podfile/models.py:25 pod/podfile/models.py:117 +#: pod/main/forms.py:50 pod/podfile/models.py:25 pod/podfile/models.py:117 #: pod/podfile/templates/podfile/home_content.html:32 pod/video/models.py:1366 #: pod/video/models.py:1437 pod/video/models.py:1498 msgid "Name" msgstr "" -#: pod/main/forms.py:50 +#: pod/main/forms.py:54 msgid "Subject" msgstr "" -#: pod/main/forms.py:51 -msgid "Please choose a subjects related your request" +#: pod/main/forms.py:55 +msgid "Please choose a subject related to your request" msgstr "" -#: pod/main/forms.py:58 pod/main/models.py:167 pod/playlist/models.py:26 +#: pod/main/forms.py:62 pod/main/models.py:167 pod/playlist/models.py:26 #: pod/video/forms.py:135 pod/video/forms.py:352 pod/video/forms.py:403 #: pod/video/models.py:274 pod/video/models.py:414 pod/video/models.py:642 #: pod/video/templates/channel/list_theme.html:10 msgid "Description" msgstr "" -#: pod/main/forms.py:59 +#: pod/main/forms.py:63 msgid "Provide a full description for your request" msgstr "" -#: pod/main/forms.py:65 +#: pod/main/forms.py:69 msgid "Please indicate the result of the following operation" msgstr "" -#: pod/main/forms.py:72 +#: pod/main/forms.py:76 msgid "Check this box if you are a metal human (required)" msgstr "" -#: pod/main/forms.py:91 +#: pod/main/forms.py:97 msgid "Please specify a subject" msgstr "" @@ -3040,11 +3115,11 @@ msgid "Name of the tab" msgstr "" #: pod/main/models.py:181 -msgid "Additional Channels Tab" +msgid "Additional channels Tab" msgstr "" #: pod/main/models.py:182 -msgid "Additional Channel Tabs" +msgid "Additional channel Tabs" msgstr "" #: pod/main/templates/403.html:4 pod/main/templates/403.html:9 @@ -3341,16 +3416,16 @@ msgstr "" msgid "Use the input to filter user by last name." msgstr "" -#: pod/main/views.py:186 -msgid "Link" +#: pod/main/tests/test_views.py:80 pod/main/views.py:291 +msgid "Your message has been sent." msgstr "" -#: pod/main/views.py:267 -msgid "your message untitled" +#: pod/main/views.py:190 +msgid "Link" msgstr "" -#: pod/main/views.py:287 -msgid "Your message have been sent." +#: pod/main/views.py:271 +msgid "your message untitled" msgstr "" #: pod/playlist/models.py:24 @@ -3660,7 +3735,7 @@ msgstr "" msgid "Shared folders" msgstr "" -#: pod/podfile/views.py:164 pod/podfile/views.py:572 +#: pod/podfile/views.py:164 pod/podfile/views.py:570 msgid "You cannot see this folder." msgstr "" @@ -3989,10 +4064,8 @@ msgid "Has this recording file require a manual claim by a user?" msgstr "" #: pod/recorder/models.py:373 -#, fuzzy -#| msgid "Email" msgid "Email sent?" -msgstr "E-mail" +msgstr "" #: pod/recorder/models.py:375 msgid "Has an email been sent to the manager of the concerned recorder?" @@ -4064,28 +4137,28 @@ msgstr "" msgid "Agree required" msgstr "" -#: pod/recorder/views.py:62 +#: pod/recorder/views.py:63 msgid "Recorder should be indicated." msgstr "" -#: pod/recorder/views.py:67 +#: pod/recorder/views.py:68 msgid "Recorder not found." msgstr "" -#: pod/recorder/views.py:81 +#: pod/recorder/views.py:82 msgid "The selected record has been deleted." msgstr "" -#: pod/recorder/views.py:115 +#: pod/recorder/views.py:116 msgid "Mediapath should be indicated." msgstr "" -#: pod/recorder/views.py:138 +#: pod/recorder/views.py:139 msgid "" "Your publication is saved. Adding it to your videos will be in a few minutes." msgstr "" -#: pod/recorder/views.py:215 +#: pod/recorder/views.py:223 #, python-format msgid "" "Hello, \n" @@ -4100,7 +4173,7 @@ msgid "" "Regards" msgstr "" -#: pod/recorder/views.py:229 +#: pod/recorder/views.py:237 #, python-format msgid "" "Hello,

a new recording has just be added on %(title_site)s from the " @@ -4109,11 +4182,11 @@ msgid "" "just copy-paste it in your browser.

Regards

" msgstr "" -#: pod/recorder/views.py:248 +#: pod/recorder/views.py:256 msgid "New recording added." msgstr "" -#: pod/recorder/views.py:331 +#: pod/recorder/views.py:339 msgid "The record has been deleted." msgstr "" @@ -4456,7 +4529,7 @@ msgid "" msgstr "" #: pod/video/models.py:340 -msgid "Select one or more groups who can upload video to this channel" +msgid "Select one or more groups who can upload video to this channel." msgstr "" #: pod/video/models.py:343 @@ -5413,7 +5486,7 @@ msgstr "" msgid "Delete the video" msgstr "" -#: pod/video/templates/videos/video_edit.html:115 +#: pod/video/templates/videos/video_edit.html:114 #: pod/video/templates/videos/video_record.html:77 msgid "Sending, please wait." msgstr "" @@ -5806,7 +5879,7 @@ msgstr "" msgid "Remove this filter" msgstr "" -#: pod/video_search/views.py:91 +#: pod/video_search/views.py:93 msgid "Sorry, video search is limited to 500 pages max." msgstr "" diff --git a/pod/locale/nl/LC_MESSAGES/djangojs.mo b/pod/locale/nl/LC_MESSAGES/djangojs.mo index 2e4dc31b55..23f46f056c 100644 Binary files a/pod/locale/nl/LC_MESSAGES/djangojs.mo and b/pod/locale/nl/LC_MESSAGES/djangojs.mo differ diff --git a/pod/locale/nl/LC_MESSAGES/djangojs.po b/pod/locale/nl/LC_MESSAGES/djangojs.po index 4c378383df..0a92bb8e39 100644 --- a/pod/locale/nl/LC_MESSAGES/djangojs.po +++ b/pod/locale/nl/LC_MESSAGES/djangojs.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: Esup-Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-24 10:13+0200\n" +"POT-Creation-Date: 2021-10-14 19:18+0000\n" "PO-Revision-Date: 2021-01-22 12:27+0100\n" "Last-Translator: obado \n" "Language-Team: \n" @@ -92,22 +92,48 @@ msgid "" "caption text" msgstr "" -#: pod/completion/static/js/caption_maker.js:41 +#: pod/completion/static/js/caption_maker.js:42 +#: pod/completion/static/js/caption_maker.js:740 +msgid "Unrecognized caption file format." +msgstr "" + +#: pod/completion/static/js/caption_maker.js:54 msgid "There is no captions to save" msgstr "" -#: pod/completion/static/js/caption_maker.js:90 +#: pod/completion/static/js/caption_maker.js:85 +#: pod/completion/static/js/caption_maker.js:754 +msgid "Not a valid time track file." +msgstr "" + +#: pod/completion/static/js/caption_maker.js:106 msgid "error during exchange" msgstr "" -#: pod/completion/static/js/caption_maker.js:94 +#: pod/completion/static/js/caption_maker.js:110 msgid "no data could be stored." msgstr "" -#: pod/completion/static/js/caption_maker.js:134 +#: pod/completion/static/js/caption_maker.js:162 msgid "Are you sure you want to delete all caption?" msgstr "" +#: pod/completion/static/js/caption_maker.js:713 +msgid "Error reading caption file. Code = " +msgstr "" + +#: pod/completion/static/js/caption_maker.js:719 +msgid "Exception thrown reading caption file. Code = " +msgstr "" + +#: pod/completion/static/js/caption_maker.js:722 +msgid "Your browser does not support FileReader." +msgstr "" + +#: pod/completion/static/js/caption_maker.js:729 +msgid "Error loading caption file: " +msgstr "" + #: pod/completion/static/js/completion.js:175 #: pod/podfile/static/podfile/js/filewidget.js:277 msgid "Are you sure you want to delete this file?" @@ -360,11 +386,13 @@ msgid "Are you sure you want to delete this element?" msgstr "" #: pod/main/static/js/main.js:454 +#: pod/podfile/static/podfile/js/filewidget.js:114 #: pod/podfile/static/podfile/js/filewidget.js:391 msgid "Error during exchange" msgstr "" #: pod/main/static/js/main.js:458 +#: pod/podfile/static/podfile/js/filewidget.js:114 msgid "No data could be stored." msgstr "" @@ -421,6 +449,10 @@ msgstr "" msgid "Enter new name of folder" msgstr "" +#: pod/podfile/static/podfile/js/filewidget.js:167 +msgid "Remove" +msgstr "" + #: pod/podfile/static/podfile/js/filewidget.js:180 #: pod/podfile/static/podfile/js/filewidget.js:202 #: pod/podfile/static/podfile/js/filewidget.js:235 @@ -440,15 +472,15 @@ msgstr "" msgid "See more" msgstr "" -#: pod/video/static/js/change_video_owner.js:117 +#: pod/video/static/js/change_video_owner.js:104 msgid "No element found" msgstr "" -#: pod/video/static/js/change_video_owner.js:717 +#: pod/video/static/js/change_video_owner.js:637 msgid "An error occurred during the change of owner" msgstr "" -#: pod/video/static/js/change_video_owner.js:730 +#: pod/video/static/js/change_video_owner.js:648 msgid "Please complete all fields correctly" msgstr "" @@ -494,6 +526,10 @@ msgstr "" msgid "Remove this comment" msgstr "" +#: pod/video/static/js/comment-script.js:259 +msgid "Add a public comment" +msgstr "" + #: pod/video/static/js/comment-script.js:383 msgid "Show answers" msgstr "" @@ -503,6 +539,7 @@ msgid "Comment has been deleted successfully." msgstr "" #: pod/video/static/js/regroup_videos_by_theme.js:51 +#: pod/video/static/js/video_category.js:530 msgid "This content is password protected." msgstr "" @@ -516,11 +553,38 @@ msgstr "" msgid "This content is in draft." msgstr "" +#: pod/video/static/js/regroup_videos_by_theme.js:76 +#: pod/video/static/js/video_category.js:436 +#: pod/video/static/js/video_category.js:555 +msgid "Video content." +msgstr "" + #: pod/video/static/js/regroup_videos_by_theme.js:81 +#: pod/video/static/js/video_category.js:437 #: pod/video/static/js/video_category.js:560 msgid "Audio content." msgstr "" +#: pod/video/static/js/regroup_videos_by_theme.js:86 +#: pod/video/static/js/video_category.js:565 +msgid "Edit the video" +msgstr "" + +#: pod/video/static/js/regroup_videos_by_theme.js:87 +#: pod/video/static/js/video_category.js:566 +msgid "Complete the video" +msgstr "" + +#: pod/video/static/js/regroup_videos_by_theme.js:88 +#: pod/video/static/js/video_category.js:567 +msgid "Chapter the video" +msgstr "" + +#: pod/video/static/js/regroup_videos_by_theme.js:89 +#: pod/video/static/js/video_category.js:568 +msgid "Delete the video" +msgstr "" + #: pod/video/static/js/regroup_videos_by_theme.js:270 msgid "Loading videos.." msgstr "" @@ -573,6 +637,14 @@ msgstr "" msgid "Delete the category" msgstr "" +#: pod/video/static/js/video_category.js:636 +msgid "Success.." +msgstr "" + +#: pod/video/static/js/video_category.js:637 +msgid "Error.." +msgstr "" + #: pod/video/static/js/video_category.js:907 msgid "Category created successfully" msgstr "" diff --git a/pod/main/forms.py b/pod/main/forms.py index f25a2567f4..9c994a9a18 100644 --- a/pod/main/forms.py +++ b/pod/main/forms.py @@ -1,3 +1,4 @@ +"""Esup-Pod forms handling.""" from django import forms from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ @@ -20,6 +21,7 @@ def add_placeholder_and_asterisk(fields): + """Add placeholder and asterisk to specified fields.""" for myField in fields: classname = fields[myField].widget.__class__.__name__ if classname == "PasswordInput" or classname == "TextInput": @@ -43,12 +45,14 @@ def add_placeholder_and_asterisk(fields): class ContactUsForm(forms.Form): + """Manage "Contact us" form.""" + name = forms.CharField(label=_("Name"), required=True, max_length=512) email = forms.EmailField(label=_("Email"), required=True) subject = forms.ChoiceField( label=_("Subject"), - help_text=_("Please choose a subjects related your request"), + help_text=_("Please choose a subject related to your request"), required=True, choices=SUBJECT_CHOICES, widget=forms.Select(), @@ -74,6 +78,7 @@ class ContactUsForm(forms.Form): ) def __init__(self, request, *args, **kwargs): + """Init contact us form.""" super(ContactUsForm, self).__init__(*args, **kwargs) if request.user and request.user.is_authenticated(): @@ -86,7 +91,8 @@ def __init__(self, request, *args, **kwargs): self.fields = add_placeholder_and_asterisk(self.fields) def clean(self): + """Clean "contact us" form submission.""" cleaned_data = super(ContactUsForm, self).clean() - if cleaned_data["subject"] == "-----": + if "subject" in cleaned_data and cleaned_data["subject"] == "-----": self._errors["subject"] = self.error_class([_("Please specify a subject")]) return cleaned_data diff --git a/pod/main/models.py b/pod/main/models.py index 1855641215..21fc13ddfa 100644 --- a/pod/main/models.py +++ b/pod/main/models.py @@ -178,5 +178,5 @@ def __str__(self): return "%s" % (self.name) class Meta: - verbose_name = _("Additional Channels Tab") - verbose_name_plural = _("Additional Channel Tabs") + verbose_name = _("Additional channels Tab") + verbose_name_plural = _("Additional channel Tabs") diff --git a/pod/main/rest_router.py b/pod/main/rest_router.py index 83330e7a38..1a17e2ccca 100644 --- a/pod/main/rest_router.py +++ b/pod/main/rest_router.py @@ -1,3 +1,4 @@ +"""Esup-Pod Main REST api url router.""" from rest_framework import routers from django.conf.urls import url from django.conf.urls import include diff --git a/pod/main/static/css/dyslexia.css b/pod/main/static/css/dyslexia.css index dc72615d6f..5fc7bde575 100644 --- a/pod/main/static/css/dyslexia.css +++ b/pod/main/static/css/dyslexia.css @@ -29,14 +29,14 @@ display: none; } -.feather-eye { +#dyslexia-switch-wrapper .feather-eye { opacity: 0; left: 5px; bottom: 0; color: var(--white) !important; transform: translateX(4px); } -.feather-eye-off { +#dyslexia-switch-wrapper .feather-eye-off { opacity: 1; right: 5px; bottom: 0; diff --git a/pod/main/static/css/pod.css b/pod/main/static/css/pod.css index 5565bd22c0..bbc962c003 100755 --- a/pod/main/static/css/pod.css +++ b/pod/main/static/css/pod.css @@ -29,6 +29,14 @@ --dark: #343a40; --color-formfields: #f1f1f1; } + +/* copy "alert-danger" style from Bootstrap 4 */ +.alert-error { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +} + .table, .navbar-light .navbar-nav .nav-link, .navbar-light .navbar-toggler { @@ -432,8 +440,8 @@ div.card a:hover>img { right: 2px; border: none; } -.card-footer .feather, -.card-header .feather { +.video-card .card-footer .feather, +.video-card .card-header .feather { height: 1rem; } diff --git a/pod/main/static/img/cookie.svg b/pod/main/static/img/cookie.svg new file mode 100644 index 0000000000..aecff25857 --- /dev/null +++ b/pod/main/static/img/cookie.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pod/main/static/img/default.svg b/pod/main/static/img/default.svg index 2dcda899f1..a5ac563cb9 100644 --- a/pod/main/static/img/default.svg +++ b/pod/main/static/img/default.svg @@ -1,14 +1,13 @@ - - + - + - - MAX_TIMESTEP) { - return false; - } - return true; - }; - var getScreenWidth = function getScreenWidth() { - return ( - Math.max(window.screen.width, window.screen.height) * - window.devicePixelRatio - ); - }; - var getScreenHeight = function getScreenHeight() { - return ( - Math.min(window.screen.width, window.screen.height) * - window.devicePixelRatio - ); - }; - var requestFullscreen = function requestFullscreen(element) { - if (isWebViewAndroid()) { - return false; - } - if (element.requestFullscreen) { - element.requestFullscreen(); - } else if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.msRequestFullscreen) { - element.msRequestFullscreen(); - } else { - return false; - } - return true; - }; - var exitFullscreen = function exitFullscreen() { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } else { - return false; - } - return true; - }; - var getFullscreenElement = function getFullscreenElement() { - return ( - document.fullscreenElement || - document.webkitFullscreenElement || - document.mozFullScreenElement || - document.msFullscreenElement - ); - }; - var linkProgram = function linkProgram( - gl, - vertexSource, - fragmentSource, - attribLocationMap - ) { - var vertexShader = gl.createShader(gl.VERTEX_SHADER); - gl.shaderSource(vertexShader, vertexSource); - gl.compileShader(vertexShader); - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(fragmentShader, fragmentSource); - gl.compileShader(fragmentShader); - var program = gl.createProgram(); - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - for (var attribName in attribLocationMap) { - gl.bindAttribLocation( - program, - attribLocationMap[attribName], - attribName - ); - } - gl.linkProgram(program); - gl.deleteShader(vertexShader); - gl.deleteShader(fragmentShader); - return program; - }; - var getProgramUniforms = function getProgramUniforms(gl, program) { - var uniforms = {}; - var uniformCount = gl.getProgramParameter( - program, - gl.ACTIVE_UNIFORMS - ); - var uniformName = ""; - for (var i = 0; i < uniformCount; i++) { - var uniformInfo = gl.getActiveUniform(program, i); - uniformName = uniformInfo.name.replace("[0]", ""); - uniforms[uniformName] = gl.getUniformLocation(program, uniformName); - } - return uniforms; - }; - var orthoMatrix = function orthoMatrix( - out, - left, - right, - bottom, - top, - near, - far - ) { - var lr = 1 / (left - right), - bt = 1 / (bottom - top), - nf = 1 / (near - far); - out[0] = -2 * lr; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = -2 * bt; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 2 * nf; - out[11] = 0; - out[12] = (left + right) * lr; - out[13] = (top + bottom) * bt; - out[14] = (far + near) * nf; - out[15] = 1; - return out; - }; - var isMobile = function isMobile() { - var check = false; - (function (a) { - if ( - /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test( - a - ) || - /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( - a.substr(0, 4) - ) - ) - check = true; - })(navigator.userAgent || navigator.vendor || window.opera); - return check; - }; - var extend = function extend(dest, src) { - for (var key in src) { - if (src.hasOwnProperty(key)) { - dest[key] = src[key]; - } - } - return dest; - }; - var safariCssSizeWorkaround = function safariCssSizeWorkaround(canvas) { - if (isIOS()) { - var width = canvas.style.width; - var height = canvas.style.height; - canvas.style.width = parseInt(width) + 1 + "px"; - canvas.style.height = parseInt(height) + "px"; - setTimeout(function () { - canvas.style.width = width; - canvas.style.height = height; - }, 100); - } - window.canvas = canvas; - }; - var frameDataFromPose = (function () { - var piOver180 = Math.PI / 180.0; - var rad45 = Math.PI * 0.25; - function mat4_perspectiveFromFieldOfView(out, fov, near, far) { - var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45), - downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45), - leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45), - rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45), - xScale = 2.0 / (leftTan + rightTan), - yScale = 2.0 / (upTan + downTan); - out[0] = xScale; - out[1] = 0.0; - out[2] = 0.0; - out[3] = 0.0; - out[4] = 0.0; - out[5] = yScale; - out[6] = 0.0; - out[7] = 0.0; - out[8] = -((leftTan - rightTan) * xScale * 0.5); - out[9] = (upTan - downTan) * yScale * 0.5; - out[10] = far / (near - far); - out[11] = -1.0; - out[12] = 0.0; - out[13] = 0.0; - out[14] = (far * near) / (near - far); - out[15] = 0.0; - return out; - } - function mat4_fromRotationTranslation(out, q, v) { - var x = q[0], - y = q[1], - z = q[2], - w = q[3], - x2 = x + x, - y2 = y + y, - z2 = z + z, - xx = x * x2, - xy = x * y2, - xz = x * z2, - yy = y * y2, - yz = y * z2, - zz = z * z2, - wx = w * x2, - wy = w * y2, - wz = w * z2; - out[0] = 1 - (yy + zz); - out[1] = xy + wz; - out[2] = xz - wy; - out[3] = 0; - out[4] = xy - wz; - out[5] = 1 - (xx + zz); - out[6] = yz + wx; - out[7] = 0; - out[8] = xz + wy; - out[9] = yz - wx; - out[10] = 1 - (xx + yy); - out[11] = 0; - out[12] = v[0]; - out[13] = v[1]; - out[14] = v[2]; - out[15] = 1; - return out; - } - function mat4_translate(out, a, v) { - var x = v[0], - y = v[1], - z = v[2], - a00, - a01, - a02, - a03, - a10, - a11, - a12, - a13, - a20, - a21, - a22, - a23; - if (a === out) { - out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; - out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; - out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; - out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; - } else { - a00 = a[0]; - a01 = a[1]; - a02 = a[2]; - a03 = a[3]; - a10 = a[4]; - a11 = a[5]; - a12 = a[6]; - a13 = a[7]; - a20 = a[8]; - a21 = a[9]; - a22 = a[10]; - a23 = a[11]; - out[0] = a00; - out[1] = a01; - out[2] = a02; - out[3] = a03; - out[4] = a10; - out[5] = a11; - out[6] = a12; - out[7] = a13; - out[8] = a20; - out[9] = a21; - out[10] = a22; - out[11] = a23; - out[12] = a00 * x + a10 * y + a20 * z + a[12]; - out[13] = a01 * x + a11 * y + a21 * z + a[13]; - out[14] = a02 * x + a12 * y + a22 * z + a[14]; - out[15] = a03 * x + a13 * y + a23 * z + a[15]; - } - return out; - } - function mat4_invert(out, a) { - var a00 = a[0], - a01 = a[1], - a02 = a[2], - a03 = a[3], - a10 = a[4], - a11 = a[5], - a12 = a[6], - a13 = a[7], - a20 = a[8], - a21 = a[9], - a22 = a[10], - a23 = a[11], - a30 = a[12], - a31 = a[13], - a32 = a[14], - a33 = a[15], - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32, - det = - b00 * b11 - - b01 * b10 + - b02 * b09 + - b03 * b08 - - b04 * b07 + - b05 * b06; - if (!det) { - return null; - } - det = 1.0 / det; - out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; - return out; - } - var defaultOrientation = new Float32Array([0, 0, 0, 1]); - var defaultPosition = new Float32Array([0, 0, 0]); - function updateEyeMatrices( - projection, - view, - pose, - fov, - offset, - vrDisplay - ) { - mat4_perspectiveFromFieldOfView( - projection, - fov || null, - vrDisplay.depthNear, - vrDisplay.depthFar - ); - var orientation = pose.orientation || defaultOrientation; - var position = pose.position || defaultPosition; - mat4_fromRotationTranslation(view, orientation, position); - if (offset) mat4_translate(view, view, offset); - mat4_invert(view, view); - } - return function (frameData, pose, vrDisplay) { - if (!frameData || !pose) return false; - frameData.pose = pose; - frameData.timestamp = pose.timestamp; - updateEyeMatrices( - frameData.leftProjectionMatrix, - frameData.leftViewMatrix, - pose, - vrDisplay._getFieldOfView("left"), - vrDisplay._getEyeOffset("left"), - vrDisplay - ); - updateEyeMatrices( - frameData.rightProjectionMatrix, - frameData.rightViewMatrix, - pose, - vrDisplay._getFieldOfView("right"), - vrDisplay._getEyeOffset("right"), - vrDisplay - ); - return true; - }; - })(); - var isInsideCrossOriginIFrame = function isInsideCrossOriginIFrame() { - var isFramed = window.self !== window.top; - var refOrigin = getOriginFromUrl(document.referrer); - var thisOrigin = getOriginFromUrl(window.location.href); - return isFramed && refOrigin !== thisOrigin; - }; - var getOriginFromUrl = function getOriginFromUrl(url) { - var domainIdx; - var protoSepIdx = url.indexOf("://"); - if (protoSepIdx !== -1) { - domainIdx = protoSepIdx + 3; - } else { - domainIdx = 0; - } - var domainEndIdx = url.indexOf("/", domainIdx); - if (domainEndIdx === -1) { - domainEndIdx = url.length; - } - return url.substring(0, domainEndIdx); - }; - var getQuaternionAngle = function getQuaternionAngle(quat) { - if (quat.w > 1) { - console.warn("getQuaternionAngle: w > 1"); - return 0; - } - var angle = 2 * Math.acos(quat.w); - return angle; - }; - var warnOnce = (function () { - var observedWarnings = {}; - return function (key, message) { - if (observedWarnings[key] === undefined) { - console.warn("webvr-polyfill: " + message); - observedWarnings[key] = true; - } - }; - })(); - var deprecateWarning = function deprecateWarning( - deprecated, - suggested - ) { - var alternative = suggested - ? "Please use " + suggested + " instead." - : ""; - warnOnce( - deprecated, - deprecated + - " has been deprecated. " + - "This may not work on native WebVR displays. " + - alternative - ); - }; - function WGLUPreserveGLState(gl, bindings, callback) { - if (!bindings) { - callback(gl); - return; - } - var boundValues = []; - var activeTexture = null; - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - switch (binding) { - case gl.TEXTURE_BINDING_2D: - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) { - console.error( - "TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit" - ); - boundValues.push(null, null); - break; - } - if (!activeTexture) { - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - } - gl.activeTexture(textureUnit); - boundValues.push(gl.getParameter(binding), null); - break; - case gl.ACTIVE_TEXTURE: - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - boundValues.push(null); - break; - default: - boundValues.push(gl.getParameter(binding)); - break; - } - } - callback(gl); - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - var boundValue = boundValues[i]; - switch (binding) { - case gl.ACTIVE_TEXTURE: - break; - case gl.ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ARRAY_BUFFER, boundValue); - break; - case gl.COLOR_CLEAR_VALUE: - gl.clearColor( - boundValue[0], - boundValue[1], - boundValue[2], - boundValue[3] - ); - break; - case gl.COLOR_WRITEMASK: - gl.colorMask( - boundValue[0], - boundValue[1], - boundValue[2], - boundValue[3] - ); - break; - case gl.CURRENT_PROGRAM: - gl.useProgram(boundValue); - break; - case gl.ELEMENT_ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue); - break; - case gl.FRAMEBUFFER_BINDING: - gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue); - break; - case gl.RENDERBUFFER_BINDING: - gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue); - break; - case gl.TEXTURE_BINDING_2D: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_2D, boundValue); - break; - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue); - break; - case gl.VIEWPORT: - gl.viewport( - boundValue[0], - boundValue[1], - boundValue[2], - boundValue[3] - ); - break; - case gl.BLEND: - case gl.CULL_FACE: - case gl.DEPTH_TEST: - case gl.SCISSOR_TEST: - case gl.STENCIL_TEST: - if (boundValue) { - gl.enable(binding); - } else { - gl.disable(binding); - } - break; - default: - console.log( - "No GL restore behavior for 0x" + binding.toString(16) - ); - break; - } - if (activeTexture) { - gl.activeTexture(activeTexture); - } - } - } - var glPreserveState = WGLUPreserveGLState; - var distortionVS = [ - "attribute vec2 position;", - "attribute vec3 texCoord;", - "varying vec2 vTexCoord;", - "uniform vec4 viewportOffsetScale[2];", - "void main() {", - " vec4 viewport = viewportOffsetScale[int(texCoord.z)];", - " vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;", - " gl_Position = vec4( position, 1.0, 1.0 );", - "}", - ].join("\n"); - var distortionFS = [ - "precision mediump float;", - "uniform sampler2D diffuse;", - "varying vec2 vTexCoord;", - "void main() {", - " gl_FragColor = texture2D(diffuse, vTexCoord);", - "}", - ].join("\n"); - function CardboardDistorter( - gl, - cardboardUI, - bufferScale, - dirtySubmitFrameBindings - ) { - this.gl = gl; - this.cardboardUI = cardboardUI; - this.bufferScale = bufferScale; - this.dirtySubmitFrameBindings = dirtySubmitFrameBindings; - this.ctxAttribs = gl.getContextAttributes(); - this.meshWidth = 20; - this.meshHeight = 20; - this.bufferWidth = gl.drawingBufferWidth; - this.bufferHeight = gl.drawingBufferHeight; - this.realBindFramebuffer = gl.bindFramebuffer; - this.realEnable = gl.enable; - this.realDisable = gl.disable; - this.realColorMask = gl.colorMask; - this.realClearColor = gl.clearColor; - this.realViewport = gl.viewport; - if (!isIOS()) { - this.realCanvasWidth = Object.getOwnPropertyDescriptor( - gl.canvas.__proto__, - "width" - ); - this.realCanvasHeight = Object.getOwnPropertyDescriptor( - gl.canvas.__proto__, - "height" - ); - } - this.isPatched = false; - this.lastBoundFramebuffer = null; - this.cullFace = false; - this.depthTest = false; - this.blend = false; - this.scissorTest = false; - this.stencilTest = false; - this.viewport = [0, 0, 0, 0]; - this.colorMask = [true, true, true, true]; - this.clearColor = [0, 0, 0, 0]; - this.attribs = { - position: 0, - texCoord: 1, - }; - this.program = linkProgram( - gl, - distortionVS, - distortionFS, - this.attribs - ); - this.uniforms = getProgramUniforms(gl, this.program); - this.viewportOffsetScale = new Float32Array(8); - this.setTextureBounds(); - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.indexCount = 0; - this.renderTarget = gl.createTexture(); - this.framebuffer = gl.createFramebuffer(); - this.depthStencilBuffer = null; - this.depthBuffer = null; - this.stencilBuffer = null; - if (this.ctxAttribs.depth && this.ctxAttribs.stencil) { - this.depthStencilBuffer = gl.createRenderbuffer(); - } else if (this.ctxAttribs.depth) { - this.depthBuffer = gl.createRenderbuffer(); - } else if (this.ctxAttribs.stencil) { - this.stencilBuffer = gl.createRenderbuffer(); - } - this.patch(); - this.onResize(); - } - CardboardDistorter.prototype.destroy = function () { - var gl = this.gl; - this.unpatch(); - gl.deleteProgram(this.program); - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.indexBuffer); - gl.deleteTexture(this.renderTarget); - gl.deleteFramebuffer(this.framebuffer); - if (this.depthStencilBuffer) { - gl.deleteRenderbuffer(this.depthStencilBuffer); - } - if (this.depthBuffer) { - gl.deleteRenderbuffer(this.depthBuffer); - } - if (this.stencilBuffer) { - gl.deleteRenderbuffer(this.stencilBuffer); - } - if (this.cardboardUI) { - this.cardboardUI.destroy(); - } - }; - CardboardDistorter.prototype.onResize = function () { - var gl = this.gl; - var self = this; - var glState = [ - gl.RENDERBUFFER_BINDING, - gl.TEXTURE_BINDING_2D, - gl.TEXTURE0, - ]; - glPreserveState(gl, glState, function (gl) { - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); - if (self.scissorTest) { - self.realDisable.call(gl, gl.SCISSOR_TEST); - } - self.realColorMask.call(gl, true, true, true, true); - self.realViewport.call( - gl, - 0, - 0, - gl.drawingBufferWidth, - gl.drawingBufferHeight - ); - self.realClearColor.call(gl, 0, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer); - gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); - gl.texImage2D( - gl.TEXTURE_2D, - 0, - self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, - self.bufferWidth, - self.bufferHeight, - 0, - self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, - gl.UNSIGNED_BYTE, - null - ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri( - gl.TEXTURE_2D, - gl.TEXTURE_WRAP_S, - gl.CLAMP_TO_EDGE - ); - gl.texParameteri( - gl.TEXTURE_2D, - gl.TEXTURE_WRAP_T, - gl.CLAMP_TO_EDGE - ); - gl.framebufferTexture2D( - gl.FRAMEBUFFER, - gl.COLOR_ATTACHMENT0, - gl.TEXTURE_2D, - self.renderTarget, - 0 - ); - if (self.ctxAttribs.depth && self.ctxAttribs.stencil) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer); - gl.renderbufferStorage( - gl.RENDERBUFFER, - gl.DEPTH_STENCIL, - self.bufferWidth, - self.bufferHeight - ); - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - gl.DEPTH_STENCIL_ATTACHMENT, - gl.RENDERBUFFER, - self.depthStencilBuffer - ); - } else if (self.ctxAttribs.depth) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer); - gl.renderbufferStorage( - gl.RENDERBUFFER, - gl.DEPTH_COMPONENT16, - self.bufferWidth, - self.bufferHeight - ); - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - gl.DEPTH_ATTACHMENT, - gl.RENDERBUFFER, - self.depthBuffer - ); - } else if (self.ctxAttribs.stencil) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer); - gl.renderbufferStorage( - gl.RENDERBUFFER, - gl.STENCIL_INDEX8, - self.bufferWidth, - self.bufferHeight - ); - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - gl.STENCIL_ATTACHMENT, - gl.RENDERBUFFER, - self.stencilBuffer - ); - } - if ( - !gl.checkFramebufferStatus(gl.FRAMEBUFFER) === - gl.FRAMEBUFFER_COMPLETE - ) { - console.error("Framebuffer incomplete!"); - } - self.realBindFramebuffer.call( - gl, - gl.FRAMEBUFFER, - self.lastBoundFramebuffer - ); - if (self.scissorTest) { - self.realEnable.call(gl, gl.SCISSOR_TEST); - } - self.realColorMask.apply(gl, self.colorMask); - self.realViewport.apply(gl, self.viewport); - self.realClearColor.apply(gl, self.clearColor); - }); - if (this.cardboardUI) { - this.cardboardUI.onResize(); - } - }; - CardboardDistorter.prototype.patch = function () { - if (this.isPatched) { - return; - } - var self = this; - var canvas = this.gl.canvas; - var gl = this.gl; - if (!isIOS()) { - canvas.width = getScreenWidth() * this.bufferScale; - canvas.height = getScreenHeight() * this.bufferScale; - Object.defineProperty(canvas, "width", { - configurable: true, - enumerable: true, - get: function get() { - return self.bufferWidth; - }, - set: function set(value) { - self.bufferWidth = value; - self.realCanvasWidth.set.call(canvas, value); - self.onResize(); - }, - }); - Object.defineProperty(canvas, "height", { - configurable: true, - enumerable: true, - get: function get() { - return self.bufferHeight; - }, - set: function set(value) { - self.bufferHeight = value; - self.realCanvasHeight.set.call(canvas, value); - self.onResize(); - }, - }); - } - this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); - if (this.lastBoundFramebuffer == null) { - this.lastBoundFramebuffer = this.framebuffer; - this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); - } - this.gl.bindFramebuffer = function (target, framebuffer) { - self.lastBoundFramebuffer = framebuffer - ? framebuffer - : self.framebuffer; - self.realBindFramebuffer.call( - gl, - target, - self.lastBoundFramebuffer - ); - }; - this.cullFace = gl.getParameter(gl.CULL_FACE); - this.depthTest = gl.getParameter(gl.DEPTH_TEST); - this.blend = gl.getParameter(gl.BLEND); - this.scissorTest = gl.getParameter(gl.SCISSOR_TEST); - this.stencilTest = gl.getParameter(gl.STENCIL_TEST); - gl.enable = function (pname) { - switch (pname) { - case gl.CULL_FACE: - self.cullFace = true; - break; - case gl.DEPTH_TEST: - self.depthTest = true; - break; - case gl.BLEND: - self.blend = true; - break; - case gl.SCISSOR_TEST: - self.scissorTest = true; - break; - case gl.STENCIL_TEST: - self.stencilTest = true; - break; - } - self.realEnable.call(gl, pname); - }; - gl.disable = function (pname) { - switch (pname) { - case gl.CULL_FACE: - self.cullFace = false; - break; - case gl.DEPTH_TEST: - self.depthTest = false; - break; - case gl.BLEND: - self.blend = false; - break; - case gl.SCISSOR_TEST: - self.scissorTest = false; - break; - case gl.STENCIL_TEST: - self.stencilTest = false; - break; - } - self.realDisable.call(gl, pname); - }; - this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK); - gl.colorMask = function (r, g, b, a) { - self.colorMask[0] = r; - self.colorMask[1] = g; - self.colorMask[2] = b; - self.colorMask[3] = a; - self.realColorMask.call(gl, r, g, b, a); - }; - this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); - gl.clearColor = function (r, g, b, a) { - self.clearColor[0] = r; - self.clearColor[1] = g; - self.clearColor[2] = b; - self.clearColor[3] = a; - self.realClearColor.call(gl, r, g, b, a); - }; - this.viewport = gl.getParameter(gl.VIEWPORT); - gl.viewport = function (x, y, w, h) { - self.viewport[0] = x; - self.viewport[1] = y; - self.viewport[2] = w; - self.viewport[3] = h; - self.realViewport.call(gl, x, y, w, h); - }; - this.isPatched = true; - safariCssSizeWorkaround(canvas); - }; - CardboardDistorter.prototype.unpatch = function () { - if (!this.isPatched) { - return; - } - var gl = this.gl; - var canvas = this.gl.canvas; - if (!isIOS()) { - Object.defineProperty(canvas, "width", this.realCanvasWidth); - Object.defineProperty(canvas, "height", this.realCanvasHeight); - } - canvas.width = this.bufferWidth; - canvas.height = this.bufferHeight; - gl.bindFramebuffer = this.realBindFramebuffer; - gl.enable = this.realEnable; - gl.disable = this.realDisable; - gl.colorMask = this.realColorMask; - gl.clearColor = this.realClearColor; - gl.viewport = this.realViewport; - if (this.lastBoundFramebuffer == this.framebuffer) { - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - } - this.isPatched = false; - setTimeout(function () { - safariCssSizeWorkaround(canvas); - }, 1); - }; - CardboardDistorter.prototype.setTextureBounds = function ( - leftBounds, - rightBounds - ) { - if (!leftBounds) { - leftBounds = [0, 0, 0.5, 1]; - } - if (!rightBounds) { - rightBounds = [0.5, 0, 0.5, 1]; - } - this.viewportOffsetScale[0] = leftBounds[0]; - this.viewportOffsetScale[1] = leftBounds[1]; - this.viewportOffsetScale[2] = leftBounds[2]; - this.viewportOffsetScale[3] = leftBounds[3]; - this.viewportOffsetScale[4] = rightBounds[0]; - this.viewportOffsetScale[5] = rightBounds[1]; - this.viewportOffsetScale[6] = rightBounds[2]; - this.viewportOffsetScale[7] = rightBounds[3]; - }; - CardboardDistorter.prototype.submitFrame = function () { - var gl = this.gl; - var self = this; - var glState = []; - if (!this.dirtySubmitFrameBindings) { - glState.push( - gl.CURRENT_PROGRAM, - gl.ARRAY_BUFFER_BINDING, - gl.ELEMENT_ARRAY_BUFFER_BINDING, - gl.TEXTURE_BINDING_2D, - gl.TEXTURE0 - ); - } - glPreserveState(gl, glState, function (gl) { - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); - if (self.cullFace) { - self.realDisable.call(gl, gl.CULL_FACE); - } - if (self.depthTest) { - self.realDisable.call(gl, gl.DEPTH_TEST); - } - if (self.blend) { - self.realDisable.call(gl, gl.BLEND); - } - if (self.scissorTest) { - self.realDisable.call(gl, gl.SCISSOR_TEST); - } - if (self.stencilTest) { - self.realDisable.call(gl, gl.STENCIL_TEST); - } - self.realColorMask.call(gl, true, true, true, true); - self.realViewport.call( - gl, - 0, - 0, - gl.drawingBufferWidth, - gl.drawingBufferHeight - ); - if (self.ctxAttribs.alpha || isIOS()) { - self.realClearColor.call(gl, 0, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); - } - gl.useProgram(self.program); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.enableVertexAttribArray(self.attribs.position); - gl.enableVertexAttribArray(self.attribs.texCoord); - gl.vertexAttribPointer( - self.attribs.position, - 2, - gl.FLOAT, - false, - 20, - 0 - ); - gl.vertexAttribPointer( - self.attribs.texCoord, - 3, - gl.FLOAT, - false, - 20, - 8 - ); - gl.activeTexture(gl.TEXTURE0); - gl.uniform1i(self.uniforms.diffuse, 0); - gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); - gl.uniform4fv( - self.uniforms.viewportOffsetScale, - self.viewportOffsetScale - ); - gl.drawElements( - gl.TRIANGLES, - self.indexCount, - gl.UNSIGNED_SHORT, - 0 - ); - if (self.cardboardUI) { - self.cardboardUI.renderNoState(); - } - self.realBindFramebuffer.call( - self.gl, - gl.FRAMEBUFFER, - self.framebuffer - ); - if (!self.ctxAttribs.preserveDrawingBuffer) { - self.realClearColor.call(gl, 0, 0, 0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - if (!self.dirtySubmitFrameBindings) { - self.realBindFramebuffer.call( - gl, - gl.FRAMEBUFFER, - self.lastBoundFramebuffer - ); - } - if (self.cullFace) { - self.realEnable.call(gl, gl.CULL_FACE); - } - if (self.depthTest) { - self.realEnable.call(gl, gl.DEPTH_TEST); - } - if (self.blend) { - self.realEnable.call(gl, gl.BLEND); - } - if (self.scissorTest) { - self.realEnable.call(gl, gl.SCISSOR_TEST); - } - if (self.stencilTest) { - self.realEnable.call(gl, gl.STENCIL_TEST); - } - self.realColorMask.apply(gl, self.colorMask); - self.realViewport.apply(gl, self.viewport); - if ( - self.ctxAttribs.alpha || - !self.ctxAttribs.preserveDrawingBuffer - ) { - self.realClearColor.apply(gl, self.clearColor); - } - }); - if (isIOS()) { - var canvas = gl.canvas; - if ( - canvas.width != self.bufferWidth || - canvas.height != self.bufferHeight - ) { - self.bufferWidth = canvas.width; - self.bufferHeight = canvas.height; - self.onResize(); - } - } - }; - CardboardDistorter.prototype.updateDeviceInfo = function (deviceInfo) { - var gl = this.gl; - var self = this; - var glState = [ - gl.ARRAY_BUFFER_BINDING, - gl.ELEMENT_ARRAY_BUFFER_BINDING, - ]; - glPreserveState(gl, glState, function (gl) { - var vertices = self.computeMeshVertices_( - self.meshWidth, - self.meshHeight, - deviceInfo - ); - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); - if (!self.indexCount) { - var indices = self.computeMeshIndices_( - self.meshWidth, - self.meshHeight - ); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); - self.indexCount = indices.length; - } - }); - }; - CardboardDistorter.prototype.computeMeshVertices_ = function ( - width, - height, - deviceInfo - ) { - var vertices = new Float32Array(2 * width * height * 5); - var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles(); - var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles(); - var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum); - var vidx = 0; - for (var e = 0; e < 2; e++) { - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++, vidx++) { - var u = i / (width - 1); - var v = j / (height - 1); - var s = u; - var t = v; - var x = lerp(lensFrustum[0], lensFrustum[2], u); - var y = lerp(lensFrustum[3], lensFrustum[1], v); - var d = Math.sqrt(x * x + y * y); - var r = deviceInfo.distortion.distortInverse(d); - var p = (x * r) / d; - var q = (y * r) / d; - u = - (p - noLensFrustum[0]) / - (noLensFrustum[2] - noLensFrustum[0]); - v = - (q - noLensFrustum[3]) / - (noLensFrustum[1] - noLensFrustum[3]); - u = (viewport.x + u * viewport.width - 0.5) * 2.0; - v = (viewport.y + v * viewport.height - 0.5) * 2.0; - vertices[vidx * 5 + 0] = u; - vertices[vidx * 5 + 1] = v; - vertices[vidx * 5 + 2] = s; - vertices[vidx * 5 + 3] = t; - vertices[vidx * 5 + 4] = e; - } - } - var w = lensFrustum[2] - lensFrustum[0]; - lensFrustum[0] = -(w + lensFrustum[0]); - lensFrustum[2] = w - lensFrustum[2]; - w = noLensFrustum[2] - noLensFrustum[0]; - noLensFrustum[0] = -(w + noLensFrustum[0]); - noLensFrustum[2] = w - noLensFrustum[2]; - viewport.x = 1 - (viewport.x + viewport.width); - } - return vertices; - }; - CardboardDistorter.prototype.computeMeshIndices_ = function ( - width, - height - ) { - var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6); - var halfwidth = width / 2; - var halfheight = height / 2; - var vidx = 0; - var iidx = 0; - for (var e = 0; e < 2; e++) { - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++, vidx++) { - if (i == 0 || j == 0) continue; - if (i <= halfwidth == j <= halfheight) { - indices[iidx++] = vidx; - indices[iidx++] = vidx - width - 1; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx - width - 1; - indices[iidx++] = vidx; - indices[iidx++] = vidx - 1; - } else { - indices[iidx++] = vidx - 1; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx - 1; - indices[iidx++] = vidx - width - 1; - } - } - } - } - return indices; - }; - CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function ( - proto, - attrName - ) { - var descriptor = Object.getOwnPropertyDescriptor(proto, attrName); - if (descriptor.get === undefined || descriptor.set === undefined) { - descriptor.configurable = true; - descriptor.enumerable = true; - descriptor.get = function () { - return this.getAttribute(attrName); - }; - descriptor.set = function (val) { - this.setAttribute(attrName, val); - }; - } - return descriptor; - }; - var uiVS = [ - "attribute vec2 position;", - "uniform mat4 projectionMat;", - "void main() {", - " gl_Position = projectionMat * vec4( position, -1.0, 1.0 );", - "}", - ].join("\n"); - var uiFS = [ - "precision mediump float;", - "uniform vec4 color;", - "void main() {", - " gl_FragColor = color;", - "}", - ].join("\n"); - var DEG2RAD = Math.PI / 180.0; - var kAnglePerGearSection = 60; - var kOuterRimEndAngle = 12; - var kInnerRimBeginAngle = 20; - var kOuterRadius = 1; - var kMiddleRadius = 0.75; - var kInnerRadius = 0.3125; - var kCenterLineThicknessDp = 4; - var kButtonWidthDp = 28; - var kTouchSlopFactor = 1.5; - function CardboardUI(gl) { - this.gl = gl; - this.attribs = { - position: 0, - }; - this.program = linkProgram(gl, uiVS, uiFS, this.attribs); - this.uniforms = getProgramUniforms(gl, this.program); - this.vertexBuffer = gl.createBuffer(); - this.gearOffset = 0; - this.gearVertexCount = 0; - this.arrowOffset = 0; - this.arrowVertexCount = 0; - this.projMat = new Float32Array(16); - this.listener = null; - this.onResize(); - } - CardboardUI.prototype.destroy = function () { - var gl = this.gl; - if (this.listener) { - gl.canvas.removeEventListener("click", this.listener, false); - } - gl.deleteProgram(this.program); - gl.deleteBuffer(this.vertexBuffer); - }; - CardboardUI.prototype.listen = function ( - optionsCallback, - backCallback - ) { - var canvas = this.gl.canvas; - this.listener = function (event) { - var midline = canvas.clientWidth / 2; - var buttonSize = kButtonWidthDp * kTouchSlopFactor; - if ( - event.clientX > midline - buttonSize && - event.clientX < midline + buttonSize && - event.clientY > canvas.clientHeight - buttonSize - ) { - optionsCallback(event); - } else if ( - event.clientX < buttonSize && - event.clientY < buttonSize - ) { - backCallback(event); - } - }; - canvas.addEventListener("click", this.listener, false); - }; - CardboardUI.prototype.onResize = function () { - var gl = this.gl; - var self = this; - var glState = [gl.ARRAY_BUFFER_BINDING]; - glPreserveState(gl, glState, function (gl) { - var vertices = []; - var midline = gl.drawingBufferWidth / 2; - var physicalPixels = - Math.max(screen.width, screen.height) * window.devicePixelRatio; - var scalingRatio = gl.drawingBufferWidth / physicalPixels; - var dps = scalingRatio * window.devicePixelRatio; - var lineWidth = (kCenterLineThicknessDp * dps) / 2; - var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps; - var buttonScale = (kButtonWidthDp * dps) / 2; - var buttonBorder = - (kButtonWidthDp * kTouchSlopFactor - kButtonWidthDp) * dps; - vertices.push(midline - lineWidth, buttonSize); - vertices.push(midline - lineWidth, gl.drawingBufferHeight); - vertices.push(midline + lineWidth, buttonSize); - vertices.push(midline + lineWidth, gl.drawingBufferHeight); - self.gearOffset = vertices.length / 2; - function addGearSegment(theta, r) { - var angle = (90 - theta) * DEG2RAD; - var x = Math.cos(angle); - var y = Math.sin(angle); - vertices.push( - kInnerRadius * x * buttonScale + midline, - kInnerRadius * y * buttonScale + buttonScale - ); - vertices.push( - r * x * buttonScale + midline, - r * y * buttonScale + buttonScale - ); - } - for (var i = 0; i <= 6; i++) { - var segmentTheta = i * kAnglePerGearSection; - addGearSegment(segmentTheta, kOuterRadius); - addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius); - addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius); - addGearSegment( - segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), - kMiddleRadius - ); - addGearSegment( - segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), - kOuterRadius - ); - } - self.gearVertexCount = vertices.length / 2 - self.gearOffset; - self.arrowOffset = vertices.length / 2; - function addArrowVertex(x, y) { - vertices.push( - buttonBorder + x, - gl.drawingBufferHeight - buttonBorder - y - ); - } - var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD); - addArrowVertex(0, buttonScale); - addArrowVertex(buttonScale, 0); - addArrowVertex(buttonScale + angledLineWidth, angledLineWidth); - addArrowVertex(angledLineWidth, buttonScale + angledLineWidth); - addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); - addArrowVertex(0, buttonScale); - addArrowVertex(buttonScale, buttonScale * 2); - addArrowVertex( - buttonScale + angledLineWidth, - buttonScale * 2 - angledLineWidth - ); - addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); - addArrowVertex(0, buttonScale); - addArrowVertex(angledLineWidth, buttonScale - lineWidth); - addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth); - addArrowVertex(angledLineWidth, buttonScale + lineWidth); - addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth); - self.arrowVertexCount = vertices.length / 2 - self.arrowOffset; - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.bufferData( - gl.ARRAY_BUFFER, - new Float32Array(vertices), - gl.STATIC_DRAW - ); - }); - }; - CardboardUI.prototype.render = function () { - var gl = this.gl; - var self = this; - var glState = [ - gl.CULL_FACE, - gl.DEPTH_TEST, - gl.BLEND, - gl.SCISSOR_TEST, - gl.STENCIL_TEST, - gl.COLOR_WRITEMASK, - gl.VIEWPORT, - gl.CURRENT_PROGRAM, - gl.ARRAY_BUFFER_BINDING, - ]; - glPreserveState(gl, glState, function (gl) { - gl.disable(gl.CULL_FACE); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.BLEND); - gl.disable(gl.SCISSOR_TEST); - gl.disable(gl.STENCIL_TEST); - gl.colorMask(true, true, true, true); - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - self.renderNoState(); - }); - }; - CardboardUI.prototype.renderNoState = function () { - var gl = this.gl; - gl.useProgram(this.program); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.enableVertexAttribArray(this.attribs.position); - gl.vertexAttribPointer( - this.attribs.position, - 2, - gl.FLOAT, - false, - 8, - 0 - ); - gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0); - orthoMatrix( - this.projMat, - 0, - gl.drawingBufferWidth, - 0, - gl.drawingBufferHeight, - 0.1, - 1024.0 - ); - gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat); - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); - gl.drawArrays( - gl.TRIANGLE_STRIP, - this.gearOffset, - this.gearVertexCount - ); - gl.drawArrays( - gl.TRIANGLE_STRIP, - this.arrowOffset, - this.arrowVertexCount - ); - }; - function Distortion(coefficients) { - this.coefficients = coefficients; - } - Distortion.prototype.distortInverse = function (radius) { - var r0 = 0; - var r1 = 1; - var dr0 = radius - this.distort(r0); - while (Math.abs(r1 - r0) > 0.0001) { - var dr1 = radius - this.distort(r1); - var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0)); - r0 = r1; - r1 = r2; - dr0 = dr1; - } - return r1; - }; - Distortion.prototype.distort = function (radius) { - var r2 = radius * radius; - var ret = 0; - for (var i = 0; i < this.coefficients.length; i++) { - ret = r2 * (ret + this.coefficients[i]); - } - return (ret + 1) * radius; - }; - var degToRad = Math.PI / 180; - var radToDeg = 180 / Math.PI; - var Vector3 = function Vector3(x, y, z) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - }; - Vector3.prototype = { - constructor: Vector3, - set: function set(x, y, z) { - this.x = x; - this.y = y; - this.z = z; - return this; - }, - copy: function copy(v) { - this.x = v.x; - this.y = v.y; - this.z = v.z; - return this; - }, - length: function length() { - return Math.sqrt( - this.x * this.x + this.y * this.y + this.z * this.z - ); - }, - normalize: function normalize() { - var scalar = this.length(); - if (scalar !== 0) { - var invScalar = 1 / scalar; - this.multiplyScalar(invScalar); - } else { - this.x = 0; - this.y = 0; - this.z = 0; - } - return this; - }, - multiplyScalar: function multiplyScalar(scalar) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - }, - applyQuaternion: function applyQuaternion(q) { - var x = this.x; - var y = this.y; - var z = this.z; - var qx = q.x; - var qy = q.y; - var qz = q.z; - var qw = q.w; - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - return this; - }, - dot: function dot(v) { - return this.x * v.x + this.y * v.y + this.z * v.z; - }, - crossVectors: function crossVectors(a, b) { - var ax = a.x, - ay = a.y, - az = a.z; - var bx = b.x, - by = b.y, - bz = b.z; - this.x = ay * bz - az * by; - this.y = az * bx - ax * bz; - this.z = ax * by - ay * bx; - return this; - }, - }; - var Quaternion = function Quaternion(x, y, z, w) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = w !== undefined ? w : 1; - }; - Quaternion.prototype = { - constructor: Quaternion, - set: function set(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - return this; - }, - copy: function copy(quaternion) { - this.x = quaternion.x; - this.y = quaternion.y; - this.z = quaternion.z; - this.w = quaternion.w; - return this; - }, - setFromEulerXYZ: function setFromEulerXYZ(x, y, z) { - var c1 = Math.cos(x / 2); - var c2 = Math.cos(y / 2); - var c3 = Math.cos(z / 2); - var s1 = Math.sin(x / 2); - var s2 = Math.sin(y / 2); - var s3 = Math.sin(z / 2); - this.x = s1 * c2 * c3 + c1 * s2 * s3; - this.y = c1 * s2 * c3 - s1 * c2 * s3; - this.z = c1 * c2 * s3 + s1 * s2 * c3; - this.w = c1 * c2 * c3 - s1 * s2 * s3; - return this; - }, - setFromEulerYXZ: function setFromEulerYXZ(x, y, z) { - var c1 = Math.cos(x / 2); - var c2 = Math.cos(y / 2); - var c3 = Math.cos(z / 2); - var s1 = Math.sin(x / 2); - var s2 = Math.sin(y / 2); - var s3 = Math.sin(z / 2); - this.x = s1 * c2 * c3 + c1 * s2 * s3; - this.y = c1 * s2 * c3 - s1 * c2 * s3; - this.z = c1 * c2 * s3 - s1 * s2 * c3; - this.w = c1 * c2 * c3 + s1 * s2 * s3; - return this; - }, - setFromAxisAngle: function setFromAxisAngle(axis, angle) { - var halfAngle = angle / 2, - s = Math.sin(halfAngle); - this.x = axis.x * s; - this.y = axis.y * s; - this.z = axis.z * s; - this.w = Math.cos(halfAngle); - return this; - }, - multiply: function multiply(q) { - return this.multiplyQuaternions(this, q); - }, - multiplyQuaternions: function multiplyQuaternions(a, b) { - var qax = a.x, - qay = a.y, - qaz = a.z, - qaw = a.w; - var qbx = b.x, - qby = b.y, - qbz = b.z, - qbw = b.w; - this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - return this; - }, - inverse: function inverse() { - this.x *= -1; - this.y *= -1; - this.z *= -1; - this.normalize(); - return this; - }, - normalize: function normalize() { - var l = Math.sqrt( - this.x * this.x + - this.y * this.y + - this.z * this.z + - this.w * this.w - ); - if (l === 0) { - this.x = 0; - this.y = 0; - this.z = 0; - this.w = 1; - } else { - l = 1 / l; - this.x = this.x * l; - this.y = this.y * l; - this.z = this.z * l; - this.w = this.w * l; - } - return this; - }, - slerp: function slerp(qb, t) { - if (t === 0) return this; - if (t === 1) return this.copy(qb); - var x = this.x, - y = this.y, - z = this.z, - w = this.w; - var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z; - if (cosHalfTheta < 0) { - this.w = -qb.w; - this.x = -qb.x; - this.y = -qb.y; - this.z = -qb.z; - cosHalfTheta = -cosHalfTheta; - } else { - this.copy(qb); - } - if (cosHalfTheta >= 1.0) { - this.w = w; - this.x = x; - this.y = y; - this.z = z; - return this; - } - var halfTheta = Math.acos(cosHalfTheta); - var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); - if (Math.abs(sinHalfTheta) < 0.001) { - this.w = 0.5 * (w + this.w); - this.x = 0.5 * (x + this.x); - this.y = 0.5 * (y + this.y); - this.z = 0.5 * (z + this.z); - return this; - } - var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, - ratioB = Math.sin(t * halfTheta) / sinHalfTheta; - this.w = w * ratioA + this.w * ratioB; - this.x = x * ratioA + this.x * ratioB; - this.y = y * ratioA + this.y * ratioB; - this.z = z * ratioA + this.z * ratioB; - return this; - }, - setFromUnitVectors: (function () { - var v1, r; - var EPS = 0.000001; - return function (vFrom, vTo) { - if (v1 === undefined) v1 = new Vector3(); - r = vFrom.dot(vTo) + 1; - if (r < EPS) { - r = 0; - if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { - v1.set(-vFrom.y, vFrom.x, 0); - } else { - v1.set(0, -vFrom.z, vFrom.y); - } - } else { - v1.crossVectors(vFrom, vTo); - } - this.x = v1.x; - this.y = v1.y; - this.z = v1.z; - this.w = r; - this.normalize(); - return this; - }; - })(), - }; - function Device(params) { - this.width = params.width || getScreenWidth(); - this.height = params.height || getScreenHeight(); - this.widthMeters = params.widthMeters; - this.heightMeters = params.heightMeters; - this.bevelMeters = params.bevelMeters; - } - var DEFAULT_ANDROID = new Device({ - widthMeters: 0.11, - heightMeters: 0.062, - bevelMeters: 0.004, - }); - var DEFAULT_IOS = new Device({ - widthMeters: 0.1038, - heightMeters: 0.0584, - bevelMeters: 0.004, - }); - var Viewers = { - CardboardV1: new CardboardViewer({ - id: "CardboardV1", - label: "Cardboard I/O 2014", - fov: 40, - interLensDistance: 0.06, - baselineLensDistance: 0.035, - screenLensDistance: 0.042, - distortionCoefficients: [0.441, 0.156], - inverseCoefficients: [ - -0.4410035, 0.42756155, -0.4804439, 0.5460139, -0.58821183, - 0.5733938, -0.48303202, 0.33299083, -0.17573841, 0.0651772, - -0.01488963, 0.001559834, - ], - }), - CardboardV2: new CardboardViewer({ - id: "CardboardV2", - label: "Cardboard I/O 2015", - fov: 60, - interLensDistance: 0.064, - baselineLensDistance: 0.035, - screenLensDistance: 0.039, - distortionCoefficients: [0.34, 0.55], - inverseCoefficients: [ - -0.33836704, -0.18162185, 0.862655, -1.2462051, 1.0560602, - -0.58208317, 0.21609078, -0.05444823, 0.009177956, -9.904169e-4, - 6.183535e-5, -1.6981803e-6, - ], - }), - }; - function DeviceInfo(deviceParams) { - this.viewer = Viewers.CardboardV2; - this.updateDeviceParams(deviceParams); - this.distortion = new Distortion(this.viewer.distortionCoefficients); - } - DeviceInfo.prototype.updateDeviceParams = function (deviceParams) { - this.device = this.determineDevice_(deviceParams) || this.device; - }; - DeviceInfo.prototype.getDevice = function () { - return this.device; - }; - DeviceInfo.prototype.setViewer = function (viewer) { - this.viewer = viewer; - this.distortion = new Distortion(this.viewer.distortionCoefficients); - }; - DeviceInfo.prototype.determineDevice_ = function (deviceParams) { - if (!deviceParams) { - if (isIOS()) { - console.warn("Using fallback iOS device measurements."); - return DEFAULT_IOS; - } else { - console.warn("Using fallback Android device measurements."); - return DEFAULT_ANDROID; - } - } - var METERS_PER_INCH = 0.0254; - var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi; - var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi; - var width = getScreenWidth(); - var height = getScreenHeight(); - return new Device({ - widthMeters: metersPerPixelX * width, - heightMeters: metersPerPixelY * height, - bevelMeters: deviceParams.bevelMm * 0.001, - }); - }; - DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var eyeToScreenDistance = viewer.screenLensDistance; - var outerDist = (device.widthMeters - viewer.interLensDistance) / 2; - var innerDist = viewer.interLensDistance / 2; - var bottomDist = viewer.baselineLensDistance - device.bevelMeters; - var topDist = device.heightMeters - bottomDist; - var outerAngle = - radToDeg * - Math.atan(distortion.distort(outerDist / eyeToScreenDistance)); - var innerAngle = - radToDeg * - Math.atan(distortion.distort(innerDist / eyeToScreenDistance)); - var bottomAngle = - radToDeg * - Math.atan(distortion.distort(bottomDist / eyeToScreenDistance)); - var topAngle = - radToDeg * - Math.atan(distortion.distort(topDist / eyeToScreenDistance)); - return { - leftDegrees: Math.min(outerAngle, viewer.fov), - rightDegrees: Math.min(innerAngle, viewer.fov), - downDegrees: Math.min(bottomAngle, viewer.fov), - upDegrees: Math.min(topAngle, viewer.fov), - }; - }; - DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var fovLeft = Math.tan(-degToRad * viewer.fov); - var fovTop = Math.tan(degToRad * viewer.fov); - var fovRight = Math.tan(degToRad * viewer.fov); - var fovBottom = Math.tan(-degToRad * viewer.fov); - var halfWidth = device.widthMeters / 4; - var halfHeight = device.heightMeters / 2; - var verticalLensOffset = - viewer.baselineLensDistance - device.bevelMeters - halfHeight; - var centerX = viewer.interLensDistance / 2 - halfWidth; - var centerY = -verticalLensOffset; - var centerZ = viewer.screenLensDistance; - var screenLeft = distortion.distort((centerX - halfWidth) / centerZ); - var screenTop = distortion.distort((centerY + halfHeight) / centerZ); - var screenRight = distortion.distort((centerX + halfWidth) / centerZ); - var screenBottom = distortion.distort( - (centerY - halfHeight) / centerZ - ); - var result = new Float32Array(4); - result[0] = Math.max(fovLeft, screenLeft); - result[1] = Math.min(fovTop, screenTop); - result[2] = Math.min(fovRight, screenRight); - result[3] = Math.max(fovBottom, screenBottom); - return result; - }; - DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var result = new Float32Array(4); - var fovLeft = distortion.distortInverse( - Math.tan(-degToRad * viewer.fov) - ); - var fovTop = distortion.distortInverse( - Math.tan(degToRad * viewer.fov) - ); - var fovRight = distortion.distortInverse( - Math.tan(degToRad * viewer.fov) - ); - var fovBottom = distortion.distortInverse( - Math.tan(-degToRad * viewer.fov) - ); - var halfWidth = device.widthMeters / 4; - var halfHeight = device.heightMeters / 2; - var verticalLensOffset = - viewer.baselineLensDistance - device.bevelMeters - halfHeight; - var centerX = viewer.interLensDistance / 2 - halfWidth; - var centerY = -verticalLensOffset; - var centerZ = viewer.screenLensDistance; - var screenLeft = (centerX - halfWidth) / centerZ; - var screenTop = (centerY + halfHeight) / centerZ; - var screenRight = (centerX + halfWidth) / centerZ; - var screenBottom = (centerY - halfHeight) / centerZ; - result[0] = Math.max(fovLeft, screenLeft); - result[1] = Math.min(fovTop, screenTop); - result[2] = Math.min(fovRight, screenRight); - result[3] = Math.max(fovBottom, screenBottom); - return result; - }; - DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function ( - undistortedFrustum - ) { - var viewer = this.viewer; - var device = this.device; - var dist = viewer.screenLensDistance; - var eyeX = (device.widthMeters - viewer.interLensDistance) / 2; - var eyeY = viewer.baselineLensDistance - device.bevelMeters; - var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters; - var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters; - var right = - (undistortedFrustum[2] * dist + eyeX) / device.widthMeters; - var bottom = - (undistortedFrustum[3] * dist + eyeY) / device.heightMeters; - return { - x: left, - y: bottom, - width: right - left, - height: top - bottom, - }; - }; - DeviceInfo.prototype.getFieldOfViewLeftEye = function ( - opt_isUndistorted - ) { - return opt_isUndistorted - ? this.getUndistortedFieldOfViewLeftEye() - : this.getDistortedFieldOfViewLeftEye(); - }; - DeviceInfo.prototype.getFieldOfViewRightEye = function ( - opt_isUndistorted - ) { - var fov = this.getFieldOfViewLeftEye(opt_isUndistorted); - return { - leftDegrees: fov.rightDegrees, - rightDegrees: fov.leftDegrees, - upDegrees: fov.upDegrees, - downDegrees: fov.downDegrees, - }; - }; - DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function () { - var p = this.getUndistortedParams_(); - return { - leftDegrees: radToDeg * Math.atan(p.outerDist), - rightDegrees: radToDeg * Math.atan(p.innerDist), - downDegrees: radToDeg * Math.atan(p.bottomDist), - upDegrees: radToDeg * Math.atan(p.topDist), - }; - }; - DeviceInfo.prototype.getUndistortedViewportLeftEye = function () { - var p = this.getUndistortedParams_(); - var viewer = this.viewer; - var device = this.device; - var eyeToScreenDistance = viewer.screenLensDistance; - var screenWidth = device.widthMeters / eyeToScreenDistance; - var screenHeight = device.heightMeters / eyeToScreenDistance; - var xPxPerTanAngle = device.width / screenWidth; - var yPxPerTanAngle = device.height / screenHeight; - var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle); - var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle); - return { - x: x, - y: y, - width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x, - height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y, - }; - }; - DeviceInfo.prototype.getUndistortedParams_ = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var eyeToScreenDistance = viewer.screenLensDistance; - var halfLensDistance = - viewer.interLensDistance / 2 / eyeToScreenDistance; - var screenWidth = device.widthMeters / eyeToScreenDistance; - var screenHeight = device.heightMeters / eyeToScreenDistance; - var eyePosX = screenWidth / 2 - halfLensDistance; - var eyePosY = - (viewer.baselineLensDistance - device.bevelMeters) / - eyeToScreenDistance; - var maxFov = viewer.fov; - var viewerMax = distortion.distortInverse( - Math.tan(degToRad * maxFov) - ); - var outerDist = Math.min(eyePosX, viewerMax); - var innerDist = Math.min(halfLensDistance, viewerMax); - var bottomDist = Math.min(eyePosY, viewerMax); - var topDist = Math.min(screenHeight - eyePosY, viewerMax); - return { - outerDist: outerDist, - innerDist: innerDist, - topDist: topDist, - bottomDist: bottomDist, - eyePosX: eyePosX, - eyePosY: eyePosY, - }; - }; - function CardboardViewer(params) { - this.id = params.id; - this.label = params.label; - this.fov = params.fov; - this.interLensDistance = params.interLensDistance; - this.baselineLensDistance = params.baselineLensDistance; - this.screenLensDistance = params.screenLensDistance; - this.distortionCoefficients = params.distortionCoefficients; - this.inverseCoefficients = params.inverseCoefficients; - } - DeviceInfo.Viewers = Viewers; - var format = 1; - var last_updated = "2018-02-20T22:55:10Z"; - var devices = [ - { - type: "android", - rules: [{ mdmh: "asus/*/Nexus 7/*" }, { ua: "Nexus 7" }], - dpi: [320.8, 323], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "asus/*/ASUS_Z00AD/*" }, { ua: "ASUS_Z00AD" }], - dpi: [403, 404.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Google/*/Pixel XL/*" }, { ua: "Pixel XL" }], - dpi: [537.9, 533], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Google/*/Pixel/*" }, { ua: "Pixel" }], - dpi: [432.6, 436.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC6435LVW/*" }, { ua: "HTC6435LVW" }], - dpi: [449.7, 443.3], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One XL/*" }, { ua: "HTC One XL" }], - dpi: [315.3, 314.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "htc/*/Nexus 9/*" }, { ua: "Nexus 9" }], - dpi: 289, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One M9/*" }, { ua: "HTC One M9" }], - dpi: [442.5, 443.3], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One_M8/*" }, { ua: "HTC One_M8" }], - dpi: [449.7, 447.4], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One/*" }, { ua: "HTC One" }], - dpi: 472.8, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Huawei/*/Nexus 6P/*" }, { ua: "Nexus 6P" }], - dpi: [515.1, 518], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "LENOVO/*/Lenovo PB2-690Y/*" }, - { ua: "Lenovo PB2-690Y" }, - ], - dpi: [457.2, 454.713], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/Nexus 5X/*" }, { ua: "Nexus 5X" }], - dpi: [422, 419.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LGMS345/*" }, { ua: "LGMS345" }], - dpi: [221.7, 219.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LG-D800/*" }, { ua: "LG-D800" }], - dpi: [422, 424.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LG-D850/*" }, { ua: "LG-D850" }], - dpi: [537.9, 541.9], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/VS985 4G/*" }, { ua: "VS985 4G" }], - dpi: [537.9, 535.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/Nexus 5/*" }, { ua: "Nexus 5 B" }], - dpi: [442.4, 444.8], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/Nexus 4/*" }, { ua: "Nexus 4" }], - dpi: [319.8, 318.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LG-P769/*" }, { ua: "LG-P769" }], - dpi: [240.6, 247.5], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LGMS323/*" }, { ua: "LGMS323" }], - dpi: [206.6, 204.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LGLS996/*" }, { ua: "LGLS996" }], - dpi: [403.4, 401.5], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Micromax/*/4560MMX/*" }, { ua: "4560MMX" }], - dpi: [240, 219.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Micromax/*/A250/*" }, { ua: "Micromax A250" }], - dpi: [480, 446.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "Micromax/*/Micromax AQ4501/*" }, - { ua: "Micromax AQ4501" }, - ], - dpi: 240, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/G5/*" }, { ua: "Moto G (5) Plus" }], - dpi: [403.4, 403], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/DROID RAZR/*" }, { ua: "DROID RAZR" }], - dpi: [368.1, 256.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT830C/*" }, { ua: "XT830C" }], - dpi: [254, 255.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1021/*" }, { ua: "XT1021" }], - dpi: [254, 256.7], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1023/*" }, { ua: "XT1023" }], - dpi: [254, 256.7], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1028/*" }, { ua: "XT1028" }], - dpi: [326.6, 327.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1034/*" }, { ua: "XT1034" }], - dpi: [326.6, 328.4], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1053/*" }, { ua: "XT1053" }], - dpi: [315.3, 316.1], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1562/*" }, { ua: "XT1562" }], - dpi: [403.4, 402.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/Nexus 6/*" }, { ua: "Nexus 6 B" }], - dpi: [494.3, 489.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1063/*" }, { ua: "XT1063" }], - dpi: [295, 296.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1064/*" }, { ua: "XT1064" }], - dpi: [295, 295.6], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1092/*" }, { ua: "XT1092" }], - dpi: [422, 424.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1095/*" }, { ua: "XT1095" }], - dpi: [422, 423.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/G4/*" }, { ua: "Moto G (4)" }], - dpi: 401, - bw: 4, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/A0001/*" }, { ua: "A0001" }], - dpi: [403.4, 401], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/ONE E1005/*" }, { ua: "ONE E1005" }], - dpi: [442.4, 441.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/ONE A2005/*" }, { ua: "ONE A2005" }], - dpi: [391.9, 405.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "OnePlus/*/ONEPLUS A5000/*" }, - { ua: "ONEPLUS A5000 " }, - ], - dpi: [403.411, 399.737], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/ONE A5010/*" }, { ua: "ONEPLUS A5010" }], - dpi: [403, 400], - bw: 2, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OPPO/*/X909/*" }, { ua: "X909" }], - dpi: [442.4, 444.1], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9082/*" }, { ua: "GT-I9082" }], - dpi: [184.7, 185.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G360P/*" }, { ua: "SM-G360P" }], - dpi: [196.7, 205.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/Nexus S/*" }, { ua: "Nexus S" }], - dpi: [234.5, 229.8], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9300/*" }, { ua: "GT-I9300" }], - dpi: [304.8, 303.9], - bw: 5, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-T230NU/*" }, { ua: "SM-T230NU" }], - dpi: 216, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SGH-T399/*" }, { ua: "SGH-T399" }], - dpi: [217.7, 231.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SGH-M919/*" }, { ua: "SGH-M919" }], - dpi: [440.8, 437.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N9005/*" }, { ua: "SM-N9005" }], - dpi: [386.4, 387], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [ - { mdmh: "samsung/*/SAMSUNG-SM-N900A/*" }, - { ua: "SAMSUNG-SM-N900A" }, - ], - dpi: [386.4, 387.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9500/*" }, { ua: "GT-I9500" }], - dpi: [442.5, 443.3], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9505/*" }, { ua: "GT-I9505" }], - dpi: 439.4, - bw: 4, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G900F/*" }, { ua: "SM-G900F" }], - dpi: [415.6, 431.6], - bw: 5, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G900M/*" }, { ua: "SM-G900M" }], - dpi: [415.6, 431.6], - bw: 5, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G800F/*" }, { ua: "SM-G800F" }], - dpi: 326.8, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G906S/*" }, { ua: "SM-G906S" }], - dpi: [562.7, 572.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9300/*" }, { ua: "GT-I9300" }], - dpi: [306.7, 304.8], - bw: 5, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-T535/*" }, { ua: "SM-T535" }], - dpi: [142.6, 136.4], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N920C/*" }, { ua: "SM-N920C" }], - dpi: [515.1, 518.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N920P/*" }, { ua: "SM-N920P" }], - dpi: [386.3655, 390.144], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N920W8/*" }, { ua: "SM-N920W8" }], - dpi: [515.1, 518.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9300I/*" }, { ua: "GT-I9300I" }], - dpi: [304.8, 305.8], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9195/*" }, { ua: "GT-I9195" }], - dpi: [249.4, 256.7], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SPH-L520/*" }, { ua: "SPH-L520" }], - dpi: [249.4, 255.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "samsung/*/SAMSUNG-SGH-I717/*" }, - { ua: "SAMSUNG-SGH-I717" }, - ], - dpi: 285.8, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SPH-D710/*" }, { ua: "SPH-D710" }], - dpi: [217.7, 204.2], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-N7100/*" }, { ua: "GT-N7100" }], - dpi: 265.1, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SCH-I605/*" }, { ua: "SCH-I605" }], - dpi: 265.1, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "samsung/*/Galaxy Nexus/*" }, - { ua: "Galaxy Nexus" }, - ], - dpi: [315.3, 314.2], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N910H/*" }, { ua: "SM-N910H" }], - dpi: [515.1, 518], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N910C/*" }, { ua: "SM-N910C" }], - dpi: [515.2, 520.2], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G130M/*" }, { ua: "SM-G130M" }], - dpi: [165.9, 164.8], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G928I/*" }, { ua: "SM-G928I" }], - dpi: [515.1, 518.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G920F/*" }, { ua: "SM-G920F" }], - dpi: 580.6, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G920P/*" }, { ua: "SM-G920P" }], - dpi: [522.5, 577], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G925F/*" }, { ua: "SM-G925F" }], - dpi: 580.6, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G925V/*" }, { ua: "SM-G925V" }], - dpi: [522.5, 576.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G930F/*" }, { ua: "SM-G930F" }], - dpi: 576.6, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G935F/*" }, { ua: "SM-G935F" }], - dpi: 533, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G950F/*" }, { ua: "SM-G950F" }], - dpi: [562.707, 565.293], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G955U/*" }, { ua: "SM-G955U" }], - dpi: [522.514, 525.762], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/C6903/*" }, { ua: "C6903" }], - dpi: [442.5, 443.3], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/D6653/*" }, { ua: "D6653" }], - dpi: [428.6, 427.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/E6653/*" }, { ua: "E6653" }], - dpi: [428.6, 425.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/E6853/*" }, { ua: "E6853" }], - dpi: [403.4, 401.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/SGP321/*" }, { ua: "SGP321" }], - dpi: [224.7, 224.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [ - { mdmh: "TCT/*/ALCATEL ONE TOUCH Fierce/*" }, - { ua: "ALCATEL ONE TOUCH Fierce" }, - ], - dpi: [240, 247.5], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "THL/*/thl 5000/*" }, { ua: "thl 5000" }], - dpi: [480, 443.3], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Fly/*/IQ4412/*" }, { ua: "IQ4412" }], - dpi: 307.9, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "ZTE/*/ZTE Blade L2/*" }, { ua: "ZTE Blade L2" }], - dpi: 240, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "BENEVE/*/VR518/*" }, { ua: "VR518" }], - dpi: 480, - bw: 3, - ac: 500, - }, - { - type: "ios", - rules: [{ res: [640, 960] }], - dpi: [325.1, 328.4], - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [640, 1136] }], - dpi: [317.1, 320.2], - bw: 3, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [750, 1334] }], - dpi: 326.4, - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [1242, 2208] }], - dpi: [453.6, 458.4], - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [1125, 2001] }], - dpi: [410.9, 415.4], - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [1125, 2436] }], - dpi: 458, - bw: 4, - ac: 1000, - }, - ]; - var DPDB_CACHE = { - format: format, - last_updated: last_updated, - devices: devices, - }; - function Dpdb(url, onDeviceParamsUpdated) { - this.dpdb = DPDB_CACHE; - this.recalculateDeviceParams_(); - if (url) { - this.onDeviceParamsUpdated = onDeviceParamsUpdated; - var xhr = new XMLHttpRequest(); - var obj = this; - xhr.open("GET", url, true); - xhr.addEventListener("load", function () { - obj.loading = false; - if (xhr.status >= 200 && xhr.status <= 299) { - obj.dpdb = JSON.parse(xhr.response); - obj.recalculateDeviceParams_(); - } else { - console.error("Error loading online DPDB!"); - } - }); - xhr.send(); - } - } - Dpdb.prototype.getDeviceParams = function () { - return this.deviceParams; - }; - Dpdb.prototype.recalculateDeviceParams_ = function () { - var newDeviceParams = this.calcDeviceParams_(); - if (newDeviceParams) { - this.deviceParams = newDeviceParams; - if (this.onDeviceParamsUpdated) { - this.onDeviceParamsUpdated(this.deviceParams); - } - } else { - console.error("Failed to recalculate device parameters."); - } - }; - Dpdb.prototype.calcDeviceParams_ = function () { - var db = this.dpdb; - if (!db) { - console.error("DPDB not available."); - return null; - } - if (db.format != 1) { - console.error("DPDB has unexpected format version."); - return null; - } - if (!db.devices || !db.devices.length) { - console.error("DPDB does not have a devices section."); - return null; - } - var userAgent = - navigator.userAgent || navigator.vendor || window.opera; - var width = getScreenWidth(); - var height = getScreenHeight(); - if (!db.devices) { - console.error("DPDB has no devices section."); - return null; - } - for (var i = 0; i < db.devices.length; i++) { - var device = db.devices[i]; - if (!device.rules) { - console.warn("Device[" + i + "] has no rules section."); - continue; - } - if (device.type != "ios" && device.type != "android") { - console.warn("Device[" + i + "] has invalid type."); - continue; - } - if (isIOS() != (device.type == "ios")) continue; - var matched = false; - for (var j = 0; j < device.rules.length; j++) { - var rule = device.rules[j]; - if (this.matchRule_(rule, userAgent, width, height)) { - matched = true; - break; - } - } - if (!matched) continue; - var xdpi = device.dpi[0] || device.dpi; - var ydpi = device.dpi[1] || device.dpi; - return new DeviceParams({ - xdpi: xdpi, - ydpi: ydpi, - bevelMm: device.bw, - }); - } - console.warn("No DPDB device match."); - return null; - }; - Dpdb.prototype.matchRule_ = function ( - rule, - ua, - screenWidth, - screenHeight - ) { - if (!rule.ua && !rule.res) return false; - if (rule.ua && ua.indexOf(rule.ua) < 0) return false; - if (rule.res) { - if (!rule.res[0] || !rule.res[1]) return false; - var resX = rule.res[0]; - var resY = rule.res[1]; - if ( - Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || - Math.max(screenWidth, screenHeight) != Math.max(resX, resY) - ) { - return false; - } - } - return true; - }; - function DeviceParams(params) { - this.xdpi = params.xdpi; - this.ydpi = params.ydpi; - this.bevelMm = params.bevelMm; - } - function SensorSample(sample, timestampS) { - this.set(sample, timestampS); - } - SensorSample.prototype.set = function (sample, timestampS) { - this.sample = sample; - this.timestampS = timestampS; - }; - SensorSample.prototype.copy = function (sensorSample) { - this.set(sensorSample.sample, sensorSample.timestampS); - }; - function ComplementaryFilter(kFilter, isDebug) { - this.kFilter = kFilter; - this.isDebug = isDebug; - this.currentAccelMeasurement = new SensorSample(); - this.currentGyroMeasurement = new SensorSample(); - this.previousGyroMeasurement = new SensorSample(); - if (isIOS()) { - this.filterQ = new Quaternion(-1, 0, 0, 1); - } else { - this.filterQ = new Quaternion(1, 0, 0, 1); - } - this.previousFilterQ = new Quaternion(); - this.previousFilterQ.copy(this.filterQ); - this.accelQ = new Quaternion(); - this.isOrientationInitialized = false; - this.estimatedGravity = new Vector3(); - this.measuredGravity = new Vector3(); - this.gyroIntegralQ = new Quaternion(); - } - ComplementaryFilter.prototype.addAccelMeasurement = function ( - vector, - timestampS - ) { - this.currentAccelMeasurement.set(vector, timestampS); - }; - ComplementaryFilter.prototype.addGyroMeasurement = function ( - vector, - timestampS - ) { - this.currentGyroMeasurement.set(vector, timestampS); - var deltaT = timestampS - this.previousGyroMeasurement.timestampS; - if (isTimestampDeltaValid(deltaT)) { - this.run_(); - } - this.previousGyroMeasurement.copy(this.currentGyroMeasurement); - }; - ComplementaryFilter.prototype.run_ = function () { - if (!this.isOrientationInitialized) { - this.accelQ = this.accelToQuaternion_( - this.currentAccelMeasurement.sample - ); - this.previousFilterQ.copy(this.accelQ); - this.isOrientationInitialized = true; - return; - } - var deltaT = - this.currentGyroMeasurement.timestampS - - this.previousGyroMeasurement.timestampS; - var gyroDeltaQ = this.gyroToQuaternionDelta_( - this.currentGyroMeasurement.sample, - deltaT - ); - this.gyroIntegralQ.multiply(gyroDeltaQ); - this.filterQ.copy(this.previousFilterQ); - this.filterQ.multiply(gyroDeltaQ); - var invFilterQ = new Quaternion(); - invFilterQ.copy(this.filterQ); - invFilterQ.inverse(); - this.estimatedGravity.set(0, 0, -1); - this.estimatedGravity.applyQuaternion(invFilterQ); - this.estimatedGravity.normalize(); - this.measuredGravity.copy(this.currentAccelMeasurement.sample); - this.measuredGravity.normalize(); - var deltaQ = new Quaternion(); - deltaQ.setFromUnitVectors( - this.estimatedGravity, - this.measuredGravity - ); - deltaQ.inverse(); - if (this.isDebug) { - console.log( - "Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)", - radToDeg * getQuaternionAngle(deltaQ), - this.estimatedGravity.x.toFixed(1), - this.estimatedGravity.y.toFixed(1), - this.estimatedGravity.z.toFixed(1), - this.measuredGravity.x.toFixed(1), - this.measuredGravity.y.toFixed(1), - this.measuredGravity.z.toFixed(1) - ); - } - var targetQ = new Quaternion(); - targetQ.copy(this.filterQ); - targetQ.multiply(deltaQ); - this.filterQ.slerp(targetQ, 1 - this.kFilter); - this.previousFilterQ.copy(this.filterQ); - }; - ComplementaryFilter.prototype.getOrientation = function () { - return this.filterQ; - }; - ComplementaryFilter.prototype.accelToQuaternion_ = function (accel) { - var normAccel = new Vector3(); - normAccel.copy(accel); - normAccel.normalize(); - var quat = new Quaternion(); - quat.setFromUnitVectors(new Vector3(0, 0, -1), normAccel); - quat.inverse(); - return quat; - }; - ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function ( - gyro, - dt - ) { - var quat = new Quaternion(); - var axis = new Vector3(); - axis.copy(gyro); - axis.normalize(); - quat.setFromAxisAngle(axis, gyro.length() * dt); - return quat; - }; - function PosePredictor(predictionTimeS, isDebug) { - this.predictionTimeS = predictionTimeS; - this.isDebug = isDebug; - this.previousQ = new Quaternion(); - this.previousTimestampS = null; - this.deltaQ = new Quaternion(); - this.outQ = new Quaternion(); - } - PosePredictor.prototype.getPrediction = function ( - currentQ, - gyro, - timestampS - ) { - if (!this.previousTimestampS) { - this.previousQ.copy(currentQ); - this.previousTimestampS = timestampS; - return currentQ; - } - var axis = new Vector3(); - axis.copy(gyro); - axis.normalize(); - var angularSpeed = gyro.length(); - if (angularSpeed < degToRad * 20) { - if (this.isDebug) { - console.log( - "Moving slowly, at %s deg/s: no prediction", - (radToDeg * angularSpeed).toFixed(1) - ); - } - this.outQ.copy(currentQ); - this.previousQ.copy(currentQ); - return this.outQ; - } - var predictAngle = angularSpeed * this.predictionTimeS; - this.deltaQ.setFromAxisAngle(axis, predictAngle); - this.outQ.copy(this.previousQ); - this.outQ.multiply(this.deltaQ); - this.previousQ.copy(currentQ); - this.previousTimestampS = timestampS; - return this.outQ; - }; - function FusionPoseSensor(kFilter, predictionTime, yawOnly, isDebug) { - this.yawOnly = yawOnly; - this.accelerometer = new Vector3(); - this.gyroscope = new Vector3(); - this.filter = new ComplementaryFilter(kFilter, isDebug); - this.posePredictor = new PosePredictor(predictionTime, isDebug); - this.isFirefoxAndroid = isFirefoxAndroid(); - this.isIOS = isIOS(); - var chromeVersion = getChromeVersion(); - this.isDeviceMotionInRadians = - !this.isIOS && chromeVersion && chromeVersion < 66; - this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion(); - this.filterToWorldQ = new Quaternion(); - if (isIOS()) { - this.filterToWorldQ.setFromAxisAngle( - new Vector3(1, 0, 0), - Math.PI / 2 - ); - } else { - this.filterToWorldQ.setFromAxisAngle( - new Vector3(1, 0, 0), - -Math.PI / 2 - ); - } - this.inverseWorldToScreenQ = new Quaternion(); - this.worldToScreenQ = new Quaternion(); - this.originalPoseAdjustQ = new Quaternion(); - this.originalPoseAdjustQ.setFromAxisAngle( - new Vector3(0, 0, 1), - (-window.orientation * Math.PI) / 180 - ); - this.setScreenTransform_(); - if (isLandscapeMode()) { - this.filterToWorldQ.multiply(this.inverseWorldToScreenQ); - } - this.resetQ = new Quaternion(); - this.orientationOut_ = new Float32Array(4); - this.start(); - } - FusionPoseSensor.prototype.getPosition = function () { - return null; - }; - FusionPoseSensor.prototype.getOrientation = function () { - var orientation = void 0; - if (this.isWithoutDeviceMotion && this._deviceOrientationQ) { - this.deviceOrientationFixQ = - this.deviceOrientationFixQ || - (function () { - var z = new Quaternion().setFromAxisAngle( - new Vector3(0, 0, -1), - 0 - ); - var y = new Quaternion(); - if (window.orientation === -90) { - y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / -2); - } else { - y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2); - } - return z.multiply(y); - })(); - this.deviceOrientationFilterToWorldQ = - this.deviceOrientationFilterToWorldQ || - (function () { - var q = new Quaternion(); - q.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2); - return q; - })(); - orientation = this._deviceOrientationQ; - var out = new Quaternion(); - out.copy(orientation); - out.multiply(this.deviceOrientationFilterToWorldQ); - out.multiply(this.resetQ); - out.multiply(this.worldToScreenQ); - out.multiplyQuaternions(this.deviceOrientationFixQ, out); - if (this.yawOnly) { - out.x = 0; - out.z = 0; - out.normalize(); - } - this.orientationOut_[0] = out.x; - this.orientationOut_[1] = out.y; - this.orientationOut_[2] = out.z; - this.orientationOut_[3] = out.w; - return this.orientationOut_; - } else { - var filterOrientation = this.filter.getOrientation(); - orientation = this.posePredictor.getPrediction( - filterOrientation, - this.gyroscope, - this.previousTimestampS - ); - } - var out = new Quaternion(); - out.copy(this.filterToWorldQ); - out.multiply(this.resetQ); - out.multiply(orientation); - out.multiply(this.worldToScreenQ); - if (this.yawOnly) { - out.x = 0; - out.z = 0; - out.normalize(); - } - this.orientationOut_[0] = out.x; - this.orientationOut_[1] = out.y; - this.orientationOut_[2] = out.z; - this.orientationOut_[3] = out.w; - return this.orientationOut_; - }; - FusionPoseSensor.prototype.resetPose = function () { - this.resetQ.copy(this.filter.getOrientation()); - this.resetQ.x = 0; - this.resetQ.y = 0; - this.resetQ.z *= -1; - this.resetQ.normalize(); - if (isLandscapeMode()) { - this.resetQ.multiply(this.inverseWorldToScreenQ); - } - this.resetQ.multiply(this.originalPoseAdjustQ); - }; - FusionPoseSensor.prototype.onDeviceOrientation_ = function (e) { - this._deviceOrientationQ = - this._deviceOrientationQ || new Quaternion(); - var alpha = e.alpha, - beta = e.beta, - gamma = e.gamma; - alpha = ((alpha || 0) * Math.PI) / 180; - beta = ((beta || 0) * Math.PI) / 180; - gamma = ((gamma || 0) * Math.PI) / 180; - this._deviceOrientationQ.setFromEulerYXZ(beta, alpha, -gamma); - }; - FusionPoseSensor.prototype.onDeviceMotion_ = function (deviceMotion) { - this.updateDeviceMotion_(deviceMotion); - }; - FusionPoseSensor.prototype.updateDeviceMotion_ = function ( - deviceMotion - ) { - var accGravity = deviceMotion.accelerationIncludingGravity; - var rotRate = deviceMotion.rotationRate; - var timestampS = deviceMotion.timeStamp / 1000; - var deltaS = timestampS - this.previousTimestampS; - if (deltaS < 0) { - warnOnce( - "fusion-pose-sensor:invalid:non-monotonic", - "Invalid timestamps detected: non-monotonic timestamp from devicemotion" - ); - this.previousTimestampS = timestampS; - return; - } else if (deltaS <= MIN_TIMESTEP || deltaS > MAX_TIMESTEP) { - warnOnce( - "fusion-pose-sensor:invalid:outside-threshold", - "Invalid timestamps detected: Timestamp from devicemotion outside expected range." - ); - this.previousTimestampS = timestampS; - return; - } - this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z); - if (isR7()) { - this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma); - } else { - this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); - } - if (!this.isDeviceMotionInRadians) { - this.gyroscope.multiplyScalar(Math.PI / 180); - } - this.filter.addAccelMeasurement(this.accelerometer, timestampS); - this.filter.addGyroMeasurement(this.gyroscope, timestampS); - this.previousTimestampS = timestampS; - }; - FusionPoseSensor.prototype.onOrientationChange_ = function ( - screenOrientation - ) { - this.setScreenTransform_(); - }; - FusionPoseSensor.prototype.onMessage_ = function (event) { - var message = event.data; - if (!message || !message.type) { - return; - } - var type = message.type.toLowerCase(); - if (type !== "devicemotion") { - return; - } - this.updateDeviceMotion_(message.deviceMotionEvent); - }; - FusionPoseSensor.prototype.setScreenTransform_ = function () { - this.worldToScreenQ.set(0, 0, 0, 1); - switch (window.orientation) { - case 0: - break; - case 90: - this.worldToScreenQ.setFromAxisAngle( - new Vector3(0, 0, 1), - -Math.PI / 2 - ); - break; - case -90: - this.worldToScreenQ.setFromAxisAngle( - new Vector3(0, 0, 1), - Math.PI / 2 - ); - break; - case 180: - break; - } - this.inverseWorldToScreenQ.copy(this.worldToScreenQ); - this.inverseWorldToScreenQ.inverse(); - }; - FusionPoseSensor.prototype.start = function () { - this.onDeviceMotionCallback_ = this.onDeviceMotion_.bind(this); - this.onOrientationChangeCallback_ = - this.onOrientationChange_.bind(this); - this.onMessageCallback_ = this.onMessage_.bind(this); - this.onDeviceOrientationCallback_ = - this.onDeviceOrientation_.bind(this); - if (isIOS() && isInsideCrossOriginIFrame()) { - window.addEventListener("message", this.onMessageCallback_); - } - window.addEventListener( - "orientationchange", - this.onOrientationChangeCallback_ - ); - if (this.isWithoutDeviceMotion) { - window.addEventListener( - "deviceorientation", - this.onDeviceOrientationCallback_ - ); - } else { - window.addEventListener( - "devicemotion", - this.onDeviceMotionCallback_ - ); - } - }; - FusionPoseSensor.prototype.stop = function () { - window.removeEventListener( - "devicemotion", - this.onDeviceMotionCallback_ - ); - window.removeEventListener( - "deviceorientation", - this.onDeviceOrientationCallback_ - ); - window.removeEventListener( - "orientationchange", - this.onOrientationChangeCallback_ - ); - window.removeEventListener("message", this.onMessageCallback_); - }; - var SENSOR_FREQUENCY = 60; - var X_AXIS = new Vector3(1, 0, 0); - var Z_AXIS = new Vector3(0, 0, 1); - var orientation = {}; - if (screen.orientation) { - orientation = screen.orientation; - } else if (screen.msOrientation) { - orientation = screen.msOrientation; - } else { - Object.defineProperty(orientation, "angle", { - get: function get$$1() { - return window.orientation || 0; - }, - }); - } - var SENSOR_TO_VR = new Quaternion(); - SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2); - SENSOR_TO_VR.multiply( - new Quaternion().setFromAxisAngle(Z_AXIS, Math.PI / 2) - ); - var PoseSensor = (function () { - function PoseSensor(config) { - classCallCheck(this, PoseSensor); - this.config = config; - this.sensor = null; - this.fusionSensor = null; - this._out = new Float32Array(4); - this.api = null; - this.errors = []; - this._sensorQ = new Quaternion(); - this._worldToScreenQ = new Quaternion(); - this._outQ = new Quaternion(); - this._onSensorRead = this._onSensorRead.bind(this); - this._onSensorError = this._onSensorError.bind(this); - this._onOrientationChange = this._onOrientationChange.bind(this); - this._onOrientationChange(); - this.init(); - } - createClass(PoseSensor, [ - { - key: "init", - value: function init() { - var sensor = null; - try { - sensor = new RelativeOrientationSensor({ - frequency: SENSOR_FREQUENCY, - }); - sensor.addEventListener("error", this._onSensorError); - } catch (error) { - this.errors.push(error); - if (error.name === "SecurityError") { - console.error( - "Cannot construct sensors due to the Feature Policy" - ); - console.warn( - 'Attempting to fall back using "devicemotion"; however this will ' + - "fail in the future without correct permissions." - ); - this.useDeviceMotion(); - } else if (error.name === "ReferenceError") { - this.useDeviceMotion(); - } else { - console.error(error); - } - } - if (sensor) { - this.api = "sensor"; - this.sensor = sensor; - this.sensor.addEventListener("reading", this._onSensorRead); - this.sensor.start(); - } - window.addEventListener( - "orientationchange", - this._onOrientationChange - ); - }, - }, - { - key: "useDeviceMotion", - value: function useDeviceMotion() { - this.api = "devicemotion"; - this.fusionSensor = new FusionPoseSensor( - this.config.K_FILTER, - this.config.PREDICTION_TIME_S, - this.config.YAW_ONLY, - this.config.DEBUG - ); - }, - }, - { - key: "getOrientation", - value: function getOrientation() { - if (this.fusionSensor) { - return this.fusionSensor.getOrientation(); - } - if (!this.sensor || !this.sensor.quaternion) { - this._out[0] = this._out[1] = this._out[2] = 0; - this._out[3] = 1; - return this._out; - } - var q = this.sensor.quaternion; - this._sensorQ.set(q[0], q[1], q[2], q[3]); - var out = this._outQ; - out.copy(SENSOR_TO_VR); - out.multiply(this._sensorQ); - out.multiply(this._worldToScreenQ); - if (this.config.YAW_ONLY) { - out.x = out.z = 0; - out.normalize(); - } - this._out[0] = out.x; - this._out[1] = out.y; - this._out[2] = out.z; - this._out[3] = out.w; - return this._out; - }, - }, - { - key: "_onSensorError", - value: function _onSensorError(event) { - this.errors.push(event.error); - if (event.error.name === "NotAllowedError") { - console.error("Permission to access sensor was denied"); - } else if (event.error.name === "NotReadableError") { - console.error("Sensor could not be read"); - } else { - console.error(event.error); - } - }, - }, - { - key: "_onSensorRead", - value: function _onSensorRead() {}, - }, - { - key: "_onOrientationChange", - value: function _onOrientationChange() { - var angle = (-orientation.angle * Math.PI) / 180; - this._worldToScreenQ.setFromAxisAngle(Z_AXIS, angle); - }, - }, - ]); - return PoseSensor; - })(); - var rotateInstructionsAsset = - "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyBDNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCBDMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE5LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEMxMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4yMTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzLDE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE5Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSBMNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiBMMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2LDY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+"; - function RotateInstructions() { - this.loadIcon_(); - var overlay = document.createElement("div"); - var s = overlay.style; - s.position = "fixed"; - s.top = 0; - s.right = 0; - s.bottom = 0; - s.left = 0; - s.backgroundColor = "gray"; - s.fontFamily = "sans-serif"; - s.zIndex = 1000000; - var img = document.createElement("img"); - img.src = this.icon; - var s = img.style; - s.marginLeft = "25%"; - s.marginTop = "25%"; - s.width = "50%"; - overlay.appendChild(img); - var text = document.createElement("div"); - var s = text.style; - s.textAlign = "center"; - s.fontSize = "16px"; - s.lineHeight = "24px"; - s.margin = "24px 25%"; - s.width = "50%"; - text.innerHTML = "Place your phone into your Cardboard viewer."; - overlay.appendChild(text); - var snackbar = document.createElement("div"); - var s = snackbar.style; - s.backgroundColor = "#CFD8DC"; - s.position = "fixed"; - s.bottom = 0; - s.width = "100%"; - s.height = "48px"; - s.padding = "14px 24px"; - s.boxSizing = "border-box"; - s.color = "#656A6B"; - overlay.appendChild(snackbar); - var snackbarText = document.createElement("div"); - snackbarText.style.float = "left"; - snackbarText.innerHTML = "No Cardboard viewer?"; - var snackbarButton = document.createElement("a"); - snackbarButton.href = - "https://www.google.com/get/cardboard/get-cardboard/"; - snackbarButton.innerHTML = "get one"; - snackbarButton.target = "_blank"; - var s = snackbarButton.style; - s.float = "right"; - s.fontWeight = 600; - s.textTransform = "uppercase"; - s.borderLeft = "1px solid gray"; - s.paddingLeft = "24px"; - s.textDecoration = "none"; - s.color = "#656A6B"; - snackbar.appendChild(snackbarText); - snackbar.appendChild(snackbarButton); - this.overlay = overlay; - this.text = text; - this.hide(); - } - RotateInstructions.prototype.show = function (parent) { - if (!parent && !this.overlay.parentElement) { - document.body.appendChild(this.overlay); - } else if (parent) { - if ( - this.overlay.parentElement && - this.overlay.parentElement != parent - ) - this.overlay.parentElement.removeChild(this.overlay); - parent.appendChild(this.overlay); - } - this.overlay.style.display = "block"; - var img = this.overlay.querySelector("img"); - var s = img.style; - if (isLandscapeMode()) { - s.width = "20%"; - s.marginLeft = "40%"; - s.marginTop = "3%"; - } else { - s.width = "50%"; - s.marginLeft = "25%"; - s.marginTop = "25%"; - } - }; - RotateInstructions.prototype.hide = function () { - this.overlay.style.display = "none"; - }; - RotateInstructions.prototype.showTemporarily = function (ms, parent) { - this.show(parent); - this.timer = setTimeout(this.hide.bind(this), ms); - }; - RotateInstructions.prototype.disableShowTemporarily = function () { - clearTimeout(this.timer); - }; - RotateInstructions.prototype.update = function () { - this.disableShowTemporarily(); - if (!isLandscapeMode() && isMobile()) { - this.show(); - } else { - this.hide(); - } - }; - RotateInstructions.prototype.loadIcon_ = function () { - this.icon = base64("image/svg+xml", rotateInstructionsAsset); - }; - var DEFAULT_VIEWER = "CardboardV1"; - var VIEWER_KEY = "WEBVR_CARDBOARD_VIEWER"; - var CLASS_NAME = "webvr-polyfill-viewer-selector"; - function ViewerSelector() { - try { - this.selectedKey = localStorage.getItem(VIEWER_KEY); - } catch (error) { - console.error("Failed to load viewer profile: %s", error); - } - if (!this.selectedKey) { - this.selectedKey = DEFAULT_VIEWER; - } - this.dialog = this.createDialog_(DeviceInfo.Viewers); - this.root = null; - this.onChangeCallbacks_ = []; - } - ViewerSelector.prototype.show = function (root) { - this.root = root; - root.appendChild(this.dialog); - var selected = this.dialog.querySelector("#" + this.selectedKey); - selected.checked = true; - this.dialog.style.display = "block"; - }; - ViewerSelector.prototype.hide = function () { - if (this.root && this.root.contains(this.dialog)) { - this.root.removeChild(this.dialog); - } - this.dialog.style.display = "none"; - }; - ViewerSelector.prototype.getCurrentViewer = function () { - return DeviceInfo.Viewers[this.selectedKey]; - }; - ViewerSelector.prototype.getSelectedKey_ = function () { - var input = this.dialog.querySelector("input[name=field]:checked"); - if (input) { - return input.id; - } - return null; - }; - ViewerSelector.prototype.onChange = function (cb) { - this.onChangeCallbacks_.push(cb); - }; - ViewerSelector.prototype.fireOnChange_ = function (viewer) { - for (var i = 0; i < this.onChangeCallbacks_.length; i++) { - this.onChangeCallbacks_[i](viewer); - } - }; - ViewerSelector.prototype.onSave_ = function () { - this.selectedKey = this.getSelectedKey_(); - if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) { - console.error("ViewerSelector.onSave_: this should never happen!"); - return; - } - this.fireOnChange_(DeviceInfo.Viewers[this.selectedKey]); - try { - localStorage.setItem(VIEWER_KEY, this.selectedKey); - } catch (error) { - console.error("Failed to save viewer profile: %s", error); - } - this.hide(); - }; - ViewerSelector.prototype.createDialog_ = function (options) { - var container = document.createElement("div"); - container.classList.add(CLASS_NAME); - container.style.display = "none"; - var overlay = document.createElement("div"); - var s = overlay.style; - s.position = "fixed"; - s.left = 0; - s.top = 0; - s.width = "100%"; - s.height = "100%"; - s.background = "rgba(0, 0, 0, 0.3)"; - overlay.addEventListener("click", this.hide.bind(this)); - var width = 280; - var dialog = document.createElement("div"); - var s = dialog.style; - s.boxSizing = "border-box"; - s.position = "fixed"; - s.top = "24px"; - s.left = "50%"; - s.marginLeft = -width / 2 + "px"; - s.width = width + "px"; - s.padding = "24px"; - s.overflow = "hidden"; - s.background = "#fafafa"; - s.fontFamily = "'Roboto', sans-serif"; - s.boxShadow = "0px 5px 20px #666"; - dialog.appendChild(this.createH1_("Select your viewer")); - for (var id in options) { - dialog.appendChild(this.createChoice_(id, options[id].label)); - } - dialog.appendChild( - this.createButton_("Save", this.onSave_.bind(this)) - ); - container.appendChild(overlay); - container.appendChild(dialog); - return container; - }; - ViewerSelector.prototype.createH1_ = function (name) { - var h1 = document.createElement("h1"); - var s = h1.style; - s.color = "black"; - s.fontSize = "20px"; - s.fontWeight = "bold"; - s.marginTop = 0; - s.marginBottom = "24px"; - h1.innerHTML = name; - return h1; - }; - ViewerSelector.prototype.createChoice_ = function (id, name) { - var div = document.createElement("div"); - div.style.marginTop = "8px"; - div.style.color = "black"; - var input = document.createElement("input"); - input.style.fontSize = "30px"; - input.setAttribute("id", id); - input.setAttribute("type", "radio"); - input.setAttribute("value", id); - input.setAttribute("name", "field"); - var label = document.createElement("label"); - label.style.marginLeft = "4px"; - label.setAttribute("for", id); - label.innerHTML = name; - div.appendChild(input); - div.appendChild(label); - return div; - }; - ViewerSelector.prototype.createButton_ = function (label, onclick) { - var button = document.createElement("button"); - button.innerHTML = label; - var s = button.style; - s.float = "right"; - s.textTransform = "uppercase"; - s.color = "#1094f7"; - s.fontSize = "14px"; - s.letterSpacing = 0; - s.border = 0; - s.background = "none"; - s.marginTop = "16px"; - button.addEventListener("click", onclick); - return button; - }; - var commonjsGlobal$$1 = - typeof window !== "undefined" - ? window - : typeof commonjsGlobal$$1 !== "undefined" - ? commonjsGlobal$$1 - : typeof self !== "undefined" - ? self - : {}; - function unwrapExports$$1(x) { - return x && x.__esModule ? x["default"] : x; - } - function createCommonjsModule$$1(fn, module) { - return ( - (module = { exports: {} }), - fn(module, module.exports), - module.exports - ); - } - var NoSleep = createCommonjsModule$$1(function (module, exports) { - (function webpackUniversalModuleDefinition(root, factory) { - module.exports = factory(); - })(commonjsGlobal$$1, function () { - return (function (modules) { - var installedModules = {}; - function __webpack_require__(moduleId) { - if (installedModules[moduleId]) { - return installedModules[moduleId].exports; - } - var module = (installedModules[moduleId] = { - i: moduleId, - l: false, - exports: {}, - }); - modules[moduleId].call( - module.exports, - module, - module.exports, - __webpack_require__ - ); - module.l = true; - return module.exports; - } - __webpack_require__.m = modules; - __webpack_require__.c = installedModules; - __webpack_require__.d = function (exports, name, getter) { - if (!__webpack_require__.o(exports, name)) { - Object.defineProperty(exports, name, { - configurable: false, - enumerable: true, - get: getter, - }); - } - }; - __webpack_require__.n = function (module) { - var getter = - module && module.__esModule - ? function getDefault() { - return module["default"]; - } - : function getModuleExports() { - return module; - }; - __webpack_require__.d(getter, "a", getter); - return getter; - }; - __webpack_require__.o = function (object, property) { - return Object.prototype.hasOwnProperty.call(object, property); - }; - __webpack_require__.p = ""; - return __webpack_require__((__webpack_require__.s = 0)); - })([ - function (module, exports, __webpack_require__) { - var _createClass = (function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - return function (Constructor, protoProps, staticProps) { - if (protoProps) - defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - })(); - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - var mediaFile = __webpack_require__(1); - var oldIOS = - typeof navigator !== "undefined" && - parseFloat( - ( - "" + - (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec( - navigator.userAgent - ) || [0, ""])[1] - ) - .replace("undefined", "3_2") - .replace("_", ".") - .replace("_", "") - ) < 10 && - !window.MSStream; - var NoSleep = (function () { - function NoSleep() { - _classCallCheck(this, NoSleep); - if (oldIOS) { - this.noSleepTimer = null; - } else { - this.noSleepVideo = document.createElement("video"); - this.noSleepVideo.setAttribute("playsinline", ""); - this.noSleepVideo.setAttribute("src", mediaFile); - this.noSleepVideo.addEventListener( - "timeupdate", - function (e) { - if (this.noSleepVideo.currentTime > 0.5) { - this.noSleepVideo.currentTime = Math.random(); - } - }.bind(this) - ); - } - } - _createClass(NoSleep, [ - { - key: "enable", - value: function enable() { - if (oldIOS) { - this.disable(); - this.noSleepTimer = window.setInterval(function () { - window.location.href = "/"; - window.setTimeout(window.stop, 0); - }, 15000); - } else { - this.noSleepVideo.play(); - } - }, - }, - { - key: "disable", - value: function disable() { - if (oldIOS) { - if (this.noSleepTimer) { - window.clearInterval(this.noSleepTimer); - this.noSleepTimer = null; - } - } else { - this.noSleepVideo.pause(); - } - }, - }, - ]); - return NoSleep; - })(); - module.exports = NoSleep; - }, - function (module, exports, __webpack_require__) { - module.exports = - "data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA="; - }, - ]); - }); - }); - var NoSleep$1 = unwrapExports$$1(NoSleep); - var nextDisplayId = 1000; - var defaultLeftBounds = [0, 0, 0.5, 1]; - var defaultRightBounds = [0.5, 0, 0.5, 1]; - var raf = window.requestAnimationFrame; - var caf = window.cancelAnimationFrame; - function VRFrameData() { - this.leftProjectionMatrix = new Float32Array(16); - this.leftViewMatrix = new Float32Array(16); - this.rightProjectionMatrix = new Float32Array(16); - this.rightViewMatrix = new Float32Array(16); - this.pose = null; - } - function VRDisplayCapabilities(config) { - Object.defineProperties(this, { - hasPosition: { - writable: false, - enumerable: true, - value: config.hasPosition, - }, - hasExternalDisplay: { - writable: false, - enumerable: true, - value: config.hasExternalDisplay, - }, - canPresent: { - writable: false, - enumerable: true, - value: config.canPresent, - }, - maxLayers: { - writable: false, - enumerable: true, - value: config.maxLayers, - }, - hasOrientation: { - enumerable: true, - get: function get() { - deprecateWarning( - "VRDisplayCapabilities.prototype.hasOrientation", - "VRDisplay.prototype.getFrameData" - ); - return config.hasOrientation; - }, - }, - }); - } - function VRDisplay(config) { - config = config || {}; - var USE_WAKELOCK = "wakelock" in config ? config.wakelock : true; - this.isPolyfilled = true; - this.displayId = nextDisplayId++; - this.displayName = ""; - this.depthNear = 0.01; - this.depthFar = 10000.0; - this.isPresenting = false; - Object.defineProperty(this, "isConnected", { - get: function get() { - deprecateWarning( - "VRDisplay.prototype.isConnected", - "VRDisplayCapabilities.prototype.hasExternalDisplay" - ); - return false; - }, - }); - this.capabilities = new VRDisplayCapabilities({ - hasPosition: false, - hasOrientation: false, - hasExternalDisplay: false, - canPresent: false, - maxLayers: 1, - }); - this.stageParameters = null; - this.waitingForPresent_ = false; - this.layer_ = null; - this.originalParent_ = null; - this.fullscreenElement_ = null; - this.fullscreenWrapper_ = null; - this.fullscreenElementCachedStyle_ = null; - this.fullscreenEventTarget_ = null; - this.fullscreenChangeHandler_ = null; - this.fullscreenErrorHandler_ = null; - if (USE_WAKELOCK && isMobile()) { - this.wakelock_ = new NoSleep$1(); - } - } - VRDisplay.prototype.getFrameData = function (frameData) { - return frameDataFromPose(frameData, this._getPose(), this); - }; - VRDisplay.prototype.getPose = function () { - deprecateWarning( - "VRDisplay.prototype.getPose", - "VRDisplay.prototype.getFrameData" - ); - return this._getPose(); - }; - VRDisplay.prototype.resetPose = function () { - deprecateWarning("VRDisplay.prototype.resetPose"); - return this._resetPose(); - }; - VRDisplay.prototype.getImmediatePose = function () { - deprecateWarning( - "VRDisplay.prototype.getImmediatePose", - "VRDisplay.prototype.getFrameData" - ); - return this._getPose(); - }; - VRDisplay.prototype.requestAnimationFrame = function (callback) { - return raf(callback); - }; - VRDisplay.prototype.cancelAnimationFrame = function (id) { - return caf(id); - }; - VRDisplay.prototype.wrapForFullscreen = function (element) { - if (isIOS()) { - return element; - } - if (!this.fullscreenWrapper_) { - this.fullscreenWrapper_ = document.createElement("div"); - var cssProperties = [ - "height: " + - Math.min(screen.height, screen.width) + - "px !important", - "top: 0 !important", - "left: 0 !important", - "right: 0 !important", - "border: 0", - "margin: 0", - "padding: 0", - "z-index: 999999 !important", - "position: fixed", - ]; - this.fullscreenWrapper_.setAttribute( - "style", - cssProperties.join("; ") + ";" - ); - this.fullscreenWrapper_.classList.add( - "webvr-polyfill-fullscreen-wrapper" - ); - } - if (this.fullscreenElement_ == element) { - return this.fullscreenWrapper_; - } - if (this.fullscreenElement_) { - if (this.originalParent_) { - this.originalParent_.appendChild(this.fullscreenElement_); - } else { - this.fullscreenElement_.parentElement.removeChild( - this.fullscreenElement_ - ); - } - } - this.fullscreenElement_ = element; - this.originalParent_ = element.parentElement; - if (!this.originalParent_) { - document.body.appendChild(element); - } - if (!this.fullscreenWrapper_.parentElement) { - var parent = this.fullscreenElement_.parentElement; - parent.insertBefore( - this.fullscreenWrapper_, - this.fullscreenElement_ - ); - parent.removeChild(this.fullscreenElement_); - } - this.fullscreenWrapper_.insertBefore( - this.fullscreenElement_, - this.fullscreenWrapper_.firstChild - ); - this.fullscreenElementCachedStyle_ = - this.fullscreenElement_.getAttribute("style"); - var self = this; - function applyFullscreenElementStyle() { - if (!self.fullscreenElement_) { - return; - } - var cssProperties = [ - "position: absolute", - "top: 0", - "left: 0", - "width: " + Math.max(screen.width, screen.height) + "px", - "height: " + Math.min(screen.height, screen.width) + "px", - "border: 0", - "margin: 0", - "padding: 0", - ]; - self.fullscreenElement_.setAttribute( - "style", - cssProperties.join("; ") + ";" - ); - } - applyFullscreenElementStyle(); - return this.fullscreenWrapper_; - }; - VRDisplay.prototype.removeFullscreenWrapper = function () { - if (!this.fullscreenElement_) { - return; - } - var element = this.fullscreenElement_; - if (this.fullscreenElementCachedStyle_) { - element.setAttribute("style", this.fullscreenElementCachedStyle_); - } else { - element.removeAttribute("style"); - } - this.fullscreenElement_ = null; - this.fullscreenElementCachedStyle_ = null; - var parent = this.fullscreenWrapper_.parentElement; - this.fullscreenWrapper_.removeChild(element); - if (this.originalParent_ === parent) { - parent.insertBefore(element, this.fullscreenWrapper_); - } else if (this.originalParent_) { - this.originalParent_.appendChild(element); - } - parent.removeChild(this.fullscreenWrapper_); - return element; - }; - VRDisplay.prototype.requestPresent = function (layers) { - var wasPresenting = this.isPresenting; - var self = this; - if (!(layers instanceof Array)) { - deprecateWarning( - "VRDisplay.prototype.requestPresent with non-array argument", - "an array of VRLayers as the first argument" - ); - layers = [layers]; - } - return new Promise(function (resolve, reject) { - if (!self.capabilities.canPresent) { - reject(new Error("VRDisplay is not capable of presenting.")); - return; - } - if ( - layers.length == 0 || - layers.length > self.capabilities.maxLayers - ) { - reject(new Error("Invalid number of layers.")); - return; - } - var incomingLayer = layers[0]; - if (!incomingLayer.source) { - resolve(); - return; - } - var leftBounds = incomingLayer.leftBounds || defaultLeftBounds; - var rightBounds = incomingLayer.rightBounds || defaultRightBounds; - if (wasPresenting) { - var layer = self.layer_; - if (layer.source !== incomingLayer.source) { - layer.source = incomingLayer.source; - } - for (var i = 0; i < 4; i++) { - layer.leftBounds[i] = leftBounds[i]; - layer.rightBounds[i] = rightBounds[i]; - } - self.wrapForFullscreen(self.layer_.source); - self.updatePresent_(); - resolve(); - return; - } - self.layer_ = { - predistorted: incomingLayer.predistorted, - source: incomingLayer.source, - leftBounds: leftBounds.slice(0), - rightBounds: rightBounds.slice(0), - }; - self.waitingForPresent_ = false; - if (self.layer_ && self.layer_.source) { - var fullscreenElement = self.wrapForFullscreen( - self.layer_.source - ); - var onFullscreenChange = function onFullscreenChange() { - var actualFullscreenElement = getFullscreenElement(); - self.isPresenting = - fullscreenElement === actualFullscreenElement; - if (self.isPresenting) { - if (screen.orientation && screen.orientation.lock) { - screen.orientation - .lock("landscape-primary") - .catch(function (error) { - console.error( - "screen.orientation.lock() failed due to", - error.message - ); - }); - } - self.waitingForPresent_ = false; - self.beginPresent_(); - resolve(); - } else { - if (screen.orientation && screen.orientation.unlock) { - screen.orientation.unlock(); - } - self.removeFullscreenWrapper(); - self.disableWakeLock(); - self.endPresent_(); - self.removeFullscreenListeners_(); - } - self.fireVRDisplayPresentChange_(); - }; - var onFullscreenError = function onFullscreenError() { - if (!self.waitingForPresent_) { - return; - } - self.removeFullscreenWrapper(); - self.removeFullscreenListeners_(); - self.disableWakeLock(); - self.waitingForPresent_ = false; - self.isPresenting = false; - reject(new Error("Unable to present.")); - }; - self.addFullscreenListeners_( - fullscreenElement, - onFullscreenChange, - onFullscreenError - ); - if (requestFullscreen(fullscreenElement)) { - self.enableWakeLock(); - self.waitingForPresent_ = true; - } else if (isIOS() || isWebViewAndroid()) { - self.enableWakeLock(); - self.isPresenting = true; - self.beginPresent_(); - self.fireVRDisplayPresentChange_(); - resolve(); - } - } - if (!self.waitingForPresent_ && !isIOS()) { - exitFullscreen(); - reject(new Error("Unable to present.")); - } - }); - }; - VRDisplay.prototype.exitPresent = function () { - var wasPresenting = this.isPresenting; - var self = this; - this.isPresenting = false; - this.layer_ = null; - this.disableWakeLock(); - return new Promise(function (resolve, reject) { - if (wasPresenting) { - if (!exitFullscreen() && isIOS()) { - self.endPresent_(); - self.fireVRDisplayPresentChange_(); - } - if (isWebViewAndroid()) { - self.removeFullscreenWrapper(); - self.removeFullscreenListeners_(); - self.endPresent_(); - self.fireVRDisplayPresentChange_(); - } - resolve(); - } else { - reject(new Error("Was not presenting to VRDisplay.")); - } - }); - }; - VRDisplay.prototype.getLayers = function () { - if (this.layer_) { - return [this.layer_]; - } - return []; - }; - VRDisplay.prototype.fireVRDisplayPresentChange_ = function () { - var event = new CustomEvent("vrdisplaypresentchange", { - detail: { display: this }, - }); - window.dispatchEvent(event); - }; - VRDisplay.prototype.fireVRDisplayConnect_ = function () { - var event = new CustomEvent("vrdisplayconnect", { - detail: { display: this }, - }); - window.dispatchEvent(event); - }; - VRDisplay.prototype.addFullscreenListeners_ = function ( - element, - changeHandler, - errorHandler - ) { - this.removeFullscreenListeners_(); - this.fullscreenEventTarget_ = element; - this.fullscreenChangeHandler_ = changeHandler; - this.fullscreenErrorHandler_ = errorHandler; - if (changeHandler) { - if (document.fullscreenEnabled) { - element.addEventListener( - "fullscreenchange", - changeHandler, - false - ); - } else if (document.webkitFullscreenEnabled) { - element.addEventListener( - "webkitfullscreenchange", - changeHandler, - false - ); - } else if (document.mozFullScreenEnabled) { - document.addEventListener( - "mozfullscreenchange", - changeHandler, - false - ); - } else if (document.msFullscreenEnabled) { - element.addEventListener( - "msfullscreenchange", - changeHandler, - false - ); - } - } - if (errorHandler) { - if (document.fullscreenEnabled) { - element.addEventListener("fullscreenerror", errorHandler, false); - } else if (document.webkitFullscreenEnabled) { - element.addEventListener( - "webkitfullscreenerror", - errorHandler, - false - ); - } else if (document.mozFullScreenEnabled) { - document.addEventListener( - "mozfullscreenerror", - errorHandler, - false - ); - } else if (document.msFullscreenEnabled) { - element.addEventListener( - "msfullscreenerror", - errorHandler, - false - ); - } - } - }; - VRDisplay.prototype.removeFullscreenListeners_ = function () { - if (!this.fullscreenEventTarget_) return; - var element = this.fullscreenEventTarget_; - if (this.fullscreenChangeHandler_) { - var changeHandler = this.fullscreenChangeHandler_; - element.removeEventListener( - "fullscreenchange", - changeHandler, - false - ); - element.removeEventListener( - "webkitfullscreenchange", - changeHandler, - false - ); - document.removeEventListener( - "mozfullscreenchange", - changeHandler, - false - ); - element.removeEventListener( - "msfullscreenchange", - changeHandler, - false - ); - } - if (this.fullscreenErrorHandler_) { - var errorHandler = this.fullscreenErrorHandler_; - element.removeEventListener("fullscreenerror", errorHandler, false); - element.removeEventListener( - "webkitfullscreenerror", - errorHandler, - false - ); - document.removeEventListener( - "mozfullscreenerror", - errorHandler, - false - ); - element.removeEventListener( - "msfullscreenerror", - errorHandler, - false - ); - } - this.fullscreenEventTarget_ = null; - this.fullscreenChangeHandler_ = null; - this.fullscreenErrorHandler_ = null; - }; - VRDisplay.prototype.enableWakeLock = function () { - if (this.wakelock_) { - this.wakelock_.enable(); - } - }; - VRDisplay.prototype.disableWakeLock = function () { - if (this.wakelock_) { - this.wakelock_.disable(); - } - }; - VRDisplay.prototype.beginPresent_ = function () {}; - VRDisplay.prototype.endPresent_ = function () {}; - VRDisplay.prototype.submitFrame = function (pose) {}; - VRDisplay.prototype.getEyeParameters = function (whichEye) { - return null; - }; - var config = { - MOBILE_WAKE_LOCK: true, - DEBUG: false, - DPDB_URL: "https://dpdb.webvr.rocks/dpdb.json", - K_FILTER: 0.98, - PREDICTION_TIME_S: 0.04, - CARDBOARD_UI_DISABLED: false, - ROTATE_INSTRUCTIONS_DISABLED: false, - YAW_ONLY: false, - BUFFER_SCALE: 0.5, - DIRTY_SUBMIT_FRAME_BINDINGS: false, - }; - var Eye = { - LEFT: "left", - RIGHT: "right", - }; - function CardboardVRDisplay(config$$1) { - var defaults = extend({}, config); - config$$1 = extend(defaults, config$$1 || {}); - VRDisplay.call(this, { - wakelock: config$$1.MOBILE_WAKE_LOCK, - }); - this.config = config$$1; - this.displayName = "Cardboard VRDisplay"; - this.capabilities = new VRDisplayCapabilities({ - hasPosition: false, - hasOrientation: true, - hasExternalDisplay: false, - canPresent: true, - maxLayers: 1, - }); - this.stageParameters = null; - this.bufferScale_ = this.config.BUFFER_SCALE; - this.poseSensor_ = new PoseSensor(this.config); - this.distorter_ = null; - this.cardboardUI_ = null; - this.dpdb_ = new Dpdb( - this.config.DPDB_URL, - this.onDeviceParamsUpdated_.bind(this) - ); - this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams()); - this.viewerSelector_ = new ViewerSelector(); - this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)); - this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()); - if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) { - this.rotateInstructions_ = new RotateInstructions(); - } - if (isIOS()) { - window.addEventListener("resize", this.onResize_.bind(this)); - } - } - CardboardVRDisplay.prototype = Object.create(VRDisplay.prototype); - CardboardVRDisplay.prototype._getPose = function () { - return { - position: null, - orientation: this.poseSensor_.getOrientation(), - linearVelocity: null, - linearAcceleration: null, - angularVelocity: null, - angularAcceleration: null, - }; - }; - CardboardVRDisplay.prototype._resetPose = function () { - if (this.poseSensor_.resetPose) { - this.poseSensor_.resetPose(); - } - }; - CardboardVRDisplay.prototype._getFieldOfView = function (whichEye) { - var fieldOfView; - if (whichEye == Eye.LEFT) { - fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye(); - } else if (whichEye == Eye.RIGHT) { - fieldOfView = this.deviceInfo_.getFieldOfViewRightEye(); - } else { - console.error("Invalid eye provided: %s", whichEye); - return null; - } - return fieldOfView; - }; - CardboardVRDisplay.prototype._getEyeOffset = function (whichEye) { - var offset; - if (whichEye == Eye.LEFT) { - offset = [ - -this.deviceInfo_.viewer.interLensDistance * 0.5, - 0.0, - 0.0, - ]; - } else if (whichEye == Eye.RIGHT) { - offset = [ - this.deviceInfo_.viewer.interLensDistance * 0.5, - 0.0, - 0.0, - ]; - } else { - console.error("Invalid eye provided: %s", whichEye); - return null; - } - return offset; - }; - CardboardVRDisplay.prototype.getEyeParameters = function (whichEye) { - var offset = this._getEyeOffset(whichEye); - var fieldOfView = this._getFieldOfView(whichEye); - var eyeParams = { - offset: offset, - renderWidth: - this.deviceInfo_.device.width * 0.5 * this.bufferScale_, - renderHeight: this.deviceInfo_.device.height * this.bufferScale_, - }; - Object.defineProperty(eyeParams, "fieldOfView", { - enumerable: true, - get: function get() { - deprecateWarning( - "VRFieldOfView", - "VRFrameData's projection matrices" - ); - return fieldOfView; - }, - }); - return eyeParams; - }; - CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function ( - newParams - ) { - if (this.config.DEBUG) { - console.log("DPDB reported that device params were updated."); - } - this.deviceInfo_.updateDeviceParams(newParams); - if (this.distorter_) { - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - }; - CardboardVRDisplay.prototype.updateBounds_ = function () { - if ( - this.layer_ && - this.distorter_ && - (this.layer_.leftBounds || this.layer_.rightBounds) - ) { - this.distorter_.setTextureBounds( - this.layer_.leftBounds, - this.layer_.rightBounds - ); - } - }; - CardboardVRDisplay.prototype.beginPresent_ = function () { - var gl = this.layer_.source.getContext("webgl"); - if (!gl) gl = this.layer_.source.getContext("experimental-webgl"); - if (!gl) gl = this.layer_.source.getContext("webgl2"); - if (!gl) return; - if (this.layer_.predistorted) { - if (!this.config.CARDBOARD_UI_DISABLED) { - gl.canvas.width = getScreenWidth() * this.bufferScale_; - gl.canvas.height = getScreenHeight() * this.bufferScale_; - this.cardboardUI_ = new CardboardUI(gl); - } - } else { - if (!this.config.CARDBOARD_UI_DISABLED) { - this.cardboardUI_ = new CardboardUI(gl); - } - this.distorter_ = new CardboardDistorter( - gl, - this.cardboardUI_, - this.config.BUFFER_SCALE, - this.config.DIRTY_SUBMIT_FRAME_BINDINGS - ); - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - if (this.cardboardUI_) { - this.cardboardUI_.listen( - function (e) { - this.viewerSelector_.show(this.layer_.source.parentElement); - e.stopPropagation(); - e.preventDefault(); - }.bind(this), - function (e) { - this.exitPresent(); - e.stopPropagation(); - e.preventDefault(); - }.bind(this) - ); - } - if (this.rotateInstructions_) { - if (isLandscapeMode() && isMobile()) { - this.rotateInstructions_.showTemporarily( - 3000, - this.layer_.source.parentElement - ); - } else { - this.rotateInstructions_.update(); - } - } - this.orientationHandler = this.onOrientationChange_.bind(this); - window.addEventListener("orientationchange", this.orientationHandler); - this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this); - window.addEventListener( - "vrdisplaypresentchange", - this.vrdisplaypresentchangeHandler - ); - this.fireVRDisplayDeviceParamsChange_(); - }; - CardboardVRDisplay.prototype.endPresent_ = function () { - if (this.distorter_) { - this.distorter_.destroy(); - this.distorter_ = null; - } - if (this.cardboardUI_) { - this.cardboardUI_.destroy(); - this.cardboardUI_ = null; - } - if (this.rotateInstructions_) { - this.rotateInstructions_.hide(); - } - this.viewerSelector_.hide(); - window.removeEventListener( - "orientationchange", - this.orientationHandler - ); - window.removeEventListener( - "vrdisplaypresentchange", - this.vrdisplaypresentchangeHandler - ); - }; - CardboardVRDisplay.prototype.updatePresent_ = function () { - this.endPresent_(); - this.beginPresent_(); - }; - CardboardVRDisplay.prototype.submitFrame = function (pose) { - if (this.distorter_) { - this.updateBounds_(); - this.distorter_.submitFrame(); - } else if (this.cardboardUI_ && this.layer_) { - var canvas = this.layer_.source.getContext("webgl").canvas; - if ( - canvas.width != this.lastWidth || - canvas.height != this.lastHeight - ) { - this.cardboardUI_.onResize(); - } - this.lastWidth = canvas.width; - this.lastHeight = canvas.height; - this.cardboardUI_.render(); - } - }; - CardboardVRDisplay.prototype.onOrientationChange_ = function (e) { - this.viewerSelector_.hide(); - if (this.rotateInstructions_) { - this.rotateInstructions_.update(); - } - this.onResize_(); - }; - CardboardVRDisplay.prototype.onResize_ = function (e) { - if (this.layer_) { - var gl = this.layer_.source.getContext("webgl"); - var cssProperties = [ - "position: absolute", - "top: 0", - "left: 0", - "width: 100vw", - "height: 100vh", - "border: 0", - "margin: 0", - "padding: 0px", - "box-sizing: content-box", - ]; - gl.canvas.setAttribute("style", cssProperties.join("; ") + ";"); - safariCssSizeWorkaround(gl.canvas); - } - }; - CardboardVRDisplay.prototype.onViewerChanged_ = function (viewer) { - this.deviceInfo_.setViewer(viewer); - if (this.distorter_) { - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - this.fireVRDisplayDeviceParamsChange_(); - }; - CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = - function () { - var event = new CustomEvent("vrdisplaydeviceparamschange", { - detail: { - vrdisplay: this, - deviceInfo: this.deviceInfo_, - }, - }); - window.dispatchEvent(event); - }; - CardboardVRDisplay.VRFrameData = VRFrameData; - CardboardVRDisplay.VRDisplay = VRDisplay; - return CardboardVRDisplay; - }); - }); - var CardboardVRDisplay = unwrapExports$$1(cardboardVrDisplay); - - var version = "0.10.5"; - - var DefaultConfig = { - PROVIDE_MOBILE_VRDISPLAY: true, - GET_VR_DISPLAYS_TIMEOUT: 1000, - MOBILE_WAKE_LOCK: true, - DEBUG: false, - DPDB_URL: "https://dpdb.webvr.rocks/dpdb.json", - K_FILTER: 0.98, - PREDICTION_TIME_S: 0.04, - TOUCH_PANNER_DISABLED: true, - CARDBOARD_UI_DISABLED: false, - ROTATE_INSTRUCTIONS_DISABLED: false, - YAW_ONLY: false, - BUFFER_SCALE: 0.5, - DIRTY_SUBMIT_FRAME_BINDINGS: false, - }; - - function WebVRPolyfill(config) { - this.config = extend(extend({}, DefaultConfig), config); - this.polyfillDisplays = []; - this.enabled = false; - this.hasNative = "getVRDisplays" in navigator; - this.native = {}; - this.native.getVRDisplays = navigator.getVRDisplays; - this.native.VRFrameData = window.VRFrameData; - this.native.VRDisplay = window.VRDisplay; - if ( - !this.hasNative || - (this.config.PROVIDE_MOBILE_VRDISPLAY && isMobile()) - ) { - this.enable(); - this.getVRDisplays().then(function (displays) { - if (displays && displays[0] && displays[0].fireVRDisplayConnect_) { - displays[0].fireVRDisplayConnect_(); - } - }); - } - } - WebVRPolyfill.prototype.getPolyfillDisplays = function () { - if (this._polyfillDisplaysPopulated) { - return this.polyfillDisplays; - } - if (isMobile()) { - var vrDisplay = new CardboardVRDisplay({ - MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK, - DEBUG: this.config.DEBUG, - DPDB_URL: this.config.DPDB_URL, - CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED, - K_FILTER: this.config.K_FILTER, - PREDICTION_TIME_S: this.config.PREDICTION_TIME_S, - TOUCH_PANNER_DISABLED: this.config.TOUCH_PANNER_DISABLED, - ROTATE_INSTRUCTIONS_DISABLED: - this.config.ROTATE_INSTRUCTIONS_DISABLED, - YAW_ONLY: this.config.YAW_ONLY, - BUFFER_SCALE: this.config.BUFFER_SCALE, - DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS, - }); - this.polyfillDisplays.push(vrDisplay); - } - this._polyfillDisplaysPopulated = true; - return this.polyfillDisplays; - }; - WebVRPolyfill.prototype.enable = function () { - this.enabled = true; - if (this.hasNative && this.native.VRFrameData) { - var NativeVRFrameData = this.native.VRFrameData; - var nativeFrameData = new this.native.VRFrameData(); - var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData; - window.VRDisplay.prototype.getFrameData = function (frameData) { - if (frameData instanceof NativeVRFrameData) { - nativeGetFrameData.call(this, frameData); - return; - } - nativeGetFrameData.call(this, nativeFrameData); - frameData.pose = nativeFrameData.pose; - copyArray( - nativeFrameData.leftProjectionMatrix, - frameData.leftProjectionMatrix - ); - copyArray( - nativeFrameData.rightProjectionMatrix, - frameData.rightProjectionMatrix - ); - copyArray(nativeFrameData.leftViewMatrix, frameData.leftViewMatrix); - copyArray(nativeFrameData.rightViewMatrix, frameData.rightViewMatrix); - }; - } - navigator.getVRDisplays = this.getVRDisplays.bind(this); - window.VRDisplay = CardboardVRDisplay.VRDisplay; - window.VRFrameData = CardboardVRDisplay.VRFrameData; - }; - WebVRPolyfill.prototype.getVRDisplays = function () { - var _this = this; - var config = this.config; - if (!this.hasNative) { - return Promise.resolve(this.getPolyfillDisplays()); - } - var timeoutId; - var vrDisplaysNative = this.native.getVRDisplays.call(navigator); - var timeoutPromise = new Promise(function (resolve) { - timeoutId = setTimeout(function () { - console.warn( - "Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill." - ); - resolve([]); - }, config.GET_VR_DISPLAYS_TIMEOUT); - }); - return race([vrDisplaysNative, timeoutPromise]).then(function ( - nativeDisplays - ) { - clearTimeout(timeoutId); - return nativeDisplays.length > 0 - ? nativeDisplays - : _this.getPolyfillDisplays(); - }); - }; - WebVRPolyfill.version = version; - WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData; - WebVRPolyfill.VRDisplay = CardboardVRDisplay.VRDisplay; - - var webvrPolyfill = Object.freeze({ - default: WebVRPolyfill, - }); - - var require$$0 = (webvrPolyfill && WebVRPolyfill) || webvrPolyfill; - - if (typeof commonjsGlobal$$1 !== "undefined" && commonjsGlobal$$1.window) { - if (!commonjsGlobal$$1.document) { - commonjsGlobal$$1.document = commonjsGlobal$$1.window.document; - } - if (!commonjsGlobal$$1.navigator) { - commonjsGlobal$$1.navigator = commonjsGlobal$$1.window.navigator; - } - } - var src = require$$0; - - return src; - }); -}); +var _assertThisInitialized = _interopDefault( + require("@babel/runtime/helpers/assertThisInitialized") +); +var _inheritsLoose = _interopDefault( + require("@babel/runtime/helpers/inheritsLoose") +); +var window$1 = _interopDefault(require("global/window")); +var document$1 = _interopDefault(require("global/document")); +var WebVRPolyfill = _interopDefault(require("webvr-polyfill")); +var videojs = _interopDefault(require("video.js")); +var THREE = require("three"); -var WebVRPolyfill = unwrapExports(webvrPolyfill); +var version = "1.8.0"; /** * @author dmarcos / https://github.com/dmarcos @@ -6199,10 +1070,8 @@ var OrbitControls = function (object, domElement) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientWidth); + scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, height - // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight); rotateStart.copy(rotateEnd); @@ -6318,10 +1187,8 @@ var OrbitControls = function (object, domElement) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientWidth); + scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, height - // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight); rotateStart.copy(rotateEnd); @@ -6555,7 +1422,7 @@ var OrbitControls = function (object, domElement) { // - scope.domElement.addEventListener("contextmenu", onContextMenu, false); + //scope.domElement.addEventListener\( 'contextmenu', onContextMenu, false ); scope.domElement.addEventListener("mousedown", onMouseDown, false); scope.domElement.addEventListener("wheel", onMouseWheel, false); @@ -6791,70 +1658,31 @@ var DeviceOrientationControls = function (object) { this.connect(); }; -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; - -var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError( - "Super expression must either be null or a function, not " + - typeof superClass - ); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true, - }, - }); - if (superClass) - Object.setPrototypeOf - ? Object.setPrototypeOf(subClass, superClass) - : (subClass.__proto__ = superClass); -}; - -var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called" - ); - } - - return call && (typeof call === "object" || typeof call === "function") - ? call - : self; -}; - /** * Convert a quaternion to an angle * * Taken from https://stackoverflow.com/a/35448946 * Thanks P. Ellul */ + function Quat2Angle(x, y, z, w) { - var test = x * y + z * w; + var test = x * y + z * w; // singularity at north pole - // singularity at north pole if (test > 0.499) { var _yaw = 2 * Math.atan2(x, w); + var _pitch = Math.PI / 2; - var _roll = 0; + var _roll = 0; return new THREE.Vector3(_pitch, _roll, _yaw); - } + } // singularity at south pole - // singularity at south pole if (test < -0.499) { var _yaw2 = -2 * Math.atan2(x, w); + var _pitch2 = -Math.PI / 2; - var _roll2 = 0; + var _roll2 = 0; return new THREE.Vector3(_pitch2, _roll2, _yaw2); } @@ -6864,31 +1692,34 @@ function Quat2Angle(x, y, z, w) { var yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz); var pitch = Math.asin(2 * test); var roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz); - return new THREE.Vector3(pitch, roll, yaw); } -var OrbitOrientationControls = (function () { +var OrbitOrientationControls = /*#__PURE__*/ (function () { function OrbitOrientationControls(options) { - classCallCheck(this, OrbitOrientationControls); - this.object = options.camera; this.domElement = options.canvas; this.orbit = new OrbitControls(this.object, this.domElement); - this.speed = 0.5; this.orbit.target.set(0, 0, -1); this.orbit.enableZoom = false; this.orbit.enablePan = false; - this.orbit.rotateSpeed = -this.speed; + this.orbit.rotateSpeed = -this.speed; // if orientation is supported - // if orientation is supported if (options.orientation) { this.orientation = new DeviceOrientationControls(this.object); + } // if projection is not full view + // limit the rotation angle in order to not display back half view + + if (options.halfView) { + this.orbit.minAzimuthAngle = -Math.PI / 4; + this.orbit.maxAzimuthAngle = Math.PI / 4; } } - OrbitOrientationControls.prototype.update = function update() { + var _proto = OrbitOrientationControls.prototype; + + _proto.update = function update() { // orientation updates the camera using quaternions and // orbit updates the camera using angles. They are incompatible // and one update overrides the other. So before @@ -6898,11 +1729,9 @@ var OrbitOrientationControls = (function () { // our changes if (this.orientation) { this.orientation.update(); - var quat = this.orientation.object.quaternion; - var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); + var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); // we also have to store the last angle since quaternions are b - // we also have to store the last angle since quaternions are b if (typeof this.lastAngle_ === "undefined") { this.lastAngle_ = currentAngle; } @@ -6919,7 +1748,7 @@ var OrbitOrientationControls = (function () { this.orbit.update(); }; - OrbitOrientationControls.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { this.orbit.dispose(); if (this.orientation) { @@ -6930,27 +1759,27 @@ var OrbitOrientationControls = (function () { return OrbitOrientationControls; })(); -// check if the browser supports cors var corsSupport = (function () { var video = document$1.createElement("video"); - video.crossOrigin = "anonymous"; - return video.hasAttribute("crossorigin"); })(); - var validProjections = [ "360", "360_LR", "360_TB", "360_CUBE", + "EAC", + "EAC_LR", "NONE", "AUTO", "Sphere", "Cube", "equirectangular", + "180", + "180_LR", + "180_MONO", ]; - var getInternalProjectionName = function getInternalProjectionName(projection) { if (!projection) { return; @@ -6977,34 +1806,276 @@ var getInternalProjectionName = function getInternalProjectionName(projection) { } }; -// Add Cardboard button -var Button = videojs.getComponent("Button"); +/** + * This class reacts to interactions with the canvas and + * triggers appropriate functionality on the player. Right now + * it does two things: + * + * 1. A `mousedown`/`touchstart` followed by `touchend`/`mouseup` without any + * `touchmove` or `mousemove` toggles play/pause on the player + * 2. Only moving on/clicking the control bar or toggling play/pause should + * show the control bar. Moving around the scene in the canvas should not. + */ -var CardboardButton = (function (_Button) { - inherits(CardboardButton, _Button); +var CanvasPlayerControls = /*#__PURE__*/ (function (_videojs$EventTarget) { + _inheritsLoose(CanvasPlayerControls, _videojs$EventTarget); - function CardboardButton(player, options) { - classCallCheck(this, CardboardButton); + function CanvasPlayerControls(player, canvas, options) { + var _this; + + _this = _videojs$EventTarget.call(this) || this; + _this.player = player; + _this.canvas = canvas; + _this.options = options; + _this.onMoveEnd = videojs.bind( + _assertThisInitialized(_this), + _this.onMoveEnd + ); + _this.onMoveStart = videojs.bind( + _assertThisInitialized(_this), + _this.onMoveStart + ); + _this.onMove = videojs.bind(_assertThisInitialized(_this), _this.onMove); + _this.onControlBarMove = videojs.bind( + _assertThisInitialized(_this), + _this.onControlBarMove + ); + + _this.player.controlBar.on( + [ + "mousedown", + "mousemove", + "mouseup", + "touchstart", + "touchmove", + "touchend", + ], + _this.onControlBarMove + ); // we have to override these here because + // video.js listens for user activity on the video element + // and makes the user active when the mouse moves. + // We don't want that for 3d videos + + _this.oldReportUserActivity = _this.player.reportUserActivity; + + _this.player.reportUserActivity = function () {}; // canvas movements + + _this.canvas.addEventListener("mousedown", _this.onMoveStart); + + _this.canvas.addEventListener("touchstart", _this.onMoveStart); + + _this.canvas.addEventListener("mousemove", _this.onMove); + + _this.canvas.addEventListener("touchmove", _this.onMove); + + _this.canvas.addEventListener("mouseup", _this.onMoveEnd); + + _this.canvas.addEventListener("touchend", _this.onMoveEnd); + + _this.shouldTogglePlay = false; + return _this; + } + + var _proto = CanvasPlayerControls.prototype; + + _proto.togglePlay = function togglePlay() { + if (this.player.paused()) { + this.player.play(); + } else { + this.player.pause(); + } + }; + + _proto.onMoveStart = function onMoveStart(e) { + // if the player does not have a controlbar or + // the move was a mouse click but not left click do not + // toggle play. + if ( + this.options.disableTogglePlay || + !this.player.controls() || + (e.type === "mousedown" && !videojs.dom.isSingleLeftClick(e)) + ) { + this.shouldTogglePlay = false; + return; + } + + this.shouldTogglePlay = true; + this.touchMoveCount_ = 0; + }; + + _proto.onMoveEnd = function onMoveEnd(e) { + // We want to have the same behavior in VR360 Player and standard player. + // in touchend we want to know if was a touch click, for a click we show the bar, + // otherwise continue with the mouse logic. + // + // Maximum movement allowed during a touch event to still be considered a tap + // Other popular libs use anywhere from 2 (hammer.js) to 15, + // so 10 seems like a nice, round number. + if (e.type === "touchend" && this.touchMoveCount_ < 10) { + if (this.player.userActive() === false) { + this.player.userActive(true); + return; + } + + this.player.userActive(false); + return; + } + + if (!this.shouldTogglePlay) { + return; + } // We want the same behavior in Desktop for VR360 and standard player + + if (e.type == "mouseup") { + this.togglePlay(); + } + }; + + _proto.onMove = function onMove(e) { + // Increase touchMoveCount_ since Android detects 1 - 6 touches when user click normally + this.touchMoveCount_++; + this.shouldTogglePlay = false; + }; + + _proto.onControlBarMove = function onControlBarMove(e) { + this.player.userActive(true); + }; + + _proto.dispose = function dispose() { + this.canvas.removeEventListener("mousedown", this.onMoveStart); + this.canvas.removeEventListener("touchstart", this.onMoveStart); + this.canvas.removeEventListener("mousemove", this.onMove); + this.canvas.removeEventListener("touchmove", this.onMove); + this.canvas.removeEventListener("mouseup", this.onMoveEnd); + this.canvas.removeEventListener("touchend", this.onMoveEnd); + this.player.controlBar.off( + [ + "mousedown", + "mousemove", + "mouseup", + "touchstart", + "touchmove", + "touchend", + ], + this.onControlBarMove + ); + this.player.reportUserActivity = this.oldReportUserActivity; + }; + + return CanvasPlayerControls; +})(videojs.EventTarget); + +/** + * This class manages ambisonic decoding and binaural rendering via Omnitone library. + */ + +var OmnitoneController = /*#__PURE__*/ (function (_videojs$EventTarget) { + _inheritsLoose(OmnitoneController, _videojs$EventTarget); + + /** + * Omnitone controller class. + * + * @class + * @param {AudioContext} audioContext - associated AudioContext. + * @param {Omnitone library} omnitone - Omnitone library element. + * @param {HTMLVideoElement} video - vidoe tag element. + * @param {Object} options - omnitone options. + */ + function OmnitoneController(audioContext, omnitone, video, options) { + var _this; + + _this = _videojs$EventTarget.call(this) || this; + var settings = videojs.mergeOptions( + { + // Safari uses the different AAC decoder than FFMPEG. The channel order is + // The default 4ch AAC channel layout for FFMPEG AAC channel ordering. + channelMap: videojs.browser.IS_SAFARI ? [2, 0, 1, 3] : [0, 1, 2, 3], + ambisonicOrder: 1, + }, + options + ); + _this.videoElementSource = audioContext.createMediaElementSource(video); + _this.foaRenderer = omnitone.createFOARenderer(audioContext, settings); + + _this.foaRenderer.initialize().then( + function () { + if (audioContext.state === "suspended") { + _this.trigger({ + type: "audiocontext-suspended", + }); + } + + _this.videoElementSource.connect(_this.foaRenderer.input); + + _this.foaRenderer.output.connect(audioContext.destination); - var _this = possibleConstructorReturn( - this, - _Button.call(this, player, options) + _this.initialized = true; + + _this.trigger({ + type: "omnitone-ready", + }); + }, + function (error) { + videojs.log.warn( + "videojs-vr: Omnitone initializes failed with the following error: " + + error + + ")" + ); + } ); + return _this; + } + /** + * Updates the rotation of the Omnitone decoder based on three.js camera matrix. + * + * @param {Camera} camera Three.js camera object + */ + + var _proto = OmnitoneController.prototype; + + _proto.update = function update(camera) { + if (!this.initialized) { + return; + } + + this.foaRenderer.setRotationMatrixFromCamera(camera.matrix); + }; + /** + * Destroys the controller and does any necessary cleanup. + */ + + _proto.dispose = function dispose() { + this.initialized = false; + this.foaRenderer.setRenderingMode("bypass"); + this.foaRenderer = null; + }; + + return OmnitoneController; +})(videojs.EventTarget); + +var Button = videojs.getComponent("Button"); + +var CardboardButton = /*#__PURE__*/ (function (_Button) { + _inheritsLoose(CardboardButton, _Button); + + function CardboardButton(player, options) { + var _this; + + _this = _Button.call(this, player, options) || this; _this.handleVrDisplayActivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayActivate_ ); _this.handleVrDisplayDeactivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayDeactivate_ ); _this.handleVrDisplayPresentChange_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayPresentChange_ ); _this.handleOrientationChange_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleOrientationChange_ ); window$1.addEventListener( @@ -7018,20 +2089,18 @@ var CardboardButton = (function (_Button) { window$1.addEventListener( "vrdisplaydeactivate", _this.handleVrDisplayDeactivate_ - ); - - // vrdisplaypresentchange does not fire activate or deactivate + ); // vrdisplaypresentchange does not fire activate or deactivate // and happens when hitting the back button during cardboard mode // so we need to make sure we stay in the correct state by // listening to it and checking if we are presenting it or not + window$1.addEventListener( "vrdisplaypresentchange", _this.handleVrDisplayPresentChange_ - ); - - // we cannot show the cardboard button in fullscreen on + ); // we cannot show the cardboard button in fullscreen on // android as it breaks the controls, and makes it impossible // to exit cardboard mode + if (videojs.browser.IS_ANDROID) { _this.on(player, "fullscreenchange", function () { if (player.isFullscreen()) { @@ -7041,84 +2110,88 @@ var CardboardButton = (function (_Button) { } }); } + return _this; } - CardboardButton.prototype.buildCSSClass = function buildCSSClass() { + var _proto = CardboardButton.prototype; + + _proto.buildCSSClass = function buildCSSClass() { return "vjs-button-vr " + _Button.prototype.buildCSSClass.call(this); }; - CardboardButton.prototype.handleVrDisplayPresentChange_ = + _proto.handleVrDisplayPresentChange_ = function handleVrDisplayPresentChange_() { if (!this.player_.vr().vrDisplay.isPresenting && this.active_) { this.handleVrDisplayDeactivate_(); } + if (this.player_.vr().vrDisplay.isPresenting && !this.active_) { this.handleVrDisplayActivate_(); } }; - CardboardButton.prototype.handleOrientationChange_ = - function handleOrientationChange_() { - if (this.active_ && videojs.browser.IS_IOS) { - this.changeSize_(); - } - }; + _proto.handleOrientationChange_ = function handleOrientationChange_() { + if (this.active_ && videojs.browser.IS_IOS) { + this.changeSize_(); + } + }; - CardboardButton.prototype.changeSize_ = function changeSize_() { + _proto.changeSize_ = function changeSize_() { this.player_.width(window$1.innerWidth); this.player_.height(window$1.innerHeight); window$1.dispatchEvent(new window$1.Event("resize")); }; - CardboardButton.prototype.handleVrDisplayActivate_ = - function handleVrDisplayActivate_() { - // we mimic fullscreen on IOS - if (videojs.browser.IS_IOS) { - this.oldWidth_ = this.player_.currentWidth(); - this.oldHeight_ = this.player_.currentHeight(); - this.player_.enterFullWindow(); - this.changeSize_(); - } + _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { + // we mimic fullscreen on IOS + if (videojs.browser.IS_IOS) { + this.oldWidth_ = this.player_.currentWidth(); + this.oldHeight_ = this.player_.currentHeight(); + this.player_.enterFullWindow(); + this.changeSize_(); + } - this.active_ = true; - }; + this.active_ = true; + }; - CardboardButton.prototype.handleVrDisplayDeactivate_ = - function handleVrDisplayDeactivate_() { - // un-mimic fullscreen on iOS - if (videojs.browser.IS_IOS) { - if (this.oldWidth_) { - this.player_.width(this.oldWidth_); - } - if (this.oldHeight_) { - this.player_.height(this.oldHeight_); - } - this.player_.exitFullWindow(); - window$1.dispatchEvent(new window$1.Event("resize")); + _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { + // un-mimic fullscreen on iOS + if (videojs.browser.IS_IOS) { + if (this.oldWidth_) { + this.player_.width(this.oldWidth_); } - this.active_ = false; - }; + if (this.oldHeight_) { + this.player_.height(this.oldHeight_); + } + + this.player_.exitFullWindow(); + } + + this.active_ = false; + }; - CardboardButton.prototype.handleClick = function handleClick(event) { + _proto.handleClick = function handleClick(event) { // if cardboard mode display is not active, activate it // otherwise deactivate it if (!this.active_) { // This starts playback mode when the cardboard button - // is clicked on Andriod. We need to do this as the controls + // is clicked on Android. We need to do this as the controls // disappear if (!this.player_.hasStarted() && videojs.browser.IS_ANDROID) { this.player_.play(); } + window$1.dispatchEvent(new window$1.Event("vrdisplayactivate")); } else { window$1.dispatchEvent(new window$1.Event("vrdisplaydeactivate")); } }; - CardboardButton.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { _Button.prototype.dispose.call(this); + window$1.removeEventListener( "vrdisplayactivate", this.handleVrDisplayActivate_ @@ -7140,36 +2213,75 @@ videojs.registerComponent("CardboardButton", CardboardButton); var BigPlayButton = videojs.getComponent("BigPlayButton"); -var BigVrPlayButton = (function (_BigPlayButton) { - inherits(BigVrPlayButton, _BigPlayButton); +var BigVrPlayButton = /*#__PURE__*/ (function (_BigPlayButton) { + _inheritsLoose(BigVrPlayButton, _BigPlayButton); function BigVrPlayButton() { - classCallCheck(this, BigVrPlayButton); - return possibleConstructorReturn( - this, - _BigPlayButton.apply(this, arguments) - ); + return _BigPlayButton.apply(this, arguments) || this; } - BigVrPlayButton.prototype.buildCSSClass = function buildCSSClass() { + var _proto = BigVrPlayButton.prototype; + + _proto.buildCSSClass = function buildCSSClass() { return ( "vjs-big-vr-play-button " + _BigPlayButton.prototype.buildCSSClass.call(this) ); }; - return BigVrPlayButton; -})(BigPlayButton); + return BigVrPlayButton; +})(BigPlayButton); + +videojs.registerComponent("BigVrPlayButton", BigVrPlayButton); + +function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = + (typeof Symbol !== "undefined" && o[Symbol.iterator]) || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + if ( + Array.isArray(o) || + (it = _unsupportedIterableToArray(o)) || + (allowArrayLike && o && typeof o.length === "number") + ) { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { done: true }; + return { done: false, value: o[i++] }; + }; + } + throw new TypeError( + "Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." + ); +} + +function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) + return _arrayLikeToArray(o, minLen); +} -videojs.registerComponent("BigVrPlayButton", BigVrPlayButton); +function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) { + arr2[i] = arr[i]; + } + return arr2; +} -// Default options for the plugin. -var defaults$1 = { - projection: "AUTO", - forceCardboard: false, +var defaults = { debug: false, + omnitone: false, + forceCardboard: false, + omnitoneOptions: {}, + projection: "AUTO", + sphereDetail: 32, + disableTogglePlay: false, }; - var errors = { "web-vr-out-of-date": { headline: "360 is out of date", @@ -7190,44 +2302,42 @@ var errors = { "Your browser/device does not support HLS 360 video. See http://webvr.info for assistance.", }, }; - var Plugin = videojs.getPlugin("plugin"); var Component = videojs.getComponent("Component"); -var VR = (function (_Plugin) { - inherits(VR, _Plugin); +var VR = /*#__PURE__*/ (function (_Plugin) { + _inheritsLoose(VR, _Plugin); function VR(player, options) { - classCallCheck(this, VR); - - var settings = videojs.mergeOptions(defaults$1, options); - - var _this = possibleConstructorReturn( - this, - _Plugin.call(this, player, settings) - ); + var _this; + var settings = videojs.mergeOptions(defaults, options); + _this = _Plugin.call(this, player, settings) || this; _this.options_ = settings; _this.player_ = player; _this.bigPlayButtonIndex_ = - player.children().indexOf(player.getChild("BigPlayButton")) || 0; + player.children().indexOf(player.getChild("BigPlayButton")) || 0; // custom videojs-errors integration boolean - // custom videojs-errors integration boolean _this.videojsErrorsSupport_ = !!videojs.errors; if (_this.videojsErrorsSupport_) { - player.errors({ errors: errors }); - } - - // IE 11 does not support enough webgl to be supported + player.errors({ + errors: errors, + }); + } // IE 11 does not support enough webgl to be supported // older safari does not support cors, so it wont work + if (videojs.browser.IE_VERSION || !corsSupport) { // if a player triggers error before 'loadstart' is fired // video.js will reset the error overlay _this.player_.on("loadstart", function () { - _this.triggerError_({ code: "web-vr-not-supported", dismiss: false }); + _this.triggerError_({ + code: "web-vr-not-supported", + dismiss: false, + }); }); - return possibleConstructorReturn(_this); + + return _assertThisInitialized(_this); } _this.polyfill_ = new WebVRPolyfill({ @@ -7235,39 +2345,79 @@ var VR = (function (_Plugin) { ROTATE_INSTRUCTIONS_DISABLED: true, }); _this.polyfill_ = new WebVRPolyfill(); - _this.handleVrDisplayActivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayActivate_ ); _this.handleVrDisplayDeactivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayDeactivate_ ); - _this.handleResize_ = videojs.bind(_this, _this.handleResize_); - _this.animate_ = videojs.bind(_this, _this.animate_); + _this.handleResize_ = videojs.bind( + _assertThisInitialized(_this), + _this.handleResize_ + ); + _this.animate_ = videojs.bind( + _assertThisInitialized(_this), + _this.animate_ + ); + + _this.setProjection(_this.options_.projection); // any time the video element is recycled for ads + // we have to reset the vr state and re-init after ad + + _this.on( + player, + "adstart", + function () { + return player.setTimeout(function () { + // if the video element was recycled for this ad + if (!player.ads || !player.ads.videoElementRecycled()) { + _this.log( + "video element not recycled for this ad, no need to reset" + ); + + return; + } + + _this.log("video element recycled for this ad, reseting"); - _this.setProjection(_this.options_.projection); + _this.reset(); + + _this.one(player, "playing", _this.init); + }); + }, + 1 + ); _this.on(player, "loadedmetadata", _this.init); + return _this; } - VR.prototype.changeProjection_ = function changeProjection_(projection) { - projection = getInternalProjectionName(projection); - // don't change to an invalid projection + var _proto = VR.prototype; + + _proto.changeProjection_ = function changeProjection_(projection) { + var _this2 = this; + + projection = getInternalProjectionName(projection); // don't change to an invalid projection + if (!projection) { projection = "NONE"; } - var position = { x: 0, y: 0, z: 0 }; + var position = { + x: 0, + y: 0, + z: 0, + }; if (this.scene) { this.scene.remove(this.movieScreen); } + if (projection === "AUTO") { // mediainfo cannot be set to auto or we would infinite loop here - // each source should know wether they are 360 or not, if using AUTO + // each source should know whatever they are 360 or not, if using AUTO if ( this.player_.mediainfo && this.player_.mediainfo.projection && @@ -7276,31 +2426,40 @@ var VR = (function (_Plugin) { var autoProjection = getInternalProjectionName( this.player_.mediainfo.projection ); - return this.changeProjection_(autoProjection); } + return this.changeProjection_("NONE"); } else if (projection === "360") { - this.movieGeometry = new THREE.SphereBufferGeometry(256, 32, 32); + this.movieGeometry = new THREE.SphereBufferGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); this.movieMaterial = new THREE.MeshBasicMaterial({ map: this.videoTexture, overdraw: true, side: THREE.BackSide, }); - this.movieScreen = new THREE.Mesh(this.movieGeometry, this.movieMaterial); this.movieScreen.position.set(position.x, position.y, position.z); - this.movieScreen.scale.x = -1; this.movieScreen.quaternion.setFromAxisAngle( - { x: 0, y: 1, z: 0 }, + { + x: 0, + y: 1, + z: 0, + }, -Math.PI / 2 ); this.scene.add(this.movieScreen); } else if (projection === "360_LR" || projection === "360_TB") { - var geometry = new THREE.SphereGeometry(256, 32, 32); - // Left eye view + var geometry = new THREE.SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); var uvs = geometry.faceVertexUvs[0]; for (var i = 0; i < uvs.length; i++) { @@ -7313,7 +2472,6 @@ var VR = (function (_Plugin) { } } } - geometry.scale(-1, 1, 1); this.movieGeometry = new THREE.BufferGeometry().fromGeometry(geometry); this.movieMaterial = new THREE.MeshBasicMaterial({ @@ -7321,16 +2479,25 @@ var VR = (function (_Plugin) { overdraw: true, side: THREE.BackSide, }); - this.movieScreen = new THREE.Mesh(this.movieGeometry, this.movieMaterial); - this.movieScreen.rotation.y = -Math.PI / 2; - // display in left eye only - this.movieScreen.layers.set(1); - this.scene.add(this.movieScreen); + this.movieScreen.scale.x = -1; + this.movieScreen.quaternion.setFromAxisAngle( + { + x: 0, + y: 1, + z: 0, + }, + -Math.PI / 2 + ); // display in left eye only - // Right eye view - geometry = new THREE.SphereGeometry(256, 32, 32); + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); // Right eye view + geometry = new THREE.SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); uvs = geometry.faceVertexUvs[0]; for (var _i = 0; _i < uvs.length; _i++) { @@ -7343,7 +2510,6 @@ var VR = (function (_Plugin) { } } } - geometry.scale(-1, 1, 1); this.movieGeometry = new THREE.BufferGeometry().fromGeometry(geometry); this.movieMaterial = new THREE.MeshBasicMaterial({ @@ -7351,10 +2517,17 @@ var VR = (function (_Plugin) { overdraw: true, side: THREE.BackSide, }); - this.movieScreen = new THREE.Mesh(this.movieGeometry, this.movieMaterial); - this.movieScreen.rotation.y = -Math.PI / 2; - // display in right eye only + this.movieScreen.scale.x = -1; + this.movieScreen.quaternion.setFromAxisAngle( + { + x: 0, + y: 1, + z: 0, + }, + -Math.PI / 2 + ); // display in right eye only + this.movieScreen.layers.set(2); this.scene.add(this.movieScreen); } else if (projection === "360_CUBE") { @@ -7364,7 +2537,6 @@ var VR = (function (_Plugin) { overdraw: true, side: THREE.BackSide, }); - var left = [ new THREE.Vector2(0, 0.5), new THREE.Vector2(0.333, 0.5), @@ -7401,18 +2573,13 @@ var VR = (function (_Plugin) { new THREE.Vector2(1, 0.5), new THREE.Vector2(0.666, 0.5), ]; - this.movieGeometry.faceVertexUvs[0] = []; - this.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]]; this.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]]; - this.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; this.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; - this.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; this.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; - this.movieGeometry.faceVertexUvs[0][6] = [ bottom[2], bottom[1], @@ -7423,37 +2590,277 @@ var VR = (function (_Plugin) { bottom[0], bottom[3], ]; - this.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]]; this.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]]; - this.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; this.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; - this.movieScreen = new THREE.Mesh(this.movieGeometry, this.movieMaterial); this.movieScreen.position.set(position.x, position.y, position.z); this.movieScreen.rotation.y = -Math.PI; + this.scene.add(this.movieScreen); + } else if ( + projection === "180" || + projection === "180_LR" || + projection === "180_MONO" + ) { + var _geometry = new THREE.SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail, + Math.PI, + Math.PI + ); // Left eye view + + _geometry.scale(-1, 1, 1); + + var _uvs = _geometry.faceVertexUvs[0]; + + if (projection !== "180_MONO") { + for (var _i2 = 0; _i2 < _uvs.length; _i2++) { + for (var _j2 = 0; _j2 < 3; _j2++) { + _uvs[_i2][_j2].x *= 0.5; + } + } + } + + this.movieGeometry = new THREE.BufferGeometry().fromGeometry(_geometry); + this.movieMaterial = new THREE.MeshBasicMaterial({ + map: this.videoTexture, + overdraw: true, + }); + this.movieScreen = new THREE.Mesh(this.movieGeometry, this.movieMaterial); // display in left eye only + + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); // Right eye view + + _geometry = new THREE.SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail, + Math.PI, + Math.PI + ); + + _geometry.scale(-1, 1, 1); + + _uvs = _geometry.faceVertexUvs[0]; + + for (var _i3 = 0; _i3 < _uvs.length; _i3++) { + for (var _j3 = 0; _j3 < 3; _j3++) { + _uvs[_i3][_j3].x *= 0.5; + _uvs[_i3][_j3].x += 0.5; + } + } + + this.movieGeometry = new THREE.BufferGeometry().fromGeometry(_geometry); + this.movieMaterial = new THREE.MeshBasicMaterial({ + map: this.videoTexture, + overdraw: true, + }); + this.movieScreen = new THREE.Mesh(this.movieGeometry, this.movieMaterial); // display in right eye only + this.movieScreen.layers.set(2); this.scene.add(this.movieScreen); + } else if (projection === "EAC" || projection === "EAC_LR") { + var makeScreen = function makeScreen(mapMatrix, scaleMatrix) { + // "Continuity correction?": because of discontinuous faces and aliasing, + // we truncate the 2-pixel-wide strips on all discontinuous edges, + var contCorrect = 2; + _this2.movieGeometry = new THREE.BoxGeometry(256, 256, 256); + _this2.movieMaterial = new THREE.ShaderMaterial({ + overdraw: true, + side: THREE.BackSide, + uniforms: { + mapped: { + value: _this2.videoTexture, + }, + mapMatrix: { + value: mapMatrix, + }, + contCorrect: { + value: contCorrect, + }, + faceWH: { + value: new THREE.Vector2(1 / 3, 1 / 2).applyMatrix3(scaleMatrix), + }, + vidWH: { + value: new THREE.Vector2( + _this2.videoTexture.image.videoWidth, + _this2.videoTexture.image.videoHeight + ).applyMatrix3(scaleMatrix), + }, + }, + vertexShader: + "\nvarying vec2 vUv;\nuniform mat3 mapMatrix;\n\nvoid main() {\n vUv = (mapMatrix * vec3(uv, 1.)).xy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);\n}", + fragmentShader: + "\nvarying vec2 vUv;\nuniform sampler2D mapped;\nuniform vec2 faceWH;\nuniform vec2 vidWH;\nuniform float contCorrect;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvoid main() {\n vec2 corner = vUv - mod(vUv, faceWH) + vec2(0, contCorrect / vidWH.y);\n\n vec2 faceWHadj = faceWH - vec2(0, contCorrect * 2. / vidWH.y);\n\n vec2 p = (vUv - corner) / faceWHadj - .5;\n vec2 q = 2. / PI * atan(2. * p) + .5;\n\n vec2 eUv = corner + q * faceWHadj;\n\n gl_FragColor = texture2D(mapped, eUv);\n}", + }); + var right = [ + new THREE.Vector2(0, 1 / 2), + new THREE.Vector2(1 / 3, 1 / 2), + new THREE.Vector2(1 / 3, 1), + new THREE.Vector2(0, 1), + ]; + var front = [ + new THREE.Vector2(1 / 3, 1 / 2), + new THREE.Vector2(2 / 3, 1 / 2), + new THREE.Vector2(2 / 3, 1), + new THREE.Vector2(1 / 3, 1), + ]; + var left = [ + new THREE.Vector2(2 / 3, 1 / 2), + new THREE.Vector2(1, 1 / 2), + new THREE.Vector2(1, 1), + new THREE.Vector2(2 / 3, 1), + ]; + var bottom = [ + new THREE.Vector2(1 / 3, 0), + new THREE.Vector2(1 / 3, 1 / 2), + new THREE.Vector2(0, 1 / 2), + new THREE.Vector2(0, 0), + ]; + var back = [ + new THREE.Vector2(1 / 3, 1 / 2), + new THREE.Vector2(1 / 3, 0), + new THREE.Vector2(2 / 3, 0), + new THREE.Vector2(2 / 3, 1 / 2), + ]; + var top = [ + new THREE.Vector2(1, 0), + new THREE.Vector2(1, 1 / 2), + new THREE.Vector2(2 / 3, 1 / 2), + new THREE.Vector2(2 / 3, 0), + ]; + + for ( + var _i4 = 0, _arr = [right, front, left, bottom, back, top]; + _i4 < _arr.length; + _i4++ + ) { + var face = _arr[_i4]; + var height = _this2.videoTexture.image.videoHeight; + var lowY = 1; + var highY = 0; + + for ( + var _iterator = _createForOfIteratorHelperLoose(face), _step; + !(_step = _iterator()).done; + + ) { + var vector = _step.value; + + if (vector.y < lowY) { + lowY = vector.y; + } + + if (vector.y > highY) { + highY = vector.y; + } + } + + for ( + var _iterator2 = _createForOfIteratorHelperLoose(face), _step2; + !(_step2 = _iterator2()).done; + + ) { + var _vector = _step2.value; + + if (Math.abs(_vector.y - lowY) < Number.EPSILON) { + _vector.y += contCorrect / height; + } + + if (Math.abs(_vector.y - highY) < Number.EPSILON) { + _vector.y -= contCorrect / height; + } + + _vector.x = + (_vector.x / height) * (height - contCorrect * 2) + + contCorrect / height; + } + } + + _this2.movieGeometry.faceVertexUvs[0] = []; + _this2.movieGeometry.faceVertexUvs[0][0] = [ + right[2], + right[1], + right[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][1] = [ + right[1], + right[0], + right[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; + _this2.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; + _this2.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; + _this2.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; + _this2.movieGeometry.faceVertexUvs[0][6] = [ + bottom[2], + bottom[1], + bottom[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][7] = [ + bottom[1], + bottom[0], + bottom[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][8] = [ + front[2], + front[1], + front[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][9] = [ + front[1], + front[0], + front[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; + _this2.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; + _this2.movieScreen = new THREE.Mesh( + _this2.movieGeometry, + _this2.movieMaterial + ); + + _this2.movieScreen.position.set(position.x, position.y, position.z); + + _this2.movieScreen.rotation.y = -Math.PI; + return _this2.movieScreen; + }; + + if (projection === "EAC") { + this.scene.add(makeScreen(new THREE.Matrix3(), new THREE.Matrix3())); + } else { + var scaleMatrix = new THREE.Matrix3().set(0, 0.5, 0, 1, 0, 0, 0, 0, 1); + makeScreen( + new THREE.Matrix3().set(0, -0.5, 0.5, 1, 0, 0, 0, 0, 1), + scaleMatrix + ); // display in left eye only + + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); + makeScreen( + new THREE.Matrix3().set(0, -0.5, 1, 1, 0, 0, 0, 0, 1), + scaleMatrix + ); // display in right eye only + + this.movieScreen.layers.set(2); + this.scene.add(this.movieScreen); + } } this.currentProjection_ = projection; }; - VR.prototype.triggerError_ = function triggerError_(errorObj) { + _proto.triggerError_ = function triggerError_(errorObj) { // if we have videojs-errors use it if (this.videojsErrorsSupport_) { - this.player_.error(errorObj); - // if we don't have videojs-errors just use a normal player error + this.player_.error(errorObj); // if we don't have videojs-errors just use a normal player error } else { // strip any html content from the error message // as it is not supported outside of videojs-errors var div = document$1.createElement("div"); - div.innerHTML = errors[errorObj.code].message; - var message = div.textContent || div.innerText || ""; - this.player_.error({ code: errorObj.code, message: message, @@ -7461,13 +2868,13 @@ var VR = (function (_Plugin) { } }; - VR.prototype.log = function log() { + _proto.log = function log() { if (!this.options_.debug) { return; } for ( - var _len = arguments.length, msgs = Array(_len), _key = 0; + var _len = arguments.length, msgs = new Array(_len), _key = 0; _key < _len; _key++ ) { @@ -7475,28 +2882,33 @@ var VR = (function (_Plugin) { } msgs.forEach(function (msg) { - videojs.log(msg); + videojs.log("VR: ", msg); }); }; - VR.prototype.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { - var _this2 = this; + _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { + var _this3 = this; if (!this.vrDisplay) { return; } + this.vrDisplay - .requestPresent([{ source: this.renderedCanvas }]) + .requestPresent([ + { + source: this.renderedCanvas, + }, + ]) .then(function () { - if (!_this2.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { + if (!_this3.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { return; - } - - // webvr-polyfill/cardboard ui only watches for click events + } // webvr-polyfill/cardboard ui only watches for click events // to tell that the back arrow button is pressed during cardboard vr. // but somewhere along the line these events are silenced with preventDefault // but only on iOS, so we translate them ourselves here + var touches = []; + var iosCardboardTouchStart_ = function iosCardboardTouchStart_(e) { for (var i = 0; i < e.touches.length; i++) { touches.push(e.touches[i]); @@ -7516,63 +2928,66 @@ var VR = (function (_Plugin) { clientY: t.clientY, }); - _this2.renderedCanvas.dispatchEvent(simulatedClick); + _this3.renderedCanvas.dispatchEvent(simulatedClick); }); - touches = []; }; - _this2.renderedCanvas.addEventListener( + _this3.renderedCanvas.addEventListener( "touchstart", iosCardboardTouchStart_ ); - _this2.renderedCanvas.addEventListener( + + _this3.renderedCanvas.addEventListener( "touchend", iosCardboardTouchEnd_ ); - _this2.iosRevertTouchToClick_ = function () { - _this2.renderedCanvas.removeEventListener( + _this3.iosRevertTouchToClick_ = function () { + _this3.renderedCanvas.removeEventListener( "touchstart", iosCardboardTouchStart_ ); - _this2.renderedCanvas.removeEventListener( + + _this3.renderedCanvas.removeEventListener( "touchend", iosCardboardTouchEnd_ ); - _this2.iosRevertTouchToClick_ = null; + + _this3.iosRevertTouchToClick_ = null; }; }); }; - VR.prototype.handleVrDisplayDeactivate_ = - function handleVrDisplayDeactivate_() { - if (!this.vrDisplay || !this.vrDisplay.isPresenting) { - return; - } - if (this.iosRevertTouchToClick_) { - this.iosRevertTouchToClick_(); - } - this.vrDisplay.exitPresent(); - }; + _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { + if (!this.vrDisplay || !this.vrDisplay.isPresenting) { + return; + } + + if (this.iosRevertTouchToClick_) { + this.iosRevertTouchToClick_(); + } + + this.vrDisplay.exitPresent(); + }; - VR.prototype.requestAnimationFrame = function requestAnimationFrame(fn) { + _proto.requestAnimationFrame = function requestAnimationFrame(fn) { if (this.vrDisplay) { return this.vrDisplay.requestAnimationFrame(fn); } - return Component.prototype.requestAnimationFrame.call(this, fn); + return this.player_.requestAnimationFrame(fn); }; - VR.prototype.cancelAnimationFrame = function cancelAnimationFrame(id) { + _proto.cancelAnimationFrame = function cancelAnimationFrame(id) { if (this.vrDisplay) { return this.vrDisplay.cancelAnimationFrame(id); } - return Component.prototype.cancelAnimationFrame.call(this, id); + return this.player_.cancelAnimationFrame(id); }; - VR.prototype.togglePlay_ = function togglePlay_() { + _proto.togglePlay_ = function togglePlay_() { if (this.player_.paused()) { this.player_.play(); } else { @@ -7580,10 +2995,11 @@ var VR = (function (_Plugin) { } }; - VR.prototype.animate_ = function animate_() { + _proto.animate_ = function animate_() { if (!this.initialized_) { return; } + if (this.getVideoEl_().readyState === this.getVideoEl_().HAVE_ENOUGH_DATA) { if (this.videoTexture) { this.videoTexture.needsUpdate = true; @@ -7591,6 +3007,11 @@ var VR = (function (_Plugin) { } this.controls3d.update(); + + if (this.omniController) { + this.omniController.update(this.camera); + } + this.effect.render(this.scene, this.camera); if (window$1.navigator.getGamepads) { @@ -7598,10 +3019,9 @@ var VR = (function (_Plugin) { var gamepads = window$1.navigator.getGamepads(); for (var i = 0; i < gamepads.length; ++i) { - var gamepad = gamepads[i]; - - // Make sure gamepad is defined + var gamepad = gamepads[i]; // Make sure gamepad is defined // Only take input if state has changed since we checked last + if ( !gamepad || !gamepad.timestamp || @@ -7609,6 +3029,7 @@ var VR = (function (_Plugin) { ) { continue; } + for (var j = 0; j < gamepad.buttons.length; ++j) { if (gamepad.buttons[j].pressed) { this.togglePlay_(); @@ -7618,21 +3039,20 @@ var VR = (function (_Plugin) { } } } - this.camera.getWorldDirection(this.cameraVector); + this.camera.getWorldDirection(this.cameraVector); this.animationFrameId_ = this.requestAnimationFrame(this.animate_); }; - VR.prototype.handleResize_ = function handleResize_() { + _proto.handleResize_ = function handleResize_() { var width = this.player_.currentWidth(); var height = this.player_.currentHeight(); - this.effect.setSize(width, height, false); this.camera.aspect = width / height; this.camera.updateProjectionMatrix(); }; - VR.prototype.setProjection = function setProjection(projection) { + _proto.setProjection = function setProjection(projection) { if (!getInternalProjectionName(projection)) { videojs.log.error( "videojs-vr: please pass a valid projection " + @@ -7645,38 +3065,39 @@ var VR = (function (_Plugin) { this.defaultProjection_ = projection; }; - VR.prototype.init = function init() { - var _this3 = this; + _proto.init = function init() { + var _this4 = this; this.reset(); - this.camera = new THREE.PerspectiveCamera( 75, this.player_.currentWidth() / this.player_.currentHeight(), 1, 1000 - ); - // Store vector representing the direction in which the camera is looking, in world space. + ); // Store vector representing the direction in which the camera is looking, in world space. + this.cameraVector = new THREE.Vector3(); if ( this.currentProjection_ === "360_LR" || - this.currentProjection_ === "360_TB" + this.currentProjection_ === "360_TB" || + this.currentProjection_ === "180" || + this.currentProjection_ === "180_LR" || + this.currentProjection_ === "180_MONO" || + this.currentProjection_ === "EAC_LR" ) { // Render left eye when not in VR mode this.camera.layers.enable(1); } this.scene = new THREE.Scene(); - this.videoTexture = new THREE.VideoTexture(this.getVideoEl_()); - - // shared regardless of wether VideoTexture is used or + this.videoTexture = new THREE.VideoTexture(this.getVideoEl_()); // shared regardless of wether VideoTexture is used or // an image canvas is used + this.videoTexture.generateMipmaps = false; this.videoTexture.minFilter = THREE.LinearFilter; this.videoTexture.magFilter = THREE.LinearFilter; this.videoTexture.format = THREE.RGBFormat; - this.changeProjection_(this.currentProjection_); if (this.currentProjection_ === "NONE") { @@ -7687,19 +3108,21 @@ var VR = (function (_Plugin) { this.player_.removeChild("BigPlayButton"); this.player_.addChild("BigVrPlayButton", {}, this.bigPlayButtonIndex_); - this.player_.bigPlayButton = this.player_.getChild("BigVrPlayButton"); + this.player_.bigPlayButton = this.player_.getChild("BigVrPlayButton"); // mobile devices, or cardboard forced to on - // mobile devices, or cardboard forced to on if ( this.options_.forceCardboard || videojs.browser.IS_ANDROID || videojs.browser.IS_IOS ) { this.addCardboardButton_(); - } + } // if ios remove full screen toggle - // if ios remove full screen toggle - if (videojs.browser.IS_IOS) { + if ( + videojs.browser.IS_IOS && + this.player_.controlBar && + this.player_.controlBar.fullscreenToggle + ) { this.player_.controlBar.fullscreenToggle.hide(); } @@ -7710,29 +3133,31 @@ var VR = (function (_Plugin) { clearColor: 0xffffff, antialias: true, }); - var webglContext = this.renderer.getContext("webgl"); var oldTexImage2D = webglContext.texImage2D; - /* this is a workaround since threejs uses try catch */ - webglContext.texImage2D = function () { - for ( - var _len2 = arguments.length, args = Array(_len2), _key2 = 0; - _key2 < _len2; - _key2++ - ) { - args[_key2] = arguments[_key2]; - } + webglContext.texImage2D = function () { try { + for ( + var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; + _key2 < _len2; + _key2++ + ) { + args[_key2] = arguments[_key2]; + } + return oldTexImage2D.apply(webglContext, args); } catch (e) { - _this3.reset(); - _this3.player_.pause(); - _this3.triggerError_({ + _this4.reset(); + + _this4.player_.pause(); + + _this4.triggerError_({ code: "web-vr-hls-cors-not-supported", dismiss: false, }); + throw new Error(e); } }; @@ -7743,64 +3168,101 @@ var VR = (function (_Plugin) { false ); this.effect = new VREffect(this.renderer); - this.effect.setSize( this.player_.currentWidth(), this.player_.currentHeight(), false ); - this.vrDisplay = null; + this.vrDisplay = null; // Previous timestamps for gamepad updates - // Previous timestamps for gamepad updates this.prevTimestamps_ = []; - this.renderedCanvas = this.renderer.domElement; this.renderedCanvas.setAttribute( "style", "width: 100%; height: 100%; position: absolute; top:0;" ); + var videoElStyle = this.getVideoEl_().style; this.player_ .el() .insertBefore(this.renderedCanvas, this.player_.el().firstChild); - this.getVideoEl_().style.display = "none"; + videoElStyle.zIndex = "-1"; + videoElStyle.opacity = "0"; if (window$1.navigator.getVRDisplays) { - this.log("VR is supported, getting vr displays"); + this.log("is supported, getting vr displays"); window$1.navigator.getVRDisplays().then(function (displays) { if (displays.length > 0) { - _this3.log("VR Displays found", displays); - _this3.vrDisplay = displays[0]; + _this4.log("Displays found", displays); - // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive + _this4.vrDisplay = displays[0]; // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive // also need the cardboard button to enter fully immersive mode // so, we want to add the button if we're not polyfilled. - if (!_this3.vrDisplay.isPolyfilled) { - _this3.log("Real HMD found using VRControls", _this3.vrDisplay); - _this3.addCardboardButton_(); - // We use VRControls here since we are working with an HMD + if (!_this4.vrDisplay.isPolyfilled) { + _this4.log("Real HMD found using VRControls", _this4.vrDisplay); + + _this4.addCardboardButton_(); // We use VRControls here since we are working with an HMD // and we only want orientation controls. - _this3.controls3d = new VRControls(_this3.camera); + + _this4.controls3d = new VRControls(_this4.camera); } } - if (!_this3.controls3d) { - _this3.log("no HMD found Using Orbit & Orientation Controls"); - _this3.controls3d = new OrbitOrientationControls({ - camera: _this3.camera, - canvas: _this3.renderedCanvas, + if (!_this4.controls3d) { + _this4.log("no HMD found Using Orbit & Orientation Controls"); + + var options = { + camera: _this4.camera, + canvas: _this4.renderedCanvas, + // check if its a half sphere view projection + halfView: _this4.currentProjection_.indexOf("180") === 0, orientation: videojs.browser.IS_IOS || videojs.browser.IS_ANDROID || false, - }); + }; + + if (_this4.options_.motionControls === false) { + options.orientation = false; + } + + _this4.controls3d = new OrbitOrientationControls(options); + _this4.canvasPlayerControls = new CanvasPlayerControls( + _this4.player_, + _this4.renderedCanvas, + _this4.options_ + ); } - _this3.animationFrameId_ = _this3.requestAnimationFrame( - _this3.animate_ + + _this4.animationFrameId_ = _this4.requestAnimationFrame( + _this4.animate_ ); }); } else if (window$1.navigator.getVRDevices) { - this.triggerError_({ code: "web-vr-out-of-date", dismiss: false }); + this.triggerError_({ + code: "web-vr-out-of-date", + dismiss: false, + }); } else { - this.triggerError_({ code: "web-vr-not-supported", dismiss: false }); + this.triggerError_({ + code: "web-vr-not-supported", + dismiss: false, + }); + } + + if (this.options_.omnitone) { + var audiocontext = THREE.AudioContext.getContext(); + this.omniController = new OmnitoneController( + audiocontext, + this.options_.omnitone, + this.getVideoEl_(), + this.options_.omnitoneOptions + ); + this.omniController.one("audiocontext-suspended", function () { + _this4.player.pause(); + + _this4.player.one("playing", function () { + audiocontext.resume(); + }); + }); } this.on(this.player_, "fullscreenchange", this.handleResize_); @@ -7820,78 +3282,93 @@ var VR = (function (_Plugin) { this.handleVrDisplayDeactivate_, true ); - this.initialized_ = true; + this.trigger("initialized"); }; - VR.prototype.addCardboardButton_ = function addCardboardButton_() { + _proto.addCardboardButton_ = function addCardboardButton_() { if (!this.player_.controlBar.getChild("CardboardButton")) { this.player_.controlBar.addChild("CardboardButton", {}); } }; - VR.prototype.getVideoEl_ = function getVideoEl_() { + _proto.getVideoEl_ = function getVideoEl_() { return this.player_.el().getElementsByTagName("video")[0]; }; - VR.prototype.reset = function reset() { + _proto.reset = function reset() { if (!this.initialized_) { return; } + if (this.omniController) { + this.omniController.off("audiocontext-suspended"); + this.omniController.dispose(); + this.omniController = undefined; + } + if (this.controls3d) { this.controls3d.dispose(); + this.controls3d = null; + } + + if (this.canvasPlayerControls) { + this.canvasPlayerControls.dispose(); + this.canvasPlayerControls = null; } + if (this.effect) { this.effect.dispose(); + this.effect = null; } - window$1.removeEventListener("resize", this.handleResize_); - window$1.removeEventListener("vrdisplaypresentchange", this.handleResize_); + window$1.removeEventListener("resize", this.handleResize_, true); + window$1.removeEventListener( + "vrdisplaypresentchange", + this.handleResize_, + true + ); window$1.removeEventListener( "vrdisplayactivate", - this.handleVrDisplayActivate_ + this.handleVrDisplayActivate_, + true ); window$1.removeEventListener( "vrdisplaydeactivate", - this.handleVrDisplayDeactivate_ - ); + this.handleVrDisplayDeactivate_, + true + ); // re-add the big play button to player - // re-add the big play button to player if (!this.player_.getChild("BigPlayButton")) { this.player_.addChild("BigPlayButton", {}, this.bigPlayButtonIndex_); } if (this.player_.getChild("BigVrPlayButton")) { this.player_.removeChild("BigVrPlayButton"); - } + } // remove the cardboard button - // remove the cardboard button if (this.player_.getChild("CardboardButton")) { this.player_.controlBar.removeChild("CardboardButton"); - } + } // show the fullscreen again - // show the fullscreen again - if (videojs.browser.IS_IOS) { + if ( + videojs.browser.IS_IOS && + this.player_.controlBar && + this.player_.controlBar.fullscreenToggle + ) { this.player_.controlBar.fullscreenToggle.show(); - } + } // reset the video element style so that it will be displayed - // reset the video element style so that it will be displayed - this.getVideoEl_().style.display = ""; + var videoElStyle = this.getVideoEl_().style; + videoElStyle.zIndex = ""; + videoElStyle.opacity = ""; // set the current projection to the default - // set the current projection to the default - this.currentProjection_ = this.defaultProjection_; - - if (this.observer_) { - this.observer_.disconnect(); - } + this.currentProjection_ = this.defaultProjection_; // reset the ios touch to click workaround - // reset the ios touch to click workaround if (this.iosRevertTouchToClick_) { this.iosRevertTouchToClick_(); - } + } // remove the old canvas - // remove the old canvas if (this.renderedCanvas) { this.renderedCanvas.parentNode.removeChild(this.renderedCanvas); } @@ -7903,12 +3380,13 @@ var VR = (function (_Plugin) { this.initialized_ = false; }; - VR.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { _Plugin.prototype.dispose.call(this); + this.reset(); }; - VR.prototype.polyfillVersion = function polyfillVersion() { + _proto.polyfillVersion = function polyfillVersion() { return WebVRPolyfill.version; }; @@ -7917,9 +3395,7 @@ var VR = (function (_Plugin) { VR.prototype.setTimeout = Component.prototype.setTimeout; VR.prototype.clearTimeout = Component.prototype.clearTimeout; - VR.VERSION = version; - videojs.registerPlugin("vr", VR); module.exports = VR; diff --git a/pod/main/static/videojs-vr/videojs-vr.css b/pod/main/static/videojs-vr/videojs-vr.css index bbbd2807f2..55714a2abe 100644 --- a/pod/main/static/videojs-vr/videojs-vr.css +++ b/pod/main/static/videojs-vr/videojs-vr.css @@ -1,7 +1,30 @@ -/** - * videojs-vr - * @version 1.3.0 - * @copyright 2018 [object Object] - * @license Apache-2.0 - */ -.video-js .vjs-big-vr-play-button{width:100px;height:100px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='360' height='360' viewBox='0 0 360 360'%3E%3Cpath fill='%23FFF' d='M334.883 275.78l-6.374-36.198-6.375-36.2-28.16 23.62-28.164 23.62 25.837 9.41C266.247 296.544 224 320.5 176.25 320.5c-77.47 0-140.5-63.03-140.5-140.5 0-77.472 63.03-140.5 140.5-140.5 53.428 0 99.98 29.978 123.733 73.993l13.304-6.923C287.025 57.76 235.45 24.5 176.25 24.5c-85.743 0-155.5 69.757-155.5 155.5 0 85.742 69.757 155.5 155.5 155.5 54.253 0 102.09-27.94 129.922-70.177l28.71 10.457z'/%3E%3Cpath fill='%23FFF' d='M314.492 175.167c-12.98 0-23.54-10.56-23.54-23.54s10.56-23.54 23.54-23.54c12.98 0 23.54 10.56 23.54 23.54s-10.56 23.54-23.54 23.54zm0-38.08c-8.018 0-14.54 6.522-14.54 14.54s6.522 14.54 14.54 14.54c8.017 0 14.54-6.522 14.54-14.54s-6.523-14.54-14.54-14.54z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M88.76 173.102h9.395c4.74-.042 8.495-1.27 11.268-3.682 2.77-2.412 4.157-5.903 4.157-10.474 0-4.4-1.153-7.817-3.46-10.25-2.307-2.434-5.83-3.65-10.568-3.65-4.147 0-7.554 1.195-10.22 3.585-2.666 2.392-4 5.514-4 9.364H69.908c0-4.74 1.26-9.055 3.776-12.95 2.518-3.892 6.03-6.928 10.537-9.108 4.508-2.18 9.554-3.27 15.14-3.27 9.225 0 16.472 2.318 21.74 6.952 5.27 4.634 7.903 11.077 7.903 19.33 0 4.147-1.323 8.05-3.967 11.71-2.646 3.66-6.062 6.422-10.252 8.284 5.078 1.736 8.94 4.465 11.584 8.19s3.968 8.166 3.968 13.33c0 8.294-2.847 14.895-8.538 19.804s-13.17 7.363-22.438 7.363c-8.887 0-16.166-2.37-21.836-7.11-5.67-4.74-8.506-11.045-8.506-18.916h15.425c0 4.062 1.365 7.363 4.094 9.902 2.73 2.54 6.4 3.81 11.014 3.81 4.782 0 8.55-1.27 11.3-3.81s4.126-6.22 4.126-11.045c0-4.865-1.44-8.61-4.316-11.235-2.878-2.623-7.152-3.936-12.822-3.936H88.76V173.1zM187.598 133.493v12.76h-1.904c-8.633.126-15.53 2.497-20.693 7.108-5.162 4.614-8.23 11.152-9.203 19.615 4.95-5.205 11.277-7.808 18.98-7.808 8.166 0 14.608 2.878 19.328 8.633 4.718 5.755 7.077 13.182 7.077 22.28 0 9.395-2.76 17.002-8.284 22.82-5.52 5.818-12.77 8.73-21.74 8.73-9.226 0-16.705-3.407-22.44-10.222-5.733-6.812-8.6-15.742-8.6-26.787v-5.267c0-16.208 3.945-28.903 11.84-38.086 7.89-9.182 19.242-13.774 34.054-13.774h1.586zM171.03 177.61c-3.386 0-6.485.95-9.3 2.855-2.814 1.904-4.877 4.443-6.188 7.617v4.697c0 6.854 1.438 12.304 4.316 16.345 2.877 4.04 6.602 6.062 11.172 6.062s8.188-1.715 10.854-5.143 4-7.934 4-13.52-1.355-10.135-4.063-13.648c-2.708-3.51-6.304-5.267-10.79-5.267zM271.136 187.447c0 13.29-2.486 23.307-7.46 30.057s-12.535 10.125-22.69 10.125c-9.988 0-17.51-3.292-22.566-9.872-5.058-6.58-7.65-16.323-7.776-29.23V172.53c0-13.287 2.485-23.252 7.458-29.896 4.973-6.643 12.558-9.966 22.757-9.966 10.112 0 17.655 3.237 22.63 9.712 4.97 6.475 7.52 16.166 7.647 29.072v15.995zm-15.425-17.265c0-8.674-1.185-15.033-3.554-19.075-2.37-4.04-6.137-6.062-11.3-6.062-5.035 0-8.738 1.915-11.107 5.745-2.37 3.83-3.62 9.807-3.746 17.932v20.948c0 8.633 1.206 15.064 3.618 19.297s6.2 6.348 11.362 6.348c4.95 0 8.61-1.957 10.98-5.87 2.37-3.915 3.62-10.04 3.746-18.378v-20.885z'/%3E%3C/g%3E%3C/svg%3E");background-size:contain;background-color:rgba(0,0,0,0.5)}.video-js .vjs-big-vr-play-button .vjs-icon-placeholder{display:none}:hover.video-js .vjs-big-vr-play-button{-webkit-transition:border-color 0.4s,outline 0.4s,background-color 0.4s;-moz-transition:border-color 0.4s,outline 0.4s,background-color 0.4s;-ms-transition:border-color 0.4s,outline 0.4s,background-color 0.4s;-o-transition:border-color 0.4s,outline 0.4s,background-color 0.4s;transition:border-color 0.4s,outline 0.4s,background-color 0.4s}.video-js .vjs-big-vr-play-button::before{content:''}.video-js canvas{cursor:move}.video-js .vjs-button-vr .vjs-icon-placeholder{height:30px;width:30px;display:inline-block;background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI0ZGRkZGRiI+CiAgICA8cGF0aCBkPSJNMjAuNzQgNkgzLjIxQzIuNTUgNiAyIDYuNTcgMiA3LjI4djEwLjQ0YzAgLjcuNTUgMS4yOCAxLjIzIDEuMjhoNC43OWMuNTIgMCAuOTYtLjMzIDEuMTQtLjc5bDEuNC0zLjQ4Yy4yMy0uNTkuNzktMS4wMSAxLjQ0LTEuMDFzMS4yMS40MiAxLjQ1IDEuMDFsMS4zOSAzLjQ4Yy4xOS40Ni42My43OSAxLjExLjc5aDQuNzljLjcxIDAgMS4yNi0uNTcgMS4yNi0xLjI4VjcuMjhjMC0uNy0uNTUtMS4yOC0xLjI2LTEuMjh6TTcuNSAxNC42MmMtMS4xNyAwLTIuMTMtLjk1LTIuMTMtMi4xMiAwLTEuMTcuOTYtMi4xMyAyLjEzLTIuMTMgMS4xOCAwIDIuMTIuOTYgMi4xMiAyLjEzcy0uOTUgMi4xMi0yLjEyIDIuMTJ6bTkgMGMtMS4xNyAwLTIuMTMtLjk1LTIuMTMtMi4xMiAwLTEuMTcuOTYtMi4xMyAyLjEzLTIuMTNzMi4xMi45NiAyLjEyIDIuMTMtLjk1IDIuMTItMi4xMiAyLjEyeiIvPgogICAgPHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+Cjwvc3ZnPgo=) no-repeat left center} +.video-js .vjs-big-vr-play-button { + width: 100px; + height: 100px; + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='360' height='360' viewBox='0 0 360 360'%3E%3Cpath fill='%23FFF' d='M334.883 275.78l-6.374-36.198-6.375-36.2-28.16 23.62-28.164 23.62 25.837 9.41C266.247 296.544 224 320.5 176.25 320.5c-77.47 0-140.5-63.03-140.5-140.5 0-77.472 63.03-140.5 140.5-140.5 53.428 0 99.98 29.978 123.733 73.993l13.304-6.923C287.025 57.76 235.45 24.5 176.25 24.5c-85.743 0-155.5 69.757-155.5 155.5 0 85.742 69.757 155.5 155.5 155.5 54.253 0 102.09-27.94 129.922-70.177l28.71 10.457z'/%3E%3Cpath fill='%23FFF' d='M314.492 175.167c-12.98 0-23.54-10.56-23.54-23.54s10.56-23.54 23.54-23.54c12.98 0 23.54 10.56 23.54 23.54s-10.56 23.54-23.54 23.54zm0-38.08c-8.018 0-14.54 6.522-14.54 14.54s6.522 14.54 14.54 14.54c8.017 0 14.54-6.522 14.54-14.54s-6.523-14.54-14.54-14.54z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M88.76 173.102h9.395c4.74-.042 8.495-1.27 11.268-3.682 2.77-2.412 4.157-5.903 4.157-10.474 0-4.4-1.153-7.817-3.46-10.25-2.307-2.434-5.83-3.65-10.568-3.65-4.147 0-7.554 1.195-10.22 3.585-2.666 2.392-4 5.514-4 9.364H69.908c0-4.74 1.26-9.055 3.776-12.95 2.518-3.892 6.03-6.928 10.537-9.108 4.508-2.18 9.554-3.27 15.14-3.27 9.225 0 16.472 2.318 21.74 6.952 5.27 4.634 7.903 11.077 7.903 19.33 0 4.147-1.323 8.05-3.967 11.71-2.646 3.66-6.062 6.422-10.252 8.284 5.078 1.736 8.94 4.465 11.584 8.19s3.968 8.166 3.968 13.33c0 8.294-2.847 14.895-8.538 19.804s-13.17 7.363-22.438 7.363c-8.887 0-16.166-2.37-21.836-7.11-5.67-4.74-8.506-11.045-8.506-18.916h15.425c0 4.062 1.365 7.363 4.094 9.902 2.73 2.54 6.4 3.81 11.014 3.81 4.782 0 8.55-1.27 11.3-3.81s4.126-6.22 4.126-11.045c0-4.865-1.44-8.61-4.316-11.235-2.878-2.623-7.152-3.936-12.822-3.936H88.76V173.1zM187.598 133.493v12.76h-1.904c-8.633.126-15.53 2.497-20.693 7.108-5.162 4.614-8.23 11.152-9.203 19.615 4.95-5.205 11.277-7.808 18.98-7.808 8.166 0 14.608 2.878 19.328 8.633 4.718 5.755 7.077 13.182 7.077 22.28 0 9.395-2.76 17.002-8.284 22.82-5.52 5.818-12.77 8.73-21.74 8.73-9.226 0-16.705-3.407-22.44-10.222-5.733-6.812-8.6-15.742-8.6-26.787v-5.267c0-16.208 3.945-28.903 11.84-38.086 7.89-9.182 19.242-13.774 34.054-13.774h1.586zM171.03 177.61c-3.386 0-6.485.95-9.3 2.855-2.814 1.904-4.877 4.443-6.188 7.617v4.697c0 6.854 1.438 12.304 4.316 16.345 2.877 4.04 6.602 6.062 11.172 6.062s8.188-1.715 10.854-5.143 4-7.934 4-13.52-1.355-10.135-4.063-13.648c-2.708-3.51-6.304-5.267-10.79-5.267zM271.136 187.447c0 13.29-2.486 23.307-7.46 30.057s-12.535 10.125-22.69 10.125c-9.988 0-17.51-3.292-22.566-9.872-5.058-6.58-7.65-16.323-7.776-29.23V172.53c0-13.287 2.485-23.252 7.458-29.896 4.973-6.643 12.558-9.966 22.757-9.966 10.112 0 17.655 3.237 22.63 9.712 4.97 6.475 7.52 16.166 7.647 29.072v15.995zm-15.425-17.265c0-8.674-1.185-15.033-3.554-19.075-2.37-4.04-6.137-6.062-11.3-6.062-5.035 0-8.738 1.915-11.107 5.745-2.37 3.83-3.62 9.807-3.746 17.932v20.948c0 8.633 1.206 15.064 3.618 19.297s6.2 6.348 11.362 6.348c4.95 0 8.61-1.957 10.98-5.87 2.37-3.915 3.62-10.04 3.746-18.378v-20.885z'/%3E%3C/g%3E%3C/svg%3E"); + background-size: contain; + background-color: rgba(0, 0, 0, 0.5); +} +.video-js .vjs-big-vr-play-button .vjs-icon-placeholder { + display: none; +} +:hover.video-js .vjs-big-vr-play-button { + -webkit-transition: border-color 0.4s, outline 0.4s, background-color 0.4s; + -moz-transition: border-color 0.4s, outline 0.4s, background-color 0.4s; + -ms-transition: border-color 0.4s, outline 0.4s, background-color 0.4s; + -o-transition: border-color 0.4s, outline 0.4s, background-color 0.4s; + transition: border-color 0.4s, outline 0.4s, background-color 0.4s; +} + +.video-js .vjs-big-vr-play-button::before { + content: ""; +} +.video-js canvas { + cursor: move; +} +.video-js .vjs-button-vr .vjs-icon-placeholder { + height: 30px; + width: 30px; + display: inline-block; + background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI0ZGRkZGRiI+CiAgICA8cGF0aCBkPSJNMjAuNzQgNkgzLjIxQzIuNTUgNiAyIDYuNTcgMiA3LjI4djEwLjQ0YzAgLjcuNTUgMS4yOCAxLjIzIDEuMjhoNC43OWMuNTIgMCAuOTYtLjMzIDEuMTQtLjc5bDEuNC0zLjQ4Yy4yMy0uNTkuNzktMS4wMSAxLjQ0LTEuMDFzMS4yMS40MiAxLjQ1IDEuMDFsMS4zOSAzLjQ4Yy4xOS40Ni42My43OSAxLjExLjc5aDQuNzljLjcxIDAgMS4yNi0uNTcgMS4yNi0xLjI4VjcuMjhjMC0uNy0uNTUtMS4yOC0xLjI2LTEuMjh6TTcuNSAxNC42MmMtMS4xNyAwLTIuMTMtLjk1LTIuMTMtMi4xMiAwLTEuMTcuOTYtMi4xMyAyLjEzLTIuMTMgMS4xOCAwIDIuMTIuOTYgMi4xMiAyLjEzcy0uOTUgMi4xMi0yLjEyIDIuMTJ6bTkgMGMtMS4xNyAwLTIuMTMtLjk1LTIuMTMtMi4xMiAwLTEuMTcuOTYtMi4xMyAyLjEzLTIuMTNzMi4xMi45NiAyLjEyIDIuMTMtLjk1IDIuMTItMi4xMiAyLjEyeiIvPgogICAgPHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+Cjwvc3ZnPgo=) no-repeat left center; +} diff --git a/pod/main/static/videojs-vr/videojs-vr.es.js b/pod/main/static/videojs-vr/videojs-vr.es.js index 1f44265a08..5d98c1d297 100644 --- a/pod/main/static/videojs-vr/videojs-vr.es.js +++ b/pod/main/static/videojs-vr/videojs-vr.es.js @@ -1,5169 +1,39 @@ -import { - SphereBufferGeometry, - MeshBasicMaterial, - BackSide, - Mesh, - SphereGeometry, - BufferGeometry, - BoxGeometry, - Vector2, - PerspectiveCamera, - Vector3, - Scene, - VideoTexture, - LinearFilter, - RGBFormat, - WebGLRenderer, - Matrix4, - Quaternion, - MOUSE, - Spherical, - EventDispatcher, - Euler, - Math as Math$1, -} from "three"; -import document$1 from "global/document"; -import window$1 from "global/window"; -import videojs from "video.js"; - -var version = "1.3.0"; - -var commonjsGlobal = - typeof window !== "undefined" - ? window - : typeof global !== "undefined" - ? global - : typeof self !== "undefined" - ? self - : {}; - -function unwrapExports(x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") - ? x["default"] - : x; -} - -function createCommonjsModule(fn, module) { - return (module = { exports: {} }), fn(module, module.exports), module.exports; -} - -var webvrPolyfill = createCommonjsModule(function (module, exports) { - /** - * @license - * webvr-polyfill - * Copyright (c) 2015-2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /** - * @license - * cardboard-vr-display - * Copyright (c) 2015-2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /** - * @license - * webvr-polyfill-dpdb - * Copyright (c) 2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /** - * @license - * wglu-preserve-state - * Copyright (c) 2016, Brandon Jones. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - /** - * @license - * nosleep.js - * Copyright (c) 2017, Rich Tibbett - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - (function (global, factory) { - module.exports = factory(); - })(commonjsGlobal, function () { - var commonjsGlobal$$1 = - typeof window !== "undefined" - ? window - : typeof commonjsGlobal !== "undefined" - ? commonjsGlobal - : typeof self !== "undefined" - ? self - : {}; - - function unwrapExports$$1(x) { - return x && - x.__esModule && - Object.prototype.hasOwnProperty.call(x, "default") - ? x["default"] - : x; - } - - function createCommonjsModule$$1(fn, module) { - return ( - (module = { exports: {} }), fn(module, module.exports), module.exports - ); - } - - var race = function race(promises) { - if (Promise.race) { - return Promise.race(promises); - } - return new Promise(function (resolve, reject) { - for (var i = 0; i < promises.length; i++) { - promises[i].then(resolve, reject); - } - }); - }; - - var isMobile = function isMobile() { - return ( - /Android/i.test(navigator.userAgent) || - /iPhone|iPad|iPod/i.test(navigator.userAgent) - ); - }; - var copyArray = function copyArray(source, dest) { - for (var i = 0, n = source.length; i < n; i++) { - dest[i] = source[i]; - } - }; - var extend = function extend(dest, src) { - for (var key in src) { - if (src.hasOwnProperty(key)) { - dest[key] = src[key]; - } - } - return dest; - }; - - var cardboardVrDisplay = createCommonjsModule$$1(function ( - module, - exports - ) { - /** - * @license - * cardboard-vr-display - * Copyright (c) 2015-2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - /** - * @license - * gl-preserve-state - * Copyright (c) 2016, Brandon Jones. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - /** - * @license - * webvr-polyfill-dpdb - * Copyright (c) 2015-2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - /** - * @license - * nosleep.js - * Copyright (c) 2017, Rich Tibbett - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - (function (global, factory) { - module.exports = factory(); - })(commonjsGlobal$$1, function () { - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - var createClass = (function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - })(); - var slicedToArray = (function () { - function sliceIterator(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - try { - for ( - var _i = arr[Symbol.iterator](), _s; - !(_n = (_s = _i.next()).done); - _n = true - ) { - _arr.push(_s.value); - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"]) _i["return"](); - } finally { - if (_d) throw _e; - } - } - return _arr; - } - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError( - "Invalid attempt to destructure non-iterable instance" - ); - } - }; - })(); - var MIN_TIMESTEP = 0.001; - var MAX_TIMESTEP = 1; - var base64 = function base64(mimeType, _base) { - return "data:" + mimeType + ";base64," + _base; - }; - var lerp = function lerp(a, b, t) { - return a + (b - a) * t; - }; - var isIOS = (function () { - var isIOS = /iPad|iPhone|iPod/.test(navigator.platform); - return function () { - return isIOS; - }; - })(); - var isWebViewAndroid = (function () { - var isWebViewAndroid = - navigator.userAgent.indexOf("Version") !== -1 && - navigator.userAgent.indexOf("Android") !== -1 && - navigator.userAgent.indexOf("Chrome") !== -1; - return function () { - return isWebViewAndroid; - }; - })(); - var isSafari = (function () { - var isSafari = /^((?!chrome|android).)*safari/i.test( - navigator.userAgent - ); - return function () { - return isSafari; - }; - })(); - var isFirefoxAndroid = (function () { - var isFirefoxAndroid = - navigator.userAgent.indexOf("Firefox") !== -1 && - navigator.userAgent.indexOf("Android") !== -1; - return function () { - return isFirefoxAndroid; - }; - })(); - var getChromeVersion = (function () { - var match = navigator.userAgent.match(/.*Chrome\/([0-9]+)/); - var value = match ? parseInt(match[1], 10) : null; - return function () { - return value; - }; - })(); - var isChromeWithoutDeviceMotion = (function () { - var value = false; - if (getChromeVersion() === 65) { - var match = navigator.userAgent.match(/.*Chrome\/([0-9\.]*)/); - if (match) { - var _match$1$split = match[1].split("."), - _match$1$split2 = slicedToArray(_match$1$split, 4), - major = _match$1$split2[0], - minor = _match$1$split2[1], - branch = _match$1$split2[2], - build = _match$1$split2[3]; - value = - parseInt(branch, 10) === 3325 && parseInt(build, 10) < 148; - } - } - return function () { - return value; - }; - })(); - var isR7 = (function () { - var isR7 = navigator.userAgent.indexOf("R7 Build") !== -1; - return function () { - return isR7; - }; - })(); - var isLandscapeMode = function isLandscapeMode() { - var rtn = window.orientation == 90 || window.orientation == -90; - return isR7() ? !rtn : rtn; - }; - var isTimestampDeltaValid = function isTimestampDeltaValid( - timestampDeltaS - ) { - if (isNaN(timestampDeltaS)) { - return false; - } - if (timestampDeltaS <= MIN_TIMESTEP) { - return false; - } - if (timestampDeltaS > MAX_TIMESTEP) { - return false; - } - return true; - }; - var getScreenWidth = function getScreenWidth() { - return ( - Math.max(window.screen.width, window.screen.height) * - window.devicePixelRatio - ); - }; - var getScreenHeight = function getScreenHeight() { - return ( - Math.min(window.screen.width, window.screen.height) * - window.devicePixelRatio - ); - }; - var requestFullscreen = function requestFullscreen(element) { - if (isWebViewAndroid()) { - return false; - } - if (element.requestFullscreen) { - element.requestFullscreen(); - } else if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.msRequestFullscreen) { - element.msRequestFullscreen(); - } else { - return false; - } - return true; - }; - var exitFullscreen = function exitFullscreen() { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } else { - return false; - } - return true; - }; - var getFullscreenElement = function getFullscreenElement() { - return ( - document.fullscreenElement || - document.webkitFullscreenElement || - document.mozFullScreenElement || - document.msFullscreenElement - ); - }; - var linkProgram = function linkProgram( - gl, - vertexSource, - fragmentSource, - attribLocationMap - ) { - var vertexShader = gl.createShader(gl.VERTEX_SHADER); - gl.shaderSource(vertexShader, vertexSource); - gl.compileShader(vertexShader); - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(fragmentShader, fragmentSource); - gl.compileShader(fragmentShader); - var program = gl.createProgram(); - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - for (var attribName in attribLocationMap) { - gl.bindAttribLocation( - program, - attribLocationMap[attribName], - attribName - ); - } - gl.linkProgram(program); - gl.deleteShader(vertexShader); - gl.deleteShader(fragmentShader); - return program; - }; - var getProgramUniforms = function getProgramUniforms(gl, program) { - var uniforms = {}; - var uniformCount = gl.getProgramParameter( - program, - gl.ACTIVE_UNIFORMS - ); - var uniformName = ""; - for (var i = 0; i < uniformCount; i++) { - var uniformInfo = gl.getActiveUniform(program, i); - uniformName = uniformInfo.name.replace("[0]", ""); - uniforms[uniformName] = gl.getUniformLocation(program, uniformName); - } - return uniforms; - }; - var orthoMatrix = function orthoMatrix( - out, - left, - right, - bottom, - top, - near, - far - ) { - var lr = 1 / (left - right), - bt = 1 / (bottom - top), - nf = 1 / (near - far); - out[0] = -2 * lr; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = -2 * bt; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 2 * nf; - out[11] = 0; - out[12] = (left + right) * lr; - out[13] = (top + bottom) * bt; - out[14] = (far + near) * nf; - out[15] = 1; - return out; - }; - var isMobile = function isMobile() { - var check = false; - (function (a) { - if ( - /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test( - a - ) || - /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( - a.substr(0, 4) - ) - ) - check = true; - })(navigator.userAgent || navigator.vendor || window.opera); - return check; - }; - var extend = function extend(dest, src) { - for (var key in src) { - if (src.hasOwnProperty(key)) { - dest[key] = src[key]; - } - } - return dest; - }; - var safariCssSizeWorkaround = function safariCssSizeWorkaround(canvas) { - if (isIOS()) { - var width = canvas.style.width; - var height = canvas.style.height; - canvas.style.width = parseInt(width) + 1 + "px"; - canvas.style.height = parseInt(height) + "px"; - setTimeout(function () { - canvas.style.width = width; - canvas.style.height = height; - }, 100); - } - window.canvas = canvas; - }; - var frameDataFromPose = (function () { - var piOver180 = Math.PI / 180.0; - var rad45 = Math.PI * 0.25; - function mat4_perspectiveFromFieldOfView(out, fov, near, far) { - var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45), - downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45), - leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45), - rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45), - xScale = 2.0 / (leftTan + rightTan), - yScale = 2.0 / (upTan + downTan); - out[0] = xScale; - out[1] = 0.0; - out[2] = 0.0; - out[3] = 0.0; - out[4] = 0.0; - out[5] = yScale; - out[6] = 0.0; - out[7] = 0.0; - out[8] = -((leftTan - rightTan) * xScale * 0.5); - out[9] = (upTan - downTan) * yScale * 0.5; - out[10] = far / (near - far); - out[11] = -1.0; - out[12] = 0.0; - out[13] = 0.0; - out[14] = (far * near) / (near - far); - out[15] = 0.0; - return out; - } - function mat4_fromRotationTranslation(out, q, v) { - var x = q[0], - y = q[1], - z = q[2], - w = q[3], - x2 = x + x, - y2 = y + y, - z2 = z + z, - xx = x * x2, - xy = x * y2, - xz = x * z2, - yy = y * y2, - yz = y * z2, - zz = z * z2, - wx = w * x2, - wy = w * y2, - wz = w * z2; - out[0] = 1 - (yy + zz); - out[1] = xy + wz; - out[2] = xz - wy; - out[3] = 0; - out[4] = xy - wz; - out[5] = 1 - (xx + zz); - out[6] = yz + wx; - out[7] = 0; - out[8] = xz + wy; - out[9] = yz - wx; - out[10] = 1 - (xx + yy); - out[11] = 0; - out[12] = v[0]; - out[13] = v[1]; - out[14] = v[2]; - out[15] = 1; - return out; - } - function mat4_translate(out, a, v) { - var x = v[0], - y = v[1], - z = v[2], - a00, - a01, - a02, - a03, - a10, - a11, - a12, - a13, - a20, - a21, - a22, - a23; - if (a === out) { - out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; - out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; - out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; - out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; - } else { - a00 = a[0]; - a01 = a[1]; - a02 = a[2]; - a03 = a[3]; - a10 = a[4]; - a11 = a[5]; - a12 = a[6]; - a13 = a[7]; - a20 = a[8]; - a21 = a[9]; - a22 = a[10]; - a23 = a[11]; - out[0] = a00; - out[1] = a01; - out[2] = a02; - out[3] = a03; - out[4] = a10; - out[5] = a11; - out[6] = a12; - out[7] = a13; - out[8] = a20; - out[9] = a21; - out[10] = a22; - out[11] = a23; - out[12] = a00 * x + a10 * y + a20 * z + a[12]; - out[13] = a01 * x + a11 * y + a21 * z + a[13]; - out[14] = a02 * x + a12 * y + a22 * z + a[14]; - out[15] = a03 * x + a13 * y + a23 * z + a[15]; - } - return out; - } - function mat4_invert(out, a) { - var a00 = a[0], - a01 = a[1], - a02 = a[2], - a03 = a[3], - a10 = a[4], - a11 = a[5], - a12 = a[6], - a13 = a[7], - a20 = a[8], - a21 = a[9], - a22 = a[10], - a23 = a[11], - a30 = a[12], - a31 = a[13], - a32 = a[14], - a33 = a[15], - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32, - det = - b00 * b11 - - b01 * b10 + - b02 * b09 + - b03 * b08 - - b04 * b07 + - b05 * b06; - if (!det) { - return null; - } - det = 1.0 / det; - out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; - return out; - } - var defaultOrientation = new Float32Array([0, 0, 0, 1]); - var defaultPosition = new Float32Array([0, 0, 0]); - function updateEyeMatrices( - projection, - view, - pose, - fov, - offset, - vrDisplay - ) { - mat4_perspectiveFromFieldOfView( - projection, - fov || null, - vrDisplay.depthNear, - vrDisplay.depthFar - ); - var orientation = pose.orientation || defaultOrientation; - var position = pose.position || defaultPosition; - mat4_fromRotationTranslation(view, orientation, position); - if (offset) mat4_translate(view, view, offset); - mat4_invert(view, view); - } - return function (frameData, pose, vrDisplay) { - if (!frameData || !pose) return false; - frameData.pose = pose; - frameData.timestamp = pose.timestamp; - updateEyeMatrices( - frameData.leftProjectionMatrix, - frameData.leftViewMatrix, - pose, - vrDisplay._getFieldOfView("left"), - vrDisplay._getEyeOffset("left"), - vrDisplay - ); - updateEyeMatrices( - frameData.rightProjectionMatrix, - frameData.rightViewMatrix, - pose, - vrDisplay._getFieldOfView("right"), - vrDisplay._getEyeOffset("right"), - vrDisplay - ); - return true; - }; - })(); - var isInsideCrossOriginIFrame = function isInsideCrossOriginIFrame() { - var isFramed = window.self !== window.top; - var refOrigin = getOriginFromUrl(document.referrer); - var thisOrigin = getOriginFromUrl(window.location.href); - return isFramed && refOrigin !== thisOrigin; - }; - var getOriginFromUrl = function getOriginFromUrl(url) { - var domainIdx; - var protoSepIdx = url.indexOf("://"); - if (protoSepIdx !== -1) { - domainIdx = protoSepIdx + 3; - } else { - domainIdx = 0; - } - var domainEndIdx = url.indexOf("/", domainIdx); - if (domainEndIdx === -1) { - domainEndIdx = url.length; - } - return url.substring(0, domainEndIdx); - }; - var getQuaternionAngle = function getQuaternionAngle(quat) { - if (quat.w > 1) { - console.warn("getQuaternionAngle: w > 1"); - return 0; - } - var angle = 2 * Math.acos(quat.w); - return angle; - }; - var warnOnce = (function () { - var observedWarnings = {}; - return function (key, message) { - if (observedWarnings[key] === undefined) { - console.warn("webvr-polyfill: " + message); - observedWarnings[key] = true; - } - }; - })(); - var deprecateWarning = function deprecateWarning( - deprecated, - suggested - ) { - var alternative = suggested - ? "Please use " + suggested + " instead." - : ""; - warnOnce( - deprecated, - deprecated + - " has been deprecated. " + - "This may not work on native WebVR displays. " + - alternative - ); - }; - function WGLUPreserveGLState(gl, bindings, callback) { - if (!bindings) { - callback(gl); - return; - } - var boundValues = []; - var activeTexture = null; - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - switch (binding) { - case gl.TEXTURE_BINDING_2D: - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) { - console.error( - "TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit" - ); - boundValues.push(null, null); - break; - } - if (!activeTexture) { - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - } - gl.activeTexture(textureUnit); - boundValues.push(gl.getParameter(binding), null); - break; - case gl.ACTIVE_TEXTURE: - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - boundValues.push(null); - break; - default: - boundValues.push(gl.getParameter(binding)); - break; - } - } - callback(gl); - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - var boundValue = boundValues[i]; - switch (binding) { - case gl.ACTIVE_TEXTURE: - break; - case gl.ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ARRAY_BUFFER, boundValue); - break; - case gl.COLOR_CLEAR_VALUE: - gl.clearColor( - boundValue[0], - boundValue[1], - boundValue[2], - boundValue[3] - ); - break; - case gl.COLOR_WRITEMASK: - gl.colorMask( - boundValue[0], - boundValue[1], - boundValue[2], - boundValue[3] - ); - break; - case gl.CURRENT_PROGRAM: - gl.useProgram(boundValue); - break; - case gl.ELEMENT_ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue); - break; - case gl.FRAMEBUFFER_BINDING: - gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue); - break; - case gl.RENDERBUFFER_BINDING: - gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue); - break; - case gl.TEXTURE_BINDING_2D: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_2D, boundValue); - break; - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue); - break; - case gl.VIEWPORT: - gl.viewport( - boundValue[0], - boundValue[1], - boundValue[2], - boundValue[3] - ); - break; - case gl.BLEND: - case gl.CULL_FACE: - case gl.DEPTH_TEST: - case gl.SCISSOR_TEST: - case gl.STENCIL_TEST: - if (boundValue) { - gl.enable(binding); - } else { - gl.disable(binding); - } - break; - default: - console.log( - "No GL restore behavior for 0x" + binding.toString(16) - ); - break; - } - if (activeTexture) { - gl.activeTexture(activeTexture); - } - } - } - var glPreserveState = WGLUPreserveGLState; - var distortionVS = [ - "attribute vec2 position;", - "attribute vec3 texCoord;", - "varying vec2 vTexCoord;", - "uniform vec4 viewportOffsetScale[2];", - "void main() {", - " vec4 viewport = viewportOffsetScale[int(texCoord.z)];", - " vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;", - " gl_Position = vec4( position, 1.0, 1.0 );", - "}", - ].join("\n"); - var distortionFS = [ - "precision mediump float;", - "uniform sampler2D diffuse;", - "varying vec2 vTexCoord;", - "void main() {", - " gl_FragColor = texture2D(diffuse, vTexCoord);", - "}", - ].join("\n"); - function CardboardDistorter( - gl, - cardboardUI, - bufferScale, - dirtySubmitFrameBindings - ) { - this.gl = gl; - this.cardboardUI = cardboardUI; - this.bufferScale = bufferScale; - this.dirtySubmitFrameBindings = dirtySubmitFrameBindings; - this.ctxAttribs = gl.getContextAttributes(); - this.meshWidth = 20; - this.meshHeight = 20; - this.bufferWidth = gl.drawingBufferWidth; - this.bufferHeight = gl.drawingBufferHeight; - this.realBindFramebuffer = gl.bindFramebuffer; - this.realEnable = gl.enable; - this.realDisable = gl.disable; - this.realColorMask = gl.colorMask; - this.realClearColor = gl.clearColor; - this.realViewport = gl.viewport; - if (!isIOS()) { - this.realCanvasWidth = Object.getOwnPropertyDescriptor( - gl.canvas.__proto__, - "width" - ); - this.realCanvasHeight = Object.getOwnPropertyDescriptor( - gl.canvas.__proto__, - "height" - ); - } - this.isPatched = false; - this.lastBoundFramebuffer = null; - this.cullFace = false; - this.depthTest = false; - this.blend = false; - this.scissorTest = false; - this.stencilTest = false; - this.viewport = [0, 0, 0, 0]; - this.colorMask = [true, true, true, true]; - this.clearColor = [0, 0, 0, 0]; - this.attribs = { - position: 0, - texCoord: 1, - }; - this.program = linkProgram( - gl, - distortionVS, - distortionFS, - this.attribs - ); - this.uniforms = getProgramUniforms(gl, this.program); - this.viewportOffsetScale = new Float32Array(8); - this.setTextureBounds(); - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.indexCount = 0; - this.renderTarget = gl.createTexture(); - this.framebuffer = gl.createFramebuffer(); - this.depthStencilBuffer = null; - this.depthBuffer = null; - this.stencilBuffer = null; - if (this.ctxAttribs.depth && this.ctxAttribs.stencil) { - this.depthStencilBuffer = gl.createRenderbuffer(); - } else if (this.ctxAttribs.depth) { - this.depthBuffer = gl.createRenderbuffer(); - } else if (this.ctxAttribs.stencil) { - this.stencilBuffer = gl.createRenderbuffer(); - } - this.patch(); - this.onResize(); - } - CardboardDistorter.prototype.destroy = function () { - var gl = this.gl; - this.unpatch(); - gl.deleteProgram(this.program); - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.indexBuffer); - gl.deleteTexture(this.renderTarget); - gl.deleteFramebuffer(this.framebuffer); - if (this.depthStencilBuffer) { - gl.deleteRenderbuffer(this.depthStencilBuffer); - } - if (this.depthBuffer) { - gl.deleteRenderbuffer(this.depthBuffer); - } - if (this.stencilBuffer) { - gl.deleteRenderbuffer(this.stencilBuffer); - } - if (this.cardboardUI) { - this.cardboardUI.destroy(); - } - }; - CardboardDistorter.prototype.onResize = function () { - var gl = this.gl; - var self = this; - var glState = [ - gl.RENDERBUFFER_BINDING, - gl.TEXTURE_BINDING_2D, - gl.TEXTURE0, - ]; - glPreserveState(gl, glState, function (gl) { - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); - if (self.scissorTest) { - self.realDisable.call(gl, gl.SCISSOR_TEST); - } - self.realColorMask.call(gl, true, true, true, true); - self.realViewport.call( - gl, - 0, - 0, - gl.drawingBufferWidth, - gl.drawingBufferHeight - ); - self.realClearColor.call(gl, 0, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer); - gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); - gl.texImage2D( - gl.TEXTURE_2D, - 0, - self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, - self.bufferWidth, - self.bufferHeight, - 0, - self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, - gl.UNSIGNED_BYTE, - null - ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri( - gl.TEXTURE_2D, - gl.TEXTURE_WRAP_S, - gl.CLAMP_TO_EDGE - ); - gl.texParameteri( - gl.TEXTURE_2D, - gl.TEXTURE_WRAP_T, - gl.CLAMP_TO_EDGE - ); - gl.framebufferTexture2D( - gl.FRAMEBUFFER, - gl.COLOR_ATTACHMENT0, - gl.TEXTURE_2D, - self.renderTarget, - 0 - ); - if (self.ctxAttribs.depth && self.ctxAttribs.stencil) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer); - gl.renderbufferStorage( - gl.RENDERBUFFER, - gl.DEPTH_STENCIL, - self.bufferWidth, - self.bufferHeight - ); - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - gl.DEPTH_STENCIL_ATTACHMENT, - gl.RENDERBUFFER, - self.depthStencilBuffer - ); - } else if (self.ctxAttribs.depth) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer); - gl.renderbufferStorage( - gl.RENDERBUFFER, - gl.DEPTH_COMPONENT16, - self.bufferWidth, - self.bufferHeight - ); - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - gl.DEPTH_ATTACHMENT, - gl.RENDERBUFFER, - self.depthBuffer - ); - } else if (self.ctxAttribs.stencil) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer); - gl.renderbufferStorage( - gl.RENDERBUFFER, - gl.STENCIL_INDEX8, - self.bufferWidth, - self.bufferHeight - ); - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - gl.STENCIL_ATTACHMENT, - gl.RENDERBUFFER, - self.stencilBuffer - ); - } - if ( - !gl.checkFramebufferStatus(gl.FRAMEBUFFER) === - gl.FRAMEBUFFER_COMPLETE - ) { - console.error("Framebuffer incomplete!"); - } - self.realBindFramebuffer.call( - gl, - gl.FRAMEBUFFER, - self.lastBoundFramebuffer - ); - if (self.scissorTest) { - self.realEnable.call(gl, gl.SCISSOR_TEST); - } - self.realColorMask.apply(gl, self.colorMask); - self.realViewport.apply(gl, self.viewport); - self.realClearColor.apply(gl, self.clearColor); - }); - if (this.cardboardUI) { - this.cardboardUI.onResize(); - } - }; - CardboardDistorter.prototype.patch = function () { - if (this.isPatched) { - return; - } - var self = this; - var canvas = this.gl.canvas; - var gl = this.gl; - if (!isIOS()) { - canvas.width = getScreenWidth() * this.bufferScale; - canvas.height = getScreenHeight() * this.bufferScale; - Object.defineProperty(canvas, "width", { - configurable: true, - enumerable: true, - get: function get() { - return self.bufferWidth; - }, - set: function set(value) { - self.bufferWidth = value; - self.realCanvasWidth.set.call(canvas, value); - self.onResize(); - }, - }); - Object.defineProperty(canvas, "height", { - configurable: true, - enumerable: true, - get: function get() { - return self.bufferHeight; - }, - set: function set(value) { - self.bufferHeight = value; - self.realCanvasHeight.set.call(canvas, value); - self.onResize(); - }, - }); - } - this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); - if (this.lastBoundFramebuffer == null) { - this.lastBoundFramebuffer = this.framebuffer; - this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); - } - this.gl.bindFramebuffer = function (target, framebuffer) { - self.lastBoundFramebuffer = framebuffer - ? framebuffer - : self.framebuffer; - self.realBindFramebuffer.call( - gl, - target, - self.lastBoundFramebuffer - ); - }; - this.cullFace = gl.getParameter(gl.CULL_FACE); - this.depthTest = gl.getParameter(gl.DEPTH_TEST); - this.blend = gl.getParameter(gl.BLEND); - this.scissorTest = gl.getParameter(gl.SCISSOR_TEST); - this.stencilTest = gl.getParameter(gl.STENCIL_TEST); - gl.enable = function (pname) { - switch (pname) { - case gl.CULL_FACE: - self.cullFace = true; - break; - case gl.DEPTH_TEST: - self.depthTest = true; - break; - case gl.BLEND: - self.blend = true; - break; - case gl.SCISSOR_TEST: - self.scissorTest = true; - break; - case gl.STENCIL_TEST: - self.stencilTest = true; - break; - } - self.realEnable.call(gl, pname); - }; - gl.disable = function (pname) { - switch (pname) { - case gl.CULL_FACE: - self.cullFace = false; - break; - case gl.DEPTH_TEST: - self.depthTest = false; - break; - case gl.BLEND: - self.blend = false; - break; - case gl.SCISSOR_TEST: - self.scissorTest = false; - break; - case gl.STENCIL_TEST: - self.stencilTest = false; - break; - } - self.realDisable.call(gl, pname); - }; - this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK); - gl.colorMask = function (r, g, b, a) { - self.colorMask[0] = r; - self.colorMask[1] = g; - self.colorMask[2] = b; - self.colorMask[3] = a; - self.realColorMask.call(gl, r, g, b, a); - }; - this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); - gl.clearColor = function (r, g, b, a) { - self.clearColor[0] = r; - self.clearColor[1] = g; - self.clearColor[2] = b; - self.clearColor[3] = a; - self.realClearColor.call(gl, r, g, b, a); - }; - this.viewport = gl.getParameter(gl.VIEWPORT); - gl.viewport = function (x, y, w, h) { - self.viewport[0] = x; - self.viewport[1] = y; - self.viewport[2] = w; - self.viewport[3] = h; - self.realViewport.call(gl, x, y, w, h); - }; - this.isPatched = true; - safariCssSizeWorkaround(canvas); - }; - CardboardDistorter.prototype.unpatch = function () { - if (!this.isPatched) { - return; - } - var gl = this.gl; - var canvas = this.gl.canvas; - if (!isIOS()) { - Object.defineProperty(canvas, "width", this.realCanvasWidth); - Object.defineProperty(canvas, "height", this.realCanvasHeight); - } - canvas.width = this.bufferWidth; - canvas.height = this.bufferHeight; - gl.bindFramebuffer = this.realBindFramebuffer; - gl.enable = this.realEnable; - gl.disable = this.realDisable; - gl.colorMask = this.realColorMask; - gl.clearColor = this.realClearColor; - gl.viewport = this.realViewport; - if (this.lastBoundFramebuffer == this.framebuffer) { - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - } - this.isPatched = false; - setTimeout(function () { - safariCssSizeWorkaround(canvas); - }, 1); - }; - CardboardDistorter.prototype.setTextureBounds = function ( - leftBounds, - rightBounds - ) { - if (!leftBounds) { - leftBounds = [0, 0, 0.5, 1]; - } - if (!rightBounds) { - rightBounds = [0.5, 0, 0.5, 1]; - } - this.viewportOffsetScale[0] = leftBounds[0]; - this.viewportOffsetScale[1] = leftBounds[1]; - this.viewportOffsetScale[2] = leftBounds[2]; - this.viewportOffsetScale[3] = leftBounds[3]; - this.viewportOffsetScale[4] = rightBounds[0]; - this.viewportOffsetScale[5] = rightBounds[1]; - this.viewportOffsetScale[6] = rightBounds[2]; - this.viewportOffsetScale[7] = rightBounds[3]; - }; - CardboardDistorter.prototype.submitFrame = function () { - var gl = this.gl; - var self = this; - var glState = []; - if (!this.dirtySubmitFrameBindings) { - glState.push( - gl.CURRENT_PROGRAM, - gl.ARRAY_BUFFER_BINDING, - gl.ELEMENT_ARRAY_BUFFER_BINDING, - gl.TEXTURE_BINDING_2D, - gl.TEXTURE0 - ); - } - glPreserveState(gl, glState, function (gl) { - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); - if (self.cullFace) { - self.realDisable.call(gl, gl.CULL_FACE); - } - if (self.depthTest) { - self.realDisable.call(gl, gl.DEPTH_TEST); - } - if (self.blend) { - self.realDisable.call(gl, gl.BLEND); - } - if (self.scissorTest) { - self.realDisable.call(gl, gl.SCISSOR_TEST); - } - if (self.stencilTest) { - self.realDisable.call(gl, gl.STENCIL_TEST); - } - self.realColorMask.call(gl, true, true, true, true); - self.realViewport.call( - gl, - 0, - 0, - gl.drawingBufferWidth, - gl.drawingBufferHeight - ); - if (self.ctxAttribs.alpha || isIOS()) { - self.realClearColor.call(gl, 0, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); - } - gl.useProgram(self.program); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.enableVertexAttribArray(self.attribs.position); - gl.enableVertexAttribArray(self.attribs.texCoord); - gl.vertexAttribPointer( - self.attribs.position, - 2, - gl.FLOAT, - false, - 20, - 0 - ); - gl.vertexAttribPointer( - self.attribs.texCoord, - 3, - gl.FLOAT, - false, - 20, - 8 - ); - gl.activeTexture(gl.TEXTURE0); - gl.uniform1i(self.uniforms.diffuse, 0); - gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); - gl.uniform4fv( - self.uniforms.viewportOffsetScale, - self.viewportOffsetScale - ); - gl.drawElements( - gl.TRIANGLES, - self.indexCount, - gl.UNSIGNED_SHORT, - 0 - ); - if (self.cardboardUI) { - self.cardboardUI.renderNoState(); - } - self.realBindFramebuffer.call( - self.gl, - gl.FRAMEBUFFER, - self.framebuffer - ); - if (!self.ctxAttribs.preserveDrawingBuffer) { - self.realClearColor.call(gl, 0, 0, 0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - if (!self.dirtySubmitFrameBindings) { - self.realBindFramebuffer.call( - gl, - gl.FRAMEBUFFER, - self.lastBoundFramebuffer - ); - } - if (self.cullFace) { - self.realEnable.call(gl, gl.CULL_FACE); - } - if (self.depthTest) { - self.realEnable.call(gl, gl.DEPTH_TEST); - } - if (self.blend) { - self.realEnable.call(gl, gl.BLEND); - } - if (self.scissorTest) { - self.realEnable.call(gl, gl.SCISSOR_TEST); - } - if (self.stencilTest) { - self.realEnable.call(gl, gl.STENCIL_TEST); - } - self.realColorMask.apply(gl, self.colorMask); - self.realViewport.apply(gl, self.viewport); - if ( - self.ctxAttribs.alpha || - !self.ctxAttribs.preserveDrawingBuffer - ) { - self.realClearColor.apply(gl, self.clearColor); - } - }); - if (isIOS()) { - var canvas = gl.canvas; - if ( - canvas.width != self.bufferWidth || - canvas.height != self.bufferHeight - ) { - self.bufferWidth = canvas.width; - self.bufferHeight = canvas.height; - self.onResize(); - } - } - }; - CardboardDistorter.prototype.updateDeviceInfo = function (deviceInfo) { - var gl = this.gl; - var self = this; - var glState = [ - gl.ARRAY_BUFFER_BINDING, - gl.ELEMENT_ARRAY_BUFFER_BINDING, - ]; - glPreserveState(gl, glState, function (gl) { - var vertices = self.computeMeshVertices_( - self.meshWidth, - self.meshHeight, - deviceInfo - ); - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); - if (!self.indexCount) { - var indices = self.computeMeshIndices_( - self.meshWidth, - self.meshHeight - ); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); - self.indexCount = indices.length; - } - }); - }; - CardboardDistorter.prototype.computeMeshVertices_ = function ( - width, - height, - deviceInfo - ) { - var vertices = new Float32Array(2 * width * height * 5); - var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles(); - var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles(); - var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum); - var vidx = 0; - for (var e = 0; e < 2; e++) { - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++, vidx++) { - var u = i / (width - 1); - var v = j / (height - 1); - var s = u; - var t = v; - var x = lerp(lensFrustum[0], lensFrustum[2], u); - var y = lerp(lensFrustum[3], lensFrustum[1], v); - var d = Math.sqrt(x * x + y * y); - var r = deviceInfo.distortion.distortInverse(d); - var p = (x * r) / d; - var q = (y * r) / d; - u = - (p - noLensFrustum[0]) / - (noLensFrustum[2] - noLensFrustum[0]); - v = - (q - noLensFrustum[3]) / - (noLensFrustum[1] - noLensFrustum[3]); - u = (viewport.x + u * viewport.width - 0.5) * 2.0; - v = (viewport.y + v * viewport.height - 0.5) * 2.0; - vertices[vidx * 5 + 0] = u; - vertices[vidx * 5 + 1] = v; - vertices[vidx * 5 + 2] = s; - vertices[vidx * 5 + 3] = t; - vertices[vidx * 5 + 4] = e; - } - } - var w = lensFrustum[2] - lensFrustum[0]; - lensFrustum[0] = -(w + lensFrustum[0]); - lensFrustum[2] = w - lensFrustum[2]; - w = noLensFrustum[2] - noLensFrustum[0]; - noLensFrustum[0] = -(w + noLensFrustum[0]); - noLensFrustum[2] = w - noLensFrustum[2]; - viewport.x = 1 - (viewport.x + viewport.width); - } - return vertices; - }; - CardboardDistorter.prototype.computeMeshIndices_ = function ( - width, - height - ) { - var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6); - var halfwidth = width / 2; - var halfheight = height / 2; - var vidx = 0; - var iidx = 0; - for (var e = 0; e < 2; e++) { - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++, vidx++) { - if (i == 0 || j == 0) continue; - if (i <= halfwidth == j <= halfheight) { - indices[iidx++] = vidx; - indices[iidx++] = vidx - width - 1; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx - width - 1; - indices[iidx++] = vidx; - indices[iidx++] = vidx - 1; - } else { - indices[iidx++] = vidx - 1; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx - 1; - indices[iidx++] = vidx - width - 1; - } - } - } - } - return indices; - }; - CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function ( - proto, - attrName - ) { - var descriptor = Object.getOwnPropertyDescriptor(proto, attrName); - if (descriptor.get === undefined || descriptor.set === undefined) { - descriptor.configurable = true; - descriptor.enumerable = true; - descriptor.get = function () { - return this.getAttribute(attrName); - }; - descriptor.set = function (val) { - this.setAttribute(attrName, val); - }; - } - return descriptor; - }; - var uiVS = [ - "attribute vec2 position;", - "uniform mat4 projectionMat;", - "void main() {", - " gl_Position = projectionMat * vec4( position, -1.0, 1.0 );", - "}", - ].join("\n"); - var uiFS = [ - "precision mediump float;", - "uniform vec4 color;", - "void main() {", - " gl_FragColor = color;", - "}", - ].join("\n"); - var DEG2RAD = Math.PI / 180.0; - var kAnglePerGearSection = 60; - var kOuterRimEndAngle = 12; - var kInnerRimBeginAngle = 20; - var kOuterRadius = 1; - var kMiddleRadius = 0.75; - var kInnerRadius = 0.3125; - var kCenterLineThicknessDp = 4; - var kButtonWidthDp = 28; - var kTouchSlopFactor = 1.5; - function CardboardUI(gl) { - this.gl = gl; - this.attribs = { - position: 0, - }; - this.program = linkProgram(gl, uiVS, uiFS, this.attribs); - this.uniforms = getProgramUniforms(gl, this.program); - this.vertexBuffer = gl.createBuffer(); - this.gearOffset = 0; - this.gearVertexCount = 0; - this.arrowOffset = 0; - this.arrowVertexCount = 0; - this.projMat = new Float32Array(16); - this.listener = null; - this.onResize(); - } - CardboardUI.prototype.destroy = function () { - var gl = this.gl; - if (this.listener) { - gl.canvas.removeEventListener("click", this.listener, false); - } - gl.deleteProgram(this.program); - gl.deleteBuffer(this.vertexBuffer); - }; - CardboardUI.prototype.listen = function ( - optionsCallback, - backCallback - ) { - var canvas = this.gl.canvas; - this.listener = function (event) { - var midline = canvas.clientWidth / 2; - var buttonSize = kButtonWidthDp * kTouchSlopFactor; - if ( - event.clientX > midline - buttonSize && - event.clientX < midline + buttonSize && - event.clientY > canvas.clientHeight - buttonSize - ) { - optionsCallback(event); - } else if ( - event.clientX < buttonSize && - event.clientY < buttonSize - ) { - backCallback(event); - } - }; - canvas.addEventListener("click", this.listener, false); - }; - CardboardUI.prototype.onResize = function () { - var gl = this.gl; - var self = this; - var glState = [gl.ARRAY_BUFFER_BINDING]; - glPreserveState(gl, glState, function (gl) { - var vertices = []; - var midline = gl.drawingBufferWidth / 2; - var physicalPixels = - Math.max(screen.width, screen.height) * window.devicePixelRatio; - var scalingRatio = gl.drawingBufferWidth / physicalPixels; - var dps = scalingRatio * window.devicePixelRatio; - var lineWidth = (kCenterLineThicknessDp * dps) / 2; - var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps; - var buttonScale = (kButtonWidthDp * dps) / 2; - var buttonBorder = - (kButtonWidthDp * kTouchSlopFactor - kButtonWidthDp) * dps; - vertices.push(midline - lineWidth, buttonSize); - vertices.push(midline - lineWidth, gl.drawingBufferHeight); - vertices.push(midline + lineWidth, buttonSize); - vertices.push(midline + lineWidth, gl.drawingBufferHeight); - self.gearOffset = vertices.length / 2; - function addGearSegment(theta, r) { - var angle = (90 - theta) * DEG2RAD; - var x = Math.cos(angle); - var y = Math.sin(angle); - vertices.push( - kInnerRadius * x * buttonScale + midline, - kInnerRadius * y * buttonScale + buttonScale - ); - vertices.push( - r * x * buttonScale + midline, - r * y * buttonScale + buttonScale - ); - } - for (var i = 0; i <= 6; i++) { - var segmentTheta = i * kAnglePerGearSection; - addGearSegment(segmentTheta, kOuterRadius); - addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius); - addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius); - addGearSegment( - segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), - kMiddleRadius - ); - addGearSegment( - segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), - kOuterRadius - ); - } - self.gearVertexCount = vertices.length / 2 - self.gearOffset; - self.arrowOffset = vertices.length / 2; - function addArrowVertex(x, y) { - vertices.push( - buttonBorder + x, - gl.drawingBufferHeight - buttonBorder - y - ); - } - var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD); - addArrowVertex(0, buttonScale); - addArrowVertex(buttonScale, 0); - addArrowVertex(buttonScale + angledLineWidth, angledLineWidth); - addArrowVertex(angledLineWidth, buttonScale + angledLineWidth); - addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); - addArrowVertex(0, buttonScale); - addArrowVertex(buttonScale, buttonScale * 2); - addArrowVertex( - buttonScale + angledLineWidth, - buttonScale * 2 - angledLineWidth - ); - addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); - addArrowVertex(0, buttonScale); - addArrowVertex(angledLineWidth, buttonScale - lineWidth); - addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth); - addArrowVertex(angledLineWidth, buttonScale + lineWidth); - addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth); - self.arrowVertexCount = vertices.length / 2 - self.arrowOffset; - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.bufferData( - gl.ARRAY_BUFFER, - new Float32Array(vertices), - gl.STATIC_DRAW - ); - }); - }; - CardboardUI.prototype.render = function () { - var gl = this.gl; - var self = this; - var glState = [ - gl.CULL_FACE, - gl.DEPTH_TEST, - gl.BLEND, - gl.SCISSOR_TEST, - gl.STENCIL_TEST, - gl.COLOR_WRITEMASK, - gl.VIEWPORT, - gl.CURRENT_PROGRAM, - gl.ARRAY_BUFFER_BINDING, - ]; - glPreserveState(gl, glState, function (gl) { - gl.disable(gl.CULL_FACE); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.BLEND); - gl.disable(gl.SCISSOR_TEST); - gl.disable(gl.STENCIL_TEST); - gl.colorMask(true, true, true, true); - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - self.renderNoState(); - }); - }; - CardboardUI.prototype.renderNoState = function () { - var gl = this.gl; - gl.useProgram(this.program); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.enableVertexAttribArray(this.attribs.position); - gl.vertexAttribPointer( - this.attribs.position, - 2, - gl.FLOAT, - false, - 8, - 0 - ); - gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0); - orthoMatrix( - this.projMat, - 0, - gl.drawingBufferWidth, - 0, - gl.drawingBufferHeight, - 0.1, - 1024.0 - ); - gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat); - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); - gl.drawArrays( - gl.TRIANGLE_STRIP, - this.gearOffset, - this.gearVertexCount - ); - gl.drawArrays( - gl.TRIANGLE_STRIP, - this.arrowOffset, - this.arrowVertexCount - ); - }; - function Distortion(coefficients) { - this.coefficients = coefficients; - } - Distortion.prototype.distortInverse = function (radius) { - var r0 = 0; - var r1 = 1; - var dr0 = radius - this.distort(r0); - while (Math.abs(r1 - r0) > 0.0001) { - var dr1 = radius - this.distort(r1); - var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0)); - r0 = r1; - r1 = r2; - dr0 = dr1; - } - return r1; - }; - Distortion.prototype.distort = function (radius) { - var r2 = radius * radius; - var ret = 0; - for (var i = 0; i < this.coefficients.length; i++) { - ret = r2 * (ret + this.coefficients[i]); - } - return (ret + 1) * radius; - }; - var degToRad = Math.PI / 180; - var radToDeg = 180 / Math.PI; - var Vector3$$1 = function Vector3$$1(x, y, z) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - }; - Vector3$$1.prototype = { - constructor: Vector3$$1, - set: function set(x, y, z) { - this.x = x; - this.y = y; - this.z = z; - return this; - }, - copy: function copy(v) { - this.x = v.x; - this.y = v.y; - this.z = v.z; - return this; - }, - length: function length() { - return Math.sqrt( - this.x * this.x + this.y * this.y + this.z * this.z - ); - }, - normalize: function normalize() { - var scalar = this.length(); - if (scalar !== 0) { - var invScalar = 1 / scalar; - this.multiplyScalar(invScalar); - } else { - this.x = 0; - this.y = 0; - this.z = 0; - } - return this; - }, - multiplyScalar: function multiplyScalar(scalar) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - }, - applyQuaternion: function applyQuaternion(q) { - var x = this.x; - var y = this.y; - var z = this.z; - var qx = q.x; - var qy = q.y; - var qz = q.z; - var qw = q.w; - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - return this; - }, - dot: function dot(v) { - return this.x * v.x + this.y * v.y + this.z * v.z; - }, - crossVectors: function crossVectors(a, b) { - var ax = a.x, - ay = a.y, - az = a.z; - var bx = b.x, - by = b.y, - bz = b.z; - this.x = ay * bz - az * by; - this.y = az * bx - ax * bz; - this.z = ax * by - ay * bx; - return this; - }, - }; - var Quaternion$$1 = function Quaternion$$1(x, y, z, w) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = w !== undefined ? w : 1; - }; - Quaternion$$1.prototype = { - constructor: Quaternion$$1, - set: function set(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - return this; - }, - copy: function copy(quaternion) { - this.x = quaternion.x; - this.y = quaternion.y; - this.z = quaternion.z; - this.w = quaternion.w; - return this; - }, - setFromEulerXYZ: function setFromEulerXYZ(x, y, z) { - var c1 = Math.cos(x / 2); - var c2 = Math.cos(y / 2); - var c3 = Math.cos(z / 2); - var s1 = Math.sin(x / 2); - var s2 = Math.sin(y / 2); - var s3 = Math.sin(z / 2); - this.x = s1 * c2 * c3 + c1 * s2 * s3; - this.y = c1 * s2 * c3 - s1 * c2 * s3; - this.z = c1 * c2 * s3 + s1 * s2 * c3; - this.w = c1 * c2 * c3 - s1 * s2 * s3; - return this; - }, - setFromEulerYXZ: function setFromEulerYXZ(x, y, z) { - var c1 = Math.cos(x / 2); - var c2 = Math.cos(y / 2); - var c3 = Math.cos(z / 2); - var s1 = Math.sin(x / 2); - var s2 = Math.sin(y / 2); - var s3 = Math.sin(z / 2); - this.x = s1 * c2 * c3 + c1 * s2 * s3; - this.y = c1 * s2 * c3 - s1 * c2 * s3; - this.z = c1 * c2 * s3 - s1 * s2 * c3; - this.w = c1 * c2 * c3 + s1 * s2 * s3; - return this; - }, - setFromAxisAngle: function setFromAxisAngle(axis, angle) { - var halfAngle = angle / 2, - s = Math.sin(halfAngle); - this.x = axis.x * s; - this.y = axis.y * s; - this.z = axis.z * s; - this.w = Math.cos(halfAngle); - return this; - }, - multiply: function multiply(q) { - return this.multiplyQuaternions(this, q); - }, - multiplyQuaternions: function multiplyQuaternions(a, b) { - var qax = a.x, - qay = a.y, - qaz = a.z, - qaw = a.w; - var qbx = b.x, - qby = b.y, - qbz = b.z, - qbw = b.w; - this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - return this; - }, - inverse: function inverse() { - this.x *= -1; - this.y *= -1; - this.z *= -1; - this.normalize(); - return this; - }, - normalize: function normalize() { - var l = Math.sqrt( - this.x * this.x + - this.y * this.y + - this.z * this.z + - this.w * this.w - ); - if (l === 0) { - this.x = 0; - this.y = 0; - this.z = 0; - this.w = 1; - } else { - l = 1 / l; - this.x = this.x * l; - this.y = this.y * l; - this.z = this.z * l; - this.w = this.w * l; - } - return this; - }, - slerp: function slerp(qb, t) { - if (t === 0) return this; - if (t === 1) return this.copy(qb); - var x = this.x, - y = this.y, - z = this.z, - w = this.w; - var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z; - if (cosHalfTheta < 0) { - this.w = -qb.w; - this.x = -qb.x; - this.y = -qb.y; - this.z = -qb.z; - cosHalfTheta = -cosHalfTheta; - } else { - this.copy(qb); - } - if (cosHalfTheta >= 1.0) { - this.w = w; - this.x = x; - this.y = y; - this.z = z; - return this; - } - var halfTheta = Math.acos(cosHalfTheta); - var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); - if (Math.abs(sinHalfTheta) < 0.001) { - this.w = 0.5 * (w + this.w); - this.x = 0.5 * (x + this.x); - this.y = 0.5 * (y + this.y); - this.z = 0.5 * (z + this.z); - return this; - } - var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, - ratioB = Math.sin(t * halfTheta) / sinHalfTheta; - this.w = w * ratioA + this.w * ratioB; - this.x = x * ratioA + this.x * ratioB; - this.y = y * ratioA + this.y * ratioB; - this.z = z * ratioA + this.z * ratioB; - return this; - }, - setFromUnitVectors: (function () { - var v1, r; - var EPS = 0.000001; - return function (vFrom, vTo) { - if (v1 === undefined) v1 = new Vector3$$1(); - r = vFrom.dot(vTo) + 1; - if (r < EPS) { - r = 0; - if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { - v1.set(-vFrom.y, vFrom.x, 0); - } else { - v1.set(0, -vFrom.z, vFrom.y); - } - } else { - v1.crossVectors(vFrom, vTo); - } - this.x = v1.x; - this.y = v1.y; - this.z = v1.z; - this.w = r; - this.normalize(); - return this; - }; - })(), - }; - function Device(params) { - this.width = params.width || getScreenWidth(); - this.height = params.height || getScreenHeight(); - this.widthMeters = params.widthMeters; - this.heightMeters = params.heightMeters; - this.bevelMeters = params.bevelMeters; - } - var DEFAULT_ANDROID = new Device({ - widthMeters: 0.11, - heightMeters: 0.062, - bevelMeters: 0.004, - }); - var DEFAULT_IOS = new Device({ - widthMeters: 0.1038, - heightMeters: 0.0584, - bevelMeters: 0.004, - }); - var Viewers = { - CardboardV1: new CardboardViewer({ - id: "CardboardV1", - label: "Cardboard I/O 2014", - fov: 40, - interLensDistance: 0.06, - baselineLensDistance: 0.035, - screenLensDistance: 0.042, - distortionCoefficients: [0.441, 0.156], - inverseCoefficients: [ - -0.4410035, 0.42756155, -0.4804439, 0.5460139, -0.58821183, - 0.5733938, -0.48303202, 0.33299083, -0.17573841, 0.0651772, - -0.01488963, 0.001559834, - ], - }), - CardboardV2: new CardboardViewer({ - id: "CardboardV2", - label: "Cardboard I/O 2015", - fov: 60, - interLensDistance: 0.064, - baselineLensDistance: 0.035, - screenLensDistance: 0.039, - distortionCoefficients: [0.34, 0.55], - inverseCoefficients: [ - -0.33836704, -0.18162185, 0.862655, -1.2462051, 1.0560602, - -0.58208317, 0.21609078, -0.05444823, 0.009177956, -9.904169e-4, - 6.183535e-5, -1.6981803e-6, - ], - }), - }; - function DeviceInfo(deviceParams) { - this.viewer = Viewers.CardboardV2; - this.updateDeviceParams(deviceParams); - this.distortion = new Distortion(this.viewer.distortionCoefficients); - } - DeviceInfo.prototype.updateDeviceParams = function (deviceParams) { - this.device = this.determineDevice_(deviceParams) || this.device; - }; - DeviceInfo.prototype.getDevice = function () { - return this.device; - }; - DeviceInfo.prototype.setViewer = function (viewer) { - this.viewer = viewer; - this.distortion = new Distortion(this.viewer.distortionCoefficients); - }; - DeviceInfo.prototype.determineDevice_ = function (deviceParams) { - if (!deviceParams) { - if (isIOS()) { - console.warn("Using fallback iOS device measurements."); - return DEFAULT_IOS; - } else { - console.warn("Using fallback Android device measurements."); - return DEFAULT_ANDROID; - } - } - var METERS_PER_INCH = 0.0254; - var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi; - var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi; - var width = getScreenWidth(); - var height = getScreenHeight(); - return new Device({ - widthMeters: metersPerPixelX * width, - heightMeters: metersPerPixelY * height, - bevelMeters: deviceParams.bevelMm * 0.001, - }); - }; - DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var eyeToScreenDistance = viewer.screenLensDistance; - var outerDist = (device.widthMeters - viewer.interLensDistance) / 2; - var innerDist = viewer.interLensDistance / 2; - var bottomDist = viewer.baselineLensDistance - device.bevelMeters; - var topDist = device.heightMeters - bottomDist; - var outerAngle = - radToDeg * - Math.atan(distortion.distort(outerDist / eyeToScreenDistance)); - var innerAngle = - radToDeg * - Math.atan(distortion.distort(innerDist / eyeToScreenDistance)); - var bottomAngle = - radToDeg * - Math.atan(distortion.distort(bottomDist / eyeToScreenDistance)); - var topAngle = - radToDeg * - Math.atan(distortion.distort(topDist / eyeToScreenDistance)); - return { - leftDegrees: Math.min(outerAngle, viewer.fov), - rightDegrees: Math.min(innerAngle, viewer.fov), - downDegrees: Math.min(bottomAngle, viewer.fov), - upDegrees: Math.min(topAngle, viewer.fov), - }; - }; - DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var fovLeft = Math.tan(-degToRad * viewer.fov); - var fovTop = Math.tan(degToRad * viewer.fov); - var fovRight = Math.tan(degToRad * viewer.fov); - var fovBottom = Math.tan(-degToRad * viewer.fov); - var halfWidth = device.widthMeters / 4; - var halfHeight = device.heightMeters / 2; - var verticalLensOffset = - viewer.baselineLensDistance - device.bevelMeters - halfHeight; - var centerX = viewer.interLensDistance / 2 - halfWidth; - var centerY = -verticalLensOffset; - var centerZ = viewer.screenLensDistance; - var screenLeft = distortion.distort((centerX - halfWidth) / centerZ); - var screenTop = distortion.distort((centerY + halfHeight) / centerZ); - var screenRight = distortion.distort((centerX + halfWidth) / centerZ); - var screenBottom = distortion.distort( - (centerY - halfHeight) / centerZ - ); - var result = new Float32Array(4); - result[0] = Math.max(fovLeft, screenLeft); - result[1] = Math.min(fovTop, screenTop); - result[2] = Math.min(fovRight, screenRight); - result[3] = Math.max(fovBottom, screenBottom); - return result; - }; - DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var result = new Float32Array(4); - var fovLeft = distortion.distortInverse( - Math.tan(-degToRad * viewer.fov) - ); - var fovTop = distortion.distortInverse( - Math.tan(degToRad * viewer.fov) - ); - var fovRight = distortion.distortInverse( - Math.tan(degToRad * viewer.fov) - ); - var fovBottom = distortion.distortInverse( - Math.tan(-degToRad * viewer.fov) - ); - var halfWidth = device.widthMeters / 4; - var halfHeight = device.heightMeters / 2; - var verticalLensOffset = - viewer.baselineLensDistance - device.bevelMeters - halfHeight; - var centerX = viewer.interLensDistance / 2 - halfWidth; - var centerY = -verticalLensOffset; - var centerZ = viewer.screenLensDistance; - var screenLeft = (centerX - halfWidth) / centerZ; - var screenTop = (centerY + halfHeight) / centerZ; - var screenRight = (centerX + halfWidth) / centerZ; - var screenBottom = (centerY - halfHeight) / centerZ; - result[0] = Math.max(fovLeft, screenLeft); - result[1] = Math.min(fovTop, screenTop); - result[2] = Math.min(fovRight, screenRight); - result[3] = Math.max(fovBottom, screenBottom); - return result; - }; - DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function ( - undistortedFrustum - ) { - var viewer = this.viewer; - var device = this.device; - var dist = viewer.screenLensDistance; - var eyeX = (device.widthMeters - viewer.interLensDistance) / 2; - var eyeY = viewer.baselineLensDistance - device.bevelMeters; - var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters; - var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters; - var right = - (undistortedFrustum[2] * dist + eyeX) / device.widthMeters; - var bottom = - (undistortedFrustum[3] * dist + eyeY) / device.heightMeters; - return { - x: left, - y: bottom, - width: right - left, - height: top - bottom, - }; - }; - DeviceInfo.prototype.getFieldOfViewLeftEye = function ( - opt_isUndistorted - ) { - return opt_isUndistorted - ? this.getUndistortedFieldOfViewLeftEye() - : this.getDistortedFieldOfViewLeftEye(); - }; - DeviceInfo.prototype.getFieldOfViewRightEye = function ( - opt_isUndistorted - ) { - var fov = this.getFieldOfViewLeftEye(opt_isUndistorted); - return { - leftDegrees: fov.rightDegrees, - rightDegrees: fov.leftDegrees, - upDegrees: fov.upDegrees, - downDegrees: fov.downDegrees, - }; - }; - DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function () { - var p = this.getUndistortedParams_(); - return { - leftDegrees: radToDeg * Math.atan(p.outerDist), - rightDegrees: radToDeg * Math.atan(p.innerDist), - downDegrees: radToDeg * Math.atan(p.bottomDist), - upDegrees: radToDeg * Math.atan(p.topDist), - }; - }; - DeviceInfo.prototype.getUndistortedViewportLeftEye = function () { - var p = this.getUndistortedParams_(); - var viewer = this.viewer; - var device = this.device; - var eyeToScreenDistance = viewer.screenLensDistance; - var screenWidth = device.widthMeters / eyeToScreenDistance; - var screenHeight = device.heightMeters / eyeToScreenDistance; - var xPxPerTanAngle = device.width / screenWidth; - var yPxPerTanAngle = device.height / screenHeight; - var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle); - var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle); - return { - x: x, - y: y, - width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x, - height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y, - }; - }; - DeviceInfo.prototype.getUndistortedParams_ = function () { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - var eyeToScreenDistance = viewer.screenLensDistance; - var halfLensDistance = - viewer.interLensDistance / 2 / eyeToScreenDistance; - var screenWidth = device.widthMeters / eyeToScreenDistance; - var screenHeight = device.heightMeters / eyeToScreenDistance; - var eyePosX = screenWidth / 2 - halfLensDistance; - var eyePosY = - (viewer.baselineLensDistance - device.bevelMeters) / - eyeToScreenDistance; - var maxFov = viewer.fov; - var viewerMax = distortion.distortInverse( - Math.tan(degToRad * maxFov) - ); - var outerDist = Math.min(eyePosX, viewerMax); - var innerDist = Math.min(halfLensDistance, viewerMax); - var bottomDist = Math.min(eyePosY, viewerMax); - var topDist = Math.min(screenHeight - eyePosY, viewerMax); - return { - outerDist: outerDist, - innerDist: innerDist, - topDist: topDist, - bottomDist: bottomDist, - eyePosX: eyePosX, - eyePosY: eyePosY, - }; - }; - function CardboardViewer(params) { - this.id = params.id; - this.label = params.label; - this.fov = params.fov; - this.interLensDistance = params.interLensDistance; - this.baselineLensDistance = params.baselineLensDistance; - this.screenLensDistance = params.screenLensDistance; - this.distortionCoefficients = params.distortionCoefficients; - this.inverseCoefficients = params.inverseCoefficients; - } - DeviceInfo.Viewers = Viewers; - var format = 1; - var last_updated = "2018-02-20T22:55:10Z"; - var devices = [ - { - type: "android", - rules: [{ mdmh: "asus/*/Nexus 7/*" }, { ua: "Nexus 7" }], - dpi: [320.8, 323], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "asus/*/ASUS_Z00AD/*" }, { ua: "ASUS_Z00AD" }], - dpi: [403, 404.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Google/*/Pixel XL/*" }, { ua: "Pixel XL" }], - dpi: [537.9, 533], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Google/*/Pixel/*" }, { ua: "Pixel" }], - dpi: [432.6, 436.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC6435LVW/*" }, { ua: "HTC6435LVW" }], - dpi: [449.7, 443.3], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One XL/*" }, { ua: "HTC One XL" }], - dpi: [315.3, 314.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "htc/*/Nexus 9/*" }, { ua: "Nexus 9" }], - dpi: 289, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One M9/*" }, { ua: "HTC One M9" }], - dpi: [442.5, 443.3], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One_M8/*" }, { ua: "HTC One_M8" }], - dpi: [449.7, 447.4], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "HTC/*/HTC One/*" }, { ua: "HTC One" }], - dpi: 472.8, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Huawei/*/Nexus 6P/*" }, { ua: "Nexus 6P" }], - dpi: [515.1, 518], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "LENOVO/*/Lenovo PB2-690Y/*" }, - { ua: "Lenovo PB2-690Y" }, - ], - dpi: [457.2, 454.713], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/Nexus 5X/*" }, { ua: "Nexus 5X" }], - dpi: [422, 419.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LGMS345/*" }, { ua: "LGMS345" }], - dpi: [221.7, 219.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LG-D800/*" }, { ua: "LG-D800" }], - dpi: [422, 424.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LG-D850/*" }, { ua: "LG-D850" }], - dpi: [537.9, 541.9], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/VS985 4G/*" }, { ua: "VS985 4G" }], - dpi: [537.9, 535.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/Nexus 5/*" }, { ua: "Nexus 5 B" }], - dpi: [442.4, 444.8], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/Nexus 4/*" }, { ua: "Nexus 4" }], - dpi: [319.8, 318.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LG-P769/*" }, { ua: "LG-P769" }], - dpi: [240.6, 247.5], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LGMS323/*" }, { ua: "LGMS323" }], - dpi: [206.6, 204.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "LGE/*/LGLS996/*" }, { ua: "LGLS996" }], - dpi: [403.4, 401.5], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Micromax/*/4560MMX/*" }, { ua: "4560MMX" }], - dpi: [240, 219.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Micromax/*/A250/*" }, { ua: "Micromax A250" }], - dpi: [480, 446.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "Micromax/*/Micromax AQ4501/*" }, - { ua: "Micromax AQ4501" }, - ], - dpi: 240, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/G5/*" }, { ua: "Moto G (5) Plus" }], - dpi: [403.4, 403], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/DROID RAZR/*" }, { ua: "DROID RAZR" }], - dpi: [368.1, 256.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT830C/*" }, { ua: "XT830C" }], - dpi: [254, 255.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1021/*" }, { ua: "XT1021" }], - dpi: [254, 256.7], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1023/*" }, { ua: "XT1023" }], - dpi: [254, 256.7], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1028/*" }, { ua: "XT1028" }], - dpi: [326.6, 327.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1034/*" }, { ua: "XT1034" }], - dpi: [326.6, 328.4], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1053/*" }, { ua: "XT1053" }], - dpi: [315.3, 316.1], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1562/*" }, { ua: "XT1562" }], - dpi: [403.4, 402.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/Nexus 6/*" }, { ua: "Nexus 6 B" }], - dpi: [494.3, 489.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1063/*" }, { ua: "XT1063" }], - dpi: [295, 296.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1064/*" }, { ua: "XT1064" }], - dpi: [295, 295.6], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1092/*" }, { ua: "XT1092" }], - dpi: [422, 424.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/XT1095/*" }, { ua: "XT1095" }], - dpi: [422, 423.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "motorola/*/G4/*" }, { ua: "Moto G (4)" }], - dpi: 401, - bw: 4, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/A0001/*" }, { ua: "A0001" }], - dpi: [403.4, 401], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/ONE E1005/*" }, { ua: "ONE E1005" }], - dpi: [442.4, 441.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/ONE A2005/*" }, { ua: "ONE A2005" }], - dpi: [391.9, 405.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "OnePlus/*/ONEPLUS A5000/*" }, - { ua: "ONEPLUS A5000 " }, - ], - dpi: [403.411, 399.737], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OnePlus/*/ONE A5010/*" }, { ua: "ONEPLUS A5010" }], - dpi: [403, 400], - bw: 2, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "OPPO/*/X909/*" }, { ua: "X909" }], - dpi: [442.4, 444.1], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9082/*" }, { ua: "GT-I9082" }], - dpi: [184.7, 185.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G360P/*" }, { ua: "SM-G360P" }], - dpi: [196.7, 205.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/Nexus S/*" }, { ua: "Nexus S" }], - dpi: [234.5, 229.8], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9300/*" }, { ua: "GT-I9300" }], - dpi: [304.8, 303.9], - bw: 5, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-T230NU/*" }, { ua: "SM-T230NU" }], - dpi: 216, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SGH-T399/*" }, { ua: "SGH-T399" }], - dpi: [217.7, 231.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SGH-M919/*" }, { ua: "SGH-M919" }], - dpi: [440.8, 437.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N9005/*" }, { ua: "SM-N9005" }], - dpi: [386.4, 387], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [ - { mdmh: "samsung/*/SAMSUNG-SM-N900A/*" }, - { ua: "SAMSUNG-SM-N900A" }, - ], - dpi: [386.4, 387.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9500/*" }, { ua: "GT-I9500" }], - dpi: [442.5, 443.3], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9505/*" }, { ua: "GT-I9505" }], - dpi: 439.4, - bw: 4, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G900F/*" }, { ua: "SM-G900F" }], - dpi: [415.6, 431.6], - bw: 5, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G900M/*" }, { ua: "SM-G900M" }], - dpi: [415.6, 431.6], - bw: 5, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G800F/*" }, { ua: "SM-G800F" }], - dpi: 326.8, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G906S/*" }, { ua: "SM-G906S" }], - dpi: [562.7, 572.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9300/*" }, { ua: "GT-I9300" }], - dpi: [306.7, 304.8], - bw: 5, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-T535/*" }, { ua: "SM-T535" }], - dpi: [142.6, 136.4], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N920C/*" }, { ua: "SM-N920C" }], - dpi: [515.1, 518.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N920P/*" }, { ua: "SM-N920P" }], - dpi: [386.3655, 390.144], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N920W8/*" }, { ua: "SM-N920W8" }], - dpi: [515.1, 518.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9300I/*" }, { ua: "GT-I9300I" }], - dpi: [304.8, 305.8], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-I9195/*" }, { ua: "GT-I9195" }], - dpi: [249.4, 256.7], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SPH-L520/*" }, { ua: "SPH-L520" }], - dpi: [249.4, 255.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "samsung/*/SAMSUNG-SGH-I717/*" }, - { ua: "SAMSUNG-SGH-I717" }, - ], - dpi: 285.8, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SPH-D710/*" }, { ua: "SPH-D710" }], - dpi: [217.7, 204.2], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/GT-N7100/*" }, { ua: "GT-N7100" }], - dpi: 265.1, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SCH-I605/*" }, { ua: "SCH-I605" }], - dpi: 265.1, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [ - { mdmh: "samsung/*/Galaxy Nexus/*" }, - { ua: "Galaxy Nexus" }, - ], - dpi: [315.3, 314.2], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N910H/*" }, { ua: "SM-N910H" }], - dpi: [515.1, 518], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-N910C/*" }, { ua: "SM-N910C" }], - dpi: [515.2, 520.2], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G130M/*" }, { ua: "SM-G130M" }], - dpi: [165.9, 164.8], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G928I/*" }, { ua: "SM-G928I" }], - dpi: [515.1, 518.4], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G920F/*" }, { ua: "SM-G920F" }], - dpi: 580.6, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G920P/*" }, { ua: "SM-G920P" }], - dpi: [522.5, 577], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G925F/*" }, { ua: "SM-G925F" }], - dpi: 580.6, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G925V/*" }, { ua: "SM-G925V" }], - dpi: [522.5, 576.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G930F/*" }, { ua: "SM-G930F" }], - dpi: 576.6, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G935F/*" }, { ua: "SM-G935F" }], - dpi: 533, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G950F/*" }, { ua: "SM-G950F" }], - dpi: [562.707, 565.293], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "samsung/*/SM-G955U/*" }, { ua: "SM-G955U" }], - dpi: [522.514, 525.762], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/C6903/*" }, { ua: "C6903" }], - dpi: [442.5, 443.3], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/D6653/*" }, { ua: "D6653" }], - dpi: [428.6, 427.6], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/E6653/*" }, { ua: "E6653" }], - dpi: [428.6, 425.7], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/E6853/*" }, { ua: "E6853" }], - dpi: [403.4, 401.9], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Sony/*/SGP321/*" }, { ua: "SGP321" }], - dpi: [224.7, 224.1], - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [ - { mdmh: "TCT/*/ALCATEL ONE TOUCH Fierce/*" }, - { ua: "ALCATEL ONE TOUCH Fierce" }, - ], - dpi: [240, 247.5], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "THL/*/thl 5000/*" }, { ua: "thl 5000" }], - dpi: [480, 443.3], - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "Fly/*/IQ4412/*" }, { ua: "IQ4412" }], - dpi: 307.9, - bw: 3, - ac: 1000, - }, - { - type: "android", - rules: [{ mdmh: "ZTE/*/ZTE Blade L2/*" }, { ua: "ZTE Blade L2" }], - dpi: 240, - bw: 3, - ac: 500, - }, - { - type: "android", - rules: [{ mdmh: "BENEVE/*/VR518/*" }, { ua: "VR518" }], - dpi: 480, - bw: 3, - ac: 500, - }, - { - type: "ios", - rules: [{ res: [640, 960] }], - dpi: [325.1, 328.4], - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [640, 1136] }], - dpi: [317.1, 320.2], - bw: 3, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [750, 1334] }], - dpi: 326.4, - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [1242, 2208] }], - dpi: [453.6, 458.4], - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [1125, 2001] }], - dpi: [410.9, 415.4], - bw: 4, - ac: 1000, - }, - { - type: "ios", - rules: [{ res: [1125, 2436] }], - dpi: 458, - bw: 4, - ac: 1000, - }, - ]; - var DPDB_CACHE = { - format: format, - last_updated: last_updated, - devices: devices, - }; - function Dpdb(url, onDeviceParamsUpdated) { - this.dpdb = DPDB_CACHE; - this.recalculateDeviceParams_(); - if (url) { - this.onDeviceParamsUpdated = onDeviceParamsUpdated; - var xhr = new XMLHttpRequest(); - var obj = this; - xhr.open("GET", url, true); - xhr.addEventListener("load", function () { - obj.loading = false; - if (xhr.status >= 200 && xhr.status <= 299) { - obj.dpdb = JSON.parse(xhr.response); - obj.recalculateDeviceParams_(); - } else { - console.error("Error loading online DPDB!"); - } - }); - xhr.send(); - } - } - Dpdb.prototype.getDeviceParams = function () { - return this.deviceParams; - }; - Dpdb.prototype.recalculateDeviceParams_ = function () { - var newDeviceParams = this.calcDeviceParams_(); - if (newDeviceParams) { - this.deviceParams = newDeviceParams; - if (this.onDeviceParamsUpdated) { - this.onDeviceParamsUpdated(this.deviceParams); - } - } else { - console.error("Failed to recalculate device parameters."); - } - }; - Dpdb.prototype.calcDeviceParams_ = function () { - var db = this.dpdb; - if (!db) { - console.error("DPDB not available."); - return null; - } - if (db.format != 1) { - console.error("DPDB has unexpected format version."); - return null; - } - if (!db.devices || !db.devices.length) { - console.error("DPDB does not have a devices section."); - return null; - } - var userAgent = - navigator.userAgent || navigator.vendor || window.opera; - var width = getScreenWidth(); - var height = getScreenHeight(); - if (!db.devices) { - console.error("DPDB has no devices section."); - return null; - } - for (var i = 0; i < db.devices.length; i++) { - var device = db.devices[i]; - if (!device.rules) { - console.warn("Device[" + i + "] has no rules section."); - continue; - } - if (device.type != "ios" && device.type != "android") { - console.warn("Device[" + i + "] has invalid type."); - continue; - } - if (isIOS() != (device.type == "ios")) continue; - var matched = false; - for (var j = 0; j < device.rules.length; j++) { - var rule = device.rules[j]; - if (this.matchRule_(rule, userAgent, width, height)) { - matched = true; - break; - } - } - if (!matched) continue; - var xdpi = device.dpi[0] || device.dpi; - var ydpi = device.dpi[1] || device.dpi; - return new DeviceParams({ - xdpi: xdpi, - ydpi: ydpi, - bevelMm: device.bw, - }); - } - console.warn("No DPDB device match."); - return null; - }; - Dpdb.prototype.matchRule_ = function ( - rule, - ua, - screenWidth, - screenHeight - ) { - if (!rule.ua && !rule.res) return false; - if (rule.ua && ua.indexOf(rule.ua) < 0) return false; - if (rule.res) { - if (!rule.res[0] || !rule.res[1]) return false; - var resX = rule.res[0]; - var resY = rule.res[1]; - if ( - Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || - Math.max(screenWidth, screenHeight) != Math.max(resX, resY) - ) { - return false; - } - } - return true; - }; - function DeviceParams(params) { - this.xdpi = params.xdpi; - this.ydpi = params.ydpi; - this.bevelMm = params.bevelMm; - } - function SensorSample(sample, timestampS) { - this.set(sample, timestampS); - } - SensorSample.prototype.set = function (sample, timestampS) { - this.sample = sample; - this.timestampS = timestampS; - }; - SensorSample.prototype.copy = function (sensorSample) { - this.set(sensorSample.sample, sensorSample.timestampS); - }; - function ComplementaryFilter(kFilter, isDebug) { - this.kFilter = kFilter; - this.isDebug = isDebug; - this.currentAccelMeasurement = new SensorSample(); - this.currentGyroMeasurement = new SensorSample(); - this.previousGyroMeasurement = new SensorSample(); - if (isIOS()) { - this.filterQ = new Quaternion$$1(-1, 0, 0, 1); - } else { - this.filterQ = new Quaternion$$1(1, 0, 0, 1); - } - this.previousFilterQ = new Quaternion$$1(); - this.previousFilterQ.copy(this.filterQ); - this.accelQ = new Quaternion$$1(); - this.isOrientationInitialized = false; - this.estimatedGravity = new Vector3$$1(); - this.measuredGravity = new Vector3$$1(); - this.gyroIntegralQ = new Quaternion$$1(); - } - ComplementaryFilter.prototype.addAccelMeasurement = function ( - vector, - timestampS - ) { - this.currentAccelMeasurement.set(vector, timestampS); - }; - ComplementaryFilter.prototype.addGyroMeasurement = function ( - vector, - timestampS - ) { - this.currentGyroMeasurement.set(vector, timestampS); - var deltaT = timestampS - this.previousGyroMeasurement.timestampS; - if (isTimestampDeltaValid(deltaT)) { - this.run_(); - } - this.previousGyroMeasurement.copy(this.currentGyroMeasurement); - }; - ComplementaryFilter.prototype.run_ = function () { - if (!this.isOrientationInitialized) { - this.accelQ = this.accelToQuaternion_( - this.currentAccelMeasurement.sample - ); - this.previousFilterQ.copy(this.accelQ); - this.isOrientationInitialized = true; - return; - } - var deltaT = - this.currentGyroMeasurement.timestampS - - this.previousGyroMeasurement.timestampS; - var gyroDeltaQ = this.gyroToQuaternionDelta_( - this.currentGyroMeasurement.sample, - deltaT - ); - this.gyroIntegralQ.multiply(gyroDeltaQ); - this.filterQ.copy(this.previousFilterQ); - this.filterQ.multiply(gyroDeltaQ); - var invFilterQ = new Quaternion$$1(); - invFilterQ.copy(this.filterQ); - invFilterQ.inverse(); - this.estimatedGravity.set(0, 0, -1); - this.estimatedGravity.applyQuaternion(invFilterQ); - this.estimatedGravity.normalize(); - this.measuredGravity.copy(this.currentAccelMeasurement.sample); - this.measuredGravity.normalize(); - var deltaQ = new Quaternion$$1(); - deltaQ.setFromUnitVectors( - this.estimatedGravity, - this.measuredGravity - ); - deltaQ.inverse(); - if (this.isDebug) { - console.log( - "Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)", - radToDeg * getQuaternionAngle(deltaQ), - this.estimatedGravity.x.toFixed(1), - this.estimatedGravity.y.toFixed(1), - this.estimatedGravity.z.toFixed(1), - this.measuredGravity.x.toFixed(1), - this.measuredGravity.y.toFixed(1), - this.measuredGravity.z.toFixed(1) - ); - } - var targetQ = new Quaternion$$1(); - targetQ.copy(this.filterQ); - targetQ.multiply(deltaQ); - this.filterQ.slerp(targetQ, 1 - this.kFilter); - this.previousFilterQ.copy(this.filterQ); - }; - ComplementaryFilter.prototype.getOrientation = function () { - return this.filterQ; - }; - ComplementaryFilter.prototype.accelToQuaternion_ = function (accel) { - var normAccel = new Vector3$$1(); - normAccel.copy(accel); - normAccel.normalize(); - var quat = new Quaternion$$1(); - quat.setFromUnitVectors(new Vector3$$1(0, 0, -1), normAccel); - quat.inverse(); - return quat; - }; - ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function ( - gyro, - dt - ) { - var quat = new Quaternion$$1(); - var axis = new Vector3$$1(); - axis.copy(gyro); - axis.normalize(); - quat.setFromAxisAngle(axis, gyro.length() * dt); - return quat; - }; - function PosePredictor(predictionTimeS, isDebug) { - this.predictionTimeS = predictionTimeS; - this.isDebug = isDebug; - this.previousQ = new Quaternion$$1(); - this.previousTimestampS = null; - this.deltaQ = new Quaternion$$1(); - this.outQ = new Quaternion$$1(); - } - PosePredictor.prototype.getPrediction = function ( - currentQ, - gyro, - timestampS - ) { - if (!this.previousTimestampS) { - this.previousQ.copy(currentQ); - this.previousTimestampS = timestampS; - return currentQ; - } - var axis = new Vector3$$1(); - axis.copy(gyro); - axis.normalize(); - var angularSpeed = gyro.length(); - if (angularSpeed < degToRad * 20) { - if (this.isDebug) { - console.log( - "Moving slowly, at %s deg/s: no prediction", - (radToDeg * angularSpeed).toFixed(1) - ); - } - this.outQ.copy(currentQ); - this.previousQ.copy(currentQ); - return this.outQ; - } - var predictAngle = angularSpeed * this.predictionTimeS; - this.deltaQ.setFromAxisAngle(axis, predictAngle); - this.outQ.copy(this.previousQ); - this.outQ.multiply(this.deltaQ); - this.previousQ.copy(currentQ); - this.previousTimestampS = timestampS; - return this.outQ; - }; - function FusionPoseSensor(kFilter, predictionTime, yawOnly, isDebug) { - this.yawOnly = yawOnly; - this.accelerometer = new Vector3$$1(); - this.gyroscope = new Vector3$$1(); - this.filter = new ComplementaryFilter(kFilter, isDebug); - this.posePredictor = new PosePredictor(predictionTime, isDebug); - this.isFirefoxAndroid = isFirefoxAndroid(); - this.isIOS = isIOS(); - var chromeVersion = getChromeVersion(); - this.isDeviceMotionInRadians = - !this.isIOS && chromeVersion && chromeVersion < 66; - this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion(); - this.filterToWorldQ = new Quaternion$$1(); - if (isIOS()) { - this.filterToWorldQ.setFromAxisAngle( - new Vector3$$1(1, 0, 0), - Math.PI / 2 - ); - } else { - this.filterToWorldQ.setFromAxisAngle( - new Vector3$$1(1, 0, 0), - -Math.PI / 2 - ); - } - this.inverseWorldToScreenQ = new Quaternion$$1(); - this.worldToScreenQ = new Quaternion$$1(); - this.originalPoseAdjustQ = new Quaternion$$1(); - this.originalPoseAdjustQ.setFromAxisAngle( - new Vector3$$1(0, 0, 1), - (-window.orientation * Math.PI) / 180 - ); - this.setScreenTransform_(); - if (isLandscapeMode()) { - this.filterToWorldQ.multiply(this.inverseWorldToScreenQ); - } - this.resetQ = new Quaternion$$1(); - this.orientationOut_ = new Float32Array(4); - this.start(); - } - FusionPoseSensor.prototype.getPosition = function () { - return null; - }; - FusionPoseSensor.prototype.getOrientation = function () { - var orientation = void 0; - if (this.isWithoutDeviceMotion && this._deviceOrientationQ) { - this.deviceOrientationFixQ = - this.deviceOrientationFixQ || - (function () { - var z = new Quaternion$$1().setFromAxisAngle( - new Vector3$$1(0, 0, -1), - 0 - ); - var y = new Quaternion$$1(); - if (window.orientation === -90) { - y.setFromAxisAngle(new Vector3$$1(0, 1, 0), Math.PI / -2); - } else { - y.setFromAxisAngle(new Vector3$$1(0, 1, 0), Math.PI / 2); - } - return z.multiply(y); - })(); - this.deviceOrientationFilterToWorldQ = - this.deviceOrientationFilterToWorldQ || - (function () { - var q = new Quaternion$$1(); - q.setFromAxisAngle(new Vector3$$1(1, 0, 0), -Math.PI / 2); - return q; - })(); - orientation = this._deviceOrientationQ; - var out = new Quaternion$$1(); - out.copy(orientation); - out.multiply(this.deviceOrientationFilterToWorldQ); - out.multiply(this.resetQ); - out.multiply(this.worldToScreenQ); - out.multiplyQuaternions(this.deviceOrientationFixQ, out); - if (this.yawOnly) { - out.x = 0; - out.z = 0; - out.normalize(); - } - this.orientationOut_[0] = out.x; - this.orientationOut_[1] = out.y; - this.orientationOut_[2] = out.z; - this.orientationOut_[3] = out.w; - return this.orientationOut_; - } else { - var filterOrientation = this.filter.getOrientation(); - orientation = this.posePredictor.getPrediction( - filterOrientation, - this.gyroscope, - this.previousTimestampS - ); - } - var out = new Quaternion$$1(); - out.copy(this.filterToWorldQ); - out.multiply(this.resetQ); - out.multiply(orientation); - out.multiply(this.worldToScreenQ); - if (this.yawOnly) { - out.x = 0; - out.z = 0; - out.normalize(); - } - this.orientationOut_[0] = out.x; - this.orientationOut_[1] = out.y; - this.orientationOut_[2] = out.z; - this.orientationOut_[3] = out.w; - return this.orientationOut_; - }; - FusionPoseSensor.prototype.resetPose = function () { - this.resetQ.copy(this.filter.getOrientation()); - this.resetQ.x = 0; - this.resetQ.y = 0; - this.resetQ.z *= -1; - this.resetQ.normalize(); - if (isLandscapeMode()) { - this.resetQ.multiply(this.inverseWorldToScreenQ); - } - this.resetQ.multiply(this.originalPoseAdjustQ); - }; - FusionPoseSensor.prototype.onDeviceOrientation_ = function (e) { - this._deviceOrientationQ = - this._deviceOrientationQ || new Quaternion$$1(); - var alpha = e.alpha, - beta = e.beta, - gamma = e.gamma; - alpha = ((alpha || 0) * Math.PI) / 180; - beta = ((beta || 0) * Math.PI) / 180; - gamma = ((gamma || 0) * Math.PI) / 180; - this._deviceOrientationQ.setFromEulerYXZ(beta, alpha, -gamma); - }; - FusionPoseSensor.prototype.onDeviceMotion_ = function (deviceMotion) { - this.updateDeviceMotion_(deviceMotion); - }; - FusionPoseSensor.prototype.updateDeviceMotion_ = function ( - deviceMotion - ) { - var accGravity = deviceMotion.accelerationIncludingGravity; - var rotRate = deviceMotion.rotationRate; - var timestampS = deviceMotion.timeStamp / 1000; - var deltaS = timestampS - this.previousTimestampS; - if (deltaS < 0) { - warnOnce( - "fusion-pose-sensor:invalid:non-monotonic", - "Invalid timestamps detected: non-monotonic timestamp from devicemotion" - ); - this.previousTimestampS = timestampS; - return; - } else if (deltaS <= MIN_TIMESTEP || deltaS > MAX_TIMESTEP) { - warnOnce( - "fusion-pose-sensor:invalid:outside-threshold", - "Invalid timestamps detected: Timestamp from devicemotion outside expected range." - ); - this.previousTimestampS = timestampS; - return; - } - this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z); - if (isR7()) { - this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma); - } else { - this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); - } - if (!this.isDeviceMotionInRadians) { - this.gyroscope.multiplyScalar(Math.PI / 180); - } - this.filter.addAccelMeasurement(this.accelerometer, timestampS); - this.filter.addGyroMeasurement(this.gyroscope, timestampS); - this.previousTimestampS = timestampS; - }; - FusionPoseSensor.prototype.onOrientationChange_ = function ( - screenOrientation - ) { - this.setScreenTransform_(); - }; - FusionPoseSensor.prototype.onMessage_ = function (event) { - var message = event.data; - if (!message || !message.type) { - return; - } - var type = message.type.toLowerCase(); - if (type !== "devicemotion") { - return; - } - this.updateDeviceMotion_(message.deviceMotionEvent); - }; - FusionPoseSensor.prototype.setScreenTransform_ = function () { - this.worldToScreenQ.set(0, 0, 0, 1); - switch (window.orientation) { - case 0: - break; - case 90: - this.worldToScreenQ.setFromAxisAngle( - new Vector3$$1(0, 0, 1), - -Math.PI / 2 - ); - break; - case -90: - this.worldToScreenQ.setFromAxisAngle( - new Vector3$$1(0, 0, 1), - Math.PI / 2 - ); - break; - case 180: - break; - } - this.inverseWorldToScreenQ.copy(this.worldToScreenQ); - this.inverseWorldToScreenQ.inverse(); - }; - FusionPoseSensor.prototype.start = function () { - this.onDeviceMotionCallback_ = this.onDeviceMotion_.bind(this); - this.onOrientationChangeCallback_ = - this.onOrientationChange_.bind(this); - this.onMessageCallback_ = this.onMessage_.bind(this); - this.onDeviceOrientationCallback_ = - this.onDeviceOrientation_.bind(this); - if (isIOS() && isInsideCrossOriginIFrame()) { - window.addEventListener("message", this.onMessageCallback_); - } - window.addEventListener( - "orientationchange", - this.onOrientationChangeCallback_ - ); - if (this.isWithoutDeviceMotion) { - window.addEventListener( - "deviceorientation", - this.onDeviceOrientationCallback_ - ); - } else { - window.addEventListener( - "devicemotion", - this.onDeviceMotionCallback_ - ); - } - }; - FusionPoseSensor.prototype.stop = function () { - window.removeEventListener( - "devicemotion", - this.onDeviceMotionCallback_ - ); - window.removeEventListener( - "deviceorientation", - this.onDeviceOrientationCallback_ - ); - window.removeEventListener( - "orientationchange", - this.onOrientationChangeCallback_ - ); - window.removeEventListener("message", this.onMessageCallback_); - }; - var SENSOR_FREQUENCY = 60; - var X_AXIS = new Vector3$$1(1, 0, 0); - var Z_AXIS = new Vector3$$1(0, 0, 1); - var orientation = {}; - if (screen.orientation) { - orientation = screen.orientation; - } else if (screen.msOrientation) { - orientation = screen.msOrientation; - } else { - Object.defineProperty(orientation, "angle", { - get: function get$$1() { - return window.orientation || 0; - }, - }); - } - var SENSOR_TO_VR = new Quaternion$$1(); - SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2); - SENSOR_TO_VR.multiply( - new Quaternion$$1().setFromAxisAngle(Z_AXIS, Math.PI / 2) - ); - var PoseSensor = (function () { - function PoseSensor(config) { - classCallCheck(this, PoseSensor); - this.config = config; - this.sensor = null; - this.fusionSensor = null; - this._out = new Float32Array(4); - this.api = null; - this.errors = []; - this._sensorQ = new Quaternion$$1(); - this._worldToScreenQ = new Quaternion$$1(); - this._outQ = new Quaternion$$1(); - this._onSensorRead = this._onSensorRead.bind(this); - this._onSensorError = this._onSensorError.bind(this); - this._onOrientationChange = this._onOrientationChange.bind(this); - this._onOrientationChange(); - this.init(); - } - createClass(PoseSensor, [ - { - key: "init", - value: function init() { - var sensor = null; - try { - sensor = new RelativeOrientationSensor({ - frequency: SENSOR_FREQUENCY, - }); - sensor.addEventListener("error", this._onSensorError); - } catch (error) { - this.errors.push(error); - if (error.name === "SecurityError") { - console.error( - "Cannot construct sensors due to the Feature Policy" - ); - console.warn( - 'Attempting to fall back using "devicemotion"; however this will ' + - "fail in the future without correct permissions." - ); - this.useDeviceMotion(); - } else if (error.name === "ReferenceError") { - this.useDeviceMotion(); - } else { - console.error(error); - } - } - if (sensor) { - this.api = "sensor"; - this.sensor = sensor; - this.sensor.addEventListener("reading", this._onSensorRead); - this.sensor.start(); - } - window.addEventListener( - "orientationchange", - this._onOrientationChange - ); - }, - }, - { - key: "useDeviceMotion", - value: function useDeviceMotion() { - this.api = "devicemotion"; - this.fusionSensor = new FusionPoseSensor( - this.config.K_FILTER, - this.config.PREDICTION_TIME_S, - this.config.YAW_ONLY, - this.config.DEBUG - ); - }, - }, - { - key: "getOrientation", - value: function getOrientation() { - if (this.fusionSensor) { - return this.fusionSensor.getOrientation(); - } - if (!this.sensor || !this.sensor.quaternion) { - this._out[0] = this._out[1] = this._out[2] = 0; - this._out[3] = 1; - return this._out; - } - var q = this.sensor.quaternion; - this._sensorQ.set(q[0], q[1], q[2], q[3]); - var out = this._outQ; - out.copy(SENSOR_TO_VR); - out.multiply(this._sensorQ); - out.multiply(this._worldToScreenQ); - if (this.config.YAW_ONLY) { - out.x = out.z = 0; - out.normalize(); - } - this._out[0] = out.x; - this._out[1] = out.y; - this._out[2] = out.z; - this._out[3] = out.w; - return this._out; - }, - }, - { - key: "_onSensorError", - value: function _onSensorError(event) { - this.errors.push(event.error); - if (event.error.name === "NotAllowedError") { - console.error("Permission to access sensor was denied"); - } else if (event.error.name === "NotReadableError") { - console.error("Sensor could not be read"); - } else { - console.error(event.error); - } - }, - }, - { - key: "_onSensorRead", - value: function _onSensorRead() {}, - }, - { - key: "_onOrientationChange", - value: function _onOrientationChange() { - var angle = (-orientation.angle * Math.PI) / 180; - this._worldToScreenQ.setFromAxisAngle(Z_AXIS, angle); - }, - }, - ]); - return PoseSensor; - })(); - var rotateInstructionsAsset = - "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyBDNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCBDMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE5LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEMxMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4yMTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzLDE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE5Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSBMNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiBMMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2LDY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+"; - function RotateInstructions() { - this.loadIcon_(); - var overlay = document.createElement("div"); - var s = overlay.style; - s.position = "fixed"; - s.top = 0; - s.right = 0; - s.bottom = 0; - s.left = 0; - s.backgroundColor = "gray"; - s.fontFamily = "sans-serif"; - s.zIndex = 1000000; - var img = document.createElement("img"); - img.src = this.icon; - var s = img.style; - s.marginLeft = "25%"; - s.marginTop = "25%"; - s.width = "50%"; - overlay.appendChild(img); - var text = document.createElement("div"); - var s = text.style; - s.textAlign = "center"; - s.fontSize = "16px"; - s.lineHeight = "24px"; - s.margin = "24px 25%"; - s.width = "50%"; - text.innerHTML = "Place your phone into your Cardboard viewer."; - overlay.appendChild(text); - var snackbar = document.createElement("div"); - var s = snackbar.style; - s.backgroundColor = "#CFD8DC"; - s.position = "fixed"; - s.bottom = 0; - s.width = "100%"; - s.height = "48px"; - s.padding = "14px 24px"; - s.boxSizing = "border-box"; - s.color = "#656A6B"; - overlay.appendChild(snackbar); - var snackbarText = document.createElement("div"); - snackbarText.style.float = "left"; - snackbarText.innerHTML = "No Cardboard viewer?"; - var snackbarButton = document.createElement("a"); - snackbarButton.href = - "https://www.google.com/get/cardboard/get-cardboard/"; - snackbarButton.innerHTML = "get one"; - snackbarButton.target = "_blank"; - var s = snackbarButton.style; - s.float = "right"; - s.fontWeight = 600; - s.textTransform = "uppercase"; - s.borderLeft = "1px solid gray"; - s.paddingLeft = "24px"; - s.textDecoration = "none"; - s.color = "#656A6B"; - snackbar.appendChild(snackbarText); - snackbar.appendChild(snackbarButton); - this.overlay = overlay; - this.text = text; - this.hide(); - } - RotateInstructions.prototype.show = function (parent) { - if (!parent && !this.overlay.parentElement) { - document.body.appendChild(this.overlay); - } else if (parent) { - if ( - this.overlay.parentElement && - this.overlay.parentElement != parent - ) - this.overlay.parentElement.removeChild(this.overlay); - parent.appendChild(this.overlay); - } - this.overlay.style.display = "block"; - var img = this.overlay.querySelector("img"); - var s = img.style; - if (isLandscapeMode()) { - s.width = "20%"; - s.marginLeft = "40%"; - s.marginTop = "3%"; - } else { - s.width = "50%"; - s.marginLeft = "25%"; - s.marginTop = "25%"; - } - }; - RotateInstructions.prototype.hide = function () { - this.overlay.style.display = "none"; - }; - RotateInstructions.prototype.showTemporarily = function (ms, parent) { - this.show(parent); - this.timer = setTimeout(this.hide.bind(this), ms); - }; - RotateInstructions.prototype.disableShowTemporarily = function () { - clearTimeout(this.timer); - }; - RotateInstructions.prototype.update = function () { - this.disableShowTemporarily(); - if (!isLandscapeMode() && isMobile()) { - this.show(); - } else { - this.hide(); - } - }; - RotateInstructions.prototype.loadIcon_ = function () { - this.icon = base64("image/svg+xml", rotateInstructionsAsset); - }; - var DEFAULT_VIEWER = "CardboardV1"; - var VIEWER_KEY = "WEBVR_CARDBOARD_VIEWER"; - var CLASS_NAME = "webvr-polyfill-viewer-selector"; - function ViewerSelector() { - try { - this.selectedKey = localStorage.getItem(VIEWER_KEY); - } catch (error) { - console.error("Failed to load viewer profile: %s", error); - } - if (!this.selectedKey) { - this.selectedKey = DEFAULT_VIEWER; - } - this.dialog = this.createDialog_(DeviceInfo.Viewers); - this.root = null; - this.onChangeCallbacks_ = []; - } - ViewerSelector.prototype.show = function (root) { - this.root = root; - root.appendChild(this.dialog); - var selected = this.dialog.querySelector("#" + this.selectedKey); - selected.checked = true; - this.dialog.style.display = "block"; - }; - ViewerSelector.prototype.hide = function () { - if (this.root && this.root.contains(this.dialog)) { - this.root.removeChild(this.dialog); - } - this.dialog.style.display = "none"; - }; - ViewerSelector.prototype.getCurrentViewer = function () { - return DeviceInfo.Viewers[this.selectedKey]; - }; - ViewerSelector.prototype.getSelectedKey_ = function () { - var input = this.dialog.querySelector("input[name=field]:checked"); - if (input) { - return input.id; - } - return null; - }; - ViewerSelector.prototype.onChange = function (cb) { - this.onChangeCallbacks_.push(cb); - }; - ViewerSelector.prototype.fireOnChange_ = function (viewer) { - for (var i = 0; i < this.onChangeCallbacks_.length; i++) { - this.onChangeCallbacks_[i](viewer); - } - }; - ViewerSelector.prototype.onSave_ = function () { - this.selectedKey = this.getSelectedKey_(); - if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) { - console.error("ViewerSelector.onSave_: this should never happen!"); - return; - } - this.fireOnChange_(DeviceInfo.Viewers[this.selectedKey]); - try { - localStorage.setItem(VIEWER_KEY, this.selectedKey); - } catch (error) { - console.error("Failed to save viewer profile: %s", error); - } - this.hide(); - }; - ViewerSelector.prototype.createDialog_ = function (options) { - var container = document.createElement("div"); - container.classList.add(CLASS_NAME); - container.style.display = "none"; - var overlay = document.createElement("div"); - var s = overlay.style; - s.position = "fixed"; - s.left = 0; - s.top = 0; - s.width = "100%"; - s.height = "100%"; - s.background = "rgba(0, 0, 0, 0.3)"; - overlay.addEventListener("click", this.hide.bind(this)); - var width = 280; - var dialog = document.createElement("div"); - var s = dialog.style; - s.boxSizing = "border-box"; - s.position = "fixed"; - s.top = "24px"; - s.left = "50%"; - s.marginLeft = -width / 2 + "px"; - s.width = width + "px"; - s.padding = "24px"; - s.overflow = "hidden"; - s.background = "#fafafa"; - s.fontFamily = "'Roboto', sans-serif"; - s.boxShadow = "0px 5px 20px #666"; - dialog.appendChild(this.createH1_("Select your viewer")); - for (var id in options) { - dialog.appendChild(this.createChoice_(id, options[id].label)); - } - dialog.appendChild( - this.createButton_("Save", this.onSave_.bind(this)) - ); - container.appendChild(overlay); - container.appendChild(dialog); - return container; - }; - ViewerSelector.prototype.createH1_ = function (name) { - var h1 = document.createElement("h1"); - var s = h1.style; - s.color = "black"; - s.fontSize = "20px"; - s.fontWeight = "bold"; - s.marginTop = 0; - s.marginBottom = "24px"; - h1.innerHTML = name; - return h1; - }; - ViewerSelector.prototype.createChoice_ = function (id, name) { - var div = document.createElement("div"); - div.style.marginTop = "8px"; - div.style.color = "black"; - var input = document.createElement("input"); - input.style.fontSize = "30px"; - input.setAttribute("id", id); - input.setAttribute("type", "radio"); - input.setAttribute("value", id); - input.setAttribute("name", "field"); - var label = document.createElement("label"); - label.style.marginLeft = "4px"; - label.setAttribute("for", id); - label.innerHTML = name; - div.appendChild(input); - div.appendChild(label); - return div; - }; - ViewerSelector.prototype.createButton_ = function (label, onclick) { - var button = document.createElement("button"); - button.innerHTML = label; - var s = button.style; - s.float = "right"; - s.textTransform = "uppercase"; - s.color = "#1094f7"; - s.fontSize = "14px"; - s.letterSpacing = 0; - s.border = 0; - s.background = "none"; - s.marginTop = "16px"; - button.addEventListener("click", onclick); - return button; - }; - var commonjsGlobal$$1 = - typeof window !== "undefined" - ? window - : typeof commonjsGlobal$$1 !== "undefined" - ? commonjsGlobal$$1 - : typeof self !== "undefined" - ? self - : {}; - function unwrapExports$$1(x) { - return x && x.__esModule ? x["default"] : x; - } - function createCommonjsModule$$1(fn, module) { - return ( - (module = { exports: {} }), - fn(module, module.exports), - module.exports - ); - } - var NoSleep = createCommonjsModule$$1(function (module, exports) { - (function webpackUniversalModuleDefinition(root, factory) { - module.exports = factory(); - })(commonjsGlobal$$1, function () { - return (function (modules) { - var installedModules = {}; - function __webpack_require__(moduleId) { - if (installedModules[moduleId]) { - return installedModules[moduleId].exports; - } - var module = (installedModules[moduleId] = { - i: moduleId, - l: false, - exports: {}, - }); - modules[moduleId].call( - module.exports, - module, - module.exports, - __webpack_require__ - ); - module.l = true; - return module.exports; - } - __webpack_require__.m = modules; - __webpack_require__.c = installedModules; - __webpack_require__.d = function (exports, name, getter) { - if (!__webpack_require__.o(exports, name)) { - Object.defineProperty(exports, name, { - configurable: false, - enumerable: true, - get: getter, - }); - } - }; - __webpack_require__.n = function (module) { - var getter = - module && module.__esModule - ? function getDefault() { - return module["default"]; - } - : function getModuleExports() { - return module; - }; - __webpack_require__.d(getter, "a", getter); - return getter; - }; - __webpack_require__.o = function (object, property) { - return Object.prototype.hasOwnProperty.call(object, property); - }; - __webpack_require__.p = ""; - return __webpack_require__((__webpack_require__.s = 0)); - })([ - function (module, exports, __webpack_require__) { - var _createClass = (function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - return function (Constructor, protoProps, staticProps) { - if (protoProps) - defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - })(); - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - var mediaFile = __webpack_require__(1); - var oldIOS = - typeof navigator !== "undefined" && - parseFloat( - ( - "" + - (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec( - navigator.userAgent - ) || [0, ""])[1] - ) - .replace("undefined", "3_2") - .replace("_", ".") - .replace("_", "") - ) < 10 && - !window.MSStream; - var NoSleep = (function () { - function NoSleep() { - _classCallCheck(this, NoSleep); - if (oldIOS) { - this.noSleepTimer = null; - } else { - this.noSleepVideo = document.createElement("video"); - this.noSleepVideo.setAttribute("playsinline", ""); - this.noSleepVideo.setAttribute("src", mediaFile); - this.noSleepVideo.addEventListener( - "timeupdate", - function (e) { - if (this.noSleepVideo.currentTime > 0.5) { - this.noSleepVideo.currentTime = Math.random(); - } - }.bind(this) - ); - } - } - _createClass(NoSleep, [ - { - key: "enable", - value: function enable() { - if (oldIOS) { - this.disable(); - this.noSleepTimer = window.setInterval(function () { - window.location.href = "/"; - window.setTimeout(window.stop, 0); - }, 15000); - } else { - this.noSleepVideo.play(); - } - }, - }, - { - key: "disable", - value: function disable() { - if (oldIOS) { - if (this.noSleepTimer) { - window.clearInterval(this.noSleepTimer); - this.noSleepTimer = null; - } - } else { - this.noSleepVideo.pause(); - } - }, - }, - ]); - return NoSleep; - })(); - module.exports = NoSleep; - }, - function (module, exports, __webpack_require__) { - module.exports = - "data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA="; - }, - ]); - }); - }); - var NoSleep$1 = unwrapExports$$1(NoSleep); - var nextDisplayId = 1000; - var defaultLeftBounds = [0, 0, 0.5, 1]; - var defaultRightBounds = [0.5, 0, 0.5, 1]; - var raf = window.requestAnimationFrame; - var caf = window.cancelAnimationFrame; - function VRFrameData() { - this.leftProjectionMatrix = new Float32Array(16); - this.leftViewMatrix = new Float32Array(16); - this.rightProjectionMatrix = new Float32Array(16); - this.rightViewMatrix = new Float32Array(16); - this.pose = null; - } - function VRDisplayCapabilities(config) { - Object.defineProperties(this, { - hasPosition: { - writable: false, - enumerable: true, - value: config.hasPosition, - }, - hasExternalDisplay: { - writable: false, - enumerable: true, - value: config.hasExternalDisplay, - }, - canPresent: { - writable: false, - enumerable: true, - value: config.canPresent, - }, - maxLayers: { - writable: false, - enumerable: true, - value: config.maxLayers, - }, - hasOrientation: { - enumerable: true, - get: function get() { - deprecateWarning( - "VRDisplayCapabilities.prototype.hasOrientation", - "VRDisplay.prototype.getFrameData" - ); - return config.hasOrientation; - }, - }, - }); - } - function VRDisplay(config) { - config = config || {}; - var USE_WAKELOCK = "wakelock" in config ? config.wakelock : true; - this.isPolyfilled = true; - this.displayId = nextDisplayId++; - this.displayName = ""; - this.depthNear = 0.01; - this.depthFar = 10000.0; - this.isPresenting = false; - Object.defineProperty(this, "isConnected", { - get: function get() { - deprecateWarning( - "VRDisplay.prototype.isConnected", - "VRDisplayCapabilities.prototype.hasExternalDisplay" - ); - return false; - }, - }); - this.capabilities = new VRDisplayCapabilities({ - hasPosition: false, - hasOrientation: false, - hasExternalDisplay: false, - canPresent: false, - maxLayers: 1, - }); - this.stageParameters = null; - this.waitingForPresent_ = false; - this.layer_ = null; - this.originalParent_ = null; - this.fullscreenElement_ = null; - this.fullscreenWrapper_ = null; - this.fullscreenElementCachedStyle_ = null; - this.fullscreenEventTarget_ = null; - this.fullscreenChangeHandler_ = null; - this.fullscreenErrorHandler_ = null; - if (USE_WAKELOCK && isMobile()) { - this.wakelock_ = new NoSleep$1(); - } - } - VRDisplay.prototype.getFrameData = function (frameData) { - return frameDataFromPose(frameData, this._getPose(), this); - }; - VRDisplay.prototype.getPose = function () { - deprecateWarning( - "VRDisplay.prototype.getPose", - "VRDisplay.prototype.getFrameData" - ); - return this._getPose(); - }; - VRDisplay.prototype.resetPose = function () { - deprecateWarning("VRDisplay.prototype.resetPose"); - return this._resetPose(); - }; - VRDisplay.prototype.getImmediatePose = function () { - deprecateWarning( - "VRDisplay.prototype.getImmediatePose", - "VRDisplay.prototype.getFrameData" - ); - return this._getPose(); - }; - VRDisplay.prototype.requestAnimationFrame = function (callback) { - return raf(callback); - }; - VRDisplay.prototype.cancelAnimationFrame = function (id) { - return caf(id); - }; - VRDisplay.prototype.wrapForFullscreen = function (element) { - if (isIOS()) { - return element; - } - if (!this.fullscreenWrapper_) { - this.fullscreenWrapper_ = document.createElement("div"); - var cssProperties = [ - "height: " + - Math.min(screen.height, screen.width) + - "px !important", - "top: 0 !important", - "left: 0 !important", - "right: 0 !important", - "border: 0", - "margin: 0", - "padding: 0", - "z-index: 999999 !important", - "position: fixed", - ]; - this.fullscreenWrapper_.setAttribute( - "style", - cssProperties.join("; ") + ";" - ); - this.fullscreenWrapper_.classList.add( - "webvr-polyfill-fullscreen-wrapper" - ); - } - if (this.fullscreenElement_ == element) { - return this.fullscreenWrapper_; - } - if (this.fullscreenElement_) { - if (this.originalParent_) { - this.originalParent_.appendChild(this.fullscreenElement_); - } else { - this.fullscreenElement_.parentElement.removeChild( - this.fullscreenElement_ - ); - } - } - this.fullscreenElement_ = element; - this.originalParent_ = element.parentElement; - if (!this.originalParent_) { - document.body.appendChild(element); - } - if (!this.fullscreenWrapper_.parentElement) { - var parent = this.fullscreenElement_.parentElement; - parent.insertBefore( - this.fullscreenWrapper_, - this.fullscreenElement_ - ); - parent.removeChild(this.fullscreenElement_); - } - this.fullscreenWrapper_.insertBefore( - this.fullscreenElement_, - this.fullscreenWrapper_.firstChild - ); - this.fullscreenElementCachedStyle_ = - this.fullscreenElement_.getAttribute("style"); - var self = this; - function applyFullscreenElementStyle() { - if (!self.fullscreenElement_) { - return; - } - var cssProperties = [ - "position: absolute", - "top: 0", - "left: 0", - "width: " + Math.max(screen.width, screen.height) + "px", - "height: " + Math.min(screen.height, screen.width) + "px", - "border: 0", - "margin: 0", - "padding: 0", - ]; - self.fullscreenElement_.setAttribute( - "style", - cssProperties.join("; ") + ";" - ); - } - applyFullscreenElementStyle(); - return this.fullscreenWrapper_; - }; - VRDisplay.prototype.removeFullscreenWrapper = function () { - if (!this.fullscreenElement_) { - return; - } - var element = this.fullscreenElement_; - if (this.fullscreenElementCachedStyle_) { - element.setAttribute("style", this.fullscreenElementCachedStyle_); - } else { - element.removeAttribute("style"); - } - this.fullscreenElement_ = null; - this.fullscreenElementCachedStyle_ = null; - var parent = this.fullscreenWrapper_.parentElement; - this.fullscreenWrapper_.removeChild(element); - if (this.originalParent_ === parent) { - parent.insertBefore(element, this.fullscreenWrapper_); - } else if (this.originalParent_) { - this.originalParent_.appendChild(element); - } - parent.removeChild(this.fullscreenWrapper_); - return element; - }; - VRDisplay.prototype.requestPresent = function (layers) { - var wasPresenting = this.isPresenting; - var self = this; - if (!(layers instanceof Array)) { - deprecateWarning( - "VRDisplay.prototype.requestPresent with non-array argument", - "an array of VRLayers as the first argument" - ); - layers = [layers]; - } - return new Promise(function (resolve, reject) { - if (!self.capabilities.canPresent) { - reject(new Error("VRDisplay is not capable of presenting.")); - return; - } - if ( - layers.length == 0 || - layers.length > self.capabilities.maxLayers - ) { - reject(new Error("Invalid number of layers.")); - return; - } - var incomingLayer = layers[0]; - if (!incomingLayer.source) { - resolve(); - return; - } - var leftBounds = incomingLayer.leftBounds || defaultLeftBounds; - var rightBounds = incomingLayer.rightBounds || defaultRightBounds; - if (wasPresenting) { - var layer = self.layer_; - if (layer.source !== incomingLayer.source) { - layer.source = incomingLayer.source; - } - for (var i = 0; i < 4; i++) { - layer.leftBounds[i] = leftBounds[i]; - layer.rightBounds[i] = rightBounds[i]; - } - self.wrapForFullscreen(self.layer_.source); - self.updatePresent_(); - resolve(); - return; - } - self.layer_ = { - predistorted: incomingLayer.predistorted, - source: incomingLayer.source, - leftBounds: leftBounds.slice(0), - rightBounds: rightBounds.slice(0), - }; - self.waitingForPresent_ = false; - if (self.layer_ && self.layer_.source) { - var fullscreenElement = self.wrapForFullscreen( - self.layer_.source - ); - var onFullscreenChange = function onFullscreenChange() { - var actualFullscreenElement = getFullscreenElement(); - self.isPresenting = - fullscreenElement === actualFullscreenElement; - if (self.isPresenting) { - if (screen.orientation && screen.orientation.lock) { - screen.orientation - .lock("landscape-primary") - .catch(function (error) { - console.error( - "screen.orientation.lock() failed due to", - error.message - ); - }); - } - self.waitingForPresent_ = false; - self.beginPresent_(); - resolve(); - } else { - if (screen.orientation && screen.orientation.unlock) { - screen.orientation.unlock(); - } - self.removeFullscreenWrapper(); - self.disableWakeLock(); - self.endPresent_(); - self.removeFullscreenListeners_(); - } - self.fireVRDisplayPresentChange_(); - }; - var onFullscreenError = function onFullscreenError() { - if (!self.waitingForPresent_) { - return; - } - self.removeFullscreenWrapper(); - self.removeFullscreenListeners_(); - self.disableWakeLock(); - self.waitingForPresent_ = false; - self.isPresenting = false; - reject(new Error("Unable to present.")); - }; - self.addFullscreenListeners_( - fullscreenElement, - onFullscreenChange, - onFullscreenError - ); - if (requestFullscreen(fullscreenElement)) { - self.enableWakeLock(); - self.waitingForPresent_ = true; - } else if (isIOS() || isWebViewAndroid()) { - self.enableWakeLock(); - self.isPresenting = true; - self.beginPresent_(); - self.fireVRDisplayPresentChange_(); - resolve(); - } - } - if (!self.waitingForPresent_ && !isIOS()) { - exitFullscreen(); - reject(new Error("Unable to present.")); - } - }); - }; - VRDisplay.prototype.exitPresent = function () { - var wasPresenting = this.isPresenting; - var self = this; - this.isPresenting = false; - this.layer_ = null; - this.disableWakeLock(); - return new Promise(function (resolve, reject) { - if (wasPresenting) { - if (!exitFullscreen() && isIOS()) { - self.endPresent_(); - self.fireVRDisplayPresentChange_(); - } - if (isWebViewAndroid()) { - self.removeFullscreenWrapper(); - self.removeFullscreenListeners_(); - self.endPresent_(); - self.fireVRDisplayPresentChange_(); - } - resolve(); - } else { - reject(new Error("Was not presenting to VRDisplay.")); - } - }); - }; - VRDisplay.prototype.getLayers = function () { - if (this.layer_) { - return [this.layer_]; - } - return []; - }; - VRDisplay.prototype.fireVRDisplayPresentChange_ = function () { - var event = new CustomEvent("vrdisplaypresentchange", { - detail: { display: this }, - }); - window.dispatchEvent(event); - }; - VRDisplay.prototype.fireVRDisplayConnect_ = function () { - var event = new CustomEvent("vrdisplayconnect", { - detail: { display: this }, - }); - window.dispatchEvent(event); - }; - VRDisplay.prototype.addFullscreenListeners_ = function ( - element, - changeHandler, - errorHandler - ) { - this.removeFullscreenListeners_(); - this.fullscreenEventTarget_ = element; - this.fullscreenChangeHandler_ = changeHandler; - this.fullscreenErrorHandler_ = errorHandler; - if (changeHandler) { - if (document.fullscreenEnabled) { - element.addEventListener( - "fullscreenchange", - changeHandler, - false - ); - } else if (document.webkitFullscreenEnabled) { - element.addEventListener( - "webkitfullscreenchange", - changeHandler, - false - ); - } else if (document.mozFullScreenEnabled) { - document.addEventListener( - "mozfullscreenchange", - changeHandler, - false - ); - } else if (document.msFullscreenEnabled) { - element.addEventListener( - "msfullscreenchange", - changeHandler, - false - ); - } - } - if (errorHandler) { - if (document.fullscreenEnabled) { - element.addEventListener("fullscreenerror", errorHandler, false); - } else if (document.webkitFullscreenEnabled) { - element.addEventListener( - "webkitfullscreenerror", - errorHandler, - false - ); - } else if (document.mozFullScreenEnabled) { - document.addEventListener( - "mozfullscreenerror", - errorHandler, - false - ); - } else if (document.msFullscreenEnabled) { - element.addEventListener( - "msfullscreenerror", - errorHandler, - false - ); - } - } - }; - VRDisplay.prototype.removeFullscreenListeners_ = function () { - if (!this.fullscreenEventTarget_) return; - var element = this.fullscreenEventTarget_; - if (this.fullscreenChangeHandler_) { - var changeHandler = this.fullscreenChangeHandler_; - element.removeEventListener( - "fullscreenchange", - changeHandler, - false - ); - element.removeEventListener( - "webkitfullscreenchange", - changeHandler, - false - ); - document.removeEventListener( - "mozfullscreenchange", - changeHandler, - false - ); - element.removeEventListener( - "msfullscreenchange", - changeHandler, - false - ); - } - if (this.fullscreenErrorHandler_) { - var errorHandler = this.fullscreenErrorHandler_; - element.removeEventListener("fullscreenerror", errorHandler, false); - element.removeEventListener( - "webkitfullscreenerror", - errorHandler, - false - ); - document.removeEventListener( - "mozfullscreenerror", - errorHandler, - false - ); - element.removeEventListener( - "msfullscreenerror", - errorHandler, - false - ); - } - this.fullscreenEventTarget_ = null; - this.fullscreenChangeHandler_ = null; - this.fullscreenErrorHandler_ = null; - }; - VRDisplay.prototype.enableWakeLock = function () { - if (this.wakelock_) { - this.wakelock_.enable(); - } - }; - VRDisplay.prototype.disableWakeLock = function () { - if (this.wakelock_) { - this.wakelock_.disable(); - } - }; - VRDisplay.prototype.beginPresent_ = function () {}; - VRDisplay.prototype.endPresent_ = function () {}; - VRDisplay.prototype.submitFrame = function (pose) {}; - VRDisplay.prototype.getEyeParameters = function (whichEye) { - return null; - }; - var config = { - MOBILE_WAKE_LOCK: true, - DEBUG: false, - DPDB_URL: "https://dpdb.webvr.rocks/dpdb.json", - K_FILTER: 0.98, - PREDICTION_TIME_S: 0.04, - CARDBOARD_UI_DISABLED: false, - ROTATE_INSTRUCTIONS_DISABLED: false, - YAW_ONLY: false, - BUFFER_SCALE: 0.5, - DIRTY_SUBMIT_FRAME_BINDINGS: false, - }; - var Eye = { - LEFT: "left", - RIGHT: "right", - }; - function CardboardVRDisplay(config$$1) { - var defaults = extend({}, config); - config$$1 = extend(defaults, config$$1 || {}); - VRDisplay.call(this, { - wakelock: config$$1.MOBILE_WAKE_LOCK, - }); - this.config = config$$1; - this.displayName = "Cardboard VRDisplay"; - this.capabilities = new VRDisplayCapabilities({ - hasPosition: false, - hasOrientation: true, - hasExternalDisplay: false, - canPresent: true, - maxLayers: 1, - }); - this.stageParameters = null; - this.bufferScale_ = this.config.BUFFER_SCALE; - this.poseSensor_ = new PoseSensor(this.config); - this.distorter_ = null; - this.cardboardUI_ = null; - this.dpdb_ = new Dpdb( - this.config.DPDB_URL, - this.onDeviceParamsUpdated_.bind(this) - ); - this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams()); - this.viewerSelector_ = new ViewerSelector(); - this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)); - this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()); - if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) { - this.rotateInstructions_ = new RotateInstructions(); - } - if (isIOS()) { - window.addEventListener("resize", this.onResize_.bind(this)); - } - } - CardboardVRDisplay.prototype = Object.create(VRDisplay.prototype); - CardboardVRDisplay.prototype._getPose = function () { - return { - position: null, - orientation: this.poseSensor_.getOrientation(), - linearVelocity: null, - linearAcceleration: null, - angularVelocity: null, - angularAcceleration: null, - }; - }; - CardboardVRDisplay.prototype._resetPose = function () { - if (this.poseSensor_.resetPose) { - this.poseSensor_.resetPose(); - } - }; - CardboardVRDisplay.prototype._getFieldOfView = function (whichEye) { - var fieldOfView; - if (whichEye == Eye.LEFT) { - fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye(); - } else if (whichEye == Eye.RIGHT) { - fieldOfView = this.deviceInfo_.getFieldOfViewRightEye(); - } else { - console.error("Invalid eye provided: %s", whichEye); - return null; - } - return fieldOfView; - }; - CardboardVRDisplay.prototype._getEyeOffset = function (whichEye) { - var offset; - if (whichEye == Eye.LEFT) { - offset = [ - -this.deviceInfo_.viewer.interLensDistance * 0.5, - 0.0, - 0.0, - ]; - } else if (whichEye == Eye.RIGHT) { - offset = [ - this.deviceInfo_.viewer.interLensDistance * 0.5, - 0.0, - 0.0, - ]; - } else { - console.error("Invalid eye provided: %s", whichEye); - return null; - } - return offset; - }; - CardboardVRDisplay.prototype.getEyeParameters = function (whichEye) { - var offset = this._getEyeOffset(whichEye); - var fieldOfView = this._getFieldOfView(whichEye); - var eyeParams = { - offset: offset, - renderWidth: - this.deviceInfo_.device.width * 0.5 * this.bufferScale_, - renderHeight: this.deviceInfo_.device.height * this.bufferScale_, - }; - Object.defineProperty(eyeParams, "fieldOfView", { - enumerable: true, - get: function get() { - deprecateWarning( - "VRFieldOfView", - "VRFrameData's projection matrices" - ); - return fieldOfView; - }, - }); - return eyeParams; - }; - CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function ( - newParams - ) { - if (this.config.DEBUG) { - console.log("DPDB reported that device params were updated."); - } - this.deviceInfo_.updateDeviceParams(newParams); - if (this.distorter_) { - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - }; - CardboardVRDisplay.prototype.updateBounds_ = function () { - if ( - this.layer_ && - this.distorter_ && - (this.layer_.leftBounds || this.layer_.rightBounds) - ) { - this.distorter_.setTextureBounds( - this.layer_.leftBounds, - this.layer_.rightBounds - ); - } - }; - CardboardVRDisplay.prototype.beginPresent_ = function () { - var gl = this.layer_.source.getContext("webgl"); - if (!gl) gl = this.layer_.source.getContext("experimental-webgl"); - if (!gl) gl = this.layer_.source.getContext("webgl2"); - if (!gl) return; - if (this.layer_.predistorted) { - if (!this.config.CARDBOARD_UI_DISABLED) { - gl.canvas.width = getScreenWidth() * this.bufferScale_; - gl.canvas.height = getScreenHeight() * this.bufferScale_; - this.cardboardUI_ = new CardboardUI(gl); - } - } else { - if (!this.config.CARDBOARD_UI_DISABLED) { - this.cardboardUI_ = new CardboardUI(gl); - } - this.distorter_ = new CardboardDistorter( - gl, - this.cardboardUI_, - this.config.BUFFER_SCALE, - this.config.DIRTY_SUBMIT_FRAME_BINDINGS - ); - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - if (this.cardboardUI_) { - this.cardboardUI_.listen( - function (e) { - this.viewerSelector_.show(this.layer_.source.parentElement); - e.stopPropagation(); - e.preventDefault(); - }.bind(this), - function (e) { - this.exitPresent(); - e.stopPropagation(); - e.preventDefault(); - }.bind(this) - ); - } - if (this.rotateInstructions_) { - if (isLandscapeMode() && isMobile()) { - this.rotateInstructions_.showTemporarily( - 3000, - this.layer_.source.parentElement - ); - } else { - this.rotateInstructions_.update(); - } - } - this.orientationHandler = this.onOrientationChange_.bind(this); - window.addEventListener("orientationchange", this.orientationHandler); - this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this); - window.addEventListener( - "vrdisplaypresentchange", - this.vrdisplaypresentchangeHandler - ); - this.fireVRDisplayDeviceParamsChange_(); - }; - CardboardVRDisplay.prototype.endPresent_ = function () { - if (this.distorter_) { - this.distorter_.destroy(); - this.distorter_ = null; - } - if (this.cardboardUI_) { - this.cardboardUI_.destroy(); - this.cardboardUI_ = null; - } - if (this.rotateInstructions_) { - this.rotateInstructions_.hide(); - } - this.viewerSelector_.hide(); - window.removeEventListener( - "orientationchange", - this.orientationHandler - ); - window.removeEventListener( - "vrdisplaypresentchange", - this.vrdisplaypresentchangeHandler - ); - }; - CardboardVRDisplay.prototype.updatePresent_ = function () { - this.endPresent_(); - this.beginPresent_(); - }; - CardboardVRDisplay.prototype.submitFrame = function (pose) { - if (this.distorter_) { - this.updateBounds_(); - this.distorter_.submitFrame(); - } else if (this.cardboardUI_ && this.layer_) { - var canvas = this.layer_.source.getContext("webgl").canvas; - if ( - canvas.width != this.lastWidth || - canvas.height != this.lastHeight - ) { - this.cardboardUI_.onResize(); - } - this.lastWidth = canvas.width; - this.lastHeight = canvas.height; - this.cardboardUI_.render(); - } - }; - CardboardVRDisplay.prototype.onOrientationChange_ = function (e) { - this.viewerSelector_.hide(); - if (this.rotateInstructions_) { - this.rotateInstructions_.update(); - } - this.onResize_(); - }; - CardboardVRDisplay.prototype.onResize_ = function (e) { - if (this.layer_) { - var gl = this.layer_.source.getContext("webgl"); - var cssProperties = [ - "position: absolute", - "top: 0", - "left: 0", - "width: 100vw", - "height: 100vh", - "border: 0", - "margin: 0", - "padding: 0px", - "box-sizing: content-box", - ]; - gl.canvas.setAttribute("style", cssProperties.join("; ") + ";"); - safariCssSizeWorkaround(gl.canvas); - } - }; - CardboardVRDisplay.prototype.onViewerChanged_ = function (viewer) { - this.deviceInfo_.setViewer(viewer); - if (this.distorter_) { - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - this.fireVRDisplayDeviceParamsChange_(); - }; - CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = - function () { - var event = new CustomEvent("vrdisplaydeviceparamschange", { - detail: { - vrdisplay: this, - deviceInfo: this.deviceInfo_, - }, - }); - window.dispatchEvent(event); - }; - CardboardVRDisplay.VRFrameData = VRFrameData; - CardboardVRDisplay.VRDisplay = VRDisplay; - return CardboardVRDisplay; - }); - }); - var CardboardVRDisplay = unwrapExports$$1(cardboardVrDisplay); - - var version = "0.10.5"; - - var DefaultConfig = { - PROVIDE_MOBILE_VRDISPLAY: true, - GET_VR_DISPLAYS_TIMEOUT: 1000, - MOBILE_WAKE_LOCK: true, - DEBUG: false, - DPDB_URL: "https://dpdb.webvr.rocks/dpdb.json", - K_FILTER: 0.98, - PREDICTION_TIME_S: 0.04, - TOUCH_PANNER_DISABLED: true, - CARDBOARD_UI_DISABLED: false, - ROTATE_INSTRUCTIONS_DISABLED: false, - YAW_ONLY: false, - BUFFER_SCALE: 0.5, - DIRTY_SUBMIT_FRAME_BINDINGS: false, - }; - - function WebVRPolyfill(config) { - this.config = extend(extend({}, DefaultConfig), config); - this.polyfillDisplays = []; - this.enabled = false; - this.hasNative = "getVRDisplays" in navigator; - this.native = {}; - this.native.getVRDisplays = navigator.getVRDisplays; - this.native.VRFrameData = window.VRFrameData; - this.native.VRDisplay = window.VRDisplay; - if ( - !this.hasNative || - (this.config.PROVIDE_MOBILE_VRDISPLAY && isMobile()) - ) { - this.enable(); - this.getVRDisplays().then(function (displays) { - if (displays && displays[0] && displays[0].fireVRDisplayConnect_) { - displays[0].fireVRDisplayConnect_(); - } - }); - } - } - WebVRPolyfill.prototype.getPolyfillDisplays = function () { - if (this._polyfillDisplaysPopulated) { - return this.polyfillDisplays; - } - if (isMobile()) { - var vrDisplay = new CardboardVRDisplay({ - MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK, - DEBUG: this.config.DEBUG, - DPDB_URL: this.config.DPDB_URL, - CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED, - K_FILTER: this.config.K_FILTER, - PREDICTION_TIME_S: this.config.PREDICTION_TIME_S, - TOUCH_PANNER_DISABLED: this.config.TOUCH_PANNER_DISABLED, - ROTATE_INSTRUCTIONS_DISABLED: - this.config.ROTATE_INSTRUCTIONS_DISABLED, - YAW_ONLY: this.config.YAW_ONLY, - BUFFER_SCALE: this.config.BUFFER_SCALE, - DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS, - }); - this.polyfillDisplays.push(vrDisplay); - } - this._polyfillDisplaysPopulated = true; - return this.polyfillDisplays; - }; - WebVRPolyfill.prototype.enable = function () { - this.enabled = true; - if (this.hasNative && this.native.VRFrameData) { - var NativeVRFrameData = this.native.VRFrameData; - var nativeFrameData = new this.native.VRFrameData(); - var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData; - window.VRDisplay.prototype.getFrameData = function (frameData) { - if (frameData instanceof NativeVRFrameData) { - nativeGetFrameData.call(this, frameData); - return; - } - nativeGetFrameData.call(this, nativeFrameData); - frameData.pose = nativeFrameData.pose; - copyArray( - nativeFrameData.leftProjectionMatrix, - frameData.leftProjectionMatrix - ); - copyArray( - nativeFrameData.rightProjectionMatrix, - frameData.rightProjectionMatrix - ); - copyArray(nativeFrameData.leftViewMatrix, frameData.leftViewMatrix); - copyArray(nativeFrameData.rightViewMatrix, frameData.rightViewMatrix); - }; - } - navigator.getVRDisplays = this.getVRDisplays.bind(this); - window.VRDisplay = CardboardVRDisplay.VRDisplay; - window.VRFrameData = CardboardVRDisplay.VRFrameData; - }; - WebVRPolyfill.prototype.getVRDisplays = function () { - var _this = this; - var config = this.config; - if (!this.hasNative) { - return Promise.resolve(this.getPolyfillDisplays()); - } - var timeoutId; - var vrDisplaysNative = this.native.getVRDisplays.call(navigator); - var timeoutPromise = new Promise(function (resolve) { - timeoutId = setTimeout(function () { - console.warn( - "Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill." - ); - resolve([]); - }, config.GET_VR_DISPLAYS_TIMEOUT); - }); - return race([vrDisplaysNative, timeoutPromise]).then(function ( - nativeDisplays - ) { - clearTimeout(timeoutId); - return nativeDisplays.length > 0 - ? nativeDisplays - : _this.getPolyfillDisplays(); - }); - }; - WebVRPolyfill.version = version; - WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData; - WebVRPolyfill.VRDisplay = CardboardVRDisplay.VRDisplay; - - var webvrPolyfill = Object.freeze({ - default: WebVRPolyfill, - }); - - var require$$0 = (webvrPolyfill && WebVRPolyfill) || webvrPolyfill; - - if (typeof commonjsGlobal$$1 !== "undefined" && commonjsGlobal$$1.window) { - if (!commonjsGlobal$$1.document) { - commonjsGlobal$$1.document = commonjsGlobal$$1.window.document; - } - if (!commonjsGlobal$$1.navigator) { - commonjsGlobal$$1.navigator = commonjsGlobal$$1.window.navigator; - } - } - var src = require$$0; - - return src; - }); -}); +/*! @name videojs-vr @version 1.8.0 @license Apache-2.0 */ +import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized"; +import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose"; +import window$1 from "global/window"; +import document$1 from "global/document"; +import WebVRPolyfill from "webvr-polyfill"; +import videojs from "video.js"; +import { + Matrix4, + Vector3, + PerspectiveCamera, + Quaternion, + EventDispatcher, + MOUSE, + Spherical, + Vector2, + Euler, + Math as Math$1, + SphereBufferGeometry, + MeshBasicMaterial, + BackSide, + Mesh, + SphereGeometry, + BufferGeometry, + BoxGeometry, + Matrix3, + Scene, + VideoTexture, + LinearFilter, + RGBFormat, + WebGLRenderer, + AudioContext, + ShaderMaterial, +} from "three"; -var WebVRPolyfill = unwrapExports(webvrPolyfill); +var version = "1.8.0"; /** * @author dmarcos / https://github.com/dmarcos @@ -6216,10 +1086,8 @@ var OrbitControls = function (object, domElement) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientWidth); + scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, height - // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight); rotateStart.copy(rotateEnd); @@ -6335,10 +1203,8 @@ var OrbitControls = function (object, domElement) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientWidth); + scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, height - // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight); rotateStart.copy(rotateEnd); @@ -6572,7 +1438,7 @@ var OrbitControls = function (object, domElement) { // - scope.domElement.addEventListener("contextmenu", onContextMenu, false); + //scope.domElement.addEventListener\( 'contextmenu', onContextMenu, false ); scope.domElement.addEventListener("mousedown", onMouseDown, false); scope.domElement.addEventListener("wheel", onMouseWheel, false); @@ -6808,70 +1674,31 @@ var DeviceOrientationControls = function (object) { this.connect(); }; -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; - -var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError( - "Super expression must either be null or a function, not " + - typeof superClass - ); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true, - }, - }); - if (superClass) - Object.setPrototypeOf - ? Object.setPrototypeOf(subClass, superClass) - : (subClass.__proto__ = superClass); -}; - -var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called" - ); - } - - return call && (typeof call === "object" || typeof call === "function") - ? call - : self; -}; - /** * Convert a quaternion to an angle * * Taken from https://stackoverflow.com/a/35448946 * Thanks P. Ellul */ + function Quat2Angle(x, y, z, w) { - var test = x * y + z * w; + var test = x * y + z * w; // singularity at north pole - // singularity at north pole if (test > 0.499) { var _yaw = 2 * Math.atan2(x, w); + var _pitch = Math.PI / 2; - var _roll = 0; + var _roll = 0; return new Vector3(_pitch, _roll, _yaw); - } + } // singularity at south pole - // singularity at south pole if (test < -0.499) { var _yaw2 = -2 * Math.atan2(x, w); + var _pitch2 = -Math.PI / 2; - var _roll2 = 0; + var _roll2 = 0; return new Vector3(_pitch2, _roll2, _yaw2); } @@ -6881,31 +1708,34 @@ function Quat2Angle(x, y, z, w) { var yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz); var pitch = Math.asin(2 * test); var roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz); - return new Vector3(pitch, roll, yaw); } -var OrbitOrientationControls = (function () { +var OrbitOrientationControls = /*#__PURE__*/ (function () { function OrbitOrientationControls(options) { - classCallCheck(this, OrbitOrientationControls); - this.object = options.camera; this.domElement = options.canvas; this.orbit = new OrbitControls(this.object, this.domElement); - this.speed = 0.5; this.orbit.target.set(0, 0, -1); this.orbit.enableZoom = false; this.orbit.enablePan = false; - this.orbit.rotateSpeed = -this.speed; + this.orbit.rotateSpeed = -this.speed; // if orientation is supported - // if orientation is supported if (options.orientation) { this.orientation = new DeviceOrientationControls(this.object); + } // if projection is not full view + // limit the rotation angle in order to not display back half view + + if (options.halfView) { + this.orbit.minAzimuthAngle = -Math.PI / 4; + this.orbit.maxAzimuthAngle = Math.PI / 4; } } - OrbitOrientationControls.prototype.update = function update() { + var _proto = OrbitOrientationControls.prototype; + + _proto.update = function update() { // orientation updates the camera using quaternions and // orbit updates the camera using angles. They are incompatible // and one update overrides the other. So before @@ -6915,11 +1745,9 @@ var OrbitOrientationControls = (function () { // our changes if (this.orientation) { this.orientation.update(); - var quat = this.orientation.object.quaternion; - var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); + var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); // we also have to store the last angle since quaternions are b - // we also have to store the last angle since quaternions are b if (typeof this.lastAngle_ === "undefined") { this.lastAngle_ = currentAngle; } @@ -6936,7 +1764,7 @@ var OrbitOrientationControls = (function () { this.orbit.update(); }; - OrbitOrientationControls.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { this.orbit.dispose(); if (this.orientation) { @@ -6947,27 +1775,27 @@ var OrbitOrientationControls = (function () { return OrbitOrientationControls; })(); -// check if the browser supports cors var corsSupport = (function () { var video = document$1.createElement("video"); - video.crossOrigin = "anonymous"; - return video.hasAttribute("crossorigin"); })(); - var validProjections = [ "360", "360_LR", "360_TB", "360_CUBE", + "EAC", + "EAC_LR", "NONE", "AUTO", "Sphere", "Cube", "equirectangular", + "180", + "180_LR", + "180_MONO", ]; - var getInternalProjectionName = function getInternalProjectionName(projection) { if (!projection) { return; @@ -6994,34 +1822,276 @@ var getInternalProjectionName = function getInternalProjectionName(projection) { } }; -// Add Cardboard button -var Button = videojs.getComponent("Button"); +/** + * This class reacts to interactions with the canvas and + * triggers appropriate functionality on the player. Right now + * it does two things: + * + * 1. A `mousedown`/`touchstart` followed by `touchend`/`mouseup` without any + * `touchmove` or `mousemove` toggles play/pause on the player + * 2. Only moving on/clicking the control bar or toggling play/pause should + * show the control bar. Moving around the scene in the canvas should not. + */ -var CardboardButton = (function (_Button) { - inherits(CardboardButton, _Button); +var CanvasPlayerControls = /*#__PURE__*/ (function (_videojs$EventTarget) { + _inheritsLoose(CanvasPlayerControls, _videojs$EventTarget); - function CardboardButton(player, options) { - classCallCheck(this, CardboardButton); + function CanvasPlayerControls(player, canvas, options) { + var _this; + + _this = _videojs$EventTarget.call(this) || this; + _this.player = player; + _this.canvas = canvas; + _this.options = options; + _this.onMoveEnd = videojs.bind( + _assertThisInitialized(_this), + _this.onMoveEnd + ); + _this.onMoveStart = videojs.bind( + _assertThisInitialized(_this), + _this.onMoveStart + ); + _this.onMove = videojs.bind(_assertThisInitialized(_this), _this.onMove); + _this.onControlBarMove = videojs.bind( + _assertThisInitialized(_this), + _this.onControlBarMove + ); + + _this.player.controlBar.on( + [ + "mousedown", + "mousemove", + "mouseup", + "touchstart", + "touchmove", + "touchend", + ], + _this.onControlBarMove + ); // we have to override these here because + // video.js listens for user activity on the video element + // and makes the user active when the mouse moves. + // We don't want that for 3d videos + + _this.oldReportUserActivity = _this.player.reportUserActivity; + + _this.player.reportUserActivity = function () {}; // canvas movements + + _this.canvas.addEventListener("mousedown", _this.onMoveStart); + + _this.canvas.addEventListener("touchstart", _this.onMoveStart); + + _this.canvas.addEventListener("mousemove", _this.onMove); + + _this.canvas.addEventListener("touchmove", _this.onMove); + + _this.canvas.addEventListener("mouseup", _this.onMoveEnd); + + _this.canvas.addEventListener("touchend", _this.onMoveEnd); + + _this.shouldTogglePlay = false; + return _this; + } + + var _proto = CanvasPlayerControls.prototype; + + _proto.togglePlay = function togglePlay() { + if (this.player.paused()) { + this.player.play(); + } else { + this.player.pause(); + } + }; + + _proto.onMoveStart = function onMoveStart(e) { + // if the player does not have a controlbar or + // the move was a mouse click but not left click do not + // toggle play. + if ( + this.options.disableTogglePlay || + !this.player.controls() || + (e.type === "mousedown" && !videojs.dom.isSingleLeftClick(e)) + ) { + this.shouldTogglePlay = false; + return; + } + + this.shouldTogglePlay = true; + this.touchMoveCount_ = 0; + }; + + _proto.onMoveEnd = function onMoveEnd(e) { + // We want to have the same behavior in VR360 Player and standard player. + // in touchend we want to know if was a touch click, for a click we show the bar, + // otherwise continue with the mouse logic. + // + // Maximum movement allowed during a touch event to still be considered a tap + // Other popular libs use anywhere from 2 (hammer.js) to 15, + // so 10 seems like a nice, round number. + if (e.type === "touchend" && this.touchMoveCount_ < 10) { + if (this.player.userActive() === false) { + this.player.userActive(true); + return; + } + + this.player.userActive(false); + return; + } + + if (!this.shouldTogglePlay) { + return; + } // We want the same behavior in Desktop for VR360 and standard player + + if (e.type == "mouseup") { + this.togglePlay(); + } + }; + + _proto.onMove = function onMove(e) { + // Increase touchMoveCount_ since Android detects 1 - 6 touches when user click normally + this.touchMoveCount_++; + this.shouldTogglePlay = false; + }; + + _proto.onControlBarMove = function onControlBarMove(e) { + this.player.userActive(true); + }; + + _proto.dispose = function dispose() { + this.canvas.removeEventListener("mousedown", this.onMoveStart); + this.canvas.removeEventListener("touchstart", this.onMoveStart); + this.canvas.removeEventListener("mousemove", this.onMove); + this.canvas.removeEventListener("touchmove", this.onMove); + this.canvas.removeEventListener("mouseup", this.onMoveEnd); + this.canvas.removeEventListener("touchend", this.onMoveEnd); + this.player.controlBar.off( + [ + "mousedown", + "mousemove", + "mouseup", + "touchstart", + "touchmove", + "touchend", + ], + this.onControlBarMove + ); + this.player.reportUserActivity = this.oldReportUserActivity; + }; + + return CanvasPlayerControls; +})(videojs.EventTarget); + +/** + * This class manages ambisonic decoding and binaural rendering via Omnitone library. + */ + +var OmnitoneController = /*#__PURE__*/ (function (_videojs$EventTarget) { + _inheritsLoose(OmnitoneController, _videojs$EventTarget); + + /** + * Omnitone controller class. + * + * @class + * @param {AudioContext} audioContext - associated AudioContext. + * @param {Omnitone library} omnitone - Omnitone library element. + * @param {HTMLVideoElement} video - vidoe tag element. + * @param {Object} options - omnitone options. + */ + function OmnitoneController(audioContext, omnitone, video, options) { + var _this; + + _this = _videojs$EventTarget.call(this) || this; + var settings = videojs.mergeOptions( + { + // Safari uses the different AAC decoder than FFMPEG. The channel order is + // The default 4ch AAC channel layout for FFMPEG AAC channel ordering. + channelMap: videojs.browser.IS_SAFARI ? [2, 0, 1, 3] : [0, 1, 2, 3], + ambisonicOrder: 1, + }, + options + ); + _this.videoElementSource = audioContext.createMediaElementSource(video); + _this.foaRenderer = omnitone.createFOARenderer(audioContext, settings); + + _this.foaRenderer.initialize().then( + function () { + if (audioContext.state === "suspended") { + _this.trigger({ + type: "audiocontext-suspended", + }); + } + + _this.videoElementSource.connect(_this.foaRenderer.input); + + _this.foaRenderer.output.connect(audioContext.destination); - var _this = possibleConstructorReturn( - this, - _Button.call(this, player, options) + _this.initialized = true; + + _this.trigger({ + type: "omnitone-ready", + }); + }, + function (error) { + videojs.log.warn( + "videojs-vr: Omnitone initializes failed with the following error: " + + error + + ")" + ); + } ); + return _this; + } + /** + * Updates the rotation of the Omnitone decoder based on three.js camera matrix. + * + * @param {Camera} camera Three.js camera object + */ + + var _proto = OmnitoneController.prototype; + + _proto.update = function update(camera) { + if (!this.initialized) { + return; + } + + this.foaRenderer.setRotationMatrixFromCamera(camera.matrix); + }; + /** + * Destroys the controller and does any necessary cleanup. + */ + + _proto.dispose = function dispose() { + this.initialized = false; + this.foaRenderer.setRenderingMode("bypass"); + this.foaRenderer = null; + }; + + return OmnitoneController; +})(videojs.EventTarget); + +var Button = videojs.getComponent("Button"); + +var CardboardButton = /*#__PURE__*/ (function (_Button) { + _inheritsLoose(CardboardButton, _Button); + + function CardboardButton(player, options) { + var _this; + + _this = _Button.call(this, player, options) || this; _this.handleVrDisplayActivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayActivate_ ); _this.handleVrDisplayDeactivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayDeactivate_ ); _this.handleVrDisplayPresentChange_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayPresentChange_ ); _this.handleOrientationChange_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleOrientationChange_ ); window$1.addEventListener( @@ -7035,20 +2105,18 @@ var CardboardButton = (function (_Button) { window$1.addEventListener( "vrdisplaydeactivate", _this.handleVrDisplayDeactivate_ - ); - - // vrdisplaypresentchange does not fire activate or deactivate + ); // vrdisplaypresentchange does not fire activate or deactivate // and happens when hitting the back button during cardboard mode // so we need to make sure we stay in the correct state by // listening to it and checking if we are presenting it or not + window$1.addEventListener( "vrdisplaypresentchange", _this.handleVrDisplayPresentChange_ - ); - - // we cannot show the cardboard button in fullscreen on + ); // we cannot show the cardboard button in fullscreen on // android as it breaks the controls, and makes it impossible // to exit cardboard mode + if (videojs.browser.IS_ANDROID) { _this.on(player, "fullscreenchange", function () { if (player.isFullscreen()) { @@ -7058,84 +2126,88 @@ var CardboardButton = (function (_Button) { } }); } + return _this; } - CardboardButton.prototype.buildCSSClass = function buildCSSClass() { + var _proto = CardboardButton.prototype; + + _proto.buildCSSClass = function buildCSSClass() { return "vjs-button-vr " + _Button.prototype.buildCSSClass.call(this); }; - CardboardButton.prototype.handleVrDisplayPresentChange_ = + _proto.handleVrDisplayPresentChange_ = function handleVrDisplayPresentChange_() { if (!this.player_.vr().vrDisplay.isPresenting && this.active_) { this.handleVrDisplayDeactivate_(); } + if (this.player_.vr().vrDisplay.isPresenting && !this.active_) { this.handleVrDisplayActivate_(); } }; - CardboardButton.prototype.handleOrientationChange_ = - function handleOrientationChange_() { - if (this.active_ && videojs.browser.IS_IOS) { - this.changeSize_(); - } - }; + _proto.handleOrientationChange_ = function handleOrientationChange_() { + if (this.active_ && videojs.browser.IS_IOS) { + this.changeSize_(); + } + }; - CardboardButton.prototype.changeSize_ = function changeSize_() { + _proto.changeSize_ = function changeSize_() { this.player_.width(window$1.innerWidth); this.player_.height(window$1.innerHeight); window$1.dispatchEvent(new window$1.Event("resize")); }; - CardboardButton.prototype.handleVrDisplayActivate_ = - function handleVrDisplayActivate_() { - // we mimic fullscreen on IOS - if (videojs.browser.IS_IOS) { - this.oldWidth_ = this.player_.currentWidth(); - this.oldHeight_ = this.player_.currentHeight(); - this.player_.enterFullWindow(); - this.changeSize_(); - } + _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { + // we mimic fullscreen on IOS + if (videojs.browser.IS_IOS) { + this.oldWidth_ = this.player_.currentWidth(); + this.oldHeight_ = this.player_.currentHeight(); + this.player_.enterFullWindow(); + this.changeSize_(); + } - this.active_ = true; - }; + this.active_ = true; + }; - CardboardButton.prototype.handleVrDisplayDeactivate_ = - function handleVrDisplayDeactivate_() { - // un-mimic fullscreen on iOS - if (videojs.browser.IS_IOS) { - if (this.oldWidth_) { - this.player_.width(this.oldWidth_); - } - if (this.oldHeight_) { - this.player_.height(this.oldHeight_); - } - this.player_.exitFullWindow(); - window$1.dispatchEvent(new window$1.Event("resize")); + _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { + // un-mimic fullscreen on iOS + if (videojs.browser.IS_IOS) { + if (this.oldWidth_) { + this.player_.width(this.oldWidth_); } - this.active_ = false; - }; + if (this.oldHeight_) { + this.player_.height(this.oldHeight_); + } + + this.player_.exitFullWindow(); + } + + this.active_ = false; + }; - CardboardButton.prototype.handleClick = function handleClick(event) { + _proto.handleClick = function handleClick(event) { // if cardboard mode display is not active, activate it // otherwise deactivate it if (!this.active_) { // This starts playback mode when the cardboard button - // is clicked on Andriod. We need to do this as the controls + // is clicked on Android. We need to do this as the controls // disappear if (!this.player_.hasStarted() && videojs.browser.IS_ANDROID) { this.player_.play(); } + window$1.dispatchEvent(new window$1.Event("vrdisplayactivate")); } else { window$1.dispatchEvent(new window$1.Event("vrdisplaydeactivate")); } }; - CardboardButton.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { _Button.prototype.dispose.call(this); + window$1.removeEventListener( "vrdisplayactivate", this.handleVrDisplayActivate_ @@ -7157,36 +2229,75 @@ videojs.registerComponent("CardboardButton", CardboardButton); var BigPlayButton = videojs.getComponent("BigPlayButton"); -var BigVrPlayButton = (function (_BigPlayButton) { - inherits(BigVrPlayButton, _BigPlayButton); +var BigVrPlayButton = /*#__PURE__*/ (function (_BigPlayButton) { + _inheritsLoose(BigVrPlayButton, _BigPlayButton); function BigVrPlayButton() { - classCallCheck(this, BigVrPlayButton); - return possibleConstructorReturn( - this, - _BigPlayButton.apply(this, arguments) - ); + return _BigPlayButton.apply(this, arguments) || this; } - BigVrPlayButton.prototype.buildCSSClass = function buildCSSClass() { + var _proto = BigVrPlayButton.prototype; + + _proto.buildCSSClass = function buildCSSClass() { return ( "vjs-big-vr-play-button " + _BigPlayButton.prototype.buildCSSClass.call(this) ); }; - return BigVrPlayButton; -})(BigPlayButton); + return BigVrPlayButton; +})(BigPlayButton); + +videojs.registerComponent("BigVrPlayButton", BigVrPlayButton); + +function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = + (typeof Symbol !== "undefined" && o[Symbol.iterator]) || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + if ( + Array.isArray(o) || + (it = _unsupportedIterableToArray(o)) || + (allowArrayLike && o && typeof o.length === "number") + ) { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { done: true }; + return { done: false, value: o[i++] }; + }; + } + throw new TypeError( + "Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." + ); +} + +function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) + return _arrayLikeToArray(o, minLen); +} -videojs.registerComponent("BigVrPlayButton", BigVrPlayButton); +function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) { + arr2[i] = arr[i]; + } + return arr2; +} -// Default options for the plugin. -var defaults$1 = { - projection: "AUTO", - forceCardboard: false, +var defaults = { debug: false, + omnitone: false, + forceCardboard: false, + omnitoneOptions: {}, + projection: "AUTO", + sphereDetail: 32, + disableTogglePlay: false, }; - var errors = { "web-vr-out-of-date": { headline: "360 is out of date", @@ -7207,44 +2318,42 @@ var errors = { "Your browser/device does not support HLS 360 video. See http://webvr.info for assistance.", }, }; - var Plugin = videojs.getPlugin("plugin"); var Component = videojs.getComponent("Component"); -var VR = (function (_Plugin) { - inherits(VR, _Plugin); +var VR = /*#__PURE__*/ (function (_Plugin) { + _inheritsLoose(VR, _Plugin); function VR(player, options) { - classCallCheck(this, VR); - - var settings = videojs.mergeOptions(defaults$1, options); - - var _this = possibleConstructorReturn( - this, - _Plugin.call(this, player, settings) - ); + var _this; + var settings = videojs.mergeOptions(defaults, options); + _this = _Plugin.call(this, player, settings) || this; _this.options_ = settings; _this.player_ = player; _this.bigPlayButtonIndex_ = - player.children().indexOf(player.getChild("BigPlayButton")) || 0; + player.children().indexOf(player.getChild("BigPlayButton")) || 0; // custom videojs-errors integration boolean - // custom videojs-errors integration boolean _this.videojsErrorsSupport_ = !!videojs.errors; if (_this.videojsErrorsSupport_) { - player.errors({ errors: errors }); - } - - // IE 11 does not support enough webgl to be supported + player.errors({ + errors: errors, + }); + } // IE 11 does not support enough webgl to be supported // older safari does not support cors, so it wont work + if (videojs.browser.IE_VERSION || !corsSupport) { // if a player triggers error before 'loadstart' is fired // video.js will reset the error overlay _this.player_.on("loadstart", function () { - _this.triggerError_({ code: "web-vr-not-supported", dismiss: false }); + _this.triggerError_({ + code: "web-vr-not-supported", + dismiss: false, + }); }); - return possibleConstructorReturn(_this); + + return _assertThisInitialized(_this); } _this.polyfill_ = new WebVRPolyfill({ @@ -7252,39 +2361,79 @@ var VR = (function (_Plugin) { ROTATE_INSTRUCTIONS_DISABLED: true, }); _this.polyfill_ = new WebVRPolyfill(); - _this.handleVrDisplayActivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayActivate_ ); _this.handleVrDisplayDeactivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayDeactivate_ ); - _this.handleResize_ = videojs.bind(_this, _this.handleResize_); - _this.animate_ = videojs.bind(_this, _this.animate_); + _this.handleResize_ = videojs.bind( + _assertThisInitialized(_this), + _this.handleResize_ + ); + _this.animate_ = videojs.bind( + _assertThisInitialized(_this), + _this.animate_ + ); + + _this.setProjection(_this.options_.projection); // any time the video element is recycled for ads + // we have to reset the vr state and re-init after ad + + _this.on( + player, + "adstart", + function () { + return player.setTimeout(function () { + // if the video element was recycled for this ad + if (!player.ads || !player.ads.videoElementRecycled()) { + _this.log( + "video element not recycled for this ad, no need to reset" + ); + + return; + } + + _this.log("video element recycled for this ad, reseting"); - _this.setProjection(_this.options_.projection); + _this.reset(); + + _this.one(player, "playing", _this.init); + }); + }, + 1 + ); _this.on(player, "loadedmetadata", _this.init); + return _this; } - VR.prototype.changeProjection_ = function changeProjection_(projection) { - projection = getInternalProjectionName(projection); - // don't change to an invalid projection + var _proto = VR.prototype; + + _proto.changeProjection_ = function changeProjection_(projection) { + var _this2 = this; + + projection = getInternalProjectionName(projection); // don't change to an invalid projection + if (!projection) { projection = "NONE"; } - var position = { x: 0, y: 0, z: 0 }; + var position = { + x: 0, + y: 0, + z: 0, + }; if (this.scene) { this.scene.remove(this.movieScreen); } + if (projection === "AUTO") { // mediainfo cannot be set to auto or we would infinite loop here - // each source should know wether they are 360 or not, if using AUTO + // each source should know whatever they are 360 or not, if using AUTO if ( this.player_.mediainfo && this.player_.mediainfo.projection && @@ -7293,31 +2442,40 @@ var VR = (function (_Plugin) { var autoProjection = getInternalProjectionName( this.player_.mediainfo.projection ); - return this.changeProjection_(autoProjection); } + return this.changeProjection_("NONE"); } else if (projection === "360") { - this.movieGeometry = new SphereBufferGeometry(256, 32, 32); + this.movieGeometry = new SphereBufferGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); this.movieMaterial = new MeshBasicMaterial({ map: this.videoTexture, overdraw: true, side: BackSide, }); - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); this.movieScreen.position.set(position.x, position.y, position.z); - this.movieScreen.scale.x = -1; this.movieScreen.quaternion.setFromAxisAngle( - { x: 0, y: 1, z: 0 }, + { + x: 0, + y: 1, + z: 0, + }, -Math.PI / 2 ); this.scene.add(this.movieScreen); } else if (projection === "360_LR" || projection === "360_TB") { - var geometry = new SphereGeometry(256, 32, 32); - // Left eye view + var geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); var uvs = geometry.faceVertexUvs[0]; for (var i = 0; i < uvs.length; i++) { @@ -7330,7 +2488,6 @@ var VR = (function (_Plugin) { } } } - geometry.scale(-1, 1, 1); this.movieGeometry = new BufferGeometry().fromGeometry(geometry); this.movieMaterial = new MeshBasicMaterial({ @@ -7338,16 +2495,25 @@ var VR = (function (_Plugin) { overdraw: true, side: BackSide, }); - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); - this.movieScreen.rotation.y = -Math.PI / 2; - // display in left eye only - this.movieScreen.layers.set(1); - this.scene.add(this.movieScreen); + this.movieScreen.scale.x = -1; + this.movieScreen.quaternion.setFromAxisAngle( + { + x: 0, + y: 1, + z: 0, + }, + -Math.PI / 2 + ); // display in left eye only - // Right eye view - geometry = new SphereGeometry(256, 32, 32); + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); // Right eye view + geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); uvs = geometry.faceVertexUvs[0]; for (var _i = 0; _i < uvs.length; _i++) { @@ -7360,7 +2526,6 @@ var VR = (function (_Plugin) { } } } - geometry.scale(-1, 1, 1); this.movieGeometry = new BufferGeometry().fromGeometry(geometry); this.movieMaterial = new MeshBasicMaterial({ @@ -7368,10 +2533,17 @@ var VR = (function (_Plugin) { overdraw: true, side: BackSide, }); - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); - this.movieScreen.rotation.y = -Math.PI / 2; - // display in right eye only + this.movieScreen.scale.x = -1; + this.movieScreen.quaternion.setFromAxisAngle( + { + x: 0, + y: 1, + z: 0, + }, + -Math.PI / 2 + ); // display in right eye only + this.movieScreen.layers.set(2); this.scene.add(this.movieScreen); } else if (projection === "360_CUBE") { @@ -7381,7 +2553,6 @@ var VR = (function (_Plugin) { overdraw: true, side: BackSide, }); - var left = [ new Vector2(0, 0.5), new Vector2(0.333, 0.5), @@ -7418,18 +2589,13 @@ var VR = (function (_Plugin) { new Vector2(1, 0.5), new Vector2(0.666, 0.5), ]; - this.movieGeometry.faceVertexUvs[0] = []; - this.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]]; this.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]]; - this.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; this.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; - this.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; this.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; - this.movieGeometry.faceVertexUvs[0][6] = [ bottom[2], bottom[1], @@ -7440,37 +2606,277 @@ var VR = (function (_Plugin) { bottom[0], bottom[3], ]; - this.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]]; this.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]]; - this.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; this.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); this.movieScreen.position.set(position.x, position.y, position.z); this.movieScreen.rotation.y = -Math.PI; + this.scene.add(this.movieScreen); + } else if ( + projection === "180" || + projection === "180_LR" || + projection === "180_MONO" + ) { + var _geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail, + Math.PI, + Math.PI + ); // Left eye view + + _geometry.scale(-1, 1, 1); + + var _uvs = _geometry.faceVertexUvs[0]; + + if (projection !== "180_MONO") { + for (var _i2 = 0; _i2 < _uvs.length; _i2++) { + for (var _j2 = 0; _j2 < 3; _j2++) { + _uvs[_i2][_j2].x *= 0.5; + } + } + } + + this.movieGeometry = new BufferGeometry().fromGeometry(_geometry); + this.movieMaterial = new MeshBasicMaterial({ + map: this.videoTexture, + overdraw: true, + }); + this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in left eye only + + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); // Right eye view + + _geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail, + Math.PI, + Math.PI + ); + + _geometry.scale(-1, 1, 1); + + _uvs = _geometry.faceVertexUvs[0]; + + for (var _i3 = 0; _i3 < _uvs.length; _i3++) { + for (var _j3 = 0; _j3 < 3; _j3++) { + _uvs[_i3][_j3].x *= 0.5; + _uvs[_i3][_j3].x += 0.5; + } + } + + this.movieGeometry = new BufferGeometry().fromGeometry(_geometry); + this.movieMaterial = new MeshBasicMaterial({ + map: this.videoTexture, + overdraw: true, + }); + this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in right eye only + this.movieScreen.layers.set(2); this.scene.add(this.movieScreen); + } else if (projection === "EAC" || projection === "EAC_LR") { + var makeScreen = function makeScreen(mapMatrix, scaleMatrix) { + // "Continuity correction?": because of discontinuous faces and aliasing, + // we truncate the 2-pixel-wide strips on all discontinuous edges, + var contCorrect = 2; + _this2.movieGeometry = new BoxGeometry(256, 256, 256); + _this2.movieMaterial = new ShaderMaterial({ + overdraw: true, + side: BackSide, + uniforms: { + mapped: { + value: _this2.videoTexture, + }, + mapMatrix: { + value: mapMatrix, + }, + contCorrect: { + value: contCorrect, + }, + faceWH: { + value: new Vector2(1 / 3, 1 / 2).applyMatrix3(scaleMatrix), + }, + vidWH: { + value: new Vector2( + _this2.videoTexture.image.videoWidth, + _this2.videoTexture.image.videoHeight + ).applyMatrix3(scaleMatrix), + }, + }, + vertexShader: + "\nvarying vec2 vUv;\nuniform mat3 mapMatrix;\n\nvoid main() {\n vUv = (mapMatrix * vec3(uv, 1.)).xy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);\n}", + fragmentShader: + "\nvarying vec2 vUv;\nuniform sampler2D mapped;\nuniform vec2 faceWH;\nuniform vec2 vidWH;\nuniform float contCorrect;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvoid main() {\n vec2 corner = vUv - mod(vUv, faceWH) + vec2(0, contCorrect / vidWH.y);\n\n vec2 faceWHadj = faceWH - vec2(0, contCorrect * 2. / vidWH.y);\n\n vec2 p = (vUv - corner) / faceWHadj - .5;\n vec2 q = 2. / PI * atan(2. * p) + .5;\n\n vec2 eUv = corner + q * faceWHadj;\n\n gl_FragColor = texture2D(mapped, eUv);\n}", + }); + var right = [ + new Vector2(0, 1 / 2), + new Vector2(1 / 3, 1 / 2), + new Vector2(1 / 3, 1), + new Vector2(0, 1), + ]; + var front = [ + new Vector2(1 / 3, 1 / 2), + new Vector2(2 / 3, 1 / 2), + new Vector2(2 / 3, 1), + new Vector2(1 / 3, 1), + ]; + var left = [ + new Vector2(2 / 3, 1 / 2), + new Vector2(1, 1 / 2), + new Vector2(1, 1), + new Vector2(2 / 3, 1), + ]; + var bottom = [ + new Vector2(1 / 3, 0), + new Vector2(1 / 3, 1 / 2), + new Vector2(0, 1 / 2), + new Vector2(0, 0), + ]; + var back = [ + new Vector2(1 / 3, 1 / 2), + new Vector2(1 / 3, 0), + new Vector2(2 / 3, 0), + new Vector2(2 / 3, 1 / 2), + ]; + var top = [ + new Vector2(1, 0), + new Vector2(1, 1 / 2), + new Vector2(2 / 3, 1 / 2), + new Vector2(2 / 3, 0), + ]; + + for ( + var _i4 = 0, _arr = [right, front, left, bottom, back, top]; + _i4 < _arr.length; + _i4++ + ) { + var face = _arr[_i4]; + var height = _this2.videoTexture.image.videoHeight; + var lowY = 1; + var highY = 0; + + for ( + var _iterator = _createForOfIteratorHelperLoose(face), _step; + !(_step = _iterator()).done; + + ) { + var vector = _step.value; + + if (vector.y < lowY) { + lowY = vector.y; + } + + if (vector.y > highY) { + highY = vector.y; + } + } + + for ( + var _iterator2 = _createForOfIteratorHelperLoose(face), _step2; + !(_step2 = _iterator2()).done; + + ) { + var _vector = _step2.value; + + if (Math.abs(_vector.y - lowY) < Number.EPSILON) { + _vector.y += contCorrect / height; + } + + if (Math.abs(_vector.y - highY) < Number.EPSILON) { + _vector.y -= contCorrect / height; + } + + _vector.x = + (_vector.x / height) * (height - contCorrect * 2) + + contCorrect / height; + } + } + + _this2.movieGeometry.faceVertexUvs[0] = []; + _this2.movieGeometry.faceVertexUvs[0][0] = [ + right[2], + right[1], + right[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][1] = [ + right[1], + right[0], + right[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; + _this2.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; + _this2.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; + _this2.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; + _this2.movieGeometry.faceVertexUvs[0][6] = [ + bottom[2], + bottom[1], + bottom[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][7] = [ + bottom[1], + bottom[0], + bottom[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][8] = [ + front[2], + front[1], + front[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][9] = [ + front[1], + front[0], + front[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; + _this2.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; + _this2.movieScreen = new Mesh( + _this2.movieGeometry, + _this2.movieMaterial + ); + + _this2.movieScreen.position.set(position.x, position.y, position.z); + + _this2.movieScreen.rotation.y = -Math.PI; + return _this2.movieScreen; + }; + + if (projection === "EAC") { + this.scene.add(makeScreen(new Matrix3(), new Matrix3())); + } else { + var scaleMatrix = new Matrix3().set(0, 0.5, 0, 1, 0, 0, 0, 0, 1); + makeScreen( + new Matrix3().set(0, -0.5, 0.5, 1, 0, 0, 0, 0, 1), + scaleMatrix + ); // display in left eye only + + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); + makeScreen( + new Matrix3().set(0, -0.5, 1, 1, 0, 0, 0, 0, 1), + scaleMatrix + ); // display in right eye only + + this.movieScreen.layers.set(2); + this.scene.add(this.movieScreen); + } } this.currentProjection_ = projection; }; - VR.prototype.triggerError_ = function triggerError_(errorObj) { + _proto.triggerError_ = function triggerError_(errorObj) { // if we have videojs-errors use it if (this.videojsErrorsSupport_) { - this.player_.error(errorObj); - // if we don't have videojs-errors just use a normal player error + this.player_.error(errorObj); // if we don't have videojs-errors just use a normal player error } else { // strip any html content from the error message // as it is not supported outside of videojs-errors var div = document$1.createElement("div"); - div.innerHTML = errors[errorObj.code].message; - var message = div.textContent || div.innerText || ""; - this.player_.error({ code: errorObj.code, message: message, @@ -7478,13 +2884,13 @@ var VR = (function (_Plugin) { } }; - VR.prototype.log = function log() { + _proto.log = function log() { if (!this.options_.debug) { return; } for ( - var _len = arguments.length, msgs = Array(_len), _key = 0; + var _len = arguments.length, msgs = new Array(_len), _key = 0; _key < _len; _key++ ) { @@ -7492,28 +2898,33 @@ var VR = (function (_Plugin) { } msgs.forEach(function (msg) { - videojs.log(msg); + videojs.log("VR: ", msg); }); }; - VR.prototype.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { - var _this2 = this; + _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { + var _this3 = this; if (!this.vrDisplay) { return; } + this.vrDisplay - .requestPresent([{ source: this.renderedCanvas }]) + .requestPresent([ + { + source: this.renderedCanvas, + }, + ]) .then(function () { - if (!_this2.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { + if (!_this3.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { return; - } - - // webvr-polyfill/cardboard ui only watches for click events + } // webvr-polyfill/cardboard ui only watches for click events // to tell that the back arrow button is pressed during cardboard vr. // but somewhere along the line these events are silenced with preventDefault // but only on iOS, so we translate them ourselves here + var touches = []; + var iosCardboardTouchStart_ = function iosCardboardTouchStart_(e) { for (var i = 0; i < e.touches.length; i++) { touches.push(e.touches[i]); @@ -7533,63 +2944,66 @@ var VR = (function (_Plugin) { clientY: t.clientY, }); - _this2.renderedCanvas.dispatchEvent(simulatedClick); + _this3.renderedCanvas.dispatchEvent(simulatedClick); }); - touches = []; }; - _this2.renderedCanvas.addEventListener( + _this3.renderedCanvas.addEventListener( "touchstart", iosCardboardTouchStart_ ); - _this2.renderedCanvas.addEventListener( + + _this3.renderedCanvas.addEventListener( "touchend", iosCardboardTouchEnd_ ); - _this2.iosRevertTouchToClick_ = function () { - _this2.renderedCanvas.removeEventListener( + _this3.iosRevertTouchToClick_ = function () { + _this3.renderedCanvas.removeEventListener( "touchstart", iosCardboardTouchStart_ ); - _this2.renderedCanvas.removeEventListener( + + _this3.renderedCanvas.removeEventListener( "touchend", iosCardboardTouchEnd_ ); - _this2.iosRevertTouchToClick_ = null; + + _this3.iosRevertTouchToClick_ = null; }; }); }; - VR.prototype.handleVrDisplayDeactivate_ = - function handleVrDisplayDeactivate_() { - if (!this.vrDisplay || !this.vrDisplay.isPresenting) { - return; - } - if (this.iosRevertTouchToClick_) { - this.iosRevertTouchToClick_(); - } - this.vrDisplay.exitPresent(); - }; + _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { + if (!this.vrDisplay || !this.vrDisplay.isPresenting) { + return; + } + + if (this.iosRevertTouchToClick_) { + this.iosRevertTouchToClick_(); + } + + this.vrDisplay.exitPresent(); + }; - VR.prototype.requestAnimationFrame = function requestAnimationFrame(fn) { + _proto.requestAnimationFrame = function requestAnimationFrame(fn) { if (this.vrDisplay) { return this.vrDisplay.requestAnimationFrame(fn); } - return Component.prototype.requestAnimationFrame.call(this, fn); + return this.player_.requestAnimationFrame(fn); }; - VR.prototype.cancelAnimationFrame = function cancelAnimationFrame(id) { + _proto.cancelAnimationFrame = function cancelAnimationFrame(id) { if (this.vrDisplay) { return this.vrDisplay.cancelAnimationFrame(id); } - return Component.prototype.cancelAnimationFrame.call(this, id); + return this.player_.cancelAnimationFrame(id); }; - VR.prototype.togglePlay_ = function togglePlay_() { + _proto.togglePlay_ = function togglePlay_() { if (this.player_.paused()) { this.player_.play(); } else { @@ -7597,10 +3011,11 @@ var VR = (function (_Plugin) { } }; - VR.prototype.animate_ = function animate_() { + _proto.animate_ = function animate_() { if (!this.initialized_) { return; } + if (this.getVideoEl_().readyState === this.getVideoEl_().HAVE_ENOUGH_DATA) { if (this.videoTexture) { this.videoTexture.needsUpdate = true; @@ -7608,6 +3023,11 @@ var VR = (function (_Plugin) { } this.controls3d.update(); + + if (this.omniController) { + this.omniController.update(this.camera); + } + this.effect.render(this.scene, this.camera); if (window$1.navigator.getGamepads) { @@ -7615,10 +3035,9 @@ var VR = (function (_Plugin) { var gamepads = window$1.navigator.getGamepads(); for (var i = 0; i < gamepads.length; ++i) { - var gamepad = gamepads[i]; - - // Make sure gamepad is defined + var gamepad = gamepads[i]; // Make sure gamepad is defined // Only take input if state has changed since we checked last + if ( !gamepad || !gamepad.timestamp || @@ -7626,6 +3045,7 @@ var VR = (function (_Plugin) { ) { continue; } + for (var j = 0; j < gamepad.buttons.length; ++j) { if (gamepad.buttons[j].pressed) { this.togglePlay_(); @@ -7635,21 +3055,20 @@ var VR = (function (_Plugin) { } } } - this.camera.getWorldDirection(this.cameraVector); + this.camera.getWorldDirection(this.cameraVector); this.animationFrameId_ = this.requestAnimationFrame(this.animate_); }; - VR.prototype.handleResize_ = function handleResize_() { + _proto.handleResize_ = function handleResize_() { var width = this.player_.currentWidth(); var height = this.player_.currentHeight(); - this.effect.setSize(width, height, false); this.camera.aspect = width / height; this.camera.updateProjectionMatrix(); }; - VR.prototype.setProjection = function setProjection(projection) { + _proto.setProjection = function setProjection(projection) { if (!getInternalProjectionName(projection)) { videojs.log.error( "videojs-vr: please pass a valid projection " + @@ -7662,38 +3081,39 @@ var VR = (function (_Plugin) { this.defaultProjection_ = projection; }; - VR.prototype.init = function init() { - var _this3 = this; + _proto.init = function init() { + var _this4 = this; this.reset(); - this.camera = new PerspectiveCamera( 75, this.player_.currentWidth() / this.player_.currentHeight(), 1, 1000 - ); - // Store vector representing the direction in which the camera is looking, in world space. + ); // Store vector representing the direction in which the camera is looking, in world space. + this.cameraVector = new Vector3(); if ( this.currentProjection_ === "360_LR" || - this.currentProjection_ === "360_TB" + this.currentProjection_ === "360_TB" || + this.currentProjection_ === "180" || + this.currentProjection_ === "180_LR" || + this.currentProjection_ === "180_MONO" || + this.currentProjection_ === "EAC_LR" ) { // Render left eye when not in VR mode this.camera.layers.enable(1); } this.scene = new Scene(); - this.videoTexture = new VideoTexture(this.getVideoEl_()); - - // shared regardless of wether VideoTexture is used or + this.videoTexture = new VideoTexture(this.getVideoEl_()); // shared regardless of wether VideoTexture is used or // an image canvas is used + this.videoTexture.generateMipmaps = false; this.videoTexture.minFilter = LinearFilter; this.videoTexture.magFilter = LinearFilter; this.videoTexture.format = RGBFormat; - this.changeProjection_(this.currentProjection_); if (this.currentProjection_ === "NONE") { @@ -7704,19 +3124,21 @@ var VR = (function (_Plugin) { this.player_.removeChild("BigPlayButton"); this.player_.addChild("BigVrPlayButton", {}, this.bigPlayButtonIndex_); - this.player_.bigPlayButton = this.player_.getChild("BigVrPlayButton"); + this.player_.bigPlayButton = this.player_.getChild("BigVrPlayButton"); // mobile devices, or cardboard forced to on - // mobile devices, or cardboard forced to on if ( this.options_.forceCardboard || videojs.browser.IS_ANDROID || videojs.browser.IS_IOS ) { this.addCardboardButton_(); - } + } // if ios remove full screen toggle - // if ios remove full screen toggle - if (videojs.browser.IS_IOS) { + if ( + videojs.browser.IS_IOS && + this.player_.controlBar && + this.player_.controlBar.fullscreenToggle + ) { this.player_.controlBar.fullscreenToggle.hide(); } @@ -7727,29 +3149,31 @@ var VR = (function (_Plugin) { clearColor: 0xffffff, antialias: true, }); - var webglContext = this.renderer.getContext("webgl"); var oldTexImage2D = webglContext.texImage2D; - /* this is a workaround since threejs uses try catch */ - webglContext.texImage2D = function () { - for ( - var _len2 = arguments.length, args = Array(_len2), _key2 = 0; - _key2 < _len2; - _key2++ - ) { - args[_key2] = arguments[_key2]; - } + webglContext.texImage2D = function () { try { + for ( + var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; + _key2 < _len2; + _key2++ + ) { + args[_key2] = arguments[_key2]; + } + return oldTexImage2D.apply(webglContext, args); } catch (e) { - _this3.reset(); - _this3.player_.pause(); - _this3.triggerError_({ + _this4.reset(); + + _this4.player_.pause(); + + _this4.triggerError_({ code: "web-vr-hls-cors-not-supported", dismiss: false, }); + throw new Error(e); } }; @@ -7760,64 +3184,101 @@ var VR = (function (_Plugin) { false ); this.effect = new VREffect(this.renderer); - this.effect.setSize( this.player_.currentWidth(), this.player_.currentHeight(), false ); - this.vrDisplay = null; + this.vrDisplay = null; // Previous timestamps for gamepad updates - // Previous timestamps for gamepad updates this.prevTimestamps_ = []; - this.renderedCanvas = this.renderer.domElement; this.renderedCanvas.setAttribute( "style", "width: 100%; height: 100%; position: absolute; top:0;" ); + var videoElStyle = this.getVideoEl_().style; this.player_ .el() .insertBefore(this.renderedCanvas, this.player_.el().firstChild); - this.getVideoEl_().style.display = "none"; + videoElStyle.zIndex = "-1"; + videoElStyle.opacity = "0"; if (window$1.navigator.getVRDisplays) { - this.log("VR is supported, getting vr displays"); + this.log("is supported, getting vr displays"); window$1.navigator.getVRDisplays().then(function (displays) { if (displays.length > 0) { - _this3.log("VR Displays found", displays); - _this3.vrDisplay = displays[0]; + _this4.log("Displays found", displays); - // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive + _this4.vrDisplay = displays[0]; // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive // also need the cardboard button to enter fully immersive mode // so, we want to add the button if we're not polyfilled. - if (!_this3.vrDisplay.isPolyfilled) { - _this3.log("Real HMD found using VRControls", _this3.vrDisplay); - _this3.addCardboardButton_(); - // We use VRControls here since we are working with an HMD + if (!_this4.vrDisplay.isPolyfilled) { + _this4.log("Real HMD found using VRControls", _this4.vrDisplay); + + _this4.addCardboardButton_(); // We use VRControls here since we are working with an HMD // and we only want orientation controls. - _this3.controls3d = new VRControls(_this3.camera); + + _this4.controls3d = new VRControls(_this4.camera); } } - if (!_this3.controls3d) { - _this3.log("no HMD found Using Orbit & Orientation Controls"); - _this3.controls3d = new OrbitOrientationControls({ - camera: _this3.camera, - canvas: _this3.renderedCanvas, + if (!_this4.controls3d) { + _this4.log("no HMD found Using Orbit & Orientation Controls"); + + var options = { + camera: _this4.camera, + canvas: _this4.renderedCanvas, + // check if its a half sphere view projection + halfView: _this4.currentProjection_.indexOf("180") === 0, orientation: videojs.browser.IS_IOS || videojs.browser.IS_ANDROID || false, - }); + }; + + if (_this4.options_.motionControls === false) { + options.orientation = false; + } + + _this4.controls3d = new OrbitOrientationControls(options); + _this4.canvasPlayerControls = new CanvasPlayerControls( + _this4.player_, + _this4.renderedCanvas, + _this4.options_ + ); } - _this3.animationFrameId_ = _this3.requestAnimationFrame( - _this3.animate_ + + _this4.animationFrameId_ = _this4.requestAnimationFrame( + _this4.animate_ ); }); } else if (window$1.navigator.getVRDevices) { - this.triggerError_({ code: "web-vr-out-of-date", dismiss: false }); + this.triggerError_({ + code: "web-vr-out-of-date", + dismiss: false, + }); } else { - this.triggerError_({ code: "web-vr-not-supported", dismiss: false }); + this.triggerError_({ + code: "web-vr-not-supported", + dismiss: false, + }); + } + + if (this.options_.omnitone) { + var audiocontext = AudioContext.getContext(); + this.omniController = new OmnitoneController( + audiocontext, + this.options_.omnitone, + this.getVideoEl_(), + this.options_.omnitoneOptions + ); + this.omniController.one("audiocontext-suspended", function () { + _this4.player.pause(); + + _this4.player.one("playing", function () { + audiocontext.resume(); + }); + }); } this.on(this.player_, "fullscreenchange", this.handleResize_); @@ -7837,78 +3298,93 @@ var VR = (function (_Plugin) { this.handleVrDisplayDeactivate_, true ); - this.initialized_ = true; + this.trigger("initialized"); }; - VR.prototype.addCardboardButton_ = function addCardboardButton_() { + _proto.addCardboardButton_ = function addCardboardButton_() { if (!this.player_.controlBar.getChild("CardboardButton")) { this.player_.controlBar.addChild("CardboardButton", {}); } }; - VR.prototype.getVideoEl_ = function getVideoEl_() { + _proto.getVideoEl_ = function getVideoEl_() { return this.player_.el().getElementsByTagName("video")[0]; }; - VR.prototype.reset = function reset() { + _proto.reset = function reset() { if (!this.initialized_) { return; } + if (this.omniController) { + this.omniController.off("audiocontext-suspended"); + this.omniController.dispose(); + this.omniController = undefined; + } + if (this.controls3d) { this.controls3d.dispose(); + this.controls3d = null; + } + + if (this.canvasPlayerControls) { + this.canvasPlayerControls.dispose(); + this.canvasPlayerControls = null; } + if (this.effect) { this.effect.dispose(); + this.effect = null; } - window$1.removeEventListener("resize", this.handleResize_); - window$1.removeEventListener("vrdisplaypresentchange", this.handleResize_); + window$1.removeEventListener("resize", this.handleResize_, true); + window$1.removeEventListener( + "vrdisplaypresentchange", + this.handleResize_, + true + ); window$1.removeEventListener( "vrdisplayactivate", - this.handleVrDisplayActivate_ + this.handleVrDisplayActivate_, + true ); window$1.removeEventListener( "vrdisplaydeactivate", - this.handleVrDisplayDeactivate_ - ); + this.handleVrDisplayDeactivate_, + true + ); // re-add the big play button to player - // re-add the big play button to player if (!this.player_.getChild("BigPlayButton")) { this.player_.addChild("BigPlayButton", {}, this.bigPlayButtonIndex_); } if (this.player_.getChild("BigVrPlayButton")) { this.player_.removeChild("BigVrPlayButton"); - } + } // remove the cardboard button - // remove the cardboard button if (this.player_.getChild("CardboardButton")) { this.player_.controlBar.removeChild("CardboardButton"); - } + } // show the fullscreen again - // show the fullscreen again - if (videojs.browser.IS_IOS) { + if ( + videojs.browser.IS_IOS && + this.player_.controlBar && + this.player_.controlBar.fullscreenToggle + ) { this.player_.controlBar.fullscreenToggle.show(); - } + } // reset the video element style so that it will be displayed - // reset the video element style so that it will be displayed - this.getVideoEl_().style.display = ""; + var videoElStyle = this.getVideoEl_().style; + videoElStyle.zIndex = ""; + videoElStyle.opacity = ""; // set the current projection to the default - // set the current projection to the default - this.currentProjection_ = this.defaultProjection_; - - if (this.observer_) { - this.observer_.disconnect(); - } + this.currentProjection_ = this.defaultProjection_; // reset the ios touch to click workaround - // reset the ios touch to click workaround if (this.iosRevertTouchToClick_) { this.iosRevertTouchToClick_(); - } + } // remove the old canvas - // remove the old canvas if (this.renderedCanvas) { this.renderedCanvas.parentNode.removeChild(this.renderedCanvas); } @@ -7920,12 +3396,13 @@ var VR = (function (_Plugin) { this.initialized_ = false; }; - VR.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { _Plugin.prototype.dispose.call(this); + this.reset(); }; - VR.prototype.polyfillVersion = function polyfillVersion() { + _proto.polyfillVersion = function polyfillVersion() { return WebVRPolyfill.version; }; @@ -7934,9 +3411,7 @@ var VR = (function (_Plugin) { VR.prototype.setTimeout = Component.prototype.setTimeout; VR.prototype.clearTimeout = Component.prototype.clearTimeout; - VR.VERSION = version; - videojs.registerPlugin("vr", VR); export default VR; diff --git a/pod/main/static/videojs-vr/videojs-vr.js b/pod/main/static/videojs-vr/videojs-vr.js index 0270709caf..33b46ddf54 100644 --- a/pod/main/static/videojs-vr/videojs-vr.js +++ b/pod/main/static/videojs-vr/videojs-vr.js @@ -1,25 +1,37 @@ -/** - * videojs-vr - * @version 1.3.0 - * @copyright 2018 [object Object] - * @license Apache-2.0 - */ +/*! @name videojs-vr @version 1.8.0 @license Apache-2.0 */ (function (global, factory) { typeof exports === "object" && typeof module !== "undefined" - ? (module.exports = factory(require("video.js"))) + ? (module.exports = factory( + require("global/window"), + require("global/document"), + require("video.js") + )) : typeof define === "function" && define.amd - ? define(["video.js"], factory) - : (global.videojsVr = factory(global.videojs)); -})(this, function (videojs) { + ? define(["global/window", "global/document", "video.js"], factory) + : ((global = global || self), + (global.videojsVr = factory( + global.window, + global.document, + global.videojs + ))); +})(this, function (window$1, document$1, videojs) { "use strict"; + window$1 = + window$1 && window$1.hasOwnProperty("default") + ? window$1["default"] + : window$1; + document$1 = + document$1 && document$1.hasOwnProperty("default") + ? document$1["default"] + : document$1; videojs = videojs && videojs.hasOwnProperty("default") ? videojs["default"] : videojs; - var version = "1.3.0"; - var commonjsGlobal = - typeof window !== "undefined" + typeof globalThis !== "undefined" + ? globalThis + : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global @@ -41,48 +53,60 @@ ); } - var win; - - if (typeof window !== "undefined") { - win = window; - } else if (typeof commonjsGlobal !== "undefined") { - win = commonjsGlobal; - } else if (typeof self !== "undefined") { - win = self; - } else { - win = {}; - } - - var window_1 = win; + var assertThisInitialized = createCommonjsModule(function (module) { + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" + ); + } - var empty = {}; + return self; + } - var empty$1 = /*#__PURE__*/ Object.freeze({ - default: empty, + module.exports = _assertThisInitialized; + (module.exports["default"] = module.exports), + (module.exports.__esModule = true); }); - var minDoc = (empty$1 && empty) || empty$1; + var _assertThisInitialized = unwrapExports(assertThisInitialized); - var topLevel = - typeof commonjsGlobal !== "undefined" - ? commonjsGlobal - : typeof window !== "undefined" - ? window - : {}; + var setPrototypeOf = createCommonjsModule(function (module) { + function _setPrototypeOf(o, p) { + module.exports = _setPrototypeOf = + Object.setPrototypeOf || + function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + (module.exports["default"] = module.exports), + (module.exports.__esModule = true); + return _setPrototypeOf(o, p); + } - var doccy; + module.exports = _setPrototypeOf; + (module.exports["default"] = module.exports), + (module.exports.__esModule = true); + }); - if (typeof document !== "undefined") { - doccy = document; - } else { - doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; + unwrapExports(setPrototypeOf); - if (!doccy) { - doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; + var inheritsLoose = createCommonjsModule(function (module) { + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + setPrototypeOf(subClass, superClass); } - } - var document_1 = doccy; + module.exports = _inheritsLoose; + (module.exports["default"] = module.exports), + (module.exports.__esModule = true); + }); + + var _inheritsLoose = unwrapExports(inheritsLoose); + + var version = "1.8.0"; var webvrPolyfill = createCommonjsModule(function (module, exports) { /** @@ -187,7 +211,7 @@ (function (global, factory) { module.exports = factory(); })(commonjsGlobal, function () { - var commonjsGlobal$$1 = + var commonjsGlobal$1 = typeof window !== "undefined" ? window : typeof commonjsGlobal !== "undefined" @@ -196,7 +220,7 @@ ? self : {}; - function unwrapExports$$1(x) { + function unwrapExports(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") @@ -204,23 +228,12 @@ : x; } - function createCommonjsModule$$1(fn, module) { + function createCommonjsModule(fn, module) { return ( (module = { exports: {} }), fn(module, module.exports), module.exports ); } - var race = function race(promises) { - if (Promise.race) { - return Promise.race(promises); - } - return new Promise(function (resolve, reject) { - for (var i = 0; i < promises.length; i++) { - promises[i].then(resolve, reject); - } - }); - }; - var isMobile = function isMobile() { return ( /Android/i.test(navigator.userAgent) || @@ -241,10 +254,7 @@ return dest; }; - var cardboardVrDisplay = createCommonjsModule$$1(function ( - module, - exports - ) { + var cardboardVrDisplay = createCommonjsModule(function (module, exports) { /** * @license * cardboard-vr-display @@ -325,7 +335,7 @@ */ (function (global, factory) { module.exports = factory(); - })(commonjsGlobal$$1, function () { + })(commonjsGlobal$1, function () { var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); @@ -389,8 +399,8 @@ })(); var MIN_TIMESTEP = 0.001; var MAX_TIMESTEP = 1; - var base64 = function base64(mimeType, _base) { - return "data:" + mimeType + ";base64," + _base; + var dataUri = function dataUri(mimeType, svg) { + return "data:" + mimeType + "," + encodeURIComponent(svg); }; var lerp = function lerp(a, b, t) { return a + (b - a) * t; @@ -433,6 +443,16 @@ return value; }; })(); + var isSafariWithoutDeviceMotion = (function () { + var value = false; + value = + isIOS() && + isSafari() && + navigator.userAgent.indexOf("13_4") !== -1; + return function () { + return value; + }; + })(); var isChromeWithoutDeviceMotion = (function () { var value = false; if (getChromeVersion() === 65) { @@ -1058,6 +1078,7 @@ this.bufferScale = bufferScale; this.dirtySubmitFrameBindings = dirtySubmitFrameBindings; this.ctxAttribs = gl.getContextAttributes(); + this.instanceExt = gl.getExtension("ANGLE_instanced_arrays"); this.meshWidth = 20; this.meshHeight = 20; this.bufferWidth = gl.drawingBufferWidth; @@ -1446,6 +1467,18 @@ } glPreserveState(gl, glState, function (gl) { self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); + var positionDivisor = 0; + var texCoordDivisor = 0; + if (self.instanceExt) { + positionDivisor = gl.getVertexAttrib( + self.attribs.position, + self.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE + ); + texCoordDivisor = gl.getVertexAttrib( + self.attribs.texCoord, + self.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE + ); + } if (self.cullFace) { self.realDisable.call(gl, gl.CULL_FACE); } @@ -1494,6 +1527,20 @@ 20, 8 ); + if (self.instanceExt) { + if (positionDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE( + self.attribs.position, + 0 + ); + } + if (texCoordDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE( + self.attribs.texCoord, + 0 + ); + } + } gl.activeTexture(gl.TEXTURE0); gl.uniform1i(self.uniforms.diffuse, 0); gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); @@ -1549,6 +1596,20 @@ ) { self.realClearColor.apply(gl, self.clearColor); } + if (self.instanceExt) { + if (positionDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE( + self.attribs.position, + positionDivisor + ); + } + if (texCoordDivisor != 0) { + self.instanceExt.vertexAttribDivisorANGLE( + self.attribs.texCoord, + texCoordDivisor + ); + } + } }); if (isIOS()) { var canvas = gl.canvas; @@ -2227,12 +2288,16 @@ ], }), }; - function DeviceInfo(deviceParams) { + function DeviceInfo(deviceParams, additionalViewers) { this.viewer = Viewers.CardboardV2; this.updateDeviceParams(deviceParams); this.distortion = new Distortion( this.viewer.distortionCoefficients ); + for (var i = 0; i < additionalViewers.length; i++) { + var viewer = additionalViewers[i]; + Viewers[viewer.id] = new CardboardViewer(viewer); + } } DeviceInfo.prototype.updateDeviceParams = function (deviceParams) { this.device = this.determineDevice_(deviceParams) || this.device; @@ -2473,7 +2538,7 @@ } DeviceInfo.Viewers = Viewers; var format = 1; - var last_updated = "2018-02-20T22:55:10Z"; + var last_updated = "2019-11-09T17:36:14Z"; var devices = [ { type: "android", @@ -2482,6 +2547,20 @@ bw: 3, ac: 500, }, + { + type: "android", + rules: [{ mdmh: "asus/*/ASUS_X00PD/*" }, { ua: "ASUS_X00PD" }], + dpi: 245, + bw: 3, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "asus/*/ASUS_X008D/*" }, { ua: "ASUS_X008D" }], + dpi: 282, + bw: 3, + ac: 500, + }, { type: "android", rules: [{ mdmh: "asus/*/ASUS_Z00AD/*" }, { ua: "ASUS_Z00AD" }], @@ -2489,6 +2568,20 @@ bw: 3, ac: 1000, }, + { + type: "android", + rules: [{ mdmh: "Google/*/Pixel 2 XL/*" }, { ua: "Pixel 2 XL" }], + dpi: 537.9, + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "Google/*/Pixel 3 XL/*" }, { ua: "Pixel 3 XL" }], + dpi: [558.5, 553.8], + bw: 3, + ac: 1000, + }, { type: "android", rules: [{ mdmh: "Google/*/Pixel XL/*" }, { ua: "Pixel XL" }], @@ -2496,6 +2589,20 @@ bw: 3, ac: 1000, }, + { + type: "android", + rules: [{ mdmh: "Google/*/Pixel 3/*" }, { ua: "Pixel 3" }], + dpi: 442.4, + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "Google/*/Pixel 2/*" }, { ua: "Pixel 2" }], + dpi: 441, + bw: 3, + ac: 500, + }, { type: "android", rules: [{ mdmh: "Google/*/Pixel/*" }, { ua: "Pixel" }], @@ -2552,6 +2659,20 @@ bw: 3, ac: 1000, }, + { + type: "android", + rules: [{ mdmh: "Huawei/*/BLN-L24/*" }, { ua: "HONORBLN-L24" }], + dpi: 480, + bw: 4, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "Huawei/*/BKL-L09/*" }, { ua: "BKL-L09" }], + dpi: 403, + bw: 3.47, + ac: 500, + }, { type: "android", rules: [ @@ -2771,6 +2892,20 @@ bw: 3, ac: 1000, }, + { + type: "android", + rules: [{ mdmh: "OnePlus/*/ONE E1001/*" }, { ua: "ONE E1001" }], + dpi: [442.4, 441.4], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "OnePlus/*/ONE E1003/*" }, { ua: "ONE E1003" }], + dpi: [442.4, 441.4], + bw: 3, + ac: 1000, + }, { type: "android", rules: [{ mdmh: "OnePlus/*/ONE E1005/*" }, { ua: "ONE E1005" }], @@ -2778,6 +2913,20 @@ bw: 3, ac: 1000, }, + { + type: "android", + rules: [{ mdmh: "OnePlus/*/ONE A2001/*" }, { ua: "ONE A2001" }], + dpi: [391.9, 405.4], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "OnePlus/*/ONE A2003/*" }, { ua: "ONE A2003" }], + dpi: [391.9, 405.4], + bw: 3, + ac: 1000, + }, { type: "android", rules: [{ mdmh: "OnePlus/*/ONE A2005/*" }, { ua: "ONE A2005" }], @@ -2785,6 +2934,36 @@ bw: 3, ac: 1000, }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A3000/*" }, + { ua: "ONEPLUS A3000" }, + ], + dpi: 401, + bw: 3, + ac: 500, + }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A3003/*" }, + { ua: "ONEPLUS A3003" }, + ], + dpi: 401, + bw: 3, + ac: 500, + }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A3010/*" }, + { ua: "ONEPLUS A3010" }, + ], + dpi: 401, + bw: 3, + ac: 500, + }, { type: "android", rules: [ @@ -2805,6 +2984,46 @@ bw: 2, ac: 1000, }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A6000/*" }, + { ua: "ONEPLUS A6000" }, + ], + dpi: 401, + bw: 3, + ac: 500, + }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A6003/*" }, + { ua: "ONEPLUS A6003" }, + ], + dpi: 401, + bw: 3, + ac: 500, + }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A6010/*" }, + { ua: "ONEPLUS A6010" }, + ], + dpi: 401, + bw: 2, + ac: 500, + }, + { + type: "android", + rules: [ + { mdmh: "OnePlus/*/ONEPLUS A6013/*" }, + { ua: "ONEPLUS A6013" }, + ], + dpi: 401, + bw: 2, + ac: 500, + }, { type: "android", rules: [{ mdmh: "OPPO/*/X909/*" }, { ua: "X909" }], @@ -3101,6 +3320,76 @@ bw: 3, ac: 500, }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G955F/*" }, { ua: "SM-G955F" }], + dpi: [522.514, 525.762], + bw: 3, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G960F/*" }, { ua: "SM-G960F" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G9600/*" }, { ua: "SM-G9600" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G960T/*" }, { ua: "SM-G960T" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G960N/*" }, { ua: "SM-G960N" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G960U/*" }, { ua: "SM-G960U" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G9608/*" }, { ua: "SM-G9608" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G960FD/*" }, { ua: "SM-G960FD" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G960W/*" }, { ua: "SM-G960W" }], + dpi: [569.575, 571.5], + bw: 3, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G965F/*" }, { ua: "SM-G965F" }], + dpi: 529, + bw: 2, + ac: 1000, + }, { type: "android", rules: [{ mdmh: "Sony/*/C6903/*" }, { ua: "C6903" }], @@ -3216,6 +3505,69 @@ bw: 4, ac: 1000, }, + { + type: "android", + rules: [{ mdmh: "Huawei/*/EML-L29/*" }, { ua: "EML-L29" }], + dpi: 428, + bw: 3.45, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "Nokia/*/Nokia 7.1/*" }, { ua: "Nokia 7.1" }], + dpi: [432, 431.9], + bw: 3, + ac: 500, + }, + { + type: "ios", + rules: [{ res: [1242, 2688] }], + dpi: 458, + bw: 4, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G570M/*" }, { ua: "SM-G570M" }], + dpi: 320, + bw: 3.684, + ac: 1000, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G970F/*" }, { ua: "SM-G970F" }], + dpi: 438, + bw: 2.281, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G973F/*" }, { ua: "SM-G973F" }], + dpi: 550, + bw: 2.002, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G975F/*" }, { ua: "SM-G975F" }], + dpi: 522, + bw: 2.054, + ac: 500, + }, + { + type: "android", + rules: [{ mdmh: "samsung/*/SM-G977F/*" }, { ua: "SM-G977F" }], + dpi: 505, + bw: 2.334, + ac: 500, + }, + { + type: "ios", + rules: [{ res: [828, 1792] }], + dpi: 326, + bw: 5, + ac: 500, + }, ]; var DPDB_CACHE = { format: format, @@ -3292,7 +3644,7 @@ var matched = false; for (var j = 0; j < device.rules.length; j++) { var rule = device.rules[j]; - if (this.matchRule_(rule, userAgent, width, height)) { + if (this.ruleMatches_(rule, userAgent, width, height)) { matched = true; break; } @@ -3309,13 +3661,15 @@ console.warn("No DPDB device match."); return null; }; - Dpdb.prototype.matchRule_ = function ( + Dpdb.prototype.ruleMatches_ = function ( rule, ua, screenWidth, screenHeight ) { if (!rule.ua && !rule.res) return false; + if (rule.ua && rule.ua.substring(0, 2) === "SM") + rule.ua = rule.ua.substring(0, 7); if (rule.ua && ua.indexOf(rule.ua) < 0) return false; if (rule.res) { if (!rule.res[0] || !rule.res[1]) return false; @@ -3507,7 +3861,8 @@ var chromeVersion = getChromeVersion(); this.isDeviceMotionInRadians = !this.isIOS && chromeVersion && chromeVersion < 66; - this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion(); + this.isWithoutDeviceMotion = + isChromeWithoutDeviceMotion() || isSafariWithoutDeviceMotion(); this.filterToWorldQ = new Quaternion(); if (isIOS()) { this.filterToWorldQ.setFromAxisAngle( @@ -3652,16 +4007,18 @@ return; } this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z); - if (isR7()) { - this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma); - } else { - this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); - } - if (!this.isDeviceMotionInRadians) { - this.gyroscope.multiplyScalar(Math.PI / 180); + if (rotRate) { + if (isR7()) { + this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma); + } else { + this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); + } + if (!this.isDeviceMotionInRadians) { + this.gyroscope.multiplyScalar(Math.PI / 180); + } + this.filter.addGyroMeasurement(this.gyroscope, timestampS); } this.filter.addAccelMeasurement(this.accelerometer, timestampS); - this.filter.addGyroMeasurement(this.gyroscope, timestampS); this.previousTimestampS = timestampS; }; FusionPoseSensor.prototype.onOrientationChange_ = function ( @@ -3747,18 +4104,6 @@ var SENSOR_FREQUENCY = 60; var X_AXIS = new Vector3(1, 0, 0); var Z_AXIS = new Vector3(0, 0, 1); - var orientation = {}; - if (screen.orientation) { - orientation = screen.orientation; - } else if (screen.msOrientation) { - orientation = screen.msOrientation; - } else { - Object.defineProperty(orientation, "angle", { - get: function get$$1() { - return window.orientation || 0; - }, - }); - } var SENSOR_TO_VR = new Quaternion(); SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2); SENSOR_TO_VR.multiply( @@ -3774,12 +4119,9 @@ this.api = null; this.errors = []; this._sensorQ = new Quaternion(); - this._worldToScreenQ = new Quaternion(); this._outQ = new Quaternion(); this._onSensorRead = this._onSensorRead.bind(this); this._onSensorError = this._onSensorError.bind(this); - this._onOrientationChange = this._onOrientationChange.bind(this); - this._onOrientationChange(); this.init(); } createClass(PoseSensor, [ @@ -3790,6 +4132,7 @@ try { sensor = new RelativeOrientationSensor({ frequency: SENSOR_FREQUENCY, + referenceFrame: "screen", }); sensor.addEventListener("error", this._onSensorError); } catch (error) { @@ -3815,10 +4158,6 @@ this.sensor.addEventListener("reading", this._onSensorRead); this.sensor.start(); } - window.addEventListener( - "orientationchange", - this._onOrientationChange - ); }, }, { @@ -3831,6 +4170,17 @@ this.config.YAW_ONLY, this.config.DEBUG ); + if (this.sensor) { + this.sensor.removeEventListener( + "reading", + this._onSensorRead + ); + this.sensor.removeEventListener( + "error", + this._onSensorError + ); + this.sensor = null; + } }, }, { @@ -3849,7 +4199,6 @@ var out = this._outQ; out.copy(SENSOR_TO_VR); out.multiply(this._sensorQ); - out.multiply(this._worldToScreenQ); if (this.config.YAW_ONLY) { out.x = out.z = 0; out.normalize(); @@ -3872,24 +4221,18 @@ } else { console.error(event.error); } + this.useDeviceMotion(); }, }, { key: "_onSensorRead", value: function _onSensorRead() {}, }, - { - key: "_onOrientationChange", - value: function _onOrientationChange() { - var angle = (-orientation.angle * Math.PI) / 180; - this._worldToScreenQ.setFromAxisAngle(Z_AXIS, angle); - }, - }, ]); return PoseSensor; })(); var rotateInstructionsAsset = - "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyBDNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCBDMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE5LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEMxMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4yMTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzLDE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE5Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSBMNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiBMMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2LDY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+"; + ""; function RotateInstructions() { this.loadIcon_(); var overlay = document.createElement("div"); @@ -3994,19 +4337,19 @@ } }; RotateInstructions.prototype.loadIcon_ = function () { - this.icon = base64("image/svg+xml", rotateInstructionsAsset); + this.icon = dataUri("image/svg+xml", rotateInstructionsAsset); }; var DEFAULT_VIEWER = "CardboardV1"; var VIEWER_KEY = "WEBVR_CARDBOARD_VIEWER"; var CLASS_NAME = "webvr-polyfill-viewer-selector"; - function ViewerSelector() { + function ViewerSelector(defaultViewer) { try { this.selectedKey = localStorage.getItem(VIEWER_KEY); } catch (error) { console.error("Failed to load viewer profile: %s", error); } if (!this.selectedKey) { - this.selectedKey = DEFAULT_VIEWER; + this.selectedKey = defaultViewer || DEFAULT_VIEWER; } this.dialog = this.createDialog_(DeviceInfo.Viewers); this.root = null; @@ -4144,13 +4487,17 @@ var commonjsGlobal$$1 = typeof window !== "undefined" ? window - : typeof commonjsGlobal$$1 !== "undefined" - ? commonjsGlobal$$1 + : typeof commonjsGlobal$1 !== "undefined" + ? commonjsGlobal$1 : typeof self !== "undefined" ? self : {}; function unwrapExports$$1(x) { - return x && x.__esModule ? x["default"] : x; + return x && + x.__esModule && + Object.prototype.hasOwnProperty.call(x, "default") + ? x["default"] + : x; } function createCommonjsModule$$1(fn, module) { return ( @@ -4822,6 +5169,8 @@ return null; }; var config = { + ADDITIONAL_VIEWERS: [], + DEFAULT_VIEWER: "", MOBILE_WAKE_LOCK: true, DEBUG: false, DPDB_URL: "https://dpdb.webvr.rocks/dpdb.json", @@ -4861,8 +5210,11 @@ this.config.DPDB_URL, this.onDeviceParamsUpdated_.bind(this) ); - this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams()); - this.viewerSelector_ = new ViewerSelector(); + this.deviceInfo_ = new DeviceInfo( + this.dpdb_.getDeviceParams(), + config$$1.ADDITIONAL_VIEWERS + ); + this.viewerSelector_ = new ViewerSelector(config$$1.DEFAULT_VIEWER); this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)); this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()); if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) { @@ -5054,7 +5406,10 @@ this.updateBounds_(); this.distorter_.submitFrame(); } else if (this.cardboardUI_ && this.layer_) { - var canvas = this.layer_.source.getContext("webgl").canvas; + var gl = this.layer_.source.getContext("webgl"); + if (!gl) gl = this.layer_.source.getContext("experimental-webgl"); + if (!gl) gl = this.layer_.source.getContext("webgl2"); + var canvas = gl.canvas; if ( canvas.width != this.lastWidth || canvas.height != this.lastHeight @@ -5076,6 +5431,8 @@ CardboardVRDisplay.prototype.onResize_ = function (e) { if (this.layer_) { var gl = this.layer_.source.getContext("webgl"); + if (!gl) gl = this.layer_.source.getContext("experimental-webgl"); + if (!gl) gl = this.layer_.source.getContext("webgl2"); var cssProperties = [ "position: absolute", "top: 0", @@ -5113,19 +5470,19 @@ return CardboardVRDisplay; }); }); - var CardboardVRDisplay = unwrapExports$$1(cardboardVrDisplay); + var CardboardVRDisplay = unwrapExports(cardboardVrDisplay); - var version = "0.10.5"; + var version = "0.10.12"; var DefaultConfig = { + ADDITIONAL_VIEWERS: [], + DEFAULT_VIEWER: "", PROVIDE_MOBILE_VRDISPLAY: true, - GET_VR_DISPLAYS_TIMEOUT: 1000, MOBILE_WAKE_LOCK: true, DEBUG: false, DPDB_URL: "https://dpdb.webvr.rocks/dpdb.json", K_FILTER: 0.98, PREDICTION_TIME_S: 0.04, - TOUCH_PANNER_DISABLED: true, CARDBOARD_UI_DISABLED: false, ROTATE_INSTRUCTIONS_DISABLED: false, YAW_ONLY: false, @@ -5160,13 +5517,14 @@ } if (isMobile()) { var vrDisplay = new CardboardVRDisplay({ + ADDITIONAL_VIEWERS: this.config.ADDITIONAL_VIEWERS, + DEFAULT_VIEWER: this.config.DEFAULT_VIEWER, MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK, DEBUG: this.config.DEBUG, DPDB_URL: this.config.DPDB_URL, CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED, K_FILTER: this.config.K_FILTER, PREDICTION_TIME_S: this.config.PREDICTION_TIME_S, - TOUCH_PANNER_DISABLED: this.config.TOUCH_PANNER_DISABLED, ROTATE_INSTRUCTIONS_DISABLED: this.config.ROTATE_INSTRUCTIONS_DISABLED, YAW_ONLY: this.config.YAW_ONLY, @@ -5217,24 +5575,13 @@ if (!this.hasNative) { return Promise.resolve(this.getPolyfillDisplays()); } - var timeoutId; - var vrDisplaysNative = this.native.getVRDisplays.call(navigator); - var timeoutPromise = new Promise(function (resolve) { - timeoutId = setTimeout(function () { - console.warn( - "Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill." - ); - resolve([]); - }, config.GET_VR_DISPLAYS_TIMEOUT); - }); - return race([vrDisplaysNative, timeoutPromise]).then(function ( - nativeDisplays - ) { - clearTimeout(timeoutId); - return nativeDisplays.length > 0 - ? nativeDisplays - : _this.getPolyfillDisplays(); - }); + return this.native.getVRDisplays + .call(navigator) + .then(function (nativeDisplays) { + return nativeDisplays.length > 0 + ? nativeDisplays + : _this.getPolyfillDisplays(); + }); }; WebVRPolyfill.version = version; WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData; @@ -5246,15 +5593,12 @@ var require$$0 = (webvrPolyfill && WebVRPolyfill) || webvrPolyfill; - if ( - typeof commonjsGlobal$$1 !== "undefined" && - commonjsGlobal$$1.window - ) { - if (!commonjsGlobal$$1.document) { - commonjsGlobal$$1.document = commonjsGlobal$$1.window.document; + if (typeof commonjsGlobal$1 !== "undefined" && commonjsGlobal$1.window) { + if (!commonjsGlobal$1.document) { + commonjsGlobal$1.document = commonjsGlobal$1.window.document; } - if (!commonjsGlobal$$1.navigator) { - commonjsGlobal$$1.navigator = commonjsGlobal$$1.window.navigator; + if (!commonjsGlobal$1.navigator) { + commonjsGlobal$1.navigator = commonjsGlobal$1.window.navigator; } } var src = require$$0; @@ -5399,7 +5743,7 @@ }, }); - var REVISION = "92"; + var REVISION = "93"; var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; var CullFaceNone = 0; var CullFaceBack = 1; @@ -6196,6 +6540,8 @@ var v1 = new Vector3(); return function extractRotation(m) { + // this method does not support reflection matrices + var te = this.elements; var me = m.elements; @@ -6206,14 +6552,22 @@ te[0] = me[0] * scaleX; te[1] = me[1] * scaleX; te[2] = me[2] * scaleX; + te[3] = 0; te[4] = me[4] * scaleY; te[5] = me[5] * scaleY; te[6] = me[6] * scaleY; + te[7] = 0; te[8] = me[8] * scaleZ; te[9] = me[9] * scaleZ; te[10] = me[10] * scaleZ; + te[11] = 0; + + te[12] = 0; + te[13] = 0; + te[14] = 0; + te[15] = 1; return this; }; @@ -6342,12 +6696,12 @@ te[10] = bd * f + ac; } - // last column + // bottom row te[3] = 0; te[7] = 0; te[11] = 0; - // bottom row + // last column te[12] = 0; te[13] = 0; te[14] = 0; @@ -6356,51 +6710,14 @@ return this; }, - makeRotationFromQuaternion: function (q) { - var te = this.elements; + makeRotationFromQuaternion: (function () { + var zero = new Vector3(0, 0, 0); + var one = new Vector3(1, 1, 1); - var x = q._x, - y = q._y, - z = q._z, - w = q._w; - var x2 = x + x, - y2 = y + y, - z2 = z + z; - var xx = x * x2, - xy = x * y2, - xz = x * z2; - var yy = y * y2, - yz = y * z2, - zz = z * z2; - var wx = w * x2, - wy = w * y2, - wz = w * z2; - - te[0] = 1 - (yy + zz); - te[4] = xy - wz; - te[8] = xz + wy; - - te[1] = xy + wz; - te[5] = 1 - (xx + zz); - te[9] = yz - wx; - - te[2] = xz - wy; - te[6] = yz + wx; - te[10] = 1 - (xx + yy); - - // last column - te[3] = 0; - te[7] = 0; - te[11] = 0; - - // bottom row - te[12] = 0; - te[13] = 0; - te[14] = 0; - te[15] = 1; - - return this; - }, + return function makeRotationFromQuaternion(q) { + return this.compose(zero, q, one); + }; + })(), lookAt: (function () { var x = new Vector3(); @@ -6946,9 +7263,48 @@ }, compose: function (position, quaternion, scale) { - this.makeRotationFromQuaternion(quaternion); - this.scale(scale); - this.setPosition(position); + var te = this.elements; + + var x = quaternion._x, + y = quaternion._y, + z = quaternion._z, + w = quaternion._w; + var x2 = x + x, + y2 = y + y, + z2 = z + z; + var xx = x * x2, + xy = x * y2, + xz = x * z2; + var yy = y * y2, + yz = y * z2, + zz = z * z2; + var wx = w * x2, + wy = w * y2, + wz = w * z2; + + var sx = scale.x, + sy = scale.y, + sz = scale.z; + + te[0] = (1 - (yy + zz)) * sx; + te[1] = (xy + wz) * sx; + te[2] = (xz - wy) * sx; + te[3] = 0; + + te[4] = (xy - wz) * sy; + te[5] = (1 - (xx + zz)) * sy; + te[6] = (yz + wx) * sy; + te[7] = 0; + + te[8] = (xz + wy) * sz; + te[9] = (yz - wx) * sz; + te[10] = (1 - (xx + yy)) * sz; + te[11] = 0; + + te[12] = position.x; + te[13] = position.y; + te[14] = position.z; + te[15] = 1; return this; }, @@ -9445,10 +9801,10 @@ */ /* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers - */ + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers + */ function WebGLRenderTarget(width, height, options) { this.width = width; this.height = height; @@ -9475,6 +9831,9 @@ options.encoding ); + this.texture.generateMipmaps = + options.generateMipmaps !== undefined ? options.generateMipmaps : true; + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; this.stencilBuffer = @@ -10082,37 +10441,46 @@ return this; }, - applyMatrix4: (function () { - var points = [ - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - ]; - - return function applyMatrix4(matrix) { - // transform of empty box is an empty box. - if (this.isEmpty()) return this; - - // NOTE: I am using a binary pattern to specify all 2^3 combinations below - points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix); // 000 - points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix); // 001 - points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix); // 010 - points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix); // 011 - points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix); // 100 - points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix); // 101 - points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix); // 110 - points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix); // 111 - - this.setFromPoints(points); + applyMatrix4: function (matrix) { + // transform of empty box is an empty box. + if (this.isEmpty()) return this; + + var m = matrix.elements; + + var xax = m[0] * this.min.x, + xay = m[1] * this.min.x, + xaz = m[2] * this.min.x; + var xbx = m[0] * this.max.x, + xby = m[1] * this.max.x, + xbz = m[2] * this.max.x; + var yax = m[4] * this.min.y, + yay = m[5] * this.min.y, + yaz = m[6] * this.min.y; + var ybx = m[4] * this.max.y, + yby = m[5] * this.max.y, + ybz = m[6] * this.max.y; + var zax = m[8] * this.min.z, + zay = m[9] * this.min.z, + zaz = m[10] * this.min.z; + var zbx = m[8] * this.max.z, + zby = m[9] * this.max.z, + zbz = m[10] * this.max.z; + + this.min.x = + Math.min(xax, xbx) + Math.min(yax, ybx) + Math.min(zax, zbx) + m[12]; + this.min.y = + Math.min(xay, xby) + Math.min(yay, yby) + Math.min(zay, zby) + m[13]; + this.min.z = + Math.min(xaz, xbz) + Math.min(yaz, ybz) + Math.min(zaz, zbz) + m[14]; + this.max.x = + Math.max(xax, xbx) + Math.max(yax, ybx) + Math.max(zax, zbx) + m[12]; + this.max.y = + Math.max(xay, xby) + Math.max(yay, yby) + Math.max(zay, zby) + m[13]; + this.max.z = + Math.max(xaz, xbz) + Math.max(yaz, ybz) + Math.max(zaz, zbz) + m[14]; - return this; - }; - })(), + return this; + }, translate: function (offset) { this.min.add(offset); @@ -10639,7 +11007,7 @@ "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; var bumpmap_pars_fragment = - "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n"; + "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n"; var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n"; @@ -10796,7 +11164,7 @@ "#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; var normalmap_pars_fragment = - "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\t\tscale *= float( gl_FrontFacing ) * 2.0 - 1.0;\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; + "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy *= normalScale;\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; @@ -10937,10 +11305,10 @@ "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; var points_frag = - "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var points_vert = - "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n"; @@ -11506,22 +11874,14 @@ return this; }, - convertGammaToLinear: function () { - var r = this.r, - g = this.g, - b = this.b; - - this.r = r * r; - this.g = g * g; - this.b = b * b; + convertGammaToLinear: function (gammaFactor) { + this.copyGammaToLinear(this, gammaFactor); return this; }, - convertLinearToGamma: function () { - this.r = Math.sqrt(this.r); - this.g = Math.sqrt(this.g); - this.b = Math.sqrt(this.b); + convertLinearToGamma: function (gammaFactor) { + this.copyLinearToGamma(this, gammaFactor); return this; }, @@ -12005,8 +12365,8 @@ }, /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ + // Cube map shader + ------------------------------------------------------------------------- */ cube: { uniforms: { @@ -12071,6 +12431,47 @@ fragmentShader: ShaderChunk.meshphysical_frag, }; + /** + * @author mrdoob / http://mrdoob.com/ + */ + + function WebGLAnimation() { + var context = null; + var isAnimating = false; + var animationLoop = null; + + function onAnimationFrame(time, frame) { + if (isAnimating === false) return; + + animationLoop(time, frame); + + context.requestAnimationFrame(onAnimationFrame); + } + + return { + start: function () { + if (isAnimating === true) return; + if (animationLoop === null) return; + + context.requestAnimationFrame(onAnimationFrame); + + isAnimating = true; + }, + + stop: function () { + isAnimating = false; + }, + + setAnimationLoop: function (callback) { + animationLoop = callback; + }, + + setContext: function (value) { + context = value; + }, + }; + } + /** * @author mrdoob / http://mrdoob.com/ */ @@ -14350,28 +14751,28 @@ clone: function () { /* - // Handle primitives + // Handle primitives - var parameters = this.parameters; + var parameters = this.parameters; - if ( parameters !== undefined ) { + if ( parameters !== undefined ) { - var values = []; + var values = []; - for ( var key in parameters ) { + for ( var key in parameters ) { - values.push( parameters[ key ] ); + values.push( parameters[ key ] ); - } + } - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + var geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; - } + } - return new this.constructor().copy( this ); - */ + return new this.constructor().copy( this ); + */ return new Geometry().copy(this); }, @@ -15027,6 +15428,12 @@ // + if (faces.length === 0) { + console.error( + "THREE.DirectGeometry: Faceless geometries are not supported." + ); + } + for (var i = 0; i < faces.length; i++) { var face = faces[i]; @@ -15185,6 +15592,8 @@ this.boundingSphere = null; this.drawRange = { start: 0, count: Infinity }; + + this.userData = {}; } BufferGeometry.prototype = Object.assign( @@ -15219,12 +15628,10 @@ "THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )." ); - this.addAttribute( + return this.addAttribute( name, new BufferAttribute(arguments[1], arguments[2]) ); - - return; } if (name === "index") { @@ -15233,7 +15640,7 @@ ); this.setIndex(attribute); - return; + return this; } this.attributes[name] = attribute; @@ -15958,6 +16365,8 @@ data.uuid = this.uuid; data.type = this.type; if (this.name !== "") data.name = this.name; + if (Object.keys(this.userData).length > 0) + data.userData = this.userData; if (this.parameters !== undefined) { var parameters = this.parameters; @@ -16017,28 +16426,28 @@ clone: function () { /* - // Handle primitives + // Handle primitives - var parameters = this.parameters; + var parameters = this.parameters; - if ( parameters !== undefined ) { + if ( parameters !== undefined ) { - var values = []; + var values = []; - for ( var key in parameters ) { + for ( var key in parameters ) { - values.push( parameters[ key ] ); + values.push( parameters[ key ] ); - } + } - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + var geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; - } + } - return new this.constructor().copy( this ); - */ + return new this.constructor().copy( this ); + */ return new BufferGeometry().copy(this); }, @@ -16121,6 +16530,10 @@ this.drawRange.start = source.drawRange.start; this.drawRange.count = source.drawRange.count; + // user data + + this.userData = source.userData; + return this; }, @@ -16700,19 +17113,28 @@ data.alphaMap = this.alphaMap.toJSON(meta).uuid; if (this.lightMap && this.lightMap.isTexture) data.lightMap = this.lightMap.toJSON(meta).uuid; + + if (this.aoMap && this.aoMap.isTexture) { + data.aoMap = this.aoMap.toJSON(meta).uuid; + data.aoMapIntensity = this.aoMapIntensity; + } + if (this.bumpMap && this.bumpMap.isTexture) { data.bumpMap = this.bumpMap.toJSON(meta).uuid; data.bumpScale = this.bumpScale; } + if (this.normalMap && this.normalMap.isTexture) { data.normalMap = this.normalMap.toJSON(meta).uuid; data.normalScale = this.normalScale.toArray(); } + if (this.displacementMap && this.displacementMap.isTexture) { data.displacementMap = this.displacementMap.toJSON(meta).uuid; data.displacementScale = this.displacementScale; data.displacementBias = this.displacementBias; } + if (this.roughnessMap && this.roughnessMap.isTexture) data.roughnessMap = this.roughnessMap.toJSON(meta).uuid; if (this.metalnessMap && this.metalnessMap.isTexture) @@ -18090,7 +18512,6 @@ Triangle.getNormal(vA, vB, vC, face.normal); intersection.face = face; - intersection.faceIndex = a; } return intersection; @@ -18152,7 +18573,7 @@ ); if (intersection) { - intersection.faceIndex = Math.floor(i / 3); // triangle number in indices buffer semantics + intersection.faceIndex = Math.floor(i / 3); // triangle number in indexed buffer semantics intersects.push(intersection); } } @@ -18175,7 +18596,10 @@ c ); - if (intersection) intersects.push(intersection); + if (intersection) { + intersection.faceIndex = Math.floor(i / 3); // triangle number in non-indexed buffer semantics + intersects.push(intersection); + } } } } else if (geometry.isGeometry) { @@ -18286,7 +18710,7 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLBackground(renderer, state, geometries, premultipliedAlpha) { + function WebGLBackground(renderer, state, objects, premultipliedAlpha) { var clearColor = new Color(0x000000); var clearAlpha = 0; @@ -18333,7 +18757,7 @@ this.matrixWorld.copyPosition(camera.matrixWorld); }; - geometries.update(boxMesh.geometry); + objects.update(boxMesh); } boxMesh.material.uniforms.tCube.value = background; @@ -18352,7 +18776,7 @@ }) ); - geometries.update(planeMesh.geometry); + objects.update(planeMesh); } planeMesh.material.map = background; @@ -18427,25 +18851,12 @@ return; } - var position = geometry.attributes.position; - - if (position.isInterleavedBufferAttribute) { - count = position.data.count; - - extension.drawArraysInstancedANGLE( - mode, - 0, - count, - geometry.maxInstancedCount - ); - } else { - extension.drawArraysInstancedANGLE( - mode, - start, - count, - geometry.maxInstancedCount - ); - } + extension.drawArraysInstancedANGLE( + mode, + start, + count, + geometry.maxInstancedCount + ); info.update(count, mode, geometry.maxInstancedCount); } @@ -19281,6 +19692,7 @@ var mat4array = new Float32Array(16); var mat3array = new Float32Array(9); + var mat2array = new Float32Array(4); // Flattening for arrays of vectors and matrices @@ -19311,6 +19723,22 @@ return r; } + function arraysEqual(a, b) { + if (a.length !== b.length) return false; + + for (var i = 0, l = a.length; i < l; i++) { + if (a[i] !== b[i]) return false; + } + + return true; + } + + function copyArray(a, b) { + for (var i = 0, l = b.length; i < l; i++) { + a[i] = b[i]; + } + } + // Texture unit allocation function allocTexUnits(renderer, n) { @@ -19334,91 +19762,221 @@ // Single scalar function setValue1f(gl, v) { + var cache = this.cache; + + if (cache[0] === v) return; + gl.uniform1f(this.addr, v); + + cache[0] = v; } function setValue1i(gl, v) { + var cache = this.cache; + + if (cache[0] === v) return; + gl.uniform1i(this.addr, v); + + cache[0] = v; } // Single float vector (from flat array or THREE.VectorN) function setValue2fv(gl, v) { - if (v.x === undefined) { - gl.uniform2fv(this.addr, v); + var cache = this.cache; + + if (v.x !== undefined) { + if (cache[0] !== v.x || cache[1] !== v.y) { + gl.uniform2f(this.addr, v.x, v.y); + + cache[0] = v.x; + cache[1] = v.y; + } } else { - gl.uniform2f(this.addr, v.x, v.y); + if (arraysEqual(cache, v)) return; + + gl.uniform2fv(this.addr, v); + + copyArray(cache, v); } } function setValue3fv(gl, v) { + var cache = this.cache; + if (v.x !== undefined) { - gl.uniform3f(this.addr, v.x, v.y, v.z); + if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z) { + gl.uniform3f(this.addr, v.x, v.y, v.z); + + cache[0] = v.x; + cache[1] = v.y; + cache[2] = v.z; + } } else if (v.r !== undefined) { - gl.uniform3f(this.addr, v.r, v.g, v.b); + if (cache[0] !== v.r || cache[1] !== v.g || cache[2] !== v.b) { + gl.uniform3f(this.addr, v.r, v.g, v.b); + + cache[0] = v.r; + cache[1] = v.g; + cache[2] = v.b; + } } else { + if (arraysEqual(cache, v)) return; + gl.uniform3fv(this.addr, v); + + copyArray(cache, v); } } function setValue4fv(gl, v) { - if (v.x === undefined) { - gl.uniform4fv(this.addr, v); + var cache = this.cache; + + if (v.x !== undefined) { + if ( + cache[0] !== v.x || + cache[1] !== v.y || + cache[2] !== v.z || + cache[3] !== v.w + ) { + gl.uniform4f(this.addr, v.x, v.y, v.z, v.w); + + cache[0] = v.x; + cache[1] = v.y; + cache[2] = v.z; + cache[3] = v.w; + } } else { - gl.uniform4f(this.addr, v.x, v.y, v.z, v.w); + if (arraysEqual(cache, v)) return; + + gl.uniform4fv(this.addr, v); + + copyArray(cache, v); } } // Single matrix (from flat array or MatrixN) function setValue2fm(gl, v) { - gl.uniformMatrix2fv(this.addr, false, v.elements || v); + var cache = this.cache; + var elements = v.elements; + + if (elements === undefined) { + if (arraysEqual(cache, v)) return; + + gl.uniformMatrix2fv(this.addr, false, v); + + copyArray(cache, v); + } else { + if (arraysEqual(cache, elements)) return; + + mat2array.set(elements); + + gl.uniformMatrix2fv(this.addr, false, mat2array); + + copyArray(cache, elements); + } } function setValue3fm(gl, v) { - if (v.elements === undefined) { + var cache = this.cache; + var elements = v.elements; + + if (elements === undefined) { + if (arraysEqual(cache, v)) return; + gl.uniformMatrix3fv(this.addr, false, v); + + copyArray(cache, v); } else { - mat3array.set(v.elements); + if (arraysEqual(cache, elements)) return; + + mat3array.set(elements); + gl.uniformMatrix3fv(this.addr, false, mat3array); + + copyArray(cache, elements); } } function setValue4fm(gl, v) { - if (v.elements === undefined) { + var cache = this.cache; + var elements = v.elements; + + if (elements === undefined) { + if (arraysEqual(cache, v)) return; + gl.uniformMatrix4fv(this.addr, false, v); + + copyArray(cache, v); } else { - mat4array.set(v.elements); + if (arraysEqual(cache, elements)) return; + + mat4array.set(elements); + gl.uniformMatrix4fv(this.addr, false, mat4array); + + copyArray(cache, elements); } } // Single texture (2D / Cube) function setValueT1(gl, v, renderer) { + var cache = this.cache; var unit = renderer.allocTextureUnit(); - gl.uniform1i(this.addr, unit); + + if (cache[0] !== unit) { + gl.uniform1i(this.addr, unit); + cache[0] = unit; + } + renderer.setTexture2D(v || emptyTexture, unit); } function setValueT6(gl, v, renderer) { + var cache = this.cache; var unit = renderer.allocTextureUnit(); - gl.uniform1i(this.addr, unit); + + if (cache[0] !== unit) { + gl.uniform1i(this.addr, unit); + cache[0] = unit; + } + renderer.setTextureCube(v || emptyCubeTexture, unit); } // Integer / Boolean vectors or arrays thereof (always flat arrays) function setValue2iv(gl, v) { + var cache = this.cache; + + if (arraysEqual(cache, v)) return; + gl.uniform2iv(this.addr, v); + + copyArray(cache, v); } function setValue3iv(gl, v) { + var cache = this.cache; + + if (arraysEqual(cache, v)) return; + gl.uniform3iv(this.addr, v); + + copyArray(cache, v); } function setValue4iv(gl, v) { + var cache = this.cache; + + if (arraysEqual(cache, v)) return; + gl.uniform4iv(this.addr, v); + + copyArray(cache, v); } // Helper to pick the right setter for the singular case @@ -19465,47 +20023,106 @@ // Array of scalars function setValue1fv(gl, v) { + var cache = this.cache; + + if (arraysEqual(cache, v)) return; + gl.uniform1fv(this.addr, v); + + copyArray(cache, v); } function setValue1iv(gl, v) { + var cache = this.cache; + + if (arraysEqual(cache, v)) return; + gl.uniform1iv(this.addr, v); + + copyArray(cache, v); } // Array of vectors (flat or from THREE classes) function setValueV2a(gl, v) { - gl.uniform2fv(this.addr, flatten(v, this.size, 2)); + var cache = this.cache; + var data = flatten(v, this.size, 2); + + if (arraysEqual(cache, data)) return; + + gl.uniform2fv(this.addr, data); + + this.updateCache(data); } function setValueV3a(gl, v) { - gl.uniform3fv(this.addr, flatten(v, this.size, 3)); + var cache = this.cache; + var data = flatten(v, this.size, 3); + + if (arraysEqual(cache, data)) return; + + gl.uniform3fv(this.addr, data); + + this.updateCache(data); } function setValueV4a(gl, v) { - gl.uniform4fv(this.addr, flatten(v, this.size, 4)); + var cache = this.cache; + var data = flatten(v, this.size, 4); + + if (arraysEqual(cache, data)) return; + + gl.uniform4fv(this.addr, data); + + this.updateCache(data); } // Array of matrices (flat or from THREE clases) function setValueM2a(gl, v) { - gl.uniformMatrix2fv(this.addr, false, flatten(v, this.size, 4)); + var cache = this.cache; + var data = flatten(v, this.size, 4); + + if (arraysEqual(cache, data)) return; + + gl.uniformMatrix2fv(this.addr, false, data); + + this.updateCache(data); } function setValueM3a(gl, v) { - gl.uniformMatrix3fv(this.addr, false, flatten(v, this.size, 9)); + var cache = this.cache; + var data = flatten(v, this.size, 9); + + if (arraysEqual(cache, data)) return; + + gl.uniformMatrix3fv(this.addr, false, data); + + this.updateCache(data); } function setValueM4a(gl, v) { - gl.uniformMatrix4fv(this.addr, false, flatten(v, this.size, 16)); + var cache = this.cache; + var data = flatten(v, this.size, 16); + + if (arraysEqual(cache, data)) return; + + gl.uniformMatrix4fv(this.addr, false, data); + + this.updateCache(data); } // Array of textures (2D / Cube) function setValueT1a(gl, v, renderer) { - var n = v.length, - units = allocTexUnits(renderer, n); + var cache = this.cache; + var n = v.length; - gl.uniform1iv(this.addr, units); + var units = allocTexUnits(renderer, n); + + if (arraysEqual(cache, units) === false) { + gl.uniform1iv(this.addr, units); + copyArray(cache, units); + } for (var i = 0; i !== n; ++i) { renderer.setTexture2D(v[i] || emptyTexture, units[i]); @@ -19513,10 +20130,15 @@ } function setValueT6a(gl, v, renderer) { - var n = v.length, - units = allocTexUnits(renderer, n); + var cache = this.cache; + var n = v.length; - gl.uniform1iv(this.addr, units); + var units = allocTexUnits(renderer, n); + + if (arraysEqual(cache, units) === false) { + gl.uniform1iv(this.addr, units); + copyArray(cache, units); + } for (var i = 0; i !== n; ++i) { renderer.setTextureCube(v[i] || emptyCubeTexture, units[i]); @@ -19568,6 +20190,7 @@ function SingleUniform(id, activeInfo, addr) { this.id = id; this.addr = addr; + this.cache = []; this.setValue = getSingularSetter(activeInfo.type); // this.path = activeInfo.name; // DEBUG @@ -19576,12 +20199,23 @@ function PureArrayUniform(id, activeInfo, addr) { this.id = id; this.addr = addr; + this.cache = []; this.size = activeInfo.size; this.setValue = getPureArraySetter(activeInfo.type); // this.path = activeInfo.name; // DEBUG } + PureArrayUniform.prototype.updateCache = function (data) { + var cache = this.cache; + + if (data instanceof Float32Array && cache.length !== data.length) { + this.cache = new Float32Array(data.length); + } + + copyArray(cache, data); + }; + function StructuredUniform(id) { this.id = id; @@ -19627,7 +20261,7 @@ // reset RegExp object, because of the early exit of a previous run RePathPart.lastIndex = 0; - for (;;) { + while (true) { var match = RePathPart.exec(path), matchEnd = RePathPart.lastIndex, id = match[1], @@ -20183,7 +20817,11 @@ customDefines, - parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest : "", + parameters.alphaTest + ? "#define ALPHATEST " + + parameters.alphaTest + + (parameters.alphaTest % 1 ? "" : ".0") + : "", // add '.0' if integer "#define GAMMA_FACTOR " + gammaFactorDefine, @@ -21932,6 +22570,7 @@ CanvasTexture.prototype = Object.create(Texture.prototype); CanvasTexture.prototype.constructor = CanvasTexture; + CanvasTexture.prototype.isCanvasTexture = true; /** * @author mikael emtinger / http://gomo.se/ @@ -22662,19 +23301,7 @@ } function enableAttribute(attribute) { - newAttributes[attribute] = 1; - - if (enabledAttributes[attribute] === 0) { - gl.enableVertexAttribArray(attribute); - enabledAttributes[attribute] = 1; - } - - if (attributeDivisors[attribute] !== 0) { - var extension = extensions.get("ANGLE_instanced_arrays"); - - extension.vertexAttribDivisorANGLE(attribute, 0); - attributeDivisors[attribute] = 0; - } + enableAttributeAndDivisor(attribute, 0); } function enableAttributeAndDivisor(attribute, meshPerAttribute) { @@ -24618,12 +25245,16 @@ currentSize = renderer.getSize(); renderer.setDrawingBufferSize(renderWidth * 2, renderHeight, 1); + + animation.start(); } else if (scope.enabled) { renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); + + animation.stop(); } } @@ -24638,6 +25269,8 @@ this.setDevice = function (value) { if (value !== undefined) device = value; + + animation.setContext(value); }; this.setPoseTarget = function (object) { @@ -24755,6 +25388,16 @@ return standingMatrix; }; + this.isPresenting = isPresenting; + + // Animation Loop + + var animation = new WebGLAnimation(); + + this.setAnimationLoop = function (callback) { + animation.setAnimationLoop(callback); + }; + this.submitFrame = function () { if (isPresenting()) device.submitFrame(); }; @@ -24769,6 +25412,175 @@ }; } + /** + * @author mrdoob / http://mrdoob.com/ + */ + + function WebXRManager(renderer) { + var gl = renderer.context; + + var device = null; + var session = null; + + var frameOfRef = null; + + var pose = null; + + function isPresenting() { + return session !== null && frameOfRef !== null; + } + + // + + var cameraL = new PerspectiveCamera(); + cameraL.layers.enable(1); + cameraL.viewport = new Vector4(); + + var cameraR = new PerspectiveCamera(); + cameraR.layers.enable(2); + cameraR.viewport = new Vector4(); + + var cameraVR = new ArrayCamera([cameraL, cameraR]); + cameraVR.layers.enable(1); + cameraVR.layers.enable(2); + + // + + this.enabled = false; + + this.getDevice = function () { + return device; + }; + + this.setDevice = function (value) { + if (value !== undefined) device = value; + + gl.setCompatibleXRDevice(value); + }; + + // + + this.setSession = function (value, options) { + session = value; + + if (session !== null) { + session.addEventListener("end", function () { + renderer.setFramebuffer(null); + animation.stop(); + }); + + session.baseLayer = new XRWebGLLayer(session, gl); + session + .requestFrameOfReference(options.frameOfReferenceType) + .then(function (value) { + frameOfRef = value; + + renderer.setFramebuffer(session.baseLayer.framebuffer); + + animation.setContext(session); + animation.start(); + }); + } + }; + + function updateCamera(camera, parent) { + if (parent === null) { + camera.matrixWorld.copy(camera.matrix); + } else { + camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix); + } + + camera.matrixWorldInverse.getInverse(camera.matrixWorld); + } + + this.getCamera = function (camera) { + if (isPresenting()) { + var parent = camera.parent; + var cameras = cameraVR.cameras; + + // apply camera.parent to cameraVR + + updateCamera(cameraVR, parent); + + for (var i = 0; i < cameras.length; i++) { + updateCamera(cameras[i], parent); + } + + // update camera and its children + + camera.matrixWorld.copy(cameraVR.matrixWorld); + + var children = camera.children; + + for (var i = 0, l = children.length; i < l; i++) { + children[i].updateMatrixWorld(true); + } + + return cameraVR; + } + + return camera; + }; + + this.isPresenting = isPresenting; + + // Animation Loop + + var onAnimationFrameCallback = null; + + function onAnimationFrame(time, frame) { + pose = frame.getDevicePose(frameOfRef); + + var layer = session.baseLayer; + var views = frame.views; + + for (var i = 0; i < views.length; i++) { + var view = views[i]; + var viewport = layer.getViewport(view); + var viewMatrix = pose.getViewMatrix(view); + + var camera = cameraVR.cameras[i]; + camera.matrix.fromArray(viewMatrix).getInverse(camera.matrix); + camera.projectionMatrix.fromArray(view.projectionMatrix); + camera.viewport.set( + viewport.x, + viewport.y, + viewport.width, + viewport.height + ); + + if (i === 0) { + cameraVR.matrix.copy(camera.matrix); + + // HACK (mrdoob) + // https://github.com/w3c/webvr/issues/203 + + cameraVR.projectionMatrix.copy(camera.projectionMatrix); + } + } + + if (onAnimationFrameCallback) onAnimationFrameCallback(); + } + + var animation = new WebGLAnimation(); + animation.setAnimationLoop(onAnimationFrame); + + this.setAnimationLoop = function (callback) { + onAnimationFrameCallback = callback; + }; + + // DEPRECATED + + this.getStandingMatrix = function () { + console.warn( + "THREE.WebXRManager: getStandingMatrix() is no longer needed." + ); + return new THREE.Matrix4(); + }; + + this.submitFrame = function () {}; + } + /** * @author supereggbert / http://www.paulbrunt.co.uk/ * @author mrdoob / http://mrdoob.com/ @@ -24856,6 +25668,7 @@ _isContextLost = false, // internal state cache + _framebuffer = null, _currentRenderTarget = null, _currentFramebuffer = null, _currentMaterialId = -1, @@ -24991,7 +25804,7 @@ background = new WebGLBackground( _this, state, - geometries, + objects, _premultipliedAlpha ); @@ -25025,7 +25838,8 @@ // vr - var vr = new WebVRManager(_this); + var vr = + "xr" in navigator ? new WebXRManager(_this) : new WebVRManager(_this); this.vr = vr; @@ -25079,9 +25893,7 @@ }; this.setSize = function (width, height, updateStyle) { - var device = vr.getDevice(); - - if (device && device.isPresenting) { + if (vr.isPresenting()) { console.warn( "THREE.WebGLRenderer: Can't change size while VR device is presenting." ); @@ -25203,7 +26015,7 @@ vr.dispose(); - stopAnimation(); + animation.stop(); }; // Events @@ -25661,42 +26473,22 @@ // Animation Loop - var isAnimating = false; - var onAnimationFrame = null; - - function startAnimation() { - if (isAnimating) return; - - requestAnimationLoopFrame(); - - isAnimating = true; - } - - function stopAnimation() { - isAnimating = false; - } - - function requestAnimationLoopFrame() { - var device = vr.getDevice(); + var onAnimationFrameCallback = null; - if (device && device.isPresenting) { - device.requestAnimationFrame(animationLoop); - } else { - window.requestAnimationFrame(animationLoop); - } + function onAnimationFrame() { + if (vr.isPresenting()) return; + if (onAnimationFrameCallback) onAnimationFrameCallback(); } - function animationLoop(time) { - if (isAnimating === false) return; + var animation = new WebGLAnimation(); + animation.setAnimationLoop(onAnimationFrame); + animation.setContext(window); - onAnimationFrame(time); + this.setAnimationLoop = function (callback) { + onAnimationFrameCallback = callback; + vr.setAnimationLoop(callback); - requestAnimationLoopFrame(); - } - - this.animate = function (callback) { - onAnimationFrame = callback; - onAnimationFrame !== null ? startAnimation() : stopAnimation(); + animation.start(); }; // Rendering @@ -25840,59 +26632,59 @@ }; /* - // TODO Duplicated code (Frustum) + // TODO Duplicated code (Frustum) - var _sphere = new Sphere(); + var _sphere = new Sphere(); - function isObjectViewable( object ) { + function isObjectViewable( object ) { - var geometry = object.geometry; + var geometry = object.geometry; - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); + if ( geometry.boundingSphere === null ) + geometry.computeBoundingSphere(); - _sphere.copy( geometry.boundingSphere ). - applyMatrix4( object.matrixWorld ); + _sphere.copy( geometry.boundingSphere ). + applyMatrix4( object.matrixWorld ); - return isSphereViewable( _sphere ); + return isSphereViewable( _sphere ); - } + } - function isSpriteViewable( sprite ) { + function isSpriteViewable( sprite ) { - _sphere.center.set( 0, 0, 0 ); - _sphere.radius = 0.7071067811865476; - _sphere.applyMatrix4( sprite.matrixWorld ); + _sphere.center.set( 0, 0, 0 ); + _sphere.radius = 0.7071067811865476; + _sphere.applyMatrix4( sprite.matrixWorld ); - return isSphereViewable( _sphere ); + return isSphereViewable( _sphere ); - } + } - function isSphereViewable( sphere ) { + function isSphereViewable( sphere ) { - if ( ! _frustum.intersectsSphere( sphere ) ) return false; + if ( ! _frustum.intersectsSphere( sphere ) ) return false; - var numPlanes = _clipping.numPlanes; + var numPlanes = _clipping.numPlanes; - if ( numPlanes === 0 ) return true; + if ( numPlanes === 0 ) return true; - var planes = _this.clippingPlanes, + var planes = _this.clippingPlanes, - center = sphere.center, - negRad = - sphere.radius, - i = 0; + center = sphere.center, + negRad = - sphere.radius, + i = 0; - do { + do { - // out when deeper than radius in the negative halfspace - if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; + // out when deeper than radius in the negative halfspace + if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; - } while ( ++ i !== numPlanes ); + } while ( ++ i !== numPlanes ); - return true; + return true; - } - */ + } + */ function projectObject(object, camera, sortObjects) { if (object.visible === false) return; @@ -25997,18 +26789,24 @@ var camera2 = cameras[j]; if (object.layers.test(camera2.layers)) { - var bounds = camera2.bounds; + if ("viewport" in camera2) { + // XR - var x = bounds.x * _width; - var y = bounds.y * _height; - var width = bounds.z * _width; - var height = bounds.w * _height; + state.viewport(_currentViewport.copy(camera2.viewport)); + } else { + var bounds = camera2.bounds; - state.viewport( - _currentViewport - .set(x, y, width, height) - .multiplyScalar(_pixelRatio) - ); + var x = bounds.x * _width; + var y = bounds.y * _height; + var width = bounds.z * _width; + var height = bounds.w * _height; + + state.viewport( + _currentViewport + .set(x, y, width, height) + .multiplyScalar(_pixelRatio) + ); + } renderObject(object, scene, camera2, geometry, material, group); } @@ -26643,11 +27441,13 @@ if (material.bumpMap) { uniforms.bumpMap.value = material.bumpMap; uniforms.bumpScale.value = material.bumpScale; + if (material.side === BackSide) uniforms.bumpScale.value *= -1; } if (material.normalMap) { uniforms.normalMap.value = material.normalMap; uniforms.normalScale.value.copy(material.normalScale); + if (material.side === BackSide) uniforms.normalScale.value.negate(); } if (material.displacementMap) { @@ -26684,11 +27484,13 @@ if (material.bumpMap) { uniforms.bumpMap.value = material.bumpMap; uniforms.bumpScale.value = material.bumpScale; + if (material.side === BackSide) uniforms.bumpScale.value *= -1; } if (material.normalMap) { uniforms.normalMap.value = material.normalMap; uniforms.normalScale.value.copy(material.normalScale); + if (material.side === BackSide) uniforms.normalScale.value.negate(); } if (material.displacementMap) { @@ -26734,11 +27536,13 @@ if (material.bumpMap) { uniforms.bumpMap.value = material.bumpMap; uniforms.bumpScale.value = material.bumpScale; + if (material.side === BackSide) uniforms.bumpScale.value *= -1; } if (material.normalMap) { uniforms.normalMap.value = material.normalMap; uniforms.normalScale.value.copy(material.normalScale); + if (material.side === BackSide) uniforms.normalScale.value.negate(); } if (material.displacementMap) { @@ -26851,6 +27655,12 @@ }; })(); + // + + this.setFramebuffer = function (value) { + _framebuffer = value; + }; + this.getRenderTarget = function () { return _currentRenderTarget; }; @@ -26865,7 +27675,7 @@ textures.setupRenderTarget(renderTarget); } - var framebuffer = null; + var framebuffer = _framebuffer; var isCube = false; if (renderTarget) { @@ -27035,23 +27845,32 @@ var height = srcTexture.image.height; var glFormat = utils.convert(dstTexture.format); var glType = utils.convert(dstTexture.type); - var pixels = srcTexture.isDataTexture - ? srcTexture.image.data - : srcTexture.image; this.setTexture2D(dstTexture, 0); - _gl.texSubImage2D( - _gl.TEXTURE_2D, - level || 0, - position.x, - position.y, - width, - height, - glFormat, - glType, - pixels - ); + if (srcTexture.isDataTexture) { + _gl.texSubImage2D( + _gl.TEXTURE_2D, + level || 0, + position.x, + position.y, + width, + height, + glFormat, + glType, + srcTexture.image.data + ); + } else { + _gl.texSubImage2D( + _gl.TEXTURE_2D, + level || 0, + position.x, + position.y, + glFormat, + glType, + srcTexture.image + ); + } }; } @@ -27070,7 +27889,7 @@ FogExp2.prototype.isFogExp2 = true; FogExp2.prototype.clone = function () { - return new FogExp2(this.color.getHex(), this.density); + return new FogExp2(this.color, this.density); }; FogExp2.prototype.toJSON = function (/* meta */) { @@ -27098,7 +27917,7 @@ Fog.prototype.isFog = true; Fog.prototype.clone = function () { - return new Fog(this.color.getHex(), this.near, this.far); + return new Fog(this.color, this.near, this.far); }; Fog.prototype.toJSON = function (/* meta */) { @@ -28050,6 +28869,8 @@ * * size: , * sizeAttenuation: + * + * morphTargets: * } */ @@ -28065,6 +28886,8 @@ this.size = 1; this.sizeAttenuation = true; + this.morphTargets = false; + this.lights = false; this.setValues(parameters); @@ -28085,6 +28908,8 @@ this.size = source.size; this.sizeAttenuation = source.sizeAttenuation; + this.morphTargets = source.morphTargets; + return this; }; @@ -28570,6 +29395,12 @@ var i, j; + if (func.length < 3) { + console.error( + "THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter." + ); + } + // generate vertices, normals and uvs var sliceCount = slices + 1; @@ -30591,7 +31422,7 @@ * * curveSegments: , // number of points on the curves * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too - * amount: , // Depth to extrude the shape + * depth: , // Depth to extrude the shape * * bevelEnabled: , // turn on bevel * bevelThickness: , // how deep into the original shape bevel goes @@ -30624,6 +31455,15 @@ ExtrudeGeometry.prototype = Object.create(Geometry.prototype); ExtrudeGeometry.prototype.constructor = ExtrudeGeometry; + ExtrudeGeometry.prototype.toJSON = function () { + var data = Geometry.prototype.toJSON.call(this); + + var shapes = this.parameters.shapes; + var options = this.parameters.options; + + return toJSON(shapes, options, data); + }; + // ExtrudeBufferGeometry function ExtrudeBufferGeometry(shapes, options) { @@ -30645,7 +31485,7 @@ for (var i = 0, l = shapes.length; i < l; i++) { var shape = shapes[i]; - addShape(shape, options); + addShape(shape); } // build geometry @@ -30665,7 +31505,7 @@ var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; var steps = options.steps !== undefined ? options.steps : 1; - var amount = options.amount !== undefined ? options.amount : 100; + var depth = options.depth !== undefined ? options.depth : 100; var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; @@ -30685,6 +31525,15 @@ ? options.UVGenerator : WorldUVGenerator; + // deprecated options + + if (options.amount !== undefined) { + console.warn( + "THREE.ExtrudeBufferGeometry: amount has been renamed to depth." + ); + depth = options.amount; + } + // var extrudePts, @@ -30974,7 +31823,7 @@ : vertices[i]; if (!extrudeByPath) { - v(vert.x, vert.y, (amount / steps) * s); + v(vert.x, vert.y, (depth / steps) * s); } else { // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); @@ -31000,7 +31849,7 @@ for (i = 0, il = contour.length; i < il; i++) { vert = scalePt2(contour[i], contourMovements[i], bs); - v(vert.x, vert.y, amount + z); + v(vert.x, vert.y, depth + z); } // expand holes @@ -31013,7 +31862,7 @@ vert = scalePt2(ahole[i], oneHoleMovements[i], bs); if (!extrudeByPath) { - v(vert.x, vert.y, amount + z); + v(vert.x, vert.y, depth + z); } else { v( vert.x, @@ -31199,6 +32048,17 @@ ExtrudeBufferGeometry.prototype = Object.create(BufferGeometry.prototype); ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry; + ExtrudeBufferGeometry.prototype.toJSON = function () { + var data = BufferGeometry.prototype.toJSON.call(this); + + var shapes = this.parameters.shapes; + var options = this.parameters.options; + + return toJSON(shapes, options, data); + }; + + // + var WorldUVGenerator = { generateTopUV: function (geometry, vertices, indexA, indexB, indexC) { var a_x = vertices[indexA * 3]; @@ -31254,6 +32114,29 @@ }, }; + function toJSON(shapes, options, data) { + // + + data.shapes = []; + + if (Array.isArray(shapes)) { + for (var i = 0, l = shapes.length; i < l; i++) { + var shape = shapes[i]; + + data.shapes.push(shape.uuid); + } + } else { + data.shapes.push(shapes.uuid); + } + + // + + if (options.extrudePath !== undefined) + data.options.extrudePath = options.extrudePath.toJSON(); + + return data; + } + /** * @author zz85 / http://www.lab4games.net/zz85/blog * @author alteredq / http://alteredqualia.com/ @@ -31314,8 +32197,7 @@ // translate parameters to ExtrudeGeometry API - parameters.amount = - parameters.height !== undefined ? parameters.height : 50; + parameters.depth = parameters.height !== undefined ? parameters.height : 50; // defaults @@ -31850,7 +32732,7 @@ var shapes = this.parameters.shapes; - return toJSON(shapes, data); + return toJSON$1(shapes, data); }; // ShapeBufferGeometry @@ -31970,12 +32852,12 @@ var shapes = this.parameters.shapes; - return toJSON(shapes, data); + return toJSON$1(shapes, data); }; // - function toJSON(shapes, data) { + function toJSON$1(shapes, data) { data.shapes = []; if (Array.isArray(shapes)) { @@ -32591,7 +33473,7 @@ CircleBufferGeometry.prototype = Object.create(BufferGeometry.prototype); CircleBufferGeometry.prototype.constructor = CircleBufferGeometry; - var Geometries = Object.freeze({ + var Geometries = /*#__PURE__*/ Object.freeze({ WireframeGeometry: WireframeGeometry, ParametricGeometry: ParametricGeometry, ParametricBufferGeometry: ParametricBufferGeometry, @@ -33327,7 +34209,7 @@ return this; }; - var Materials = Object.freeze({ + var Materials = /*#__PURE__*/ Object.freeze({ ShadowMaterial: ShadowMaterial, SpriteMaterial: SpriteMaterial, RawShaderMaterial: RawShaderMaterial, @@ -33589,18 +34471,12 @@ delete loading[url]; - if (this.status === 200) { - for (var i = 0, il = callbacks.length; i < il; i++) { - var callback = callbacks[i]; - if (callback.onLoad) callback.onLoad(response); - } - - scope.manager.itemEnd(url); - } else if (this.status === 0) { + if (this.status === 200 || this.status === 0) { // Some browsers return HTTP Status 0 when using non-http protocol // e.g. 'file://' or 'data://'. Handle as success. - console.warn("THREE.FileLoader: HTTP Status 0 received."); + if (this.status === 0) + console.warn("THREE.FileLoader: HTTP Status 0 received."); for (var i = 0, il = callbacks.length; i < il; i++) { var callback = callbacks[i]; @@ -33931,36 +34807,29 @@ "img" ); - image.addEventListener( - "load", - function () { - Cache.add(url, this); + function onImageLoad() { + image.removeEventListener("load", onImageLoad, false); + image.removeEventListener("error", onImageError, false); - if (onLoad) onLoad(this); + Cache.add(url, this); - scope.manager.itemEnd(url); - }, - false - ); + if (onLoad) onLoad(this); - /* - image.addEventListener( 'progress', function ( event ) { + scope.manager.itemEnd(url); + } - if ( onProgress ) onProgress( event ); + function onImageError(event) { + image.removeEventListener("load", onImageLoad, false); + image.removeEventListener("error", onImageError, false); - }, false ); - */ + if (onError) onError(event); - image.addEventListener( - "error", - function (event) { - if (onError) onError(event); + scope.manager.itemEnd(url); + scope.manager.itemError(url); + } - scope.manager.itemEnd(url); - scope.manager.itemError(url); - }, - false - ); + image.addEventListener("load", onImageLoad, false); + image.addEventListener("error", onImageError, false); if (url.substr(0, 5) !== "data:") { if (this.crossOrigin !== undefined) @@ -34620,14 +35489,14 @@ */ /* - Based on an optimized c++ solution in - - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ - - http://ideone.com/NoEbVM + Based on an optimized c++ solution in + - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ + - http://ideone.com/NoEbVM - This CubicPoly class could be used for reusing some variables and calculations, - but for three.js curve use, it could be possible inlined and flatten into a single function call - which can be placed in CurveUtils. - */ + This CubicPoly class could be used for reusing some variables and calculations, + but for three.js curve use, it could be possible inlined and flatten into a single function call + which can be placed in CurveUtils. + */ function CubicPoly() { var c0 = 0, @@ -34678,9 +35547,9 @@ // var tmp = new Vector3(); - var px = new CubicPoly(); - var py = new CubicPoly(); - var pz = new CubicPoly(); + var px = new CubicPoly(), + py = new CubicPoly(), + pz = new CubicPoly(); function CatmullRomCurve3(points, closed, curveType, tension) { Curve.call(this); @@ -35342,7 +36211,7 @@ return this; }; - var Curves = Object.freeze({ + var Curves = /*#__PURE__*/ Object.freeze({ ArcCurve: ArcCurve, CatmullRomCurve3: CatmullRomCurve3, CubicBezierCurve: CubicBezierCurve, @@ -37491,6 +38360,7 @@ name: clip.name, duration: clip.duration, tracks: tracks, + uuid: clip.uuid, }; for (var i = 0, n = clipTracks.length; i !== n; ++i) { @@ -38951,10 +39821,12 @@ setTexturePath: function (value) { this.texturePath = value; + return this; }, setCrossOrigin: function (value) { this.crossOrigin = value; + return this; }, parse: function (json, onLoad) { @@ -39175,6 +40047,31 @@ break; + case "ExtrudeGeometry": + case "ExtrudeBufferGeometry": + var geometryShapes = []; + + for (var j = 0, jl = data.shapes.length; j < jl; j++) { + var shape = shapes[data.shapes[j]]; + + geometryShapes.push(shape); + } + + var extrudePath = data.options.extrudePath; + + if (extrudePath !== undefined) { + data.options.extrudePath = new Curves[ + extrudePath.type + ]().fromJSON(extrudePath); + } + + geometry = new Geometries[data.type]( + geometryShapes, + data.options + ); + + break; + case "BufferGeometry": geometry = bufferGeometryLoader.parse(data); @@ -39198,6 +40095,8 @@ geometry.uuid = data.uuid; if (data.name !== undefined) geometry.name = data.name; + if (geometry.isBufferGeometry === true && data.userData !== undefined) + geometry.userData = data.userData; geometries[data.uuid] = geometry; } @@ -39239,7 +40138,11 @@ var animations = []; for (var i = 0; i < json.length; i++) { - var clip = AnimationClip.parse(json[i]); + var data = json[i]; + + var clip = AnimationClip.parse(data); + + if (data.uuid !== undefined) clip.uuid = data.uuid; animations.push(clip); } @@ -39914,7 +40817,7 @@ }); function createPaths(text, size, divisions, data) { - var chars = String(text).split(""); + var chars = Array.from ? Array.from(text) : String(text).split(""); // see #13988 var scale = size / data.resolution; var line_height = (data.boundingBox.yMax - @@ -40455,6 +41358,15 @@ return this; }, + setMediaElementSource: function (mediaElement) { + this.hasPlaybackControl = false; + this.sourceType = "mediaNode"; + this.source = this.context.createMediaElementSource(mediaElement); + this.connect(); + + return this; + }, + setBuffer: function (audioBuffer) { this.buffer = audioBuffer; this.sourceType = "buffer"; @@ -44102,26 +45014,26 @@ this.update(); /* - var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); - var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); + var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); + var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); - this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); - this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); + this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); + this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); - var d = light.distance; + var d = light.distance; - if ( d === 0.0 ) { + if ( d === 0.0 ) { - this.lightDistance.visible = false; + this.lightDistance.visible = false; - } else { + } else { - this.lightDistance.scale.set( d, d, d ); + this.lightDistance.scale.set( d, d, d ); - } + } - this.add( this.lightDistance ); - */ + this.add( this.lightDistance ); + */ } PointLightHelper.prototype = Object.create(Mesh.prototype); @@ -44140,19 +45052,19 @@ } /* - var d = this.light.distance; + var d = this.light.distance; - if ( d === 0.0 ) { + if ( d === 0.0 ) { - this.lightDistance.visible = false; + this.lightDistance.visible = false; - } else { + } else { - this.lightDistance.visible = true; - this.lightDistance.scale.set( d, d, d ); + this.lightDistance.visible = true; + this.lightDistance.scale.set( d, d, d ); - } - */ + } + */ }; /** @@ -44871,20 +45783,20 @@ var max = box.max; /* - 5____4 - 1/___0/| - | 6__|_7 - 2/___3/ - - 0: max.x, max.y, max.z - 1: min.x, max.y, max.z - 2: min.x, min.y, max.z - 3: max.x, min.y, max.z - 4: max.x, max.y, min.z - 5: min.x, max.y, min.z - 6: min.x, min.y, min.z - 7: max.x, min.y, min.z - */ + 5____4 + 1/___0/| + | 6__|_7 + 2/___3/ + + 0: max.x, max.y, max.z + 1: min.x, max.y, max.z + 2: min.x, min.y, max.z + 3: max.x, min.y, max.z + 4: max.x, max.y, min.z + 5: min.x, max.y, min.z + 6: min.x, min.y, min.z + 7: max.x, min.y, min.z + */ var position = this.geometry.attributes.position; var array = position.array; @@ -45035,6 +45947,8 @@ this.scale.set(0.5 * this.size, 0.5 * this.size, scale); + this.children[0].material.side = scale < 0 ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here + this.lookAt(this.plane.normal); Object3D.prototype.updateMatrixWorld.call(this, force); @@ -45056,8 +45970,7 @@ * headWidth - Number */ - var lineGeometry; - var coneGeometry; + var lineGeometry, coneGeometry; function ArrowHelper(dir, origin, length, color, headLength, headWidth) { // dir is assumed to be normalized @@ -46072,6 +46985,13 @@ // Object.assign(WebGLRenderer.prototype, { + animate: function (callback) { + console.warn( + "THREE.WebGLRenderer: .animate() is now .setAnimationLoop()." + ); + this.setAnimationLoop(callback); + }, + getCurrentRenderTarget: function () { console.warn( "THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget()." @@ -47475,10 +48395,8 @@ ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientWidth); + scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, height - // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight); rotateStart.copy(rotateEnd); @@ -47596,10 +48514,8 @@ ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientWidth); + scope.rotateLeft((2 * Math.PI * rotateDelta.x) / element.clientHeight); // yes, height - // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp((2 * Math.PI * rotateDelta.y) / element.clientHeight); rotateStart.copy(rotateEnd); @@ -47833,7 +48749,7 @@ // - scope.domElement.addEventListener("contextmenu", onContextMenu, false); + //scope.domElement.addEventListener\( 'contextmenu', onContextMenu, false ); scope.domElement.addEventListener("mousedown", onMouseDown, false); scope.domElement.addEventListener("wheel", onMouseWheel, false); @@ -48075,70 +48991,31 @@ this.connect(); }; - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - - var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError( - "Super expression must either be null or a function, not " + - typeof superClass - ); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true, - }, - }); - if (superClass) - Object.setPrototypeOf - ? Object.setPrototypeOf(subClass, superClass) - : (subClass.__proto__ = superClass); - }; - - var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called" - ); - } - - return call && (typeof call === "object" || typeof call === "function") - ? call - : self; - }; - /** * Convert a quaternion to an angle * * Taken from https://stackoverflow.com/a/35448946 * Thanks P. Ellul */ + function Quat2Angle(x, y, z, w) { - var test = x * y + z * w; + var test = x * y + z * w; // singularity at north pole - // singularity at north pole if (test > 0.499) { var _yaw = 2 * Math.atan2(x, w); + var _pitch = Math.PI / 2; - var _roll = 0; + var _roll = 0; return new Vector3(_pitch, _roll, _yaw); - } + } // singularity at south pole - // singularity at south pole if (test < -0.499) { var _yaw2 = -2 * Math.atan2(x, w); + var _pitch2 = -Math.PI / 2; - var _roll2 = 0; + var _roll2 = 0; return new Vector3(_pitch2, _roll2, _yaw2); } @@ -48148,31 +49025,34 @@ var yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz); var pitch = Math.asin(2 * test); var roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz); - return new Vector3(pitch, roll, yaw); } - var OrbitOrientationControls = (function () { + var OrbitOrientationControls = /*#__PURE__*/ (function () { function OrbitOrientationControls(options) { - classCallCheck(this, OrbitOrientationControls); - this.object = options.camera; this.domElement = options.canvas; this.orbit = new OrbitControls(this.object, this.domElement); - this.speed = 0.5; this.orbit.target.set(0, 0, -1); this.orbit.enableZoom = false; this.orbit.enablePan = false; - this.orbit.rotateSpeed = -this.speed; + this.orbit.rotateSpeed = -this.speed; // if orientation is supported - // if orientation is supported if (options.orientation) { this.orientation = new DeviceOrientationControls(this.object); + } // if projection is not full view + // limit the rotation angle in order to not display back half view + + if (options.halfView) { + this.orbit.minAzimuthAngle = -Math.PI / 4; + this.orbit.maxAzimuthAngle = Math.PI / 4; } } - OrbitOrientationControls.prototype.update = function update() { + var _proto = OrbitOrientationControls.prototype; + + _proto.update = function update() { // orientation updates the camera using quaternions and // orbit updates the camera using angles. They are incompatible // and one update overrides the other. So before @@ -48182,11 +49062,9 @@ // our changes if (this.orientation) { this.orientation.update(); - var quat = this.orientation.object.quaternion; - var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); + var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); // we also have to store the last angle since quaternions are b - // we also have to store the last angle since quaternions are b if (typeof this.lastAngle_ === "undefined") { this.lastAngle_ = currentAngle; } @@ -48203,7 +49081,7 @@ this.orbit.update(); }; - OrbitOrientationControls.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { this.orbit.dispose(); if (this.orientation) { @@ -48214,27 +49092,27 @@ return OrbitOrientationControls; })(); - // check if the browser supports cors var corsSupport = (function () { - var video = document_1.createElement("video"); - + var video = document$1.createElement("video"); video.crossOrigin = "anonymous"; - return video.hasAttribute("crossorigin"); })(); - var validProjections = [ "360", "360_LR", "360_TB", "360_CUBE", + "EAC", + "EAC_LR", "NONE", "AUTO", "Sphere", "Cube", "equirectangular", + "180", + "180_LR", + "180_MONO", ]; - var getInternalProjectionName = function getInternalProjectionName( projection ) { @@ -48263,61 +49141,301 @@ } }; - // Add Cardboard button - var Button = videojs.getComponent("Button"); + /** + * This class reacts to interactions with the canvas and + * triggers appropriate functionality on the player. Right now + * it does two things: + * + * 1. A `mousedown`/`touchstart` followed by `touchend`/`mouseup` without any + * `touchmove` or `mousemove` toggles play/pause on the player + * 2. Only moving on/clicking the control bar or toggling play/pause should + * show the control bar. Moving around the scene in the canvas should not. + */ - var CardboardButton = (function (_Button) { - inherits(CardboardButton, _Button); + var CanvasPlayerControls = /*#__PURE__*/ (function (_videojs$EventTarget) { + _inheritsLoose(CanvasPlayerControls, _videojs$EventTarget); - function CardboardButton(player, options) { - classCallCheck(this, CardboardButton); + function CanvasPlayerControls(player, canvas, options) { + var _this; + + _this = _videojs$EventTarget.call(this) || this; + _this.player = player; + _this.canvas = canvas; + _this.options = options; + _this.onMoveEnd = videojs.bind( + _assertThisInitialized(_this), + _this.onMoveEnd + ); + _this.onMoveStart = videojs.bind( + _assertThisInitialized(_this), + _this.onMoveStart + ); + _this.onMove = videojs.bind(_assertThisInitialized(_this), _this.onMove); + _this.onControlBarMove = videojs.bind( + _assertThisInitialized(_this), + _this.onControlBarMove + ); + + _this.player.controlBar.on( + [ + "mousedown", + "mousemove", + "mouseup", + "touchstart", + "touchmove", + "touchend", + ], + _this.onControlBarMove + ); // we have to override these here because + // video.js listens for user activity on the video element + // and makes the user active when the mouse moves. + // We don't want that for 3d videos + + _this.oldReportUserActivity = _this.player.reportUserActivity; + + _this.player.reportUserActivity = function () {}; // canvas movements - var _this = possibleConstructorReturn( - this, - _Button.call(this, player, options) + _this.canvas.addEventListener("mousedown", _this.onMoveStart); + + _this.canvas.addEventListener("touchstart", _this.onMoveStart); + + _this.canvas.addEventListener("mousemove", _this.onMove); + + _this.canvas.addEventListener("touchmove", _this.onMove); + + _this.canvas.addEventListener("mouseup", _this.onMoveEnd); + + _this.canvas.addEventListener("touchend", _this.onMoveEnd); + + _this.shouldTogglePlay = false; + return _this; + } + + var _proto = CanvasPlayerControls.prototype; + + _proto.togglePlay = function togglePlay() { + if (this.player.paused()) { + this.player.play(); + } else { + this.player.pause(); + } + }; + + _proto.onMoveStart = function onMoveStart(e) { + // if the player does not have a controlbar or + // the move was a mouse click but not left click do not + // toggle play. + if ( + this.options.disableTogglePlay || + !this.player.controls() || + (e.type === "mousedown" && !videojs.dom.isSingleLeftClick(e)) + ) { + this.shouldTogglePlay = false; + return; + } + + this.shouldTogglePlay = true; + this.touchMoveCount_ = 0; + }; + + _proto.onMoveEnd = function onMoveEnd(e) { + // We want to have the same behavior in VR360 Player and standard player. + // in touchend we want to know if was a touch click, for a click we show the bar, + // otherwise continue with the mouse logic. + // + // Maximum movement allowed during a touch event to still be considered a tap + // Other popular libs use anywhere from 2 (hammer.js) to 15, + // so 10 seems like a nice, round number. + if (e.type === "touchend" && this.touchMoveCount_ < 10) { + if (this.player.userActive() === false) { + this.player.userActive(true); + return; + } + + this.player.userActive(false); + return; + } + + if (!this.shouldTogglePlay) { + return; + } // We want the same behavior in Desktop for VR360 and standard player + + if (e.type == "mouseup") { + this.togglePlay(); + } + }; + + _proto.onMove = function onMove(e) { + // Increase touchMoveCount_ since Android detects 1 - 6 touches when user click normally + this.touchMoveCount_++; + this.shouldTogglePlay = false; + }; + + _proto.onControlBarMove = function onControlBarMove(e) { + this.player.userActive(true); + }; + + _proto.dispose = function dispose() { + this.canvas.removeEventListener("mousedown", this.onMoveStart); + this.canvas.removeEventListener("touchstart", this.onMoveStart); + this.canvas.removeEventListener("mousemove", this.onMove); + this.canvas.removeEventListener("touchmove", this.onMove); + this.canvas.removeEventListener("mouseup", this.onMoveEnd); + this.canvas.removeEventListener("touchend", this.onMoveEnd); + this.player.controlBar.off( + [ + "mousedown", + "mousemove", + "mouseup", + "touchstart", + "touchmove", + "touchend", + ], + this.onControlBarMove + ); + this.player.reportUserActivity = this.oldReportUserActivity; + }; + + return CanvasPlayerControls; + })(videojs.EventTarget); + + /** + * This class manages ambisonic decoding and binaural rendering via Omnitone library. + */ + + var OmnitoneController = /*#__PURE__*/ (function (_videojs$EventTarget) { + _inheritsLoose(OmnitoneController, _videojs$EventTarget); + + /** + * Omnitone controller class. + * + * @class + * @param {AudioContext} audioContext - associated AudioContext. + * @param {Omnitone library} omnitone - Omnitone library element. + * @param {HTMLVideoElement} video - vidoe tag element. + * @param {Object} options - omnitone options. + */ + function OmnitoneController(audioContext, omnitone, video, options) { + var _this; + + _this = _videojs$EventTarget.call(this) || this; + var settings = videojs.mergeOptions( + { + // Safari uses the different AAC decoder than FFMPEG. The channel order is + // The default 4ch AAC channel layout for FFMPEG AAC channel ordering. + channelMap: videojs.browser.IS_SAFARI ? [2, 0, 1, 3] : [0, 1, 2, 3], + ambisonicOrder: 1, + }, + options + ); + _this.videoElementSource = audioContext.createMediaElementSource(video); + _this.foaRenderer = omnitone.createFOARenderer(audioContext, settings); + + _this.foaRenderer.initialize().then( + function () { + if (audioContext.state === "suspended") { + _this.trigger({ + type: "audiocontext-suspended", + }); + } + + _this.videoElementSource.connect(_this.foaRenderer.input); + + _this.foaRenderer.output.connect(audioContext.destination); + + _this.initialized = true; + + _this.trigger({ + type: "omnitone-ready", + }); + }, + function (error) { + videojs.log.warn( + "videojs-vr: Omnitone initializes failed with the following error: " + + error + + ")" + ); + } ); + return _this; + } + /** + * Updates the rotation of the Omnitone decoder based on three.js camera matrix. + * + * @param {Camera} camera Three.js camera object + */ + + var _proto = OmnitoneController.prototype; + + _proto.update = function update(camera) { + if (!this.initialized) { + return; + } + + this.foaRenderer.setRotationMatrixFromCamera(camera.matrix); + }; + /** + * Destroys the controller and does any necessary cleanup. + */ + + _proto.dispose = function dispose() { + this.initialized = false; + this.foaRenderer.setRenderingMode("bypass"); + this.foaRenderer = null; + }; + + return OmnitoneController; + })(videojs.EventTarget); + + var Button = videojs.getComponent("Button"); + + var CardboardButton = /*#__PURE__*/ (function (_Button) { + _inheritsLoose(CardboardButton, _Button); + + function CardboardButton(player, options) { + var _this; + + _this = _Button.call(this, player, options) || this; _this.handleVrDisplayActivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayActivate_ ); _this.handleVrDisplayDeactivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayDeactivate_ ); _this.handleVrDisplayPresentChange_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayPresentChange_ ); _this.handleOrientationChange_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleOrientationChange_ ); - window_1.addEventListener( + window$1.addEventListener( "orientationchange", _this.handleOrientationChange_ ); - window_1.addEventListener( + window$1.addEventListener( "vrdisplayactivate", _this.handleVrDisplayActivate_ ); - window_1.addEventListener( + window$1.addEventListener( "vrdisplaydeactivate", _this.handleVrDisplayDeactivate_ - ); - - // vrdisplaypresentchange does not fire activate or deactivate + ); // vrdisplaypresentchange does not fire activate or deactivate // and happens when hitting the back button during cardboard mode // so we need to make sure we stay in the correct state by // listening to it and checking if we are presenting it or not - window_1.addEventListener( + + window$1.addEventListener( "vrdisplaypresentchange", _this.handleVrDisplayPresentChange_ - ); - - // we cannot show the cardboard button in fullscreen on + ); // we cannot show the cardboard button in fullscreen on // android as it breaks the controls, and makes it impossible // to exit cardboard mode + if (videojs.browser.IS_ANDROID) { _this.on(player, "fullscreenchange", function () { if (player.isFullscreen()) { @@ -48327,93 +49445,97 @@ } }); } + return _this; } - CardboardButton.prototype.buildCSSClass = function buildCSSClass() { + var _proto = CardboardButton.prototype; + + _proto.buildCSSClass = function buildCSSClass() { return "vjs-button-vr " + _Button.prototype.buildCSSClass.call(this); }; - CardboardButton.prototype.handleVrDisplayPresentChange_ = + _proto.handleVrDisplayPresentChange_ = function handleVrDisplayPresentChange_() { if (!this.player_.vr().vrDisplay.isPresenting && this.active_) { this.handleVrDisplayDeactivate_(); } + if (this.player_.vr().vrDisplay.isPresenting && !this.active_) { this.handleVrDisplayActivate_(); } }; - CardboardButton.prototype.handleOrientationChange_ = - function handleOrientationChange_() { - if (this.active_ && videojs.browser.IS_IOS) { - this.changeSize_(); - } - }; + _proto.handleOrientationChange_ = function handleOrientationChange_() { + if (this.active_ && videojs.browser.IS_IOS) { + this.changeSize_(); + } + }; - CardboardButton.prototype.changeSize_ = function changeSize_() { - this.player_.width(window_1.innerWidth); - this.player_.height(window_1.innerHeight); - window_1.dispatchEvent(new window_1.Event("resize")); + _proto.changeSize_ = function changeSize_() { + this.player_.width(window$1.innerWidth); + this.player_.height(window$1.innerHeight); + window$1.dispatchEvent(new window$1.Event("resize")); }; - CardboardButton.prototype.handleVrDisplayActivate_ = - function handleVrDisplayActivate_() { - // we mimic fullscreen on IOS - if (videojs.browser.IS_IOS) { - this.oldWidth_ = this.player_.currentWidth(); - this.oldHeight_ = this.player_.currentHeight(); - this.player_.enterFullWindow(); - this.changeSize_(); - } + _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { + // we mimic fullscreen on IOS + if (videojs.browser.IS_IOS) { + this.oldWidth_ = this.player_.currentWidth(); + this.oldHeight_ = this.player_.currentHeight(); + this.player_.enterFullWindow(); + this.changeSize_(); + } - this.active_ = true; - }; + this.active_ = true; + }; - CardboardButton.prototype.handleVrDisplayDeactivate_ = - function handleVrDisplayDeactivate_() { - // un-mimic fullscreen on iOS - if (videojs.browser.IS_IOS) { - if (this.oldWidth_) { - this.player_.width(this.oldWidth_); - } - if (this.oldHeight_) { - this.player_.height(this.oldHeight_); - } - this.player_.exitFullWindow(); - window_1.dispatchEvent(new window_1.Event("resize")); + _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { + // un-mimic fullscreen on iOS + if (videojs.browser.IS_IOS) { + if (this.oldWidth_) { + this.player_.width(this.oldWidth_); } - this.active_ = false; - }; + if (this.oldHeight_) { + this.player_.height(this.oldHeight_); + } + + this.player_.exitFullWindow(); + } + + this.active_ = false; + }; - CardboardButton.prototype.handleClick = function handleClick(event) { + _proto.handleClick = function handleClick(event) { // if cardboard mode display is not active, activate it // otherwise deactivate it if (!this.active_) { // This starts playback mode when the cardboard button - // is clicked on Andriod. We need to do this as the controls + // is clicked on Android. We need to do this as the controls // disappear if (!this.player_.hasStarted() && videojs.browser.IS_ANDROID) { this.player_.play(); } - window_1.dispatchEvent(new window_1.Event("vrdisplayactivate")); + + window$1.dispatchEvent(new window$1.Event("vrdisplayactivate")); } else { - window_1.dispatchEvent(new window_1.Event("vrdisplaydeactivate")); + window$1.dispatchEvent(new window$1.Event("vrdisplaydeactivate")); } }; - CardboardButton.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { _Button.prototype.dispose.call(this); - window_1.removeEventListener( + + window$1.removeEventListener( "vrdisplayactivate", this.handleVrDisplayActivate_ ); - window_1.removeEventListener( + window$1.removeEventListener( "vrdisplaydeactivate", this.handleVrDisplayDeactivate_ ); - window_1.removeEventListener( + window$1.removeEventListener( "vrdisplaypresentchange", this.handleVrDisplayPresentChange_ ); @@ -48426,18 +49548,16 @@ var BigPlayButton = videojs.getComponent("BigPlayButton"); - var BigVrPlayButton = (function (_BigPlayButton) { - inherits(BigVrPlayButton, _BigPlayButton); + var BigVrPlayButton = /*#__PURE__*/ (function (_BigPlayButton) { + _inheritsLoose(BigVrPlayButton, _BigPlayButton); function BigVrPlayButton() { - classCallCheck(this, BigVrPlayButton); - return possibleConstructorReturn( - this, - _BigPlayButton.apply(this, arguments) - ); + return _BigPlayButton.apply(this, arguments) || this; } - BigVrPlayButton.prototype.buildCSSClass = function buildCSSClass() { + var _proto = BigVrPlayButton.prototype; + + _proto.buildCSSClass = function buildCSSClass() { return ( "vjs-big-vr-play-button " + _BigPlayButton.prototype.buildCSSClass.call(this) @@ -48449,13 +49569,54 @@ videojs.registerComponent("BigVrPlayButton", BigVrPlayButton); - // Default options for the plugin. - var defaults$1 = { - projection: "AUTO", - forceCardboard: false, + function _createForOfIteratorHelperLoose(o, allowArrayLike) { + var it = + (typeof Symbol !== "undefined" && o[Symbol.iterator]) || o["@@iterator"]; + if (it) return (it = it.call(o)).next.bind(it); + if ( + Array.isArray(o) || + (it = _unsupportedIterableToArray(o)) || + (allowArrayLike && o && typeof o.length === "number") + ) { + if (it) o = it; + var i = 0; + return function () { + if (i >= o.length) return { done: true }; + return { done: false, value: o[i++] }; + }; + } + throw new TypeError( + "Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." + ); + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) + return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) { + arr2[i] = arr[i]; + } + return arr2; + } + + var defaults = { debug: false, + omnitone: false, + forceCardboard: false, + omnitoneOptions: {}, + projection: "AUTO", + sphereDetail: 32, + disableTogglePlay: false, }; - var errors = { "web-vr-out-of-date": { headline: "360 is out of date", @@ -48476,44 +49637,42 @@ "Your browser/device does not support HLS 360 video. See http://webvr.info for assistance.", }, }; - var Plugin = videojs.getPlugin("plugin"); var Component = videojs.getComponent("Component"); - var VR = (function (_Plugin) { - inherits(VR, _Plugin); + var VR = /*#__PURE__*/ (function (_Plugin) { + _inheritsLoose(VR, _Plugin); function VR(player, options) { - classCallCheck(this, VR); - - var settings = videojs.mergeOptions(defaults$1, options); - - var _this = possibleConstructorReturn( - this, - _Plugin.call(this, player, settings) - ); + var _this; + var settings = videojs.mergeOptions(defaults, options); + _this = _Plugin.call(this, player, settings) || this; _this.options_ = settings; _this.player_ = player; _this.bigPlayButtonIndex_ = - player.children().indexOf(player.getChild("BigPlayButton")) || 0; + player.children().indexOf(player.getChild("BigPlayButton")) || 0; // custom videojs-errors integration boolean - // custom videojs-errors integration boolean _this.videojsErrorsSupport_ = !!videojs.errors; if (_this.videojsErrorsSupport_) { - player.errors({ errors: errors }); - } - - // IE 11 does not support enough webgl to be supported + player.errors({ + errors: errors, + }); + } // IE 11 does not support enough webgl to be supported // older safari does not support cors, so it wont work + if (videojs.browser.IE_VERSION || !corsSupport) { // if a player triggers error before 'loadstart' is fired // video.js will reset the error overlay _this.player_.on("loadstart", function () { - _this.triggerError_({ code: "web-vr-not-supported", dismiss: false }); + _this.triggerError_({ + code: "web-vr-not-supported", + dismiss: false, + }); }); - return possibleConstructorReturn(_this); + + return _assertThisInitialized(_this); } _this.polyfill_ = new WebVRPolyfill({ @@ -48521,39 +49680,79 @@ ROTATE_INSTRUCTIONS_DISABLED: true, }); _this.polyfill_ = new WebVRPolyfill(); - _this.handleVrDisplayActivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayActivate_ ); _this.handleVrDisplayDeactivate_ = videojs.bind( - _this, + _assertThisInitialized(_this), _this.handleVrDisplayDeactivate_ ); - _this.handleResize_ = videojs.bind(_this, _this.handleResize_); - _this.animate_ = videojs.bind(_this, _this.animate_); + _this.handleResize_ = videojs.bind( + _assertThisInitialized(_this), + _this.handleResize_ + ); + _this.animate_ = videojs.bind( + _assertThisInitialized(_this), + _this.animate_ + ); + + _this.setProjection(_this.options_.projection); // any time the video element is recycled for ads + // we have to reset the vr state and re-init after ad + + _this.on( + player, + "adstart", + function () { + return player.setTimeout(function () { + // if the video element was recycled for this ad + if (!player.ads || !player.ads.videoElementRecycled()) { + _this.log( + "video element not recycled for this ad, no need to reset" + ); - _this.setProjection(_this.options_.projection); + return; + } + + _this.log("video element recycled for this ad, reseting"); + + _this.reset(); + + _this.one(player, "playing", _this.init); + }); + }, + 1 + ); _this.on(player, "loadedmetadata", _this.init); + return _this; } - VR.prototype.changeProjection_ = function changeProjection_(projection) { - projection = getInternalProjectionName(projection); - // don't change to an invalid projection + var _proto = VR.prototype; + + _proto.changeProjection_ = function changeProjection_(projection) { + var _this2 = this; + + projection = getInternalProjectionName(projection); // don't change to an invalid projection + if (!projection) { projection = "NONE"; } - var position = { x: 0, y: 0, z: 0 }; + var position = { + x: 0, + y: 0, + z: 0, + }; if (this.scene) { this.scene.remove(this.movieScreen); } + if (projection === "AUTO") { // mediainfo cannot be set to auto or we would infinite loop here - // each source should know wether they are 360 or not, if using AUTO + // each source should know whatever they are 360 or not, if using AUTO if ( this.player_.mediainfo && this.player_.mediainfo.projection && @@ -48562,31 +49761,40 @@ var autoProjection = getInternalProjectionName( this.player_.mediainfo.projection ); - return this.changeProjection_(autoProjection); } + return this.changeProjection_("NONE"); } else if (projection === "360") { - this.movieGeometry = new SphereBufferGeometry(256, 32, 32); + this.movieGeometry = new SphereBufferGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); this.movieMaterial = new MeshBasicMaterial({ map: this.videoTexture, overdraw: true, side: BackSide, }); - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); this.movieScreen.position.set(position.x, position.y, position.z); - this.movieScreen.scale.x = -1; this.movieScreen.quaternion.setFromAxisAngle( - { x: 0, y: 1, z: 0 }, + { + x: 0, + y: 1, + z: 0, + }, -Math.PI / 2 ); this.scene.add(this.movieScreen); } else if (projection === "360_LR" || projection === "360_TB") { - var geometry = new SphereGeometry(256, 32, 32); - // Left eye view + var geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); var uvs = geometry.faceVertexUvs[0]; for (var i = 0; i < uvs.length; i++) { @@ -48599,7 +49807,6 @@ } } } - geometry.scale(-1, 1, 1); this.movieGeometry = new BufferGeometry().fromGeometry(geometry); this.movieMaterial = new MeshBasicMaterial({ @@ -48607,16 +49814,25 @@ overdraw: true, side: BackSide, }); - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); - this.movieScreen.rotation.y = -Math.PI / 2; - // display in left eye only - this.movieScreen.layers.set(1); - this.scene.add(this.movieScreen); + this.movieScreen.scale.x = -1; + this.movieScreen.quaternion.setFromAxisAngle( + { + x: 0, + y: 1, + z: 0, + }, + -Math.PI / 2 + ); // display in left eye only - // Right eye view - geometry = new SphereGeometry(256, 32, 32); + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); // Right eye view + geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail + ); uvs = geometry.faceVertexUvs[0]; for (var _i = 0; _i < uvs.length; _i++) { @@ -48629,7 +49845,6 @@ } } } - geometry.scale(-1, 1, 1); this.movieGeometry = new BufferGeometry().fromGeometry(geometry); this.movieMaterial = new MeshBasicMaterial({ @@ -48637,10 +49852,17 @@ overdraw: true, side: BackSide, }); - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); - this.movieScreen.rotation.y = -Math.PI / 2; - // display in right eye only + this.movieScreen.scale.x = -1; + this.movieScreen.quaternion.setFromAxisAngle( + { + x: 0, + y: 1, + z: 0, + }, + -Math.PI / 2 + ); // display in right eye only + this.movieScreen.layers.set(2); this.scene.add(this.movieScreen); } else if (projection === "360_CUBE") { @@ -48650,7 +49872,6 @@ overdraw: true, side: BackSide, }); - var left = [ new Vector2(0, 0.5), new Vector2(0.333, 0.5), @@ -48687,18 +49908,13 @@ new Vector2(1, 0.5), new Vector2(0.666, 0.5), ]; - this.movieGeometry.faceVertexUvs[0] = []; - this.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]]; this.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]]; - this.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; this.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; - this.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; this.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; - this.movieGeometry.faceVertexUvs[0][6] = [ bottom[2], bottom[1], @@ -48709,37 +49925,293 @@ bottom[0], bottom[3], ]; - this.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]]; this.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]]; - this.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; this.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; - this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); this.movieScreen.position.set(position.x, position.y, position.z); this.movieScreen.rotation.y = -Math.PI; + this.scene.add(this.movieScreen); + } else if ( + projection === "180" || + projection === "180_LR" || + projection === "180_MONO" + ) { + var _geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail, + Math.PI, + Math.PI + ); // Left eye view + + _geometry.scale(-1, 1, 1); + + var _uvs = _geometry.faceVertexUvs[0]; + + if (projection !== "180_MONO") { + for (var _i2 = 0; _i2 < _uvs.length; _i2++) { + for (var _j2 = 0; _j2 < 3; _j2++) { + _uvs[_i2][_j2].x *= 0.5; + } + } + } + this.movieGeometry = new BufferGeometry().fromGeometry(_geometry); + this.movieMaterial = new MeshBasicMaterial({ + map: this.videoTexture, + overdraw: true, + }); + this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in left eye only + + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); // Right eye view + + _geometry = new SphereGeometry( + 256, + this.options_.sphereDetail, + this.options_.sphereDetail, + Math.PI, + Math.PI + ); + + _geometry.scale(-1, 1, 1); + + _uvs = _geometry.faceVertexUvs[0]; + + for (var _i3 = 0; _i3 < _uvs.length; _i3++) { + for (var _j3 = 0; _j3 < 3; _j3++) { + _uvs[_i3][_j3].x *= 0.5; + _uvs[_i3][_j3].x += 0.5; + } + } + + this.movieGeometry = new BufferGeometry().fromGeometry(_geometry); + this.movieMaterial = new MeshBasicMaterial({ + map: this.videoTexture, + overdraw: true, + }); + this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in right eye only + + this.movieScreen.layers.set(2); this.scene.add(this.movieScreen); + } else if (projection === "EAC" || projection === "EAC_LR") { + var makeScreen = function makeScreen(mapMatrix, scaleMatrix) { + // "Continuity correction?": because of discontinuous faces and aliasing, + // we truncate the 2-pixel-wide strips on all discontinuous edges, + var contCorrect = 2; + _this2.movieGeometry = new BoxGeometry(256, 256, 256); + _this2.movieMaterial = new ShaderMaterial({ + overdraw: true, + side: BackSide, + uniforms: { + mapped: { + value: _this2.videoTexture, + }, + mapMatrix: { + value: mapMatrix, + }, + contCorrect: { + value: contCorrect, + }, + faceWH: { + value: new Vector2(1 / 3, 1 / 2).applyMatrix3(scaleMatrix), + }, + vidWH: { + value: new Vector2( + _this2.videoTexture.image.videoWidth, + _this2.videoTexture.image.videoHeight + ).applyMatrix3(scaleMatrix), + }, + }, + vertexShader: + "\nvarying vec2 vUv;\nuniform mat3 mapMatrix;\n\nvoid main() {\n vUv = (mapMatrix * vec3(uv, 1.)).xy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);\n}", + fragmentShader: + "\nvarying vec2 vUv;\nuniform sampler2D mapped;\nuniform vec2 faceWH;\nuniform vec2 vidWH;\nuniform float contCorrect;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvoid main() {\n vec2 corner = vUv - mod(vUv, faceWH) + vec2(0, contCorrect / vidWH.y);\n\n vec2 faceWHadj = faceWH - vec2(0, contCorrect * 2. / vidWH.y);\n\n vec2 p = (vUv - corner) / faceWHadj - .5;\n vec2 q = 2. / PI * atan(2. * p) + .5;\n\n vec2 eUv = corner + q * faceWHadj;\n\n gl_FragColor = texture2D(mapped, eUv);\n}", + }); + var right = [ + new Vector2(0, 1 / 2), + new Vector2(1 / 3, 1 / 2), + new Vector2(1 / 3, 1), + new Vector2(0, 1), + ]; + var front = [ + new Vector2(1 / 3, 1 / 2), + new Vector2(2 / 3, 1 / 2), + new Vector2(2 / 3, 1), + new Vector2(1 / 3, 1), + ]; + var left = [ + new Vector2(2 / 3, 1 / 2), + new Vector2(1, 1 / 2), + new Vector2(1, 1), + new Vector2(2 / 3, 1), + ]; + var bottom = [ + new Vector2(1 / 3, 0), + new Vector2(1 / 3, 1 / 2), + new Vector2(0, 1 / 2), + new Vector2(0, 0), + ]; + var back = [ + new Vector2(1 / 3, 1 / 2), + new Vector2(1 / 3, 0), + new Vector2(2 / 3, 0), + new Vector2(2 / 3, 1 / 2), + ]; + var top = [ + new Vector2(1, 0), + new Vector2(1, 1 / 2), + new Vector2(2 / 3, 1 / 2), + new Vector2(2 / 3, 0), + ]; + + for ( + var _i4 = 0, _arr = [right, front, left, bottom, back, top]; + _i4 < _arr.length; + _i4++ + ) { + var face = _arr[_i4]; + var height = _this2.videoTexture.image.videoHeight; + var lowY = 1; + var highY = 0; + + for ( + var _iterator = _createForOfIteratorHelperLoose(face), _step; + !(_step = _iterator()).done; + + ) { + var vector = _step.value; + + if (vector.y < lowY) { + lowY = vector.y; + } + + if (vector.y > highY) { + highY = vector.y; + } + } + + for ( + var _iterator2 = _createForOfIteratorHelperLoose(face), _step2; + !(_step2 = _iterator2()).done; + + ) { + var _vector = _step2.value; + + if (Math.abs(_vector.y - lowY) < Number.EPSILON) { + _vector.y += contCorrect / height; + } + + if (Math.abs(_vector.y - highY) < Number.EPSILON) { + _vector.y -= contCorrect / height; + } + + _vector.x = + (_vector.x / height) * (height - contCorrect * 2) + + contCorrect / height; + } + } + + _this2.movieGeometry.faceVertexUvs[0] = []; + _this2.movieGeometry.faceVertexUvs[0][0] = [ + right[2], + right[1], + right[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][1] = [ + right[1], + right[0], + right[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][2] = [ + left[2], + left[1], + left[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][3] = [ + left[1], + left[0], + left[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; + _this2.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; + _this2.movieGeometry.faceVertexUvs[0][6] = [ + bottom[2], + bottom[1], + bottom[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][7] = [ + bottom[1], + bottom[0], + bottom[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][8] = [ + front[2], + front[1], + front[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][9] = [ + front[1], + front[0], + front[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][10] = [ + back[2], + back[1], + back[3], + ]; + _this2.movieGeometry.faceVertexUvs[0][11] = [ + back[1], + back[0], + back[3], + ]; + _this2.movieScreen = new Mesh( + _this2.movieGeometry, + _this2.movieMaterial + ); + + _this2.movieScreen.position.set(position.x, position.y, position.z); + + _this2.movieScreen.rotation.y = -Math.PI; + return _this2.movieScreen; + }; + + if (projection === "EAC") { + this.scene.add(makeScreen(new Matrix3(), new Matrix3())); + } else { + var scaleMatrix = new Matrix3().set(0, 0.5, 0, 1, 0, 0, 0, 0, 1); + makeScreen( + new Matrix3().set(0, -0.5, 0.5, 1, 0, 0, 0, 0, 1), + scaleMatrix + ); // display in left eye only + + this.movieScreen.layers.set(1); + this.scene.add(this.movieScreen); + makeScreen( + new Matrix3().set(0, -0.5, 1, 1, 0, 0, 0, 0, 1), + scaleMatrix + ); // display in right eye only + + this.movieScreen.layers.set(2); + this.scene.add(this.movieScreen); + } } this.currentProjection_ = projection; }; - VR.prototype.triggerError_ = function triggerError_(errorObj) { + _proto.triggerError_ = function triggerError_(errorObj) { // if we have videojs-errors use it if (this.videojsErrorsSupport_) { - this.player_.error(errorObj); - // if we don't have videojs-errors just use a normal player error + this.player_.error(errorObj); // if we don't have videojs-errors just use a normal player error } else { // strip any html content from the error message // as it is not supported outside of videojs-errors - var div = document_1.createElement("div"); - + var div = document$1.createElement("div"); div.innerHTML = errors[errorObj.code].message; - var message = div.textContent || div.innerText || ""; - this.player_.error({ code: errorObj.code, message: message, @@ -48747,13 +50219,13 @@ } }; - VR.prototype.log = function log() { + _proto.log = function log() { if (!this.options_.debug) { return; } for ( - var _len = arguments.length, msgs = Array(_len), _key = 0; + var _len = arguments.length, msgs = new Array(_len), _key = 0; _key < _len; _key++ ) { @@ -48761,105 +50233,112 @@ } msgs.forEach(function (msg) { - videojs.log(msg); + videojs.log("VR: ", msg); }); }; - VR.prototype.handleVrDisplayActivate_ = - function handleVrDisplayActivate_() { - var _this2 = this; + _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { + var _this3 = this; - if (!this.vrDisplay) { - return; - } - this.vrDisplay - .requestPresent([{ source: this.renderedCanvas }]) - .then(function () { - if (!_this2.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { - return; - } + if (!this.vrDisplay) { + return; + } - // webvr-polyfill/cardboard ui only watches for click events - // to tell that the back arrow button is pressed during cardboard vr. - // but somewhere along the line these events are silenced with preventDefault - // but only on iOS, so we translate them ourselves here - var touches = []; - var iosCardboardTouchStart_ = function iosCardboardTouchStart_(e) { - for (var i = 0; i < e.touches.length; i++) { - touches.push(e.touches[i]); - } - }; + this.vrDisplay + .requestPresent([ + { + source: this.renderedCanvas, + }, + ]) + .then(function () { + if (!_this3.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { + return; + } // webvr-polyfill/cardboard ui only watches for click events + // to tell that the back arrow button is pressed during cardboard vr. + // but somewhere along the line these events are silenced with preventDefault + // but only on iOS, so we translate them ourselves here - var iosCardboardTouchEnd_ = function iosCardboardTouchEnd_(e) { - if (!touches.length) { - return; - } + var touches = []; + + var iosCardboardTouchStart_ = function iosCardboardTouchStart_(e) { + for (var i = 0; i < e.touches.length; i++) { + touches.push(e.touches[i]); + } + }; - touches.forEach(function (t) { - var simulatedClick = new window_1.MouseEvent("click", { - screenX: t.screenX, - screenY: t.screenY, - clientX: t.clientX, - clientY: t.clientY, - }); + var iosCardboardTouchEnd_ = function iosCardboardTouchEnd_(e) { + if (!touches.length) { + return; + } - _this2.renderedCanvas.dispatchEvent(simulatedClick); + touches.forEach(function (t) { + var simulatedClick = new window$1.MouseEvent("click", { + screenX: t.screenX, + screenY: t.screenY, + clientX: t.clientX, + clientY: t.clientY, }); - touches = []; - }; + _this3.renderedCanvas.dispatchEvent(simulatedClick); + }); + touches = []; + }; + + _this3.renderedCanvas.addEventListener( + "touchstart", + iosCardboardTouchStart_ + ); + + _this3.renderedCanvas.addEventListener( + "touchend", + iosCardboardTouchEnd_ + ); - _this2.renderedCanvas.addEventListener( + _this3.iosRevertTouchToClick_ = function () { + _this3.renderedCanvas.removeEventListener( "touchstart", iosCardboardTouchStart_ ); - _this2.renderedCanvas.addEventListener( + + _this3.renderedCanvas.removeEventListener( "touchend", iosCardboardTouchEnd_ ); - _this2.iosRevertTouchToClick_ = function () { - _this2.renderedCanvas.removeEventListener( - "touchstart", - iosCardboardTouchStart_ - ); - _this2.renderedCanvas.removeEventListener( - "touchend", - iosCardboardTouchEnd_ - ); - _this2.iosRevertTouchToClick_ = null; - }; - }); - }; + _this3.iosRevertTouchToClick_ = null; + }; + }); + }; - VR.prototype.handleVrDisplayDeactivate_ = - function handleVrDisplayDeactivate_() { - if (!this.vrDisplay || !this.vrDisplay.isPresenting) { - return; - } - if (this.iosRevertTouchToClick_) { - this.iosRevertTouchToClick_(); - } - this.vrDisplay.exitPresent(); - }; + _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { + if (!this.vrDisplay || !this.vrDisplay.isPresenting) { + return; + } - VR.prototype.requestAnimationFrame = function requestAnimationFrame(fn) { + if (this.iosRevertTouchToClick_) { + this.iosRevertTouchToClick_(); + } + + this.vrDisplay.exitPresent(); + }; + + _proto.requestAnimationFrame = function requestAnimationFrame(fn) { if (this.vrDisplay) { return this.vrDisplay.requestAnimationFrame(fn); } - return Component.prototype.requestAnimationFrame.call(this, fn); + return this.player_.requestAnimationFrame(fn); }; - VR.prototype.cancelAnimationFrame = function cancelAnimationFrame(id) { + _proto.cancelAnimationFrame = function cancelAnimationFrame(id) { if (this.vrDisplay) { return this.vrDisplay.cancelAnimationFrame(id); } - return Component.prototype.cancelAnimationFrame.call(this, id); + return this.player_.cancelAnimationFrame(id); }; - VR.prototype.togglePlay_ = function togglePlay_() { + _proto.togglePlay_ = function togglePlay_() { if (this.player_.paused()) { this.player_.play(); } else { @@ -48867,10 +50346,11 @@ } }; - VR.prototype.animate_ = function animate_() { + _proto.animate_ = function animate_() { if (!this.initialized_) { return; } + if ( this.getVideoEl_().readyState === this.getVideoEl_().HAVE_ENOUGH_DATA ) { @@ -48880,17 +50360,21 @@ } this.controls3d.update(); + + if (this.omniController) { + this.omniController.update(this.camera); + } + this.effect.render(this.scene, this.camera); - if (window_1.navigator.getGamepads) { + if (window$1.navigator.getGamepads) { // Grab all gamepads - var gamepads = window_1.navigator.getGamepads(); + var gamepads = window$1.navigator.getGamepads(); for (var i = 0; i < gamepads.length; ++i) { - var gamepad = gamepads[i]; - - // Make sure gamepad is defined + var gamepad = gamepads[i]; // Make sure gamepad is defined // Only take input if state has changed since we checked last + if ( !gamepad || !gamepad.timestamp || @@ -48898,6 +50382,7 @@ ) { continue; } + for (var j = 0; j < gamepad.buttons.length; ++j) { if (gamepad.buttons[j].pressed) { this.togglePlay_(); @@ -48907,21 +50392,20 @@ } } } - this.camera.getWorldDirection(this.cameraVector); + this.camera.getWorldDirection(this.cameraVector); this.animationFrameId_ = this.requestAnimationFrame(this.animate_); }; - VR.prototype.handleResize_ = function handleResize_() { + _proto.handleResize_ = function handleResize_() { var width = this.player_.currentWidth(); var height = this.player_.currentHeight(); - this.effect.setSize(width, height, false); this.camera.aspect = width / height; this.camera.updateProjectionMatrix(); }; - VR.prototype.setProjection = function setProjection(projection) { + _proto.setProjection = function setProjection(projection) { if (!getInternalProjectionName(projection)) { videojs.log.error( "videojs-vr: please pass a valid projection " + @@ -48934,38 +50418,39 @@ this.defaultProjection_ = projection; }; - VR.prototype.init = function init() { - var _this3 = this; + _proto.init = function init() { + var _this4 = this; this.reset(); - this.camera = new PerspectiveCamera( 75, this.player_.currentWidth() / this.player_.currentHeight(), 1, 1000 - ); - // Store vector representing the direction in which the camera is looking, in world space. + ); // Store vector representing the direction in which the camera is looking, in world space. + this.cameraVector = new Vector3(); if ( this.currentProjection_ === "360_LR" || - this.currentProjection_ === "360_TB" + this.currentProjection_ === "360_TB" || + this.currentProjection_ === "180" || + this.currentProjection_ === "180_LR" || + this.currentProjection_ === "180_MONO" || + this.currentProjection_ === "EAC_LR" ) { // Render left eye when not in VR mode this.camera.layers.enable(1); } this.scene = new Scene(); - this.videoTexture = new VideoTexture(this.getVideoEl_()); - - // shared regardless of wether VideoTexture is used or + this.videoTexture = new VideoTexture(this.getVideoEl_()); // shared regardless of wether VideoTexture is used or // an image canvas is used + this.videoTexture.generateMipmaps = false; this.videoTexture.minFilter = LinearFilter; this.videoTexture.magFilter = LinearFilter; this.videoTexture.format = RGBFormat; - this.changeProjection_(this.currentProjection_); if (this.currentProjection_ === "NONE") { @@ -48976,52 +50461,56 @@ this.player_.removeChild("BigPlayButton"); this.player_.addChild("BigVrPlayButton", {}, this.bigPlayButtonIndex_); - this.player_.bigPlayButton = this.player_.getChild("BigVrPlayButton"); + this.player_.bigPlayButton = this.player_.getChild("BigVrPlayButton"); // mobile devices, or cardboard forced to on - // mobile devices, or cardboard forced to on if ( this.options_.forceCardboard || videojs.browser.IS_ANDROID || videojs.browser.IS_IOS ) { this.addCardboardButton_(); - } + } // if ios remove full screen toggle - // if ios remove full screen toggle - if (videojs.browser.IS_IOS) { + if ( + videojs.browser.IS_IOS && + this.player_.controlBar && + this.player_.controlBar.fullscreenToggle + ) { this.player_.controlBar.fullscreenToggle.hide(); } this.camera.position.set(0, 0, 0); this.renderer = new WebGLRenderer({ - devicePixelRatio: window_1.devicePixelRatio, + devicePixelRatio: window$1.devicePixelRatio, alpha: false, clearColor: 0xffffff, antialias: true, }); - var webglContext = this.renderer.getContext("webgl"); var oldTexImage2D = webglContext.texImage2D; - /* this is a workaround since threejs uses try catch */ - webglContext.texImage2D = function () { - for ( - var _len2 = arguments.length, args = Array(_len2), _key2 = 0; - _key2 < _len2; - _key2++ - ) { - args[_key2] = arguments[_key2]; - } + webglContext.texImage2D = function () { try { + for ( + var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; + _key2 < _len2; + _key2++ + ) { + args[_key2] = arguments[_key2]; + } + return oldTexImage2D.apply(webglContext, args); } catch (e) { - _this3.reset(); - _this3.player_.pause(); - _this3.triggerError_({ + _this4.reset(); + + _this4.player_.pause(); + + _this4.triggerError_({ code: "web-vr-hls-cors-not-supported", dismiss: false, }); + throw new Error(e); } }; @@ -49032,158 +50521,207 @@ false ); this.effect = new VREffect(this.renderer); - this.effect.setSize( this.player_.currentWidth(), this.player_.currentHeight(), false ); - this.vrDisplay = null; + this.vrDisplay = null; // Previous timestamps for gamepad updates - // Previous timestamps for gamepad updates this.prevTimestamps_ = []; - this.renderedCanvas = this.renderer.domElement; this.renderedCanvas.setAttribute( "style", "width: 100%; height: 100%; position: absolute; top:0;" ); + var videoElStyle = this.getVideoEl_().style; this.player_ .el() .insertBefore(this.renderedCanvas, this.player_.el().firstChild); - this.getVideoEl_().style.display = "none"; + videoElStyle.zIndex = "-1"; + videoElStyle.opacity = "0"; - if (window_1.navigator.getVRDisplays) { - this.log("VR is supported, getting vr displays"); - window_1.navigator.getVRDisplays().then(function (displays) { + if (window$1.navigator.getVRDisplays) { + this.log("is supported, getting vr displays"); + window$1.navigator.getVRDisplays().then(function (displays) { if (displays.length > 0) { - _this3.log("VR Displays found", displays); - _this3.vrDisplay = displays[0]; + _this4.log("Displays found", displays); - // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive + _this4.vrDisplay = displays[0]; // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive // also need the cardboard button to enter fully immersive mode // so, we want to add the button if we're not polyfilled. - if (!_this3.vrDisplay.isPolyfilled) { - _this3.log("Real HMD found using VRControls", _this3.vrDisplay); - _this3.addCardboardButton_(); - // We use VRControls here since we are working with an HMD + if (!_this4.vrDisplay.isPolyfilled) { + _this4.log("Real HMD found using VRControls", _this4.vrDisplay); + + _this4.addCardboardButton_(); // We use VRControls here since we are working with an HMD // and we only want orientation controls. - _this3.controls3d = new VRControls(_this3.camera); + + _this4.controls3d = new VRControls(_this4.camera); } } - if (!_this3.controls3d) { - _this3.log("no HMD found Using Orbit & Orientation Controls"); - _this3.controls3d = new OrbitOrientationControls({ - camera: _this3.camera, - canvas: _this3.renderedCanvas, + if (!_this4.controls3d) { + _this4.log("no HMD found Using Orbit & Orientation Controls"); + + var options = { + camera: _this4.camera, + canvas: _this4.renderedCanvas, + // check if its a half sphere view projection + halfView: _this4.currentProjection_.indexOf("180") === 0, orientation: videojs.browser.IS_IOS || videojs.browser.IS_ANDROID || false, - }); + }; + + if (_this4.options_.motionControls === false) { + options.orientation = false; + } + + _this4.controls3d = new OrbitOrientationControls(options); + _this4.canvasPlayerControls = new CanvasPlayerControls( + _this4.player_, + _this4.renderedCanvas, + _this4.options_ + ); } - _this3.animationFrameId_ = _this3.requestAnimationFrame( - _this3.animate_ + + _this4.animationFrameId_ = _this4.requestAnimationFrame( + _this4.animate_ ); }); - } else if (window_1.navigator.getVRDevices) { - this.triggerError_({ code: "web-vr-out-of-date", dismiss: false }); + } else if (window$1.navigator.getVRDevices) { + this.triggerError_({ + code: "web-vr-out-of-date", + dismiss: false, + }); } else { - this.triggerError_({ code: "web-vr-not-supported", dismiss: false }); + this.triggerError_({ + code: "web-vr-not-supported", + dismiss: false, + }); + } + + if (this.options_.omnitone) { + var audiocontext = AudioContext.getContext(); + this.omniController = new OmnitoneController( + audiocontext, + this.options_.omnitone, + this.getVideoEl_(), + this.options_.omnitoneOptions + ); + this.omniController.one("audiocontext-suspended", function () { + _this4.player.pause(); + + _this4.player.one("playing", function () { + audiocontext.resume(); + }); + }); } this.on(this.player_, "fullscreenchange", this.handleResize_); - window_1.addEventListener( + window$1.addEventListener( "vrdisplaypresentchange", this.handleResize_, true ); - window_1.addEventListener("resize", this.handleResize_, true); - window_1.addEventListener( + window$1.addEventListener("resize", this.handleResize_, true); + window$1.addEventListener( "vrdisplayactivate", this.handleVrDisplayActivate_, true ); - window_1.addEventListener( + window$1.addEventListener( "vrdisplaydeactivate", this.handleVrDisplayDeactivate_, true ); - this.initialized_ = true; + this.trigger("initialized"); }; - VR.prototype.addCardboardButton_ = function addCardboardButton_() { + _proto.addCardboardButton_ = function addCardboardButton_() { if (!this.player_.controlBar.getChild("CardboardButton")) { this.player_.controlBar.addChild("CardboardButton", {}); } }; - VR.prototype.getVideoEl_ = function getVideoEl_() { + _proto.getVideoEl_ = function getVideoEl_() { return this.player_.el().getElementsByTagName("video")[0]; }; - VR.prototype.reset = function reset() { + _proto.reset = function reset() { if (!this.initialized_) { return; } + if (this.omniController) { + this.omniController.off("audiocontext-suspended"); + this.omniController.dispose(); + this.omniController = undefined; + } + if (this.controls3d) { this.controls3d.dispose(); + this.controls3d = null; + } + + if (this.canvasPlayerControls) { + this.canvasPlayerControls.dispose(); + this.canvasPlayerControls = null; } + if (this.effect) { this.effect.dispose(); + this.effect = null; } - window_1.removeEventListener("resize", this.handleResize_); - window_1.removeEventListener( + window$1.removeEventListener("resize", this.handleResize_, true); + window$1.removeEventListener( "vrdisplaypresentchange", - this.handleResize_ + this.handleResize_, + true ); - window_1.removeEventListener( + window$1.removeEventListener( "vrdisplayactivate", - this.handleVrDisplayActivate_ + this.handleVrDisplayActivate_, + true ); - window_1.removeEventListener( + window$1.removeEventListener( "vrdisplaydeactivate", - this.handleVrDisplayDeactivate_ - ); + this.handleVrDisplayDeactivate_, + true + ); // re-add the big play button to player - // re-add the big play button to player if (!this.player_.getChild("BigPlayButton")) { this.player_.addChild("BigPlayButton", {}, this.bigPlayButtonIndex_); } if (this.player_.getChild("BigVrPlayButton")) { this.player_.removeChild("BigVrPlayButton"); - } + } // remove the cardboard button - // remove the cardboard button if (this.player_.getChild("CardboardButton")) { this.player_.controlBar.removeChild("CardboardButton"); - } + } // show the fullscreen again - // show the fullscreen again - if (videojs.browser.IS_IOS) { + if ( + videojs.browser.IS_IOS && + this.player_.controlBar && + this.player_.controlBar.fullscreenToggle + ) { this.player_.controlBar.fullscreenToggle.show(); - } - - // reset the video element style so that it will be displayed - this.getVideoEl_().style.display = ""; + } // reset the video element style so that it will be displayed - // set the current projection to the default - this.currentProjection_ = this.defaultProjection_; + var videoElStyle = this.getVideoEl_().style; + videoElStyle.zIndex = ""; + videoElStyle.opacity = ""; // set the current projection to the default - if (this.observer_) { - this.observer_.disconnect(); - } + this.currentProjection_ = this.defaultProjection_; // reset the ios touch to click workaround - // reset the ios touch to click workaround if (this.iosRevertTouchToClick_) { this.iosRevertTouchToClick_(); - } + } // remove the old canvas - // remove the old canvas if (this.renderedCanvas) { this.renderedCanvas.parentNode.removeChild(this.renderedCanvas); } @@ -49195,12 +50733,13 @@ this.initialized_ = false; }; - VR.prototype.dispose = function dispose() { + _proto.dispose = function dispose() { _Plugin.prototype.dispose.call(this); + this.reset(); }; - VR.prototype.polyfillVersion = function polyfillVersion() { + _proto.polyfillVersion = function polyfillVersion() { return WebVRPolyfill.version; }; @@ -49209,9 +50748,7 @@ VR.prototype.setTimeout = Component.prototype.setTimeout; VR.prototype.clearTimeout = Component.prototype.clearTimeout; - VR.VERSION = version; - videojs.registerPlugin("vr", VR); return VR; diff --git a/pod/main/static/videojs-vr/videojs-vr.min.js b/pod/main/static/videojs-vr/videojs-vr.min.js index f42640131e..c4ae5d213b 100644 --- a/pod/main/static/videojs-vr/videojs-vr.min.js +++ b/pod/main/static/videojs-vr/videojs-vr.min.js @@ -1,181 +1,180 @@ +/*! @name videojs-vr @version 1.8.0 @license Apache-2.0 */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("global/window"),require("global/document"),require("video.js")):"function"==typeof define&&define.amd?define(["global/window","global/document","video.js"],t):(e=e||self).videojsVr=t(e.window,e.document,e.videojs)}(this,(function(e,t,i){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e,t=t&&t.hasOwnProperty("default")?t.default:t,i=i&&i.hasOwnProperty("default")?i.default:i;var r="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function a(e,t){return e(t={exports:{}},t.exports),t.exports}var o=n(a((function(e){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e},e.exports.default=e.exports,e.exports.__esModule=!0}))),s=a((function(e){function t(i,r){return e.exports=t=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},e.exports.default=e.exports,e.exports.__esModule=!0,t(i,r)}e.exports=t,e.exports.default=e.exports,e.exports.__esModule=!0}));n(s);var c=n(a((function(e){e.exports=function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,s(e,t)},e.exports.default=e.exports,e.exports.__esModule=!0}))),h=n(a((function(e,t){ /** - * videojs-vr - * @version 1.3.0 - * @copyright 2018 [object Object] - * @license Apache-2.0 - */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js")):"function"==typeof define&&define.amd?define(["video.js"],t):e.videojsVr=t(e.videojs)}(this,function(o){"use strict";o=o&&o.hasOwnProperty("default")?o["default"]:o;var l="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var e,c="undefined"!=typeof window?window:void 0!==l?l:"undefined"!=typeof self?self:{},t={},i=Object.freeze({"default":t}),n=i&&t||i,r=void 0!==l?l:"undefined"!=typeof window?window:{};"undefined"!=typeof document?e=document:(e=r["__GLOBAL_DOCUMENT_CACHE@4"])||(e=r["__GLOBAL_DOCUMENT_CACHE@4"]=n);var a,s,u=e,h=(function(e,t){ + * @license + * webvr-polyfill + * Copyright (c) 2015-2017 Google + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** - * @license - * webvr-polyfill - * Copyright (c) 2015-2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + * @license + * cardboard-vr-display + * Copyright (c) 2015-2017 Google + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** - * @license - * cardboard-vr-display - * Copyright (c) 2015-2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + * @license + * webvr-polyfill-dpdb + * Copyright (c) 2017 Google + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** - * @license - * webvr-polyfill-dpdb - * Copyright (c) 2017 Google - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + * @license + * wglu-preserve-state + * Copyright (c) 2016, Brandon Jones. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ /** - * @license - * wglu-preserve-state - * Copyright (c) 2016, Brandon Jones. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ + * @license + * nosleep.js + * Copyright (c) 2017, Rich Tibbett + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +e.exports=function(){var e,t="undefined"!=typeof window?window:void 0!==r?r:"undefined"!=typeof self?self:{},i=function(){return/Android/i.test(navigator.userAgent)||/iPhone|iPad|iPod/i.test(navigator.userAgent)},n=function(e,t){for(var i=0,r=e.length;ie.TEXTURE31){console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"),n.push(null,null);break}r||(r=e.getParameter(e.ACTIVE_TEXTURE)),e.activeTexture(o),n.push(e.getParameter(s),null);break;case e.ACTIVE_TEXTURE:r=e.getParameter(e.ACTIVE_TEXTURE),n.push(null);break;default:n.push(e.getParameter(s))}}i(e);for(var a=0;ae.TEXTURE31)break;e.activeTexture(o),e.bindTexture(e.TEXTURE_2D,c);break;case e.TEXTURE_BINDING_CUBE_MAP:var o=t[++a];if(oe.TEXTURE31)break;e.activeTexture(o),e.bindTexture(e.TEXTURE_CUBE_MAP,c);break;case e.VIEWPORT:e.viewport(c[0],c[1],c[2],c[3]);break;case e.BLEND:case e.CULL_FACE:case e.DEPTH_TEST:case e.SCISSOR_TEST:case e.STENCIL_TEST:c?e.enable(s):e.disable(s);break;default:console.log("No GL restore behavior for 0x"+s.toString(16))}r&&e.activeTexture(r)}}else i(e)},_=["attribute vec2 position;","attribute vec3 texCoord;","varying vec2 vTexCoord;","uniform vec4 viewportOffsetScale[2];","void main() {"," vec4 viewport = viewportOffsetScale[int(texCoord.z)];"," vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;"," gl_Position = vec4( position, 1.0, 1.0 );","}"].join("\n"),S=["precision mediump float;","uniform sampler2D diffuse;","varying vec2 vTexCoord;","void main() {"," gl_FragColor = texture2D(diffuse, vTexCoord);","}"].join("\n");function j(e,t,i,n){this.gl=e,this.cardboardUI=t,this.bufferScale=i,this.dirtySubmitFrameBindings=n,this.ctxAttribs=e.getContextAttributes(),this.meshWidth=20,this.meshHeight=20,this.bufferWidth=e.drawingBufferWidth,this.bufferHeight=e.drawingBufferHeight,this.realBindFramebuffer=e.bindFramebuffer,this.realEnable=e.enable,this.realDisable=e.disable,this.realColorMask=e.colorMask,this.realClearColor=e.clearColor,this.realViewport=e.viewport,l()||(this.realCanvasWidth=Object.getOwnPropertyDescriptor(e.canvas.__proto__,"width"),this.realCanvasHeight=Object.getOwnPropertyDescriptor(e.canvas.__proto__,"height")),this.isPatched=!1,this.lastBoundFramebuffer=null,this.cullFace=!1,this.depthTest=!1,this.blend=!1,this.scissorTest=!1,this.stencilTest=!1,this.viewport=[0,0,0,0],this.colorMask=[!0,!0,!0,!0],this.clearColor=[0,0,0,0],this.attribs={position:0,texCoord:1},this.program=A(e,_,S,this.attribs),this.uniforms=v(e,this.program),this.viewportOffsetScale=new Float32Array(8),this.setTextureBounds(),this.vertexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),this.indexCount=0,this.renderTarget=e.createTexture(),this.framebuffer=e.createFramebuffer(),this.depthStencilBuffer=null,this.depthBuffer=null,this.stencilBuffer=null,this.ctxAttribs.depth&&this.ctxAttribs.stencil?this.depthStencilBuffer=e.createRenderbuffer():this.ctxAttribs.depth?this.depthBuffer=e.createRenderbuffer():this.ctxAttribs.stencil&&(this.stencilBuffer=e.createRenderbuffer()),this.patch(),this.onResize()}j.prototype.destroy=function(){var e=this.gl;this.unpatch(),e.deleteProgram(this.program),e.deleteBuffer(this.vertexBuffer),e.deleteBuffer(this.indexBuffer),e.deleteTexture(this.renderTarget),e.deleteFramebuffer(this.framebuffer),this.depthStencilBuffer&&e.deleteRenderbuffer(this.depthStencilBuffer),this.depthBuffer&&e.deleteRenderbuffer(this.depthBuffer),this.stencilBuffer&&e.deleteRenderbuffer(this.stencilBuffer),this.cardboardUI&&this.cardboardUI.destroy()},j.prototype.onResize=function(){var e=this.gl,t=this,i=[e.RENDERBUFFER_BINDING,e.TEXTURE_BINDING_2D,e.TEXTURE0];I(e,i,function(e){t.realBindFramebuffer.call(e,e.FRAMEBUFFER,null),t.scissorTest&&t.realDisable.call(e,e.SCISSOR_TEST),t.realColorMask.call(e,!0,!0,!0,!0),t.realViewport.call(e,0,0,e.drawingBufferWidth,e.drawingBufferHeight),t.realClearColor.call(e,0,0,0,1),e.clear(e.COLOR_BUFFER_BIT),t.realBindFramebuffer.call(e,e.FRAMEBUFFER,t.framebuffer),e.bindTexture(e.TEXTURE_2D,t.renderTarget),e.texImage2D(e.TEXTURE_2D,0,t.ctxAttribs.alpha?e.RGBA:e.RGB,t.bufferWidth,t.bufferHeight,0,t.ctxAttribs.alpha?e.RGBA:e.RGB,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t.renderTarget,0),t.ctxAttribs.depth&&t.ctxAttribs.stencil?(e.bindRenderbuffer(e.RENDERBUFFER,t.depthStencilBuffer),e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,t.bufferWidth,t.bufferHeight),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t.depthStencilBuffer)):t.ctxAttribs.depth?(e.bindRenderbuffer(e.RENDERBUFFER,t.depthBuffer),e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,t.bufferWidth,t.bufferHeight),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t.depthBuffer)):t.ctxAttribs.stencil&&(e.bindRenderbuffer(e.RENDERBUFFER,t.stencilBuffer),e.renderbufferStorage(e.RENDERBUFFER,e.STENCIL_INDEX8,t.bufferWidth,t.bufferHeight),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.STENCIL_ATTACHMENT,e.RENDERBUFFER,t.stencilBuffer)),!e.checkFramebufferStatus(e.FRAMEBUFFER)===e.FRAMEBUFFER_COMPLETE&&console.error("Framebuffer incomplete!"),t.realBindFramebuffer.call(e,e.FRAMEBUFFER,t.lastBoundFramebuffer),t.scissorTest&&t.realEnable.call(e,e.SCISSOR_TEST),t.realColorMask.apply(e,t.colorMask),t.realViewport.apply(e,t.viewport),t.realClearColor.apply(e,t.clearColor)}),this.cardboardUI&&this.cardboardUI.onResize()},j.prototype.patch=function(){if(!this.isPatched){var r=this,t=this.gl.canvas,a=this.gl;l()||(t.width=m()*this.bufferScale,t.height=M()*this.bufferScale,Object.defineProperty(t,"width",{configurable:!0,enumerable:!0,get:function(){return r.bufferWidth},set:function(e){r.bufferWidth=e,r.realCanvasWidth.set.call(t,e),r.onResize()}}),Object.defineProperty(t,"height",{configurable:!0,enumerable:!0,get:function(){return r.bufferHeight},set:function(e){r.bufferHeight=e,r.realCanvasHeight.set.call(t,e),r.onResize()}})),this.lastBoundFramebuffer=a.getParameter(a.FRAMEBUFFER_BINDING),null==this.lastBoundFramebuffer&&(this.lastBoundFramebuffer=this.framebuffer,this.gl.bindFramebuffer(a.FRAMEBUFFER,this.framebuffer)),this.gl.bindFramebuffer=function(e,t){r.lastBoundFramebuffer=t||r.framebuffer,r.realBindFramebuffer.call(a,e,r.lastBoundFramebuffer)},this.cullFace=a.getParameter(a.CULL_FACE),this.depthTest=a.getParameter(a.DEPTH_TEST),this.blend=a.getParameter(a.BLEND),this.scissorTest=a.getParameter(a.SCISSOR_TEST),this.stencilTest=a.getParameter(a.STENCIL_TEST),a.enable=function(e){switch(e){case a.CULL_FACE:r.cullFace=!0;break;case a.DEPTH_TEST:r.depthTest=!0;break;case a.BLEND:r.blend=!0;break;case a.SCISSOR_TEST:r.scissorTest=!0;break;case a.STENCIL_TEST:r.stencilTest=!0}r.realEnable.call(a,e)},a.disable=function(e){switch(e){case a.CULL_FACE:r.cullFace=!1;break;case a.DEPTH_TEST:r.depthTest=!1;break;case a.BLEND:r.blend=!1;break;case a.SCISSOR_TEST:r.scissorTest=!1;break;case a.STENCIL_TEST:r.stencilTest=!1}r.realDisable.call(a,e)},this.colorMask=a.getParameter(a.COLOR_WRITEMASK),a.colorMask=function(e,t,i,n){r.colorMask[0]=e,r.colorMask[1]=t,r.colorMask[2]=i,r.colorMask[3]=n,r.realColorMask.call(a,e,t,i,n)},this.clearColor=a.getParameter(a.COLOR_CLEAR_VALUE),a.clearColor=function(e,t,i,n){r.clearColor[0]=e,r.clearColor[1]=t,r.clearColor[2]=i,r.clearColor[3]=n,r.realClearColor.call(a,e,t,i,n)},this.viewport=a.getParameter(a.VIEWPORT),a.viewport=function(e,t,i,n){r.viewport[0]=e,r.viewport[1]=t,r.viewport[2]=i,r.viewport[3]=n,r.realViewport.call(a,e,t,i,n)},this.isPatched=!0,T(t)}},j.prototype.unpatch=function(){if(this.isPatched){var e=this.gl,t=this.gl.canvas;l()||(Object.defineProperty(t,"width",this.realCanvasWidth),Object.defineProperty(t,"height",this.realCanvasHeight)),t.width=this.bufferWidth,t.height=this.bufferHeight,e.bindFramebuffer=this.realBindFramebuffer,e.enable=this.realEnable,e.disable=this.realDisable,e.colorMask=this.realColorMask,e.clearColor=this.realClearColor,e.viewport=this.realViewport,this.lastBoundFramebuffer==this.framebuffer&&e.bindFramebuffer(e.FRAMEBUFFER,null),this.isPatched=!1,setTimeout(function(){T(t)},1)}},j.prototype.setTextureBounds=function(e,t){e||(e=[0,0,.5,1]),t||(t=[.5,0,.5,1]),this.viewportOffsetScale[0]=e[0],this.viewportOffsetScale[1]=e[1],this.viewportOffsetScale[2]=e[2],this.viewportOffsetScale[3]=e[3],this.viewportOffsetScale[4]=t[0],this.viewportOffsetScale[5]=t[1],this.viewportOffsetScale[6]=t[2],this.viewportOffsetScale[7]=t[3]},j.prototype.submitFrame=function(){var e=this.gl,t=this,i=[];if(this.dirtySubmitFrameBindings||i.push(e.CURRENT_PROGRAM,e.ARRAY_BUFFER_BINDING,e.ELEMENT_ARRAY_BUFFER_BINDING,e.TEXTURE_BINDING_2D,e.TEXTURE0),I(e,i,function(e){t.realBindFramebuffer.call(e,e.FRAMEBUFFER,null),t.cullFace&&t.realDisable.call(e,e.CULL_FACE),t.depthTest&&t.realDisable.call(e,e.DEPTH_TEST),t.blend&&t.realDisable.call(e,e.BLEND),t.scissorTest&&t.realDisable.call(e,e.SCISSOR_TEST),t.stencilTest&&t.realDisable.call(e,e.STENCIL_TEST),t.realColorMask.call(e,!0,!0,!0,!0),t.realViewport.call(e,0,0,e.drawingBufferWidth,e.drawingBufferHeight),(t.ctxAttribs.alpha||l())&&(t.realClearColor.call(e,0,0,0,1),e.clear(e.COLOR_BUFFER_BIT)),e.useProgram(t.program),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,t.indexBuffer),e.bindBuffer(e.ARRAY_BUFFER,t.vertexBuffer),e.enableVertexAttribArray(t.attribs.position),e.enableVertexAttribArray(t.attribs.texCoord),e.vertexAttribPointer(t.attribs.position,2,e.FLOAT,!1,20,0),e.vertexAttribPointer(t.attribs.texCoord,3,e.FLOAT,!1,20,8),e.activeTexture(e.TEXTURE0),e.uniform1i(t.uniforms.diffuse,0),e.bindTexture(e.TEXTURE_2D,t.renderTarget),e.uniform4fv(t.uniforms.viewportOffsetScale,t.viewportOffsetScale),e.drawElements(e.TRIANGLES,t.indexCount,e.UNSIGNED_SHORT,0),t.cardboardUI&&t.cardboardUI.renderNoState(),t.realBindFramebuffer.call(t.gl,e.FRAMEBUFFER,t.framebuffer),t.ctxAttribs.preserveDrawingBuffer||(t.realClearColor.call(e,0,0,0,0),e.clear(e.COLOR_BUFFER_BIT)),t.dirtySubmitFrameBindings||t.realBindFramebuffer.call(e,e.FRAMEBUFFER,t.lastBoundFramebuffer),t.cullFace&&t.realEnable.call(e,e.CULL_FACE),t.depthTest&&t.realEnable.call(e,e.DEPTH_TEST),t.blend&&t.realEnable.call(e,e.BLEND),t.scissorTest&&t.realEnable.call(e,e.SCISSOR_TEST),t.stencilTest&&t.realEnable.call(e,e.STENCIL_TEST),t.realColorMask.apply(e,t.colorMask),t.realViewport.apply(e,t.viewport),!t.ctxAttribs.alpha&&t.ctxAttribs.preserveDrawingBuffer||t.realClearColor.apply(e,t.clearColor)}),l()){var n=e.canvas;n.width==t.bufferWidth&&n.height==t.bufferHeight||(t.bufferWidth=n.width,t.bufferHeight=n.height,t.onResize())}},j.prototype.updateDeviceInfo=function(n){var e=this.gl,r=this,t=[e.ARRAY_BUFFER_BINDING,e.ELEMENT_ARRAY_BUFFER_BINDING];I(e,t,function(e){var t=r.computeMeshVertices_(r.meshWidth,r.meshHeight,n);if(e.bindBuffer(e.ARRAY_BUFFER,r.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,t,e.STATIC_DRAW),!r.indexCount){var i=r.computeMeshIndices_(r.meshWidth,r.meshHeight);e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,r.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,i,e.STATIC_DRAW),r.indexCount=i.length}})},j.prototype.computeMeshVertices_=function(e,t,i){for(var n=new Float32Array(2*e*t*5),r=i.getLeftEyeVisibleTanAngles(),a=i.getLeftEyeNoLensTanAngles(),s=i.getLeftEyeVisibleScreenRect(a),o=0,c=0;c<2;c++){for(var u=0;ut-42&&e.clientXr.clientHeight-42?i(e):e.clientX<42&&e.clientY<42&&n(e)},r.addEventListener("click",this.listener,!1)},R.prototype.onResize=function(){var e=this.gl,g=this,t=[e.ARRAY_BUFFER_BINDING];I(e,t,function(i){var a=[],s=i.drawingBufferWidth/2,e=Math.max(screen.width,screen.height)*window.devicePixelRatio,t=i.drawingBufferWidth/e,n=t*window.devicePixelRatio,r=4*n/2,o=42*n,c=28*n/2,u=14*n;function h(e,t){var i=(90-e)*z,n=Math.cos(i),r=Math.sin(i);a.push(.3125*n*c+s,.3125*r*c+c),a.push(t*n*c+s,t*r*c+c)}a.push(s-r,o),a.push(s-r,i.drawingBufferHeight),a.push(s+r,o),a.push(s+r,i.drawingBufferHeight),g.gearOffset=a.length/2;for(var l=0;l<=6;l++){var d=60*l;h(d,1),h(d+12,1),h(d+20,.75),h(d+40,.75),h(d+48,1)}function p(e,t){a.push(u+e,i.drawingBufferHeight-u-t)}g.gearVertexCount=a.length/2-g.gearOffset,g.arrowOffset=a.length/2;var f=r/Math.sin(45*z);p(0,c),p(c,0),p(c+f,f),p(f,c+f),p(f,c-f),p(0,c),p(c,2*c),p(c+f,2*c-f),p(f,c-f),p(0,c),p(f,c-r),p(28*n,c-r),p(f,c+r),p(28*n,c+r),g.arrowVertexCount=a.length/2-g.arrowOffset,i.bindBuffer(i.ARRAY_BUFFER,g.vertexBuffer),i.bufferData(i.ARRAY_BUFFER,new Float32Array(a),i.STATIC_DRAW)})},R.prototype.render=function(){var e=this.gl,t=this,i=[e.CULL_FACE,e.DEPTH_TEST,e.BLEND,e.SCISSOR_TEST,e.STENCIL_TEST,e.COLOR_WRITEMASK,e.VIEWPORT,e.CURRENT_PROGRAM,e.ARRAY_BUFFER_BINDING];I(e,i,function(e){e.disable(e.CULL_FACE),e.disable(e.DEPTH_TEST),e.disable(e.BLEND),e.disable(e.SCISSOR_TEST),e.disable(e.STENCIL_TEST),e.colorMask(!0,!0,!0,!0),e.viewport(0,0,e.drawingBufferWidth,e.drawingBufferHeight),t.renderNoState()})},R.prototype.renderNoState=function(){var e,t,i,n,r,a,s,o,c,u,h=this.gl;h.useProgram(this.program),h.bindBuffer(h.ARRAY_BUFFER,this.vertexBuffer),h.enableVertexAttribArray(this.attribs.position),h.vertexAttribPointer(this.attribs.position,2,h.FLOAT,!1,8,0),h.uniform4f(this.uniforms.color,1,1,1,1),e=this.projMat,t=0,i=h.drawingBufferWidth,n=0,r=h.drawingBufferHeight,o=1/(t-i),c=1/(n-r),u=1/((a=.1)-(s=1024)),e[0]=-2*o,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*c,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*u,e[11]=0,e[12]=(t+i)*o,e[13]=(r+n)*c,e[14]=(s+a)*u,e[15]=1,h.uniformMatrix4fv(this.uniforms.projectionMat,!1,this.projMat),h.drawArrays(h.TRIANGLE_STRIP,0,4),h.drawArrays(h.TRIANGLE_STRIP,this.gearOffset,this.gearVertexCount),h.drawArrays(h.TRIANGLE_STRIP,this.arrowOffset,this.arrowVertexCount)},U.prototype.distortInverse=function(e){for(var t=0,i=1,n=e-this.distort(t);1e-4Math.abs(e.z)?F.set(-e.y,e.x,0):F.set(0,-e.z,e.y)):F.crossVectors(e,t),this.x=F.x,this.y=F.y,this.z=F.z,this.w=G,this.normalize(),this}};var H=new Y({widthMeters:.11,heightMeters:.062,bevelMeters:.004}),V=new Y({widthMeters:.1038,heightMeters:.0584,bevelMeters:.004}),W={CardboardV1:new Z({id:"CardboardV1",label:"Cardboard I/O 2014",fov:40,interLensDistance:.06,baselineLensDistance:.035,screenLensDistance:.042,distortionCoefficients:[.441,.156],inverseCoefficients:[-.4410035,.42756155,-.4804439,.5460139,-.58821183,.5733938,-.48303202,.33299083,-.17573841,.0651772,-.01488963,.001559834]}),CardboardV2:new Z({id:"CardboardV2",label:"Cardboard I/O 2015",fov:60,interLensDistance:.064,baselineLensDistance:.035,screenLensDistance:.039,distortionCoefficients:[.34,.55],inverseCoefficients:[-.33836704,-.18162185,.862655,-1.2462051,1.0560602,-.58208317,.21609078,-.05444823,.009177956,-.0009904169,6183535e-11,-16981803e-13]})};function X(e){this.viewer=W.CardboardV2,this.updateDeviceParams(e),this.distortion=new U(this.viewer.distortionCoefficients)}function Z(e){this.id=e.id,this.label=e.label,this.fov=e.fov,this.interLensDistance=e.interLensDistance,this.baselineLensDistance=e.baselineLensDistance,this.screenLensDistance=e.screenLensDistance,this.distortionCoefficients=e.distortionCoefficients,this.inverseCoefficients=e.inverseCoefficients}X.prototype.updateDeviceParams=function(e){this.device=this.determineDevice_(e)||this.device},X.prototype.getDevice=function(){return this.device},X.prototype.setViewer=function(e){this.viewer=e,this.distortion=new U(this.viewer.distortionCoefficients)},X.prototype.determineDevice_=function(e){if(!e)return l()?(console.warn("Using fallback iOS device measurements."),V):(console.warn("Using fallback Android device measurements."),H);var t=.0254/e.xdpi,i=.0254/e.ydpi,n=m(),r=M();return new Y({widthMeters:t*n,heightMeters:i*r,bevelMeters:.001*e.bevelMm})},X.prototype.getDistortedFieldOfViewLeftEye=function(){var e=this.viewer,t=this.device,i=this.distortion,n=e.screenLensDistance,r=(t.widthMeters-e.interLensDistance)/2,a=e.interLensDistance/2,s=e.baselineLensDistance-t.bevelMeters,o=t.heightMeters-s,c=B*Math.atan(i.distort(r/n)),u=B*Math.atan(i.distort(a/n)),h=B*Math.atan(i.distort(s/n)),l=B*Math.atan(i.distort(o/n));return{leftDegrees:Math.min(c,e.fov),rightDegrees:Math.min(u,e.fov),downDegrees:Math.min(h,e.fov),upDegrees:Math.min(l,e.fov)}},X.prototype.getLeftEyeVisibleTanAngles=function(){var e=this.viewer,t=this.device,i=this.distortion,n=Math.tan(-P*e.fov),r=Math.tan(P*e.fov),a=Math.tan(P*e.fov),s=Math.tan(-P*e.fov),o=t.widthMeters/4,c=t.heightMeters/2,u=e.baselineLensDistance-t.bevelMeters-c,h=e.interLensDistance/2-o,l=-u,d=e.screenLensDistance,p=i.distort((h-o)/d),f=i.distort((l+c)/d),g=i.distort((h+o)/d),m=i.distort((l-c)/d),M=new Float32Array(4);return M[0]=Math.max(n,p),M[1]=Math.min(r,f),M[2]=Math.min(a,g),M[3]=Math.max(s,m),M},X.prototype.getLeftEyeNoLensTanAngles=function(){var e=this.viewer,t=this.device,i=this.distortion,n=new Float32Array(4),r=i.distortInverse(Math.tan(-P*e.fov)),a=i.distortInverse(Math.tan(P*e.fov)),s=i.distortInverse(Math.tan(P*e.fov)),o=i.distortInverse(Math.tan(-P*e.fov)),c=t.widthMeters/4,u=t.heightMeters/2,h=e.baselineLensDistance-t.bevelMeters-u,l=e.interLensDistance/2-c,d=-h,p=e.screenLensDistance,f=(l-c)/p,g=(d+u)/p,m=(l+c)/p,M=(d-u)/p;return n[0]=Math.max(r,f),n[1]=Math.min(a,g),n[2]=Math.min(s,m),n[3]=Math.max(o,M),n},X.prototype.getLeftEyeVisibleScreenRect=function(e){var t=this.viewer,i=this.device,n=t.screenLensDistance,r=(i.widthMeters-t.interLensDistance)/2,a=t.baselineLensDistance-i.bevelMeters,s=(e[0]*n+r)/i.widthMeters,o=(e[1]*n+a)/i.heightMeters,c=(e[2]*n+r)/i.widthMeters,u=(e[3]*n+a)/i.heightMeters;return{x:s,y:u,width:c-s,height:o-u}},X.prototype.getFieldOfViewLeftEye=function(e){return e?this.getUndistortedFieldOfViewLeftEye():this.getDistortedFieldOfViewLeftEye()},X.prototype.getFieldOfViewRightEye=function(e){var t=this.getFieldOfViewLeftEye(e);return{leftDegrees:t.rightDegrees,rightDegrees:t.leftDegrees,upDegrees:t.upDegrees,downDegrees:t.downDegrees}},X.prototype.getUndistortedFieldOfViewLeftEye=function(){var e=this.getUndistortedParams_();return{leftDegrees:B*Math.atan(e.outerDist),rightDegrees:B*Math.atan(e.innerDist),downDegrees:B*Math.atan(e.bottomDist),upDegrees:B*Math.atan(e.topDist)}},X.prototype.getUndistortedViewportLeftEye=function(){var e=this.getUndistortedParams_(),t=this.viewer,i=this.device,n=t.screenLensDistance,r=i.widthMeters/n,a=i.heightMeters/n,s=i.width/r,o=i.height/a,c=Math.round((e.eyePosX-e.outerDist)*s),u=Math.round((e.eyePosY-e.bottomDist)*o);return{x:c,y:u,width:Math.round((e.eyePosX+e.innerDist)*s)-c,height:Math.round((e.eyePosY+e.topDist)*o)-u}},X.prototype.getUndistortedParams_=function(){var e=this.viewer,t=this.device,i=this.distortion,n=e.screenLensDistance,r=e.interLensDistance/2/n,a=t.widthMeters/n,s=t.heightMeters/n,o=a/2-r,c=(e.baselineLensDistance-t.bevelMeters)/n,u=e.fov,h=i.distortInverse(Math.tan(P*u)),l=Math.min(o,h),d=Math.min(r,h),p=Math.min(c,h),f=Math.min(s-c,h);return{outerDist:l,innerDist:d,topDist:f,bottomDist:p,eyePosX:o,eyePosY:c}},X.Viewers=W;var q={format:1,last_updated:"2018-02-20T22:55:10Z",devices:[{type:"android",rules:[{mdmh:"asus/*/Nexus 7/*"},{ua:"Nexus 7"}],dpi:[320.8,323],bw:3,ac:500},{type:"android",rules:[{mdmh:"asus/*/ASUS_Z00AD/*"},{ua:"ASUS_Z00AD"}],dpi:[403,404.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Google/*/Pixel XL/*"},{ua:"Pixel XL"}],dpi:[537.9,533],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Google/*/Pixel/*"},{ua:"Pixel"}],dpi:[432.6,436.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"HTC/*/HTC6435LVW/*"},{ua:"HTC6435LVW"}],dpi:[449.7,443.3],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"HTC/*/HTC One XL/*"},{ua:"HTC One XL"}],dpi:[315.3,314.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"htc/*/Nexus 9/*"},{ua:"Nexus 9"}],dpi:289,bw:3,ac:500},{type:"android",rules:[{mdmh:"HTC/*/HTC One M9/*"},{ua:"HTC One M9"}],dpi:[442.5,443.3],bw:3,ac:500},{type:"android",rules:[{mdmh:"HTC/*/HTC One_M8/*"},{ua:"HTC One_M8"}],dpi:[449.7,447.4],bw:3,ac:500},{type:"android",rules:[{mdmh:"HTC/*/HTC One/*"},{ua:"HTC One"}],dpi:472.8,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Huawei/*/Nexus 6P/*"},{ua:"Nexus 6P"}],dpi:[515.1,518],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LENOVO/*/Lenovo PB2-690Y/*"},{ua:"Lenovo PB2-690Y"}],dpi:[457.2,454.713],bw:3,ac:500},{type:"android",rules:[{mdmh:"LGE/*/Nexus 5X/*"},{ua:"Nexus 5X"}],dpi:[422,419.9],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LGE/*/LGMS345/*"},{ua:"LGMS345"}],dpi:[221.7,219.1],bw:3,ac:500},{type:"android",rules:[{mdmh:"LGE/*/LG-D800/*"},{ua:"LG-D800"}],dpi:[422,424.1],bw:3,ac:500},{type:"android",rules:[{mdmh:"LGE/*/LG-D850/*"},{ua:"LG-D850"}],dpi:[537.9,541.9],bw:3,ac:500},{type:"android",rules:[{mdmh:"LGE/*/VS985 4G/*"},{ua:"VS985 4G"}],dpi:[537.9,535.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LGE/*/Nexus 5/*"},{ua:"Nexus 5 B"}],dpi:[442.4,444.8],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LGE/*/Nexus 4/*"},{ua:"Nexus 4"}],dpi:[319.8,318.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LGE/*/LG-P769/*"},{ua:"LG-P769"}],dpi:[240.6,247.5],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LGE/*/LGMS323/*"},{ua:"LGMS323"}],dpi:[206.6,204.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"LGE/*/LGLS996/*"},{ua:"LGLS996"}],dpi:[403.4,401.5],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Micromax/*/4560MMX/*"},{ua:"4560MMX"}],dpi:[240,219.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Micromax/*/A250/*"},{ua:"Micromax A250"}],dpi:[480,446.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Micromax/*/Micromax AQ4501/*"},{ua:"Micromax AQ4501"}],dpi:240,bw:3,ac:500},{type:"android",rules:[{mdmh:"motorola/*/G5/*"},{ua:"Moto G (5) Plus"}],dpi:[403.4,403],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/DROID RAZR/*"},{ua:"DROID RAZR"}],dpi:[368.1,256.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/XT830C/*"},{ua:"XT830C"}],dpi:[254,255.9],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/XT1021/*"},{ua:"XT1021"}],dpi:[254,256.7],bw:3,ac:500},{type:"android",rules:[{mdmh:"motorola/*/XT1023/*"},{ua:"XT1023"}],dpi:[254,256.7],bw:3,ac:500},{type:"android",rules:[{mdmh:"motorola/*/XT1028/*"},{ua:"XT1028"}],dpi:[326.6,327.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/XT1034/*"},{ua:"XT1034"}],dpi:[326.6,328.4],bw:3,ac:500},{type:"android",rules:[{mdmh:"motorola/*/XT1053/*"},{ua:"XT1053"}],dpi:[315.3,316.1],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/XT1562/*"},{ua:"XT1562"}],dpi:[403.4,402.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/Nexus 6/*"},{ua:"Nexus 6 B"}],dpi:[494.3,489.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/XT1063/*"},{ua:"XT1063"}],dpi:[295,296.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/XT1064/*"},{ua:"XT1064"}],dpi:[295,295.6],bw:3,ac:500},{type:"android",rules:[{mdmh:"motorola/*/XT1092/*"},{ua:"XT1092"}],dpi:[422,424.1],bw:3,ac:500},{type:"android",rules:[{mdmh:"motorola/*/XT1095/*"},{ua:"XT1095"}],dpi:[422,423.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"motorola/*/G4/*"},{ua:"Moto G (4)"}],dpi:401,bw:4,ac:1e3},{type:"android",rules:[{mdmh:"OnePlus/*/A0001/*"},{ua:"A0001"}],dpi:[403.4,401],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"OnePlus/*/ONE E1005/*"},{ua:"ONE E1005"}],dpi:[442.4,441.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"OnePlus/*/ONE A2005/*"},{ua:"ONE A2005"}],dpi:[391.9,405.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"OnePlus/*/ONEPLUS A5000/*"},{ua:"ONEPLUS A5000 "}],dpi:[403.411,399.737],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"OnePlus/*/ONE A5010/*"},{ua:"ONEPLUS A5010"}],dpi:[403,400],bw:2,ac:1e3},{type:"android",rules:[{mdmh:"OPPO/*/X909/*"},{ua:"X909"}],dpi:[442.4,444.1],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-I9082/*"},{ua:"GT-I9082"}],dpi:[184.7,185.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G360P/*"},{ua:"SM-G360P"}],dpi:[196.7,205.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/Nexus S/*"},{ua:"Nexus S"}],dpi:[234.5,229.8],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-I9300/*"},{ua:"GT-I9300"}],dpi:[304.8,303.9],bw:5,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-T230NU/*"},{ua:"SM-T230NU"}],dpi:216,bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SGH-T399/*"},{ua:"SGH-T399"}],dpi:[217.7,231.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SGH-M919/*"},{ua:"SGH-M919"}],dpi:[440.8,437.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-N9005/*"},{ua:"SM-N9005"}],dpi:[386.4,387],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SAMSUNG-SM-N900A/*"},{ua:"SAMSUNG-SM-N900A"}],dpi:[386.4,387.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-I9500/*"},{ua:"GT-I9500"}],dpi:[442.5,443.3],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/GT-I9505/*"},{ua:"GT-I9505"}],dpi:439.4,bw:4,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G900F/*"},{ua:"SM-G900F"}],dpi:[415.6,431.6],bw:5,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G900M/*"},{ua:"SM-G900M"}],dpi:[415.6,431.6],bw:5,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G800F/*"},{ua:"SM-G800F"}],dpi:326.8,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G906S/*"},{ua:"SM-G906S"}],dpi:[562.7,572.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-I9300/*"},{ua:"GT-I9300"}],dpi:[306.7,304.8],bw:5,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-T535/*"},{ua:"SM-T535"}],dpi:[142.6,136.4],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-N920C/*"},{ua:"SM-N920C"}],dpi:[515.1,518.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-N920P/*"},{ua:"SM-N920P"}],dpi:[386.3655,390.144],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-N920W8/*"},{ua:"SM-N920W8"}],dpi:[515.1,518.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-I9300I/*"},{ua:"GT-I9300I"}],dpi:[304.8,305.8],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-I9195/*"},{ua:"GT-I9195"}],dpi:[249.4,256.7],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SPH-L520/*"},{ua:"SPH-L520"}],dpi:[249.4,255.9],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SAMSUNG-SGH-I717/*"},{ua:"SAMSUNG-SGH-I717"}],dpi:285.8,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SPH-D710/*"},{ua:"SPH-D710"}],dpi:[217.7,204.2],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/GT-N7100/*"},{ua:"GT-N7100"}],dpi:265.1,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SCH-I605/*"},{ua:"SCH-I605"}],dpi:265.1,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/Galaxy Nexus/*"},{ua:"Galaxy Nexus"}],dpi:[315.3,314.2],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-N910H/*"},{ua:"SM-N910H"}],dpi:[515.1,518],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-N910C/*"},{ua:"SM-N910C"}],dpi:[515.2,520.2],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-G130M/*"},{ua:"SM-G130M"}],dpi:[165.9,164.8],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-G928I/*"},{ua:"SM-G928I"}],dpi:[515.1,518.4],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G920F/*"},{ua:"SM-G920F"}],dpi:580.6,bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-G920P/*"},{ua:"SM-G920P"}],dpi:[522.5,577],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G925F/*"},{ua:"SM-G925F"}],dpi:580.6,bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-G925V/*"},{ua:"SM-G925V"}],dpi:[522.5,576.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G930F/*"},{ua:"SM-G930F"}],dpi:576.6,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"samsung/*/SM-G935F/*"},{ua:"SM-G935F"}],dpi:533,bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-G950F/*"},{ua:"SM-G950F"}],dpi:[562.707,565.293],bw:3,ac:500},{type:"android",rules:[{mdmh:"samsung/*/SM-G955U/*"},{ua:"SM-G955U"}],dpi:[522.514,525.762],bw:3,ac:500},{type:"android",rules:[{mdmh:"Sony/*/C6903/*"},{ua:"C6903"}],dpi:[442.5,443.3],bw:3,ac:500},{type:"android",rules:[{mdmh:"Sony/*/D6653/*"},{ua:"D6653"}],dpi:[428.6,427.6],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Sony/*/E6653/*"},{ua:"E6653"}],dpi:[428.6,425.7],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Sony/*/E6853/*"},{ua:"E6853"}],dpi:[403.4,401.9],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Sony/*/SGP321/*"},{ua:"SGP321"}],dpi:[224.7,224.1],bw:3,ac:500},{type:"android",rules:[{mdmh:"TCT/*/ALCATEL ONE TOUCH Fierce/*"},{ua:"ALCATEL ONE TOUCH Fierce"}],dpi:[240,247.5],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"THL/*/thl 5000/*"},{ua:"thl 5000"}],dpi:[480,443.3],bw:3,ac:1e3},{type:"android",rules:[{mdmh:"Fly/*/IQ4412/*"},{ua:"IQ4412"}],dpi:307.9,bw:3,ac:1e3},{type:"android",rules:[{mdmh:"ZTE/*/ZTE Blade L2/*"},{ua:"ZTE Blade L2"}],dpi:240,bw:3,ac:500},{type:"android",rules:[{mdmh:"BENEVE/*/VR518/*"},{ua:"VR518"}],dpi:480,bw:3,ac:500},{type:"ios",rules:[{res:[640,960]}],dpi:[325.1,328.4],bw:4,ac:1e3},{type:"ios",rules:[{res:[640,1136]}],dpi:[317.1,320.2],bw:3,ac:1e3},{type:"ios",rules:[{res:[750,1334]}],dpi:326.4,bw:4,ac:1e3},{type:"ios",rules:[{res:[1242,2208]}],dpi:[453.6,458.4],bw:4,ac:1e3},{type:"ios",rules:[{res:[1125,2001]}],dpi:[410.9,415.4],bw:4,ac:1e3},{type:"ios",rules:[{res:[1125,2436]}],dpi:458,bw:4,ac:1e3}]};function J(e,t){if(this.dpdb=q,this.recalculateDeviceParams_(),e){this.onDeviceParamsUpdated=t;var i=new XMLHttpRequest,n=this;i.open("GET",e,!0),i.addEventListener("load",function(){n.loading=!1,200<=i.status&&i.status<=299?(n.dpdb=JSON.parse(i.response),n.recalculateDeviceParams_()):console.error("Error loading online DPDB!")}),i.send()}}function K(e){this.xdpi=e.xdpi,this.ydpi=e.ydpi,this.bevelMm=e.bevelMm}function $(e,t){this.set(e,t)}function ee(e,t){this.kFilter=e,this.isDebug=t,this.currentAccelMeasurement=new $,this.currentGyroMeasurement=new $,this.previousGyroMeasurement=new $,l()?this.filterQ=new Q(-1,0,0,1):this.filterQ=new Q(1,0,0,1),this.previousFilterQ=new Q,this.previousFilterQ.copy(this.filterQ),this.accelQ=new Q,this.isOrientationInitialized=!1,this.estimatedGravity=new k,this.measuredGravity=new k,this.gyroIntegralQ=new Q}function te(e,t){this.predictionTimeS=e,this.isDebug=t,this.previousQ=new Q,this.previousTimestampS=null,this.deltaQ=new Q,this.outQ=new Q}function ie(e,t,i,n){this.yawOnly=i,this.accelerometer=new k,this.gyroscope=new k,this.filter=new ee(e,n),this.posePredictor=new te(t,n),this.isFirefoxAndroid=u(),this.isIOS=l();var r=h();this.isDeviceMotionInRadians=!this.isIOS&&r&&r<66,this.isWithoutDeviceMotion=p(),this.filterToWorldQ=new Q,l()?this.filterToWorldQ.setFromAxisAngle(new k(1,0,0),Math.PI/2):this.filterToWorldQ.setFromAxisAngle(new k(1,0,0),-Math.PI/2),this.inverseWorldToScreenQ=new Q,this.worldToScreenQ=new Q,this.originalPoseAdjustQ=new Q,this.originalPoseAdjustQ.setFromAxisAngle(new k(0,0,1),-window.orientation*Math.PI/180),this.setScreenTransform_(),g()&&this.filterToWorldQ.multiply(this.inverseWorldToScreenQ),this.resetQ=new Q,this.orientationOut_=new Float32Array(4),this.start()}J.prototype.getDeviceParams=function(){return this.deviceParams},J.prototype.recalculateDeviceParams_=function(){var e=this.calcDeviceParams_();e?(this.deviceParams=e,this.onDeviceParamsUpdated&&this.onDeviceParamsUpdated(this.deviceParams)):console.error("Failed to recalculate device parameters.")},J.prototype.calcDeviceParams_=function(){var e=this.dpdb;if(!e)return console.error("DPDB not available."),null;if(1!=e.format)return console.error("DPDB has unexpected format version."),null;if(!e.devices||!e.devices.length)return console.error("DPDB does not have a devices section."),null;var t=navigator.userAgent||navigator.vendor||window.opera,i=m(),n=M();if(!e.devices)return console.error("DPDB has no devices section."),null;for(var r=0;r 1"),0):2*Math.acos(n.w)),this.estimatedGravity.x.toFixed(1),this.estimatedGravity.y.toFixed(1),this.estimatedGravity.z.toFixed(1),this.measuredGravity.x.toFixed(1),this.measuredGravity.y.toFixed(1),this.measuredGravity.z.toFixed(1));var a=new Q;a.copy(this.filterQ),a.multiply(r),this.filterQ.slerp(a,1-this.kFilter),this.previousFilterQ.copy(this.filterQ)},ee.prototype.getOrientation=function(){return this.filterQ},ee.prototype.accelToQuaternion_=function(e){var t=new k;t.copy(e),t.normalize();var i=new Q;return i.setFromUnitVectors(new k(0,0,-1),t),i.inverse(),i},ee.prototype.gyroToQuaternionDelta_=function(e,t){var i=new Q,n=new k;return n.copy(e),n.normalize(),i.setFromAxisAngle(n,e.length()*t),i},te.prototype.getPrediction=function(e,t,i){if(!this.previousTimestampS)return this.previousQ.copy(e),this.previousTimestampS=i,e;var n=new k;n.copy(t),n.normalize();var r=t.length();if(r<20*P)return this.isDebug&&console.log("Moving slowly, at %s deg/s: no prediction",(B*r).toFixed(1)),this.outQ.copy(e),this.previousQ.copy(e),this.outQ;var a=r*this.predictionTimeS;return this.deltaQ.setFromAxisAngle(n,a),this.outQ.copy(this.previousQ),this.outQ.multiply(this.deltaQ),this.previousQ.copy(e),this.previousTimestampS=i,this.outQ},ie.prototype.getPosition=function(){return null},ie.prototype.getOrientation=function(){var e=void 0;if(this.isWithoutDeviceMotion&&this._deviceOrientationQ){this.deviceOrientationFixQ=this.deviceOrientationFixQ||(n=(new Q).setFromAxisAngle(new k(0,0,-1),0),r=new Q,-90===window.orientation?r.setFromAxisAngle(new k(0,1,0),Math.PI/-2):r.setFromAxisAngle(new k(0,1,0),Math.PI/2),n.multiply(r)),this.deviceOrientationFilterToWorldQ=this.deviceOrientationFilterToWorldQ||((i=new Q).setFromAxisAngle(new k(1,0,0),-Math.PI/2),i),e=this._deviceOrientationQ;var t=new Q;return t.copy(e),t.multiply(this.deviceOrientationFilterToWorldQ),t.multiply(this.resetQ),t.multiply(this.worldToScreenQ),t.multiplyQuaternions(this.deviceOrientationFixQ,t),this.yawOnly&&(t.x=0,t.z=0,t.normalize()),this.orientationOut_[0]=t.x,this.orientationOut_[1]=t.y,this.orientationOut_[2]=t.z,this.orientationOut_[3]=t.w,this.orientationOut_}var i,n,r,a=this.filter.getOrientation();e=this.posePredictor.getPrediction(a,this.gyroscope,this.previousTimestampS);var t=new Q;return t.copy(this.filterToWorldQ),t.multiply(this.resetQ),t.multiply(e),t.multiply(this.worldToScreenQ),this.yawOnly&&(t.x=0,t.z=0,t.normalize()),this.orientationOut_[0]=t.x,this.orientationOut_[1]=t.y,this.orientationOut_[2]=t.z,this.orientationOut_[3]=t.w,this.orientationOut_},ie.prototype.resetPose=function(){this.resetQ.copy(this.filter.getOrientation()),this.resetQ.x=0,this.resetQ.y=0,this.resetQ.z*=-1,this.resetQ.normalize(),g()&&this.resetQ.multiply(this.inverseWorldToScreenQ),this.resetQ.multiply(this.originalPoseAdjustQ)},ie.prototype.onDeviceOrientation_=function(e){this._deviceOrientationQ=this._deviceOrientationQ||new Q;var t=e.alpha,i=e.beta,n=e.gamma;t=(t||0)*Math.PI/180,i=(i||0)*Math.PI/180,n=(n||0)*Math.PI/180,this._deviceOrientationQ.setFromEulerYXZ(i,t,-n)},ie.prototype.onDeviceMotion_=function(e){this.updateDeviceMotion_(e)},ie.prototype.updateDeviceMotion_=function(e){var t=e.accelerationIncludingGravity,i=e.rotationRate,n=e.timeStamp/1e3,r=n-this.previousTimestampS;return r<0?L("fusion-pose-sensor:invalid:non-monotonic","Invalid timestamps detected: non-monotonic timestamp from devicemotion"):r<=.001||1h.capabilities.maxLayers)e(new Error("Invalid number of layers."));else{var i=c[0];if(i.source){var n=i.leftBounds||Ae,r=i.rightBounds||ve;if(u){var a=h.layer_;a.source!==i.source&&(a.source=i.source);for(var s=0;s<4;s++)a.leftBounds[s]=n[s],a.rightBounds[s]=r[s];return h.wrapForFullscreen(h.layer_.source),h.updatePresent_(),void t()}if(h.layer_={predistorted:i.predistorted,source:i.source,leftBounds:n.slice(0),rightBounds:r.slice(0)},h.waitingForPresent_=!1,h.layer_&&h.layer_.source){var o=h.wrapForFullscreen(h.layer_.source);h.addFullscreenListeners_(o,function(){var e=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;h.isPresenting=o===e,h.isPresenting?(screen.orientation&&screen.orientation.lock&&screen.orientation.lock("landscape-primary")["catch"](function(e){console.error("screen.orientation.lock() failed due to",e.message)}),h.waitingForPresent_=!1,h.beginPresent_(),t()):(screen.orientation&&screen.orientation.unlock&&screen.orientation.unlock(),h.removeFullscreenWrapper(),h.disableWakeLock(),h.endPresent_(),h.removeFullscreenListeners_()),h.fireVRDisplayPresentChange_()},function(){h.waitingForPresent_&&(h.removeFullscreenWrapper(),h.removeFullscreenListeners_(),h.disableWakeLock(),h.waitingForPresent_=!1,h.isPresenting=!1,e(new Error("Unable to present.")))}),function(e){if(d())return!1;if(e.requestFullscreen)e.requestFullscreen();else if(e.webkitRequestFullscreen)e.webkitRequestFullscreen();else if(e.mozRequestFullScreen)e.mozRequestFullScreen();else{if(!e.msRequestFullscreen)return!1;e.msRequestFullscreen()}return!0}(o)?(h.enableWakeLock(),h.waitingForPresent_=!0):(l()||d())&&(h.enableWakeLock(),h.isPresenting=!0,h.beginPresent_(),h.fireVRDisplayPresentChange_(),t())}h.waitingForPresent_||l()||(y(),e(new Error("Unable to present.")))}else t()}else e(new Error("VRDisplay is not capable of presenting."))})},Te.prototype.exitPresent=function(){var i=this.isPresenting,n=this;return this.isPresenting=!1,this.layer_=null,this.disableWakeLock(),new Promise(function(e,t){i?(!y()&&l()&&(n.endPresent_(),n.fireVRDisplayPresentChange_()),d()&&(n.removeFullscreenWrapper(),n.removeFullscreenListeners_(),n.endPresent_(),n.fireVRDisplayPresentChange_()),e()):t(new Error("Was not presenting to VRDisplay."))})},Te.prototype.getLayers=function(){return this.layer_?[this.layer_]:[]},Te.prototype.fireVRDisplayPresentChange_=function(){var e=new CustomEvent("vrdisplaypresentchange",{detail:{display:this}});window.dispatchEvent(e)},Te.prototype.fireVRDisplayConnect_=function(){var e=new CustomEvent("vrdisplayconnect",{detail:{display:this}});window.dispatchEvent(e)},Te.prototype.addFullscreenListeners_=function(e,t,i){this.removeFullscreenListeners_(),this.fullscreenEventTarget_=e,this.fullscreenChangeHandler_=t,this.fullscreenErrorHandler_=i,t&&(document.fullscreenEnabled?e.addEventListener("fullscreenchange",t,!1):document.webkitFullscreenEnabled?e.addEventListener("webkitfullscreenchange",t,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenchange",t,!1):document.msFullscreenEnabled&&e.addEventListener("msfullscreenchange",t,!1)),i&&(document.fullscreenEnabled?e.addEventListener("fullscreenerror",i,!1):document.webkitFullscreenEnabled?e.addEventListener("webkitfullscreenerror",i,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenerror",i,!1):document.msFullscreenEnabled&&e.addEventListener("msfullscreenerror",i,!1))},Te.prototype.removeFullscreenListeners_=function(){if(this.fullscreenEventTarget_){var e=this.fullscreenEventTarget_;if(this.fullscreenChangeHandler_){var t=this.fullscreenChangeHandler_;e.removeEventListener("fullscreenchange",t,!1),e.removeEventListener("webkitfullscreenchange",t,!1),document.removeEventListener("mozfullscreenchange",t,!1),e.removeEventListener("msfullscreenchange",t,!1)}if(this.fullscreenErrorHandler_){var i=this.fullscreenErrorHandler_;e.removeEventListener("fullscreenerror",i,!1),e.removeEventListener("webkitfullscreenerror",i,!1),document.removeEventListener("mozfullscreenerror",i,!1),e.removeEventListener("msfullscreenerror",i,!1)}this.fullscreenEventTarget_=null,this.fullscreenChangeHandler_=null,this.fullscreenErrorHandler_=null}},Te.prototype.enableWakeLock=function(){this.wakelock_&&this.wakelock_.enable()},Te.prototype.disableWakeLock=function(){this.wakelock_&&this.wakelock_.disable()},Te.prototype.beginPresent_=function(){},Te.prototype.endPresent_=function(){},Te.prototype.submitFrame=function(e){};var Ne={MOBILE_WAKE_LOCK:!0,DEBUG:(Te.prototype.getEyeParameters=function(e){return null},!1),DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1},De={LEFT:"left",RIGHT:"right"};function Le(e){var t=E({},Ne);e=E(t,e||{}),Te.call(this,{wakelock:e.MOBILE_WAKE_LOCK}),this.config=e,this.displayName="Cardboard VRDisplay",this.capabilities=new Ee({hasPosition:!1,hasOrientation:!0,hasExternalDisplay:!1,canPresent:!0,maxLayers:1}),this.stageParameters=null,this.bufferScale_=this.config.BUFFER_SCALE,this.poseSensor_=new oe(this.config),this.distorter_=null,this.cardboardUI_=null,this.dpdb_=new J(this.config.DPDB_URL,this.onDeviceParamsUpdated_.bind(this)),this.deviceInfo_=new X(this.dpdb_.getDeviceParams()),this.viewerSelector_=new le,this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)),this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()),this.config.ROTATE_INSTRUCTIONS_DISABLED||(this.rotateInstructions_=new ce),l()&&window.addEventListener("resize",this.onResize_.bind(this))}return(Le.prototype=Object.create(Te.prototype))._getPose=function(){return{position:null,orientation:this.poseSensor_.getOrientation(),linearVelocity:null,linearAcceleration:null,angularVelocity:null,angularAcceleration:null}},Le.prototype._resetPose=function(){this.poseSensor_.resetPose&&this.poseSensor_.resetPose()},Le.prototype._getFieldOfView=function(e){var t;if(e==De.LEFT)t=this.deviceInfo_.getFieldOfViewLeftEye();else{if(e!=De.RIGHT)return console.error("Invalid eye provided: %s",e),null;t=this.deviceInfo_.getFieldOfViewRightEye()}return t},Le.prototype._getEyeOffset=function(e){var t;if(e==De.LEFT)t=[.5*-this.deviceInfo_.viewer.interLensDistance,0,0];else{if(e!=De.RIGHT)return console.error("Invalid eye provided: %s",e),null;t=[.5*this.deviceInfo_.viewer.interLensDistance,0,0]}return t},Le.prototype.getEyeParameters=function(e){var t=this._getEyeOffset(e),i=this._getFieldOfView(e),n={offset:t,renderWidth:.5*this.deviceInfo_.device.width*this.bufferScale_,renderHeight:this.deviceInfo_.device.height*this.bufferScale_};return Object.defineProperty(n,"fieldOfView",{enumerable:!0,get:function(){return b("VRFieldOfView","VRFrameData's projection matrices"),i}}),n},Le.prototype.onDeviceParamsUpdated_=function(e){this.config.DEBUG&&console.log("DPDB reported that device params were updated."),this.deviceInfo_.updateDeviceParams(e),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_)},Le.prototype.updateBounds_=function(){this.layer_&&this.distorter_&&(this.layer_.leftBounds||this.layer_.rightBounds)&&this.distorter_.setTextureBounds(this.layer_.leftBounds,this.layer_.rightBounds)},Le.prototype.beginPresent_=function(){var e=this.layer_.source.getContext("webgl");e||(e=this.layer_.source.getContext("experimental-webgl")),e||(e=this.layer_.source.getContext("webgl2")),e&&(this.layer_.predistorted?this.config.CARDBOARD_UI_DISABLED||(e.canvas.width=m()*this.bufferScale_,e.canvas.height=M()*this.bufferScale_,this.cardboardUI_=new R(e)):(this.config.CARDBOARD_UI_DISABLED||(this.cardboardUI_=new R(e)),this.distorter_=new j(e,this.cardboardUI_,this.config.BUFFER_SCALE,this.config.DIRTY_SUBMIT_FRAME_BINDINGS),this.distorter_.updateDeviceInfo(this.deviceInfo_)),this.cardboardUI_&&this.cardboardUI_.listen(function(e){this.viewerSelector_.show(this.layer_.source.parentElement),e.stopPropagation(),e.preventDefault()}.bind(this),function(e){this.exitPresent(),e.stopPropagation(),e.preventDefault()}.bind(this)),this.rotateInstructions_&&(g()&&w()?this.rotateInstructions_.showTemporarily(3e3,this.layer_.source.parentElement):this.rotateInstructions_.update()),this.orientationHandler=this.onOrientationChange_.bind(this),window.addEventListener("orientationchange",this.orientationHandler),this.vrdisplaypresentchangeHandler=this.updateBounds_.bind(this),window.addEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler),this.fireVRDisplayDeviceParamsChange_())},Le.prototype.endPresent_=function(){this.distorter_&&(this.distorter_.destroy(),this.distorter_=null),this.cardboardUI_&&(this.cardboardUI_.destroy(),this.cardboardUI_=null),this.rotateInstructions_&&this.rotateInstructions_.hide(),this.viewerSelector_.hide(),window.removeEventListener("orientationchange",this.orientationHandler),window.removeEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler)},Le.prototype.updatePresent_=function(){this.endPresent_(),this.beginPresent_()},Le.prototype.submitFrame=function(e){if(this.distorter_)this.updateBounds_(),this.distorter_.submitFrame();else if(this.cardboardUI_&&this.layer_){var t=this.layer_.source.getContext("webgl").canvas;t.width==this.lastWidth&&t.height==this.lastHeight||this.cardboardUI_.onResize(),this.lastWidth=t.width,this.lastHeight=t.height,this.cardboardUI_.render()}},Le.prototype.onOrientationChange_=function(e){this.viewerSelector_.hide(),this.rotateInstructions_&&this.rotateInstructions_.update(),this.onResize_()},Le.prototype.onResize_=function(e){if(this.layer_){var t=this.layer_.source.getContext("webgl");t.canvas.setAttribute("style",["position: absolute","top: 0","left: 0","width: 100vw","height: 100vh","border: 0","margin: 0","padding: 0px","box-sizing: content-box"].join("; ")+";"),T(t.canvas)}},Le.prototype.onViewerChanged_=function(e){this.deviceInfo_.setViewer(e),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_),this.fireVRDisplayDeviceParamsChange_()},Le.prototype.fireVRDisplayDeviceParamsChange_=function(){var e=new CustomEvent("vrdisplaydeviceparamschange",{detail:{vrdisplay:this,deviceInfo:this.deviceInfo_}});window.dispatchEvent(e)},Le.VRFrameData=function(){this.leftProjectionMatrix=new Float32Array(16),this.leftViewMatrix=new Float32Array(16),this.rightProjectionMatrix=new Float32Array(16),this.rightViewMatrix=new Float32Array(16),this.pose=null},Le.VRDisplay=Te,Le}()}(t={exports:{}},t.exports),(e=t.exports)&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e["default"]:e),o={PROVIDE_MOBILE_VRDISPLAY:!0,GET_VR_DISPLAYS_TIMEOUT:1e3,MOBILE_WAKE_LOCK:!0,DEBUG:!1,DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,TOUCH_PANNER_DISABLED:!0,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1};function c(e){this.config=a(a({},o),e),this.polyfillDisplays=[],this.enabled=!1,this.hasNative="getVRDisplays"in navigator,this["native"]={},this["native"].getVRDisplays=navigator.getVRDisplays,this["native"].VRFrameData=window.VRFrameData,this["native"].VRDisplay=window.VRDisplay,(!this.hasNative||this.config.PROVIDE_MOBILE_VRDISPLAY&&n())&&(this.enable(),this.getVRDisplays().then(function(e){e&&e[0]&&e[0].fireVRDisplayConnect_&&e[0].fireVRDisplayConnect_()}))}c.prototype.getPolyfillDisplays=function(){if(this._polyfillDisplaysPopulated)return this.polyfillDisplays;if(n()){var e=new s({MOBILE_WAKE_LOCK:this.config.MOBILE_WAKE_LOCK,DEBUG:this.config.DEBUG,DPDB_URL:this.config.DPDB_URL,CARDBOARD_UI_DISABLED:this.config.CARDBOARD_UI_DISABLED,K_FILTER:this.config.K_FILTER,PREDICTION_TIME_S:this.config.PREDICTION_TIME_S,TOUCH_PANNER_DISABLED:this.config.TOUCH_PANNER_DISABLED,ROTATE_INSTRUCTIONS_DISABLED:this.config.ROTATE_INSTRUCTIONS_DISABLED,YAW_ONLY:this.config.YAW_ONLY,BUFFER_SCALE:this.config.BUFFER_SCALE,DIRTY_SUBMIT_FRAME_BINDINGS:this.config.DIRTY_SUBMIT_FRAME_BINDINGS});this.polyfillDisplays.push(e)}return this._polyfillDisplaysPopulated=!0,this.polyfillDisplays},c.prototype.enable=function(){if(this.enabled=!0,this.hasNative&&this["native"].VRFrameData){var t=this["native"].VRFrameData,i=new this["native"].VRFrameData,n=this["native"].VRDisplay.prototype.getFrameData;window.VRDisplay.prototype.getFrameData=function(e){e instanceof t?n.call(this,e):(n.call(this,i),e.pose=i.pose,r(i.leftProjectionMatrix,e.leftProjectionMatrix),r(i.rightProjectionMatrix,e.rightProjectionMatrix),r(i.leftViewMatrix,e.leftViewMatrix),r(i.rightViewMatrix,e.rightViewMatrix))}}navigator.getVRDisplays=this.getVRDisplays.bind(this),window.VRDisplay=s.VRDisplay,window.VRFrameData=s.VRFrameData},c.prototype.getVRDisplays=function(){var t,i=this,n=this.config;if(!this.hasNative)return Promise.resolve(this.getPolyfillDisplays());var r,e=this["native"].getVRDisplays.call(navigator),a=new Promise(function(e){t=setTimeout(function(){console.warn("Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill."),e([])},n.GET_VR_DISPLAYS_TIMEOUT)});return(r=[e,a],Promise.race?Promise.race(r):new Promise(function(e,t){for(var i=0;i>8&255]+r[e>>16&255]+r[e>>24&255]+"-"+r[255&t]+r[t>>8&255]+"-"+r[t>>16&15|64]+r[t>>24&255]+"-"+r[63&i|128]+r[i>>8&255]+"-"+r[i>>16&255]+r[i>>24&255]+r[255&n]+r[n>>8&255]+r[n>>16&255]+r[n>>24&255]).toUpperCase()}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,n,r){return n+(e-t)*(r-n)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:i<=e?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:i<=e?1:(e=(e-t)/(i-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*Vt.DEG2RAD},radToDeg:function(e){return e*Vt.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))}};function Wt(e,t){this.x=e||0,this.y=t||0}function Xt(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0Number.EPSILON){var A=Math.sqrt(y),v=Math.atan2(A,m*M);g=Math.sin(g*v)/A,s=Math.sin(s*v)/A}var w=s*M;if(o=o*g+l*w,c=c*g+d*w,u=u*g+p*w,h=h*g+f*w,g===1-s){var x=1/Math.sqrt(o*o+c*c+u*u+h*h);o*=x,c*=x,u*=x,h*=x}}e[t]=o,e[t+1]=c,e[t+2]=u,e[t+3]=h}}),Object.defineProperties(Zt.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this.onChangeCallback()}}}),Object.assign(Zt.prototype,{set:function(e,t,i,n){return this._x=e,this._y=t,this._z=i,this._w=n,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this.onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var i=e._x,n=e._y,r=e._z,a=e.order,s=Math.cos,o=Math.sin,c=s(i/2),u=s(n/2),h=s(r/2),l=o(i/2),d=o(n/2),p=o(r/2);return"XYZ"===a?(this._x=l*u*h+c*d*p,this._y=c*d*h-l*u*p,this._z=c*u*p+l*d*h,this._w=c*u*h-l*d*p):"YXZ"===a?(this._x=l*u*h+c*d*p,this._y=c*d*h-l*u*p,this._z=c*u*p-l*d*h,this._w=c*u*h+l*d*p):"ZXY"===a?(this._x=l*u*h-c*d*p,this._y=c*d*h+l*u*p,this._z=c*u*p+l*d*h,this._w=c*u*h-l*d*p):"ZYX"===a?(this._x=l*u*h-c*d*p,this._y=c*d*h+l*u*p,this._z=c*u*p-l*d*h,this._w=c*u*h+l*d*p):"YZX"===a?(this._x=l*u*h+c*d*p,this._y=c*d*h+l*u*p,this._z=c*u*p-l*d*h,this._w=c*u*h-l*d*p):"XZY"===a&&(this._x=l*u*h-c*d*p,this._y=c*d*h-l*u*p,this._z=c*u*p+l*d*h,this._w=c*u*h+l*d*p),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,n=Math.sin(i);return this._x=e.x*n,this._y=e.y*n,this._z=e.z*n,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,n=i[0],r=i[4],a=i[8],s=i[1],o=i[5],c=i[9],u=i[2],h=i[6],l=i[10],d=n+o+l;return 0Math.abs(e.z)?T.set(-e.y,e.x,0):T.set(0,-e.z,e.y)):T.crossVectors(e,t),this._x=T.x,this._y=T.y,this._z=T.z,this._w=E,this.normalize()}),inverse:function(){return this.conjugate()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this.onChangeCallback(),this},multiply:function(e,t){return t!==undefined?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var i=e._x,n=e._y,r=e._z,a=e._w,s=t._x,o=t._y,c=t._z,u=t._w;return this._x=i*u+a*s+n*c-r*o,this._y=n*u+a*o+r*s-i*c,this._z=r*u+a*c+i*o-n*s,this._w=a*u-i*s-n*o-r*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,n=this._y,r=this._z,a=this._w,s=a*e._w+i*e._x+n*e._y+r*e._z;if(s<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,s=-s):this.copy(e),1<=s)return this._w=a,this._x=i,this._y=n,this._z=r,this;var o=Math.sqrt(1-s*s);if(Math.abs(o)<.001)return this._w=.5*(a+this._w),this._x=.5*(i+this._x),this._y=.5*(n+this._y),this._z=.5*(r+this._z),this;var c=Math.atan2(o,s),u=Math.sin((1-t)*c)/o,h=Math.sin(t*c)/o;return this._w=a*u+this._w*h,this._x=i*u+this._x*h,this._y=n*u+this._y*h,this._z=r*u+this._z*h,this.onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return t===undefined&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this.onChangeCallback(),this},toArray:function(e,t){return e===undefined&&(e=[]),t===undefined&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(qt.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return t!==undefined?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return t!==undefined?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return t!==undefined?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:(j=new Zt,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(j.setFromEuler(e))}),applyAxisAngle:(S=new Zt,function(e,t){return this.applyQuaternion(S.setFromAxisAngle(e,t))}),applyMatrix3:function(e){var t=this.x,i=this.y,n=this.z,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6]*n,this.y=r[1]*t+r[4]*i+r[7]*n,this.z=r[2]*t+r[5]*i+r[8]*n,this},applyMatrix4:function(e){var t=this.x,i=this.y,n=this.z,r=e.elements,a=1/(r[3]*t+r[7]*i+r[11]*n+r[15]);return this.x=(r[0]*t+r[4]*i+r[8]*n+r[12])*a,this.y=(r[1]*t+r[5]*i+r[9]*n+r[13])*a,this.z=(r[2]*t+r[6]*i+r[10]*n+r[14])*a,this},applyQuaternion:function(e){var t=this.x,i=this.y,n=this.z,r=e.x,a=e.y,s=e.z,o=e.w,c=o*t+a*n-s*i,u=o*i+s*t-r*n,h=o*n+r*i-a*t,l=-r*t-a*i-s*n;return this.x=c*o+l*-r+u*-s-h*-a,this.y=u*o+l*-a+h*-r-c*-s,this.z=h*o+l*-s+c*-a-u*-r,this},project:(_=new Xt,function(e){return _.multiplyMatrices(e.projectionMatrix,_.getInverse(e.matrixWorld)),this.applyMatrix4(_)}),unproject:(I=new Xt,function(e){return I.multiplyMatrices(e.matrixWorld,I.getInverse(e.projectionMatrix)),this.applyMatrix4(I)}),transformDirection:function(e){var t=this.x,i=this.y,n=this.z,r=e.elements;return this.x=r[0]*t+r[4]*i+r[8]*n,this.y=r[1]*t+r[5]*i+r[9]*n,this.z=r[2]*t+r[6]*i+r[10]*n,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:(L=new qt,b=new qt,function(e,t){return L.set(e,e,e),b.set(t,t,t),this.clamp(L,b)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.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)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},cross:function(e,t){return t!==undefined?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var i=e.x,n=e.y,r=e.z,a=t.x,s=t.y,o=t.z;return this.x=n*o-r*s,this.y=r*a-i*o,this.z=i*s-n*a,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:(D=new qt,function(e){return D.copy(this).projectOnVector(e),this.sub(D)}),reflect:(N=new qt,function(e){return this.sub(N.copy(e).multiplyScalar(2*this.dot(e)))}),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(Vt.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,n=this.z-e.z;return t*t+i*i+n*n},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),i=this.setFromMatrixColumn(e,1).length(),n=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=n,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return t===undefined&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return e===undefined&&(e=[]),t===undefined&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,i){return i!==undefined&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}}),Object.assign(Jt.prototype,{isMatrix3:!0,set:function(e,t,i,n,r,a,s,o,c){var u=this.elements;return u[0]=e,u[1]=n,u[2]=s,u[3]=t,u[4]=r,u[5]=o,u[6]=i,u[7]=a,u[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},applyToBufferAttribute:(C=new qt,function(e){for(var t=0,i=e.count;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return t===undefined&&(console.warn("THREE.Box3: .getParameter() target is now required"),t=new qt),t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:(ni=new qt,function(e){return this.clampPoint(e.center,ni),ni.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return 0=e.constant},intersectsTriangle:function(){var o=new qt,c=new qt,u=new qt,i=new qt,n=new qt,r=new qt,h=new qt,a=new qt,l=new qt,s=new qt;function d(e){var t,i;for(t=0,i=e.length-3;t<=i;t+=3){h.fromArray(e,t);var n=l.x*Math.abs(h.x)+l.y*Math.abs(h.y)+l.z*Math.abs(h.z),r=o.dot(h),a=c.dot(h),s=u.dot(h);if(Math.max(-Math.max(r,a,s),Math.min(r,a,s))>n)return!1}return!0}return function(e){if(this.isEmpty())return!1;this.getCenter(a),l.subVectors(this.max,a),o.subVectors(e.a,a),c.subVectors(e.b,a),u.subVectors(e.c,a),i.subVectors(c,o),n.subVectors(u,c),r.subVectors(o,u);var t=[0,-i.z,i.y,0,-n.z,n.y,0,-r.z,r.y,i.z,0,-i.x,n.z,0,-n.x,r.z,0,-r.x,-i.y,i.x,0,-n.y,n.x,0,-r.y,r.x,0];return!!d(t)&&(!!d(t=[1,0,0,0,1,0,0,0,1])&&(s.crossVectors(i,n),d(t=[s.x,s.y,s.z])))}}(),clampPoint:function(e,t){return t===undefined&&(console.warn("THREE.Box3: .clampPoint() target is now required"),t=new qt),t.copy(e).clamp(this.min,this.max)},distanceToPoint:(ii=new qt,function(e){return ii.copy(e).clamp(this.min,this.max).sub(e).length()}),getBoundingSphere:(ti=new qt,function(e){return e===undefined&&(console.warn("THREE.Box3: .getBoundingSphere() target is now required"),e=new xi),this.getCenter(e.center),e.radius=.5*this.getSize(ti).length(),e}),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:(ei=[new qt,new qt,new qt,new qt,new qt,new qt,new qt,new qt],function(e){return this.isEmpty()||(ei[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),ei[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),ei[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),ei[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),ei[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),ei[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),ei[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),ei[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(ei)),this}),translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),Object.assign(xi.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(ai=new wi,function(e,t){var i=this.center;t!==undefined?i.copy(t):ai.setFromPoints(e).getCenter(i);for(var n=0,r=0,a=e.length;rthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t},getBoundingBox:function(e){return e===undefined&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),e=new wi),e.set(this.center,this.center),e.expandByScalar(this.radius),e},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}}),Object.assign(Ei.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,n){return this.normal.set(e,t,i),this.constant=n,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:(ui=new qt,hi=new qt,function(e,t,i){var n=ui.subVectors(i,t).cross(hi.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(n,e),this}),clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return t===undefined&&(console.warn("THREE.Plane: .projectPoint() target is now required"),t=new qt),t.copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:(ci=new qt,function(e,t){t===undefined&&(console.warn("THREE.Plane: .intersectLine() target is now required"),t=new qt);var i=e.delta(ci),n=this.normal.dot(i);if(0===n)return 0===this.distanceToPoint(e.start)?t.copy(e.start):undefined;var r=-(e.start.dot(this.normal)+this.constant)/n;return r<0||1 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars_begin:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n",lights_pars_maps:"#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif\n",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif\n",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n",normal_fragment_maps:"#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\t\tscale *= float( gl_FrontFacing ) * 2.0 - 1.0;\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},Li={merge:function(e){for(var t={},i=0;i>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function a(e,t,i){return i<0&&(i+=1),1t&&(t=e[i]);return t}gn.prototype=Object.assign(Object.create(p.prototype),{constructor:gn,isGeometry:!0,applyMatrix:function(e){for(var t=(new Jt).getNormalMatrix(e),i=0,n=this.vertices.length;ii.far?null:{distance:c,point:u.clone(),object:e}}function X(e,t,i,n,r,a,s,o){R.fromBufferAttribute(n,a),U.fromBufferAttribute(n,s),P.fromBufferAttribute(n,o);var c=W(e,e.material,t,i,R,U,P,H);if(c){r&&(G.fromBufferAttribute(r,a),Q.fromBufferAttribute(r,s),Y.fromBufferAttribute(r,o),c.uv=V(H,R,U,P,G,Q,Y));var u=new sn(a,s,o);vr.getNormal(R,U,P,u.normal),c.face=u,c.faceIndex=a}return c}return function(e,t){var i,n=this.geometry,r=this.material,a=this.matrixWorld;if(r!==undefined&&(null===n.boundingSphere&&n.computeBoundingSphere(),z.copy(n.boundingSphere),z.applyMatrix4(a),!1!==e.ray.intersectsSphere(z)&&(C.getInverse(a),O.copy(e.ray).applyMatrix4(C),null===n.boundingBox||!1!==O.intersectsBox(n.boundingBox))))if(n.isBufferGeometry){var s,o,c,u,h,l=n.index,d=n.attributes.position,p=n.attributes.uv;if(null!==l)for(u=0,h=l.count;u/gm,function(e,t){var i=Di[t];if(i===undefined)throw new Error("Can not resolve #include <"+t+">");return Da(i)})}function La(e){return e.replace(/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,function(e,t,i,n){for(var r="",a=parseInt(t);a 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),f.compileShader(t),f.compileShader(i),f.attachShader(e,t),f.attachShader(e,i),f.linkProgram(e),A=e,v={position:f.getAttribLocation(A,"position"),uv:f.getAttribLocation(A,"uv")},w={uvOffset:f.getUniformLocation(A,"uvOffset"),uvScale:f.getUniformLocation(A,"uvScale"),rotation:f.getUniformLocation(A,"rotation"),center:f.getUniformLocation(A,"center"),scale:f.getUniformLocation(A,"scale"),color:f.getUniformLocation(A,"color"),map:f.getUniformLocation(A,"map"),opacity:f.getUniformLocation(A,"opacity"),modelViewMatrix:f.getUniformLocation(A,"modelViewMatrix"),projectionMatrix:f.getUniformLocation(A,"projectionMatrix"),fogType:f.getUniformLocation(A,"fogType"),fogDensity:f.getUniformLocation(A,"fogDensity"),fogNear:f.getUniformLocation(A,"fogNear"),fogFar:f.getUniformLocation(A,"fogFar"),fogColor:f.getUniformLocation(A,"fogColor"),fogDepth:f.getUniformLocation(A,"fogDepth"),alphaTest:f.getUniformLocation(A,"alphaTest")};var a=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");a.width=8,a.height=8;var s=a.getContext("2d");s.fillStyle="white",s.fillRect(0,0,8,8),x=new os(a)}function L(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(e,t,i){if(0!==e.length){A===undefined&&D(),g.useProgram(A),g.initAttributes(),g.enableAttribute(v.position),g.enableAttribute(v.uv),g.disableUnusedAttributes(),g.disable(f.CULL_FACE),g.enable(f.BLEND),f.bindBuffer(f.ARRAY_BUFFER,M),f.vertexAttribPointer(v.position,2,f.FLOAT,!1,16,0),f.vertexAttribPointer(v.uv,2,f.FLOAT,!1,16,8),f.bindBuffer(f.ELEMENT_ARRAY_BUFFER,y),f.uniformMatrix4fv(w.projectionMatrix,!1,i.projectionMatrix.elements),g.activeTexture(f.TEXTURE0),f.uniform1i(w.map,0);var n=0,r=0,a=t.fog;a?(f.uniform3f(w.fogColor,a.color.r,a.color.g,a.color.b),a.isFog?(f.uniform1f(w.fogNear,a.near),f.uniform1f(w.fogFar,a.far),f.uniform1i(w.fogType,1),r=n=1):a.isFogExp2&&(f.uniform1f(w.fogDensity,a.density),f.uniform1i(w.fogType,2),r=n=2)):(f.uniform1i(w.fogType,0),r=n=0);for(var s=0,o=e.length;st||e.height>t){if("data"in e)return void console.warn("THREE.WebGLRenderer: image in DataTexture is too big ("+e.width+"x"+e.height+").");var i=t/Math.max(e.width,e.height),n=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return n.width=Math.floor(e.width*i),n.height=Math.floor(e.height*i),n.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,n.width,n.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+n.width+"x"+n.height,e),n}return e}function E(e){return Vt.isPowerOfTwo(e.width)&&Vt.isPowerOfTwo(e.height)}function T(e,t){return e.generateMipmaps&&t&&e.minFilter!==ke&&e.minFilter!==Qe}function N(e,t,i,n){g.generateMipmap(e),M.get(t).__maxMipLevel=Math.log(Math.max(i,n))*Math.LOG2E}function a(e){return e===ke||e===Fe||e===Ge?g.NEAREST:g.LINEAR}function D(e){var t=e.target;t.removeEventListener("dispose",D),function(e){var t=M.get(e);if(e.image&&t.__image__webglTextureCube)g.deleteTexture(t.__image__webglTextureCube);else{if(t.__webglInit===undefined)return;g.deleteTexture(t.__webglTexture)}M.remove(e)}(t),t.isVideoTexture&&delete o[t.id],v.memory.textures--}function s(e){var t=e.target;t.removeEventListener("dispose",s),function(e){var t=M.get(e),i=M.get(e.texture);if(!e)return;i.__webglTexture!==undefined&&g.deleteTexture(i.__webglTexture);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLRenderTargetCube)for(var n=0;n<6;n++)g.deleteFramebuffer(t.__webglFramebuffer[n]),t.__webglDepthbuffer&&g.deleteRenderbuffer(t.__webglDepthbuffer[n]);else g.deleteFramebuffer(t.__webglFramebuffer),t.__webglDepthbuffer&&g.deleteRenderbuffer(t.__webglDepthbuffer);M.remove(e.texture),M.remove(e)}(t),v.memory.textures--}function c(e,t){var i,n,r,a=M.get(e);if(e.isVideoTexture&&(n=(i=e).id,r=v.render.frame,o[n]!==r&&(o[n]=r,i.update())),0=B.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+B.maxTextures),V+=1,e},this.setTexture2D=(he=!1,function(e,t){e&&e.isWebGLRenderTarget&&(he||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),he=!0),e=e.texture),l.setTexture2D(e,t)}),this.setTexture=(le=!1,function(e,t){le||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),le=!0),l.setTexture2D(e,t)}),this.setTextureCube=(de=!1,function(e,t){e&&e.isWebGLRenderTargetCube&&(de||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),de=!0),e=e.texture),e&&e.isCubeTexture||Array.isArray(e.image)&&6===e.image.length?l.setTextureCube(e,t):l.setTextureCubeDynamic(e,t)}),this.getRenderTarget=function(){return w},this.setRenderTarget=function(e){(w=e)&&F.get(e).__webglFramebuffer===undefined&&l.setupRenderTarget(e);var t=null,i=!1;if(e){var n=F.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=n[e.activeCubeFace],i=!0):t=n,E.copy(e.viewport),S.copy(e.scissor),j=e.scissorTest}else E.copy(O).multiplyScalar(X),S.copy(z).multiplyScalar(X),j=R;if(x!==t&&(P.bindFramebuffer(P.FRAMEBUFFER,t),x=t),k.viewport(E),k.scissor(S),k.setScissorTest(j),i){var r=F.get(e.texture);P.framebufferTexture2D(P.FRAMEBUFFER,P.COLOR_ATTACHMENT0,P.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,r.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,n,r,a){if(e&&e.isWebGLRenderTarget){var s=F.get(e).__webglFramebuffer;if(s){var o=!1;s!==x&&(P.bindFramebuffer(P.FRAMEBUFFER,s),o=!0);try{var c=e.texture,u=c.format,h=c.type;if(u!==st&&A.convert(u)!==P.getParameter(P.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(h===Ve||A.convert(h)===P.getParameter(P.IMPLEMENTATION_COLOR_READ_TYPE)||h===Ke&&(T.get("OES_texture_float")||T.get("WEBGL_color_buffer_float"))||h===$e&&T.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");P.checkFramebufferStatus(P.FRAMEBUFFER)===P.FRAMEBUFFER_COMPLETE?0<=t&&t<=e.width-n&&0<=i&&i<=e.height-r&&P.readPixels(t,i,n,r,A.convert(u),A.convert(h),a):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{o&&P.bindFramebuffer(P.FRAMEBUFFER,x)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")},this.copyFramebufferToTexture=function(e,t,i){var n=t.image.width,r=t.image.height,a=A.convert(t.format);this.setTexture2D(t,0),P.copyTexImage2D(P.TEXTURE_2D,i||0,a,e.x,e.y,n,r,0)},this.copyTextureToTexture=function(e,t,i,n){var r=t.image.width,a=t.image.height,s=A.convert(i.format),o=A.convert(i.type),c=t.isDataTexture?t.image.data:t.image;this.setTexture2D(i,0),P.texSubImage2D(P.TEXTURE_2D,n||0,e.x,e.y,r,a,s,o,c)}}function ms(e,t){this.name="",this.color=new Ii(e),this.density=t!==undefined?t:25e-5}function Ms(e,t,i){this.name="",this.color=new Ii(e),this.near=t!==undefined?t:1,this.far=i!==undefined?i:1e3}function ys(){nn.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function As(e){gr.call(this),this.type="SpriteMaterial",this.color=new Ii(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function vs(e){nn.call(this),this.type="Sprite",this.material=e!==undefined?e:new As,this.center=new Wt(.5,.5)}function ws(){nn.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function xs(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),t===undefined)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,n=this.bones.length;ii)){var n=e.ray.origin.distanceTo(Ra);ne.far||t.push({distance:n,point:Ra.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)},copy:function(e){return nn.prototype.copy.call(this,e),e.center!==undefined&&this.center.copy(e.center),this}}),ws.prototype=Object.assign(Object.create(nn.prototype),{constructor:ws,copy:function(e){nn.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,n=t.length;i=t[n].distance;n++)t[n-1].object.visible=!1,t[n].object.visible=!0;for(;ne.far||t.push({distance:v,point:c.clone().applyMatrix4(this.matrixWorld),index:f,face:null,faceIndex:null,object:this}))}else for(f=0,g=d.length/3-1;fe.far||t.push({distance:v,point:c.clone().applyMatrix4(this.matrixWorld),index:f,face:null,faceIndex:null,object:this}))}else if(r.isGeometry){var y=r.vertices,A=y.length;for(f=0;fe.far||t.push({distance:v,point:c.clone().applyMatrix4(this.matrixWorld),index:f,face:null,faceIndex:null,object:this}))}}}}),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Ls.prototype=Object.assign(Object.create(Ds.prototype),{constructor:Ls,isLineSegments:!0,computeLineDistances:(Za=new qt,qa=new qt,function(){var e=this.geometry;if(e.isBufferGeometry)if(null===e.index){for(var t=e.attributes.position,i=[],n=0,r=t.count;nr.far)return;a.push({distance:n,distanceToRay:Math.sqrt(i),point:u.clone(),index:t,face:null,object:s})}}}),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Ss.prototype=Object.assign(Object.create(nn.prototype),{constructor:Ss,isGroup:!0}),js.prototype=Object.assign(Object.create(mi.prototype),{constructor:js,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),((Cs.prototype=Object.create(mi.prototype)).constructor=Cs).prototype.isCompressedTexture=!0,((Os.prototype=Object.create(mi.prototype)).constructor=Os).prototype.isDepthTexture=!0,(zs.prototype=Object.create(Bn.prototype)).constructor=zs,(Rs.prototype=Object.create(gn.prototype)).constructor=Rs,(Us.prototype=Object.create(Bn.prototype)).constructor=Us,(Ps.prototype=Object.create(gn.prototype)).constructor=Ps,(Bs.prototype=Object.create(Bn.prototype)).constructor=Bs,(ks.prototype=Object.create(gn.prototype)).constructor=ks,(Fs.prototype=Object.create(Bs.prototype)).constructor=Fs,(Gs.prototype=Object.create(gn.prototype)).constructor=Gs,(Qs.prototype=Object.create(Bs.prototype)).constructor=Qs,(Ys.prototype=Object.create(gn.prototype)).constructor=Ys,(Hs.prototype=Object.create(Bs.prototype)).constructor=Hs,(Vs.prototype=Object.create(gn.prototype)).constructor=Vs,(Ws.prototype=Object.create(Bs.prototype)).constructor=Ws,(Xs.prototype=Object.create(gn.prototype)).constructor=Xs,(Zs.prototype=Object.create(Bn.prototype)).constructor=Zs,(qs.prototype=Object.create(gn.prototype)).constructor=qs,(Js.prototype=Object.create(Bn.prototype)).constructor=Js,(Ks.prototype=Object.create(gn.prototype)).constructor=Ks,($s.prototype=Object.create(Bn.prototype)).constructor=$s;var eo=function(e,t,i){i=i||2;var n,r,a,s,o,c,u,h=t&&t.length,l=h?t[0]*i:e.length,d=to(e,0,l,i,!0),p=[];if(!d)return p;if(h&&(d=function(e,t,i,n){var r,a,s,o,c,u=[];for(r=0,a=t.length;r80*i){n=a=e[0],r=s=e[1];for(var f=i;fa.x?r.x>s.x?r.x:s.x:a.x>s.x?a.x:s.x,h=r.y>a.y?r.y>s.y?r.y:s.y:a.y>s.y?a.y:s.y,l=ho(o,c,t,i,n),d=ho(u,h,t,i,n),p=e.nextZ;p&&p.z<=d;){if(p!==e.prev&&p!==e.next&&po(r.x,r.y,a.x,a.y,s.x,s.y,p.x,p.y)&&0<=fo(p.prev,p,p.next))return!1;p=p.nextZ}for(p=e.prevZ;p&&p.z>=l;){if(p!==e.prev&&p!==e.next&&po(r.x,r.y,a.x,a.y,s.x,s.y,p.x,p.y)&&0<=fo(p.prev,p,p.next))return!1;p=p.prevZ}return!0}function so(e,t,i){var n=e;do{var r=n.prev,a=n.next.next;!go(r,a)&&mo(r,n,n.next,a)&&Mo(r,a)&&Mo(a,r)&&(t.push(r.i/i),t.push(n.i/i),t.push(a.i/i),vo(n),vo(n.next),n=e=a),n=n.next}while(n!==e);return n}function oo(e,t,i,n,r,a){var s,o,c=e;do{for(var u=c.next.next;u!==c.prev;){if(c.i!==u.i&&(o=u,(s=c).next.i!==o.i&&s.prev.i!==o.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&mo(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(s,o)&&Mo(s,o)&&Mo(o,s)&&function(e,t){var i=e,n=!1,r=(e.x+t.x)/2,a=(e.y+t.y)/2;for(;i.y>a!=i.next.y>a&&i.next.y!==i.y&&r<(i.next.x-i.x)*(a-i.y)/(i.next.y-i.y)+i.x&&(n=!n),i=i.next,i!==e;);return n}(s,o))){var h=yo(c,u);return c=io(c,c.next),h=io(h,h.next),no(c,t,i,n,r,a),void no(h,t,i,n,r,a)}u=u.next}c=c.next}while(c!==e)}function co(e,t){return e.x-t.x}function uo(e,t){if(t=function(e,t){var i,n=t,r=e.x,a=e.y,s=-Infinity;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){var o=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(o<=r&&s=n.x&&n.x>=h&&r!==n.x&&po(ai.x)&&Mo(n,e)&&(i=n,d=c),n=n.next;return i}(e,t)){var i=yo(t,e);io(i,i.next)}}function ho(e,t,i,n,r){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*r)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-n)*r)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function lo(e){for(var t=e,i=e;t.xNumber.EPSILON){var d=Math.sqrt(h),p=Math.sqrt(c*c+u*u),f=t.x-o/d,g=t.y+s/d,m=((i.x-u/p-f)*u-(i.y+c/p-g)*c)/(s*u-o*c),M=(n=f+s*m-e.x)*n+(r=g+o*m-e.y)*r;if(M<=2)return new Wt(n,r);a=Math.sqrt(M/2)}else{var y=!1;s>Number.EPSILON?c>Number.EPSILON&&(y=!0):s<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(o)===Math.sign(u)&&(y=!0),y?(n=-o,r=s,a=Math.sqrt(h)):(n=s,r=o,a=Math.sqrt(h/2))}return new Wt(n/a,r/a)}for(var z=[],R=0,U=T.length,P=U-1,B=R+1;RNumber.EPSILON&&(u.normalize(),r=Math.acos(Vt.clamp(s[i-1].dot(s[i]),-1,1)),o[i].applyMatrix4(h.makeRotationAxis(u,r))),c[i].crossVectors(s[i],o[i]);if(!0===t)for(r=Math.acos(Vt.clamp(o[0].dot(o[e]),-1,1)),r/=e,0n.length-2?n.length-1:a+1],h=n[a>n.length-3?n.length-1:a+2];return i.set(Ac(s,o.x,c.x,u.x,h.x),Ac(s,o.y,c.y,u.y,h.y)),i},bc.prototype.copy=function(e){hc.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var r=i[n]-t,a=this.curves[n],s=a.getLength(),o=0===s?0:1-r/s;return a.getPointAt(o)}n++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,n=this.curves.length;i>>1;et;)--a;if(++a,0!==r||a!==n){a<=r&&(r=(a=Math.max(a,1))-1);var s=this.getValueSize();this.times=$c.arraySlice(i,r,a),this.values=$c.arraySlice(this.values,r*s,a*s)}return this},validate:function(){var e=!0,t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);var i=this.times,n=this.values,r=i.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);for(var a=null,s=0;s!==r;s++){var o=i[s];if("number"==typeof o&&isNaN(o)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,s,o),e=!1;break}if(null!==a&&oNumber.EPSILON){if(u<0&&(s=t[a],c=-c,o=t[r],u=-u),e.yo.y)continue;if(e.y===s.y){if(e.x===s.x)return!0}else{var h=u*(e.x-s.x)-c*(e.y-s.y);if(0===h)return!0;if(h<0)continue;n=!n}}else{if(e.y!==s.y)continue;if(o.x<=e.x&&e.x<=s.x||s.x<=e.x&&e.x<=o.x)return!0}}return n}var r=xo.isClockWise,a=this.subPaths;if(0===a.length)return[];if(!0===t)return i(a);var s,o,c,u=[];if(1===a.length)return o=a[0],(c=new jc).curves=o.curves,u.push(c),u;var h=!r(a[0].getPoints());h=e?!h:h;var l,d,p=[],f=[],g=[],m=0;f[m]=undefined,g[m]=[];for(var M=0,y=a.length;Mi.parameterPositions[1]&&(this.stopFading(),0===n&&(this.enabled=!1))}}return this._effectiveWeight=t},_updateTimeScale:function(e){var t=0;if(!this.paused){t=this.timeScale;var i=this._timeScaleInterpolant;if(null!==i)t*=i.evaluate(e)[0],e>i.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}return this._effectiveTimeScale=t},_updateTime:function(e){var t=this.time+e;if(0===e)return t;var i=this._clip.duration,n=this.loop,r=this._loopCount;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(i<=t)t=i;else{if(!(t<0))break e;t=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{var a=2202===n;if(-1===r&&(0<=e?(r=0,this._setEndings(!0,0===this.repetitions,a)):this._setEndings(0===this.repetitions,!0,a)),i<=t||t<0){var s=Math.floor(t/i);t-=i*s,r+=Math.abs(s);var o=this.repetitions-r;if(o<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,t=0this.max.x||e.ythis.max.y)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y},getParameter:function(e,t){return t===undefined&&(console.warn("THREE.Box2: .getParameter() target is now required"),t=new Wt),t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return t===undefined&&(console.warn("THREE.Box2: .clampPoint() target is now required"),t=new Wt),t.copy(e).clamp(this.min,this.max)},distanceToPoint:(Ku=new Wt,function(e){return Ku.copy(e).clamp(this.min,this.max).sub(e).length()}),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),((Ph.prototype=Object.create(nn.prototype)).constructor=Ph).prototype.isImmediateRenderObject=!0,((Bh.prototype=Object.create(Ls.prototype)).constructor=Bh).prototype.update=(eh=new qt,th=new qt,ih=new Jt,function(){var e=["a","b","c"];this.object.updateMatrixWorld(!0),ih.getNormalMatrix(this.object.matrixWorld);var t=this.object.matrixWorld,i=this.geometry.attributes.position,n=this.object.geometry;if(n&&n.isGeometry)for(var r=n.vertices,a=n.faces,s=0,o=0,c=a.length;op||8*(1-s.dot(o.object.quaternion))>p)||(o.dispatchEvent(c),a.copy(o.object.position),s.copy(o.object.quaternion),y=!1))}),this.dispose=function(){o.domElement.removeEventListener("contextmenu",H,!1),o.domElement.removeEventListener("mousedown",U,!1),o.domElement.removeEventListener("wheel",k,!1),o.domElement.removeEventListener("touchstart",G,!1),o.domElement.removeEventListener("touchend",Y,!1),o.domElement.removeEventListener("touchmove",Q,!1),document.removeEventListener("mousemove",P,!1),document.removeEventListener("mouseup",B,!1),window.removeEventListener("keydown",F,!1)};var o=this,c={type:"change"},u={type:"start"},h={type:"end"},l={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_DOLLY_PAN:4},d=l.NONE,p=1e-6,f=new Rh,g=new Rh,m=1,M=new qt,y=!1,A=new Wt,v=new Wt,w=new Wt,x=new Wt,E=new Wt,T=new Wt,N=new Wt,D=new Wt,L=new Wt;function b(){return Math.pow(.95,o.zoomSpeed)}o.rotateLeft=function(e){g.theta-=e},o.rotateUp=function(e){g.phi-=e};var I,_,S,j=(I=new qt,function(e,t){I.setFromMatrixColumn(t,0),I.multiplyScalar(-e),M.add(I)}),C=(_=new qt,function(e,t){!0===o.screenSpacePanning?_.setFromMatrixColumn(t,1):(_.setFromMatrixColumn(t,0),_.crossVectors(o.object.up,_)),_.multiplyScalar(e),M.add(_)}),O=(S=new qt,function(e,t){var i=o.domElement===document?o.domElement.body:o.domElement;if(o.object.isPerspectiveCamera){var n=o.object.position;S.copy(n).sub(o.target);var r=S.length();r*=Math.tan(o.object.fov/2*Math.PI/180),j(2*e*r/i.clientHeight,o.object.matrix),C(2*t*r/i.clientHeight,o.object.matrix)}else o.object.isOrthographicCamera?(j(e*(o.object.right-o.object.left)/o.object.zoom/i.clientWidth,o.object.matrix),C(t*(o.object.top-o.object.bottom)/o.object.zoom/i.clientHeight,o.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),o.enablePan=!1)});function z(e){o.object.isPerspectiveCamera?m/=e:o.object.isOrthographicCamera?(o.object.zoom=Math.max(o.minZoom,Math.min(o.maxZoom,o.object.zoom*e)),o.object.updateProjectionMatrix(),y=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),o.enableZoom=!1)}function R(e){o.object.isPerspectiveCamera?m*=e:o.object.isOrthographicCamera?(o.object.zoom=Math.max(o.minZoom,Math.min(o.maxZoom,o.object.zoom/e)),o.object.updateProjectionMatrix(),y=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),o.enableZoom=!1)}function U(e){if(!1!==o.enabled){switch(e.preventDefault(),e.button){case o.mouseButtons.ORBIT:if(!1===o.enableRotate)return;n=e,A.set(n.clientX,n.clientY),d=l.ROTATE;break;case o.mouseButtons.ZOOM:if(!1===o.enableZoom)return;i=e,N.set(i.clientX,i.clientY),d=l.DOLLY;break;case o.mouseButtons.PAN:if(!1===o.enablePan)return;t=e,x.set(t.clientX,t.clientY),d=l.PAN}var t,i,n;d!==l.NONE&&(document.addEventListener("mousemove",P,!1),document.addEventListener("mouseup",B,!1),o.dispatchEvent(u))}}function P(e){var t,i;if(!1!==o.enabled)switch(e.preventDefault(),d){case l.ROTATE:if(!1===o.enableRotate)return;!function(e){v.set(e.clientX,e.clientY),w.subVectors(v,A).multiplyScalar(o.rotateSpeed);var t=o.domElement===document?o.domElement.body:o.domElement;o.rotateLeft(2*Math.PI*w.x/t.clientWidth),o.rotateUp(2*Math.PI*w.y/t.clientHeight),A.copy(v),o.update()}(e);break;case l.DOLLY:if(!1===o.enableZoom)return;i=e,D.set(i.clientX,i.clientY),L.subVectors(D,N),0http://webvr.info for more info."},"web-vr-not-supported":{headline:"360 not supported on this device",type:"360_NOT_SUPPORTED",message:"Your browser does not support 360. See http://webvr.info for assistance."},"web-vr-hls-cors-not-supported":{headline:"360 HLS video not supported on this device",type:"360_NOT_SUPPORTED",message:"Your browser/device does not support HLS 360 video. See http://webvr.info for assistance."}},yl=o.getPlugin("plugin"),Al=o.getComponent("Component"),vl=function(r){function a(e,t){sl(this,a);var i=o.mergeOptions(ml,t),n=cl(this,r.call(this,e,i));return n.options_=i,n.player_=e,n.bigPlayButtonIndex_=e.children().indexOf(e.getChild("BigPlayButton"))||0,n.videojsErrorsSupport_=!!o.errors,n.videojsErrorsSupport_&&e.errors({errors:Ml}),o.browser.IE_VERSION||!ll?(n.player_.on("loadstart",function(){n.triggerError_({code:"web-vr-not-supported",dismiss:!1})}),cl(n)):(n.polyfill_=new d({ROTATE_INSTRUCTIONS_DISABLED:!0}),n.polyfill_=new d,n.handleVrDisplayActivate_=o.bind(n,n.handleVrDisplayActivate_),n.handleVrDisplayDeactivate_=o.bind(n,n.handleVrDisplayDeactivate_),n.handleResize_=o.bind(n,n.handleResize_),n.animate_=o.bind(n,n.animate_),n.setProjection(n.options_.projection),n.on(e,"loadedmetadata",n.init),n)}return ol(a,r),a.prototype.changeProjection_=function(e){(e=pl(e))||(e="NONE");var t=0,i=0,n=0;if(this.scene&&this.scene.remove(this.movieScreen),"AUTO"===e){if(this.player_.mediainfo&&this.player_.mediainfo.projection&&"AUTO"!==this.player_.mediainfo.projection){var r=pl(this.player_.mediainfo.projection);return this.changeProjection_(r)}return this.changeProjection_("NONE")}if("360"===e)this.movieGeometry=new So(256,32,32),this.movieMaterial=new mr({map:this.videoTexture,overdraw:!0,side:Z}),this.movieScreen=new wr(this.movieGeometry,this.movieMaterial),this.movieScreen.position.set(t,i,n),this.movieScreen.scale.x=-1,this.movieScreen.quaternion.setFromAxisAngle({x:0,y:1,z:0},-Math.PI/2),this.scene.add(this.movieScreen);else if("360_LR"===e||"360_TB"===e){for(var a=new _o(256,32,32),s=a.faceVertexUvs[0],o=0;oe.TEXTURE31){console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"),r.push(null,null);break}n||(n=e.getParameter(e.ACTIVE_TEXTURE)),e.activeTexture(c),r.push(e.getParameter(o),null);break;case e.ACTIVE_TEXTURE:n=e.getParameter(e.ACTIVE_TEXTURE),r.push(null);break;default:r.push(e.getParameter(o))}for(i(e),a=0;ae.TEXTURE31)break;e.activeTexture(c),e.bindTexture(e.TEXTURE_2D,s);break;case e.TEXTURE_BINDING_CUBE_MAP:var c;if((c=t[++a])e.TEXTURE31)break;e.activeTexture(c),e.bindTexture(e.TEXTURE_CUBE_MAP,s);break;case e.VIEWPORT:e.viewport(s[0],s[1],s[2],s[3]);break;case e.BLEND:case e.CULL_FACE:case e.DEPTH_TEST:case e.SCISSOR_TEST:case e.STENCIL_TEST:s?e.enable(o):e.disable(o);break;default:console.log("No GL restore behavior for 0x"+o.toString(16))}n&&e.activeTexture(n)}}else i(e)},L=["attribute vec2 position;","attribute vec3 texCoord;","varying vec2 vTexCoord;","uniform vec4 viewportOffsetScale[2];","void main() {"," vec4 viewport = viewportOffsetScale[int(texCoord.z)];"," vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;"," gl_Position = vec4( position, 1.0, 1.0 );","}"].join("\n"),P=["precision mediump float;","uniform sampler2D diffuse;","varying vec2 vTexCoord;","void main() {"," gl_FragColor = texture2D(diffuse, vTexCoord);","}"].join("\n");function C(e,t,i,r){this.gl=e,this.cardboardUI=t,this.bufferScale=i,this.dirtySubmitFrameBindings=r,this.ctxAttribs=e.getContextAttributes(),this.instanceExt=e.getExtension("ANGLE_instanced_arrays"),this.meshWidth=20,this.meshHeight=20,this.bufferWidth=e.drawingBufferWidth,this.bufferHeight=e.drawingBufferHeight,this.realBindFramebuffer=e.bindFramebuffer,this.realEnable=e.enable,this.realDisable=e.disable,this.realColorMask=e.colorMask,this.realClearColor=e.clearColor,this.realViewport=e.viewport,s()||(this.realCanvasWidth=Object.getOwnPropertyDescriptor(e.canvas.__proto__,"width"),this.realCanvasHeight=Object.getOwnPropertyDescriptor(e.canvas.__proto__,"height")),this.isPatched=!1,this.lastBoundFramebuffer=null,this.cullFace=!1,this.depthTest=!1,this.blend=!1,this.scissorTest=!1,this.stencilTest=!1,this.viewport=[0,0,0,0],this.colorMask=[!0,!0,!0,!0],this.clearColor=[0,0,0,0],this.attribs={position:0,texCoord:1},this.program=A(e,L,P,this.attribs),this.uniforms=x(e,this.program),this.viewportOffsetScale=new Float32Array(8),this.setTextureBounds(),this.vertexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),this.indexCount=0,this.renderTarget=e.createTexture(),this.framebuffer=e.createFramebuffer(),this.depthStencilBuffer=null,this.depthBuffer=null,this.stencilBuffer=null,this.ctxAttribs.depth&&this.ctxAttribs.stencil?this.depthStencilBuffer=e.createRenderbuffer():this.ctxAttribs.depth?this.depthBuffer=e.createRenderbuffer():this.ctxAttribs.stencil&&(this.stencilBuffer=e.createRenderbuffer()),this.patch(),this.onResize()}C.prototype.destroy=function(){var e=this.gl;this.unpatch(),e.deleteProgram(this.program),e.deleteBuffer(this.vertexBuffer),e.deleteBuffer(this.indexBuffer),e.deleteTexture(this.renderTarget),e.deleteFramebuffer(this.framebuffer),this.depthStencilBuffer&&e.deleteRenderbuffer(this.depthStencilBuffer),this.depthBuffer&&e.deleteRenderbuffer(this.depthBuffer),this.stencilBuffer&&e.deleteRenderbuffer(this.stencilBuffer),this.cardboardUI&&this.cardboardUI.destroy()},C.prototype.onResize=function(){var e=this.gl,t=this,i=[e.RENDERBUFFER_BINDING,e.TEXTURE_BINDING_2D,e.TEXTURE0];R(e,i,(function(e){t.realBindFramebuffer.call(e,e.FRAMEBUFFER,null),t.scissorTest&&t.realDisable.call(e,e.SCISSOR_TEST),t.realColorMask.call(e,!0,!0,!0,!0),t.realViewport.call(e,0,0,e.drawingBufferWidth,e.drawingBufferHeight),t.realClearColor.call(e,0,0,0,1),e.clear(e.COLOR_BUFFER_BIT),t.realBindFramebuffer.call(e,e.FRAMEBUFFER,t.framebuffer),e.bindTexture(e.TEXTURE_2D,t.renderTarget),e.texImage2D(e.TEXTURE_2D,0,t.ctxAttribs.alpha?e.RGBA:e.RGB,t.bufferWidth,t.bufferHeight,0,t.ctxAttribs.alpha?e.RGBA:e.RGB,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t.renderTarget,0),t.ctxAttribs.depth&&t.ctxAttribs.stencil?(e.bindRenderbuffer(e.RENDERBUFFER,t.depthStencilBuffer),e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,t.bufferWidth,t.bufferHeight),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t.depthStencilBuffer)):t.ctxAttribs.depth?(e.bindRenderbuffer(e.RENDERBUFFER,t.depthBuffer),e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,t.bufferWidth,t.bufferHeight),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t.depthBuffer)):t.ctxAttribs.stencil&&(e.bindRenderbuffer(e.RENDERBUFFER,t.stencilBuffer),e.renderbufferStorage(e.RENDERBUFFER,e.STENCIL_INDEX8,t.bufferWidth,t.bufferHeight),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.STENCIL_ATTACHMENT,e.RENDERBUFFER,t.stencilBuffer)),!e.checkFramebufferStatus(e.FRAMEBUFFER)===e.FRAMEBUFFER_COMPLETE&&console.error("Framebuffer incomplete!"),t.realBindFramebuffer.call(e,e.FRAMEBUFFER,t.lastBoundFramebuffer),t.scissorTest&&t.realEnable.call(e,e.SCISSOR_TEST),t.realColorMask.apply(e,t.colorMask),t.realViewport.apply(e,t.viewport),t.realClearColor.apply(e,t.clearColor)})),this.cardboardUI&&this.cardboardUI.onResize()},C.prototype.patch=function(){if(!this.isPatched){var e=this,t=this.gl.canvas,i=this.gl;s()||(t.width=v()*this.bufferScale,t.height=g()*this.bufferScale,Object.defineProperty(t,"width",{configurable:!0,enumerable:!0,get:function(){return e.bufferWidth},set:function(i){e.bufferWidth=i,e.realCanvasWidth.set.call(t,i),e.onResize()}}),Object.defineProperty(t,"height",{configurable:!0,enumerable:!0,get:function(){return e.bufferHeight},set:function(i){e.bufferHeight=i,e.realCanvasHeight.set.call(t,i),e.onResize()}})),this.lastBoundFramebuffer=i.getParameter(i.FRAMEBUFFER_BINDING),null==this.lastBoundFramebuffer&&(this.lastBoundFramebuffer=this.framebuffer,this.gl.bindFramebuffer(i.FRAMEBUFFER,this.framebuffer)),this.gl.bindFramebuffer=function(t,r){e.lastBoundFramebuffer=r||e.framebuffer,e.realBindFramebuffer.call(i,t,e.lastBoundFramebuffer)},this.cullFace=i.getParameter(i.CULL_FACE),this.depthTest=i.getParameter(i.DEPTH_TEST),this.blend=i.getParameter(i.BLEND),this.scissorTest=i.getParameter(i.SCISSOR_TEST),this.stencilTest=i.getParameter(i.STENCIL_TEST),i.enable=function(t){switch(t){case i.CULL_FACE:e.cullFace=!0;break;case i.DEPTH_TEST:e.depthTest=!0;break;case i.BLEND:e.blend=!0;break;case i.SCISSOR_TEST:e.scissorTest=!0;break;case i.STENCIL_TEST:e.stencilTest=!0}e.realEnable.call(i,t)},i.disable=function(t){switch(t){case i.CULL_FACE:e.cullFace=!1;break;case i.DEPTH_TEST:e.depthTest=!1;break;case i.BLEND:e.blend=!1;break;case i.SCISSOR_TEST:e.scissorTest=!1;break;case i.STENCIL_TEST:e.stencilTest=!1}e.realDisable.call(i,t)},this.colorMask=i.getParameter(i.COLOR_WRITEMASK),i.colorMask=function(t,r,n,a){e.colorMask[0]=t,e.colorMask[1]=r,e.colorMask[2]=n,e.colorMask[3]=a,e.realColorMask.call(i,t,r,n,a)},this.clearColor=i.getParameter(i.COLOR_CLEAR_VALUE),i.clearColor=function(t,r,n,a){e.clearColor[0]=t,e.clearColor[1]=r,e.clearColor[2]=n,e.clearColor[3]=a,e.realClearColor.call(i,t,r,n,a)},this.viewport=i.getParameter(i.VIEWPORT),i.viewport=function(t,r,n,a){e.viewport[0]=t,e.viewport[1]=r,e.viewport[2]=n,e.viewport[3]=a,e.realViewport.call(i,t,r,n,a)},this.isPatched=!0,_(t)}},C.prototype.unpatch=function(){if(this.isPatched){var e=this.gl,t=this.gl.canvas;s()||(Object.defineProperty(t,"width",this.realCanvasWidth),Object.defineProperty(t,"height",this.realCanvasHeight)),t.width=this.bufferWidth,t.height=this.bufferHeight,e.bindFramebuffer=this.realBindFramebuffer,e.enable=this.realEnable,e.disable=this.realDisable,e.colorMask=this.realColorMask,e.clearColor=this.realClearColor,e.viewport=this.realViewport,this.lastBoundFramebuffer==this.framebuffer&&e.bindFramebuffer(e.FRAMEBUFFER,null),this.isPatched=!1,setTimeout((function(){_(t)}),1)}},C.prototype.setTextureBounds=function(e,t){e||(e=[0,0,.5,1]),t||(t=[.5,0,.5,1]),this.viewportOffsetScale[0]=e[0],this.viewportOffsetScale[1]=e[1],this.viewportOffsetScale[2]=e[2],this.viewportOffsetScale[3]=e[3],this.viewportOffsetScale[4]=t[0],this.viewportOffsetScale[5]=t[1],this.viewportOffsetScale[6]=t[2],this.viewportOffsetScale[7]=t[3]},C.prototype.submitFrame=function(){var e=this.gl,t=this,i=[];if(this.dirtySubmitFrameBindings||i.push(e.CURRENT_PROGRAM,e.ARRAY_BUFFER_BINDING,e.ELEMENT_ARRAY_BUFFER_BINDING,e.TEXTURE_BINDING_2D,e.TEXTURE0),R(e,i,(function(e){t.realBindFramebuffer.call(e,e.FRAMEBUFFER,null);var i=0,r=0;t.instanceExt&&(i=e.getVertexAttrib(t.attribs.position,t.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE),r=e.getVertexAttrib(t.attribs.texCoord,t.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE)),t.cullFace&&t.realDisable.call(e,e.CULL_FACE),t.depthTest&&t.realDisable.call(e,e.DEPTH_TEST),t.blend&&t.realDisable.call(e,e.BLEND),t.scissorTest&&t.realDisable.call(e,e.SCISSOR_TEST),t.stencilTest&&t.realDisable.call(e,e.STENCIL_TEST),t.realColorMask.call(e,!0,!0,!0,!0),t.realViewport.call(e,0,0,e.drawingBufferWidth,e.drawingBufferHeight),(t.ctxAttribs.alpha||s())&&(t.realClearColor.call(e,0,0,0,1),e.clear(e.COLOR_BUFFER_BIT)),e.useProgram(t.program),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,t.indexBuffer),e.bindBuffer(e.ARRAY_BUFFER,t.vertexBuffer),e.enableVertexAttribArray(t.attribs.position),e.enableVertexAttribArray(t.attribs.texCoord),e.vertexAttribPointer(t.attribs.position,2,e.FLOAT,!1,20,0),e.vertexAttribPointer(t.attribs.texCoord,3,e.FLOAT,!1,20,8),t.instanceExt&&(0!=i&&t.instanceExt.vertexAttribDivisorANGLE(t.attribs.position,0),0!=r&&t.instanceExt.vertexAttribDivisorANGLE(t.attribs.texCoord,0)),e.activeTexture(e.TEXTURE0),e.uniform1i(t.uniforms.diffuse,0),e.bindTexture(e.TEXTURE_2D,t.renderTarget),e.uniform4fv(t.uniforms.viewportOffsetScale,t.viewportOffsetScale),e.drawElements(e.TRIANGLES,t.indexCount,e.UNSIGNED_SHORT,0),t.cardboardUI&&t.cardboardUI.renderNoState(),t.realBindFramebuffer.call(t.gl,e.FRAMEBUFFER,t.framebuffer),t.ctxAttribs.preserveDrawingBuffer||(t.realClearColor.call(e,0,0,0,0),e.clear(e.COLOR_BUFFER_BIT)),t.dirtySubmitFrameBindings||t.realBindFramebuffer.call(e,e.FRAMEBUFFER,t.lastBoundFramebuffer),t.cullFace&&t.realEnable.call(e,e.CULL_FACE),t.depthTest&&t.realEnable.call(e,e.DEPTH_TEST),t.blend&&t.realEnable.call(e,e.BLEND),t.scissorTest&&t.realEnable.call(e,e.SCISSOR_TEST),t.stencilTest&&t.realEnable.call(e,e.STENCIL_TEST),t.realColorMask.apply(e,t.colorMask),t.realViewport.apply(e,t.viewport),!t.ctxAttribs.alpha&&t.ctxAttribs.preserveDrawingBuffer||t.realClearColor.apply(e,t.clearColor),t.instanceExt&&(0!=i&&t.instanceExt.vertexAttribDivisorANGLE(t.attribs.position,i),0!=r&&t.instanceExt.vertexAttribDivisorANGLE(t.attribs.texCoord,r))})),s()){var r=e.canvas;r.width==t.bufferWidth&&r.height==t.bufferHeight||(t.bufferWidth=r.width,t.bufferHeight=r.height,t.onResize())}},C.prototype.updateDeviceInfo=function(e){var t=this.gl,i=this,r=[t.ARRAY_BUFFER_BINDING,t.ELEMENT_ARRAY_BUFFER_BINDING];R(t,r,(function(t){var r=i.computeMeshVertices_(i.meshWidth,i.meshHeight,e);if(t.bindBuffer(t.ARRAY_BUFFER,i.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,r,t.STATIC_DRAW),!i.indexCount){var n=i.computeMeshIndices_(i.meshWidth,i.meshHeight);t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,i.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,n,t.STATIC_DRAW),i.indexCount=n.length}}))},C.prototype.computeMeshVertices_=function(e,t,i){for(var r=new Float32Array(2*e*t*5),n=i.getLeftEyeVisibleTanAngles(),a=i.getLeftEyeNoLensTanAngles(),s=i.getLeftEyeVisibleScreenRect(a),c=0,h=0;h<2;h++){for(var l=0;ln-42&&r.clientXi.clientHeight-42?e(r):r.clientX<42&&r.clientY<42&&t(r)},i.addEventListener("click",this.listener,!1)},N.prototype.onResize=function(){var e=this.gl,t=this,i=[e.ARRAY_BUFFER_BINDING];R(e,i,(function(e){var i=[],r=e.drawingBufferWidth/2,n=Math.max(screen.width,screen.height)*window.devicePixelRatio,a=e.drawingBufferWidth/n*window.devicePixelRatio,o=4*a/2,s=42*a,c=28*a/2,h=14*a;function l(e,t){var n=(90-e)*O,a=Math.cos(n),o=Math.sin(n);i.push(.3125*a*c+r,.3125*o*c+c),i.push(t*a*c+r,t*o*c+c)}i.push(r-o,s),i.push(r-o,e.drawingBufferHeight),i.push(r+o,s),i.push(r+o,e.drawingBufferHeight),t.gearOffset=i.length/2;for(var u=0;u<=6;u++){var d=60*u;l(d,1),l(d+12,1),l(d+20,.75),l(d+40,.75),l(d+48,1)}function p(t,r){i.push(h+t,e.drawingBufferHeight-h-r)}t.gearVertexCount=i.length/2-t.gearOffset,t.arrowOffset=i.length/2;var f=o/Math.sin(45*O);p(0,c),p(c,0),p(c+f,f),p(f,c+f),p(f,c-f),p(0,c),p(c,2*c),p(c+f,2*c-f),p(f,c-f),p(0,c),p(f,c-o),p(28*a,c-o),p(f,c+o),p(28*a,c+o),t.arrowVertexCount=i.length/2-t.arrowOffset,e.bindBuffer(e.ARRAY_BUFFER,t.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,new Float32Array(i),e.STATIC_DRAW)}))},N.prototype.render=function(){var e=this.gl,t=this,i=[e.CULL_FACE,e.DEPTH_TEST,e.BLEND,e.SCISSOR_TEST,e.STENCIL_TEST,e.COLOR_WRITEMASK,e.VIEWPORT,e.CURRENT_PROGRAM,e.ARRAY_BUFFER_BINDING];R(e,i,(function(e){e.disable(e.CULL_FACE),e.disable(e.DEPTH_TEST),e.disable(e.BLEND),e.disable(e.SCISSOR_TEST),e.disable(e.STENCIL_TEST),e.colorMask(!0,!0,!0,!0),e.viewport(0,0,e.drawingBufferWidth,e.drawingBufferHeight),t.renderNoState()}))},N.prototype.renderNoState=function(){var e,t,i,r,n,a,o,s,c,h,l=this.gl;l.useProgram(this.program),l.bindBuffer(l.ARRAY_BUFFER,this.vertexBuffer),l.enableVertexAttribArray(this.attribs.position),l.vertexAttribPointer(this.attribs.position,2,l.FLOAT,!1,8,0),l.uniform4f(this.uniforms.color,1,1,1,1),e=this.projMat,t=0,i=l.drawingBufferWidth,r=0,n=l.drawingBufferHeight,s=1/(t-i),c=1/(r-n),h=1/((a=.1)-(o=1024)),e[0]=-2*s,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*c,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*h,e[11]=0,e[12]=(t+i)*s,e[13]=(n+r)*c,e[14]=(o+a)*h,e[15]=1,l.uniformMatrix4fv(this.uniforms.projectionMat,!1,this.projMat),l.drawArrays(l.TRIANGLE_STRIP,0,4),l.drawArrays(l.TRIANGLE_STRIP,this.gearOffset,this.gearVertexCount),l.drawArrays(l.TRIANGLE_STRIP,this.arrowOffset,this.arrowVertexCount)},B.prototype.distortInverse=function(e){for(var t=0,i=1,r=e-this.distort(t);Math.abs(i-t)>1e-4;){var n=e-this.distort(i),a=i-n*((i-t)/(n-r));t=i,i=a,r=n}return i},B.prototype.distort=function(e){for(var t=e*e,i=0,r=0;r=1)return this.w=a,this.x=i,this.y=r,this.z=n,this;var s=Math.acos(o),c=Math.sqrt(1-o*o);if(Math.abs(c)<.001)return this.w=.5*(a+this.w),this.x=.5*(i+this.x),this.y=.5*(r+this.y),this.z=.5*(n+this.z),this;var h=Math.sin((1-t)*s)/c,l=Math.sin(t*s)/c;return this.w=a*h+this.w*l,this.x=i*h+this.x*l,this.y=r*h+this.y*l,this.z=n*h+this.z*l,this},setFromUnitVectors:function(e,t){return void 0===G&&(G=new z),(V=e.dot(t)+1)<1e-6?(V=0,Math.abs(e.x)>Math.abs(e.z)?G.set(-e.y,e.x,0):G.set(0,-e.z,e.y)):G.crossVectors(e,t),this.x=G.x,this.y=G.y,this.z=G.z,this.w=V,this.normalize(),this}};var j=new k({widthMeters:.11,heightMeters:.062,bevelMeters:.004}),W=new k({widthMeters:.1038,heightMeters:.0584,bevelMeters:.004}),X={CardboardV1:new q({id:"CardboardV1",label:"Cardboard I/O 2014",fov:40,interLensDistance:.06,baselineLensDistance:.035,screenLensDistance:.042,distortionCoefficients:[.441,.156],inverseCoefficients:[-.4410035,.42756155,-.4804439,.5460139,-.58821183,.5733938,-.48303202,.33299083,-.17573841,.0651772,-.01488963,.001559834]}),CardboardV2:new q({id:"CardboardV2",label:"Cardboard I/O 2015",fov:60,interLensDistance:.064,baselineLensDistance:.035,screenLensDistance:.039,distortionCoefficients:[.34,.55],inverseCoefficients:[-.33836704,-.18162185,.862655,-1.2462051,1.0560602,-.58208317,.21609078,-.05444823,.009177956,-.0009904169,6183535e-11,-16981803e-13]})};function Y(e,t){this.viewer=X.CardboardV2,this.updateDeviceParams(e),this.distortion=new B(this.viewer.distortionCoefficients);for(var i=0;i=200&&i.status<=299?(r.dpdb=JSON.parse(i.response),r.recalculateDeviceParams_()):console.error("Error loading online DPDB!")})),i.send()}}function J(e){this.xdpi=e.xdpi,this.ydpi=e.ydpi,this.bevelMm=e.bevelMm}function K(e,t){this.set(e,t)}function $(e,t){this.kFilter=e,this.isDebug=t,this.currentAccelMeasurement=new K,this.currentGyroMeasurement=new K,this.previousGyroMeasurement=new K,s()?this.filterQ=new H(-1,0,0,1):this.filterQ=new H(1,0,0,1),this.previousFilterQ=new H,this.previousFilterQ.copy(this.filterQ),this.accelQ=new H,this.isOrientationInitialized=!1,this.estimatedGravity=new z,this.measuredGravity=new z,this.gyroIntegralQ=new H}function ee(e,t){this.predictionTimeS=e,this.isDebug=t,this.previousQ=new H,this.previousTimestampS=null,this.deltaQ=new H,this.outQ=new H}function te(e,t,i,r){this.yawOnly=i,this.accelerometer=new z,this.gyroscope=new z,this.filter=new $(e,r),this.posePredictor=new ee(t,r),this.isFirefoxAndroid=l(),this.isIOS=s();var n=u();this.isDeviceMotionInRadians=!this.isIOS&&n&&n<66,this.isWithoutDeviceMotion=p()||d(),this.filterToWorldQ=new H,s()?this.filterToWorldQ.setFromAxisAngle(new z(1,0,0),Math.PI/2):this.filterToWorldQ.setFromAxisAngle(new z(1,0,0),-Math.PI/2),this.inverseWorldToScreenQ=new H,this.worldToScreenQ=new H,this.originalPoseAdjustQ=new H,this.originalPoseAdjustQ.setFromAxisAngle(new z(0,0,1),-window.orientation*Math.PI/180),this.setScreenTransform_(),m()&&this.filterToWorldQ.multiply(this.inverseWorldToScreenQ),this.resetQ=new H,this.orientationOut_=new Float32Array(4),this.start()}Z.prototype.getDeviceParams=function(){return this.deviceParams},Z.prototype.recalculateDeviceParams_=function(){var e=this.calcDeviceParams_();e?(this.deviceParams=e,this.onDeviceParamsUpdated&&this.onDeviceParamsUpdated(this.deviceParams)):console.error("Failed to recalculate device parameters.")},Z.prototype.calcDeviceParams_=function(){var e=this.dpdb;if(!e)return console.error("DPDB not available."),null;if(1!=e.format)return console.error("DPDB has unexpected format version."),null;if(!e.devices||!e.devices.length)return console.error("DPDB does not have a devices section."),null;var t=navigator.userAgent||navigator.vendor||window.opera,i=v(),r=g();if(!e.devices)return console.error("DPDB has no devices section."),null;for(var n=0;n1||this.run_(),this.previousGyroMeasurement.copy(this.currentGyroMeasurement)},$.prototype.run_=function(){if(!this.isOrientationInitialized)return this.accelQ=this.accelToQuaternion_(this.currentAccelMeasurement.sample),this.previousFilterQ.copy(this.accelQ),void(this.isOrientationInitialized=!0);var e=this.currentGyroMeasurement.timestampS-this.previousGyroMeasurement.timestampS,t=this.gyroToQuaternionDelta_(this.currentGyroMeasurement.sample,e);this.gyroIntegralQ.multiply(t),this.filterQ.copy(this.previousFilterQ),this.filterQ.multiply(t);var i=new H;i.copy(this.filterQ),i.inverse(),this.estimatedGravity.set(0,0,-1),this.estimatedGravity.applyQuaternion(i),this.estimatedGravity.normalize(),this.measuredGravity.copy(this.currentAccelMeasurement.sample),this.measuredGravity.normalize();var r,n=new H;n.setFromUnitVectors(this.estimatedGravity,this.measuredGravity),n.inverse(),this.isDebug&&console.log("Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)",U*((r=n).w>1?(console.warn("getQuaternionAngle: w > 1"),0):2*Math.acos(r.w)),this.estimatedGravity.x.toFixed(1),this.estimatedGravity.y.toFixed(1),this.estimatedGravity.z.toFixed(1),this.measuredGravity.x.toFixed(1),this.measuredGravity.y.toFixed(1),this.measuredGravity.z.toFixed(1));var a=new H;a.copy(this.filterQ),a.multiply(n),this.filterQ.slerp(a,1-this.kFilter),this.previousFilterQ.copy(this.filterQ)},$.prototype.getOrientation=function(){return this.filterQ},$.prototype.accelToQuaternion_=function(e){var t=new z;t.copy(e),t.normalize();var i=new H;return i.setFromUnitVectors(new z(0,0,-1),t),i.inverse(),i},$.prototype.gyroToQuaternionDelta_=function(e,t){var i=new H,r=new z;return r.copy(e),r.normalize(),i.setFromAxisAngle(r,e.length()*t),i},ee.prototype.getPrediction=function(e,t,i){if(!this.previousTimestampS)return this.previousQ.copy(e),this.previousTimestampS=i,e;var r=new z;r.copy(t),r.normalize();var n=t.length();if(n<20*F)return this.isDebug&&console.log("Moving slowly, at %s deg/s: no prediction",(U*n).toFixed(1)),this.outQ.copy(e),this.previousQ.copy(e),this.outQ;var a=n*this.predictionTimeS;return this.deltaQ.setFromAxisAngle(r,a),this.outQ.copy(this.previousQ),this.outQ.multiply(this.deltaQ),this.previousQ.copy(e),this.previousTimestampS=i,this.outQ},te.prototype.getPosition=function(){return null},te.prototype.getOrientation=function(){var e=void 0;if(this.isWithoutDeviceMotion&&this._deviceOrientationQ)return this.deviceOrientationFixQ=this.deviceOrientationFixQ||(i=(new H).setFromAxisAngle(new z(0,0,-1),0),r=new H,-90===window.orientation?r.setFromAxisAngle(new z(0,1,0),Math.PI/-2):r.setFromAxisAngle(new z(0,1,0),Math.PI/2),i.multiply(r)),this.deviceOrientationFilterToWorldQ=this.deviceOrientationFilterToWorldQ||((t=new H).setFromAxisAngle(new z(1,0,0),-Math.PI/2),t),e=this._deviceOrientationQ,(n=new H).copy(e),n.multiply(this.deviceOrientationFilterToWorldQ),n.multiply(this.resetQ),n.multiply(this.worldToScreenQ),n.multiplyQuaternions(this.deviceOrientationFixQ,n),this.yawOnly&&(n.x=0,n.z=0,n.normalize()),this.orientationOut_[0]=n.x,this.orientationOut_[1]=n.y,this.orientationOut_[2]=n.z,this.orientationOut_[3]=n.w,this.orientationOut_;var t,i,r,n,a=this.filter.getOrientation();return e=this.posePredictor.getPrediction(a,this.gyroscope,this.previousTimestampS),(n=new H).copy(this.filterToWorldQ),n.multiply(this.resetQ),n.multiply(e),n.multiply(this.worldToScreenQ),this.yawOnly&&(n.x=0,n.z=0,n.normalize()),this.orientationOut_[0]=n.x,this.orientationOut_[1]=n.y,this.orientationOut_[2]=n.z,this.orientationOut_[3]=n.w,this.orientationOut_},te.prototype.resetPose=function(){this.resetQ.copy(this.filter.getOrientation()),this.resetQ.x=0,this.resetQ.y=0,this.resetQ.z*=-1,this.resetQ.normalize(),m()&&this.resetQ.multiply(this.inverseWorldToScreenQ),this.resetQ.multiply(this.originalPoseAdjustQ)},te.prototype.onDeviceOrientation_=function(e){this._deviceOrientationQ=this._deviceOrientationQ||new H;var t=e.alpha,i=e.beta,r=e.gamma;t=(t||0)*Math.PI/180,i=(i||0)*Math.PI/180,r=(r||0)*Math.PI/180,this._deviceOrientationQ.setFromEulerYXZ(i,t,-r)},te.prototype.onDeviceMotion_=function(e){this.updateDeviceMotion_(e)},te.prototype.updateDeviceMotion_=function(e){var t=e.accelerationIncludingGravity,i=e.rotationRate,r=e.timeStamp/1e3,n=r-this.previousTimestampS;return n<0?(T("fusion-pose-sensor:invalid:non-monotonic","Invalid timestamps detected: non-monotonic timestamp from devicemotion"),void(this.previousTimestampS=r)):n<=.001||n>1?(T("fusion-pose-sensor:invalid:outside-threshold","Invalid timestamps detected: Timestamp from devicemotion outside expected range."),void(this.previousTimestampS=r)):(this.accelerometer.set(-t.x,-t.y,-t.z),i&&(f()?this.gyroscope.set(-i.beta,i.alpha,i.gamma):this.gyroscope.set(i.alpha,i.beta,i.gamma),this.isDeviceMotionInRadians||this.gyroscope.multiplyScalar(Math.PI/180),this.filter.addGyroMeasurement(this.gyroscope,r)),this.filter.addAccelMeasurement(this.accelerometer,r),void(this.previousTimestampS=r))},te.prototype.onOrientationChange_=function(e){this.setScreenTransform_()},te.prototype.onMessage_=function(e){var t=e.data;t&&t.type&&"devicemotion"===t.type.toLowerCase()&&this.updateDeviceMotion_(t.deviceMotionEvent)},te.prototype.setScreenTransform_=function(){switch(this.worldToScreenQ.set(0,0,0,1),window.orientation){case 0:break;case 90:this.worldToScreenQ.setFromAxisAngle(new z(0,0,1),-Math.PI/2);break;case-90:this.worldToScreenQ.setFromAxisAngle(new z(0,0,1),Math.PI/2)}this.inverseWorldToScreenQ.copy(this.worldToScreenQ),this.inverseWorldToScreenQ.inverse()},te.prototype.start=function(){var e,t,i;this.onDeviceMotionCallback_=this.onDeviceMotion_.bind(this),this.onOrientationChangeCallback_=this.onOrientationChange_.bind(this),this.onMessageCallback_=this.onMessage_.bind(this),this.onDeviceOrientationCallback_=this.onDeviceOrientation_.bind(this),s()&&(e=window.self!==window.top,t=M(document.referrer),i=M(window.location.href),e&&t!==i)&&window.addEventListener("message",this.onMessageCallback_),window.addEventListener("orientationchange",this.onOrientationChangeCallback_),this.isWithoutDeviceMotion?window.addEventListener("deviceorientation",this.onDeviceOrientationCallback_):window.addEventListener("devicemotion",this.onDeviceMotionCallback_)},te.prototype.stop=function(){window.removeEventListener("devicemotion",this.onDeviceMotionCallback_),window.removeEventListener("deviceorientation",this.onDeviceOrientationCallback_),window.removeEventListener("orientationchange",this.onOrientationChangeCallback_),window.removeEventListener("message",this.onMessageCallback_)};var ie=new z(1,0,0),re=new z(0,0,1),ne=new H;ne.setFromAxisAngle(ie,-Math.PI/2),ne.multiply((new H).setFromAxisAngle(re,Math.PI/2));var ae=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.config=t,this.sensor=null,this.fusionSensor=null,this._out=new Float32Array(4),this.api=null,this.errors=[],this._sensorQ=new H,this._outQ=new H,this._onSensorRead=this._onSensorRead.bind(this),this._onSensorError=this._onSensorError.bind(this),this.init()}return n(e,[{key:"init",value:function(){var e=null;try{(e=new RelativeOrientationSensor({frequency:60,referenceFrame:"screen"})).addEventListener("error",this._onSensorError)}catch(e){this.errors.push(e),"SecurityError"===e.name?(console.error("Cannot construct sensors due to the Feature Policy"),console.warn('Attempting to fall back using "devicemotion"; however this will fail in the future without correct permissions.'),this.useDeviceMotion()):"ReferenceError"===e.name?this.useDeviceMotion():console.error(e)}e&&(this.api="sensor",this.sensor=e,this.sensor.addEventListener("reading",this._onSensorRead),this.sensor.start())}},{key:"useDeviceMotion",value:function(){this.api="devicemotion",this.fusionSensor=new te(this.config.K_FILTER,this.config.PREDICTION_TIME_S,this.config.YAW_ONLY,this.config.DEBUG),this.sensor&&(this.sensor.removeEventListener("reading",this._onSensorRead),this.sensor.removeEventListener("error",this._onSensorError),this.sensor=null)}},{key:"getOrientation",value:function(){if(this.fusionSensor)return this.fusionSensor.getOrientation();if(!this.sensor||!this.sensor.quaternion)return this._out[0]=this._out[1]=this._out[2]=0,this._out[3]=1,this._out;var e=this.sensor.quaternion;this._sensorQ.set(e[0],e[1],e[2],e[3]);var t=this._outQ;return t.copy(ne),t.multiply(this._sensorQ),this.config.YAW_ONLY&&(t.x=t.z=0,t.normalize()),this._out[0]=t.x,this._out[1]=t.y,this._out[2]=t.z,this._out[3]=t.w,this._out}},{key:"_onSensorError",value:function(e){this.errors.push(e.error),"NotAllowedError"===e.error.name?console.error("Permission to access sensor was denied"):"NotReadableError"===e.error.name?console.error("Sensor could not be read"):console.error(e.error),this.useDeviceMotion()}},{key:"_onSensorRead",value:function(){}}]),e}();function oe(){this.loadIcon_();var e=document.createElement("div");(a=e.style).position="fixed",a.top=0,a.right=0,a.bottom=0,a.left=0,a.backgroundColor="gray",a.fontFamily="sans-serif",a.zIndex=1e6;var t=document.createElement("img");t.src=this.icon,(a=t.style).marginLeft="25%",a.marginTop="25%",a.width="50%",e.appendChild(t);var i=document.createElement("div");(a=i.style).textAlign="center",a.fontSize="16px",a.lineHeight="24px",a.margin="24px 25%",a.width="50%",i.innerHTML="Place your phone into your Cardboard viewer.",e.appendChild(i);var r=document.createElement("div");(a=r.style).backgroundColor="#CFD8DC",a.position="fixed",a.bottom=0,a.width="100%",a.height="48px",a.padding="14px 24px",a.boxSizing="border-box",a.color="#656A6B",e.appendChild(r);var n=document.createElement("div");n.style.float="left",n.innerHTML="No Cardboard viewer?";var a,o=document.createElement("a");o.href="https://www.google.com/get/cardboard/get-cardboard/",o.innerHTML="get one",o.target="_blank",(a=o.style).float="right",a.fontWeight=600,a.textTransform="uppercase",a.borderLeft="1px solid gray",a.paddingLeft="24px",a.textDecoration="none",a.color="#656A6B",r.appendChild(n),r.appendChild(o),this.overlay=e,this.text=i,this.hide()}function se(e){try{this.selectedKey=localStorage.getItem("WEBVR_CARDBOARD_VIEWER")}catch(e){console.error("Failed to load viewer profile: %s",e)}this.selectedKey||(this.selectedKey=e||"CardboardV1"),this.dialog=this.createDialog_(Y.Viewers),this.root=null,this.onChangeCallbacks_=[]}oe.prototype.show=function(e){e||this.overlay.parentElement?e&&(this.overlay.parentElement&&this.overlay.parentElement!=e&&this.overlay.parentElement.removeChild(this.overlay),e.appendChild(this.overlay)):document.body.appendChild(this.overlay),this.overlay.style.display="block";var t=this.overlay.querySelector("img").style;m()?(t.width="20%",t.marginLeft="40%",t.marginTop="3%"):(t.width="50%",t.marginLeft="25%",t.marginTop="25%")},oe.prototype.hide=function(){this.overlay.style.display="none"},oe.prototype.showTemporarily=function(e,t){this.show(t),this.timer=setTimeout(this.hide.bind(this),e)},oe.prototype.disableShowTemporarily=function(){clearTimeout(this.timer)},oe.prototype.update=function(){this.disableShowTemporarily(),!m()&&w()?this.show():this.hide()},oe.prototype.loadIcon_=function(){this.icon="data:image/svg+xml,"+encodeURIComponent("")},se.prototype.show=function(e){this.root=e,e.appendChild(this.dialog),this.dialog.querySelector("#"+this.selectedKey).checked=!0,this.dialog.style.display="block"},se.prototype.hide=function(){this.root&&this.root.contains(this.dialog)&&this.root.removeChild(this.dialog),this.dialog.style.display="none"},se.prototype.getCurrentViewer=function(){return Y.Viewers[this.selectedKey]},se.prototype.getSelectedKey_=function(){var e=this.dialog.querySelector("input[name=field]:checked");return e?e.id:null},se.prototype.onChange=function(e){this.onChangeCallbacks_.push(e)},se.prototype.fireOnChange_=function(e){for(var t=0;t.5&&(this.noSleepVideo.currentTime=Math.random())}.bind(this)))}return r(e,[{key:"enable",value:function(){a?(this.disable(),this.noSleepTimer=window.setInterval((function(){window.location.href="/",window.setTimeout(window.stop,0)}),15e3)):this.noSleepVideo.play()}},{key:"disable",value:function(){a?this.noSleepTimer&&(window.clearInterval(this.noSleepTimer),this.noSleepTimer=null):this.noSleepVideo.pause()}}]),e}();e.exports=o},function(e,t,i){e.exports="data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA="}])}))})))&&ce.__esModule&&Object.prototype.hasOwnProperty.call(ce,"default")?ce.default:ce,le=1e3,ue=[0,0,.5,1],de=[.5,0,.5,1],pe=window.requestAnimationFrame,fe=window.cancelAnimationFrame;function me(e){Object.defineProperties(this,{hasPosition:{writable:!1,enumerable:!0,value:e.hasPosition},hasExternalDisplay:{writable:!1,enumerable:!0,value:e.hasExternalDisplay},canPresent:{writable:!1,enumerable:!0,value:e.canPresent},maxLayers:{writable:!1,enumerable:!0,value:e.maxLayers},hasOrientation:{enumerable:!0,get:function(){return S("VRDisplayCapabilities.prototype.hasOrientation","VRDisplay.prototype.getFrameData"),e.hasOrientation}}})}function ve(e){var t=!("wakelock"in(e=e||{}))||e.wakelock;this.isPolyfilled=!0,this.displayId=le++,this.displayName="",this.depthNear=.01,this.depthFar=1e4,this.isPresenting=!1,Object.defineProperty(this,"isConnected",{get:function(){return S("VRDisplay.prototype.isConnected","VRDisplayCapabilities.prototype.hasExternalDisplay"),!1}}),this.capabilities=new me({hasPosition:!1,hasOrientation:!1,hasExternalDisplay:!1,canPresent:!1,maxLayers:1}),this.stageParameters=null,this.waitingForPresent_=!1,this.layer_=null,this.originalParent_=null,this.fullscreenElement_=null,this.fullscreenWrapper_=null,this.fullscreenElementCachedStyle_=null,this.fullscreenEventTarget_=null,this.fullscreenChangeHandler_=null,this.fullscreenErrorHandler_=null,t&&w()&&(this.wakelock_=new he)}ve.prototype.getFrameData=function(e){return E(e,this._getPose(),this)},ve.prototype.getPose=function(){return S("VRDisplay.prototype.getPose","VRDisplay.prototype.getFrameData"),this._getPose()},ve.prototype.resetPose=function(){return S("VRDisplay.prototype.resetPose"),this._resetPose()},ve.prototype.getImmediatePose=function(){return S("VRDisplay.prototype.getImmediatePose","VRDisplay.prototype.getFrameData"),this._getPose()},ve.prototype.requestAnimationFrame=function(e){return pe(e)},ve.prototype.cancelAnimationFrame=function(e){return fe(e)},ve.prototype.wrapForFullscreen=function(e){if(s())return e;if(!this.fullscreenWrapper_){this.fullscreenWrapper_=document.createElement("div");var t=["height: "+Math.min(screen.height,screen.width)+"px !important","top: 0 !important","left: 0 !important","right: 0 !important","border: 0","margin: 0","padding: 0","z-index: 999999 !important","position: fixed"];this.fullscreenWrapper_.setAttribute("style",t.join("; ")+";"),this.fullscreenWrapper_.classList.add("webvr-polyfill-fullscreen-wrapper")}if(this.fullscreenElement_==e)return this.fullscreenWrapper_;if(this.fullscreenElement_&&(this.originalParent_?this.originalParent_.appendChild(this.fullscreenElement_):this.fullscreenElement_.parentElement.removeChild(this.fullscreenElement_)),this.fullscreenElement_=e,this.originalParent_=e.parentElement,this.originalParent_||document.body.appendChild(e),!this.fullscreenWrapper_.parentElement){var i=this.fullscreenElement_.parentElement;i.insertBefore(this.fullscreenWrapper_,this.fullscreenElement_),i.removeChild(this.fullscreenElement_)}this.fullscreenWrapper_.insertBefore(this.fullscreenElement_,this.fullscreenWrapper_.firstChild),this.fullscreenElementCachedStyle_=this.fullscreenElement_.getAttribute("style");var r=this;return function(){if(r.fullscreenElement_){var e=["position: absolute","top: 0","left: 0","width: "+Math.max(screen.width,screen.height)+"px","height: "+Math.min(screen.height,screen.width)+"px","border: 0","margin: 0","padding: 0"];r.fullscreenElement_.setAttribute("style",e.join("; ")+";")}}(),this.fullscreenWrapper_},ve.prototype.removeFullscreenWrapper=function(){if(this.fullscreenElement_){var e=this.fullscreenElement_;this.fullscreenElementCachedStyle_?e.setAttribute("style",this.fullscreenElementCachedStyle_):e.removeAttribute("style"),this.fullscreenElement_=null,this.fullscreenElementCachedStyle_=null;var t=this.fullscreenWrapper_.parentElement;return this.fullscreenWrapper_.removeChild(e),this.originalParent_===t?t.insertBefore(e,this.fullscreenWrapper_):this.originalParent_&&this.originalParent_.appendChild(e),t.removeChild(this.fullscreenWrapper_),e}},ve.prototype.requestPresent=function(e){var t=this.isPresenting,i=this;return e instanceof Array||(S("VRDisplay.prototype.requestPresent with non-array argument","an array of VRLayers as the first argument"),e=[e]),new Promise((function(r,n){if(i.capabilities.canPresent)if(0==e.length||e.length>i.capabilities.maxLayers)n(new Error("Invalid number of layers."));else{var a=e[0];if(a.source){var o=a.leftBounds||ue,h=a.rightBounds||de;if(t){var l=i.layer_;l.source!==a.source&&(l.source=a.source);for(var u=0;u<4;u++)l.leftBounds[u]=o[u],l.rightBounds[u]=h[u];return i.wrapForFullscreen(i.layer_.source),i.updatePresent_(),void r()}if(i.layer_={predistorted:a.predistorted,source:a.source,leftBounds:o.slice(0),rightBounds:h.slice(0)},i.waitingForPresent_=!1,i.layer_&&i.layer_.source){var d=i.wrapForFullscreen(i.layer_.source);i.addFullscreenListeners_(d,(function(){var e=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;i.isPresenting=d===e,i.isPresenting?(screen.orientation&&screen.orientation.lock&&screen.orientation.lock("landscape-primary").catch((function(e){console.error("screen.orientation.lock() failed due to",e.message)})),i.waitingForPresent_=!1,i.beginPresent_(),r()):(screen.orientation&&screen.orientation.unlock&&screen.orientation.unlock(),i.removeFullscreenWrapper(),i.disableWakeLock(),i.endPresent_(),i.removeFullscreenListeners_()),i.fireVRDisplayPresentChange_()}),(function(){i.waitingForPresent_&&(i.removeFullscreenWrapper(),i.removeFullscreenListeners_(),i.disableWakeLock(),i.waitingForPresent_=!1,i.isPresenting=!1,n(new Error("Unable to present.")))})),function(e){if(c())return!1;if(e.requestFullscreen)e.requestFullscreen();else if(e.webkitRequestFullscreen)e.webkitRequestFullscreen();else if(e.mozRequestFullScreen)e.mozRequestFullScreen();else{if(!e.msRequestFullscreen)return!1;e.msRequestFullscreen()}return!0}(d)?(i.enableWakeLock(),i.waitingForPresent_=!0):(s()||c())&&(i.enableWakeLock(),i.isPresenting=!0,i.beginPresent_(),i.fireVRDisplayPresentChange_(),r())}i.waitingForPresent_||s()||(y(),n(new Error("Unable to present.")))}else r()}else n(new Error("VRDisplay is not capable of presenting."))}))},ve.prototype.exitPresent=function(){var e=this.isPresenting,t=this;return this.isPresenting=!1,this.layer_=null,this.disableWakeLock(),new Promise((function(i,r){e?(!y()&&s()&&(t.endPresent_(),t.fireVRDisplayPresentChange_()),c()&&(t.removeFullscreenWrapper(),t.removeFullscreenListeners_(),t.endPresent_(),t.fireVRDisplayPresentChange_()),i()):r(new Error("Was not presenting to VRDisplay."))}))},ve.prototype.getLayers=function(){return this.layer_?[this.layer_]:[]},ve.prototype.fireVRDisplayPresentChange_=function(){var e=new CustomEvent("vrdisplaypresentchange",{detail:{display:this}});window.dispatchEvent(e)},ve.prototype.fireVRDisplayConnect_=function(){var e=new CustomEvent("vrdisplayconnect",{detail:{display:this}});window.dispatchEvent(e)},ve.prototype.addFullscreenListeners_=function(e,t,i){this.removeFullscreenListeners_(),this.fullscreenEventTarget_=e,this.fullscreenChangeHandler_=t,this.fullscreenErrorHandler_=i,t&&(document.fullscreenEnabled?e.addEventListener("fullscreenchange",t,!1):document.webkitFullscreenEnabled?e.addEventListener("webkitfullscreenchange",t,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenchange",t,!1):document.msFullscreenEnabled&&e.addEventListener("msfullscreenchange",t,!1)),i&&(document.fullscreenEnabled?e.addEventListener("fullscreenerror",i,!1):document.webkitFullscreenEnabled?e.addEventListener("webkitfullscreenerror",i,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenerror",i,!1):document.msFullscreenEnabled&&e.addEventListener("msfullscreenerror",i,!1))},ve.prototype.removeFullscreenListeners_=function(){if(this.fullscreenEventTarget_){var e=this.fullscreenEventTarget_;if(this.fullscreenChangeHandler_){var t=this.fullscreenChangeHandler_;e.removeEventListener("fullscreenchange",t,!1),e.removeEventListener("webkitfullscreenchange",t,!1),document.removeEventListener("mozfullscreenchange",t,!1),e.removeEventListener("msfullscreenchange",t,!1)}if(this.fullscreenErrorHandler_){var i=this.fullscreenErrorHandler_;e.removeEventListener("fullscreenerror",i,!1),e.removeEventListener("webkitfullscreenerror",i,!1),document.removeEventListener("mozfullscreenerror",i,!1),e.removeEventListener("msfullscreenerror",i,!1)}this.fullscreenEventTarget_=null,this.fullscreenChangeHandler_=null,this.fullscreenErrorHandler_=null}},ve.prototype.enableWakeLock=function(){this.wakelock_&&this.wakelock_.enable()},ve.prototype.disableWakeLock=function(){this.wakelock_&&this.wakelock_.disable()},ve.prototype.beginPresent_=function(){},ve.prototype.endPresent_=function(){},ve.prototype.submitFrame=function(e){},ve.prototype.getEyeParameters=function(e){return null};var ge={ADDITIONAL_VIEWERS:[],DEFAULT_VIEWER:"",MOBILE_WAKE_LOCK:!0,DEBUG:!1,DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1},ye="left",Ae="right";function xe(e){var t=b({},ge);e=b(t,e||{}),ve.call(this,{wakelock:e.MOBILE_WAKE_LOCK}),this.config=e,this.displayName="Cardboard VRDisplay",this.capabilities=new me({hasPosition:!1,hasOrientation:!0,hasExternalDisplay:!1,canPresent:!0,maxLayers:1}),this.stageParameters=null,this.bufferScale_=this.config.BUFFER_SCALE,this.poseSensor_=new ae(this.config),this.distorter_=null,this.cardboardUI_=null,this.dpdb_=new Z(this.config.DPDB_URL,this.onDeviceParamsUpdated_.bind(this)),this.deviceInfo_=new Y(this.dpdb_.getDeviceParams(),e.ADDITIONAL_VIEWERS),this.viewerSelector_=new se(e.DEFAULT_VIEWER),this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)),this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()),this.config.ROTATE_INSTRUCTIONS_DISABLED||(this.rotateInstructions_=new oe),s()&&window.addEventListener("resize",this.onResize_.bind(this))}return xe.prototype=Object.create(ve.prototype),xe.prototype._getPose=function(){return{position:null,orientation:this.poseSensor_.getOrientation(),linearVelocity:null,linearAcceleration:null,angularVelocity:null,angularAcceleration:null}},xe.prototype._resetPose=function(){this.poseSensor_.resetPose&&this.poseSensor_.resetPose()},xe.prototype._getFieldOfView=function(e){var t;if(e==ye)t=this.deviceInfo_.getFieldOfViewLeftEye();else{if(e!=Ae)return console.error("Invalid eye provided: %s",e),null;t=this.deviceInfo_.getFieldOfViewRightEye()}return t},xe.prototype._getEyeOffset=function(e){var t;if(e==ye)t=[.5*-this.deviceInfo_.viewer.interLensDistance,0,0];else{if(e!=Ae)return console.error("Invalid eye provided: %s",e),null;t=[.5*this.deviceInfo_.viewer.interLensDistance,0,0]}return t},xe.prototype.getEyeParameters=function(e){var t=this._getEyeOffset(e),i=this._getFieldOfView(e),r={offset:t,renderWidth:.5*this.deviceInfo_.device.width*this.bufferScale_,renderHeight:this.deviceInfo_.device.height*this.bufferScale_};return Object.defineProperty(r,"fieldOfView",{enumerable:!0,get:function(){return S("VRFieldOfView","VRFrameData's projection matrices"),i}}),r},xe.prototype.onDeviceParamsUpdated_=function(e){this.config.DEBUG&&console.log("DPDB reported that device params were updated."),this.deviceInfo_.updateDeviceParams(e),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_)},xe.prototype.updateBounds_=function(){this.layer_&&this.distorter_&&(this.layer_.leftBounds||this.layer_.rightBounds)&&this.distorter_.setTextureBounds(this.layer_.leftBounds,this.layer_.rightBounds)},xe.prototype.beginPresent_=function(){var e=this.layer_.source.getContext("webgl");e||(e=this.layer_.source.getContext("experimental-webgl")),e||(e=this.layer_.source.getContext("webgl2")),e&&(this.layer_.predistorted?this.config.CARDBOARD_UI_DISABLED||(e.canvas.width=v()*this.bufferScale_,e.canvas.height=g()*this.bufferScale_,this.cardboardUI_=new N(e)):(this.config.CARDBOARD_UI_DISABLED||(this.cardboardUI_=new N(e)),this.distorter_=new C(e,this.cardboardUI_,this.config.BUFFER_SCALE,this.config.DIRTY_SUBMIT_FRAME_BINDINGS),this.distorter_.updateDeviceInfo(this.deviceInfo_)),this.cardboardUI_&&this.cardboardUI_.listen(function(e){this.viewerSelector_.show(this.layer_.source.parentElement),e.stopPropagation(),e.preventDefault()}.bind(this),function(e){this.exitPresent(),e.stopPropagation(),e.preventDefault()}.bind(this)),this.rotateInstructions_&&(m()&&w()?this.rotateInstructions_.showTemporarily(3e3,this.layer_.source.parentElement):this.rotateInstructions_.update()),this.orientationHandler=this.onOrientationChange_.bind(this),window.addEventListener("orientationchange",this.orientationHandler),this.vrdisplaypresentchangeHandler=this.updateBounds_.bind(this),window.addEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler),this.fireVRDisplayDeviceParamsChange_())},xe.prototype.endPresent_=function(){this.distorter_&&(this.distorter_.destroy(),this.distorter_=null),this.cardboardUI_&&(this.cardboardUI_.destroy(),this.cardboardUI_=null),this.rotateInstructions_&&this.rotateInstructions_.hide(),this.viewerSelector_.hide(),window.removeEventListener("orientationchange",this.orientationHandler),window.removeEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler)},xe.prototype.updatePresent_=function(){this.endPresent_(),this.beginPresent_()},xe.prototype.submitFrame=function(e){if(this.distorter_)this.updateBounds_(),this.distorter_.submitFrame();else if(this.cardboardUI_&&this.layer_){var t=this.layer_.source.getContext("webgl");t||(t=this.layer_.source.getContext("experimental-webgl")),t||(t=this.layer_.source.getContext("webgl2"));var i=t.canvas;i.width==this.lastWidth&&i.height==this.lastHeight||this.cardboardUI_.onResize(),this.lastWidth=i.width,this.lastHeight=i.height,this.cardboardUI_.render()}},xe.prototype.onOrientationChange_=function(e){this.viewerSelector_.hide(),this.rotateInstructions_&&this.rotateInstructions_.update(),this.onResize_()},xe.prototype.onResize_=function(e){if(this.layer_){var t=this.layer_.source.getContext("webgl");t||(t=this.layer_.source.getContext("experimental-webgl")),t||(t=this.layer_.source.getContext("webgl2")),t.canvas.setAttribute("style",["position: absolute","top: 0","left: 0","width: 100vw","height: 100vh","border: 0","margin: 0","padding: 0px","box-sizing: content-box"].join("; ")+";"),_(t.canvas)}},xe.prototype.onViewerChanged_=function(e){this.deviceInfo_.setViewer(e),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_),this.fireVRDisplayDeviceParamsChange_()},xe.prototype.fireVRDisplayDeviceParamsChange_=function(){var e=new CustomEvent("vrdisplaydeviceparamschange",{detail:{vrdisplay:this,deviceInfo:this.deviceInfo_}});window.dispatchEvent(e)},xe.VRFrameData=function(){this.leftProjectionMatrix=new Float32Array(16),this.leftViewMatrix=new Float32Array(16),this.rightProjectionMatrix=new Float32Array(16),this.rightViewMatrix=new Float32Array(16),this.pose=null},xe.VRDisplay=ve,xe}()})))&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,s={ADDITIONAL_VIEWERS:[],DEFAULT_VIEWER:"",PROVIDE_MOBILE_VRDISPLAY:!0,MOBILE_WAKE_LOCK:!0,DEBUG:!1,DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1};function c(e){this.config=a(a({},s),e),this.polyfillDisplays=[],this.enabled=!1,this.hasNative="getVRDisplays"in navigator,this.native={},this.native.getVRDisplays=navigator.getVRDisplays,this.native.VRFrameData=window.VRFrameData,this.native.VRDisplay=window.VRDisplay,(!this.hasNative||this.config.PROVIDE_MOBILE_VRDISPLAY&&i())&&(this.enable(),this.getVRDisplays().then((function(e){e&&e[0]&&e[0].fireVRDisplayConnect_&&e[0].fireVRDisplayConnect_()})))}c.prototype.getPolyfillDisplays=function(){if(this._polyfillDisplaysPopulated)return this.polyfillDisplays;if(i()){var e=new o({ADDITIONAL_VIEWERS:this.config.ADDITIONAL_VIEWERS,DEFAULT_VIEWER:this.config.DEFAULT_VIEWER,MOBILE_WAKE_LOCK:this.config.MOBILE_WAKE_LOCK,DEBUG:this.config.DEBUG,DPDB_URL:this.config.DPDB_URL,CARDBOARD_UI_DISABLED:this.config.CARDBOARD_UI_DISABLED,K_FILTER:this.config.K_FILTER,PREDICTION_TIME_S:this.config.PREDICTION_TIME_S,ROTATE_INSTRUCTIONS_DISABLED:this.config.ROTATE_INSTRUCTIONS_DISABLED,YAW_ONLY:this.config.YAW_ONLY,BUFFER_SCALE:this.config.BUFFER_SCALE,DIRTY_SUBMIT_FRAME_BINDINGS:this.config.DIRTY_SUBMIT_FRAME_BINDINGS});this.polyfillDisplays.push(e)}return this._polyfillDisplaysPopulated=!0,this.polyfillDisplays},c.prototype.enable=function(){if(this.enabled=!0,this.hasNative&&this.native.VRFrameData){var e=this.native.VRFrameData,t=new this.native.VRFrameData,i=this.native.VRDisplay.prototype.getFrameData;window.VRDisplay.prototype.getFrameData=function(r){r instanceof e?i.call(this,r):(i.call(this,t),r.pose=t.pose,n(t.leftProjectionMatrix,r.leftProjectionMatrix),n(t.rightProjectionMatrix,r.rightProjectionMatrix),n(t.leftViewMatrix,r.leftViewMatrix),n(t.rightViewMatrix,r.rightViewMatrix))}}navigator.getVRDisplays=this.getVRDisplays.bind(this),window.VRDisplay=o.VRDisplay,window.VRFrameData=o.VRFrameData},c.prototype.getVRDisplays=function(){var e=this;return this.config,this.hasNative?this.native.getVRDisplays.call(navigator).then((function(t){return t.length>0?t:e.getPolyfillDisplays()})):Promise.resolve(this.getPolyfillDisplays())},c.version="0.10.12",c.VRFrameData=o.VRFrameData,c.VRDisplay=o.VRDisplay;var h=Object.freeze({default:c}),l=h&&c||h;return void 0!==t&&t.window&&(t.document||(t.document=t.window.document),t.navigator||(t.navigator=t.window.navigator)),l}()})));function l(){}void 0===Number.EPSILON&&(Number.EPSILON=Math.pow(2,-52)),void 0===Number.isInteger&&(Number.isInteger=function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}),void 0===Math.sign&&(Math.sign=function(e){return e<0?-1:e>0?1:+e}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),i=1;i>8&255]+e[t>>16&255]+e[t>>24&255]+"-"+e[255&i]+e[i>>8&255]+"-"+e[i>>16&15|64]+e[i>>24&255]+"-"+e[63&r|128]+e[r>>8&255]+"-"+e[r>>16&255]+e[r>>24&255]+e[255&n]+e[n>>8&255]+e[n>>16&255]+e[n>>24&255]).toUpperCase()}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,r,n){return r+(e-t)*(n-r)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*M.DEG2RAD},radToDeg:function(e){return e*M.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))}};function T(e,t){this.x=e||0,this.y=t||0}function S(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}function R(e,t,i,r){this._x=e||0,this._y=t||0,this._z=i||0,this._w=void 0!==r?r:1}function L(e,t,i){this.x=e||0,this.y=t||0,this.z=i||0}function P(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(T.prototype,{width:{get:function(){return this.x},set:function(e){this.x=e}},height:{get:function(){return this.y},set:function(e){this.y=e}}}),Object.assign(T.prototype,{isVector2:!0,set:function(e,t){return this.x=e,this.y=t,this},setScalar:function(e){return this.x=e,this.y=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(e){return this.x=e.x,this.y=e.y,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this)},addScalar:function(e){return this.x+=e,this.y+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this)},subScalar:function(e){return this.x-=e,this.y-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this},multiply:function(e){return this.x*=e.x,this.y*=e.y,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this},divide:function(e){return this.x/=e.x,this.y/=e.y,this},divideScalar:function(e){return this.multiplyScalar(1/e)},applyMatrix3:function(e){var t=this.x,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[7],this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this},clampScalar:(u=new T,d=new T,function(e,t){return u.set(e,e),d.set(t,t),this.clamp(u,d)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(e){return this.x*e.x+this.y*e.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)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var e=Math.atan2(this.y,this.x);return e<0&&(e+=2*Math.PI),e},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y;return t*t+i*i},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},equals:function(e){return e.x===this.x&&e.y===this.y},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this},rotateAround:function(e,t){var i=Math.cos(t),r=Math.sin(t),n=this.x-e.x,a=this.y-e.y;return this.x=n*i-a*r+e.x,this.y=n*r+a*i+e.y,this}}),Object.assign(S.prototype,{isMatrix4:!0,set:function(e,t,i,r,n,a,o,s,c,h,l,u,d,p,f,m){var v=this.elements;return v[0]=e,v[4]=t,v[8]=i,v[12]=r,v[1]=n,v[5]=a,v[9]=o,v[13]=s,v[2]=c,v[6]=h,v[10]=l,v[14]=u,v[3]=d,v[7]=p,v[11]=f,v[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new S).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this},copyPosition:function(e){var t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this},extractBasis:function(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this},extractRotation:(x=new L,function(e){var t=this.elements,i=e.elements,r=1/x.setFromMatrixColumn(e,0).length(),n=1/x.setFromMatrixColumn(e,1).length(),a=1/x.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[3]=0,t[4]=i[4]*n,t[5]=i[5]*n,t[6]=i[6]*n,t[7]=0,t[8]=i[8]*a,t[9]=i[9]*a,t[10]=i[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}),makeRotationFromEuler:function(e){e&&e.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var t=this.elements,i=e.x,r=e.y,n=e.z,a=Math.cos(i),o=Math.sin(i),s=Math.cos(r),c=Math.sin(r),h=Math.cos(n),l=Math.sin(n);if("XYZ"===e.order){var u=a*h,d=a*l,p=o*h,f=o*l;t[0]=s*h,t[4]=-s*l,t[8]=c,t[1]=d+p*c,t[5]=u-f*c,t[9]=-o*s,t[2]=f-u*c,t[6]=p+d*c,t[10]=a*s}else if("YXZ"===e.order){var m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m+y*o,t[4]=g*o-v,t[8]=a*c,t[1]=a*l,t[5]=a*h,t[9]=-o,t[2]=v*o-g,t[6]=y+m*o,t[10]=a*s}else if("ZXY"===e.order){m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m-y*o,t[4]=-a*l,t[8]=g+v*o,t[1]=v+g*o,t[5]=a*h,t[9]=y-m*o,t[2]=-a*c,t[6]=o,t[10]=a*s}else if("ZYX"===e.order){u=a*h,d=a*l,p=o*h,f=o*l;t[0]=s*h,t[4]=p*c-d,t[8]=u*c+f,t[1]=s*l,t[5]=f*c+u,t[9]=d*c-p,t[2]=-c,t[6]=o*s,t[10]=a*s}else if("YZX"===e.order){var A=a*s,x=a*c,w=o*s,b=o*c;t[0]=s*h,t[4]=b-A*l,t[8]=w*l+x,t[1]=l,t[5]=a*h,t[9]=-o*h,t[2]=-c*h,t[6]=x*l+w,t[10]=A-b*l}else if("XZY"===e.order){A=a*s,x=a*c,w=o*s,b=o*c;t[0]=s*h,t[4]=-l,t[8]=c*h,t[1]=A*l+b,t[5]=a*h,t[9]=x*l-w,t[2]=w*l-x,t[6]=o*h,t[10]=b*l+A}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromQuaternion:(y=new L(0,0,0),A=new L(1,1,1),function(e){return this.compose(y,e,A)}),lookAt:(m=new L,v=new L,g=new L,function(e,t,i){var r=this.elements;return g.subVectors(e,t),0===g.lengthSq()&&(g.z=1),g.normalize(),m.crossVectors(i,g),0===m.lengthSq()&&(1===Math.abs(i.z)?g.x+=1e-4:g.z+=1e-4,g.normalize(),m.crossVectors(i,g)),m.normalize(),v.crossVectors(g,m),r[0]=m.x,r[4]=v.x,r[8]=g.x,r[1]=m.y,r[5]=v.y,r[9]=g.y,r[2]=m.z,r[6]=v.z,r[10]=g.z,this}),multiply:function(e,t){return void 0!==t?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(e,t)):this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var i=e.elements,r=t.elements,n=this.elements,a=i[0],o=i[4],s=i[8],c=i[12],h=i[1],l=i[5],u=i[9],d=i[13],p=i[2],f=i[6],m=i[10],v=i[14],g=i[3],y=i[7],A=i[11],x=i[15],w=r[0],b=r[4],_=r[8],E=r[12],M=r[1],T=r[5],S=r[9],R=r[13],L=r[2],P=r[6],C=r[10],D=r[14],I=r[3],O=r[7],N=r[11],B=r[15];return n[0]=a*w+o*M+s*L+c*I,n[4]=a*b+o*T+s*P+c*O,n[8]=a*_+o*S+s*C+c*N,n[12]=a*E+o*R+s*D+c*B,n[1]=h*w+l*M+u*L+d*I,n[5]=h*b+l*T+u*P+d*O,n[9]=h*_+l*S+u*C+d*N,n[13]=h*E+l*R+u*D+d*B,n[2]=p*w+f*M+m*L+v*I,n[6]=p*b+f*T+m*P+v*O,n[10]=p*_+f*S+m*C+v*N,n[14]=p*E+f*R+m*D+v*B,n[3]=g*w+y*M+A*L+x*I,n[7]=g*b+y*T+A*P+x*O,n[11]=g*_+y*S+A*C+x*N,n[15]=g*E+y*R+A*D+x*B,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this},applyToBufferAttribute:function(){var e=new L;return function(t){for(var i=0,r=t.count;i=0?1:-1,y=1-v*v;if(y>Number.EPSILON){var A=Math.sqrt(y),x=Math.atan2(A,v*g);m=Math.sin(m*x)/A,o=Math.sin(o*x)/A}var w=o*g;if(s=s*m+u*w,c=c*m+d*w,h=h*m+p*w,l=l*m+f*w,m===1-o){var b=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=b,c*=b,h*=b,l*=b}}e[t]=s,e[t+1]=c,e[t+2]=h,e[t+3]=l}}),Object.defineProperties(R.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this.onChangeCallback()}}}),Object.assign(R.prototype,{set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this.onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var i=e._x,r=e._y,n=e._z,a=e.order,o=Math.cos,s=Math.sin,c=o(i/2),h=o(r/2),l=o(n/2),u=s(i/2),d=s(r/2),p=s(n/2);return"XYZ"===a?(this._x=u*h*l+c*d*p,this._y=c*d*l-u*h*p,this._z=c*h*p+u*d*l,this._w=c*h*l-u*d*p):"YXZ"===a?(this._x=u*h*l+c*d*p,this._y=c*d*l-u*h*p,this._z=c*h*p-u*d*l,this._w=c*h*l+u*d*p):"ZXY"===a?(this._x=u*h*l-c*d*p,this._y=c*d*l+u*h*p,this._z=c*h*p+u*d*l,this._w=c*h*l-u*d*p):"ZYX"===a?(this._x=u*h*l-c*d*p,this._y=c*d*l+u*h*p,this._z=c*h*p-u*d*l,this._w=c*h*l+u*d*p):"YZX"===a?(this._x=u*h*l+c*d*p,this._y=c*d*l+u*h*p,this._z=c*h*p-u*d*l,this._w=c*h*l-u*d*p):"XZY"===a&&(this._x=u*h*l-c*d*p,this._y=c*d*l-u*h*p,this._z=c*h*p+u*d*l,this._w=c*h*l+u*d*p),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,r=i[0],n=i[4],a=i[8],o=i[1],s=i[5],c=i[9],h=i[2],l=i[6],u=i[10],d=r+s+u;return d>0?(t=.5/Math.sqrt(d+1),this._w=.25/t,this._x=(l-c)*t,this._y=(a-h)*t,this._z=(o-n)*t):r>s&&r>u?(t=2*Math.sqrt(1+r-s-u),this._w=(l-c)/t,this._x=.25*t,this._y=(n+o)/t,this._z=(a+h)/t):s>u?(t=2*Math.sqrt(1+s-r-u),this._w=(a-h)/t,this._x=(n+o)/t,this._y=.25*t,this._z=(c+l)/t):(t=2*Math.sqrt(1+u-r-s),this._w=(o-n)/t,this._x=(a+h)/t,this._y=(c+l)/t,this._z=.25*t),this.onChangeCallback(),this},setFromUnitVectors:function(){var e,t=new L;return function(i,r){return void 0===t&&(t=new L),(e=i.dot(r)+1)<1e-6?(e=0,Math.abs(i.x)>Math.abs(i.z)?t.set(-i.y,i.x,0):t.set(0,-i.z,i.y)):t.crossVectors(i,r),this._x=t.x,this._y=t.y,this._z=t.z,this._w=e,this.normalize()}}(),inverse:function(){return this.conjugate()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this.onChangeCallback(),this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var i=e._x,r=e._y,n=e._z,a=e._w,o=t._x,s=t._y,c=t._z,h=t._w;return this._x=i*h+a*o+r*c-n*s,this._y=r*h+a*s+n*o-i*c,this._z=n*h+a*c+i*s-r*o,this._w=a*h-i*o-r*s-n*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,r=this._y,n=this._z,a=this._w,o=a*e._w+i*e._x+r*e._y+n*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=a,this._x=i,this._y=r,this._z=n,this;var s=Math.sqrt(1-o*o);if(Math.abs(s)<.001)return this._w=.5*(a+this._w),this._x=.5*(i+this._x),this._y=.5*(r+this._y),this._z=.5*(n+this._z),this;var c=Math.atan2(s,o),h=Math.sin((1-t)*c)/s,l=Math.sin(t*c)/s;return this._w=a*h+this._w*l,this._x=i*h+this._x*l,this._y=r*h+this._y*l,this._z=n*h+this._z*l,this.onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return void 0===t&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this.onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(L.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:(w=new R,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(w.setFromEuler(e))}),applyAxisAngle:function(){var e=new R;return function(t,i){return this.applyQuaternion(e.setFromAxisAngle(t,i))}}(),applyMatrix3:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[3]*i+n[6]*r,this.y=n[1]*t+n[4]*i+n[7]*r,this.z=n[2]*t+n[5]*i+n[8]*r,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements,a=1/(n[3]*t+n[7]*i+n[11]*r+n[15]);return this.x=(n[0]*t+n[4]*i+n[8]*r+n[12])*a,this.y=(n[1]*t+n[5]*i+n[9]*r+n[13])*a,this.z=(n[2]*t+n[6]*i+n[10]*r+n[14])*a,this},applyQuaternion:function(e){var t=this.x,i=this.y,r=this.z,n=e.x,a=e.y,o=e.z,s=e.w,c=s*t+a*r-o*i,h=s*i+o*t-n*r,l=s*r+n*i-a*t,u=-n*t-a*i-o*r;return this.x=c*s+u*-n+h*-o-l*-a,this.y=h*s+u*-a+l*-n-c*-o,this.z=l*s+u*-o+c*-a-h*-n,this},project:function(){var e=new S;return function(t){return e.multiplyMatrices(t.projectionMatrix,e.getInverse(t.matrixWorld)),this.applyMatrix4(e)}}(),unproject:function(){var e=new S;return function(t){return e.multiplyMatrices(t.matrixWorld,e.getInverse(t.projectionMatrix)),this.applyMatrix4(e)}}(),transformDirection:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r,this.y=n[1]*t+n[5]*i+n[9]*r,this.z=n[2]*t+n[6]*i+n[10]*r,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:function(){var e=new L,t=new L;return function(i,r){return e.set(i,i,i),t.set(r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.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)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},cross:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var i=e.x,r=e.y,n=e.z,a=t.x,o=t.y,s=t.z;return this.x=r*s-n*o,this.y=n*a-i*s,this.z=i*o-r*a,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:function(){var e=new L;return function(t){return e.copy(this).projectOnVector(t),this.sub(e)}}(),reflect:function(){var e=new L;return function(t){return this.sub(e.copy(t).multiplyScalar(2*this.dot(t)))}}(),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(M.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}}),Object.assign(P.prototype,{isMatrix3:!0,set:function(e,t,i,r,n,a,o,s,c){var h=this.elements;return h[0]=e,h[1]=r,h[2]=o,h[3]=t,h[4]=n,h[5]=s,h[6]=i,h[7]=a,h[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},applyToBufferAttribute:function(){var e=new L;return function(t){for(var i=0,r=t.count;i2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")}(r)}),i.image=r.uuid}return t||(e.textures[this.uuid]=i),i},dispose:function(){this.dispatchEvent({type:"dispose"})},transformUv:function(e){if(300===this.mapping){if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case 1e3:e.x=e.x-Math.floor(e.x);break;case 1001:e.x=e.x<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case 1e3:e.y=e.y-Math.floor(e.y);break;case 1001:e.y=e.y<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}this.flipY&&(e.y=1-e.y)}}}),Object.defineProperty(F.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(U.prototype,{isVector4:!0,set:function(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this.w=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setW:function(e){return this.w=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=this.w,a=e.elements;return this.x=a[0]*t+a[4]*i+a[8]*r+a[12]*n,this.y=a[1]*t+a[5]*i+a[9]*r+a[13]*n,this.z=a[2]*t+a[6]*i+a[10]*r+a[14]*n,this.w=a[3]*t+a[7]*i+a[11]*r+a[15]*n,this},divideScalar:function(e){return this.multiplyScalar(1/e)},setAxisAngleFromQuaternion:function(e){this.w=2*Math.acos(e.w);var t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this},setAxisAngleFromRotationMatrix:function(e){var t,i,r,n,a=e.elements,o=a[0],s=a[4],c=a[8],h=a[1],l=a[5],u=a[9],d=a[2],p=a[6],f=a[10];if(Math.abs(s-h)<.01&&Math.abs(c-d)<.01&&Math.abs(u-p)<.01){if(Math.abs(s+h)<.1&&Math.abs(c+d)<.1&&Math.abs(u+p)<.1&&Math.abs(o+l+f-3)<.1)return this.set(1,0,0,0),this;t=Math.PI;var m=(o+1)/2,v=(l+1)/2,g=(f+1)/2,y=(s+h)/4,A=(c+d)/4,x=(u+p)/4;return m>v&&m>g?m<.01?(i=0,r=.707106781,n=.707106781):(r=y/(i=Math.sqrt(m)),n=A/i):v>g?v<.01?(i=.707106781,r=0,n=.707106781):(i=y/(r=Math.sqrt(v)),n=x/r):g<.01?(i=.707106781,r=.707106781,n=0):(i=A/(n=Math.sqrt(g)),r=x/n),this.set(i,r,n,t),this}var w=Math.sqrt((p-u)*(p-u)+(c-d)*(c-d)+(h-s)*(h-s));return Math.abs(w)<.001&&(w=1),this.x=(p-u)/w,this.y=(c-d)/w,this.z=(h-s)/w,this.w=Math.acos((o+l+f-1)/2),this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this.w=Math.min(this.w,e.w),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this.w=Math.max(this.w,e.w),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this.w=Math.max(e.w,Math.min(t.w,this.w)),this},clampScalar:function(){var e,t;return function(i,r){return void 0===e&&(e=new U,t=new U),e.set(i,i,i,i),t.set(r,r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this.w=this.w<0?Math.ceil(this.w):Math.floor(this.w),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.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)},manhattanLength: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()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this.w+=(e.w-this.w)*t,this},lerpVectors:function(e,t,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z&&e.w===this.w},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this.w=e[t+3],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e[t+3]=this.w,e},fromBufferAttribute:function(e,t,i){return void 0!==i&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this.w=e.getW(t),this}}),z.prototype=Object.assign(Object.create(l.prototype),{constructor:z,isWebGLRenderTarget:!0,setSize:function(e,t){this.width===e&&this.height===t||(this.width=e,this.height=t,this.dispose()),this.viewport.set(0,0,e,t),this.scissor.set(0,0,e,t)},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.width=e.width,this.height=e.height,this.viewport.copy(e.viewport),this.texture=e.texture.clone(),this.depthBuffer=e.depthBuffer,this.stencilBuffer=e.stencilBuffer,this.depthTexture=e.depthTexture,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),G.prototype=Object.create(z.prototype),G.prototype.constructor=G,G.prototype.isWebGLRenderTargetCube=!0,V.prototype=Object.create(F.prototype),V.prototype.constructor=V,V.prototype.isDataTexture=!0,Object.assign(H.prototype,{isBox3:!0,set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromArray:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,a=-1/0,o=-1/0,s=0,c=e.length;sn&&(n=h),l>a&&(a=l),u>o&&(o=u)}return this.min.set(t,i,r),this.max.set(n,a,o),this},setFromBufferAttribute:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,a=-1/0,o=-1/0,s=0,c=e.count;sn&&(n=h),l>a&&(a=l),u>o&&(o=u)}return this.min.set(t,i,r),this.max.set(n,a,o),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return void 0===t&&(console.warn("THREE.Box3: .getParameter() target is now required"),t=new L),t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:(C=new L,function(e){return this.clampPoint(e.center,C),C.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=e.constant&&i>=e.constant},intersectsTriangle:function(){var e=new L,t=new L,i=new L,r=new L,n=new L,a=new L,o=new L,s=new L,c=new L,h=new L;function l(r){var n,a;for(n=0,a=r.length-3;n<=a;n+=3){o.fromArray(r,n);var s=c.x*Math.abs(o.x)+c.y*Math.abs(o.y)+c.z*Math.abs(o.z),h=e.dot(o),l=t.dot(o),u=i.dot(o);if(Math.max(-Math.max(h,l,u),Math.min(h,l,u))>s)return!1}return!0}return function(o){if(this.isEmpty())return!1;this.getCenter(s),c.subVectors(this.max,s),e.subVectors(o.a,s),t.subVectors(o.b,s),i.subVectors(o.c,s),r.subVectors(t,e),n.subVectors(i,t),a.subVectors(e,i);var u=[0,-r.z,r.y,0,-n.z,n.y,0,-a.z,a.y,r.z,0,-r.x,n.z,0,-n.x,a.z,0,-a.x,-r.y,r.x,0,-n.y,n.x,0,-a.y,a.x,0];return!!l(u)&&(!!l(u=[1,0,0,0,1,0,0,0,1])&&(h.crossVectors(r,n),l(u=[h.x,h.y,h.z])))}}(),clampPoint:function(e,t){return void 0===t&&(console.warn("THREE.Box3: .clampPoint() target is now required"),t=new L),t.copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new L;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),getBoundingSphere:function(){var e=new L;return function(t){return void 0===t&&(console.warn("THREE.Box3: .getBoundingSphere() target is now required"),t=new k),this.getCenter(t.center),t.radius=.5*this.getSize(e).length(),t}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:function(e){if(this.isEmpty())return this;var t=e.elements,i=t[0]*this.min.x,r=t[1]*this.min.x,n=t[2]*this.min.x,a=t[0]*this.max.x,o=t[1]*this.max.x,s=t[2]*this.max.x,c=t[4]*this.min.y,h=t[5]*this.min.y,l=t[6]*this.min.y,u=t[4]*this.max.y,d=t[5]*this.max.y,p=t[6]*this.max.y,f=t[8]*this.min.z,m=t[9]*this.min.z,v=t[10]*this.min.z,g=t[8]*this.max.z,y=t[9]*this.max.z,A=t[10]*this.max.z;return this.min.x=Math.min(i,a)+Math.min(c,u)+Math.min(f,g)+t[12],this.min.y=Math.min(r,o)+Math.min(h,d)+Math.min(m,y)+t[13],this.min.z=Math.min(n,s)+Math.min(l,p)+Math.min(v,A)+t[14],this.max.x=Math.max(i,a)+Math.max(c,u)+Math.max(f,g)+t[12],this.max.y=Math.max(r,o)+Math.max(h,d)+Math.max(m,y)+t[13],this.max.z=Math.max(n,s)+Math.max(l,p)+Math.max(v,A)+t[14],this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),Object.assign(k.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(D=new H,function(e,t){var i=this.center;void 0!==t?i.copy(t):D.setFromPoints(e).getCenter(i);for(var r=0,n=0,a=e.length;nthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t},getBoundingBox:function(e){return void 0===e&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),e=new H),e.set(this.center,this.center),e.expandByScalar(this.radius),e},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}}),Object.assign(j.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(){var e=new L,t=new L;return function(i,r,n){var a=e.subVectors(n,r).cross(t.subVectors(i,r)).normalize();return this.setFromNormalAndCoplanarPoint(a,i),this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return void 0===t&&(console.warn("THREE.Plane: .projectPoint() target is now required"),t=new L),t.copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(){var e=new L;return function(t,i){void 0===i&&(console.warn("THREE.Plane: .intersectLine() target is now required"),i=new L);var r=t.delta(e),n=this.normal.dot(r);if(0===n)return 0===this.distanceToPoint(t.start)?i.copy(t.start):void 0;var a=-(t.start.dot(this.normal)+this.constant)/n;return a<0||a>1?void 0:i.copy(r).multiplyScalar(a).add(t.start)}}(),intersectsLine:function(e){var t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return void 0===e&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),e=new L),e.copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var e=new L,t=new P;return function(i,r){var n=r||t.getNormalMatrix(i),a=this.coplanarPoint(e).applyMatrix4(i),o=this.normal.applyMatrix3(n).normalize();return this.constant=-a.dot(o),this}}(),translate:function(e){return this.constant-=e.dot(this.normal),this},equals:function(e){return e.normal.equals(this.normal)&&e.constant===this.constant}}),Object.assign(W.prototype,{set:function(e,t,i,r,n,a){var o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(i),o[3].copy(r),o[4].copy(n),o[5].copy(a),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,i=0;i<6;i++)t[i].copy(e.planes[i]);return this},setFromMatrix:function(e){var t=this.planes,i=e.elements,r=i[0],n=i[1],a=i[2],o=i[3],s=i[4],c=i[5],h=i[6],l=i[7],u=i[8],d=i[9],p=i[10],f=i[11],m=i[12],v=i[13],g=i[14],y=i[15];return t[0].setComponents(o-r,l-s,f-u,y-m).normalize(),t[1].setComponents(o+r,l+s,f+u,y+m).normalize(),t[2].setComponents(o+n,l+c,f+d,y+v).normalize(),t[3].setComponents(o-n,l-c,f-d,y-v).normalize(),t[4].setComponents(o-a,l-h,f-p,y-g).normalize(),t[5].setComponents(o+a,l+h,f+p,y+g).normalize(),this},intersectsObject:(N=new k,function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),N.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(N)}),intersectsSprite:function(){var e=new k;return function(t){return e.center.set(0,0,0),e.radius=.7071067811865476,e.applyMatrix4(t.matrixWorld),this.intersectsSphere(e)}}(),intersectsSphere:function(e){for(var t=this.planes,i=e.center,r=-e.radius,n=0;n<6;n++){if(t[n].distanceToPoint(i)0?e.min.x:e.max.x,O.x=r.normal.x>0?e.max.x:e.min.x,I.y=r.normal.y>0?e.min.y:e.max.y,O.y=r.normal.y>0?e.max.y:e.min.y,I.z=r.normal.z>0?e.min.z:e.max.z,O.z=r.normal.z>0?e.max.z:e.min.z;var n=r.distanceToPoint(I),a=r.distanceToPoint(O);if(n<0&&a<0)return!1}return!0}),containsPoint:function(e){for(var t=this.planes,i=0;i<6;i++)if(t[i].distanceToPoint(e)<0)return!1;return!0}});var X,Y={alphamap_fragment:"#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n",alphamap_pars_fragment:"#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n",alphatest_fragment:"#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n",aomap_fragment:"#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n",aomap_pars_fragment:"#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif",begin_vertex:"\nvec3 transformed = vec3( position );\n",beginnormal_vertex:"\nvec3 objectNormal = vec3( normal );\n",bsdfs:"float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars_begin:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n",lights_pars_maps:"#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif\n",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif\n",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n",normal_fragment_maps:"#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy *= normalScale;\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}\n",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},q={merge:function(e){for(var t={},i=0;i>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function e(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+6*(t-e)*(2/3-i):e}return function(t,i,r){if(t=M.euclideanModulo(t,1),i=M.clamp(i,0,1),r=M.clamp(r,0,1),0===i)this.r=this.g=this.b=r;else{var n=r<=.5?r*(1+i):r+i-r*i,a=2*r-n;this.r=e(a,n,t+1/3),this.g=e(a,n,t),this.b=e(a,n,t-1/3)}return this}}(),setStyle:function(e){function t(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}var i;if(i=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var r,n=i[1],a=i[2];switch(n){case"rgb":case"rgba":if(r=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(255,parseInt(r[1],10))/255,this.g=Math.min(255,parseInt(r[2],10))/255,this.b=Math.min(255,parseInt(r[3],10))/255,t(r[5]),this;if(r=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(100,parseInt(r[1],10))/100,this.g=Math.min(100,parseInt(r[2],10))/100,this.b=Math.min(100,parseInt(r[3],10))/100,t(r[5]),this;break;case"hsl":case"hsla":if(r=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a)){var o=parseFloat(r[1])/360,s=parseInt(r[2],10)/100,c=parseInt(r[3],10)/100;return t(r[5]),this.setHSL(o,s,c)}}}else if(i=/^\#([A-Fa-f0-9]+)$/.exec(e)){var h,l=(h=i[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}e&&e.length>0&&(void 0!==(h=Q[e])?this.setHex(h):console.warn("THREE.Color: Unknown color "+e));return this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(e){return this.r=e.r,this.g=e.g,this.b=e.b,this},copyGammaToLinear:function(e,t){return void 0===t&&(t=2),this.r=Math.pow(e.r,t),this.g=Math.pow(e.g,t),this.b=Math.pow(e.b,t),this},copyLinearToGamma:function(e,t){void 0===t&&(t=2);var i=t>0?1/t:1;return this.r=Math.pow(e.r,i),this.g=Math.pow(e.g,i),this.b=Math.pow(e.b,i),this},convertGammaToLinear:function(e){return this.copyGammaToLinear(this,e),this},convertLinearToGamma:function(e){return this.copyLinearToGamma(this,e),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(e){void 0===e&&(console.warn("THREE.Color: .getHSL() target is now required"),e={h:0,s:0,l:0});var t,i,r=this.r,n=this.g,a=this.b,o=Math.max(r,n,a),s=Math.min(r,n,a),c=(s+o)/2;if(s===o)t=0,i=0;else{var h=o-s;switch(i=c<=.5?h/(o+s):h/(2-o-s),o){case r:t=(n-a)/h+(n1){for(var t=0;t1){for(var t=0;t0){r.children=[];for(s=0;s0&&(i.geometries=u),d.length>0&&(i.materials=d),p.length>0&&(i.textures=p),f.length>0&&(i.images=f),o.length>0&&(i.shapes=o)}return i.object=r,i;function m(e){var t=[];for(var i in e){var r=e[i];delete r.metadata,t.push(r)}return t}},clone:function(e){return(new this.constructor).copy(this,e)},copy:function(e,t){if(void 0===t&&(t=!0),this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(var i=0;it&&(t=e[i]);return t}ve.prototype=Object.assign(Object.create(l.prototype),{constructor:ve,isGeometry:!0,applyMatrix:function(e){for(var t=(new P).getNormalMatrix(e),i=0,r=this.vertices.length;i0)for(d=0;d0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,i;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,i,r,n;for(i=0,r=this.faces.length;i=0;i--){var f=d[i];for(this.faces.splice(f,1),o=0,s=this.faceVertexUvs.length;o0,v=p.vertexNormals.length>0,g=1!==p.color.r||1!==p.color.g||1!==p.color.b,y=p.vertexColors.length>0,A=0;if(A=_(A,0,0),A=_(A,1,!0),A=_(A,2,!1),A=_(A,3,f),A=_(A,4,m),A=_(A,5,v),A=_(A,6,g),A=_(A,7,y),o.push(A),o.push(p.a,p.b,p.c),o.push(p.materialIndex),f){var x=this.faceVertexUvs[0][n];o.push(T(x[0]),T(x[1]),T(x[2]))}if(m&&o.push(E(p.normal)),v){var w=p.vertexNormals;o.push(E(w[0]),E(w[1]),E(w[2]))}if(g&&o.push(M(p.color)),y){var b=p.vertexColors;o.push(M(b[0]),M(b[1]),M(b[2]))}}function _(e,t,i){return i?e|1<0&&(e.data.colors=h),u.length>0&&(e.data.uvs=[u]),e.data.faces=o,e},clone:function(){return(new ve).copy(this)},copy:function(e){var t,i,r,n,a,o;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var s=e.vertices;for(t=0,i=s.length;t0,o=n[1]&&n[1].length>0,s=e.morphTargets,c=s.length;if(c>0){t=[];for(var h=0;h0){l=[];for(h=0;h0?1:-1,h.push(P.x,P.y,P.z),l.push(y/m),l.push(1-A/v),S+=1}}for(A=0;A65535?Ee:be)(e,1):this.index=e},addAttribute:function(e,t){return t&&t.isBufferAttribute||t&&t.isInterleavedBufferAttribute?"index"===e?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),this.setIndex(t),this):(this.attributes[e]=t,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),this.addAttribute(e,new ge(arguments[1],arguments[2])))},getAttribute:function(e){return this.attributes[e]},removeAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,i){this.groups.push({start:e,count:t,materialIndex:void 0!==i?i:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix:function(e){var t=this.attributes.position;void 0!==t&&(e.applyToBufferAttribute(t),t.needsUpdate=!0);var i=this.attributes.normal;void 0!==i&&((new P).getNormalMatrix(e).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var e=new S;return function(t){return e.makeRotationX(t),this.applyMatrix(e),this}}(),rotateY:function(){var e=new S;return function(t){return e.makeRotationY(t),this.applyMatrix(e),this}}(),rotateZ:function(){var e=new S;return function(t){return e.makeRotationZ(t),this.applyMatrix(e),this}}(),translate:function(){var e=new S;return function(t,i,r){return e.makeTranslation(t,i,r),this.applyMatrix(e),this}}(),scale:function(){var e=new S;return function(t,i,r){return e.makeScale(t,i,r),this.applyMatrix(e),this}}(),lookAt:function(){var e=new he;return function(t){e.lookAt(t),e.updateMatrix(),this.applyMatrix(e.matrix)}}(),center:function(){var e=new L;return function(){return this.computeBoundingBox(),this.boundingBox.getCenter(e).negate(),this.translate(e.x,e.y,e.z),this}}(),setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var i=new Me(3*t.vertices.length,3),r=new Me(3*t.colors.length,3);if(this.addAttribute("position",i.copyVector3sArray(t.vertices)),this.addAttribute("color",r.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var n=new Me(t.lineDistances.length,1);this.addAttribute("lineDistance",n.copyArray(t.lineDistances))}null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone())}else e.isMesh&&t&&t.isGeometry&&this.fromGeometry(t);return this},setFromPoints:function(e){for(var t=[],i=0,r=e.length;i0){var i=new Float32Array(3*e.normals.length);this.addAttribute("normal",new ge(i,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var r=new Float32Array(3*e.colors.length);this.addAttribute("color",new ge(r,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var n=new Float32Array(2*e.uvs.length);this.addAttribute("uv",new ge(n,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var a=new Float32Array(2*e.uvs2.length);this.addAttribute("uv2",new ge(a,2).copyVector2sArray(e.uvs2))}for(var o in this.groups=e.groups,e.morphTargets){for(var s=[],c=e.morphTargets[o],h=0,l=c.length;h0){var p=new Me(4*e.skinIndices.length,4);this.addAttribute("skinIndex",p.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var f=new Me(4*e.skinWeights.length,4);this.addAttribute("skinWeight",f.copyVector4sArray(e.skinWeights))}return null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone()),this},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new H);var e=this.attributes.position;void 0!==e?this.boundingBox.setFromBufferAttribute(e):this.boundingBox.makeEmpty(),(isNaN(this.boundingBox.min.x)||isNaN(this.boundingBox.min.y)||isNaN(this.boundingBox.min.z))&&console.error('THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.',this)},computeBoundingSphere:function(){var e=new H,t=new L;return function(){null===this.boundingSphere&&(this.boundingSphere=new k);var i=this.attributes.position;if(i){var r=this.boundingSphere.center;e.setFromBufferAttribute(i),e.getCenter(r);for(var n=0,a=0,o=i.count;a0&&(e.userData=this.userData),void 0!==this.parameters){var t=this.parameters;for(var i in t)void 0!==t[i]&&(e[i]=t[i]);return e}e.data={attributes:{}};var r=this.index;if(null!==r){var n=Array.prototype.slice.call(r.array);e.data.index={type:r.array.constructor.name,array:n}}var a=this.attributes;for(var i in a){var o=a[i];n=Array.prototype.slice.call(o.array);e.data.attributes[i]={itemSize:o.itemSize,type:o.array.constructor.name,array:n,normalized:o.normalized}}var s=this.groups;s.length>0&&(e.data.groups=JSON.parse(JSON.stringify(s)));var c=this.boundingSphere;return null!==c&&(e.data.boundingSphere={center:c.center.toArray(),radius:c.radius}),e},clone:function(){return(new Pe).copy(this)},copy:function(e){var t,i,r;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var n=e.index;null!==n&&this.setIndex(n.clone());var a=e.attributes;for(t in a){var o=a[t];this.addAttribute(t,o.clone())}var s=e.morphAttributes;for(t in s){var c=[],h=s[t];for(i=0,r=h.length;i0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}var a=void 0!==i.precision?i.precision:"highp",o=n(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);var s=!0===i.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),l=e.getParameter(e.MAX_TEXTURE_SIZE),u=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),d=e.getParameter(e.MAX_VERTEX_ATTRIBS),p=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),f=e.getParameter(e.MAX_VARYING_VECTORS),m=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),v=h>0,g=!!t.get("OES_texture_float");return{getMaxAnisotropy:function(){if(void 0!==r)return r;var i=t.get("EXT_texture_filter_anisotropic");return r=null!==i?e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:n,precision:a,logarithmicDepthBuffer:s,maxTextures:c,maxVertexTextures:h,maxTextureSize:l,maxCubemapSize:u,maxAttributes:d,maxVertexUniforms:p,maxVaryings:f,maxFragmentUniforms:m,vertexTextures:v,floatFragmentTextures:g,floatVertexTextures:v&&g}}function $e(){var e=this,t=null,i=0,r=!1,n=!1,a=new j,o=new P,s={value:null,needsUpdate:!1};function c(){s.value!==t&&(s.value=t,s.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,i,r,n){var c=null!==t?t.length:0,h=null;if(0!==c){if(h=s.value,!0!==n||null===h){var l=r+4*c,u=i.matrixWorldInverse;o.getNormalMatrix(u),(null===h||h.length65535?Ee:be)(o,1),t.update(r,e.ELEMENT_ARRAY_BUFFER),n[i.id]=r,r}}}function it(e,t,i){var r,n,a;this.setMode=function(e){r=e},this.setIndex=function(e){n=e.type,a=e.bytesPerElement},this.render=function(t,o){e.drawElements(r,o,n,t*a),i.update(o,r)},this.renderInstances=function(e,o,s){var c=t.get("ANGLE_instanced_arrays");null!==c?(c.drawElementsInstancedANGLE(r,s,n,o*a,e.maxInstancedCount),i.update(s,r,e.maxInstancedCount)):console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.")}}function rt(e){var t={frame:0,calls:0,triangles:0,points:0,lines:0};return{memory:{geometries:0,textures:0},render:t,programs:null,autoReset:!0,reset:function(){t.frame++,t.calls=0,t.triangles=0,t.points=0,t.lines=0},update:function(i,r,n){switch(n=n||1,t.calls++,r){case e.TRIANGLES:t.triangles+=n*(i/3);break;case e.TRIANGLE_STRIP:case e.TRIANGLE_FAN:t.triangles+=n*(i-2);break;case e.LINES:t.lines+=n*(i/2);break;case e.LINE_STRIP:t.lines+=n*(i-1);break;case e.LINE_LOOP:t.lines+=n*i;break;case e.POINTS:t.points+=n*i;break;default:console.error("THREE.WebGLInfo: Unknown draw mode:",r)}}}}function nt(e,t){return Math.abs(t[1])-Math.abs(e[1])}function at(e){var t={},i=new Float32Array(8);return{update:function(r,n,a,o){var s=r.morphTargetInfluences,c=s.length,h=t[n.id];if(void 0===h){h=[];for(var l=0;l0&&(i.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(i.morphTargets=!0),!0===this.skinning&&(i.skinning=!0),!1===this.visible&&(i.visible=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),t){var n=r(e.textures),a=r(e.images);n.length>0&&(i.textures=n),a.length>0&&(i.images=a)}return i},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.lights=e.lights,this.blending=e.blending,this.side=e.side,this.flatShading=e.flatShading,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.premultipliedAlpha=e.premultipliedAlpha,this.overdraw=e.overdraw,this.visible=e.visible,this.userData=JSON.parse(JSON.stringify(e.userData)),this.clipShadows=e.clipShadows,this.clipIntersection=e.clipIntersection;var t=e.clippingPlanes,i=null;if(null!==t){var r=t.length;i=new Array(r);for(var n=0;n!==r;++n)i[n]=t[n].clone()}return this.clippingPlanes=i,this.shadowSide=e.shadowSide,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),je.prototype=Object.create(ke.prototype),je.prototype.constructor=je,je.prototype.isMeshBasicMaterial=!0,je.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this},We.prototype=Object.create(ke.prototype),We.prototype.constructor=We,We.prototype.isShaderMaterial=!0,We.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.fragmentShader=e.fragmentShader,this.vertexShader=e.vertexShader,this.uniforms=q.clone(e.uniforms),this.defines=Object.assign({},e.defines),this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.lights=e.lights,this.clipping=e.clipping,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.morphNormals=e.morphNormals,this.extensions=e.extensions,this},We.prototype.toJSON=function(e){var t=ke.prototype.toJSON.call(this,e);return t.uniforms=this.uniforms,t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t},Object.assign(Xe.prototype,{set:function(e,t){return this.origin.copy(e),this.direction.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this},at:function(e,t){return void 0===t&&(console.warn("THREE.Ray: .at() target is now required"),t=new L),t.copy(this.direction).multiplyScalar(e).add(this.origin)},lookAt:function(e){return this.direction.copy(e).sub(this.origin).normalize(),this},recast:function(){var e=new L;return function(t){return this.origin.copy(this.at(t,e)),this}}(),closestPointToPoint:function(e,t){void 0===t&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),t=new L),t.subVectors(e,this.origin);var i=t.dot(this.direction);return i<0?t.copy(this.origin):t.copy(this.direction).multiplyScalar(i).add(this.origin)},distanceToPoint:function(e){return Math.sqrt(this.distanceSqToPoint(e))},distanceSqToPoint:function(){var e=new L;return function(t){var i=e.subVectors(t,this.origin).dot(this.direction);return i<0?this.origin.distanceToSquared(t):(e.copy(this.direction).multiplyScalar(i).add(this.origin),e.distanceToSquared(t))}}(),distanceSqToSegment:(Be=new L,Fe=new L,Ue=new L,function(e,t,i,r){Be.copy(e).add(t).multiplyScalar(.5),Fe.copy(t).sub(e).normalize(),Ue.copy(this.origin).sub(Be);var n,a,o,s,c=.5*e.distanceTo(t),h=-this.direction.dot(Fe),l=Ue.dot(this.direction),u=-Ue.dot(Fe),d=Ue.lengthSq(),p=Math.abs(1-h*h);if(p>0)if(a=h*l-u,s=c*p,(n=h*u-l)>=0)if(a>=-s)if(a<=s){var f=1/p;o=(n*=f)*(n+h*(a*=f)+2*l)+a*(h*n+a+2*u)+d}else a=c,o=-(n=Math.max(0,-(h*a+l)))*n+a*(a+2*u)+d;else a=-c,o=-(n=Math.max(0,-(h*a+l)))*n+a*(a+2*u)+d;else a<=-s?o=-(n=Math.max(0,-(-h*c+l)))*n+(a=n>0?-c:Math.min(Math.max(-c,-u),c))*(a+2*u)+d:a<=s?(n=0,o=(a=Math.min(Math.max(-c,-u),c))*(a+2*u)+d):o=-(n=Math.max(0,-(h*c+l)))*n+(a=n>0?c:Math.min(Math.max(-c,-u),c))*(a+2*u)+d;else a=h>0?-c:c,o=-(n=Math.max(0,-(h*a+l)))*n+a*(a+2*u)+d;return i&&i.copy(this.direction).multiplyScalar(n).add(this.origin),r&&r.copy(Fe).multiplyScalar(a).add(Be),o}),intersectSphere:function(){var e=new L;return function(t,i){e.subVectors(t.center,this.origin);var r=e.dot(this.direction),n=e.dot(e)-r*r,a=t.radius*t.radius;if(n>a)return null;var o=Math.sqrt(a-n),s=r-o,c=r+o;return s<0&&c<0?null:s<0?this.at(c,i):this.at(s,i)}}(),intersectsSphere:function(e){return this.distanceToPoint(e.center)<=e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null},intersectPlane:function(e,t){var i=this.distanceToPlane(e);return null===i?null:this.at(i,t)},intersectsPlane:function(e){var t=e.distanceToPoint(this.origin);return 0===t||e.normal.dot(this.direction)*t<0},intersectBox:function(e,t){var i,r,n,a,o,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(i=(e.min.x-u.x)*c,r=(e.max.x-u.x)*c):(i=(e.max.x-u.x)*c,r=(e.min.x-u.x)*c),h>=0?(n=(e.min.y-u.y)*h,a=(e.max.y-u.y)*h):(n=(e.max.y-u.y)*h,a=(e.min.y-u.y)*h),i>a||n>r?null:((n>i||i!=i)&&(i=n),(a=0?(o=(e.min.z-u.z)*l,s=(e.max.z-u.z)*l):(o=(e.max.z-u.z)*l,s=(e.min.z-u.z)*l),i>s||o>r?null:((o>i||i!=i)&&(i=o),(s=0?i:r,t)))},intersectsBox:(Ne=new L,function(e){return null!==this.intersectBox(e,Ne)}),intersectTriangle:function(){var e=new L,t=new L,i=new L,r=new L;return function(n,a,o,s,c){t.subVectors(a,n),i.subVectors(o,n),r.crossVectors(t,i);var h,l=this.direction.dot(r);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}e.subVectors(this.origin,n);var u=h*this.direction.dot(i.crossVectors(e,i));if(u<0)return null;var d=h*this.direction.dot(t.cross(e));if(d<0)return null;if(u+d>l)return null;var p=-h*e.dot(r);return p<0?null:this.at(p/l,c)}}(),applyMatrix4:function(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this},equals:function(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}}),Object.assign(Ye.prototype,{set:function(e,t){return this.start.copy(e),this.end.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.start.copy(e.start),this.end.copy(e.end),this},getCenter:function(e){return void 0===e&&(console.warn("THREE.Line3: .getCenter() target is now required"),e=new L),e.addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(e){return void 0===e&&(console.warn("THREE.Line3: .delta() target is now required"),e=new L),e.subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(e,t){return void 0===t&&(console.warn("THREE.Line3: .at() target is now required"),t=new L),this.delta(t).multiplyScalar(e).add(this.start)},closestPointToPointParameter:(ze=new L,Ge=new L,function(e,t){ze.subVectors(e,this.start),Ge.subVectors(this.end,this.start);var i=Ge.dot(Ge),r=Ge.dot(ze)/i;return t&&(r=M.clamp(r,0,1)),r}),closestPointToPoint:function(e,t,i){var r=this.closestPointToPointParameter(e,t);return void 0===i&&(console.warn("THREE.Line3: .closestPointToPoint() target is now required"),i=new L),this.delta(i).multiplyScalar(r).add(this.start)},applyMatrix4:function(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this},equals:function(e){return e.start.equals(this.start)&&e.end.equals(this.end)}}),Object.assign(qe,{getNormal:(Ve=new L,function(e,t,i,r){void 0===r&&(console.warn("THREE.Triangle: .getNormal() target is now required"),r=new L),r.subVectors(i,t),Ve.subVectors(e,t),r.cross(Ve);var n=r.lengthSq();return n>0?r.multiplyScalar(1/Math.sqrt(n)):r.set(0,0,0)}),getBarycoord:function(){var e=new L,t=new L,i=new L;return function(r,n,a,o,s){e.subVectors(o,n),t.subVectors(a,n),i.subVectors(r,n);var c=e.dot(e),h=e.dot(t),l=e.dot(i),u=t.dot(t),d=t.dot(i),p=c*u-h*h;if(void 0===s&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),s=new L),0===p)return s.set(-2,-1,-1);var f=1/p,m=(u*l-h*d)*f,v=(c*d-h*l)*f;return s.set(1-m-v,v,m)}}(),containsPoint:function(){var e=new L;return function(t,i,r,n){return qe.getBarycoord(t,i,r,n,e),e.x>=0&&e.y>=0&&e.x+e.y<=1}}()}),Object.assign(qe.prototype,{set:function(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this},setFromPointsAndIndices:function(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this},getArea:function(){var e=new L,t=new L;return function(){return e.subVectors(this.c,this.b),t.subVectors(this.a,this.b),.5*e.cross(t).length()}}(),getMidpoint:function(e){return void 0===e&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),e=new L),e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},getNormal:function(e){return qe.getNormal(this.a,this.b,this.c,e)},getPlane:function(e){return void 0===e&&(console.warn("THREE.Triangle: .getPlane() target is now required"),e=new L),e.setFromCoplanarPoints(this.a,this.b,this.c)},getBarycoord:function(e,t){return qe.getBarycoord(e,this.a,this.b,this.c,t)},containsPoint:function(e){return qe.containsPoint(e,this.a,this.b,this.c)},intersectsBox:function(e){return e.intersectsTriangle(this)},closestPointToPoint:function(){var e=new j,t=[new Ye,new Ye,new Ye],i=new L,r=new L;return function(n,a){void 0===a&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),a=new L);var o=1/0;if(e.setFromCoplanarPoints(this.a,this.b,this.c),e.projectPoint(n,i),!0===this.containsPoint(i))a.copy(i);else{t[0].set(this.a,this.b),t[1].set(this.b,this.c),t[2].set(this.c,this.a);for(var s=0;s0){var o=n[a[0]];if(void 0!==o)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=o.length;e0)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=s.length;ei.far?null:{distance:c,point:f.clone(),object:e}}function g(e,t,i,o,s,c,d,f){r.fromBufferAttribute(o,c),n.fromBufferAttribute(o,d),a.fromBufferAttribute(o,f);var g=v(e,e.material,t,i,r,n,a,p);if(g){s&&(h.fromBufferAttribute(s,c),l.fromBufferAttribute(s,d),u.fromBufferAttribute(s,f),g.uv=m(p,r,n,a,h,l,u));var y=new de(c,d,f);qe.getNormal(r,n,a,y.normal),g.face=y}return g}return function(d,f){var y,A=this.geometry,x=this.material,w=this.matrixWorld;if(void 0!==x&&(null===A.boundingSphere&&A.computeBoundingSphere(),i.copy(A.boundingSphere),i.applyMatrix4(w),!1!==d.ray.intersectsSphere(i)&&(e.getInverse(w),t.copy(d.ray).applyMatrix4(e),null===A.boundingBox||!1!==t.intersectsBox(A.boundingBox))))if(A.isBufferGeometry){var b,_,E,M,T,S=A.index,R=A.attributes.position,L=A.attributes.uv;if(null!==S)for(M=0,T=S.count;M0&&(I=F);for(var U=0,z=B.length;U0)return e;var n=t*i,a=ut[n];if(void 0===a&&(a=new Float32Array(n),ut[n]=a),0!==t){r.toArray(a,0);for(var o=1,s=0;o!==t;++o)s+=i,e[o].toArray(a,s)}return a}function gt(e,t){if(e.length!==t.length)return!1;for(var i=0,r=e.length;i/gm,(function(e,t){var i=Y[t];if(void 0===i)throw new Error("Can not resolve #include <"+t+">");return ni(i)}))}function ai(e){return e.replace(/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,(function(e,t,i,r){for(var n="",a=parseInt(t);a0?e.gammaFactor:1,x=function(e,t,i){return[(e=e||{}).derivatives||t.envMapCubeUV||t.bumpMap||t.normalMap||t.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(e.fragDepth||t.logarithmicDepthBuffer)&&i.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",e.drawBuffers&&i.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(e.shaderTextureLOD||t.envMap)&&i.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(ti).join("\n")}(r.extensions,a,t),w=function(e){var t=[];for(var i in e){var r=e[i];!1!==r&&t.push("#define "+i+" "+r)}return t.join("\n")}(s),b=o.createProgram();r.isRawShaderMaterial?((f=[w].filter(ti).join("\n")).length>0&&(f+="\n"),(m=[x,w].filter(ti).join("\n")).length>0&&(m+="\n")):(f=["precision "+a.precision+" float;","precision "+a.precision+" int;","#define SHADER_NAME "+n.name,w,a.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+A,"#define MAX_BONES "+a.maxBones,a.useFog&&a.fog?"#define USE_FOG":"",a.useFog&&a.fogExp?"#define FOG_EXP2":"",a.map?"#define USE_MAP":"",a.envMap?"#define USE_ENVMAP":"",a.envMap?"#define "+d:"",a.lightMap?"#define USE_LIGHTMAP":"",a.aoMap?"#define USE_AOMAP":"",a.emissiveMap?"#define USE_EMISSIVEMAP":"",a.bumpMap?"#define USE_BUMPMAP":"",a.normalMap?"#define USE_NORMALMAP":"",a.displacementMap&&a.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",a.specularMap?"#define USE_SPECULARMAP":"",a.roughnessMap?"#define USE_ROUGHNESSMAP":"",a.metalnessMap?"#define USE_METALNESSMAP":"",a.alphaMap?"#define USE_ALPHAMAP":"",a.vertexColors?"#define USE_COLOR":"",a.flatShading?"#define FLAT_SHADED":"",a.skinning?"#define USE_SKINNING":"",a.useVertexTexture?"#define BONE_TEXTURE":"",a.morphTargets?"#define USE_MORPHTARGETS":"",a.morphNormals&&!1===a.flatShading?"#define USE_MORPHNORMALS":"",a.doubleSided?"#define DOUBLE_SIDED":"",a.flipSided?"#define FLIP_SIDED":"",a.shadowMapEnabled?"#define USE_SHADOWMAP":"",a.shadowMapEnabled?"#define "+l:"",a.sizeAttenuation?"#define USE_SIZEATTENUATION":"",a.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",a.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(ti).join("\n"),m=[x,"precision "+a.precision+" float;","precision "+a.precision+" int;","#define SHADER_NAME "+n.name,w,a.alphaTest?"#define ALPHATEST "+a.alphaTest+(a.alphaTest%1?"":".0"):"","#define GAMMA_FACTOR "+A,a.useFog&&a.fog?"#define USE_FOG":"",a.useFog&&a.fogExp?"#define FOG_EXP2":"",a.map?"#define USE_MAP":"",a.envMap?"#define USE_ENVMAP":"",a.envMap?"#define "+u:"",a.envMap?"#define "+d:"",a.envMap?"#define "+p:"",a.lightMap?"#define USE_LIGHTMAP":"",a.aoMap?"#define USE_AOMAP":"",a.emissiveMap?"#define USE_EMISSIVEMAP":"",a.bumpMap?"#define USE_BUMPMAP":"",a.normalMap?"#define USE_NORMALMAP":"",a.specularMap?"#define USE_SPECULARMAP":"",a.roughnessMap?"#define USE_ROUGHNESSMAP":"",a.metalnessMap?"#define USE_METALNESSMAP":"",a.alphaMap?"#define USE_ALPHAMAP":"",a.vertexColors?"#define USE_COLOR":"",a.gradientMap?"#define USE_GRADIENTMAP":"",a.flatShading?"#define FLAT_SHADED":"",a.doubleSided?"#define DOUBLE_SIDED":"",a.flipSided?"#define FLIP_SIDED":"",a.shadowMapEnabled?"#define USE_SHADOWMAP":"",a.shadowMapEnabled?"#define "+l:"",a.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",a.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",a.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",a.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"",a.envMap&&t.get("EXT_shader_texture_lod")?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",0!==a.toneMapping?"#define TONE_MAPPING":"",0!==a.toneMapping?Y.tonemapping_pars_fragment:"",0!==a.toneMapping?ei("toneMapping",a.toneMapping):"",a.dithering?"#define DITHERING":"",a.outputEncoding||a.mapEncoding||a.envMapEncoding||a.emissiveMapEncoding?Y.encodings_pars_fragment:"",a.mapEncoding?$t("mapTexelToLinear",a.mapEncoding):"",a.envMapEncoding?$t("envMapTexelToLinear",a.envMapEncoding):"",a.emissiveMapEncoding?$t("emissiveMapTexelToLinear",a.emissiveMapEncoding):"",a.outputEncoding?(v="linearToOutputTexel",g=a.outputEncoding,y=Kt(g),"vec4 "+v+"( vec4 value ) { return LinearTo"+y[0]+y[1]+"; }"):"",a.depthPacking?"#define DEPTH_PACKING "+r.depthPacking:"","\n"].filter(ti).join("\n")),c=ri(c=ii(c=ni(c),a),a),h=ri(h=ii(h=ni(h),a),a);var _=f+(c=ai(c)),E=m+(h=ai(h)),M=Zt(o,o.VERTEX_SHADER,_),T=Zt(o,o.FRAGMENT_SHADER,E);o.attachShader(b,M),o.attachShader(b,T),void 0!==r.index0AttributeName?o.bindAttribLocation(b,0,r.index0AttributeName):!0===a.morphTargets&&o.bindAttribLocation(b,0,"position"),o.linkProgram(b);var S,R,L=o.getProgramInfoLog(b).trim(),P=o.getShaderInfoLog(M).trim(),C=o.getShaderInfoLog(T).trim(),D=!0,I=!0;return!1===o.getProgramParameter(b,o.LINK_STATUS)?(D=!1,console.error("THREE.WebGLProgram: shader error: ",o.getError(),"gl.VALIDATE_STATUS",o.getProgramParameter(b,o.VALIDATE_STATUS),"gl.getProgramInfoLog",L,P,C)):""!==L?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",L):""!==P&&""!==C||(I=!1),I&&(this.diagnostics={runnable:D,material:r,programLog:L,vertexShader:{log:P,prefix:f},fragmentShader:{log:C,prefix:m}}),o.deleteShader(M),o.deleteShader(T),this.getUniforms=function(){return void 0===S&&(S=new Qt(o,b,e)),S},this.getAttributes=function(){return void 0===R&&(R=function(e,t){for(var i={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;n0,maxBones:d,useVertexTexture:i.floatVertexTextures,morphTargets:t.morphTargets,morphNormals:t.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:r.directional.length,numPointLights:r.point.length,numSpotLights:r.spot.length,numRectAreaLights:r.rectArea.length,numHemiLights:r.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:t.dithering,shadowMapEnabled:e.shadowMap.enabled&&l.receiveShadow&&a.length>0,shadowMapType:e.shadowMap.type,toneMapping:e.toneMapping,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:t.premultipliedAlpha,alphaTest:t.alphaTest,doubleSided:2===t.side,flipSided:1===t.side,depthPacking:void 0!==t.depthPacking&&t.depthPacking}},this.getProgramCode=function(t,i){var r=[];if(i.shaderID?r.push(i.shaderID):(r.push(t.fragmentShader),r.push(t.vertexShader)),void 0!==t.defines)for(var n in t.defines)r.push(n),r.push(t.defines[n]);for(var o=0;o1&&i.sort(hi),r.length>1&&r.sort(li)}}}function di(){var e={};return{get:function(t,i){var r=t.id+","+i.id,n=e[r];return void 0===n&&(n=new ui,e[r]=n),n},dispose:function(){e={}}}}function pi(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var i;switch(t.type){case"DirectionalLight":i={direction:new L,color:new Z,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new T};break;case"SpotLight":i={position:new L,direction:new L,color:new Z,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new T};break;case"PointLight":i={position:new L,color:new Z,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new T,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":i={direction:new L,skyColor:new Z,groundColor:new Z};break;case"RectAreaLight":i={color:new Z,position:new L,halfWidth:new L,halfHeight:new L}}return e[t.id]=i,i}}}var fi,mi,vi,gi,yi,Ai,xi,wi,bi=0;function _i(){var e=new pi,t={id:bi++,hash:"",ambient:[0,0,0],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},i=new L,r=new S,n=new S;return{setup:function(a,o,s){for(var c=0,h=0,l=0,u=0,d=0,p=0,f=0,m=0,v=s.matrixWorldInverse,g=0,y=a.length;g0:s&&s.isGeometry&&(m=s.morphTargets&&s.morphTargets.length>0)),t.isSkinnedMesh&&!1===i.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t);var v=0;m&&(v|=1),t.isSkinnedMesh&&i.skinning&&(v|=2),c=p[v]}if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var g=c.uuid,y=i.uuid,A=u[g];void 0===A&&(A={},u[g]=A);var x=A[y];void 0===x&&(x=c.clone(),A[y]=x),c=x}return c.visible=i.visible,c.wireframe=i.wireframe,c.side=null!=i.shadowSide?i.shadowSide:d[i.side],c.clipShadows=i.clipShadows,c.clippingPlanes=i.clippingPlanes,c.clipIntersection=i.clipIntersection,c.wireframeLinewidth=i.wireframeLinewidth,c.linewidth=i.linewidth,r&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(n),c.nearDistance=a,c.farDistance=o),c}function _(i,n,a,o){if(!1!==i.visible){if(i.layers.test(n.layers)&&(i.isMesh||i.isLine||i.isPoints)&&i.castShadow&&(!i.frustumCulled||r.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,i.matrixWorld);var s=t.update(i),h=i.material;if(Array.isArray(h))for(var l=s.groups,u=0,d=l.length;u 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),t.compileShader(i),t.compileShader(r),t.attachShader(e,i),t.attachShader(e,r),t.linkProgram(e),e}(),c={position:t.getAttribLocation(s,"position"),uv:t.getAttribLocation(s,"uv")},h={uvOffset:t.getUniformLocation(s,"uvOffset"),uvScale:t.getUniformLocation(s,"uvScale"),rotation:t.getUniformLocation(s,"rotation"),center:t.getUniformLocation(s,"center"),scale:t.getUniformLocation(s,"scale"),color:t.getUniformLocation(s,"color"),map:t.getUniformLocation(s,"map"),opacity:t.getUniformLocation(s,"opacity"),modelViewMatrix:t.getUniformLocation(s,"modelViewMatrix"),projectionMatrix:t.getUniformLocation(s,"projectionMatrix"),fogType:t.getUniformLocation(s,"fogType"),fogDensity:t.getUniformLocation(s,"fogDensity"),fogNear:t.getUniformLocation(s,"fogNear"),fogFar:t.getUniformLocation(s,"fogFar"),fogColor:t.getUniformLocation(s,"fogColor"),fogDepth:t.getUniformLocation(s,"fogDepth"),alphaTest:t.getUniformLocation(s,"alphaTest")};var r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");r.width=8,r.height=8;var u=r.getContext("2d");u.fillStyle="white",u.fillRect(0,0,8,8),l=new Li(r)}function m(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(n,v,g){if(0!==n.length){void 0===s&&f(),i.useProgram(s),i.initAttributes(),i.enableAttribute(c.position),i.enableAttribute(c.uv),i.disableUnusedAttributes(),i.disable(t.CULL_FACE),i.enable(t.BLEND),t.bindBuffer(t.ARRAY_BUFFER,a),t.vertexAttribPointer(c.position,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(c.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,o),t.uniformMatrix4fv(h.projectionMatrix,!1,g.projectionMatrix.elements),i.activeTexture(t.TEXTURE0),t.uniform1i(h.map,0);var y=0,A=0,x=v.fog;x?(t.uniform3f(h.fogColor,x.color.r,x.color.g,x.color.b),x.isFog?(t.uniform1f(h.fogNear,x.near),t.uniform1f(h.fogFar,x.far),t.uniform1i(h.fogType,1),y=1,A=1):x.isFogExp2&&(t.uniform1f(h.fogDensity,x.density),t.uniform1i(h.fogType,2),y=2,A=2)):(t.uniform1i(h.fogType,0),y=0,A=0);for(var w=0,b=n.length;w=1):-1!==L.indexOf("OpenGL ES")&&(R=parseFloat(/^OpenGL\ ES\ ([0-9])/.exec(L)[1]),S=R>=2);var P=null,C={},D=new U,I=new U;function O(t,i,r){var n=new Uint8Array(4),a=e.createTexture();e.bindTexture(t,a),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(var o=0;ot||e.height>t){if("data"in e)return void console.warn("THREE.WebGLRenderer: image in DataTexture is too big ("+e.width+"x"+e.height+").");var i=t/Math.max(e.width,e.height),r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return r.width=Math.floor(e.width*i),r.height=Math.floor(e.height*i),r.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,r.width,r.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+r.width+"x"+r.height,e),r}return e}function u(e){return M.isPowerOfTwo(e.width)&&M.isPowerOfTwo(e.height)}function d(e,t){return e.generateMipmaps&&t&&1003!==e.minFilter&&1006!==e.minFilter}function p(t,i,n,a){e.generateMipmap(t),r.get(i).__maxMipLevel=Math.log(Math.max(n,a))*Math.LOG2E}function f(t){return 1003===t||1004===t||1005===t?e.NEAREST:e.LINEAR}function m(t){var i=t.target;i.removeEventListener("dispose",m),function(t){var i=r.get(t);if(t.image&&i.__image__webglTextureCube)e.deleteTexture(i.__image__webglTextureCube);else{if(void 0===i.__webglInit)return;e.deleteTexture(i.__webglTexture)}r.remove(t)}(i),i.isVideoTexture&&delete h[i.id],o.memory.textures--}function v(t){var i=t.target;i.removeEventListener("dispose",v),function(t){var i=r.get(t),n=r.get(t.texture);if(!t)return;void 0!==n.__webglTexture&&e.deleteTexture(n.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLRenderTargetCube)for(var a=0;a<6;a++)e.deleteFramebuffer(i.__webglFramebuffer[a]),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer[a]);else e.deleteFramebuffer(i.__webglFramebuffer),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer);r.remove(t.texture),r.remove(t)}(i),o.memory.textures--}function g(t,f){var v=r.get(t);if(t.isVideoTexture&&function(e){var t=e.id,i=o.render.frame;h[t]!==i&&(h[t]=i,e.update())}(t),t.version>0&&v.__version!==t.version){var g=t.image;if(void 0===g)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined",t);else{if(!1!==g.complete)return void function(t,r,h){void 0===t.__webglInit&&(t.__webglInit=!0,r.addEventListener("dispose",m),t.__webglTexture=e.createTexture(),o.memory.textures++);i.activeTexture(e.TEXTURE0+h),i.bindTexture(e.TEXTURE_2D,t.__webglTexture),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,r.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,r.unpackAlignment);var f=l(r.image,n.maxTextureSize);(function(e){return 1001!==e.wrapS||1001!==e.wrapT||1003!==e.minFilter&&1006!==e.minFilter})(r)&&!1===u(f)&&(f=function(e){return e instanceof HTMLImageElement||e instanceof HTMLCanvasElement||e instanceof ImageBitmap?(void 0===s&&(s=document.createElementNS("http://www.w3.org/1999/xhtml","canvas")),s.width=M.floorPowerOfTwo(e.width),s.height=M.floorPowerOfTwo(e.height),s.getContext("2d").drawImage(e,0,0,s.width,s.height),console.warn("THREE.WebGLRenderer: image is not power of two ("+e.width+"x"+e.height+"). Resized to "+s.width+"x"+s.height,e),s):e}(f));var v=u(f),g=a.convert(r.format),A=a.convert(r.type);y(e.TEXTURE_2D,r,v);var x,w=r.mipmaps;if(r.isDepthTexture){var b=e.DEPTH_COMPONENT;if(1015===r.type){if(!c)throw new Error("Float Depth Texture only supported in WebGL2.0");b=e.DEPTH_COMPONENT32F}else c&&(b=e.DEPTH_COMPONENT16);1026===r.format&&b===e.DEPTH_COMPONENT&&1012!==r.type&&1014!==r.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=1012,A=a.convert(r.type)),1027===r.format&&(b=e.DEPTH_STENCIL,1020!==r.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=1020,A=a.convert(r.type))),i.texImage2D(e.TEXTURE_2D,0,b,f.width,f.height,0,g,A,null)}else if(r.isDataTexture)if(w.length>0&&v){for(var _=0,E=w.length;_-1?i.compressedTexImage2D(e.TEXTURE_2D,_,g,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):i.texImage2D(e.TEXTURE_2D,_,g,x.width,x.height,0,g,A,x.data);t.__maxMipLevel=w.length-1}else if(w.length>0&&v){for(_=0,E=w.length;_1||r.get(o).__currentAnisotropy)&&(e.texParameterf(i,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(o.anisotropy,n.getMaxAnisotropy())),r.get(o).__currentAnisotropy=o.anisotropy)}}function A(t,n,o,s){var c=a.convert(n.texture.format),h=a.convert(n.texture.type);i.texImage2D(s,0,c,n.width,n.height,0,c,h,null),e.bindFramebuffer(e.FRAMEBUFFER,t),e.framebufferTexture2D(e.FRAMEBUFFER,o,s,r.get(n.texture).__webglTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}function x(t,i){e.bindRenderbuffer(e.RENDERBUFFER,t),i.depthBuffer&&!i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t)):i.depthBuffer&&i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t)):e.renderbufferStorage(e.RENDERBUFFER,e.RGBA4,i.width,i.height),e.bindRenderbuffer(e.RENDERBUFFER,null)}function w(t){var i=r.get(t),n=!0===t.isWebGLRenderTargetCube;if(t.depthTexture){if(n)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,i){if(i&&i.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(e.bindFramebuffer(e.FRAMEBUFFER,t),!i.depthTexture||!i.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");r.get(i.depthTexture).__webglTexture&&i.depthTexture.image.width===i.width&&i.depthTexture.image.height===i.height||(i.depthTexture.image.width=i.width,i.depthTexture.image.height=i.height,i.depthTexture.needsUpdate=!0),g(i.depthTexture,0);var n=r.get(i.depthTexture).__webglTexture;if(1026===i.depthTexture.format)e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,n,0);else{if(1027!==i.depthTexture.format)throw new Error("Unknown depthTexture format");e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,n,0)}}(i.__webglFramebuffer,t)}else if(n){i.__webglDepthbuffer=[];for(var a=0;a<6;a++)e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[a]),i.__webglDepthbuffer[a]=e.createRenderbuffer(),x(i.__webglDepthbuffer[a],t)}else e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer=e.createRenderbuffer(),x(i.__webglDepthbuffer,t);e.bindFramebuffer(e.FRAMEBUFFER,null)}this.setTexture2D=g,this.setTextureCube=function(t,s){var c=r.get(t);if(6===t.image.length)if(t.version>0&&c.__version!==t.version){c.__image__webglTextureCube||(t.addEventListener("dispose",m),c.__image__webglTextureCube=e.createTexture(),o.memory.textures++),i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,t.flipY);for(var h=t&&t.isCompressedTexture,f=t.image[0]&&t.image[0].isDataTexture,v=[],g=0;g<6;g++)v[g]=h||f?f?t.image[g].image:t.image[g]:l(t.image[g],n.maxCubemapSize);var A=v[0],x=u(A),w=a.convert(t.format),b=a.convert(t.type);y(e.TEXTURE_CUBE_MAP,t,x);for(g=0;g<6;g++)if(h)for(var _,E=v[g].mipmaps,M=0,T=E.length;M-1?i.compressedTexImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,w,_.width,_.height,0,_.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,w,_.width,_.height,0,w,b,_.data);else f?i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,w,v[g].width,v[g].height,0,w,b,v[g].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,w,w,b,v[g]);c.__maxMipLevel=h?E.length-1:0,d(t,x)&&p(e.TEXTURE_CUBE_MAP,t,A.width,A.height),c.__version=t.version,t.onUpdate&&t.onUpdate(t)}else i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube)},this.setTextureCubeDynamic=function(t,n){i.activeTexture(e.TEXTURE0+n),i.bindTexture(e.TEXTURE_CUBE_MAP,r.get(t).__webglTexture)},this.setupRenderTarget=function(t){var n=r.get(t),a=r.get(t.texture);t.addEventListener("dispose",v),a.__webglTexture=e.createTexture(),o.memory.textures++;var s=!0===t.isWebGLRenderTargetCube,c=u(t);if(s){n.__webglFramebuffer=[];for(var h=0;h<6;h++)n.__webglFramebuffer[h]=e.createFramebuffer()}else n.__webglFramebuffer=e.createFramebuffer();if(s){i.bindTexture(e.TEXTURE_CUBE_MAP,a.__webglTexture),y(e.TEXTURE_CUBE_MAP,t.texture,c);for(h=0;h<6;h++)A(n.__webglFramebuffer[h],t,e.COLOR_ATTACHMENT0,e.TEXTURE_CUBE_MAP_POSITIVE_X+h);d(t.texture,c)&&p(e.TEXTURE_CUBE_MAP,t.texture,t.width,t.height),i.bindTexture(e.TEXTURE_CUBE_MAP,null)}else i.bindTexture(e.TEXTURE_2D,a.__webglTexture),y(e.TEXTURE_2D,t.texture,c),A(n.__webglFramebuffer,t,e.COLOR_ATTACHMENT0,e.TEXTURE_2D),d(t.texture,c)&&p(e.TEXTURE_2D,t.texture,t.width,t.height),i.bindTexture(e.TEXTURE_2D,null);t.depthBuffer&&w(t)},this.updateRenderTargetMipmap=function(t){var n=t.texture;if(d(n,u(t))){var a=t.isWebGLRenderTargetCube?e.TEXTURE_CUBE_MAP:e.TEXTURE_2D,o=r.get(n).__webglTexture;i.bindTexture(a,o),p(a,n,t.width,t.height),i.bindTexture(a,null)}}}function Ii(e,t){return{convert:function(i){var r;if(1e3===i)return e.REPEAT;if(1001===i)return e.CLAMP_TO_EDGE;if(1002===i)return e.MIRRORED_REPEAT;if(1003===i)return e.NEAREST;if(1004===i)return e.NEAREST_MIPMAP_NEAREST;if(1005===i)return e.NEAREST_MIPMAP_LINEAR;if(1006===i)return e.LINEAR;if(1007===i)return e.LINEAR_MIPMAP_NEAREST;if(1008===i)return e.LINEAR_MIPMAP_LINEAR;if(1009===i)return e.UNSIGNED_BYTE;if(1017===i)return e.UNSIGNED_SHORT_4_4_4_4;if(1018===i)return e.UNSIGNED_SHORT_5_5_5_1;if(1019===i)return e.UNSIGNED_SHORT_5_6_5;if(1010===i)return e.BYTE;if(1011===i)return e.SHORT;if(1012===i)return e.UNSIGNED_SHORT;if(1013===i)return e.INT;if(1014===i)return e.UNSIGNED_INT;if(1015===i)return e.FLOAT;if(1016===i&&null!==(r=t.get("OES_texture_half_float")))return r.HALF_FLOAT_OES;if(1021===i)return e.ALPHA;if(1022===i)return e.RGB;if(1023===i)return e.RGBA;if(1024===i)return e.LUMINANCE;if(1025===i)return e.LUMINANCE_ALPHA;if(1026===i)return e.DEPTH_COMPONENT;if(1027===i)return e.DEPTH_STENCIL;if(100===i)return e.FUNC_ADD;if(101===i)return e.FUNC_SUBTRACT;if(102===i)return e.FUNC_REVERSE_SUBTRACT;if(200===i)return e.ZERO;if(201===i)return e.ONE;if(202===i)return e.SRC_COLOR;if(203===i)return e.ONE_MINUS_SRC_COLOR;if(204===i)return e.SRC_ALPHA;if(205===i)return e.ONE_MINUS_SRC_ALPHA;if(206===i)return e.DST_ALPHA;if(207===i)return e.ONE_MINUS_DST_ALPHA;if(208===i)return e.DST_COLOR;if(209===i)return e.ONE_MINUS_DST_COLOR;if(210===i)return e.SRC_ALPHA_SATURATE;if((33776===i||33777===i||33778===i||33779===i)&&null!==(r=t.get("WEBGL_compressed_texture_s3tc"))){if(33776===i)return r.COMPRESSED_RGB_S3TC_DXT1_EXT;if(33777===i)return r.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(33778===i)return r.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(33779===i)return r.COMPRESSED_RGBA_S3TC_DXT5_EXT}if((35840===i||35841===i||35842===i||35843===i)&&null!==(r=t.get("WEBGL_compressed_texture_pvrtc"))){if(35840===i)return r.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(35841===i)return r.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(35842===i)return r.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(35843===i)return r.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(36196===i&&null!==(r=t.get("WEBGL_compressed_texture_etc1")))return r.COMPRESSED_RGB_ETC1_WEBGL;if((37808===i||37809===i||37810===i||37811===i||37812===i||37813===i||37814===i||37815===i||37816===i||37817===i||37818===i||37819===i||37820===i||37821===i)&&null!==(r=t.get("WEBGL_compressed_texture_astc")))return i;if((103===i||104===i)&&null!==(r=t.get("EXT_blend_minmax"))){if(103===i)return r.MIN_EXT;if(104===i)return r.MAX_EXT}return 1020===i&&null!==(r=t.get("WEBGL_depth_texture"))?r.UNSIGNED_INT_24_8_WEBGL:0}}}function Oi(e,t,i,r){le.call(this),this.type="PerspectiveCamera",this.fov=void 0!==e?e:50,this.zoom=1,this.near=void 0!==i?i:.1,this.far=void 0!==r?r:2e3,this.focus=10,this.aspect=void 0!==t?t:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Ni(e){Oi.call(this),this.cameras=e||[]}function Bi(e){var t=this,i=null,r=null,n=null,a=new S,o=new S;"undefined"!=typeof window&&"VRFrameData"in window&&(r=new window.VRFrameData,window.addEventListener("vrdisplaypresentchange",v,!1));var s=new S,c=new R,h=new L,l=new Oi;l.bounds=new U(0,0,.5,1),l.layers.enable(1);var u=new Oi;u.bounds=new U(.5,0,.5,1),u.layers.enable(2);var d,p,f=new Ni([l,u]);function m(){return null!==i&&!0===i.isPresenting}function v(){if(m()){var r=i.getEyeParameters("left"),n=r.renderWidth,a=r.renderHeight;p=e.getPixelRatio(),d=e.getSize(),e.setDrawingBufferSize(2*n,a,1),g.start()}else t.enabled&&(e.setDrawingBufferSize(d.width,d.height,p),g.stop())}f.layers.enable(1),f.layers.enable(2),this.enabled=!1,this.userHeight=1.6,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e),g.setContext(e)},this.setPoseTarget=function(e){void 0!==e&&(n=e)},this.getCamera=function(e){if(null===i)return e;i.depthNear=e.near,i.depthFar=e.far,i.getFrameData(r);var d=i.stageParameters;d?a.fromArray(d.sittingToStandingTransform):a.makeTranslation(0,t.userHeight,0);var p=r.pose,m=null!==n?n:e;if(m.matrix.copy(a),m.matrix.decompose(m.position,m.quaternion,m.scale),null!==p.orientation&&(c.fromArray(p.orientation),m.quaternion.multiply(c)),null!==p.position&&(c.setFromRotationMatrix(a),h.fromArray(p.position),h.applyQuaternion(c),m.position.add(h)),m.updateMatrixWorld(),!1===i.isPresenting)return e;l.near=e.near,u.near=e.near,l.far=e.far,u.far=e.far,f.matrixWorld.copy(e.matrixWorld),f.matrixWorldInverse.copy(e.matrixWorldInverse),l.matrixWorldInverse.fromArray(r.leftViewMatrix),u.matrixWorldInverse.fromArray(r.rightViewMatrix),o.getInverse(a),l.matrixWorldInverse.multiply(o),u.matrixWorldInverse.multiply(o);var v=m.parent;null!==v&&(s.getInverse(v.matrixWorld),l.matrixWorldInverse.multiply(s),u.matrixWorldInverse.multiply(s)),l.matrixWorld.getInverse(l.matrixWorldInverse),u.matrixWorld.getInverse(u.matrixWorldInverse),l.projectionMatrix.fromArray(r.leftProjectionMatrix),u.projectionMatrix.fromArray(r.rightProjectionMatrix),f.projectionMatrix.copy(l.projectionMatrix);var g=i.getLayers();if(g.length){var y=g[0];null!==y.leftBounds&&4===y.leftBounds.length&&l.bounds.fromArray(y.leftBounds),null!==y.rightBounds&&4===y.rightBounds.length&&u.bounds.fromArray(y.rightBounds)}return f},this.getStandingMatrix=function(){return a},this.isPresenting=m;var g=new ee;this.setAnimationLoop=function(e){g.setAnimationLoop(e)},this.submitFrame=function(){m()&&i.submitFrame()},this.dispose=function(){"undefined"!=typeof window&&window.removeEventListener("vrdisplaypresentchange",v)}}function Fi(e){var t=e.context,i=null,r=null,n=null,a=null;function o(){return null!==r&&null!==n}var s=new Oi;s.layers.enable(1),s.viewport=new U;var c=new Oi;c.layers.enable(2),c.viewport=new U;var h=new Ni([s,c]);function l(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.getInverse(e.matrixWorld)}h.layers.enable(1),h.layers.enable(2),this.enabled=!1,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e),t.setCompatibleXRDevice(e)},this.setSession=function(i,a){null!==(r=i)&&(r.addEventListener("end",(function(){e.setFramebuffer(null),d.stop()})),r.baseLayer=new XRWebGLLayer(r,t),r.requestFrameOfReference(a.frameOfReferenceType).then((function(t){n=t,e.setFramebuffer(r.baseLayer.framebuffer),d.setContext(r),d.start()})))},this.getCamera=function(e){if(o()){var t=e.parent,i=h.cameras;l(h,t);for(var r=0;r=0){var c=r[o];if(void 0!==c){var h=c.normalized,l=c.itemSize,u=A.get(c);if(void 0===u)continue;var f=u.buffer,v=u.type,g=u.bytesPerElement;if(c.isInterleavedBufferAttribute){var y=c.data,x=y.stride,w=c.offset;y&&y.isInstancedInterleavedBuffer?(m.enableAttributeAndDivisor(s,y.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=y.meshPerAttribute*y.count)):m.enableAttribute(s),d.bindBuffer(d.ARRAY_BUFFER,f),d.vertexAttribPointer(s,l,v,h,x*g,w*g)}else c.isInstancedBufferAttribute?(m.enableAttributeAndDivisor(s,c.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=c.meshPerAttribute*c.count)):m.enableAttribute(s),d.bindBuffer(d.ARRAY_BUFFER,f),d.vertexAttribPointer(s,l,v,h,0,0)}else if(void 0!==a){var b=a[o];if(void 0!==b)switch(b.length){case 2:d.vertexAttrib2fv(s,b);break;case 3:d.vertexAttrib3fv(s,b);break;case 4:d.vertexAttrib4fv(s,b);break;default:d.vertexAttrib1fv(s,b)}}}}m.disableUnusedAttributes()}(r,s,i),null!==u&&d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,l.buffer));var y=1/0;null!==u?y=u.count:void 0!==f&&(y=f.count);var w=i.drawRange.start*v,b=i.drawRange.count*v,_=null!==a?a.start*v:0,E=null!==a?a.count*v:1/0,M=Math.max(w,_),T=Math.min(y,w+b,_+E)-1,S=Math.max(0,T-M+1);if(0!==S){if(n.isMesh)if(!0===r.wireframe)m.setLineWidth(r.wireframeLinewidth*pe()),g.setMode(d.LINES);else switch(n.drawMode){case 0:g.setMode(d.TRIANGLES);break;case 1:g.setMode(d.TRIANGLE_STRIP);break;case 2:g.setMode(d.TRIANGLE_FAN)}else if(n.isLine){var L=r.linewidth;void 0===L&&(L=1),m.setLineWidth(L*pe()),n.isLineSegments?g.setMode(d.LINES):n.isLineLoop?g.setMode(d.LINE_LOOP):g.setMode(d.LINE_STRIP)}else n.isPoints&&g.setMode(d.POINTS);i&&i.isInstancedBufferGeometry?i.maxInstancedCount>0&&g.renderInstances(i,M,S):g.render(M,S)}},this.compile=function(e,t){(u=E.get(e,t)).init(),e.traverse((function(e){e.isLight&&(u.pushLight(e),e.castShadow&&u.pushShadow(e))})),u.setupLights(t),e.traverse((function(t){if(t.material)if(Array.isArray(t.material))for(var i=0;i=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(p=0;p=0&&e.numSupportedMorphNormals++}var f=r.shader.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(r.numClippingPlanes=ce.numPlanes,r.numIntersection=ce.numIntersection,f.clippingPlanes=ce.uniform),r.fog=t,r.lightsHash=n.state.hash,e.lights&&(f.ambientLightColor.value=n.state.ambient,f.directionalLights.value=n.state.directional,f.spotLights.value=n.state.spot,f.rectAreaLights.value=n.state.rectArea,f.pointLights.value=n.state.point,f.hemisphereLights.value=n.state.hemi,f.directionalShadowMap.value=n.state.directionalShadowMap,f.directionalShadowMatrix.value=n.state.directionalShadowMatrix,f.spotShadowMap.value=n.state.spotShadowMap,f.spotShadowMatrix.value=n.state.spotShadowMatrix,f.pointShadowMap.value=n.state.pointShadowMap,f.pointShadowMatrix.value=n.state.pointShadowMatrix);var m=r.program.getUniforms(),v=Qt.seqWithValue(m.seq,f);r.uniformsList=v}function Re(e,t,i,r){Z=0;var n=g.get(i),a=u.state.lights;if(he&&(le||e!==k)){var o=e===k&&i.id===G;ce.setState(i.clippingPlanes,i.clipIntersection,i.clipShadows,e,n,o)}!1===i.needsUpdate&&(void 0===n.program||i.fog&&n.fog!==t||i.lights&&n.lightsHash!==a.state.hash?i.needsUpdate=!0:void 0===n.numClippingPlanes||n.numClippingPlanes===ce.numPlanes&&n.numIntersection===ce.numIntersection||(i.needsUpdate=!0)),i.needsUpdate&&(Se(i,t,r),i.needsUpdate=!1);var s,c,h=!1,l=!1,p=!1,v=n.program,y=v.getUniforms(),A=n.shader.uniforms;if(m.useProgram(v.program)&&(h=!0,l=!0,p=!0),i.id!==G&&(G=i.id,l=!0),h||e!==k){if(y.setValue(d,"projectionMatrix",e.projectionMatrix),f.logarithmicDepthBuffer&&y.setValue(d,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),k!==(j||e)&&(k=j||e,l=!0,p=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshStandardMaterial||i.envMap){var x=y.map.cameraPosition;void 0!==x&&x.setValue(d,de.setFromMatrixPosition(e.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.skinning)&&y.setValue(d,"viewMatrix",e.matrixWorldInverse)}if(i.skinning){y.setOptional(d,r,"bindMatrix"),y.setOptional(d,r,"bindMatrixInverse");var w=r.skeleton;if(w){var b=w.bones;if(f.floatVertexTextures){if(void 0===w.boneTexture){var _=Math.sqrt(4*b.length);_=M.ceilPowerOfTwo(_),_=Math.max(_,4);var E=new Float32Array(_*_*4);E.set(w.boneMatrices);var T=new V(E,_,_,1023,1015);T.needsUpdate=!0,w.boneMatrices=E,w.boneTexture=T,w.boneTextureSize=_}y.setValue(d,"boneTexture",w.boneTexture),y.setValue(d,"boneTextureSize",w.boneTextureSize)}else y.setOptional(d,w,"boneMatrices")}}return l&&(y.setValue(d,"toneMappingExposure",O.toneMappingExposure),y.setValue(d,"toneMappingWhitePoint",O.toneMappingWhitePoint),i.lights&&(c=p,(s=A).ambientLightColor.needsUpdate=c,s.directionalLights.needsUpdate=c,s.pointLights.needsUpdate=c,s.spotLights.needsUpdate=c,s.rectAreaLights.needsUpdate=c,s.hemisphereLights.needsUpdate=c),t&&i.fog&&function(e,t){e.fogColor.value=t.color,t.isFog?(e.fogNear.value=t.near,e.fogFar.value=t.far):t.isFogExp2&&(e.fogDensity.value=t.density)}(A,t),i.isMeshBasicMaterial?Le(A,i):i.isMeshLambertMaterial?(Le(A,i),function(e,t){t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap)}(A,i)):i.isMeshPhongMaterial?(Le(A,i),i.isMeshToonMaterial?function(e,t){Pe(e,t),t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(A,i):Pe(A,i)):i.isMeshStandardMaterial?(Le(A,i),i.isMeshPhysicalMaterial?function(e,t){e.clearCoat.value=t.clearCoat,e.clearCoatRoughness.value=t.clearCoatRoughness,Ce(e,t)}(A,i):Ce(A,i)):i.isMeshDepthMaterial?(Le(A,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(A,i)):i.isMeshDistanceMaterial?(Le(A,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias);e.referencePosition.value.copy(t.referencePosition),e.nearDistance.value=t.nearDistance,e.farDistance.value=t.farDistance}(A,i)):i.isMeshNormalMaterial?(Le(A,i),function(e,t){t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale,1===t.side&&(e.bumpScale.value*=-1));t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale),1===t.side&&e.normalScale.value.negate());t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(A,i)):i.isLineBasicMaterial?(function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity}(A,i),i.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(A,i)):i.isPointsMaterial?function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity,e.size.value=t.size*re,e.scale.value=.5*ie,e.map.value=t.map,null!==t.map&&(!0===t.map.matrixAutoUpdate&&t.map.updateMatrix(),e.uvTransform.value.copy(t.map.matrix))}(A,i):i.isShadowMaterial&&(A.color.value=i.color,A.opacity.value=i.opacity),void 0!==A.ltc_1&&(A.ltc_1.value=K.LTC_1),void 0!==A.ltc_2&&(A.ltc_2.value=K.LTC_2),Qt.upload(d,n.uniformsList,A,O)),i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(Qt.upload(d,n.uniformsList,A,O),i.uniformsNeedUpdate=!1),y.setValue(d,"modelViewMatrix",r.modelViewMatrix),y.setValue(d,"normalMatrix",r.normalMatrix),y.setValue(d,"modelMatrix",r.matrixWorld),v}function Le(e,t){var i;e.opacity.value=t.opacity,t.color&&(e.diffuse.value=t.color),t.emissive&&e.emissive.value.copy(t.emissive).multiplyScalar(t.emissiveIntensity),t.map&&(e.map.value=t.map),t.alphaMap&&(e.alphaMap.value=t.alphaMap),t.specularMap&&(e.specularMap.value=t.specularMap),t.envMap&&(e.envMap.value=t.envMap,e.flipEnvMap.value=t.envMap&&t.envMap.isCubeTexture?-1:1,e.reflectivity.value=t.reflectivity,e.refractionRatio.value=t.refractionRatio,e.maxMipLevel.value=g.get(t.envMap).__maxMipLevel),t.lightMap&&(e.lightMap.value=t.lightMap,e.lightMapIntensity.value=t.lightMapIntensity),t.aoMap&&(e.aoMap.value=t.aoMap,e.aoMapIntensity.value=t.aoMapIntensity),t.map?i=t.map:t.specularMap?i=t.specularMap:t.displacementMap?i=t.displacementMap:t.normalMap?i=t.normalMap:t.bumpMap?i=t.bumpMap:t.roughnessMap?i=t.roughnessMap:t.metalnessMap?i=t.metalnessMap:t.alphaMap?i=t.alphaMap:t.emissiveMap&&(i=t.emissiveMap),void 0!==i&&(i.isWebGLRenderTarget&&(i=i.texture),!0===i.matrixAutoUpdate&&i.updateMatrix(),e.uvTransform.value.copy(i.matrix))}function Pe(e,t){e.specular.value=t.specular,e.shininess.value=Math.max(t.shininess,1e-4),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale,1===t.side&&(e.bumpScale.value*=-1)),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale),1===t.side&&e.normalScale.value.negate()),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}function Ce(e,t){e.roughness.value=t.roughness,e.metalness.value=t.metalness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap),t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale,1===t.side&&(e.bumpScale.value*=-1)),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale),1===t.side&&e.normalScale.value.negate()),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}Ee.setAnimationLoop((function(){ve.isPresenting()||be&&be()})),Ee.setContext(window),this.setAnimationLoop=function(e){be=e,ve.setAnimationLoop(e),Ee.start()},this.render=function(e,t,i,r){if(t&&t.isCamera){if(!N){H="",G=-1,k=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),ve.enabled&&(t=ve.getCamera(t)),(u=E.get(e,t)).init(),e.onBeforeRender(O,e,t,i),ue.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),se.setFromMatrix(ue),le=this.localClippingEnabled,he=ce.init(this.clippingPlanes,le,t),(l=_.get(e,t)).init(),function e(t,i,r){if(!1===t.visible)return;if(t.layers.test(i.layers))if(t.isLight)u.pushLight(t),t.castShadow&&u.pushShadow(t);else if(t.isSprite)t.frustumCulled&&!se.intersectsSprite(t)||u.pushSprite(t);else if(t.isImmediateRenderObject)r&&de.setFromMatrixPosition(t.matrixWorld).applyMatrix4(ue),l.push(t,null,t.material,de.z,null);else if((t.isMesh||t.isLine||t.isPoints)&&(t.isSkinnedMesh&&t.skeleton.update(),!t.frustumCulled||se.intersectsObject(t))){r&&de.setFromMatrixPosition(t.matrixWorld).applyMatrix4(ue);var n=w.update(t),a=t.material;if(Array.isArray(a))for(var o=n.groups,s=0,c=o.length;s=f.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+f.maxTextures),Z+=1,e},this.setTexture2D=(_e=!1,function(e,t){e&&e.isWebGLRenderTarget&&(_e||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),_e=!0),e=e.texture),y.setTexture2D(e,t)}),this.setTexture=function(){var e=!1;return function(t,i){e||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),e=!0),y.setTexture2D(t,i)}}(),this.setTextureCube=function(){var e=!1;return function(t,i){t&&t.isWebGLRenderTargetCube&&(e||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),e=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?y.setTextureCube(t,i):y.setTextureCubeDynamic(t,i)}}(),this.setFramebuffer=function(e){B=e},this.getRenderTarget=function(){return F},this.setRenderTarget=function(e){F=e,e&&void 0===g.get(e).__webglFramebuffer&&y.setupRenderTarget(e);var t=B,i=!1;if(e){var r=g.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=r[e.activeCubeFace],i=!0):t=r,X.copy(e.viewport),Y.copy(e.scissor),Q=e.scissorTest}else X.copy(ne).multiplyScalar(re),Y.copy(ae).multiplyScalar(re),Q=oe;if(z!==t&&(d.bindFramebuffer(d.FRAMEBUFFER,t),z=t),m.viewport(X),m.scissor(Y),m.setScissorTest(Q),i){var n=g.get(e.texture);d.framebufferTexture2D(d.FRAMEBUFFER,d.COLOR_ATTACHMENT0,d.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,n.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,r,n,a){if(e&&e.isWebGLRenderTarget){var o=g.get(e).__webglFramebuffer;if(o){var s=!1;o!==z&&(d.bindFramebuffer(d.FRAMEBUFFER,o),s=!0);try{var c=e.texture,h=c.format,l=c.type;if(1023!==h&&I.convert(h)!==d.getParameter(d.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(1009===l||I.convert(l)===d.getParameter(d.IMPLEMENTATION_COLOR_READ_TYPE)||1015===l&&(p.get("OES_texture_float")||p.get("WEBGL_color_buffer_float"))||1016===l&&p.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");d.checkFramebufferStatus(d.FRAMEBUFFER)===d.FRAMEBUFFER_COMPLETE?t>=0&&t<=e.width-r&&i>=0&&i<=e.height-n&&d.readPixels(t,i,r,n,I.convert(h),I.convert(l),a):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&d.bindFramebuffer(d.FRAMEBUFFER,z)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")},this.copyFramebufferToTexture=function(e,t,i){var r=t.image.width,n=t.image.height,a=I.convert(t.format);this.setTexture2D(t,0),d.copyTexImage2D(d.TEXTURE_2D,i||0,a,e.x,e.y,r,n,0)},this.copyTextureToTexture=function(e,t,i,r){var n=t.image.width,a=t.image.height,o=I.convert(i.format),s=I.convert(i.type);this.setTexture2D(i,0),t.isDataTexture?d.texSubImage2D(d.TEXTURE_2D,r||0,e.x,e.y,n,a,o,s,t.image.data):d.texSubImage2D(d.TEXTURE_2D,r||0,e.x,e.y,o,s,t.image)}}function zi(e,t){this.name="",this.color=new Z(e),this.density=void 0!==t?t:25e-5}function Gi(e,t,i){this.name="",this.color=new Z(e),this.near=void 0!==t?t:1,this.far=void 0!==i?i:1e3}function Vi(){he.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function Hi(e){ke.call(this),this.type="SpriteMaterial",this.color=new Z(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function ki(e){he.call(this),this.type="Sprite",this.material=void 0!==e?e:new Hi,this.center=new T(.5,.5)}function ji(){he.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function Wi(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===t)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,r=this.bones.length;i=0?(e(g-h,v,d),p.subVectors(u,d)):(e(g+h,v,d),p.subVectors(d,u)),v-h>=0?(e(g,v-h,d),f.subVectors(u,d)):(e(g,v+h,d),f.subVectors(d,u)),l.crossVectors(p,f).normalize(),s.push(l.x,l.y,l.z),c.push(g,v)}}for(r=0;r.9&&o<.1&&(t<.2&&(a[e+0]+=1),i<.2&&(a[e+2]+=1),r<.2&&(a[e+4]+=1))}}()}(),this.addAttribute("position",new Me(n,3)),this.addAttribute("normal",new Me(n.slice(),3)),this.addAttribute("uv",new Me(a,2)),0===r?this.computeVertexNormals():this.normalizeNormals()}function hr(e,t){ve.call(this),this.type="TetrahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new lr(e,t)),this.mergeVertices()}function lr(e,t){cr.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],e,t),this.type="TetrahedronBufferGeometry",this.parameters={radius:e,detail:t}}function ur(e,t){ve.call(this),this.type="OctahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new dr(e,t)),this.mergeVertices()}function dr(e,t){cr.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],e,t),this.type="OctahedronBufferGeometry",this.parameters={radius:e,detail:t}}function pr(e,t){ve.call(this),this.type="IcosahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new fr(e,t)),this.mergeVertices()}function fr(e,t){var i=(1+Math.sqrt(5))/2,r=[-1,i,0,1,i,0,-1,-i,0,1,-i,0,0,-1,i,0,1,i,0,-1,-i,0,1,-i,i,0,-1,i,0,1,-i,0,-1,-i,0,1];cr.call(this,r,[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],e,t),this.type="IcosahedronBufferGeometry",this.parameters={radius:e,detail:t}}function mr(e,t){ve.call(this),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new vr(e,t)),this.mergeVertices()}function vr(e,t){var i=(1+Math.sqrt(5))/2,r=1/i,n=[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-r,-i,0,-r,i,0,r,-i,0,r,i,-r,-i,0,-r,i,0,r,-i,0,r,i,0,-i,0,-r,i,0,-r,-i,0,r,i,0,r];cr.call(this,n,[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],e,t),this.type="DodecahedronBufferGeometry",this.parameters={radius:e,detail:t}}function gr(e,t,i,r,n,a){ve.call(this),this.type="TubeGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},void 0!==a&&console.warn("THREE.TubeGeometry: taper has been removed.");var o=new yr(e,t,i,r,n);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals,this.fromBufferGeometry(o),this.mergeVertices()}function yr(e,t,i,r,n){Pe.call(this),this.type="TubeBufferGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},t=t||64,i=i||1,r=r||8,n=n||!1;var a=e.computeFrenetFrames(t,n);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals;var o,s,c=new L,h=new L,l=new T,u=new L,d=[],p=[],f=[],m=[];function v(n){u=e.getPointAt(n/t,u);var o=a.normals[n],l=a.binormals[n];for(s=0;s<=r;s++){var f=s/r*Math.PI*2,m=Math.sin(f),v=-Math.cos(f);h.x=v*o.x+m*l.x,h.y=v*o.y+m*l.y,h.z=v*o.z+m*l.z,h.normalize(),p.push(h.x,h.y,h.z),c.x=u.x+i*h.x,c.y=u.y+i*h.y,c.z=u.z+i*h.z,d.push(c.x,c.y,c.z)}}!function(){for(o=0;oi)){var r=e.ray.origin.distanceTo(fi);re.far||t.push({distance:r,point:fi.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)},copy:function(e){return he.prototype.copy.call(this,e),void 0!==e.center&&this.center.copy(e.center),this}}),ji.prototype=Object.assign(Object.create(he.prototype),{constructor:ji,copy:function(e){he.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,r=t.length;i1){e.setFromMatrixPosition(i.matrixWorld),t.setFromMatrixPosition(this.matrixWorld);var n=e.distanceTo(t);r[0].object.visible=!0;for(var a=1,o=r.length;a=r[a].distance;a++)r[a-1].object.visible=!1,r[a].object.visible=!0;for(;ao))d.applyMatrix4(this.matrixWorld),(_=r.ray.origin.distanceTo(d))r.far||n.push({distance:_,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}else for(g=0,y=m.length/3-1;go))d.applyMatrix4(this.matrixWorld),(_=r.ray.origin.distanceTo(d))r.far||n.push({distance:_,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}else if(s.isGeometry){var w=s.vertices,b=w.length;for(g=0;go))d.applyMatrix4(this.matrixWorld),(_=r.ray.origin.distanceTo(d))r.far||n.push({distance:_,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Zi.prototype=Object.assign(Object.create(Qi.prototype),{constructor:Zi,isLineSegments:!0,computeLineDistances:function(){var e=new L,t=new L;return function(){var i=this.geometry;if(i.isBufferGeometry)if(null===i.index){for(var r=i.attributes.position,n=[],a=0,o=r.count;ar.far)return;n.push({distance:c,distanceToRay:Math.sqrt(o),point:d.clone(),index:i,face:null,object:a})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),er.prototype=Object.assign(Object.create(he.prototype),{constructor:er,isGroup:!0}),tr.prototype=Object.assign(Object.create(F.prototype),{constructor:tr,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),ir.prototype=Object.create(F.prototype),ir.prototype.constructor=ir,ir.prototype.isCompressedTexture=!0,rr.prototype=Object.create(F.prototype),rr.prototype.constructor=rr,rr.prototype.isDepthTexture=!0,nr.prototype=Object.create(Pe.prototype),nr.prototype.constructor=nr,ar.prototype=Object.create(ve.prototype),ar.prototype.constructor=ar,or.prototype=Object.create(Pe.prototype),or.prototype.constructor=or,sr.prototype=Object.create(ve.prototype),sr.prototype.constructor=sr,cr.prototype=Object.create(Pe.prototype),cr.prototype.constructor=cr,hr.prototype=Object.create(ve.prototype),hr.prototype.constructor=hr,lr.prototype=Object.create(cr.prototype),lr.prototype.constructor=lr,ur.prototype=Object.create(ve.prototype),ur.prototype.constructor=ur,dr.prototype=Object.create(cr.prototype),dr.prototype.constructor=dr,pr.prototype=Object.create(ve.prototype),pr.prototype.constructor=pr,fr.prototype=Object.create(cr.prototype),fr.prototype.constructor=fr,mr.prototype=Object.create(ve.prototype),mr.prototype.constructor=mr,vr.prototype=Object.create(cr.prototype),vr.prototype.constructor=vr,gr.prototype=Object.create(ve.prototype),gr.prototype.constructor=gr,yr.prototype=Object.create(Pe.prototype),yr.prototype.constructor=yr,Ar.prototype=Object.create(ve.prototype),Ar.prototype.constructor=Ar,xr.prototype=Object.create(Pe.prototype),xr.prototype.constructor=xr,wr.prototype=Object.create(ve.prototype),wr.prototype.constructor=wr,br.prototype=Object.create(Pe.prototype),br.prototype.constructor=br;var _r=function(e,t,i){i=i||2;var r,n,a,o,s,c,h,l=t&&t.length,u=l?t[0]*i:e.length,d=Er(e,0,u,i,!0),p=[];if(!d)return p;if(l&&(d=function(e,t,i,r){var n,a,o,s,c,h=[];for(n=0,a=t.length;n80*i){r=a=e[0],n=o=e[1];for(var f=i;fa&&(a=s),c>o&&(o=c);h=0!==(h=Math.max(a-r,o-n))?1/h:0}return Tr(d,p,i,r,n,h),p};function Er(e,t,i,r,n){var a,o;if(n===function(e,t,i,r){for(var n=0,a=t,o=i-r;a0)for(a=t;a=t;a-=r)o=Hr(a,e[a],e[a+1],o);return o&&Ur(o,o.next)&&(kr(o),o=o.next),o}function Mr(e,t){if(!e)return e;t||(t=e);var i,r=e;do{if(i=!1,r.steiner||!Ur(r,r.next)&&0!==Fr(r.prev,r,r.next))r=r.next;else{if(kr(r),(r=t=r.prev)===r.next)break;i=!0}}while(i||r!==t);return t}function Tr(e,t,i,r,n,a,o){if(e){!o&&a&&function(e,t,i,r){var n=e;do{null===n.z&&(n.z=Ir(n.x,n.y,t,i,r)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==e);n.prevZ.nextZ=null,n.prevZ=null,function(e){var t,i,r,n,a,o,s,c,h=1;do{for(i=e,e=null,a=null,o=0;i;){for(o++,r=i,s=0,t=0;t0||c>0&&r;)0!==s&&(0===c||!r||i.z<=r.z)?(n=i,i=i.nextZ,s--):(n=r,r=r.nextZ,c--),a?a.nextZ=n:e=n,n.prevZ=a,a=n;i=r}a.nextZ=null,h*=2}while(o>1)}(n)}(e,r,n,a);for(var s,c,h=e;e.prev!==e.next;)if(s=e.prev,c=e.next,a?Rr(e,r,n,a):Sr(e))t.push(s.i/i),t.push(e.i/i),t.push(c.i/i),kr(e),e=c.next,h=c.next;else if((e=c)===h){o?1===o?Tr(e=Lr(e,t,i),t,i,r,n,a,2):2===o&&Pr(e,t,i,r,n,a):Tr(Mr(e),t,i,r,n,a,1);break}}}function Sr(e){var t=e.prev,i=e,r=e.next;if(Fr(t,i,r)>=0)return!1;for(var n=e.next.next;n!==e.prev;){if(Nr(t.x,t.y,i.x,i.y,r.x,r.y,n.x,n.y)&&Fr(n.prev,n,n.next)>=0)return!1;n=n.next}return!0}function Rr(e,t,i,r){var n=e.prev,a=e,o=e.next;if(Fr(n,a,o)>=0)return!1;for(var s=n.xa.x?n.x>o.x?n.x:o.x:a.x>o.x?a.x:o.x,l=n.y>a.y?n.y>o.y?n.y:o.y:a.y>o.y?a.y:o.y,u=Ir(s,c,t,i,r),d=Ir(h,l,t,i,r),p=e.nextZ;p&&p.z<=d;){if(p!==e.prev&&p!==e.next&&Nr(n.x,n.y,a.x,a.y,o.x,o.y,p.x,p.y)&&Fr(p.prev,p,p.next)>=0)return!1;p=p.nextZ}for(p=e.prevZ;p&&p.z>=u;){if(p!==e.prev&&p!==e.next&&Nr(n.x,n.y,a.x,a.y,o.x,o.y,p.x,p.y)&&Fr(p.prev,p,p.next)>=0)return!1;p=p.prevZ}return!0}function Lr(e,t,i){var r=e;do{var n=r.prev,a=r.next.next;!Ur(n,a)&&zr(n,r,r.next,a)&&Gr(n,a)&&Gr(a,n)&&(t.push(n.i/i),t.push(r.i/i),t.push(a.i/i),kr(r),kr(r.next),r=e=a),r=r.next}while(r!==e);return r}function Pr(e,t,i,r,n,a){var o=e;do{for(var s=o.next.next;s!==o.prev;){if(o.i!==s.i&&Br(o,s)){var c=Vr(o,s);return o=Mr(o,o.next),c=Mr(c,c.next),Tr(o,t,i,r,n,a),void Tr(c,t,i,r,n,a)}s=s.next}o=o.next}while(o!==e)}function Cr(e,t){return e.x-t.x}function Dr(e,t){if(t=function(e,t){var i,r=t,n=e.x,a=e.y,o=-1/0;do{if(a<=r.y&&a>=r.next.y&&r.next.y!==r.y){var s=r.x+(a-r.y)*(r.next.x-r.x)/(r.next.y-r.y);if(s<=n&&s>o){if(o=s,s===n){if(a===r.y)return r;if(a===r.next.y)return r.next}i=r.x=r.x&&r.x>=l&&n!==r.x&&Nr(ai.x)&&Gr(r,e)&&(i=r,d=c),r=r.next;return i}(e,t)){var i=Vr(t,e);Mr(i,i.next)}}function Ir(e,t,i,r,n){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*n)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*n)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function Or(e){var t=e,i=e;do{t.x=0&&(e-o)*(r-s)-(i-o)*(t-s)>=0&&(i-o)*(a-s)-(n-o)*(r-s)>=0}function Br(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&zr(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(e,t)&&Gr(e,t)&&Gr(t,e)&&function(e,t){var i=e,r=!1,n=(e.x+t.x)/2,a=(e.y+t.y)/2;do{i.y>a!=i.next.y>a&&i.next.y!==i.y&&n<(i.next.x-i.x)*(a-i.y)/(i.next.y-i.y)+i.x&&(r=!r),i=i.next}while(i!==e);return r}(e,t)}function Fr(e,t,i){return(t.y-e.y)*(i.x-t.x)-(t.x-e.x)*(i.y-t.y)}function Ur(e,t){return e.x===t.x&&e.y===t.y}function zr(e,t,i,r){return!!(Ur(e,t)&&Ur(i,r)||Ur(e,r)&&Ur(i,t))||Fr(e,t,i)>0!=Fr(e,t,r)>0&&Fr(i,r,e)>0!=Fr(i,r,t)>0}function Gr(e,t){return Fr(e.prev,e,e.next)<0?Fr(e,t,e.next)>=0&&Fr(e,e.prev,t)>=0:Fr(e,t,e.prev)<0||Fr(e,e.next,t)<0}function Vr(e,t){var i=new jr(e.i,e.x,e.y),r=new jr(t.i,t.x,t.y),n=e.next,a=t.prev;return e.next=t,t.prev=e,i.next=n,n.prev=i,r.next=i,i.prev=r,a.next=r,r.prev=a,r}function Hr(e,t,i,r){var n=new jr(e,t,i);return r?(n.next=r.next,n.prev=r,r.next.prev=n,r.next=n):(n.prev=n,n.next=n),n}function kr(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function jr(e,t,i){this.i=e,this.x=t,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var Wr={area:function(e){for(var t=e.length,i=0,r=t-1,n=0;n2&&e[t-1].equals(e[0])&&e.pop()}function Yr(e,t){for(var i=0;iNumber.EPSILON){var d=Math.sqrt(l),p=Math.sqrt(c*c+h*h),f=t.x-s/d,m=t.y+o/d,v=((i.x-h/p-f)*h-(i.y+c/p-m)*c)/(o*h-s*c),g=(r=f+o*v-e.x)*r+(n=m+s*v-e.y)*n;if(g<=2)return new T(r,n);a=Math.sqrt(g/2)}else{var y=!1;o>Number.EPSILON?c>Number.EPSILON&&(y=!0):o<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(r=-s,n=o,a=Math.sqrt(l)):(r=o,n=s,a=Math.sqrt(l/2))}return new T(r/a,n/a)}for(var V=[],H=0,k=P.length,j=k-1,W=H+1;H=0;D--){for(O=D/d,N=l*Math.cos(O*Math.PI/2),I=u*Math.sin(O*Math.PI/2),H=0,k=P.length;H=0;){i=H,(r=H-1)<0&&(r=e.length-1);var n=0,a=s+2*d;for(n=0;n0)&&f.push(w,b,E),(c!==i-1||h0&&g(!0),t>0&&g(!1)),this.setIndex(h),this.addAttribute("position",new Me(l,3)),this.addAttribute("normal",new Me(u,3)),this.addAttribute("uv",new Me(d,2))}function pn(e,t,i,r,n,a,o){un.call(this,0,e,t,i,r,n,a,o),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:a,thetaLength:o}}function fn(e,t,i,r,n,a,o){dn.call(this,0,e,t,i,r,n,a,o),this.type="ConeBufferGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:a,thetaLength:o}}function mn(e,t,i,r){ve.call(this),this.type="CircleGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},this.fromBufferGeometry(new vn(e,t,i,r)),this.mergeVertices()}function vn(e,t,i,r){Pe.call(this),this.type="CircleBufferGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},e=e||1,t=void 0!==t?Math.max(3,t):8,i=void 0!==i?i:0,r=void 0!==r?r:2*Math.PI;var n,a,o=[],s=[],c=[],h=[],l=new L,u=new T;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),a=0,n=3;a<=t;a++,n+=3){var d=i+a/t*r;l.x=e*Math.cos(d),l.y=e*Math.sin(d),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[n]/e+1)/2,u.y=(s[n+1]/e+1)/2,h.push(u.x,u.y)}for(n=1;n<=t;n++)o.push(n,n+1,0);this.setIndex(o),this.addAttribute("position",new Me(s,3)),this.addAttribute("normal",new Me(c,3)),this.addAttribute("uv",new Me(h,2))}Kr.prototype=Object.create(ve.prototype),Kr.prototype.constructor=Kr,$r.prototype=Object.create(Qr.prototype),$r.prototype.constructor=$r,en.prototype=Object.create(ve.prototype),en.prototype.constructor=en,tn.prototype=Object.create(Pe.prototype),tn.prototype.constructor=tn,rn.prototype=Object.create(ve.prototype),rn.prototype.constructor=rn,nn.prototype=Object.create(Pe.prototype),nn.prototype.constructor=nn,an.prototype=Object.create(ve.prototype),an.prototype.constructor=an,on.prototype=Object.create(Pe.prototype),on.prototype.constructor=on,sn.prototype=Object.create(ve.prototype),sn.prototype.constructor=sn,sn.prototype.toJSON=function(){var e=ve.prototype.toJSON.call(this);return hn(this.parameters.shapes,e)},cn.prototype=Object.create(Pe.prototype),cn.prototype.constructor=cn,cn.prototype.toJSON=function(){var e=Pe.prototype.toJSON.call(this);return hn(this.parameters.shapes,e)},ln.prototype=Object.create(Pe.prototype),ln.prototype.constructor=ln,un.prototype=Object.create(ve.prototype),un.prototype.constructor=un,dn.prototype=Object.create(Pe.prototype),dn.prototype.constructor=dn,pn.prototype=Object.create(un.prototype),pn.prototype.constructor=pn,fn.prototype=Object.create(dn.prototype),fn.prototype.constructor=fn,mn.prototype=Object.create(ve.prototype),mn.prototype.constructor=mn,vn.prototype=Object.create(Pe.prototype),vn.prototype.constructor=vn;var gn=Object.freeze({WireframeGeometry:nr,ParametricGeometry:ar,ParametricBufferGeometry:or,TetrahedronGeometry:hr,TetrahedronBufferGeometry:lr,OctahedronGeometry:ur,OctahedronBufferGeometry:dr,IcosahedronGeometry:pr,IcosahedronBufferGeometry:fr,DodecahedronGeometry:mr,DodecahedronBufferGeometry:vr,PolyhedronGeometry:sr,PolyhedronBufferGeometry:cr,TubeGeometry:gr,TubeBufferGeometry:yr,TorusKnotGeometry:Ar,TorusKnotBufferGeometry:xr,TorusGeometry:wr,TorusBufferGeometry:br,TextGeometry:Kr,TextBufferGeometry:$r,SphereGeometry:en,SphereBufferGeometry:tn,RingGeometry:rn,RingBufferGeometry:nn,PlaneGeometry:Ie,PlaneBufferGeometry:Oe,LatheGeometry:an,LatheBufferGeometry:on,ShapeGeometry:sn,ShapeBufferGeometry:cn,ExtrudeGeometry:qr,ExtrudeBufferGeometry:Qr,EdgesGeometry:ln,ConeGeometry:pn,ConeBufferGeometry:fn,CylinderGeometry:un,CylinderBufferGeometry:dn,CircleGeometry:mn,CircleBufferGeometry:vn,BoxGeometry:Ce,BoxBufferGeometry:De});function yn(e){ke.call(this),this.type="ShadowMaterial",this.color=new Z(0),this.transparent=!0,this.setValues(e)}function An(e){We.call(this,e),this.type="RawShaderMaterial"}function xn(e){ke.call(this),this.defines={STANDARD:""},this.type="MeshStandardMaterial",this.color=new Z(16777215),this.roughness=.5,this.metalness=.5,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Z(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalScale=new T(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapIntensity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(e)}function wn(e){xn.call(this),this.defines={PHYSICAL:""},this.type="MeshPhysicalMaterial",this.reflectivity=.5,this.clearCoat=0,this.clearCoatRoughness=0,this.setValues(e)}function bn(e){ke.call(this),this.type="MeshPhongMaterial",this.color=new Z(16777215),this.specular=new Z(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Z(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalScale=new T(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(e)}function _n(e){bn.call(this),this.defines={TOON:""},this.type="MeshToonMaterial",this.gradientMap=null,this.setValues(e)}function En(e){ke.call(this),this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalScale=new T(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(e)}function Mn(e){ke.call(this),this.type="MeshLambertMaterial",this.color=new Z(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Z(0),this.emissiveIntensity=1,this.emissiveMap=null,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(e)}function Tn(e){qi.call(this),this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(e)}yn.prototype=Object.create(ke.prototype),yn.prototype.constructor=yn,yn.prototype.isShadowMaterial=!0,yn.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.color.copy(e.color),this},An.prototype=Object.create(We.prototype),An.prototype.constructor=An,An.prototype.isRawShaderMaterial=!0,xn.prototype=Object.create(ke.prototype),xn.prototype.constructor=xn,xn.prototype.isMeshStandardMaterial=!0,xn.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.defines={STANDARD:""},this.color.copy(e.color),this.roughness=e.roughness,this.metalness=e.metalness,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.roughnessMap=e.roughnessMap,this.metalnessMap=e.metalnessMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapIntensity=e.envMapIntensity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.morphNormals=e.morphNormals,this},wn.prototype=Object.create(xn.prototype),wn.prototype.constructor=wn,wn.prototype.isMeshPhysicalMaterial=!0,wn.prototype.copy=function(e){return xn.prototype.copy.call(this,e),this.defines={PHYSICAL:""},this.reflectivity=e.reflectivity,this.clearCoat=e.clearCoat,this.clearCoatRoughness=e.clearCoatRoughness,this},bn.prototype=Object.create(ke.prototype),bn.prototype.constructor=bn,bn.prototype.isMeshPhongMaterial=!0,bn.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.color.copy(e.color),this.specular.copy(e.specular),this.shininess=e.shininess,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.morphNormals=e.morphNormals,this},_n.prototype=Object.create(bn.prototype),_n.prototype.constructor=_n,_n.prototype.isMeshToonMaterial=!0,_n.prototype.copy=function(e){return bn.prototype.copy.call(this,e),this.gradientMap=e.gradientMap,this},En.prototype=Object.create(ke.prototype),En.prototype.constructor=En,En.prototype.isMeshNormalMaterial=!0,En.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.morphNormals=e.morphNormals,this},Mn.prototype=Object.create(ke.prototype),Mn.prototype.constructor=Mn,Mn.prototype.isMeshLambertMaterial=!0,Mn.prototype.copy=function(e){return ke.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.morphNormals=e.morphNormals,this},Tn.prototype=Object.create(qi.prototype),Tn.prototype.constructor=Tn,Tn.prototype.isLineDashedMaterial=!0,Tn.prototype.copy=function(e){return qi.prototype.copy.call(this,e),this.scale=e.scale,this.dashSize=e.dashSize,this.gapSize=e.gapSize,this};var Sn=Object.freeze({ShadowMaterial:yn,SpriteMaterial:Hi,RawShaderMaterial:An,ShaderMaterial:We,PointsMaterial:Ki,MeshPhysicalMaterial:wn,MeshStandardMaterial:xn,MeshPhongMaterial:bn,MeshToonMaterial:_n,MeshNormalMaterial:En,MeshLambertMaterial:Mn,MeshDepthMaterial:Ti,MeshDistanceMaterial:Si,MeshBasicMaterial:je,LineDashedMaterial:Tn,LineBasicMaterial:qi,Material:ke}),Rn={enabled:!1,files:{},add:function(e,t){!1!==this.enabled&&(this.files[e]=t)},get:function(e){if(!1!==this.enabled)return this.files[e]},remove:function(e){delete this.files[e]},clear:function(){this.files={}}};function Ln(e,t,i){var r=this,n=!1,a=0,o=0,s=void 0;this.onStart=void 0,this.onLoad=e,this.onProgress=t,this.onError=i,this.itemStart=function(e){o++,!1===n&&void 0!==r.onStart&&r.onStart(e,a,o),n=!0},this.itemEnd=function(e){a++,void 0!==r.onProgress&&r.onProgress(e,a,o),a===o&&(n=!1,void 0!==r.onLoad&&r.onLoad())},this.itemError=function(e){void 0!==r.onError&&r.onError(e)},this.resolveURL=function(e){return s?s(e):e},this.setURLModifier=function(e){return s=e,this}}var Pn=new Ln,Cn={};function Dn(e){this.manager=void 0!==e?e:Pn}function In(e){this.manager=void 0!==e?e:Pn}function On(e){this.manager=void 0!==e?e:Pn}function Nn(){this.type="Curve",this.arcLengthDivisions=200}function Bn(e,t,i,r,n,a,o,s){Nn.call(this),this.type="EllipseCurve",this.aX=e||0,this.aY=t||0,this.xRadius=i||1,this.yRadius=r||1,this.aStartAngle=n||0,this.aEndAngle=a||2*Math.PI,this.aClockwise=o||!1,this.aRotation=s||0}function Fn(e,t,i,r,n,a){Bn.call(this,e,t,i,i,r,n,a),this.type="ArcCurve"}function Un(){var e=0,t=0,i=0,r=0;function n(n,a,o,s){e=n,t=o,i=-3*n+3*a-2*o-s,r=2*n-2*a+o+s}return{initCatmullRom:function(e,t,i,r,a){n(t,i,a*(i-e),a*(r-t))},initNonuniformCatmullRom:function(e,t,i,r,a,o,s){var c=(t-e)/a-(i-e)/(a+o)+(i-t)/o,h=(i-t)/o-(r-t)/(o+s)+(r-i)/s;n(t,i,c*=o,h*=o)},calc:function(n){var a=n*n;return e+t*n+i*a+r*(a*n)}}}Object.assign(Dn.prototype,{load:function(e,t,i,r){void 0===e&&(e=""),void 0!==this.path&&(e=this.path+e),e=this.manager.resolveURL(e);var n=this,a=Rn.get(e);if(void 0!==a)return n.manager.itemStart(e),setTimeout((function(){t&&t(a),n.manager.itemEnd(e)}),0),a;if(void 0===Cn[e]){var o=e.match(/^data:(.*?)(;base64)?,(.*)$/);if(o){var s=o[1],c=!!o[2],h=o[3];h=window.decodeURIComponent(h),c&&(h=window.atob(h));try{var l,u=(this.responseType||"").toLowerCase();switch(u){case"arraybuffer":case"blob":for(var d=new Uint8Array(h.length),p=0;p0||0===e.search(/^data\:image\/jpeg/);n.format=r?1022:1023,n.needsUpdate=!0,void 0!==t&&t(n)}),i,r),n},setCrossOrigin:function(e){return this.crossOrigin=e,this},setPath:function(e){return this.path=e,this}}),Object.assign(Nn.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(e,t){var i=this.getUtoTmapping(e);return this.getPoint(i,t)},getPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPoint(i/e));return t},getSpacedPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPointAt(i/e));return t},getLength:function(){var e=this.getLengths();return e[e.length-1]},getLengths:function(e){if(void 0===e&&(e=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var t,i,r=[],n=this.getPoint(0),a=0;for(r.push(0),i=1;i<=e;i++)a+=(t=this.getPoint(i/e)).distanceTo(n),r.push(a),n=t;return this.cacheArcLengths=r,r},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(e,t){var i,r=this.getLengths(),n=0,a=r.length;i=t||e*r[a-1];for(var o,s=0,c=a-1;s<=c;)if((o=r[n=Math.floor(s+(c-s)/2)]-i)<0)s=n+1;else{if(!(o>0)){c=n;break}c=n-1}if(r[n=c]===i)return n/(a-1);var h=r[n];return(n+(i-h)/(r[n+1]-h))/(a-1)},getTangent:function(e){var t=e-1e-4,i=e+1e-4;t<0&&(t=0),i>1&&(i=1);var r=this.getPoint(t);return this.getPoint(i).clone().sub(r).normalize()},getTangentAt:function(e){var t=this.getUtoTmapping(e);return this.getTangent(t)},computeFrenetFrames:function(e,t){var i,r,n,a=new L,o=[],s=[],c=[],h=new L,l=new S;for(i=0;i<=e;i++)r=i/e,o[i]=this.getTangentAt(r),o[i].normalize();s[0]=new L,c[0]=new L;var u=Number.MAX_VALUE,d=Math.abs(o[0].x),p=Math.abs(o[0].y),f=Math.abs(o[0].z);for(d<=u&&(u=d,a.set(1,0,0)),p<=u&&(u=p,a.set(0,1,0)),f<=u&&a.set(0,0,1),h.crossVectors(o[0],a).normalize(),s[0].crossVectors(o[0],h),c[0].crossVectors(o[0],s[0]),i=1;i<=e;i++)s[i]=s[i-1].clone(),c[i]=c[i-1].clone(),h.crossVectors(o[i-1],o[i]),h.length()>Number.EPSILON&&(h.normalize(),n=Math.acos(M.clamp(o[i-1].dot(o[i]),-1,1)),s[i].applyMatrix4(l.makeRotationAxis(h,n))),c[i].crossVectors(o[i],s[i]);if(!0===t)for(n=Math.acos(M.clamp(s[0].dot(s[e]),-1,1)),n/=e,o[0].dot(h.crossVectors(s[0],s[e]))>0&&(n=-n),i=1;i<=e;i++)s[i].applyMatrix4(l.makeRotationAxis(o[i],n*i)),c[i].crossVectors(o[i],s[i]);return{tangents:o,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this},toJSON:function(){var e={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e},fromJSON:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}),Bn.prototype=Object.create(Nn.prototype),Bn.prototype.constructor=Bn,Bn.prototype.isEllipseCurve=!0,Bn.prototype.getPoint=function(e,t){for(var i=t||new T,r=2*Math.PI,n=this.aEndAngle-this.aStartAngle,a=Math.abs(n)r;)n-=r;n0?0:(Math.floor(Math.abs(l)/c)+1)*c:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?i=s[(l-1)%c]:(zn.subVectors(s[0],s[1]).add(s[0]),i=zn),r=s[l%c],n=s[(l+1)%c],this.closed||l+2r.length-2?r.length-1:a+1],l=r[a>r.length-3?r.length-1:a+2];return i.set(jn(o,s.x,c.x,h.x,l.x),jn(o,s.y,c.y,h.y,l.y)),i},$n.prototype.copy=function(e){Nn.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var n=i[r]-t,a=this.curves[r],o=a.getLength(),s=0===o?0:1-n/o;return a.getPointAt(s)}r++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,r=this.curves.length;i1&&!i[i.length-1].equals(i[0])&&i.push(i[0]),i},copy:function(e){Nn.prototype.copy.call(this,e),this.curves=[];for(var t=0,i=e.curves.length;t0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(e){return ta.prototype.copy.call(this,e),this.currentPoint.copy(e.currentPoint),this},toJSON:function(){var e=ta.prototype.toJSON.call(this);return e.currentPoint=this.currentPoint.toArray(),e},fromJSON:function(e){return ta.prototype.fromJSON.call(this,e),this.currentPoint.fromArray(e.currentPoint),this}}),ra.prototype=Object.assign(Object.create(ia.prototype),{constructor:ra,getPointsHoles:function(e){for(var t=[],i=0,r=this.holes.length;i=n)break e;var s=t[1];e=(n=t[--i-1]))break t}a=i,i=0}for(;i>>1;et;)--a;if(++a,0!==n||a!==r){n>=a&&(n=(a=Math.max(a,1))-1);var o=this.getValueSize();this.times=Ea.arraySlice(i,n,a),this.values=Ea.arraySlice(this.values,n*o,a*o)}return this},validate:function(){var e=!0,t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);var i=this.times,r=this.values,n=i.length;0===n&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);for(var a=null,o=0;o!==n;o++){var s=i[o];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,o,s),e=!1;break}if(null!==a&&a>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,o,s,a),e=!1;break}a=s}if(void 0!==r&&Ea.isTypedArray(r)){o=0;for(var c=r.length;o!==c;++o){var h=r[o];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,o,h),e=!1;break}}}return e},optimize:function(){for(var e=this.times,t=this.values,i=this.getValueSize(),r=2302===this.getInterpolation(),n=1,a=e.length-1,o=1;o0){e[n]=e[a];for(f=a*i,m=n*i,d=0;d!==i;++d)t[m+d]=t[f+d];++n}return n!==e.length&&(this.times=Ea.arraySlice(e,0,n),this.values=Ea.arraySlice(t,0,n*i)),this}}),Ta.prototype=Object.assign(Object.create(Ma.prototype),{constructor:Ta,ValueTypeName:"vector"}),Object.assign(Sa,{parse:function(e){for(var t=[],i=e.tracks,r=1/(e.fps||1),n=0,a=i.length;n!==a;++n)t.push(Ma.parse(i[n]).scale(r));return new Sa(e.name,e.duration,t)},toJSON:function(e){for(var t=[],i=e.tracks,r={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid},n=0,a=i.length;n!==a;++n)t.push(Ma.toJSON(i[n]));return r},CreateFromMorphTargetSequence:function(e,t,i,r){for(var n=t.length,a=[],o=0;o1){var h=r[u=c[1]];h||(r[u]=h=[]),h.push(s)}}var l=[];for(var u in r)l.push(Sa.CreateFromMorphTargetSequence(u,r[u],t,i));return l},parseAnimation:function(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var i=function(e,t,i,r,n){if(0!==i.length){var a=[],o=[];Ea.flattenJSON(i,a,o,r),0!==a.length&&n.push(new e(t,a,o))}},r=[],n=e.name||"default",a=e.length||-1,o=e.fps||30,s=e.hierarchy||[],c=0;c1?e.skinWeights[r+1]:0,s=i>2?e.skinWeights[r+2]:0,c=i>3?e.skinWeights[r+3]:0;t.skinWeights.push(new U(a,o,s,c))}if(e.skinIndices)for(r=0,n=e.skinIndices.length;r1?e.skinIndices[r+1]:0,u=i>2?e.skinIndices[r+2]:0,d=i>3?e.skinIndices[r+3]:0;t.skinIndices.push(new U(h,l,u,d))}t.bones=e.bones,t.bones&&t.bones.length>0&&(t.skinWeights.length!==t.skinIndices.length||t.skinIndices.length!==t.vertices.length)&&console.warn("When skinning, number of vertices ("+t.vertices.length+"), skinIndices ("+t.skinIndices.length+"), and skinWeights ("+t.skinWeights.length+") should match.")}(e,i),function(e,t){var i=e.scale;if(void 0!==e.morphTargets)for(var r=0,n=e.morphTargets.length;r0){console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');var l=t.faces,u=e.morphColors[0].colors;for(r=0,n=l.length;r0&&(t.animations=i)}(e,i),i.computeFaceNormals(),i.computeBoundingSphere(),void 0===e.materials||0===e.materials.length?{geometry:i}:{geometry:i,materials:Na.prototype.initMaterials(e.materials,t,this.crossOrigin)}}}),Object.assign(function(e){this.manager=void 0!==e?e:Pn,this.texturePath=""}.prototype,{load:function(e,t,i,r){""===this.texturePath&&(this.texturePath=e.substring(0,e.lastIndexOf("/")+1));var n=this;new Dn(n.manager).load(e,(function(i){var a=null;try{a=JSON.parse(i)}catch(t){return void 0!==r&&r(t),void console.error("THREE:ObjectLoader: Can't parse "+e+".",t.message)}var o=a.metadata;void 0!==o&&void 0!==o.type&&"geometry"!==o.type.toLowerCase()?n.parse(a,t):console.error("THREE.ObjectLoader: Can't load "+e+". Use THREE.JSONLoader instead.")}),i,r)},setTexturePath:function(e){return this.texturePath=e,this},setCrossOrigin:function(e){return this.crossOrigin=e,this},parse:function(e,t){var i=this.parseShape(e.shapes),r=this.parseGeometries(e.geometries,i),n=this.parseImages(e.images,(function(){void 0!==t&&t(s)})),a=this.parseTextures(e.textures,n),o=this.parseMaterials(e.materials,a),s=this.parseObject(e.object,r,o);return e.animations&&(s.animations=this.parseAnimations(e.animations)),void 0!==e.images&&0!==e.images.length||void 0!==t&&t(s),s},parseShape:function(e){var t={};if(void 0!==e)for(var i=0,r=e.length;i0){var a=new In(new Ln(t));a.setCrossOrigin(this.crossOrigin);for(var o=0,s=e.length;o0?new Yi(o,s):new Qe(o,s);break;case"LOD":r=new ji;break;case"Line":r=new Qi(n(e.geometry),a(e.material),e.mode);break;case"LineLoop":r=new Ji(n(e.geometry),a(e.material));break;case"LineSegments":r=new Zi(n(e.geometry),a(e.material));break;case"PointCloud":case"Points":r=new $i(n(e.geometry),a(e.material));break;case"Sprite":r=new ki(a(e.material));break;case"Group":r=new er;break;default:r=new he}if(r.uuid=e.uuid,void 0!==e.name&&(r.name=e.name),void 0!==e.matrix?(r.matrix.fromArray(e.matrix),void 0!==e.matrixAutoUpdate&&(r.matrixAutoUpdate=e.matrixAutoUpdate),r.matrixAutoUpdate&&r.matrix.decompose(r.position,r.quaternion,r.scale)):(void 0!==e.position&&r.position.fromArray(e.position),void 0!==e.rotation&&r.rotation.fromArray(e.rotation),void 0!==e.quaternion&&r.quaternion.fromArray(e.quaternion),void 0!==e.scale&&r.scale.fromArray(e.scale)),void 0!==e.castShadow&&(r.castShadow=e.castShadow),void 0!==e.receiveShadow&&(r.receiveShadow=e.receiveShadow),e.shadow&&(void 0!==e.shadow.bias&&(r.shadow.bias=e.shadow.bias),void 0!==e.shadow.radius&&(r.shadow.radius=e.shadow.radius),void 0!==e.shadow.mapSize&&r.shadow.mapSize.fromArray(e.shadow.mapSize),void 0!==e.shadow.camera&&(r.shadow.camera=this.parseObject(e.shadow.camera))),void 0!==e.visible&&(r.visible=e.visible),void 0!==e.frustumCulled&&(r.frustumCulled=e.frustumCulled),void 0!==e.renderOrder&&(r.renderOrder=e.renderOrder),void 0!==e.userData&&(r.userData=e.userData),void 0!==e.children)for(var c=e.children,h=0;hNumber.EPSILON){if(h<0&&(o=t[a],c=-c,s=t[n],h=-h),e.ys.y)continue;if(e.y===o.y){if(e.x===o.x)return!0}else{var l=h*(e.x-o.x)-c*(e.y-o.y);if(0===l)return!0;if(l<0)continue;r=!r}}else{if(e.y!==o.y)continue;if(s.x<=e.x&&e.x<=o.x||o.x<=e.x&&e.x<=s.x)return!0}}return r}var n=Wr.isClockWise,a=this.subPaths;if(0===a.length)return[];if(!0===t)return i(a);var o,s,c,h=[];if(1===a.length)return s=a[0],(c=new ra).curves=s.curves,h.push(c),h;var l=!n(a[0].getPoints());l=e?!l:l;var u,d,p=[],f=[],m=[],v=0;f[v]=void 0,m[v]=[];for(var g=0,y=a.length;g1){for(var A=!1,x=[],w=0,b=f.length;w0&&(A||(m=p))}g=0;for(var R=f.length;g0){this.source.connect(this.filters[0]);for(var e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(var e=1,t=this.filters.length;e=.5)for(var a=0;a!==n;++a)e[t+a]=e[i+a]},_slerp:function(e,t,i,r){R.slerpFlat(e,t,e,t,e,i,r)},_lerp:function(e,t,i,r,n){for(var a=1-r,o=0;o!==n;++o){var s=t+o;e[s]=e[s]*a+e[i+o]*r}}});var ho,lo,uo,po,fo,mo,vo,go,yo,Ao,xo,wo;function bo(e,t,i){var r=i||_o.parseTrackName(t);this._targetGroup=e,this._bindings=e.subscribe_(t,r)}function _o(e,t,i){this.path=t,this.parsedPath=i||_o.parseTrackName(t),this.node=_o.findNode(e,this.parsedPath.nodeName)||e,this.rootNode=e}function Eo(e,t,i){this._mixer=e,this._clip=t,this._localRoot=i||null;for(var r=t.tracks,n=r.length,a=new Array(n),o={endingStart:2400,endingEnd:2400},s=0;s!==n;++s){var c=r[s].createInterpolant(null);a[s]=c,c.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(n),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}function Mo(e){this._root=e,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}function To(e){"string"==typeof e&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),e=arguments[1]),this.value=e}function So(){Pe.call(this),this.type="InstancedBufferGeometry",this.maxInstancedCount=void 0}function Ro(e,t,i,r){this.data=e,this.itemSize=t,this.offset=i,this.normalized=!0===r}function Lo(e,t){this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.dynamic=!1,this.updateRange={offset:0,count:-1},this.version=0}function Po(e,t,i){Lo.call(this,e,t),this.meshPerAttribute=i||1}function Co(e,t,i){ge.call(this,e,t),this.meshPerAttribute=i||1}function Do(e,t){return e.distance-t.distance}function Io(e,t,i,r){if(!1!==e.visible&&(e.raycast(t,i),!0===r))for(var n=e.children,a=0,o=n.length;a=t){var l=t++,u=e[l];i[u.uuid]=h,e[h]=u,i[c]=l,e[l]=s;for(var d=0,p=n;d!==p;++d){var f=r[d],m=f[l],v=f[h];f[h]=m,f[l]=v}}}this.nCachedObjects_=t},uncache:function(){for(var e=this._objects,t=e.length,i=this.nCachedObjects_,r=this._indicesByUUID,n=this._bindings,a=n.length,o=0,s=arguments.length;o!==s;++o){var c=arguments[o],h=c.uuid,l=r[h];if(void 0!==l)if(delete r[h],l0)for(var c=this._interpolants,h=this._propertyBindings,l=0,u=c.length;l!==u;++l)c[l].evaluate(o),h[l].accumulate(r,s)}else this._updateWeight(e)},_updateWeight:function(e){var t=0;if(this.enabled){t=this.weight;var i=this._weightInterpolant;if(null!==i){var r=i.evaluate(e)[0];t*=r,e>i.parameterPositions[1]&&(this.stopFading(),0===r&&(this.enabled=!1))}}return this._effectiveWeight=t,t},_updateTimeScale:function(e){var t=0;if(!this.paused){t=this.timeScale;var i=this._timeScaleInterpolant;if(null!==i)t*=i.evaluate(e)[0],e>i.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}return this._effectiveTimeScale=t,t},_updateTime:function(e){var t=this.time+e;if(0===e)return t;var i=this._clip.duration,r=this.loop,n=this._loopCount;if(2200===r){-1===n&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(t>=i)t=i;else{if(!(t<0))break e;t=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{var a=2202===r;if(-1===n&&(e>=0?(n=0,this._setEndings(!0,0===this.repetitions,a)):this._setEndings(0===this.repetitions,!0,a)),t>=i||t<0){var o=Math.floor(t/i);t-=i*o,n+=Math.abs(o);var s=this.repetitions-n;if(s<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,t=e>0?i:0,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(1===s){var c=e<0;this._setEndings(c,!c,a)}else this._setEndings(!1,!1,a);this._loopCount=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:o})}}if(a&&1==(1&n))return this.time=t,i-t}return this.time=t,t},_setEndings:function(e,t,i){var r=this._interpolantSettings;i?(r.endingStart=2401,r.endingEnd=2401):(r.endingStart=e?this.zeroSlopeAtStart?2401:2400:2402,r.endingEnd=t?this.zeroSlopeAtEnd?2401:2400:2402)},_scheduleFading:function(e,t,i){var r=this._mixer,n=r.time,a=this._weightInterpolant;null===a&&(a=r._lendControlInterpolant(),this._weightInterpolant=a);var o=a.parameterPositions,s=a.sampleValues;return o[0]=n,s[0]=t,o[1]=n+e,s[1]=i,this}}),Mo.prototype=Object.assign(Object.create(l.prototype),{constructor:Mo,_bindAction:function(e,t){var i=e._localRoot||this._root,r=e._clip.tracks,n=r.length,a=e._propertyBindings,o=e._interpolants,s=i.uuid,c=this._bindingsByRootAndName,h=c[s];void 0===h&&(h={},c[s]=h);for(var l=0;l!==n;++l){var u=r[l],d=u.name,p=h[d];if(void 0!==p)a[l]=p;else{if(void 0!==(p=a[l])){null===p._cacheIndex&&(++p.referenceCount,this._addInactiveBinding(p,s,d));continue}var f=t&&t._propertyBindings[l].binding.parsedPath;++(p=new co(_o.create(i,d,f),u.ValueTypeName,u.getValueSize())).referenceCount,this._addInactiveBinding(p,s,d),a[l]=p}o[l].resultBuffer=p.buffer}},_activateAction:function(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){var t=(e._localRoot||this._root).uuid,i=e._clip.uuid,r=this._actionsByClip[i];this._bindAction(e,r&&r.knownActions[0]),this._addInactiveAction(e,i,t)}for(var n=e._propertyBindings,a=0,o=n.length;a!==o;++a){var s=n[a];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}},_deactivateAction:function(e){if(this._isActiveAction(e)){for(var t=e._propertyBindings,i=0,r=t.length;i!==r;++i){var n=t[i];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(e)}},_initMemoryManager:function(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;var e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}},_isActiveAction:function(e){var t=e._cacheIndex;return null!==t&&tthis.max.x||e.ythis.max.y)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y},getParameter:function(e,t){return void 0===t&&(console.warn("THREE.Box2: .getParameter() target is now required"),t=new T),t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return void 0===t&&(console.warn("THREE.Box2: .clampPoint() target is now required"),t=new T),t.copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new T;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}),Bo.prototype=Object.create(he.prototype),Bo.prototype.constructor=Bo,Bo.prototype.isImmediateRenderObject=!0,Fo.prototype=Object.create(Zi.prototype),Fo.prototype.constructor=Fo,Fo.prototype.update=function(){var e=new L,t=new L,i=new P;return function(){var r=["a","b","c"];this.object.updateMatrixWorld(!0),i.getNormalMatrix(this.object.matrixWorld);var n=this.object.matrixWorld,a=this.geometry.attributes.position,o=this.object.geometry;if(o&&o.isGeometry)for(var s=o.vertices,c=o.faces,h=0,l=0,u=c.length;l.99999?this.quaternion.set(0,0,0,1):e.y<-.99999?this.quaternion.set(1,0,0,0):(wo.set(e.z,0,-e.x).normalize(),xo=Math.acos(e.y),this.quaternion.setFromAxisAngle(wo,xo))}),Jo.prototype.setLength=function(e,t,i){void 0===t&&(t=.2*e),void 0===i&&(i=.2*t),this.line.scale.set(1,Math.max(0,e-t),1),this.line.updateMatrix(),this.cone.scale.set(i,t,i),this.cone.position.y=e,this.cone.updateMatrix()},Jo.prototype.setColor=function(e){this.line.material.color.copy(e),this.cone.material.color.copy(e)},Ko.prototype=Object.create(Zi.prototype),Ko.prototype.constructor=Ko,Nn.create=function(e,t){return console.log("THREE.Curve.create() has been deprecated"),e.prototype=Object.create(Nn.prototype),e.prototype.constructor=e,e.prototype.getPoint=t,e},Object.assign(ta.prototype,{createPointsGeometry:function(e){console.warn("THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");var t=this.getPoints(e);return this.createGeometry(t)},createSpacedPointsGeometry:function(e){console.warn("THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");var t=this.getSpacedPoints(e);return this.createGeometry(t)},createGeometry:function(e){console.warn("THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");for(var t=new ve,i=0,r=e.length;i0?i=e[0]:t&&t("VR input not available.")})).catch((function(){console.warn("VRControls: Unable to get VR Displays")})),this.scale=1,this.standing=!1,this.userHeight=1.6,this.getVRDisplay=function(){return i},this.setVRDisplay=function(e){i=e},this.getVRDisplays=function(){return console.warn("VRControls: getVRDisplays() is being deprecated."),r},this.getStandingMatrix=function(){return a},this.update=function(){var t;i&&(i.getFrameData?(i.getFrameData(o),t=o.pose):i.getPose&&(t=i.getPose()),null!==t.orientation&&e.quaternion.fromArray(t.orientation),null!==t.position?e.position.fromArray(t.position):e.position.set(0,0,0),this.standing&&(i.stageParameters?(e.updateMatrix(),a.fromArray(i.stageParameters.sittingToStandingTransform),e.applyMatrix(a)):e.position.setY(e.position.y+this.userHeight)),e.position.multiplyScalar(n.scale))},this.dispose=function(){i=null}},ts=function(e,t){var i,r,n,a,o=new L,s=new L,c=new S,h=new S,l=new S,u=null;"VRFrameData"in window&&(u=new window.VRFrameData),navigator.getVRDisplays&&navigator.getVRDisplays().then((function(e){r=e,e.length>0?i=e[0]:t&&t("HMD not available")})).catch((function(){console.warn("VREffect: Unable to get VR Displays")})),this.isPresenting=!1;var d=this,p=e.getSize(),f=!1,m=e.getPixelRatio();this.getVRDisplay=function(){return i},this.setVRDisplay=function(e){i=e},this.getVRDisplays=function(){return console.warn("VREffect: getVRDisplays() is being deprecated."),r},this.setSize=function(t,r,n){if(p={width:t,height:r},f=n,d.isPresenting){var a=i.getEyeParameters("left");e.setPixelRatio(1),e.setSize(2*a.renderWidth,a.renderHeight,!1)}else e.setPixelRatio(m),e.setSize(t,r,n)};var v=e.domElement,g=[0,0,.5,1],y=[.5,0,.5,1];function A(){var t=d.isPresenting;if(d.isPresenting=void 0!==i&&i.isPresenting,d.isPresenting){var r=i.getEyeParameters("left"),n=r.renderWidth,a=r.renderHeight;t||(m=e.getPixelRatio(),p=e.getSize(),e.setPixelRatio(1),e.setSize(2*n,a,!1))}else t&&(e.setPixelRatio(m),e.setSize(p.width,p.height,f))}window.addEventListener("vrdisplaypresentchange",A,!1),this.setFullScreen=function(e){return new Promise((function(t,r){void 0!==i?d.isPresenting!==e?t(e?i.requestPresent([{source:v}]):i.exitPresent()):t():r(new Error("No VR hardware found."))}))},this.requestPresent=function(){return this.setFullScreen(!0)},this.exitPresent=function(){return this.setFullScreen(!1)},this.requestAnimationFrame=function(e){return void 0!==i?i.requestAnimationFrame(e):window.requestAnimationFrame(e)},this.cancelAnimationFrame=function(e){void 0!==i?i.cancelAnimationFrame(e):window.cancelAnimationFrame(e)},this.submitFrame=function(){void 0!==i&&d.isPresenting&&i.submitFrame()},this.autoSubmitFrame=!0;var x=new Oi;x.layers.enable(1);var w=new Oi;w.layers.enable(2),this.render=function(t,r,p,f){if(i&&d.isPresenting){var m=t.autoUpdate;m&&(t.updateMatrixWorld(),t.autoUpdate=!1),Array.isArray(t)&&(console.warn("VREffect.render() no longer supports arrays. Use object.layers instead."),t=t[0]);var v,A,M=e.getSize(),T=i.getLayers();if(T.length){var S=T[0];v=null!==S.leftBounds&&4===S.leftBounds.length?S.leftBounds:g,A=null!==S.rightBounds&&4===S.rightBounds.length?S.rightBounds:y}else v=g,A=y;if(n={x:Math.round(M.width*v[0]),y:Math.round(M.height*v[1]),width:Math.round(M.width*v[2]),height:Math.round(M.height*v[3])},a={x:Math.round(M.width*A[0]),y:Math.round(M.height*A[1]),width:Math.round(M.width*A[2]),height:Math.round(M.height*A[3])},p?(e.setRenderTarget(p),p.scissorTest=!0):(e.setRenderTarget(null),e.setScissorTest(!0)),(e.autoClear||f)&&e.clear(),null===r.parent&&r.updateMatrixWorld(),r.matrixWorld.decompose(x.position,x.quaternion,x.scale),w.position.copy(x.position),w.quaternion.copy(x.quaternion),w.scale.copy(x.scale),i.getFrameData)i.depthNear=r.near,i.depthFar=r.far,i.getFrameData(u),x.projectionMatrix.elements=u.leftProjectionMatrix,w.projectionMatrix.elements=u.rightProjectionMatrix,function(e){e.pose.orientation?(b.fromArray(e.pose.orientation),c.makeRotationFromQuaternion(b)):c.identity();e.pose.position&&(_.fromArray(e.pose.position),c.setPosition(_));h.fromArray(e.leftViewMatrix),h.multiply(c),l.fromArray(e.rightViewMatrix),l.multiply(c),h.getInverse(h),l.getInverse(l)}(u),x.updateMatrix(),x.matrix.multiply(h),x.matrix.decompose(x.position,x.quaternion,x.scale),w.updateMatrix(),w.matrix.multiply(l),w.matrix.decompose(w.position,w.quaternion,w.scale);else{var R=i.getEyeParameters("left"),L=i.getEyeParameters("right");x.projectionMatrix=E(R.fieldOfView,!0,r.near,r.far),w.projectionMatrix=E(L.fieldOfView,!0,r.near,r.far),o.fromArray(R.offset),s.fromArray(L.offset),x.translateOnAxis(o,x.scale.x),w.translateOnAxis(s,w.scale.x)}return p?(p.viewport.set(n.x,n.y,n.width,n.height),p.scissor.set(n.x,n.y,n.width,n.height)):(e.setViewport(n.x,n.y,n.width,n.height),e.setScissor(n.x,n.y,n.width,n.height)),e.render(t,x,p,f),p?(p.viewport.set(a.x,a.y,a.width,a.height),p.scissor.set(a.x,a.y,a.width,a.height)):(e.setViewport(a.x,a.y,a.width,a.height),e.setScissor(a.x,a.y,a.width,a.height)),e.render(t,w,p,f),p?(p.viewport.set(0,0,M.width,M.height),p.scissor.set(0,0,M.width,M.height),p.scissorTest=!1,e.setRenderTarget(null)):(e.setViewport(0,0,M.width,M.height),e.setScissorTest(!1)),m&&(t.autoUpdate=!0),void(d.autoSubmitFrame&&d.submitFrame())}e.render(t,r,p,f)},this.dispose=function(){window.removeEventListener("vrdisplaypresentchange",A,!1)};var b=new R,_=new L;function E(e,t,i,r){var n=Math.PI/180;return function(e,t,i,r){i=void 0===i?.01:i,r=void 0===r?1e4:r;var n=(t=void 0===t||t)?-1:1,a=new S,o=a.elements,s=function(e){var t=2/(e.leftTan+e.rightTan),i=(e.leftTan-e.rightTan)*t*.5,r=2/(e.upTan+e.downTan);return{scale:[t,r],offset:[i,(e.upTan-e.downTan)*r*.5]}}(e);return o[0]=s.scale[0],o[1]=0,o[2]=s.offset[0]*n,o[3]=0,o[4]=0,o[5]=s.scale[1],o[6]=-s.offset[1]*n,o[7]=0,o[8]=0,o[9]=0,o[10]=r/(i-r)*-n,o[11]=r*i/(i-r),o[12]=0,o[13]=0,o[14]=n,o[15]=0,a.transpose(),a}({upTan:Math.tan(e.upDegrees*n),downTan:Math.tan(e.downDegrees*n),leftTan:Math.tan(e.leftDegrees*n),rightTan:Math.tan(e.rightDegrees*n)},t,i,r)}},is=function(e,t){this.object=e,this.domElement=void 0!==t?t:document,this.enabled=!0,this.target=new L,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.25,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!1,this.keyPanSpeed=7,this.autoRotate=!1,this.autoRotateSpeed=2,this.enableKeys=!0,this.keys={LEFT:37,UP:38,RIGHT:39,BOTTOM:40},this.mouseButtons={ORBIT:b,ZOOM:_,PAN:E},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this.getPolarAngle=function(){return h.phi},this.getAzimuthalAngle=function(){return h.theta},this.saveState=function(){i.target0.copy(i.target),i.position0.copy(i.object.position),i.zoom0=i.object.zoom},this.reset=function(){i.target.copy(i.target0),i.object.position.copy(i.position0),i.object.zoom=i.zoom0,i.object.updateProjectionMatrix(),i.dispatchEvent(r),i.update(),s=o.NONE},this.update=function(){var t=new L,n=(new R).setFromUnitVectors(e.up,new L(0,1,0)),a=n.clone().inverse(),f=new L,m=new R;return function(){var e=i.object.position;return t.copy(e).sub(i.target),t.applyQuaternion(n),h.setFromVector3(t),i.autoRotate&&s===o.NONE&&i.rotateLeft(2*Math.PI/60/60*i.autoRotateSpeed),h.theta+=l.theta,h.phi+=l.phi,h.theta=Math.max(i.minAzimuthAngle,Math.min(i.maxAzimuthAngle,h.theta)),h.phi=Math.max(i.minPolarAngle,Math.min(i.maxPolarAngle,h.phi)),h.makeSafe(),h.radius*=u,h.radius=Math.max(i.minDistance,Math.min(i.maxDistance,h.radius)),i.target.add(d),t.setFromSpherical(h),t.applyQuaternion(a),e.copy(i.target).add(t),i.object.lookAt(i.target),!0===i.enableDamping?(l.theta*=1-i.dampingFactor,l.phi*=1-i.dampingFactor,d.multiplyScalar(1-i.dampingFactor)):(l.set(0,0,0),d.set(0,0,0)),u=1,!!(p||f.distanceToSquared(i.object.position)>c||8*(1-m.dot(i.object.quaternion))>c)&&(i.dispatchEvent(r),f.copy(i.object.position),m.copy(i.object.quaternion),p=!1,!0)}}(),this.dispose=function(){i.domElement.removeEventListener("contextmenu",k,!1),i.domElement.removeEventListener("mousedown",N,!1),i.domElement.removeEventListener("wheel",U,!1),i.domElement.removeEventListener("touchstart",G,!1),i.domElement.removeEventListener("touchend",H,!1),i.domElement.removeEventListener("touchmove",V,!1),document.removeEventListener("mousemove",B,!1),document.removeEventListener("mouseup",F,!1),window.removeEventListener("keydown",z,!1)};var i=this,r={type:"change"},n={type:"start"},a={type:"end"},o={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_DOLLY_PAN:4},s=o.NONE,c=1e-6,h=new Oo,l=new Oo,u=1,d=new L,p=!1,f=new T,m=new T,v=new T,g=new T,y=new T,A=new T,x=new T,w=new T,M=new T;function S(){return Math.pow(.95,i.zoomSpeed)}i.rotateLeft=function(e){l.theta-=e},i.rotateUp=function(e){l.phi-=e};var P=function(){var e=new L;return function(t,i){e.setFromMatrixColumn(i,0),e.multiplyScalar(-t),d.add(e)}}(),C=function(){var e=new L;return function(t,r){!0===i.screenSpacePanning?e.setFromMatrixColumn(r,1):(e.setFromMatrixColumn(r,0),e.crossVectors(i.object.up,e)),e.multiplyScalar(t),d.add(e)}}(),D=function(){var e=new L;return function(t,r){var n=i.domElement===document?i.domElement.body:i.domElement;if(i.object.isPerspectiveCamera){var a=i.object.position;e.copy(a).sub(i.target);var o=e.length();o*=Math.tan(i.object.fov/2*Math.PI/180),P(2*t*o/n.clientHeight,i.object.matrix),C(2*r*o/n.clientHeight,i.object.matrix)}else i.object.isOrthographicCamera?(P(t*(i.object.right-i.object.left)/i.object.zoom/n.clientWidth,i.object.matrix),C(r*(i.object.top-i.object.bottom)/i.object.zoom/n.clientHeight,i.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),i.enablePan=!1)}}();function I(e){i.object.isPerspectiveCamera?u/=e:i.object.isOrthographicCamera?(i.object.zoom=Math.max(i.minZoom,Math.min(i.maxZoom,i.object.zoom*e)),i.object.updateProjectionMatrix(),p=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),i.enableZoom=!1)}function O(e){i.object.isPerspectiveCamera?u*=e:i.object.isOrthographicCamera?(i.object.zoom=Math.max(i.minZoom,Math.min(i.maxZoom,i.object.zoom/e)),i.object.updateProjectionMatrix(),p=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),i.enableZoom=!1)}function N(e){if(!1!==i.enabled){switch(e.preventDefault(),e.button){case i.mouseButtons.ORBIT:if(!1===i.enableRotate)return;!function(e){f.set(e.clientX,e.clientY)}(e),s=o.ROTATE;break;case i.mouseButtons.ZOOM:if(!1===i.enableZoom)return;!function(e){x.set(e.clientX,e.clientY)}(e),s=o.DOLLY;break;case i.mouseButtons.PAN:if(!1===i.enablePan)return;!function(e){g.set(e.clientX,e.clientY)}(e),s=o.PAN}s!==o.NONE&&(document.addEventListener("mousemove",B,!1),document.addEventListener("mouseup",F,!1),i.dispatchEvent(n))}}function B(e){if(!1!==i.enabled)switch(e.preventDefault(),s){case o.ROTATE:if(!1===i.enableRotate)return;!function(e){m.set(e.clientX,e.clientY),v.subVectors(m,f).multiplyScalar(i.rotateSpeed);var t=i.domElement===document?i.domElement.body:i.domElement;i.rotateLeft(2*Math.PI*v.x/t.clientHeight),i.rotateUp(2*Math.PI*v.y/t.clientHeight),f.copy(m),i.update()}(e);break;case o.DOLLY:if(!1===i.enableZoom)return;!function(e){w.set(e.clientX,e.clientY),M.subVectors(w,x),M.y>0?I(S()):M.y<0&&O(S()),x.copy(w),i.update()}(e);break;case o.PAN:if(!1===i.enablePan)return;!function(e){y.set(e.clientX,e.clientY),A.subVectors(y,g).multiplyScalar(i.panSpeed),D(A.x,A.y),g.copy(y),i.update()}(e)}}function F(e){!1!==i.enabled&&(document.removeEventListener("mousemove",B,!1),document.removeEventListener("mouseup",F,!1),i.dispatchEvent(a),s=o.NONE)}function U(e){!1===i.enabled||!1===i.enableZoom||s!==o.NONE&&s!==o.ROTATE||(e.preventDefault(),e.stopPropagation(),i.dispatchEvent(n),function(e){e.deltaY<0?O(S()):e.deltaY>0&&I(S()),i.update()}(e),i.dispatchEvent(a))}function z(e){!1!==i.enabled&&!1!==i.enableKeys&&!1!==i.enablePan&&function(e){switch(e.keyCode){case i.keys.UP:D(0,i.keyPanSpeed),i.update();break;case i.keys.BOTTOM:D(0,-i.keyPanSpeed),i.update();break;case i.keys.LEFT:D(i.keyPanSpeed,0),i.update();break;case i.keys.RIGHT:D(-i.keyPanSpeed,0),i.update()}}(e)}function G(e){if(!1!==i.enabled){switch(e.preventDefault(),e.touches.length){case 1:if(!1===i.enableRotate)return;!function(e){f.set(e.touches[0].pageX,e.touches[0].pageY)}(e),s=o.TOUCH_ROTATE;break;case 2:if(!1===i.enableZoom&&!1===i.enablePan)return;!function(e){if(i.enableZoom){var t=e.touches[0].pageX-e.touches[1].pageX,r=e.touches[0].pageY-e.touches[1].pageY,n=Math.sqrt(t*t+r*r);x.set(0,n)}if(i.enablePan){var a=.5*(e.touches[0].pageX+e.touches[1].pageX),o=.5*(e.touches[0].pageY+e.touches[1].pageY);g.set(a,o)}}(e),s=o.TOUCH_DOLLY_PAN;break;default:s=o.NONE}s!==o.NONE&&i.dispatchEvent(n)}}function V(e){if(!1!==i.enabled)switch(e.preventDefault(),e.stopPropagation(),e.touches.length){case 1:if(!1===i.enableRotate)return;if(s!==o.TOUCH_ROTATE)return;!function(e){m.set(e.touches[0].pageX,e.touches[0].pageY),v.subVectors(m,f).multiplyScalar(i.rotateSpeed);var t=i.domElement===document?i.domElement.body:i.domElement;i.rotateLeft(2*Math.PI*v.x/t.clientHeight),i.rotateUp(2*Math.PI*v.y/t.clientHeight),f.copy(m),i.update()}(e);break;case 2:if(!1===i.enableZoom&&!1===i.enablePan)return;if(s!==o.TOUCH_DOLLY_PAN)return;!function(e){if(i.enableZoom){var t=e.touches[0].pageX-e.touches[1].pageX,r=e.touches[0].pageY-e.touches[1].pageY,n=Math.sqrt(t*t+r*r);w.set(0,n),M.set(0,Math.pow(w.y/x.y,i.zoomSpeed)),I(M.y),x.copy(w)}if(i.enablePan){var a=.5*(e.touches[0].pageX+e.touches[1].pageX),o=.5*(e.touches[0].pageY+e.touches[1].pageY);y.set(a,o),A.subVectors(y,g).multiplyScalar(i.panSpeed),D(A.x,A.y),g.copy(y)}i.update()}(e);break;default:s=o.NONE}}function H(e){!1!==i.enabled&&(i.dispatchEvent(a),s=o.NONE)}function k(e){!1!==i.enabled&&e.preventDefault()}i.domElement.addEventListener("mousedown",N,!1),i.domElement.addEventListener("wheel",U,!1),i.domElement.addEventListener("touchstart",G,!1),i.domElement.addEventListener("touchend",H,!1),i.domElement.addEventListener("touchmove",V,!1),window.addEventListener("keydown",z,!1),this.update()};(is.prototype=Object.create(l.prototype)).constructor=is,Object.defineProperties(is.prototype,{center:{get:function(){return console.warn("OrbitControls: .center has been renamed to .target"),this.target}},noZoom:{get:function(){return console.warn("OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."),!this.enableZoom},set:function(e){console.warn("OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."),this.enableZoom=!e}},noRotate:{get:function(){return console.warn("OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."),!this.enableRotate},set:function(e){console.warn("OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."),this.enableRotate=!e}},noPan:{get:function(){return console.warn("OrbitControls: .noPan has been deprecated. Use .enablePan instead."),!this.enablePan},set:function(e){console.warn("OrbitControls: .noPan has been deprecated. Use .enablePan instead."),this.enablePan=!e}},noKeys:{get:function(){return console.warn("OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."),!this.enableKeys},set:function(e){console.warn("OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."),this.enableKeys=!e}},staticMoving:{get:function(){return console.warn("OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."),!this.enableDamping},set:function(e){console.warn("OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."),this.enableDamping=!e}},dynamicDampingFactor:{get:function(){return console.warn("OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."),this.dampingFactor},set:function(e){console.warn("OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."),this.dampingFactor=e}}});var rs=function(e){var t=this;this.object=e,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation={},this.screenOrientation=0,this.alphaOffset=0;var i=function(e){t.deviceOrientation=e},r=function(){t.screenOrientation=window.orientation||0},n=function(){var e=new L(0,0,1),t=new ie,i=new R,r=new R(-Math.sqrt(.5),0,0,Math.sqrt(.5));return function(n,a,o,s,c){t.set(o,a,-s,"YXZ"),n.setFromEuler(t),n.multiply(r),n.multiply(i.setFromAxisAngle(e,-c))}}();this.connect=function(){r(),window.addEventListener("orientationchange",r,!1),window.addEventListener("deviceorientation",i,!1),t.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",r,!1),window.removeEventListener("deviceorientation",i,!1),t.enabled=!1},this.update=function(){if(!1!==t.enabled){var e=t.deviceOrientation;if(e){var i=e.alpha?M.degToRad(e.alpha)+t.alphaOffset:0,r=e.beta?M.degToRad(e.beta):0,a=e.gamma?M.degToRad(e.gamma):0,o=t.screenOrientation?M.degToRad(t.screenOrientation):0;n(t.object.quaternion,i,r,a,o)}}},this.dispose=function(){t.disconnect()},this.connect()};var ns,as=function(){function e(e){this.object=e.camera,this.domElement=e.canvas,this.orbit=new is(this.object,this.domElement),this.speed=.5,this.orbit.target.set(0,0,-1),this.orbit.enableZoom=!1,this.orbit.enablePan=!1,this.orbit.rotateSpeed=-this.speed,e.orientation&&(this.orientation=new rs(this.object)),e.halfView&&(this.orbit.minAzimuthAngle=-Math.PI/4,this.orbit.maxAzimuthAngle=Math.PI/4)}var t=e.prototype;return t.update=function(){if(this.orientation){this.orientation.update();var e=this.orientation.object.quaternion,t=function(e,t,i,r){var n=e*t+i*r;if(n>.499){var a=2*Math.atan2(e,r);return new L(Math.PI/2,0,a)}if(n<-.499){var o=-2*Math.atan2(e,r);return new L(-Math.PI/2,0,o)}var s=e*e,c=t*t,h=i*i,l=Math.atan2(2*t*r-2*e*i,1-2*c-2*h);return new L(Math.asin(2*n),Math.atan2(2*e*r-2*t*i,1-2*s-2*h),l)}(e.x,e.y,e.z,e.w);void 0===this.lastAngle_&&(this.lastAngle_=t),this.orbit.rotateLeft((this.lastAngle_.z-t.z)*(1+this.speed)),this.orbit.rotateUp((this.lastAngle_.y-t.y)*(1+this.speed)),this.lastAngle_=t}this.orbit.update()},t.dispose=function(){this.orbit.dispose(),this.orientation&&this.orientation.dispose()},e}(),os=((ns=t.createElement("video")).crossOrigin="anonymous",ns.hasAttribute("crossorigin")),ss=["360","360_LR","360_TB","360_CUBE","EAC","EAC_LR","NONE","AUTO","Sphere","Cube","equirectangular","180","180_LR","180_MONO"],cs=function(e){if(e){if(e=e.toString().trim(),/sphere/i.test(e))return"360";if(/cube/i.test(e))return"360_CUBE";if(/equirectangular/i.test(e))return"360";for(var t=0;t=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function fs(e,t){(null==t||t>e.length)&&(t=e.length);for(var i=0,r=new Array(t);ihttp://webvr.info for more info."},"web-vr-not-supported":{headline:"360 not supported on this device",type:"360_NOT_SUPPORTED",message:"Your browser does not support 360. See http://webvr.info for assistance."},"web-vr-hls-cors-not-supported":{headline:"360 HLS video not supported on this device",type:"360_NOT_SUPPORTED",message:"Your browser/device does not support HLS 360 video. See http://webvr.info for assistance."}},gs=i.getPlugin("plugin"),ys=i.getComponent("Component"),As=function(r){function n(e,t){var n,a=i.mergeOptions(ms,t);return(n=r.call(this,e,a)||this).options_=a,n.player_=e,n.bigPlayButtonIndex_=e.children().indexOf(e.getChild("BigPlayButton"))||0,n.videojsErrorsSupport_=!!i.errors,n.videojsErrorsSupport_&&e.errors({errors:vs}),i.browser.IE_VERSION||!os?(n.player_.on("loadstart",(function(){n.triggerError_({code:"web-vr-not-supported",dismiss:!1})})),o(n)):(n.polyfill_=new h({ROTATE_INSTRUCTIONS_DISABLED:!0}),n.polyfill_=new h,n.handleVrDisplayActivate_=i.bind(o(n),n.handleVrDisplayActivate_),n.handleVrDisplayDeactivate_=i.bind(o(n),n.handleVrDisplayDeactivate_),n.handleResize_=i.bind(o(n),n.handleResize_),n.animate_=i.bind(o(n),n.animate_),n.setProjection(n.options_.projection),n.on(e,"adstart",(function(){return e.setTimeout((function(){e.ads&&e.ads.videoElementRecycled()?(n.log("video element recycled for this ad, reseting"),n.reset(),n.one(e,"playing",n.init)):n.log("video element not recycled for this ad, no need to reset")}))}),1),n.on(e,"loadedmetadata",n.init),n)}c(n,r);var a=n.prototype;return a.changeProjection_=function(e){var t=this;(e=cs(e))||(e="NONE");var i=0,r=0,n=0;if(this.scene&&this.scene.remove(this.movieScreen),"AUTO"===e){if(this.player_.mediainfo&&this.player_.mediainfo.projection&&"AUTO"!==this.player_.mediainfo.projection){var a=cs(this.player_.mediainfo.projection);return this.changeProjection_(a)}return this.changeProjection_("NONE")}if("360"===e)this.movieGeometry=new tn(256,this.options_.sphereDetail,this.options_.sphereDetail),this.movieMaterial=new je({map:this.videoTexture,overdraw:!0,side:1}),this.movieScreen=new Qe(this.movieGeometry,this.movieMaterial),this.movieScreen.position.set(i,r,n),this.movieScreen.scale.x=-1,this.movieScreen.quaternion.setFromAxisAngle({x:0,y:1,z:0},-Math.PI/2),this.scene.add(this.movieScreen);else if("360_LR"===e||"360_TB"===e){for(var o=new en(256,this.options_.sphereDetail,this.options_.sphereDetail),s=o.faceVertexUvs[0],c=0;cy&&(y=x.y)}for(var w,b=ps(m);!(w=b()).done;){var _=w.value;Math.abs(_.y-g)0&&(t.log("Displays found",e),t.vrDisplay=e[0],t.vrDisplay.isPolyfilled||(t.log("Real HMD found using VRControls",t.vrDisplay),t.addCardboardButton_(),t.controls3d=new es(t.camera))),!t.controls3d){t.log("no HMD found Using Orbit & Orientation Controls");var r={camera:t.camera,canvas:t.renderedCanvas,halfView:0===t.currentProjection_.indexOf("180"),orientation:i.browser.IS_IOS||i.browser.IS_ANDROID||!1};!1===t.options_.motionControls&&(r.orientation=!1),t.controls3d=new as(r),t.canvasPlayerControls=new hs(t.player_,t.renderedCanvas,t.options_)}t.animationFrameId_=t.requestAnimationFrame(t.animate_)}))):e.navigator.getVRDevices?this.triggerError_({code:"web-vr-out-of-date",dismiss:!1}):this.triggerError_({code:"web-vr-not-supported",dismiss:!1}),this.options_.omnitone){var o=to();this.omniController=new ls(o,this.options_.omnitone,this.getVideoEl_(),this.options_.omnitoneOptions),this.omniController.one("audiocontext-suspended",(function(){t.player.pause(),t.player.one("playing",(function(){o.resume()}))}))}this.on(this.player_,"fullscreenchange",this.handleResize_),e.addEventListener("vrdisplaypresentchange",this.handleResize_,!0),e.addEventListener("resize",this.handleResize_,!0),e.addEventListener("vrdisplayactivate",this.handleVrDisplayActivate_,!0),e.addEventListener("vrdisplaydeactivate",this.handleVrDisplayDeactivate_,!0),this.initialized_=!0,this.trigger("initialized")},a.addCardboardButton_=function(){this.player_.controlBar.getChild("CardboardButton")||this.player_.controlBar.addChild("CardboardButton",{})},a.getVideoEl_=function(){return this.player_.el().getElementsByTagName("video")[0]},a.reset=function(){if(this.initialized_){this.omniController&&(this.omniController.off("audiocontext-suspended"),this.omniController.dispose(),this.omniController=void 0),this.controls3d&&(this.controls3d.dispose(),this.controls3d=null),this.canvasPlayerControls&&(this.canvasPlayerControls.dispose(),this.canvasPlayerControls=null),this.effect&&(this.effect.dispose(),this.effect=null),e.removeEventListener("resize",this.handleResize_,!0),e.removeEventListener("vrdisplaypresentchange",this.handleResize_,!0),e.removeEventListener("vrdisplayactivate",this.handleVrDisplayActivate_,!0),e.removeEventListener("vrdisplaydeactivate",this.handleVrDisplayDeactivate_,!0),this.player_.getChild("BigPlayButton")||this.player_.addChild("BigPlayButton",{},this.bigPlayButtonIndex_),this.player_.getChild("BigVrPlayButton")&&this.player_.removeChild("BigVrPlayButton"),this.player_.getChild("CardboardButton")&&this.player_.controlBar.removeChild("CardboardButton"),i.browser.IS_IOS&&this.player_.controlBar&&this.player_.controlBar.fullscreenToggle&&this.player_.controlBar.fullscreenToggle.show();var t=this.getVideoEl_().style;t.zIndex="",t.opacity="",this.currentProjection_=this.defaultProjection_,this.iosRevertTouchToClick_&&this.iosRevertTouchToClick_(),this.renderedCanvas&&this.renderedCanvas.parentNode.removeChild(this.renderedCanvas),this.animationFrameId_&&this.cancelAnimationFrame(this.animationFrameId_),this.initialized_=!1}},a.dispose=function(){r.prototype.dispose.call(this),this.reset()},a.polyfillVersion=function(){return h.version},n}(gs);return As.prototype.setTimeout=ys.prototype.setTimeout,As.prototype.clearTimeout=ys.prototype.clearTimeout,As.VERSION="1.8.0",i.registerPlugin("vr",As),As})); diff --git a/pod/main/templates/base.html b/pod/main/templates/base.html index 264e831df5..3573b77545 100644 --- a/pod/main/templates/base.html +++ b/pod/main/templates/base.html @@ -72,9 +72,9 @@
- {%if MAINTENANCE_SHEDULED%} + {% if MAINTENANCE_SHEDULED and not request.GET.is_iframe %}
{{MAINTENANCE_TEXT_SHEDULED|safe}}
- {%endif%} + {% endif %}