From cd5a9721819c7dc09e5989d837ed47c6c496b5ff Mon Sep 17 00:00:00 2001 From: "Nathan C." <149914029+Natuworkguy@users.noreply.github.com> Date: Mon, 28 Sep 2026 23:33:12 -0700 Subject: [PATCH 1/8] Add Flash Web docs and fix bugs --- flash/system_prompt.txt | 2 +- flash/theme.py | 14 + flash/tools.py | 229 +++++++- flash/voice.py | 51 +- flash/web.py | 120 +++- flash/web/index.html | 1242 +++++++++++++++++++++++++++++++++++++-- flash/workspace.py | 63 +- tests/test_voice.py | 62 +- tests/test_web.py | 249 +++++++- 9 files changed, 1928 insertions(+), 104 deletions(-) diff --git a/flash/system_prompt.txt b/flash/system_prompt.txt index a541b5d..7f20172 100644 --- a/flash/system_prompt.txt +++ b/flash/system_prompt.txt @@ -42,7 +42,7 @@ A new file too long for one call is written in pieces: the first with no `append == Sending what you make == The user sees only what you send. `view_image` and `screenshot` show a file to you, never to them, and an image in a tool result is one you looked at, not one the user gave you. -When you make an image, a PDF, or a web page for the user, send it the moment it is finished, without being asked: `send_image` for a picture, `send_pdf` for a PDF, `send_html` for a page. Every revision is a new version: send it again each time, and never just view it and describe the change. +When you make an image, a PDF, a web page, or a document for the user, send it the moment it is finished, without being asked: `send_image` for a picture, `send_pdf` for a PDF, `send_html` for a page, `send_document` for Markdown or text. The user can edit a document you send and comment on it; when they do, read the file again before you change it, and answer each comment. When a document you send has unfinished parts, gaps, or open questions, say so in comments on those passages rather than leaving them to be found. Every revision is a new version: send it again each time, and never just view it and describe the change. Check before you send, and check for the exact problem the user reported (overlapping lines, a wrong arrow, cut-off text). If you can still see it, or cannot tell, say so plainly. Never tell the user a problem is fixed because you changed the code meant to fix it: it is fixed when you looked and it was gone. diff --git a/flash/theme.py b/flash/theme.py index f5d8a1b..7d9d0fe 100644 --- a/flash/theme.py +++ b/flash/theme.py @@ -329,6 +329,20 @@ def tool_file(path: str) -> bool: return True +def tool_document(path: str, comments: list[dict]) -> bool: + """Hand a document to whoever is drawing, with the agent's comments + on it: each a quote from the document and a note about it. + + True when something took it, as with `tool_file`. + """ + + sink = _sink() + if sink is None: + return False + sink("document", json.dumps({"path": path, "comments": comments}), "") + return True + + def tool_plan(steps: list[dict]) -> bool: """Hand the plan's checklist to whoever is drawing, as its steps. diff --git a/flash/tools.py b/flash/tools.py index f87eddb..90c7ecd 100644 --- a/flash/tools.py +++ b/flash/tools.py @@ -61,6 +61,7 @@ plural, remote_answer, tool_diff, + tool_document, tool_file, tool_line, tool_result, @@ -120,9 +121,15 @@ To hand the user a finished web page, use the send_html tool with its path. It opens in their browser, or beside the chat in the web UI. Screenshot it first and send it once it looks right. -When you make an image, PDF, or web page for the user, send it with the - matching tool as soon as it is finished, without being asked: that is - how they see it. +To hand the user a Markdown or text document (a report, plan, README, + notes), use the send_document tool with its path. In the web UI it + opens beside the chat, where they can edit it and comment on it; their + comments reach you as a message that quotes each passage. To flag + unfinished work, a gap, or a question in it, pass comments, each + quoting the words it is about. +When you make an image, PDF, web page, or document for the user, send it + with the matching tool as soon as it is finished, without being asked: + that is how they see it. To see how a web page actually renders, use the screenshot tool on the .html file you wrote or on a URL. It runs a headless browser and attaches the picture, so it is the only way to check a page you built; @@ -2407,6 +2414,163 @@ def send_html(path: str, caption: str = "") -> str: ) +DOCUMENT_SUFFIXES = (".md", ".markdown", ".txt") +MAX_DOCUMENT_BYTES = 2 * 1024 * 1024 +MAX_DOC_COMMENTS = 20 +MAX_QUOTE_CHARS = 300 +MAX_NOTE_CHARS = 1000 + +_MD_LINK = re.compile(r"!?\[([^\]]*)\]\([^)]*\)") +_MD_LINE_MARK = re.compile( + r"^[ \t]*(?:#{1,6}[ \t]+|>[ \t]?|[-*+][ \t]+|\d+[.)][ \t]+)", re.M +) +_MD_INLINE_MARK = re.compile(r"|\*\*|__|~~|`|(?|.+-])") + + +def _plain(text: str) -> str: + """Text as the page shows it: Markdown's marks gone, spaces single. + + A comment quotes words as they read, and the model may copy them + from the file with their marks or without, so both are compared + this way.""" + + text = _MD_LINK.sub(r"\1", text) + text = _MD_LINE_MARK.sub("", text) + text = _MD_INLINE_MARK.sub("", text) + text = _MD_ESCAPE.sub(r"\1", text) + return " ".join(text.split()) + + +def _doc_comments( + raw: Any, text: str, +) -> tuple[list[dict], list[str]]: + """The comments the model left on a document, cleaned, and a line + for each one whose quote is not in the document. + + A quote that is not found still goes: the page shows it as a note + on the whole document.""" + + if isinstance(raw, str): + try: + raw = json.loads(raw) if raw.strip() else [] + except json.JSONDecodeError: + return [], ["comments was not a list; none were added"] + if isinstance(raw, dict): + raw = [raw] + if not isinstance(raw, list): + return [], ["comments was not a list; none were added"] + + plain_text = _plain(text) + flat_text = " ".join(text.split()) + comments: list[dict] = [] + missing: list[str] = [] + for item in raw[:MAX_DOC_COMMENTS]: + if not isinstance(item, dict): + continue + quote = str(item.get("quote") or "").strip()[:MAX_QUOTE_CHARS] + note = str( + item.get("note") or item.get("comment") or item.get("text") or "" + ).strip()[:MAX_NOTE_CHARS] + if not note: + continue + comments.append({"quote": quote, "note": note}) + if quote and " ".join(quote.split()) not in flat_text and ( + _plain(quote) not in plain_text + ): + missing.append( + f'comment {len(comments)} quotes "{quote[:60]}", which is ' + "not in the document word for word, so it shows without " + "a place" + ) + return comments, missing + + +def send_document( + path: str, caption: str = "", comments: Any = None, +) -> str: + """Put a Markdown or text document in front of the user, with any + comments the model left on its passages.""" + + tool_line(f"SendDocument({path})") + + doc = Path(path).expanduser() + problem = "" + size = 0 + if not doc.is_file(): + problem = f"no file at {doc}" + elif doc.suffix.lower() not in DOCUMENT_SUFFIXES: + problem = f"{doc.name} is not a .md or .txt file" + else: + try: + size = doc.stat().st_size + doc.read_bytes().decode("utf-8") + except OSError as exc: + problem = f"could not read {doc}: {exc}" + except UnicodeDecodeError: + problem = f"{doc.name} is not UTF-8 text" + else: + if size > MAX_DOCUMENT_BYTES: + problem = ( + f"{doc.name} is {size // 1024} KB; the limit is " + f"{MAX_DOCUMENT_BYTES // (1024 * 1024)} MB" + ) + + if problem: + result = f"Error: {problem}." + tool_result(result, style=ERROR) + return result + + kilobytes = max(1, round(size / 1024)) + note = caption.strip() + label = f"{doc.name} ({kilobytes} KB)" + (f": {note}" if note else "") + left, missing = _doc_comments( + comments, doc.read_text(encoding="utf-8") + ) + count = len(left) + if count: + label += f", {count} comment{'' if count == 1 else 's'}" + unplaced = f" To fix: {'; '.join(missing)}." if missing else "" + pinned = ( + f" Your {count} comment{'' if count == 1 else 's'} show" + f"{'s' if count == 1 else ''} on the passages quoted." + if count else "" + ) + + shown = tool_document(str(doc), left) if left else tool_file(str(doc)) + if shown: + tool_result(label) + return ( + f"Sent {doc.name} ({kilobytes} KB) to the user's screen, " + f"beside the chat.{pinned} They can edit it there, and " + "saving writes the file. Their comments come to you as a " + f"message quoting each passage.{unplaced}" + ) + + problem = _open_with_spinner(doc) + tool_result(label + (f" ({problem})" if problem else "")) + console.print( + Text(f"{' ' * RESULT_INDENT}{_display_path(doc)}", style=DIM) + ) + # The app it opens in has no place for them: they print under it. + for item in left: + where = f'"{item["quote"]}": ' if item["quote"] else "" + console.print( + Text(f"{' ' * RESULT_INDENT}{where}{item['note']}", style=DIM) + ) + + if problem: + return ( + f"Could not open {doc.name}: {problem}. Its path is on " + "screen; tell the user where the file is." + ) + return ( + f"Sent {doc.name} ({kilobytes} KB). It opened in the user's " + "default app for it, with its path on screen" + + (", and your comments printed under it." if left else ".") + ) + + DEFAULT_SCREENSHOT_WIDTH = 1280 DEFAULT_SCREENSHOT_HEIGHT = 800 MIN_SCREENSHOT_SIDE = 200 @@ -3089,6 +3253,64 @@ def interact( }, }, }, + { + "type": "function", + "function": { + "name": "send_document", + "description": ( + "Show a Markdown or text document (.md, .markdown, .txt) " + "to the user: a report, plan, README, or notes you wrote. " + "In the web UI it opens beside the chat, rendered, where " + "they can edit it and comment on passages; their comments " + "reach you as a message quoting each one. Write the file " + "first; this only shows it. To flag something for them in " + "it (unfinished work, a gap to fill, an open question, an " + "assumption to check), add comments pinned to passages." + ), + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Path to the document.", + }, + "caption": { + "type": "string", + "description": ( + "Optional single line shown with it." + ), + }, + "comments": { + "type": "array", + "description": ( + "Optional notes for the user, each pinned to " + "a passage: what is unfinished, missing, or " + "needs their decision there." + ), + "items": { + "type": "object", + "properties": { + "quote": { + "type": "string", + "description": ( + "A few words from the document, " + "exactly as they read, marking " + "the passage." + ), + }, + "note": { + "type": "string", + "description": "What to tell them.", + }, + }, + "required": ["quote", "note"], + }, + }, + }, + "required": ["path"], + }, + }, + }, { "type": "function", "function": { @@ -3693,6 +3915,7 @@ def interact( "send_image": send_image, "send_pdf": send_pdf, "send_html": send_html, + "send_document": send_document, "screenshot": screenshot, "open_page": open_page, "interact": interact, diff --git a/flash/voice.py b/flash/voice.py index 7842ff5..4bb678b 100644 --- a/flash/voice.py +++ b/flash/voice.py @@ -22,6 +22,7 @@ from collections.abc import Callable from dataclasses import dataclass from pathlib import Path +from typing import Optional from urllib.error import URLError from urllib.request import Request, urlopen @@ -258,8 +259,23 @@ def web_missing() -> list[str]: return [p for p in missing_packages() if p != "sounddevice"] -def _download(url: str, out: Path, label: str, on_progress: Progress) -> str: - """Stream `url` to `out`, reporting percent complete as it goes.""" +# What a download returns when it was called off: not a failure to +# report, and nothing of it is left on disk. +CANCELLED = "cancelled" + + +class _Stopped(Exception): + """The download was called off between chunks.""" + + +def _download( + url: str, out: Path, label: str, on_progress: Progress, + stop: Optional[threading.Event] = None, +) -> str: + """Stream `url` to `out`, reporting percent complete as it goes. + + Setting `stop` calls it off at the next chunk, a moment at most, and + it returns CANCELLED with the part it had deleted.""" out.parent.mkdir(parents=True, exist_ok=True) part = out.with_suffix(out.suffix + ".part") @@ -274,6 +290,8 @@ def _download(url: str, out: Path, label: str, on_progress: Progress) -> str: with part.open("wb") as handle: while True: + if stop is not None and stop.is_set(): + raise _Stopped chunk = response.read(DOWNLOAD_CHUNK) if not chunk: break @@ -284,6 +302,9 @@ def _download(url: str, out: Path, label: str, on_progress: Progress) -> str: on_progress(label, percent) part.replace(out) + except _Stopped: + part.unlink(missing_ok=True) + return CANCELLED except (URLError, OSError, ValueError) as exc: part.unlink(missing_ok=True) return f"could not download {label}: {exc}" @@ -310,7 +331,9 @@ def _unpack(archive: Path, into: Path) -> str: return "" -def ensure_models(on_progress: Progress) -> str: +def ensure_models( + on_progress: Progress, stop: Optional[threading.Event] = None, +) -> str: """Download whatever voice mode is missing. Returns "" when ready. Both models are large enough that the download is worth showing, so @@ -321,11 +344,13 @@ def ensure_models(on_progress: Progress) -> str: if models_present(): return "" - return (download_listening(vosk_model(), on_progress) - or download_voice(piper_voice(), on_progress)) + return (download_listening(vosk_model(), on_progress, stop) + or download_voice(piper_voice(), on_progress, stop)) -def download_listening(name: str, on_progress: Progress) -> str: +def download_listening( + name: str, on_progress: Progress, stop: Optional[threading.Event] = None, +) -> str: """Fetch and unpack the Vosk model NAME. Returns "" once it is in.""" if listening_installed(name): @@ -335,6 +360,7 @@ def download_listening(name: str, on_progress: Progress) -> str: archive = MODELS_DIR / f"{name}.zip" why = _download( f"{VOSK_BASE}/{name}.zip", archive, "listening model", on_progress, + stop, ) if why: return why @@ -351,7 +377,9 @@ def download_listening(name: str, on_progress: Progress) -> str: return "" -def download_voice(name: str, on_progress: Progress) -> str: +def download_voice( + name: str, on_progress: Progress, stop: Optional[threading.Event] = None, +) -> str: """Fetch the Piper voice NAME, network and settings. Returns "" once it is in.""" @@ -368,8 +396,13 @@ def download_voice(name: str, on_progress: Progress) -> str: onnx, config = piper_paths(name) MODELS_DIR.mkdir(parents=True, exist_ok=True) - return (_download(onnx_url, onnx, "voice", on_progress) - or _download(config_url, config, "voice settings", on_progress)) + why = (_download(onnx_url, onnx, "voice", on_progress, stop) + or _download(config_url, config, "voice settings", on_progress, + stop)) + # Called off between its two files: no voice without its settings. + if why == CANCELLED: + onnx.unlink(missing_ok=True) + return why def remove_listening(name: str) -> None: diff --git a/flash/web.py b/flash/web.py index 7aba5f6..f8c07f8 100644 --- a/flash/web.py +++ b/flash/web.py @@ -442,6 +442,13 @@ def sign_out_others(self, keep: str) -> list[str]: self.token = secrets.token_urlsafe(24) return keys + def new_token(self) -> str: + """End the link and make another. Signed-in browsers stay.""" + + with self._lock: + self.token = secrets.token_urlsafe(24) + return self.token + def listing(self, current: str, watching: set) -> list[dict]: """The signed-in browsers, as the page shows them, newest first.""" @@ -630,10 +637,16 @@ class Session: def __init__(self, hub: Optional[Hub] = None) -> None: self.hub = hub or Hub() self.lan = False + # Documents the user edited in the page since each chat's last + # turn: chat id -> the paths, told to the model with its next + # message so it reads them again rather than writing over them. + self.edited: dict[str, list[str]] = {} # The voice models are being downloaded for the page: the first # use's pair, or one model picked in Settings, (kind, name). self.voice_setup = False self.voice_job: Optional[tuple[str, str]] = None + # Set to call off whichever of those is running. + self.voice_stop = threading.Event() # The link's token and the browsers signed in with it. A server # restarted after an update takes over the old one's (Server). self.access = Access() @@ -647,7 +660,7 @@ def __init__(self, hub: Optional[Hub] = None) -> None: # Starts this same `flash --web` again, as whatever version is # installed now. Only a server that owns its process can: one # beside a terminal session would take the session down with it. - self.restart: Optional[Callable[[], None]] = None + self.restart: Optional[Callable[..., None]] = None # Opens the server again listening on the network, or not. Set # by whatever runs the server (see _attach). self.switch_lan: Optional[Callable[[bool], None]] = None @@ -755,6 +768,7 @@ def set_up_voice(self) -> None: if self.voice_setup or self.voice_job: return self.voice_setup = True + self.voice_stop.clear() def run() -> None: said: dict[str, int] = {} @@ -769,13 +783,15 @@ def progress(label: str, percent: int) -> None: why = "" try: - why = voice.ensure_models(progress) + why = voice.ensure_models(progress, self.voice_stop) finally: with self._lock: self.voice_setup = False - self.hub.publish( - {"type": "voice-setup", "done": True, "error": why} - ) + cancelled = why == voice.CANCELLED + self.hub.publish({ + "type": "voice-setup", "done": True, + "error": "" if cancelled else why, "cancelled": cancelled, + }) threading.Thread(target=run, daemon=True).start() @@ -790,6 +806,7 @@ def fetch_voice_model(self, kind: str, name: str) -> None: if self.voice_setup or self.voice_job: raise ValueError("A voice model is already downloading.") self.voice_job = (kind, name) + self.voice_stop.clear() def run() -> None: said: list[int] = [-1] @@ -806,7 +823,7 @@ def progress(label: str, percent: int) -> None: try: fetch = (voice.download_listening if kind == "listening" else voice.download_voice) - why = fetch(name, progress) + why = fetch(name, progress, self.voice_stop) if not why: ai.set_config_var(VOICE_SETTINGS[kind], name) except Exception as exc: # noqa: BLE001 @@ -814,13 +831,25 @@ def progress(label: str, percent: int) -> None: finally: with self._lock: self.voice_job = None + cancelled = why == voice.CANCELLED self.hub.publish({ "type": "voice-model", "kind": kind, "name": name, - "done": True, "error": why, + "done": True, "error": "" if cancelled else why, + "cancelled": cancelled, }) threading.Thread(target=run, daemon=True).start() + def cancel_voice_download(self) -> bool: + """Call off the voice download running, if one is. True when one + was: it stops at its next chunk and says so to every page.""" + + with self._lock: + running = self.voice_setup or self.voice_job is not None + if running: + self.voice_stop.set() + return running + # Sub-agents ---------------------------------------------------- def adopt(self, chat: Chat, agent_ids: set) -> None: @@ -1245,9 +1274,12 @@ def sink(kind: str, text: str, style: str) -> None: session.emit(chat, {"type": "diff", "text": text}) elif kind == "plan": session.emit(chat, {"type": "plan", "steps": json.loads(text)}) - elif kind == "file": + elif kind in ("file", "document"): + shown = json.loads(text) if kind == "document" else {"path": text} try: - kept = workspace.keep_file(text) + kept = workspace.keep_file(shown["path"]) + if shown.get("comments"): + kept["comments"] = shown["comments"] session.emit(chat, {"type": "file", **kept}) except (workspace.WorkspaceError, OSError) as exc: session.emit(chat, { @@ -1325,6 +1357,17 @@ def project_prompt(found: "workspace.Project") -> str: return "\n".join(lines) +def edited_note(paths: list[str]) -> str: + """What the model is told about documents the user edited by hand.""" + + names = ", ".join(paths) + return ( + f"[The user edited {names} in the side panel and saved it. Read " + "it again before you change it: their version is the one that " + "counts.]" + ) + + def attachments(files: Optional[list]) -> list[dict]: """The files a message carries, as the page shows them: those that are really there, and no more than MAX_ATTACHMENTS.""" @@ -1392,6 +1435,11 @@ def run_turn( # its own sub-agents and never another chat's. owned = session.owned(chat.id) news, delivered = subagents.notices(owned) if owned else ("", []) + edited = session.edited.pop(chat.id, []) + if edited: + news = "\n\n".join( + part for part in (news, edited_note(edited)) if part + ) said, images = outgoing(ai, text, files) if images and not model_sees_images(ai.Config.host, ai.Config.model): session.emit(chat, {"type": "note", "text": ( @@ -1918,6 +1966,23 @@ def command(session: Session, body: dict, browser: str = "") -> dict: threading.Timer(RESTART_DELAY, session.restart).start() return session.updates.snapshot() + if name == "server-restart": + # From the page's shortcut: Flash started again, with a new link. + # The page is handed the new token to come back in with. + if session.restart is None: + raise ValueError( + "This Flash runs beside a terminal session. Quit it there " + "and start it again." + ) + if any(c.busy or c.queued for c in session.chats.values()): + raise ValueError("Wait for the reply to finish first.") + token = session.access.new_token() + threading.Timer( + RESTART_DELAY, session.restart, + ("Restarting, as asked from the page. The new link follows.",), + ).start() + return {"token": token} + if name == "skills": return {"skills": [ { @@ -2013,6 +2078,9 @@ def command(session: Session, body: dict, browser: str = "") -> dict: if name == "voice-models": return voice_models(session) + if name == "voice-cancel": + return {"cancelling": session.cancel_voice_download()} + if name in ("voice-model", "voice-model-remove"): kind = str(body.get("kind") or "") if kind not in VOICE_KINDS: @@ -2138,6 +2206,16 @@ def command(session: Session, body: dict, browser: str = "") -> dict: if name == "dirs": return {"dirs": workspace.folder_suggestions(arg)} + if name == "document-save": + saved = workspace.save_document(arg, str(body.get("text") or "")) + # Told to the model with the chat's next message. + where = saved["path"] or arg + if chat_id in session.chats: + listed = session.edited.setdefault(chat_id, []) + if where not in listed: + listed.append(where) + return saved + if name == "undo": message = checkpoint.undo() if chat_id in session.chats: @@ -2575,8 +2653,10 @@ def __init__( lan: bool = False, ): # Set before binding: a port already in use makes the base class - # call server_close() from inside its own __init__. + # call server_close() from inside its own __init__, before any of + # the rest is set up. self.closing = threading.Event() + self.keep_session = False super().__init__((LAN_HOST if lan else HOST, port), Handler) # Cookies ignore the port, so two servers on one machine each # need a name of their own. @@ -2596,7 +2676,6 @@ def __init__( self.swapping = False self.swapped = threading.Event() self.replacement: Optional[Server] = None - self.keep_session = False @property def port(self) -> int: @@ -2637,9 +2716,14 @@ def network_url(self) -> Optional[str]: def server_close(self) -> None: self.closing.set() - self.session.hub.close() - if not self.keep_session: - self.session.close() + # No session yet when the port could not be had: there is nothing + # to close but the socket, and the OSError that says why has to + # get out. + session = getattr(self, "session", None) + if session is not None: + session.hub.close() + if not self.keep_session: + session.close() super().server_close() @@ -2743,7 +2827,9 @@ def _listen( RESTART_DELAY = 0.4 -def _restart(server: "Server") -> None: +def _restart( + server: "Server", why: str = "Restarting to finish the update.", +) -> None: """Start this `flash --web` again as the version now installed. exec replaces the process in place: the same port, the same @@ -2759,7 +2845,7 @@ def _restart(server: "Server") -> None: args.append("--lan") if "--no-open" not in args: args.append("--no-open") - console.print(Text("Restarting to finish the update.", style=DIM)) + console.print(Text(why, style=DIM)) os.execv( # nosec B606 -- this same interpreter, running Flash again sys.executable, [sys.executable, "-m", "flash", *args] ) @@ -2814,7 +2900,7 @@ def _attach(server: "Server", standalone: bool) -> None: # Windows cannot replace a running Flash at all: its update # finishes after this one quits, so there is nothing to # restart. - session.restart = lambda: _restart(server) + session.restart = lambda *why: _restart(server, *why) session.updates.can_restart = True else: _background = server diff --git a/flash/web/index.html b/flash/web/index.html index a7250b5..ea2f311 100644 --- a/flash/web/index.html +++ b/flash/web/index.html @@ -6,6 +6,9 @@ Flash + + " + f"" + "
" + ) diff --git a/flash/system_prompt.txt b/flash/system_prompt.txt index 7f20172..8cc0da5 100644 --- a/flash/system_prompt.txt +++ b/flash/system_prompt.txt @@ -42,7 +42,7 @@ A new file too long for one call is written in pieces: the first with no `append == Sending what you make == The user sees only what you send. `view_image` and `screenshot` show a file to you, never to them, and an image in a tool result is one you looked at, not one the user gave you. -When you make an image, a PDF, a web page, or a document for the user, send it the moment it is finished, without being asked: `send_image` for a picture, `send_pdf` for a PDF, `send_html` for a page, `send_document` for Markdown or text. The user can edit a document you send and comment on it; when they do, read the file again before you change it, and answer each comment. When a document you send has unfinished parts, gaps, or open questions, say so in comments on those passages rather than leaving them to be found. Every revision is a new version: send it again each time, and never just view it and describe the change. +When you make an image, a PDF, a web page, a document, or a 3D model for the user, send it the moment it is finished, without being asked: `send_image` for a picture, `send_pdf` for a PDF, `send_html` for a page, `send_document` for Markdown or text. A 3D model is made and shown in one step with `make_3d_model`; use `send_3d_model` for a .glb, .stl, or .obj file that already exists. The user can edit a document you send and comment on it; when they do, read the file again before you change it, and answer each comment. When a document you send has unfinished parts, gaps, or open questions, say so in comments on those passages rather than leaving them to be found. Every revision is a new version: send it again each time, and never just view it and describe the change. Check before you send, and check for the exact problem the user reported (overlapping lines, a wrong arrow, cut-off text). If you can still see it, or cannot tell, say so plainly. Never tell the user a problem is fixed because you changed the code meant to fix it: it is fixed when you looked and it was gone. diff --git a/flash/tools.py b/flash/tools.py index b4edba0..038b09e 100644 --- a/flash/tools.py +++ b/flash/tools.py @@ -28,7 +28,15 @@ from rich.text import Text from . import agent as subagents -from . import checkpoint, editor, extensions, learning, plan, skills +from . import ( + checkpoint, + editor, + extensions, + learning, + model3d, + plan, + skills, +) from .browser import ( ACTIONS, MAX_ELEMENTS, @@ -130,6 +138,11 @@ comments reach you as a message that quotes each passage. To flag unfinished work, a gap, or a question in it, pass comments, each quoting the words it is about. +To make a 3D model (an object, a prop, a room, a layout), use the + make_3d_model tool: it builds the model from parts such as boxes, + cylinders, spheres, lathed profiles, and extruded outlines, saves a + .glb, and shows it in a 3D viewer. Use send_3d_model to show a .glb, + .stl, or .obj file that already exists. When you make an image, PDF, web page, or document for the user, send it with the matching tool as soon as it is finished, without being asked: that is how they see it. @@ -2419,6 +2432,7 @@ def send_html(path: str, caption: str = "") -> str: DOCUMENT_SUFFIXES = (".md", ".markdown", ".txt") MAX_DOCUMENT_BYTES = 2 * 1024 * 1024 +MAX_MODEL_BYTES = 50 * 1024 * 1024 MAX_DOC_COMMENTS = 20 MAX_QUOTE_CHARS = 300 MAX_NOTE_CHARS = 1000 @@ -2574,6 +2588,187 @@ def send_document( ) +MODEL_PREVIEW_WIDTH = 900 +MODEL_PREVIEW_HEIGHT = 700 +MODEL_PREVIEW_WAIT_MS = 1500 +_model_count = 0 + + +def _model_preview(model_path: Path) -> str: + """Draw the model the way the web UI will, and attach the picture + for the model to judge. Returns a line for its tool result.""" + + global _model_count + + if not model_sees_images(OLLAMA_HOST, MODEL_NAME): + return ( + f"The active model ({MODEL_NAME}) has no vision, so there is " + "no picture of it; check the numbers above against what you " + "meant to build." + ) + + web = Path(__file__).parent / "web" / "three" + try: + page = model3d.preview_page( + model_path.read_bytes(), model_path.suffix.lower(), + (web / "viewer.js").read_text(encoding="utf-8"), + (web / "three.min.js").read_text(encoding="utf-8"), + ) + except OSError as exc: + return f"No picture of it: {exc}." + + _model_count += 1 + html = Path(SCRATCH_DIR) / f"model-{_model_count}.html" + out = Path(SCRATCH_DIR) / f"model-{_model_count}.png" + html.write_text(page, encoding="utf-8") + problems, why = capture( + html.resolve().as_uri(), out, + width=MODEL_PREVIEW_WIDTH, height=MODEL_PREVIEW_HEIGHT, + full_page=False, wait_ms=MODEL_PREVIEW_WAIT_MS, + ) + if why: + tool_result(f"No preview: {why}", style=WARN) + return f"No picture of it: {why}" + + data = out.read_bytes() + _pending_images.append(data) + note = ( + "A picture of it, as the user's viewer first shows it (from the " + "front right, above), is attached, so judge the shape from what " + "you can see there." + ) + if problems: + note += " The viewer reported: " + "; ".join( + problems[:MAX_PAGE_PROBLEMS] + ) + return note + + +def _show_model(model_path: Path, label: str) -> str: + """Put a model in front of the user. Returns how it went.""" + + if tool_file(str(model_path)): + tool_result(label) + return ( + "It is on the user's screen beside the chat, in a 3D viewer " + "they can turn, zoom, and download it from." + ) + + problem = _open_with_spinner(model_path) + tool_result(label + (f" ({problem})" if problem else "")) + console.print( + Text(f"{' ' * RESULT_INDENT}{_display_path(model_path)}", style=DIM) + ) + if problem: + return ( + f"Could not open it: {problem}. Its path is on screen; tell " + "the user where the file is and that the web UI (flash --web) " + "shows 3D models." + ) + return ( + "It opened in the user's default 3D viewer, with its path on " + "screen." + ) + + +def make_3d_model( + path: str, parts: Any, title: str = "", caption: str = "", +) -> str: + """Build a 3D model out of simple parts, save it as a .glb file, + and show it to the user.""" + + model_path = Path(path).expanduser() + if model_path.suffix.lower() != ".glb": + model_path = model_path.with_name(model_path.name + ".glb") + tool_line(f"Make3DModel({model_path})") + + problem = "" + if model_path.is_dir(): + problem = f"{model_path} is a directory, not a file" + elif model_path.exists(): + try: + with open(model_path, "rb") as handle: + if not model3d.is_glb(handle.read(12)): + problem = ( + f"{model_path.name} already exists and is not a " + ".glb model, so it was left alone; pick another " + "path" + ) + except OSError as exc: + problem = f"could not read {model_path}: {exc}" + if problem: + result = f"Error: {problem}." + tool_result(result, style=ERROR) + return result + + try: + built = model3d.build_parts(parts) + data = model3d.to_glb(built, str(title or "").strip()) + except model3d.ModelError as exc: + result = f"Error: {exc}. Nothing was written." + tool_result(result, style=ERROR) + return result + + checkpoint.record(model_path) + try: + model_path.parent.mkdir(parents=True, exist_ok=True) + model_path.write_bytes(data) + except OSError as exc: + result = f"Error: could not write {model_path}: {exc}" + tool_result(result, style=ERROR) + return result + + kilobytes = max(1, round(len(data) / 1024)) + note = caption.strip() + count = len(built) + label = ( + f"{model_path.name} ({count} part{plural(count)}, {kilobytes} KB)" + + (f": {note}" if note else "") + ) + shown = _show_model(model_path, label) + return ( + f"Saved {model_path} ({kilobytes} KB).\n" + f"{model3d.describe(built)}\n{shown}\n{_model_preview(model_path)}" + "\nTo change it, call make_3d_model again with the whole list " + "of parts, changed, and the same path." + ) + + +def send_3d_model(path: str, caption: str = "") -> str: + """Put a 3D model file someone else made in front of the user.""" + + tool_line(f"Send3DModel({path})") + + model_path = Path(path).expanduser() + size = 0 + if not model_path.is_file(): + problem = f"no file at {model_path}" + else: + problem = model3d.check_model_file(model_path) or "" + if not problem: + size = model_path.stat().st_size + if size > MAX_MODEL_BYTES: + problem = ( + f"{model_path.name} is {size // (1024 * 1024)} MB; the " + f"limit is {MAX_MODEL_BYTES // (1024 * 1024)} MB" + ) + if problem: + result = f"Error: {problem}." + tool_result(result, style=ERROR) + return result + + kilobytes = max(1, round(size / 1024)) + note = caption.strip() + label = f"{model_path.name} ({kilobytes} KB)" + ( + f": {note}" if note else "" + ) + shown = _show_model(model_path, label) + return ( + f"Sent {model_path.name} ({kilobytes} KB). {shown}\n" + f"{_model_preview(model_path)}" + ) + + DEFAULT_SCREENSHOT_WIDTH = 1280 DEFAULT_SCREENSHOT_HEIGHT = 800 MIN_SCREENSHOT_SIDE = 200 @@ -3360,6 +3555,216 @@ def interact( }, }, }, + { + "type": "function", + "function": { + "name": "make_3d_model", + "description": ( + "Build a 3D model out of parts, save it as a .glb file, " + "and show it to the user in a 3D viewer they can turn and " + "zoom (beside the chat in the web UI). Use it for any " + "object, prop, scene, or layout the user wants to see in " + "3D. Y is up, units are metres, and the ground is y = 0, " + "so a part rests on it when its position's y is half its " + "height. Every shape is centred on its position. Build " + "the object from many parts, sized in proportion to the " + "real thing. The result gives the model's overall size, " + "and a picture of it when you can see images: check both " + "and fix what is off. To revise, call again with the " + "whole changed list and the same path." + ), + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": ( + "Where to save it, ending in .glb, such as " + "chair.glb." + ), + }, + "parts": { + "type": "array", + "description": "The parts, each one shape.", + "items": { + "type": "object", + "properties": { + "shape": { + "type": "string", + "enum": list(model3d.SHAPES), + "description": ( + "box (size [x,y,z]); sphere " + "(radius); cylinder (radius, " + "height, or radius_top and " + "radius_bottom for a taper); cone " + "(radius, height, point up); " + "torus (radius to the tube's " + "centre, tube; lies flat like a " + "ring on a table); plane (size " + "[x,z], facing up); lathe (points " + "[[radius,y],...] from bottom to " + "top, spun round the Y axis: " + "vases, bottles, lamps, chess " + "pieces); extrude (points " + "[[x,z],...], an outline seen " + "from above, raised to height: " + "walls, letters, gears, " + "L-shapes); mesh (vertices " + "[[x,y,z],...] and faces, each a " + "list of vertex indices from 0)." + ), + }, + "name": { + "type": "string", + "description": ( + "What the part is, like " + "'left front leg'." + ), + }, + "size": { + "type": "array", + "items": {"type": "number"}, + }, + "radius": {"type": "number"}, + "radius_top": {"type": "number"}, + "radius_bottom": {"type": "number"}, + "height": {"type": "number"}, + "tube": {"type": "number"}, + "points": { + "type": "array", + "items": { + "type": "array", + "items": {"type": "number"}, + }, + }, + "vertices": { + "type": "array", + "items": { + "type": "array", + "items": {"type": "number"}, + }, + }, + "faces": { + "type": "array", + "items": { + "type": "array", + "items": {"type": "integer"}, + }, + }, + "segments": { + "type": "integer", + "description": ( + "How smooth a round shape is, " + "3 to 128. 6 makes a hexagonal " + "prism of a cylinder." + ), + }, + "position": { + "type": "array", + "items": {"type": "number"}, + "description": ( + "[x, y, z] of the shape's centre." + ), + }, + "rotation": { + "type": "array", + "items": {"type": "number"}, + "description": ( + "[x, y, z] turns in degrees, " + "about the shape's centre. " + "[90, 0, 0] lays a cylinder on " + "its side along Z; [0, 0, 90] " + "along X." + ), + }, + "scale": { + "type": "array", + "items": {"type": "number"}, + "description": ( + "[x, y, z] stretch, such as a " + "sphere made an egg." + ), + }, + "color": { + "type": "string", + "description": ( + "A hex code like #c0392b, or a " + "common name." + ), + }, + "metalness": { + "type": "number", + "description": "0 (default) to 1.", + }, + "roughness": { + "type": "number", + "description": ( + "0 (mirror) to 1 (chalk); " + "default 0.6." + ), + }, + "opacity": { + "type": "number", + "description": ( + "1 (default) to 0; below 1 for " + "glass or water." + ), + }, + "emissive": { + "type": "string", + "description": ( + "A colour it glows, for lamps " + "and screens." + ), + }, + }, + "required": ["shape"], + }, + }, + "title": { + "type": "string", + "description": "Optional name for the model.", + }, + "caption": { + "type": "string", + "description": ( + "Optional single line shown with it." + ), + }, + }, + "required": ["path", "parts"], + }, + }, + }, + { + "type": "function", + "function": { + "name": "send_3d_model", + "description": ( + "Show a 3D model file that already exists (.glb, .stl, or " + ".obj), such as one a script made or the user has, in a " + "3D viewer they can turn and zoom (beside the chat in the " + "web UI). For a model you build yourself, use " + "make_3d_model, which shows it too." + ), + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Path to the .glb, .stl, or .obj.", + }, + "caption": { + "type": "string", + "description": ( + "Optional single line shown with it." + ), + }, + }, + "required": ["path"], + }, + }, + }, { "type": "function", "function": { @@ -3983,6 +4388,8 @@ def interact( "send_pdf": send_pdf, "send_html": send_html, "send_document": send_document, + "make_3d_model": make_3d_model, + "send_3d_model": send_3d_model, "screenshot": screenshot, "open_page": open_page, "interact": interact, diff --git a/flash/web.py b/flash/web.py index 1a4fcf5..506a85c 100644 --- a/flash/web.py +++ b/flash/web.py @@ -107,6 +107,13 @@ if path.is_file() and path.suffix in KATEX_TYPES }) +# three.js and Flash's viewer on it, which draw the 3D models the agent +# makes: shipped with Flash too, and loaded only once a model is opened. +STATIC.update({ + path.relative_to(WEB_DIR).as_posix(): KATEX_TYPES[path.suffix] + for path in sorted((WEB_DIR / "three").glob("*.js")) +}) + # How often an idle event stream says it is still there. Proxies and # some browsers drop a stream that has been silent for a minute. PING_SECONDS = 15 diff --git a/flash/web/index.html b/flash/web/index.html index d7419d5..9ac96e2 100644 --- a/flash/web/index.html +++ b/flash/web/index.html @@ -1142,6 +1142,18 @@ #viewer-body .image { position: absolute; inset: 0; overflow: auto; display: grid; place-items: center; padding: 20px; cursor: zoom-in; } #viewer-body .image img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 8px; box-shadow: var(--shadow); animation: rise-far 0.45s var(--apple) both; } #viewer-body .image.actual { place-items: start; cursor: zoom-out; } +/* A 3D model: the canvas fills the panel; a few controls float on it. */ +.model-view { position: absolute; inset: 0; background: radial-gradient(ellipse at 50% 35%, var(--surface), var(--code-bg) 75%); } +.model-view .stage { position: absolute; inset: 0; cursor: grab; } +.model-view .stage:active { cursor: grabbing; } +.model-view .model-note { position: absolute; inset: 0; display: grid; place-items: center; padding: 24px; text-align: center; color: var(--text-3); font-size: 13.5px; pointer-events: none; } +.model-view .model-tools { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); display: flex; align-items: center; gap: 4px; padding: 4px; border-radius: 12px; background: color-mix(in srgb, var(--surface) 88%, transparent); border: 1px solid var(--border); box-shadow: var(--shadow); backdrop-filter: blur(8px); animation: rise-far 0.45s var(--apple) both; } +.model-view .model-tools[hidden] { display: none; } +.model-view .model-tools button { padding: 5px 10px; border-radius: 8px; font-size: 12.5px; color: var(--text-2); white-space: nowrap; } +.model-view .model-tools button:hover { background: var(--hover); color: var(--text); } +.model-view .model-tools button[aria-pressed="true"] { background: var(--hover); color: var(--text); } +.model-view .model-tools .hint { padding: 0 8px; font-size: 12px; color: var(--text-3); white-space: nowrap; } +@media (max-width: 560px) { .model-view .model-tools .hint { display: none; } } /* A document, set like a page: a readable column, generous margins. */ #viewer-body .doc-scroll { position: absolute; inset: 0; overflow: auto; background: var(--bg); display: flex; flex-direction: column; } @@ -1528,6 +1540,7 @@ quote: '', link: '', code: '', + cube: '', image: '', server: '', more: '', @@ -2074,6 +2087,7 @@ } const fileUrl = (entry, download) => `/api/files/${encodeURIComponent(entry.id)}${download ? "?download=1" : ""}`; const fileKind = (entry) => (entry.kind === "pdf" ? "PDF" : entry.kind === "html" ? "HTML" + : entry.kind === "model" ? "3D model" : entry.kind === "doc" ? (/\.txt$/i.test(entry.name) ? "Text" : "Markdown") : (entry.mime || "image/").split("/")[1].toUpperCase()); @@ -2084,6 +2098,7 @@ const thumb = entry.kind === "image" ? `` : entry.kind === "doc" ? `${icon("file")}` + : entry.kind === "model" ? `${icon("cube")}` : `${fileKind(entry)}`; card.innerHTML = `${thumb}
` + `
${icon("chevRight")}`; @@ -2148,6 +2163,7 @@ const body = $("#viewer-body"); let view = body.querySelector(`.browser-view[data-run="${CSS.escape(run)}"]`); if (!view) { + dropModel(); body.textContent = ""; view = body.appendChild(el("div", "browser-view", `
`)); view.dataset.run = run; @@ -2196,7 +2212,7 @@ viewing = lastViewed = entry; $("#viewer-title").textContent = entry.name; $("#viewer-size").textContent = `${fileKind(entry)} · ${fileSize(entry.size)}`; - $("#viewer-kind").innerHTML = icon({ pdf: "file", html: "globe", doc: "file" }[entry.kind] || "image"); + $("#viewer-kind").innerHTML = icon({ pdf: "file", html: "globe", doc: "file", model: "cube" }[entry.kind] || "image"); $("#viewer-edit").hidden = entry.kind !== "doc"; $("#viewer-editing").hidden = true; if (openDoc && openDoc.onSelect) document.removeEventListener("selectionchange", openDoc.onSelect); @@ -2206,6 +2222,7 @@ download.setAttribute("download", entry.name); $("#viewer-open").href = fileUrl(entry); const body = $("#viewer-body"); + dropModel(); body.textContent = ""; if (entry.kind === "html") { // Sandboxed twice over: here, and by the header the server sends, @@ -2222,6 +2239,8 @@ body.appendChild(frame); } else if (entry.kind === "doc") { openDocument(entry, body); + } else if (entry.kind === "model") { + openModel(entry, body); } else { const holder = el("div", "image"); const img = el("img"); @@ -2239,6 +2258,84 @@ markOpenCard(); } +// --------------------------------------------------------------------------- +// 3D models: a .glb, .stl or .obj Flash made or found, drawn by three.js +// in the panel, to turn with a drag, zoom with a scroll, and pan with a +// right-drag. three.js is big, so it loads the first time a model opens. + +let modelView = null; // the model in the panel: its viewer, to let go of +let threeLoading = null; + +function loadScript(src) { + return new Promise((resolve, reject) => { + const tag = document.createElement("script"); + tag.src = src; + tag.onload = resolve; + tag.onerror = () => { tag.remove(); reject(new Error(`could not load ${src}`)); }; + document.head.appendChild(tag); + }); +} + +function loadThree() { + if (window.FlashModelView) return Promise.resolve(); + threeLoading = threeLoading || loadScript("/static/three/three.min.js") + .then(() => loadScript("/static/three/viewer.js")) + .catch((e) => { threeLoading = null; throw e; }); + return threeLoading; +} + +// Lets go of the model's GPU memory once the panel shows something else. +function dropModel() { + if (!modelView) return; + const gone = modelView; + modelView = null; + gone.dropped = true; + if (gone.handle) gone.handle.dispose(); +} + +async function openModel(entry, body) { + const view = body.appendChild(el("div", "model-view", + `
Loading the model…
` + + ``)); + const mine = { entry, handle: null, dropped: false }; + modelView = mine; + const note = view.querySelector(".model-note"); + const suffix = (/\.[^.]+$/.exec(entry.name) || [".glb"])[0].toLowerCase(); + try { + await loadThree(); + if (mine.dropped) return; + const handle = await FlashModelView.show(view.querySelector(".stage"), fileUrl(entry), suffix); + if (mine.dropped) { handle.dispose(); return; } + mine.handle = handle; + } catch (e) { + if (!mine.dropped) note.textContent = `Could not show this model: ${e && e.message ? e.message : e}`; + return; + } + note.remove(); + const tools = view.querySelector(".model-tools"); + tools.hidden = false; + const press = (button, on) => button.setAttribute("aria-pressed", on ? "true" : "false"); + tools.querySelector("[data-reset]").onclick = () => mine.handle.reset(); + const spin = tools.querySelector("[data-spin]"); + spin.onclick = () => { const on = spin.getAttribute("aria-pressed") !== "true"; press(spin, on); mine.handle.spin(on); }; + // Grabbing the model stops it spinning; the button says so too. + view.querySelector(".stage").addEventListener("pointerdown", () => press(spin, false)); + const wire = tools.querySelector("[data-wire]"); + wire.onclick = () => { const on = wire.getAttribute("aria-pressed") !== "true"; press(wire, on); mine.handle.wireframe(on); }; + const size = modelSize(mine.handle); + if (size) $("#viewer-size").textContent = `${fileKind(entry)} · ${fileSize(entry.size)} · ${size}`; +} + +// The model's size, as the panel's subtitle shows it: 1.2 × 0.8 × 0.6 m. +function modelSize(handle) { + if (!handle || !handle.size) return ""; + const round = (n) => String(n >= 10 ? Math.round(n) : Number(n.toPrecision(2))); + return `${handle.size.map(round).join(" × ")} m`; +} + // --------------------------------------------------------------------------- // Documents: Markdown or text Flash sent, read like a page, edited in // place, and commented on. Select a passage to comment on it; the @@ -2969,8 +3066,8 @@ dropCommentUi(); if (window.CSS && CSS.highlights) CSS.highlights.delete("doc-comment"); markOpenCard(); - // Emptied once it has slid away, so a PDF is not left loaded. - setTimeout(() => { if (!viewing) $("#viewer-body").textContent = ""; }, 480); + // Emptied once it has slid away, so a PDF or a model is not left loaded. + setTimeout(() => { if (!viewing) { dropModel(); $("#viewer-body").textContent = ""; } }, 480); return true; } @@ -3091,8 +3188,8 @@ shot.onclick = () => openViewer(f); continue; } - const viewable = f.kind === "pdf"; - const chip = box.appendChild(el(viewable ? "button" : "div", "doc", `${icon("file")}`)); + const viewable = f.kind === "pdf" || f.kind === "model"; + const chip = box.appendChild(el(viewable ? "button" : "div", "doc", `${icon(f.kind === "model" ? "cube" : "file")}`)); chip.querySelector(".name").textContent = f.name; chip.querySelector(".meta").textContent = `${extOf(f.name)} · ${fileSize(f.size)}`; if (viewable) { chip.type = "button"; chip.onclick = () => openViewer(f); } diff --git a/flash/web/three/LICENSE.txt b/flash/web/three/LICENSE.txt new file mode 100644 index 0000000..8ada2a5 --- /dev/null +++ b/flash/web/three/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright © 2010-2026 three.js authors + +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. diff --git a/flash/web/three/three.min.js b/flash/web/three/three.min.js new file mode 100644 index 0000000..727277d --- /dev/null +++ b/flash/web/three/three.min.js @@ -0,0 +1,4225 @@ +/* three.js 0.186.1 (MIT, see LICENSE.txt): core, OrbitControls, GLTFLoader, STLLoader, OBJLoader and RoomEnvironment, bundled as window.FlashThree for Flash's 3D model viewer. */ +(()=>{var T_=Object.defineProperty;var A_=(r,e)=>{for(var t in e)T_(r,t,{get:e[t],enumerable:!0})};var Tf={};A_(Tf,{ACESFilmicToneMapping:()=>Yh,AddEquation:()=>ls,AddOperation:()=>zd,AdditiveAnimationBlendMode:()=>iu,AdditiveBlending:()=>zh,AgXToneMapping:()=>Kh,AlphaFormat:()=>tu,AlwaysCompare:()=>$d,AlwaysDepth:()=>Ho,AlwaysStencilFunc:()=>qd,AmbientLight:()=>Fa,AnimationAction:()=>Ya,AnimationClip:()=>gi,AnimationLoader:()=>th,AnimationMixer:()=>dh,AnimationObjectGroup:()=>uh,AnimationUtils:()=>eh,ArcCurve:()=>la,ArrayCamera:()=>Ha,ArrowHelper:()=>Dh,AttachedBindMode:()=>Nc,Audio:()=>Xa,AudioAnalyser:()=>hh,AudioContext:()=>Qr,AudioListener:()=>lh,AudioLoader:()=>oh,AxesHelper:()=>Uh,BackSide:()=>qt,BasicDepthPacking:()=>Wd,BasicShadowMap:()=>Am,BatchedMesh:()=>ta,BezierInterpolant:()=>Na,Bone:()=>is,BooleanKeyframeTrack:()=>di,Box2:()=>Za,Box3:()=>Ft,Box3Helper:()=>Lh,BoxGeometry:()=>ui,BoxHelper:()=>Ph,BufferAttribute:()=>Qe,BufferGeometry:()=>Oe,BufferGeometryLoader:()=>Va,ByteType:()=>jh,Cache:()=>Yn,Camera:()=>Gs,CameraHelper:()=>Ih,CanvasTexture:()=>jc,CapsuleGeometry:()=>sa,CatmullRomCurve3:()=>ca,CineonToneMapping:()=>qh,CircleGeometry:()=>ra,ClampToEdgeWrapping:()=>Yt,Clock:()=>yh,Color:()=>ce,ColorKeyframeTrack:()=>Zr,ColorManagement:()=>Je,Compatibility:()=>hg,CompressedArrayTexture:()=>Kc,CompressedCubeTexture:()=>Jc,CompressedTexture:()=>Us,CompressedTextureLoader:()=>nh,ConeGeometry:()=>Ur,ConstantAlphaFactor:()=>Fd,ConstantColorFactor:()=>Dd,Controls:()=>eo,CubeCamera:()=>Ga,CubeDepthTexture:()=>ia,CubeReflectionMapping:()=>ni,CubeRefractionMapping:()=>Oi,CubeTexture:()=>ss,CubeTextureLoader:()=>ih,CubeUVReflectionMapping:()=>Zs,CubicBezierCurve:()=>Fr,CubicBezierCurve3:()=>ha,CubicInterpolant:()=>Pa,CullFaceBack:()=>Bh,CullFaceFront:()=>xd,CullFaceFrontBack:()=>Tm,CullFaceNone:()=>_d,Curve:()=>yn,CurvePath:()=>da,CustomBlending:()=>vd,CustomToneMapping:()=>Zh,CylinderGeometry:()=>Dr,Cylindrical:()=>vh,Data3DTexture:()=>Rs,DataArrayTexture:()=>ws,DataTexture:()=>hn,DataTextureLoader:()=>sh,DataUtils:()=>Bc,DecrementStencilOp:()=>Vm,DecrementWrapStencilOp:()=>Hm,DefaultLoadingManager:()=>rf,DepthFormat:()=>Zn,DepthStencilFormat:()=>zi,DepthTexture:()=>Pi,DetachedBindMode:()=>kd,DirectionalLight:()=>Ws,DirectionalLightHelper:()=>Ch,DiscreteInterpolant:()=>La,DodecahedronGeometry:()=>oa,DoubleSide:()=>Rn,DstAlphaFactor:()=>Cd,DstColorFactor:()=>Pd,DynamicCopyUsage:()=>sg,DynamicDrawUsage:()=>$m,DynamicReadUsage:()=>tg,EdgesGeometry:()=>aa,EllipseCurve:()=>Fs,EqualCompare:()=>Kd,EqualDepth:()=>Xo,EqualStencilFunc:()=>Ym,EquirectangularReflectionMapping:()=>io,EquirectangularRefractionMapping:()=>so,Euler:()=>Dn,EventDispatcher:()=>xn,ExternalTexture:()=>Nr,ExtrudeGeometry:()=>ga,FileLoader:()=>kt,Float16BufferAttribute:()=>Wc,Float32BufferAttribute:()=>fe,FloatType:()=>en,Fog:()=>jo,FogExp2:()=>Jo,FramebufferTexture:()=>Zc,FrontSide:()=>ei,Frustum:()=>hi,FrustumArray:()=>ea,GLBufferAttribute:()=>_h,GLSL1:()=>og,GLSL3:()=>ru,GreaterCompare:()=>Jd,GreaterDepth:()=>Yo,GreaterEqualCompare:()=>Dl,GreaterEqualDepth:()=>qo,GreaterEqualStencilFunc:()=>jm,GreaterStencilFunc:()=>Km,GridHelper:()=>wh,Group:()=>cn,HTMLTexture:()=>$c,HalfFloatType:()=>Bn,HemisphereLight:()=>Ua,HemisphereLightHelper:()=>Eh,IcosahedronGeometry:()=>_a,ImageBitmapLoader:()=>$r,ImageLoader:()=>as,ImageUtils:()=>Ko,IncrementStencilOp:()=>km,IncrementWrapStencilOp:()=>Gm,InstancedBufferAttribute:()=>An,InstancedBufferGeometry:()=>ka,InstancedInterleavedBuffer:()=>gh,InstancedMesh:()=>Ii,Int16BufferAttribute:()=>Gc,Int32BufferAttribute:()=>Hc,Int8BufferAttribute:()=>zc,IntType:()=>Ja,InterleavedBuffer:()=>ci,InterleavedBufferAttribute:()=>Kn,Interpolant:()=>$n,InterpolateBezier:()=>Dc,InterpolateDiscrete:()=>Qi,InterpolateLinear:()=>es,InterpolateSmooth:()=>Fo,InterpolationSamplingMode:()=>cg,InterpolationSamplingType:()=>lg,InvertStencilOp:()=>Wm,KeepStencilOp:()=>Oo,KeyframeTrack:()=>dn,LOD:()=>Qo,LatheGeometry:()=>xa,Layers:()=>Cs,LessCompare:()=>Zd,LessDepth:()=>Wo,LessEqualCompare:()=>Nl,LessEqualDepth:()=>As,LessEqualStencilFunc:()=>Zm,LessStencilFunc:()=>qm,Light:()=>Qn,LightProbe:()=>Ba,LightShadow:()=>Vs,Line:()=>En,Line3:()=>Sh,LineBasicMaterial:()=>Rt,LineCurve:()=>Or,LineCurve3:()=>ua,LineDashedMaterial:()=>Ia,LineLoop:()=>Ds,LineSegments:()=>Xt,LinearFilter:()=>pt,LinearInterpolant:()=>Yr,LinearMipMapLinearFilter:()=>Im,LinearMipMapNearestFilter:()=>Cm,LinearMipmapLinearFilter:()=>vn,LinearMipmapNearestFilter:()=>cs,LinearSRGBColorSpace:()=>nn,LinearToneMapping:()=>Wh,LinearTransfer:()=>Er,Loader:()=>It,LoaderUtils:()=>Fn,LoadingManager:()=>Kr,LoopOnce:()=>Vd,LoopPingPong:()=>Hd,LoopRepeat:()=>Gd,MOUSE:()=>Ui,Material:()=>vt,MaterialBlending:()=>Em,MaterialLoader:()=>za,MathUtils:()=>mo,Matrix2:()=>Mh,Matrix3:()=>qe,Matrix4:()=>ze,MaxEquation:()=>Td,Mesh:()=>rt,MeshBasicMaterial:()=>Kt,MeshDepthMaterial:()=>Xr,MeshDistanceMaterial:()=>qr,MeshLambertMaterial:()=>ks,MeshMatcapMaterial:()=>Ca,MeshNormalMaterial:()=>Ra,MeshPhongMaterial:()=>zs,MeshPhysicalMaterial:()=>sn,MeshStandardMaterial:()=>Un,MeshToonMaterial:()=>wa,MinEquation:()=>bd,MirroredRepeatWrapping:()=>$i,MixOperation:()=>Bd,MultiplyBlending:()=>Vh,MultiplyOperation:()=>no,NearestFilter:()=>At,NearestMipMapLinearFilter:()=>Rm,NearestMipMapNearestFilter:()=>wm,NearestMipmapLinearFilter:()=>Bi,NearestMipmapNearestFilter:()=>ro,NeutralToneMapping:()=>Jh,NeverCompare:()=>Yd,NeverDepth:()=>Go,NeverStencilFunc:()=>Xm,NoBlending:()=>ti,NoColorSpace:()=>yi,NoNormalPacking:()=>Um,NoToneMapping:()=>On,NormalAnimationBlendMode:()=>Ll,NormalBlending:()=>Ys,NormalGAPacking:()=>Om,NormalRGPacking:()=>Fm,NotEqualCompare:()=>jd,NotEqualDepth:()=>Zo,NotEqualStencilFunc:()=>Jm,NumberKeyframeTrack:()=>fi,Object3D:()=>st,ObjectLoader:()=>rh,ObjectSpaceNormalMap:()=>Xd,OctahedronGeometry:()=>Gr,OneFactor:()=>Ed,OneMinusConstantAlphaFactor:()=>Od,OneMinusConstantColorFactor:()=>Ud,OneMinusDstAlphaFactor:()=>Id,OneMinusDstColorFactor:()=>Ld,OneMinusSrcAlphaFactor:()=>Hh,OneMinusSrcColorFactor:()=>Rd,OrthographicCamera:()=>_i,PCFShadowMap:()=>to,PCFSoftShadowMap:()=>yd,PMREMGenerator:()=>zl,Path:()=>rs,PerspectiveCamera:()=>Lt,Plane:()=>gn,PlaneGeometry:()=>Bs,PlaneHelper:()=>Nh,PointLight:()=>Di,PointLightHelper:()=>Ah,Points:()=>jn,PointsMaterial:()=>wn,PolarGridHelper:()=>Rh,PolyhedronGeometry:()=>Li,PositionalAudio:()=>ch,PropertyBinding:()=>lt,PropertyMixer:()=>qa,QuadraticBezierCurve:()=>Br,QuadraticBezierCurve3:()=>zr,Quaternion:()=>wt,QuaternionKeyframeTrack:()=>pi,QuaternionLinearInterpolant:()=>Da,R11_EAC_Format:()=>cl,RED_GREEN_RGTC2_Format:()=>fo,RED_RGTC1_Format:()=>Cl,REVISION:()=>gd,RG11_EAC_Format:()=>uo,RGBADepthPacking:()=>Lm,RGBAFormat:()=>tn,RGBAIntegerFormat:()=>tl,RGBA_ASTC_10x10_Format:()=>bl,RGBA_ASTC_10x5_Format:()=>vl,RGBA_ASTC_10x6_Format:()=>Ml,RGBA_ASTC_10x8_Format:()=>Sl,RGBA_ASTC_12x10_Format:()=>Tl,RGBA_ASTC_12x12_Format:()=>Al,RGBA_ASTC_4x4_Format:()=>dl,RGBA_ASTC_5x4_Format:()=>fl,RGBA_ASTC_5x5_Format:()=>pl,RGBA_ASTC_6x5_Format:()=>ml,RGBA_ASTC_6x6_Format:()=>gl,RGBA_ASTC_8x5_Format:()=>_l,RGBA_ASTC_8x6_Format:()=>xl,RGBA_ASTC_8x8_Format:()=>yl,RGBA_BPTC_Format:()=>El,RGBA_ETC2_EAC_Format:()=>ll,RGBA_PVRTC_2BPPV1_Format:()=>rl,RGBA_PVRTC_4BPPV1_Format:()=>sl,RGBA_S3TC_DXT1_Format:()=>lo,RGBA_S3TC_DXT3_Format:()=>co,RGBA_S3TC_DXT5_Format:()=>ho,RGBDepthPacking:()=>Nm,RGBFormat:()=>nu,RGBIntegerFormat:()=>Pm,RGB_BPTC_SIGNED_Format:()=>wl,RGB_BPTC_UNSIGNED_Format:()=>Rl,RGB_ETC1_Format:()=>ol,RGB_ETC2_Format:()=>al,RGB_PVRTC_2BPPV1_Format:()=>il,RGB_PVRTC_4BPPV1_Format:()=>nl,RGB_S3TC_DXT1_Format:()=>ao,RGDepthPacking:()=>Dm,RGFormat:()=>ki,RGIntegerFormat:()=>el,RawShaderMaterial:()=>Wr,Ray:()=>Jn,Raycaster:()=>xh,RectAreaLight:()=>Oa,RedFormat:()=>Qa,RedIntegerFormat:()=>oo,ReinhardToneMapping:()=>Xh,RenderObjectRefreshType:()=>ug,RenderTarget:()=>Cr,RenderTarget3D:()=>fh,RepeatWrapping:()=>li,ReplaceStencilOp:()=>zm,ReverseSubtractEquation:()=>Sd,RingGeometry:()=>ya,SIGNED_R11_EAC_Format:()=>hl,SIGNED_RED_GREEN_RGTC2_Format:()=>Pl,SIGNED_RED_RGTC1_Format:()=>Il,SIGNED_RG11_EAC_Format:()=>ul,SRGBColorSpace:()=>Tt,SRGBTransfer:()=>ht,Scene:()=>Ps,ShaderChunk:()=>je,ShaderLib:()=>ii,ShaderMaterial:()=>un,ShadowMaterial:()=>Ea,Shape:()=>os,ShapeGeometry:()=>va,ShapePath:()=>Fh,ShapeUtils:()=>Nn,ShortType:()=>$h,Skeleton:()=>Ns,SkeletonHelper:()=>Th,SkinnedMesh:()=>Ls,Source:()=>Uc,Sphere:()=>Nt,SphereGeometry:()=>Hr,Spherical:()=>Xs,SphericalHarmonics3:()=>jr,SplineCurve:()=>kr,SpotLight:()=>Hs,SpotLightHelper:()=>bh,Sprite:()=>$o,SpriteMaterial:()=>Lr,SrcAlphaFactor:()=>Gh,SrcAlphaSaturateFactor:()=>Nd,SrcColorFactor:()=>wd,StaticCopyUsage:()=>ig,StaticDrawUsage:()=>Ul,StaticReadUsage:()=>eg,StereoCamera:()=>ah,StreamCopyUsage:()=>rg,StreamDrawUsage:()=>Qm,StreamReadUsage:()=>ng,StringKeyframeTrack:()=>mi,SubtractEquation:()=>Md,SubtractiveBlending:()=>kh,TOUCH:()=>Fi,TangentSpaceNormalMap:()=>xi,TetrahedronGeometry:()=>Ma,Texture:()=>Et,TextureLoader:()=>Jr,TextureSource:()=>Ln,TextureUtils:()=>Oh,Timer:()=>Wa,TimestampQuery:()=>ag,TorusGeometry:()=>Sa,TorusKnotGeometry:()=>ba,Triangle:()=>qn,TriangleFanDrawMode:()=>js,TriangleStripDrawMode:()=>po,TrianglesDrawMode:()=>su,TubeGeometry:()=>Ta,UVMapping:()=>Ka,Uint16BufferAttribute:()=>Ir,Uint32BufferAttribute:()=>Pr,Uint8BufferAttribute:()=>kc,Uint8ClampedBufferAttribute:()=>Vc,Uniform:()=>ph,UniformsGroup:()=>mh,UniformsLib:()=>xe,UniformsUtils:()=>sf,UnsignedByteType:()=>fn,UnsignedInt101111Type:()=>eu,UnsignedInt248Type:()=>Js,UnsignedInt5999Type:()=>Qh,UnsignedIntType:()=>Cn,UnsignedShort4444Type:()=>ja,UnsignedShort5551Type:()=>$a,UnsignedShortType:()=>Ks,VSMShadowMap:()=>qs,Vector2:()=>J,Vector3:()=>R,Vector4:()=>mt,VectorKeyframeTrack:()=>Ni,VideoFrameTexture:()=>Yc,VideoTexture:()=>na,WebGL3DRenderTarget:()=>Oc,WebGLArrayRenderTarget:()=>Fc,WebGLCoordinateSystem:()=>_n,WebGLCubeRenderTarget:()=>kl,WebGLRenderTarget:()=>Zt,WebGLRenderer:()=>bf,WebGLUtils:()=>t_,WebGPUCoordinateSystem:()=>ts,WebXRController:()=>Is,WireframeGeometry:()=>Aa,WrapAroundEnding:()=>Ar,ZeroCurvatureEnding:()=>Ji,ZeroFactor:()=>Ad,ZeroSlopeEnding:()=>ji,ZeroStencilOp:()=>Bm,createCanvasElement:()=>Qd,error:()=>Pe,getConsoleFunction:()=>pg,log:()=>Rr,setConsoleFunction:()=>fg,warn:()=>de,warnOnce:()=>ai});var gd="186",Ui={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},Fi={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},_d=0,Bh=1,xd=2,Tm=3,Am=0,to=1,yd=2,qs=3,ei=0,qt=1,Rn=2,ti=0,Ys=1,zh=2,kh=3,Vh=4,vd=5,Em=6,ls=100,Md=101,Sd=102,bd=103,Td=104,Ad=200,Ed=201,wd=202,Rd=203,Gh=204,Hh=205,Cd=206,Id=207,Pd=208,Ld=209,Nd=210,Dd=211,Ud=212,Fd=213,Od=214,Go=0,Ho=1,Wo=2,As=3,Xo=4,qo=5,Yo=6,Zo=7,no=0,Bd=1,zd=2,On=0,Wh=1,Xh=2,qh=3,Yh=4,Zh=5,Kh=6,Jh=7,Nc="attached",kd="detached",Ka=300,ni=301,Oi=302,io=303,so=304,Zs=306,li=1e3,Yt=1001,$i=1002,At=1003,ro=1004,wm=1004,Bi=1005,Rm=1005,pt=1006,cs=1007,Cm=1007,vn=1008,Im=1008,fn=1009,jh=1010,$h=1011,Ks=1012,Ja=1013,Cn=1014,en=1015,Bn=1016,ja=1017,$a=1018,Js=1020,Qh=35902,eu=35899,tu=1021,nu=1022,tn=1023,Zn=1026,zi=1027,Qa=1028,oo=1029,ki=1030,el=1031,Pm=1032,tl=1033,ao=33776,lo=33777,co=33778,ho=33779,nl=35840,il=35841,sl=35842,rl=35843,ol=36196,al=37492,ll=37496,cl=37488,hl=37489,uo=37490,ul=37491,dl=37808,fl=37809,pl=37810,ml=37811,gl=37812,_l=37813,xl=37814,yl=37815,vl=37816,Ml=37817,Sl=37818,bl=37819,Tl=37820,Al=37821,El=36492,wl=36494,Rl=36495,Cl=36283,Il=36284,fo=36285,Pl=36286,Vd=2200,Gd=2201,Hd=2202,Qi=2300,es=2301,Fo=2302,Dc=2303,Ji=2400,ji=2401,Ar=2402,Ll=2500,iu=2501,su=0,po=1,js=2,Wd=3200,Lm=3201,Nm=3202,Dm=3203,xi=0,Xd=1,yi="",Tt="srgb",nn="srgb-linear",Er="linear",ht="srgb",Um="",Fm="rg",Om="ga",Bm=0,Oo=7680,zm=7681,km=7682,Vm=7683,Gm=34055,Hm=34056,Wm=5386,Xm=512,qm=513,Ym=514,Zm=515,Km=516,Jm=517,jm=518,qd=519,Yd=512,Zd=513,Kd=514,Nl=515,Jd=516,jd=517,Dl=518,$d=519,Ul=35044,$m=35048,Qm=35040,eg=35045,tg=35049,ng=35041,ig=35046,sg=35050,rg=35042,og="100",ru="300 es",_n=2e3,ts=2001,ag={COMPUTE:"compute",RENDER:"render"},lg={PERSPECTIVE:"perspective",LINEAR:"linear",FLAT:"flat"},cg={NORMAL:"normal",CENTROID:"centroid",SAMPLE:"sample",FIRST:"first",EITHER:"either"},hg={TEXTURE_COMPARE:"depthTextureCompare"},ug={NONE:0,SHARED:1,FULL:2};function E_(r){for(let e=r.length-1;e>=0;--e)if(r[e]>=65535)return!0;return!1}var w_={Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array};function br(r,e){return new w_[r](e)}function dg(r){return ArrayBuffer.isView(r)&&!(r instanceof DataView)}function wr(r){return document.createElementNS("http://www.w3.org/1999/xhtml",r)}function Qd(){let r=wr("canvas");return r.style.display="block",r}var fp={},ns=null;function fg(r){ns=r}function pg(){return ns}function Rr(...r){let e="THREE."+r.shift();ns?ns("log",e,...r):console.log(e,...r)}function mg(r){let e=r[0];if(typeof e=="string"&&e.startsWith("TSL:")){let t=r[1];t&&t.isStackTrace?r[0]+=" "+t.getLocation():r[1]='Stack trace not available. Enable "THREE.Node.captureStackTrace" to capture stack traces.'}return r}function de(...r){r=mg(r);let e="THREE."+r.shift();if(ns)ns("warn",e,...r);else{let t=r[0];t&&t.isStackTrace?console.warn(t.getError(e)):console.warn(e,...r)}}function Pe(...r){r=mg(r);let e="THREE."+r.shift();if(ns)ns("error",e,...r);else{let t=r[0];t&&t.isStackTrace?console.error(t.getError(e)):console.error(e,...r)}}function ai(...r){let e=r.join(" ");e in fp||(fp[e]=!0,de(...r))}function gg(r,e,t){return new Promise(function(n,i){function s(){switch(r.clientWaitSync(e,r.SYNC_FLUSH_COMMANDS_BIT,0)){case r.WAIT_FAILED:i();break;case r.TIMEOUT_EXPIRED:setTimeout(s,t);break;default:n()}}setTimeout(s,t)})}var _g={[Go]:Ho,[Wo]:Yo,[Xo]:Zo,[As]:qo,[Ho]:Go,[Yo]:Wo,[Zo]:Xo,[qo]:As},xn=class{addEventListener(e,t){this._listeners===void 0&&(this._listeners={});let n=this._listeners;n[e]===void 0&&(n[e]=[]),n[e].indexOf(t)===-1&&n[e].push(t)}hasEventListener(e,t){let n=this._listeners;return n===void 0?!1:n[e]!==void 0&&n[e].indexOf(t)!==-1}removeEventListener(e,t){let n=this._listeners;if(n===void 0)return;let i=n[e];if(i!==void 0){let s=i.indexOf(t);s!==-1&&i.splice(s,1)}}dispatchEvent(e){let t=this._listeners;if(t===void 0)return;let n=t[e.type];if(n!==void 0){e.target=this;let i=n.slice(0);for(let s=0,o=i.length;s>8&255]+jt[r>>16&255]+jt[r>>24&255]+"-"+jt[e&255]+jt[e>>8&255]+"-"+jt[e>>16&15|64]+jt[e>>24&255]+"-"+jt[t&63|128]+jt[t>>8&255]+"-"+jt[t>>16&255]+jt[t>>24&255]+jt[n&255]+jt[n>>8&255]+jt[n>>16&255]+jt[n>>24&255]).toLowerCase()}function He(r,e,t){return Math.max(e,Math.min(t,r))}function ef(r,e){return(r%e+e)%e}function R_(r,e,t,n,i){return n+(r-e)*(i-n)/(t-e)}function C_(r,e,t){return r!==e?(t-r)/(e-r):0}function Bo(r,e,t){return(1-t)*r+t*e}function I_(r,e,t,n){return Bo(r,e,1-Math.exp(-t*n))}function P_(r,e=1){return e-Math.abs(ef(r,e*2)-e)}function L_(r,e,t){return r<=e?0:r>=t?1:(r=(r-e)/(t-e),r*r*(3-2*r))}function N_(r,e,t){return r<=e?0:r>=t?1:(r=(r-e)/(t-e),r*r*r*(r*(r*6-15)+10))}function D_(r,e){return r+Math.floor(Math.random()*(e-r+1))}function U_(r,e){return r+Math.random()*(e-r)}function F_(r){return r*(.5-Math.random())}function O_(r){r!==void 0&&(pp=r);let e=pp+=1831565813;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}function B_(r){return r*Ts}function z_(r){return r*Es}function k_(r){return r>0&&Number.isInteger(r)&&2**Math.round(Math.log2(r))===r}function V_(r){return Math.pow(2,Math.ceil(Math.log(r)/Math.LN2))}function G_(r){return Math.pow(2,Math.floor(Math.log(r)/Math.LN2))}function H_(r,e,t,n,i){let s=Math.cos,o=Math.sin,a=s(t/2),l=o(t/2),c=s((e+n)/2),h=o((e+n)/2),u=s((e-n)/2),d=o((e-n)/2),f=s((n-e)/2),p=o((n-e)/2);switch(i){case"XYX":r.set(a*h,l*u,l*d,a*c);break;case"YZY":r.set(l*d,a*h,l*u,a*c);break;case"ZXZ":r.set(l*u,l*d,a*h,a*c);break;case"XZX":r.set(a*h,l*p,l*f,a*c);break;case"YXY":r.set(l*f,a*h,l*p,a*c);break;case"ZYZ":r.set(l*p,l*f,a*h,a*c);break;default:de("MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+i)}}function ln(r,e){switch(e.constructor){case Float32Array:return r;case Uint32Array:return r/4294967295;case Uint16Array:return r/65535;case Uint8Array:case Uint8ClampedArray:return r/255;case Int32Array:return Math.max(r/2147483647,-1);case Int16Array:return Math.max(r/32767,-1);case Int8Array:return Math.max(r/127,-1);default:throw new Error("THREE.MathUtils: Invalid component type.")}}function Ke(r,e){switch(e.constructor){case Float32Array:return r;case Uint32Array:return Math.round(r*4294967295);case Uint16Array:return Math.round(r*65535);case Uint8Array:case Uint8ClampedArray:return Math.round(r*255);case Int32Array:return Math.round(r*2147483647);case Int16Array:return Math.round(r*32767);case Int8Array:return Math.round(r*127);default:throw new Error("THREE.MathUtils: Invalid component type.")}}var mo={DEG2RAD:Ts,RAD2DEG:Es,generateUUID:Tn,clamp:He,euclideanModulo:ef,mapLinear:R_,inverseLerp:C_,lerp:Bo,damp:I_,pingpong:P_,smoothstep:L_,smootherstep:N_,randInt:D_,randFloat:U_,randFloatSpread:F_,seededRandom:O_,degToRad:B_,radToDeg:z_,isPowerOfTwo:k_,ceilPowerOfTwo:V_,floorPowerOfTwo:G_,setQuaternionFromProperEuler:H_,normalize:Ke,denormalize:ln},J=class r{static{r.prototype.isVector2=!0}constructor(e=0,t=0){this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("THREE.Vector2: index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("THREE.Vector2: index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){let t=this.x,n=this.y,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6],this.y=i[1]*t+i[4]*n+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=He(this.x,e.x,t.x),this.y=He(this.y,e.y,t.y),this}clampScalar(e,t){return this.x=He(this.x,e,t),this.y=He(this.y,e,t),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(He(n,e,t))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;let n=this.dot(e)/t;return Math.acos(He(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){let n=Math.cos(t),i=Math.sin(t),s=this.x-e.x,o=this.y-e.y;return this.x=s*n-o*i+e.x,this.y=s*i+o*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}},wt=class{constructor(e=0,t=0,n=0,i=1){this.isQuaternion=!0,this._x=e,this._y=t,this._z=n,this._w=i}static slerpFlat(e,t,n,i,s,o,a){let l=n[i+0],c=n[i+1],h=n[i+2],u=n[i+3],d=s[o+0],f=s[o+1],p=s[o+2],_=s[o+3];if(u!==_||l!==d||c!==f||h!==p){let g=l*d+c*f+h*p+u*_;g<0&&(d=-d,f=-f,p=-p,_=-_,g=-g);let m=1-a;if(g<.9995){let y=Math.acos(g),b=Math.sin(y);m=Math.sin(m*y)/b,a=Math.sin(a*y)/b,l=l*m+d*a,c=c*m+f*a,h=h*m+p*a,u=u*m+_*a}else{l=l*m+d*a,c=c*m+f*a,h=h*m+p*a,u=u*m+_*a;let y=1/Math.sqrt(l*l+c*c+h*h+u*u);l*=y,c*=y,h*=y,u*=y}}e[t]=l,e[t+1]=c,e[t+2]=h,e[t+3]=u}static multiplyQuaternionsFlat(e,t,n,i,s,o){let a=n[i],l=n[i+1],c=n[i+2],h=n[i+3],u=s[o],d=s[o+1],f=s[o+2],p=s[o+3];return e[t]=a*p+h*u+l*f-c*d,e[t+1]=l*p+h*d+c*u-a*f,e[t+2]=c*p+h*f+a*d-l*u,e[t+3]=h*p-a*u-l*d-c*f,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){let n=e._x,i=e._y,s=e._z,o=e._order,a=Math.cos,l=Math.sin,c=a(n/2),h=a(i/2),u=a(s/2),d=l(n/2),f=l(i/2),p=l(s/2);switch(o){case"XYZ":this._x=d*h*u+c*f*p,this._y=c*f*u-d*h*p,this._z=c*h*p+d*f*u,this._w=c*h*u-d*f*p;break;case"YXZ":this._x=d*h*u+c*f*p,this._y=c*f*u-d*h*p,this._z=c*h*p-d*f*u,this._w=c*h*u+d*f*p;break;case"ZXY":this._x=d*h*u-c*f*p,this._y=c*f*u+d*h*p,this._z=c*h*p+d*f*u,this._w=c*h*u-d*f*p;break;case"ZYX":this._x=d*h*u-c*f*p,this._y=c*f*u+d*h*p,this._z=c*h*p-d*f*u,this._w=c*h*u+d*f*p;break;case"YZX":this._x=d*h*u+c*f*p,this._y=c*f*u+d*h*p,this._z=c*h*p-d*f*u,this._w=c*h*u-d*f*p;break;case"XZY":this._x=d*h*u-c*f*p,this._y=c*f*u-d*h*p,this._z=c*h*p+d*f*u,this._w=c*h*u+d*f*p;break;default:de("Quaternion: .setFromEuler() encountered an unknown order: "+o)}return t===!0&&this._onChangeCallback(),this}setFromAxisAngle(e,t){let n=t/2,i=Math.sin(n);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){let t=e.elements,n=t[0],i=t[4],s=t[8],o=t[1],a=t[5],l=t[9],c=t[2],h=t[6],u=t[10],d=n+a+u;if(d>0){let f=.5/Math.sqrt(d+1);this._w=.25/f,this._x=(h-l)*f,this._y=(s-c)*f,this._z=(o-i)*f}else if(n>a&&n>u){let f=2*Math.sqrt(1+n-a-u);this._w=(h-l)/f,this._x=.25*f,this._y=(i+o)/f,this._z=(s+c)/f}else if(a>u){let f=2*Math.sqrt(1+a-n-u);this._w=(s-c)/f,this._x=(i+o)/f,this._y=.25*f,this._z=(l+h)/f}else{let f=2*Math.sqrt(1+u-n-a);this._w=(o-i)/f,this._x=(s+c)/f,this._y=(l+h)/f,this._z=.25*f}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return n<1e-8?(n=0,Math.abs(e.x)>Math.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(He(this.dot(e),-1,1)))}rotateTowards(e,t){let n=this.angleTo(e);if(n===0)return this;let i=Math.min(1,t/n);return this.slerp(e,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let e=this.length();return e===0?(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(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){let n=e._x,i=e._y,s=e._z,o=e._w,a=t._x,l=t._y,c=t._z,h=t._w;return this._x=n*h+o*a+i*c-s*l,this._y=i*h+o*l+s*a-n*c,this._z=s*h+o*c+n*l-i*a,this._w=o*h-n*a-i*l-s*c,this._onChangeCallback(),this}slerp(e,t){let n=e._x,i=e._y,s=e._z,o=e._w,a=this.dot(e);a<0&&(n=-n,i=-i,s=-s,o=-o,a=-a);let l=1-t;if(a<.9995){let c=Math.acos(a),h=Math.sin(c);l=Math.sin(l*c)/h,t=Math.sin(t*c)/h,this._x=this._x*l+n*t,this._y=this._y*l+i*t,this._z=this._z*l+s*t,this._w=this._w*l+o*t,this._onChangeCallback()}else this._x=this._x*l+n*t,this._y=this._y*l+i*t,this._z=this._z*l+s*t,this._w=this._w*l+o*t,this.normalize();return this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){let e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),i=Math.sqrt(1-n),s=Math.sqrt(n);return this.set(i*Math.sin(e),i*Math.cos(e),s*Math.sin(t),s*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}},R=class r{static{r.prototype.isVector3=!0}constructor(e=0,t=0,n=0){this.x=e,this.y=t,this.z=n}set(e,t,n){return n===void 0&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(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("THREE.Vector3: index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("THREE.Vector3: index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(mp.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(mp.setFromAxisAngle(e,t))}applyMatrix3(e){let t=this.x,n=this.y,i=this.z,s=e.elements;return this.x=s[0]*t+s[3]*n+s[6]*i,this.y=s[1]*t+s[4]*n+s[7]*i,this.z=s[2]*t+s[5]*n+s[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){let t=this.x,n=this.y,i=this.z,s=e.elements,o=1/(s[3]*t+s[7]*n+s[11]*i+s[15]);return this.x=(s[0]*t+s[4]*n+s[8]*i+s[12])*o,this.y=(s[1]*t+s[5]*n+s[9]*i+s[13])*o,this.z=(s[2]*t+s[6]*n+s[10]*i+s[14])*o,this}applyQuaternion(e){let t=this.x,n=this.y,i=this.z,s=e.x,o=e.y,a=e.z,l=e.w,c=2*(o*i-a*n),h=2*(a*t-s*i),u=2*(s*n-o*t);return this.x=t+l*c+o*u-a*h,this.y=n+l*h+a*c-s*u,this.z=i+l*u+s*h-o*c,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){let t=this.x,n=this.y,i=this.z,s=e.elements;return this.x=s[0]*t+s[4]*n+s[8]*i,this.y=s[1]*t+s[5]*n+s[9]*i,this.z=s[2]*t+s[6]*n+s[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(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(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(e,t){return this.x=He(this.x,e.x,t.x),this.y=He(this.y,e.y,t.y),this.z=He(this.z,e.z,t.z),this}clampScalar(e,t){return this.x=He(this.x,e,t),this.y=He(this.y,e,t),this.z=He(this.z,e,t),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(He(n,e,t))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(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(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){let n=e.x,i=e.y,s=e.z,o=t.x,a=t.y,l=t.z;return this.x=i*l-s*a,this.y=s*o-n*l,this.z=n*a-i*o,this}projectOnVector(e){let t=e.lengthSq();if(t===0)return this.set(0,0,0);let n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return Su.copy(this).projectOnVector(e),this.sub(Su)}reflect(e){return this.sub(Su.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;let n=this.dot(e)/t;return Math.acos(He(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,n=this.y-e.y,i=this.z-e.z;return t*t+n*n+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){let i=Math.sin(t)*e;return this.x=i*Math.sin(n),this.y=Math.cos(t)*e,this.z=i*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){let t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){let t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,t*4)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,t*3)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){let e=Math.random()*Math.PI*2,t=Math.random()*2-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}},Su=new R,mp=new wt,qe=class r{static{r.prototype.isMatrix3=!0}constructor(e,t,n,i,s,o,a,l,c){this.elements=[1,0,0,0,1,0,0,0,1],e!==void 0&&this.set(e,t,n,i,s,o,a,l,c)}set(e,t,n,i,s,o,a,l,c){let h=this.elements;return h[0]=e,h[1]=i,h[2]=a,h[3]=t,h[4]=s,h[5]=l,h[6]=n,h[7]=o,h[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){let t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){let 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}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){let n=e.elements,i=t.elements,s=this.elements,o=n[0],a=n[3],l=n[6],c=n[1],h=n[4],u=n[7],d=n[2],f=n[5],p=n[8],_=i[0],g=i[3],m=i[6],y=i[1],b=i[4],x=i[7],T=i[2],S=i[5],w=i[8];return s[0]=o*_+a*y+l*T,s[3]=o*g+a*b+l*S,s[6]=o*m+a*x+l*w,s[1]=c*_+h*y+u*T,s[4]=c*g+h*b+u*S,s[7]=c*m+h*x+u*w,s[2]=d*_+f*y+p*T,s[5]=d*g+f*b+p*S,s[8]=d*m+f*x+p*w,this}multiplyScalar(e){let t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){let e=this.elements,t=e[0],n=e[1],i=e[2],s=e[3],o=e[4],a=e[5],l=e[6],c=e[7],h=e[8];return t*o*h-t*a*c-n*s*h+n*a*l+i*s*c-i*o*l}invert(){let e=this.elements,t=e[0],n=e[1],i=e[2],s=e[3],o=e[4],a=e[5],l=e[6],c=e[7],h=e[8],u=h*o-a*c,d=a*l-h*s,f=c*s-o*l,p=t*u+n*d+i*f;if(p===0)return this.set(0,0,0,0,0,0,0,0,0);let _=1/p;return e[0]=u*_,e[1]=(i*c-h*n)*_,e[2]=(a*n-i*o)*_,e[3]=d*_,e[4]=(h*t-i*l)*_,e[5]=(i*s-a*t)*_,e[6]=f*_,e[7]=(n*l-c*t)*_,e[8]=(o*t-n*s)*_,this}transpose(){let e,t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){let t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,i,s,o,a){let l=Math.cos(s),c=Math.sin(s);return this.set(n*l,n*c,-n*(l*o+c*a)+o+e,-i*c,i*l,-i*(-c*o+l*a)+a+t,0,0,1),this}scale(e,t){return ai("Matrix3: .scale() is deprecated. Use .makeScale() instead."),this.premultiply(bu.makeScale(e,t)),this}rotate(e){return ai("Matrix3: .rotate() is deprecated. Use .makeRotation() instead."),this.premultiply(bu.makeRotation(-e)),this}translate(e,t){return ai("Matrix3: .translate() is deprecated. Use .makeTranslation() instead."),this.premultiply(bu.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){let t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){let t=this.elements,n=e.elements;for(let i=0;i<9;i++)if(t[i]!==n[i])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){let n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return new this.constructor().fromArray(this.elements)}},bu=new qe,gp=new qe().set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),_p=new qe().set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function W_(){let r={enabled:!0,workingColorSpace:nn,spaces:{},convert:function(i,s,o){return this.enabled===!1||s===o||!s||!o||(this.spaces[s].transfer===ht&&(i.r=Ci(i.r),i.g=Ci(i.g),i.b=Ci(i.b)),this.spaces[s].primaries!==this.spaces[o].primaries&&(i.applyMatrix3(this.spaces[s].toXYZ),i.applyMatrix3(this.spaces[o].fromXYZ)),this.spaces[o].transfer===ht&&(i.r=Tr(i.r),i.g=Tr(i.g),i.b=Tr(i.b))),i},workingToColorSpace:function(i,s){return this.convert(i,this.workingColorSpace,s)},colorSpaceToWorking:function(i,s){return this.convert(i,s,this.workingColorSpace)},getPrimaries:function(i){return this.spaces[i].primaries},getTransfer:function(i){return i===yi?Er:this.spaces[i].transfer},getToneMappingMode:function(i){return this.spaces[i].outputColorSpaceConfig.toneMappingMode||"standard"},getLuminanceCoefficients:function(i,s=this.workingColorSpace){return i.fromArray(this.spaces[s].luminanceCoefficients)},define:function(i){Object.assign(this.spaces,i)},_getMatrix:function(i,s,o){return i.copy(this.spaces[s].toXYZ).multiply(this.spaces[o].fromXYZ)},_getDrawingBufferColorSpace:function(i){return this.spaces[i].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(i=this.workingColorSpace){return this.spaces[i].workingColorSpaceConfig.unpackColorSpace},fromWorkingColorSpace:function(i,s){return ai("ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace()."),r.workingToColorSpace(i,s)},toWorkingColorSpace:function(i,s){return ai("ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking()."),r.colorSpaceToWorking(i,s)}},e=[.64,.33,.3,.6,.15,.06],t=[.2126,.7152,.0722],n=[.3127,.329];return r.define({[nn]:{primaries:e,whitePoint:n,transfer:Er,toXYZ:gp,fromXYZ:_p,luminanceCoefficients:t,workingColorSpaceConfig:{unpackColorSpace:Tt},outputColorSpaceConfig:{drawingBufferColorSpace:Tt}},[Tt]:{primaries:e,whitePoint:n,transfer:ht,toXYZ:gp,fromXYZ:_p,luminanceCoefficients:t,outputColorSpaceConfig:{drawingBufferColorSpace:Tt}}}),r}var Je=W_();function Ci(r){return r<.04045?r*.0773993808:Math.pow(r*.9478672986+.0521327014,2.4)}function Tr(r){return r<.0031308?r*12.92:1.055*Math.pow(r,.41666)-.055}var ir,Ko=class{static getDataURL(e,t="image/png"){if(/^data:/i.test(e.src)||typeof HTMLCanvasElement>"u")return e.src;let n;if(e instanceof HTMLCanvasElement)n=e;else{ir===void 0&&(ir=wr("canvas")),ir.width=e.width,ir.height=e.height;let i=ir.getContext("2d");e instanceof ImageData?i.putImageData(e,0,0):i.drawImage(e,0,0,e.width,e.height),n=ir}return n.toDataURL(t)}static sRGBToLinear(e){if(typeof HTMLImageElement<"u"&&e instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&e instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&e instanceof ImageBitmap){let t=wr("canvas");t.width=e.width,t.height=e.height;let n=t.getContext("2d");n.drawImage(e,0,0,e.width,e.height);let i=n.getImageData(0,0,e.width,e.height),s=i.data;for(let o=0;o1),this.pmremVersion=0,this.normalized=!1}get width(){return this.source.getSize(Au).x}get height(){return this.source.getSize(Au).y}get depth(){return this.source.getSize(Au).z}get image(){return this.source.data}set image(e){this.source.data=e}updateMatrix(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}clone(){return new this.constructor().copy(this)}copy(e){return this.name=e.name,this.source=e.source,this.mipmaps=e.mipmaps.slice(0),this.mapping=e.mapping,this.channel=e.channel,this.wrapS=e.wrapS,this.wrapT=e.wrapT,this.magFilter=e.magFilter,this.minFilter=e.minFilter,this.anisotropy=e.anisotropy,this.format=e.format,this.internalFormat=e.internalFormat,this.type=e.type,this.normalized=e.normalized,this.offset.copy(e.offset),this.repeat.copy(e.repeat),this.center.copy(e.center),this.rotation=e.rotation,this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrix.copy(e.matrix),this.generateMipmaps=e.generateMipmaps,this.premultiplyAlpha=e.premultiplyAlpha,this.flipY=e.flipY,this.unpackAlignment=e.unpackAlignment,this.colorSpace=e.colorSpace,this.renderTarget=e.renderTarget,this.isRenderTargetTexture=e.isRenderTargetTexture,this.isArrayTexture=e.isArrayTexture,this.userData=JSON.parse(JSON.stringify(e.userData)),this.needsUpdate=!0,this}setValues(e){for(let t in e){let n=e[t];if(n===void 0){de(`Texture.setValues(): parameter '${t}' has value of undefined.`);continue}let i=this[t];if(i===void 0){de(`Texture.setValues(): property '${t}' does not exist.`);continue}i&&n&&i.isVector2&&n.isVector2||i&&n&&i.isVector3&&n.isVector3||i&&n&&i.isMatrix3&&n.isMatrix3?i.copy(n):this[t]=n}}toJSON(e){let t=e===void 0||typeof e=="string";if(!t&&e.textures[this.uuid]!==void 0)return e.textures[this.uuid];let n={metadata:{version:4.7,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,image:this.source.toJSON(e).uuid,mapping:this.mapping,channel:this.channel,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,internalFormat:this.internalFormat,type:this.type,normalized:this.normalized,colorSpace:this.colorSpace,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,generateMipmaps:this.generateMipmaps,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};return Object.keys(this.userData).length>0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(this.mapping!==Ka)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case li:e.x=e.x-Math.floor(e.x);break;case Yt:e.x=e.x<0?0:1;break;case $i:Math.abs(Math.floor(e.x)%2)===1?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x);break}if(e.y<0||e.y>1)switch(this.wrapT){case li:e.y=e.y-Math.floor(e.y);break;case Yt:e.y=e.y<0?0:1;break;case $i:Math.abs(Math.floor(e.y)%2)===1?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y);break}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){e===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){e===!0&&this.pmremVersion++}};Et.DEFAULT_IMAGE=null;Et.DEFAULT_MAPPING=Ka;Et.DEFAULT_ANISOTROPY=1;var mt=class r{static{r.prototype.isVector4=!0}constructor(e=0,t=0,n=0,i=1){this.x=e,this.y=t,this.z=n,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,i){return this.x=e,this.y=t,this.z=n,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(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("THREE.Vector4: index is out of range: "+e)}return this}getComponent(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("THREE.Vector4: index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=e.w!==void 0?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(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(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(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(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}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){let t=this.x,n=this.y,i=this.z,s=this.w,o=e.elements;return this.x=o[0]*t+o[4]*n+o[8]*i+o[12]*s,this.y=o[1]*t+o[5]*n+o[9]*i+o[13]*s,this.z=o[2]*t+o[6]*n+o[10]*i+o[14]*s,this.w=o[3]*t+o[7]*n+o[11]*i+o[15]*s,this}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this.w/=e.w,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);let 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(e){let t,n,i,s,l=e.elements,c=l[0],h=l[4],u=l[8],d=l[1],f=l[5],p=l[9],_=l[2],g=l[6],m=l[10];if(Math.abs(h-d)<.01&&Math.abs(u-_)<.01&&Math.abs(p-g)<.01){if(Math.abs(h+d)<.1&&Math.abs(u+_)<.1&&Math.abs(p+g)<.1&&Math.abs(c+f+m-3)<.1)return this.set(1,0,0,0),this;t=Math.PI;let b=(c+1)/2,x=(f+1)/2,T=(m+1)/2,S=(h+d)/4,w=(u+_)/4,v=(p+g)/4;return b>x&&b>T?b<.01?(n=0,i=.707106781,s=.707106781):(n=Math.sqrt(b),i=S/n,s=w/n):x>T?x<.01?(n=.707106781,i=0,s=.707106781):(i=Math.sqrt(x),n=S/i,s=v/i):T<.01?(n=.707106781,i=.707106781,s=0):(s=Math.sqrt(T),n=w/s,i=v/s),this.set(n,i,s,t),this}let y=Math.sqrt((g-p)*(g-p)+(u-_)*(u-_)+(d-h)*(d-h));return Math.abs(y)<.001&&(y=1),this.x=(g-p)/y,this.y=(u-_)/y,this.z=(d-h)/y,this.w=Math.acos((c+f+m-1)/2),this}setFromMatrixPosition(e){let t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this.w=t[15],this}min(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(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(e,t){return this.x=He(this.x,e.x,t.x),this.y=He(this.y,e.y,t.y),this.z=He(this.z,e.z,t.z),this.w=He(this.w,e.w,t.w),this}clampScalar(e,t){return this.x=He(this.x,e,t),this.y=He(this.y,e,t),this.z=He(this.z,e,t),this.w=He(this.w,e,t),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(He(n,e,t))}floor(){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(){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(){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(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(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(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this.w=e.w+(t.w-e.w)*n,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z&&e.w===this.w}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this.w=e[t+3],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e[t+3]=this.w,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this.w=e.getW(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}},Cr=class extends xn{constructor(e=1,t=1,n={}){super(),n=Object.assign({generateMipmaps:!1,internalFormat:null,minFilter:pt,depthBuffer:!0,stencilBuffer:!1,resolveColorBuffer:!0,resolveDepthBuffer:!0,resolveStencilBuffer:!0,storeMultisampledColorBuffer:!0,storeMultisampledDepthBuffer:!0,storeMultisampledStencilBuffer:!0,depthTexture:null,samples:0,count:1,depth:1,multiview:!1,useArrayDepthTexture:!1},n),this.isRenderTarget=!0,this.width=e,this.height=t,this.depth=n.depth,this.scissor=new mt(0,0,e,t),this.scissorTest=!1,this.viewport=new mt(0,0,e,t),this.textures=[];let i={width:e,height:t,depth:n.depth},s=new Et(i),o=n.count;for(let a=0;a1);this.dispose()}this.viewport.set(0,0,e,t),this.scissor.set(0,0,e,t)}clone(){return new this.constructor().copy(this)}copy(e){this.width=e.width,this.height=e.height,this.depth=e.depth,this.scissor.copy(e.scissor),this.scissorTest=e.scissorTest,this.viewport.copy(e.viewport),this.textures.length=0;for(let t=0,n=e.textures.length;t>>0}enable(e){this.mask|=1<1){for(let t=0;t1){for(let n=0;n0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),this.pivot!==null&&(i.pivot=this.pivot.toArray()),this.morphTargetDictionary!==void 0&&(i.morphTargetDictionary=Object.assign({},this.morphTargetDictionary)),this.morphTargetInfluences!==void 0&&(i.morphTargetInfluences=this.morphTargetInfluences.slice()),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.geometryInfo=this._geometryInfo.map(a=>({...a,boundingBox:a.boundingBox?a.boundingBox.toJSON():void 0,boundingSphere:a.boundingSphere?a.boundingSphere.toJSON():void 0})),i.instanceInfo=this._instanceInfo.map(a=>({...a})),i.availableInstanceIds=this._availableInstanceIds.slice(),i.availableGeometryIds=this._availableGeometryIds.slice(),i.nextIndexStart=this._nextIndexStart,i.nextVertexStart=this._nextVertexStart,i.geometryCount=this._geometryCount,i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.matricesTexture=this._matricesTexture.toJSON(e),i.indirectTexture=this._indirectTexture.toJSON(e),this._colorsTexture!==null&&(i.colorsTexture=this._colorsTexture.toJSON(e)),this.boundingSphere!==null&&(i.boundingSphere=this.boundingSphere.toJSON()),this.boundingBox!==null&&(i.boundingBox=this.boundingBox.toJSON()));function s(a,l){return a[l.uuid]===void 0&&(a[l.uuid]=l.toJSON(e)),l.uuid}if(this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=s(e.geometries,this.geometry);let a=this.geometry.parameters;if(a!==void 0&&a.shapes!==void 0){let l=a.shapes;if(Array.isArray(l))for(let c=0,h=l.length;c0){i.children=[];for(let a=0;a0){i.animations=[];for(let a=0;a0&&(n.geometries=a),l.length>0&&(n.materials=l),c.length>0&&(n.textures=c),h.length>0&&(n.images=h),u.length>0&&(n.shapes=u),d.length>0&&(n.skeletons=d),f.length>0&&(n.animations=f),p.length>0&&(n.nodes=p)}return n.object=i,n;function o(a){let l=[];for(let c in a){let h=a[c];delete h.metadata,l.push(h)}return l}}clone(e){return new this.constructor().copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.pivot=e.pivot!==null?e.pivot.clone():null,this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,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.static=e.static,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),t===!0)for(let n=0;nf+p?(c.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!c.inputState.pinching&&d<=f-p&&(c.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else l!==null&&e.gripSpace&&(s=t.getPose(e.gripSpace,n),s!==null&&(l.matrix.fromArray(s.transform.matrix),l.matrix.decompose(l.position,l.rotation,l.scale),l.matrixWorldNeedsUpdate=!0,s.linearVelocity?(l.hasLinearVelocity=!0,l.linearVelocity.copy(s.linearVelocity)):l.hasLinearVelocity=!1,s.angularVelocity?(l.hasAngularVelocity=!0,l.angularVelocity.copy(s.angularVelocity)):l.hasAngularVelocity=!1,l.eventsEnabled&&l.dispatchEvent({type:"gripUpdated",data:e,target:this})));a!==null&&(i=t.getPose(e.targetRaySpace,n),i===null&&s!==null&&(i=s),i!==null&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Q_)))}return a!==null&&(a.visible=i!==null),l!==null&&(l.visible=s!==null),c!==null&&(c.visible=o!==null),this}_getHandJoint(e,t){if(e.joints[t.jointName]===void 0){let n=new cn;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}},xg={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Xi={h:0,s:0,l:0},ql={h:0,s:0,l:0};function wu(r,e,t){return t<0&&(t+=1),t>1&&(t-=1),t<1/6?r+(e-r)*6*t:t<1/2?e:t<2/3?r+(e-r)*6*(2/3-t):r}var ce=class{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(t===void 0&&n===void 0){let i=e;i&&i.isColor?this.copy(i):typeof i=="number"?this.setHex(i):typeof i=="string"&&this.setStyle(i)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=Tt){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(e&255)/255,Je.colorSpaceToWorking(this,t),this}setRGB(e,t,n,i=Je.workingColorSpace){return this.r=e,this.g=t,this.b=n,Je.colorSpaceToWorking(this,i),this}setHSL(e,t,n,i=Je.workingColorSpace){if(e=ef(e,1),t=He(t,0,1),n=He(n,0,1),t===0)this.r=this.g=this.b=n;else{let s=n<=.5?n*(1+t):n+t-n*t,o=2*n-s;this.r=wu(o,s,e+1/3),this.g=wu(o,s,e),this.b=wu(o,s,e-1/3)}return Je.colorSpaceToWorking(this,i),this}setStyle(e,t=Tt){function n(s){s!==void 0&&parseFloat(s)<1&&de("Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let s,o=i[1],a=i[2];switch(o){case"rgb":case"rgba":if(s=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(s[4]),this.setRGB(Math.min(255,parseInt(s[1],10))/255,Math.min(255,parseInt(s[2],10))/255,Math.min(255,parseInt(s[3],10))/255,t);if(s=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(s[4]),this.setRGB(Math.min(100,parseInt(s[1],10))/100,Math.min(100,parseInt(s[2],10))/100,Math.min(100,parseInt(s[3],10))/100,t);break;case"hsl":case"hsla":if(s=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(s[4]),this.setHSL(parseFloat(s[1])/360,parseFloat(s[2])/100,parseFloat(s[3])/100,t);break;default:de("Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){let s=i[1],o=s.length;if(o===3)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,t);if(o===6)return this.setHex(parseInt(s,16),t);de("Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=Tt){let n=xg[e.toLowerCase()];return n!==void 0?this.setHex(n,t):de("Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=Ci(e.r),this.g=Ci(e.g),this.b=Ci(e.b),this}copyLinearToSRGB(e){return this.r=Tr(e.r),this.g=Tr(e.g),this.b=Tr(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=Tt){return Je.workingToColorSpace($t.copy(this),e),Math.round(He($t.r*255,0,255))*65536+Math.round(He($t.g*255,0,255))*256+Math.round(He($t.b*255,0,255))}getHexString(e=Tt){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=Je.workingColorSpace){Je.workingToColorSpace($t.copy(this),t);let n=$t.r,i=$t.g,s=$t.b,o=Math.max(n,i,s),a=Math.min(n,i,s),l,c,h=(a+o)/2;if(a===o)l=0,c=0;else{let u=o-a;switch(c=h<=.5?u/(o+a):u/(2-o-a),o){case n:l=(i-s)/u+(i0?i.multiplyScalar(1/Math.sqrt(s)):i.set(0,0,0)}static getBarycoord(e,t,n,i,s){Hn.subVectors(i,t),bi.subVectors(n,t),Ru.subVectors(e,t);let o=Hn.dot(Hn),a=Hn.dot(bi),l=Hn.dot(Ru),c=bi.dot(bi),h=bi.dot(Ru),u=o*c-a*a;if(u===0)return s.set(0,0,0),null;let d=1/u,f=(c*l-a*h)*d,p=(o*h-a*l)*d;return s.set(1-f-p,p,f)}static containsPoint(e,t,n,i){return this.getBarycoord(e,t,n,i,Ti)===null?!1:Ti.x>=0&&Ti.y>=0&&Ti.x+Ti.y<=1}static getInterpolation(e,t,n,i,s,o,a,l){return this.getBarycoord(e,t,n,i,Ti)===null?(l.x=0,l.y=0,"z"in l&&(l.z=0),"w"in l&&(l.w=0),null):(l.setScalar(0),l.addScaledVector(s,Ti.x),l.addScaledVector(o,Ti.y),l.addScaledVector(a,Ti.z),l)}static getInterpolatedAttribute(e,t,n,i,s,o){return Lu.setScalar(0),Nu.setScalar(0),Du.setScalar(0),Lu.fromBufferAttribute(e,t),Nu.fromBufferAttribute(e,n),Du.fromBufferAttribute(e,i),o.setScalar(0),o.addScaledVector(Lu,s.x),o.addScaledVector(Nu,s.y),o.addScaledVector(Du,s.z),o}static isFrontFacing(e,t,n,i){return Hn.subVectors(n,t),bi.subVectors(e,t),Hn.cross(bi).dot(i)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,i){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,n,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,i),this}clone(){return new this.constructor().copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Hn.subVectors(this.c,this.b),bi.subVectors(this.a,this.b),Hn.cross(bi).length()*.5}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return r.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return r.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,n,i,s){return r.getInterpolation(e,this.a,this.b,this.c,t,n,i,s)}containsPoint(e){return r.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return r.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){let n=this.a,i=this.b,s=this.c,o,a;ar.subVectors(i,n),lr.subVectors(s,n),Cu.subVectors(e,n);let l=ar.dot(Cu),c=lr.dot(Cu);if(l<=0&&c<=0)return t.copy(n);Iu.subVectors(e,i);let h=ar.dot(Iu),u=lr.dot(Iu);if(h>=0&&u<=h)return t.copy(i);let d=l*u-h*c;if(d<=0&&l>=0&&h<=0)return o=l/(l-h),t.copy(n).addScaledVector(ar,o);Pu.subVectors(e,s);let f=ar.dot(Pu),p=lr.dot(Pu);if(p>=0&&f<=p)return t.copy(s);let _=f*c-l*p;if(_<=0&&c>=0&&p<=0)return a=c/(c-p),t.copy(n).addScaledVector(lr,a);let g=h*p-f*u;if(g<=0&&u-h>=0&&f-p>=0)return Ap.subVectors(s,i),a=(u-h)/(u-h+(f-p)),t.copy(i).addScaledVector(Ap,a);let m=1/(g+_+d);return o=_*m,a=d*m,t.copy(n).addScaledVector(ar,o).addScaledVector(lr,a)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}},Ft=class{constructor(e=new R(1/0,1/0,1/0),t=new R(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(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(e,t){return 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(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Wn),Wn.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(bo),Zl.subVectors(this.max,bo),cr.subVectors(e.a,bo),hr.subVectors(e.b,bo),ur.subVectors(e.c,bo),qi.subVectors(hr,cr),Yi.subVectors(ur,hr),ds.subVectors(cr,ur);let t=[0,-qi.z,qi.y,0,-Yi.z,Yi.y,0,-ds.z,ds.y,qi.z,0,-qi.x,Yi.z,0,-Yi.x,ds.z,0,-ds.x,-qi.y,qi.x,0,-Yi.y,Yi.x,0,-ds.y,ds.x,0];return!Uu(t,cr,hr,ur,Zl)||(t=[1,0,0,0,1,0,0,0,1],!Uu(t,cr,hr,ur,Zl))?!1:(Kl.crossVectors(qi,Yi),t=[Kl.x,Kl.y,Kl.z],Uu(t,cr,hr,ur,Zl))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Wn).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=this.getSize(Wn).length()*.5),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()?this:(Ai[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Ai[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Ai[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Ai[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Ai[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Ai[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Ai[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Ai[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Ai),this)}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}toJSON(){return{min:this.min.toArray(),max:this.max.toArray()}}fromJSON(e){return this.min.fromArray(e.min),this.max.fromArray(e.max),this}},Ai=[new R,new R,new R,new R,new R,new R,new R,new R],Wn=new R,Yl=new Ft,cr=new R,hr=new R,ur=new R,qi=new R,Yi=new R,ds=new R,bo=new R,Zl=new R,Kl=new R,fs=new R;function Uu(r,e,t,n,i){for(let s=0,o=r.length-3;s<=o;s+=3){fs.fromArray(r,s);let a=i.x*Math.abs(fs.x)+i.y*Math.abs(fs.y)+i.z*Math.abs(fs.z),l=e.dot(fs),c=t.dot(fs),h=n.dot(fs);if(Math.max(-Math.max(l,c,h),Math.min(l,c,h))>a)return!1}return!0}var Ri=e0();function e0(){let r=new ArrayBuffer(4),e=new Float32Array(r),t=new Uint32Array(r),n=new Uint32Array(512),i=new Uint32Array(512);for(let l=0;l<256;++l){let c=l-127;c<-27?(n[l]=0,n[l|256]=32768,i[l]=24,i[l|256]=24):c<-14?(n[l]=1024>>-c-14,n[l|256]=1024>>-c-14|32768,i[l]=-c-1,i[l|256]=-c-1):c<=15?(n[l]=c+15<<10,n[l|256]=c+15<<10|32768,i[l]=13,i[l|256]=13):c<128?(n[l]=31744,n[l|256]=64512,i[l]=24,i[l|256]=24):(n[l]=31744,n[l|256]=64512,i[l]=13,i[l|256]=13)}let s=new Uint32Array(2048),o=new Uint32Array(64),a=new Uint32Array(64);for(let l=1;l<1024;++l){let c=l<<13,h=0;for(;(c&8388608)===0;)c<<=1,h-=8388608;c&=-8388609,h+=947912704,s[l]=c|h}for(let l=1024;l<2048;++l)s[l]=939524096+(l-1024<<13);for(let l=1;l<31;++l)o[l]=l<<23;o[31]=1199570944,o[32]=2147483648;for(let l=33;l<63;++l)o[l]=2147483648+(l-32<<23);o[63]=3347054592;for(let l=1;l<64;++l)l!==32&&(a[l]=1024);return{floatView:e,uint32View:t,baseTable:n,shiftTable:i,mantissaTable:s,exponentTable:o,offsetTable:a}}function mn(r){Math.abs(r)>65504&&de("DataUtils.toHalfFloat(): Value out of range."),r=He(r,-65504,65504),Ri.floatView[0]=r;let e=Ri.uint32View[0],t=e>>23&511;return Ri.baseTable[t]+((e&8388607)>>Ri.shiftTable[t])}function Do(r){let e=r>>10;return Ri.uint32View[0]=Ri.mantissaTable[Ri.offsetTable[e]+(r&1023)]+Ri.exponentTable[e],Ri.floatView[0]}var Bc=class{static toHalfFloat(e){return mn(e)}static fromHalfFloat(e){return Do(e)}},zt=new R,Jl=new J,t0=0,Qe=class extends xn{constructor(e,t,n=!1){if(super(),Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,Object.defineProperty(this,"id",{value:t0++}),this.name="",this.array=e,this.itemSize=t,this.count=e!==void 0?e.length/t:0,this.normalized=n,this.usage=Ul,this.updateRanges=[],this.gpuType=en,this.version=0}onUploadCallback(){}set needsUpdate(e){e===!0&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let i=0,s=this.itemSize;ithis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;To.subVectors(e,this.center);let t=To.lengthSq();if(t>this.radius*this.radius){let n=Math.sqrt(t),i=(n-this.radius)*.5;this.center.addScaledVector(To,i/n),this.radius+=i}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(this.center.equals(e.center)===!0?this.radius=Math.max(this.radius,e.radius):(Fu.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(To.copy(e.center).add(Fu)),this.expandByPoint(To.copy(e.center).sub(Fu))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return new this.constructor().copy(this)}toJSON(){return{radius:this.radius,center:this.center.toArray()}}fromJSON(e){return this.radius=e.radius,this.center.fromArray(e.center),this}},i0=0,Pn=new ze,Ou=new st,dr=new R,bn=new Ft,Ao=new Ft,Wt=new R,Oe=class r extends xn{constructor(){super(),this.isBufferGeometry=!0,Object.defineProperty(this,"id",{value:i0++}),this.uuid=Tn(),this.name="",this.type="BufferGeometry",this.index=null,this.indirect=null,this.indirectOffset=0,this.attributes={},this.morphAttributes={},this.morphTargetsRelative=!1,this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.drawRange={start:0,count:1/0},this.userData={},this._transformed=!1}getIndex(){return this.index}setIndex(e){return Array.isArray(e)?this.index=new(E_(e)?Pr:Ir)(e,1):this.index=e,this}setIndirect(e,t=0){return this.indirect=e,this.indirectOffset=t,this}getIndirect(){return this.indirect}getAttribute(e){return this.attributes[e]}setAttribute(e,t){return this.attributes[e]=t,this}deleteAttribute(e){return delete this.attributes[e],this}hasAttribute(e){return this.attributes[e]!==void 0}addGroup(e,t,n=0){this.groups.push({start:e,count:t,materialIndex:n})}clearGroups(){this.groups=[]}setDrawRange(e,t){this.drawRange.start=e,this.drawRange.count=t}applyMatrix4(e){let t=this.attributes.position;t!==void 0&&(t.applyMatrix4(e),t.needsUpdate=!0);let n=this.attributes.normal;if(n!==void 0){let s=new qe().getNormalMatrix(e);n.applyNormalMatrix(s),n.needsUpdate=!0}let i=this.attributes.tangent;return i!==void 0&&(i.transformDirection(e),i.needsUpdate=!0),this.boundingBox!==null&&this.computeBoundingBox(),this.boundingSphere!==null&&this.computeBoundingSphere(),this._transformed=!0,this}applyQuaternion(e){return Pn.makeRotationFromQuaternion(e),this.applyMatrix4(Pn),this}rotateX(e){return Pn.makeRotationX(e),this.applyMatrix4(Pn),this}rotateY(e){return Pn.makeRotationY(e),this.applyMatrix4(Pn),this}rotateZ(e){return Pn.makeRotationZ(e),this.applyMatrix4(Pn),this}translate(e,t,n){return Pn.makeTranslation(e,t,n),this.applyMatrix4(Pn),this}scale(e,t,n){return Pn.makeScale(e,t,n),this.applyMatrix4(Pn),this}lookAt(e){return Ou.lookAt(e),Ou.updateMatrix(),this.applyMatrix4(Ou.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(dr).negate(),this.translate(dr.x,dr.y,dr.z),this}setFromPoints(e){let t=this.getAttribute("position");if(t===void 0){let n=[];for(let i=0,s=e.length;it.count&&de("BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry."),t.needsUpdate=!0}return this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new Ft);let e=this.attributes.position,t=this.morphAttributes.position;if(e&&e.isGLBufferAttribute){Pe("BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.",this),this.boundingBox.set(new R(-1/0,-1/0,-1/0),new R(1/0,1/0,1/0));return}if(e!==void 0){if(this.boundingBox.setFromBufferAttribute(e),t)for(let n=0,i=t.length;n0&&(e.userData=this.userData),this.parameters!==void 0&&this._transformed!==!0){let l=this.parameters;for(let c in l)l[c]!==void 0&&(e[c]=l[c]);return e}e.data={attributes:{}};let t=this.index;t!==null&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});let n=this.attributes;for(let l in n){let c=n[l];e.data.attributes[l]=c.toJSON(e.data)}let i={},s=!1;for(let l in this.morphAttributes){let c=this.morphAttributes[l],h=[];for(let u=0,d=c.length;u0&&(i[l]=h,s=!0)}s&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);let o=this.groups;o.length>0&&(e.data.groups=JSON.parse(JSON.stringify(o)));let a=this.boundingSphere;return a!==null&&(e.data.boundingSphere=a.toJSON()),e}clone(){return new this.constructor().copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;let t={};this.name=e.name;let n=e.index;n!==null&&this.setIndex(n.clone());let i=e.attributes;for(let c in i){let h=i[c];this.setAttribute(c,h.clone(t))}let s=e.morphAttributes;for(let c in s){let h=[],u=s[c];for(let d=0,f=u.length;d1)?null:t.copy(e.start).addScaledVector(i,o)}intersectsLine(e){let t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){let n=t||r0.getNormalMatrix(e),i=this.coplanarPoint(Bu).applyMatrix4(e),s=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(s),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return new this.constructor().copy(this)}toJSON(){return{normal:this.normal.toArray(),constant:this.constant}}fromJSON(e){return this.normal.fromArray(e.normal),this.constant=e.constant,this}},o0=0,vt=class extends xn{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:o0++}),this.uuid=Tn(),this.name="",this.type="Material",this.blending=Ys,this.side=ei,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.alphaHash=!1,this.blendSrc=Gh,this.blendDst=Hh,this.blendEquation=ls,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.blendColor=new ce(0,0,0),this.blendAlpha=0,this.depthFunc=As,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=qd,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=Oo,this.stencilZFail=Oo,this.stencilZPass=Oo,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.forceSinglePass=!1,this.allowOverride=!0,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(e){this._alphaTest>0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(e!==void 0)for(let t in e){let n=e[t];if(n===void 0){de(`Material: parameter '${t}' has value of undefined.`);continue}let i=this[t];if(i===void 0){de(`Material: '${t}' is not a property of THREE.${this.type}.`);continue}i&&i.isColor?i.set(n):i&&i.isVector2&&n&&n.isVector2||i&&i.isEuler&&n&&n.isEuler||i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[t]=n}}toJSON(e){let t=e===void 0||typeof e=="string";t&&(e={textures:{},images:{}});let n={metadata:{version:4.7,type:"Material",generator:"Material.toJSON"}};n.uuid=this.uuid,n.type=this.type,n.blending=this.blending,n.side=this.side,n.shadowSide=this.shadowSide,n.vertexColors=this.vertexColors,n.opacity=this.opacity,n.transparent=this.transparent,n.blendSrc=this.blendSrc,n.blendDst=this.blendDst,n.blendEquation=this.blendEquation,n.blendSrcAlpha=this.blendSrcAlpha,n.blendDstAlpha=this.blendDstAlpha,n.blendEquationAlpha=this.blendEquationAlpha,n.blendColor=this.blendColor.getHex(),n.blendAlpha=this.blendAlpha,n.depthFunc=this.depthFunc,n.depthTest=this.depthTest,n.depthWrite=this.depthWrite,n.colorWrite=this.colorWrite,n.clipIntersection=this.clipIntersection,n.clipShadows=this.clipShadows,n.stencilWriteMask=this.stencilWriteMask,n.stencilFunc=this.stencilFunc,n.stencilRef=this.stencilRef,n.stencilFuncMask=this.stencilFuncMask,n.stencilFail=this.stencilFail,n.stencilZFail=this.stencilZFail,n.stencilZPass=this.stencilZPass,n.stencilWrite=this.stencilWrite,n.polygonOffset=this.polygonOffset,n.polygonOffsetFactor=this.polygonOffsetFactor,n.polygonOffsetUnits=this.polygonOffsetUnits,n.dithering=this.dithering,n.alphaTest=this.alphaTest,n.alphaHash=this.alphaHash,n.alphaToCoverage=this.alphaToCoverage,n.premultipliedAlpha=this.premultipliedAlpha,n.forceSinglePass=this.forceSinglePass,n.allowOverride=this.allowOverride,n.visible=this.visible,n.toneMapped=this.toneMapped,n.name=this.name,this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.sheenColorMap&&this.sheenColorMap.isTexture&&(n.sheenColorMap=this.sheenColorMap.toJSON(e).uuid),this.sheenRoughnessMap&&this.sheenRoughnessMap.isTexture&&(n.sheenRoughnessMap=this.sheenRoughnessMap.toJSON(e).uuid),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.retroreflectivity!==void 0&&(n.retroreflectivity=this.retroreflectivity),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),this.attenuationDistance!==void 0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),Array.isArray(this.clippingPlanes)&&this.clippingPlanes.length>0&&(n.clippingPlanes=this.clippingPlanes.map(s=>s.toJSON())),this.rotation!==void 0&&(n.rotation=this.rotation),this.depthPacking!==void 0&&(n.depthPacking=this.depthPacking),this.linewidth!==void 0&&(n.linewidth=this.linewidth),this.linecap!==void 0&&(n.linecap=this.linecap),this.linejoin!==void 0&&(n.linejoin=this.linejoin),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.wireframe!==void 0&&(n.wireframe=this.wireframe),this.wireframeLinewidth!==void 0&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!==void 0&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!==void 0&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading!==void 0&&(n.flatShading=this.flatShading),this.fog!==void 0&&(n.fog=this.fog),Object.keys(this.userData).length>0&&(n.userData=this.userData);function i(s){let o=[];for(let a in s){let l=s[a];delete l.metadata,o.push(l)}return o}if(t){let s=i(e.textures),o=i(e.images);s.length>0&&(n.textures=s),o.length>0&&(n.images=o)}return n}fromJSON(e,t){if(e.uuid!==void 0&&(this.uuid=e.uuid),e.name!==void 0&&(this.name=e.name),e.color!==void 0&&this.color!==void 0&&this.color.setHex(e.color),e.roughness!==void 0&&(this.roughness=e.roughness),e.metalness!==void 0&&(this.metalness=e.metalness),e.sheen!==void 0&&(this.sheen=e.sheen),e.sheenColor!==void 0&&(this.sheenColor=new ce().setHex(e.sheenColor)),e.sheenRoughness!==void 0&&(this.sheenRoughness=e.sheenRoughness),e.emissive!==void 0&&this.emissive!==void 0&&this.emissive.setHex(e.emissive),e.specular!==void 0&&this.specular!==void 0&&this.specular.setHex(e.specular),e.specularIntensity!==void 0&&(this.specularIntensity=e.specularIntensity),e.specularColor!==void 0&&this.specularColor!==void 0&&this.specularColor.setHex(e.specularColor),e.shininess!==void 0&&(this.shininess=e.shininess),e.clearcoat!==void 0&&(this.clearcoat=e.clearcoat),e.clearcoatRoughness!==void 0&&(this.clearcoatRoughness=e.clearcoatRoughness),e.dispersion!==void 0&&(this.dispersion=e.dispersion),e.retroreflectivity!==void 0&&(this.retroreflectivity=e.retroreflectivity),e.iridescence!==void 0&&(this.iridescence=e.iridescence),e.iridescenceIOR!==void 0&&(this.iridescenceIOR=e.iridescenceIOR),e.iridescenceThicknessRange!==void 0&&(this.iridescenceThicknessRange=e.iridescenceThicknessRange),e.transmission!==void 0&&(this.transmission=e.transmission),e.thickness!==void 0&&(this.thickness=e.thickness),e.attenuationDistance!==void 0&&(this.attenuationDistance=e.attenuationDistance),e.attenuationColor!==void 0&&this.attenuationColor!==void 0&&this.attenuationColor.setHex(e.attenuationColor),e.anisotropy!==void 0&&(this.anisotropy=e.anisotropy),e.anisotropyRotation!==void 0&&(this.anisotropyRotation=e.anisotropyRotation),e.fog!==void 0&&(this.fog=e.fog),e.flatShading!==void 0&&(this.flatShading=e.flatShading),e.blending!==void 0&&(this.blending=e.blending),e.combine!==void 0&&(this.combine=e.combine),e.side!==void 0&&(this.side=e.side),e.shadowSide!==void 0&&(this.shadowSide=e.shadowSide),e.opacity!==void 0&&(this.opacity=e.opacity),e.transparent!==void 0&&(this.transparent=e.transparent),e.alphaTest!==void 0&&(this.alphaTest=e.alphaTest),e.alphaHash!==void 0&&(this.alphaHash=e.alphaHash),e.depthFunc!==void 0&&(this.depthFunc=e.depthFunc),e.depthTest!==void 0&&(this.depthTest=e.depthTest),e.depthWrite!==void 0&&(this.depthWrite=e.depthWrite),e.colorWrite!==void 0&&(this.colorWrite=e.colorWrite),e.clippingPlanes!==void 0&&(this.clippingPlanes=e.clippingPlanes.map(n=>new gn().fromJSON(n))),e.clipIntersection!==void 0&&(this.clipIntersection=e.clipIntersection),e.clipShadows!==void 0&&(this.clipShadows=e.clipShadows),e.depthPacking!==void 0&&(this.depthPacking=e.depthPacking),e.blendSrc!==void 0&&(this.blendSrc=e.blendSrc),e.blendDst!==void 0&&(this.blendDst=e.blendDst),e.blendEquation!==void 0&&(this.blendEquation=e.blendEquation),e.blendSrcAlpha!==void 0&&(this.blendSrcAlpha=e.blendSrcAlpha),e.blendDstAlpha!==void 0&&(this.blendDstAlpha=e.blendDstAlpha),e.blendEquationAlpha!==void 0&&(this.blendEquationAlpha=e.blendEquationAlpha),e.blendColor!==void 0&&this.blendColor!==void 0&&this.blendColor.setHex(e.blendColor),e.blendAlpha!==void 0&&(this.blendAlpha=e.blendAlpha),e.stencilWriteMask!==void 0&&(this.stencilWriteMask=e.stencilWriteMask),e.stencilFunc!==void 0&&(this.stencilFunc=e.stencilFunc),e.stencilRef!==void 0&&(this.stencilRef=e.stencilRef),e.stencilFuncMask!==void 0&&(this.stencilFuncMask=e.stencilFuncMask),e.stencilFail!==void 0&&(this.stencilFail=e.stencilFail),e.stencilZFail!==void 0&&(this.stencilZFail=e.stencilZFail),e.stencilZPass!==void 0&&(this.stencilZPass=e.stencilZPass),e.stencilWrite!==void 0&&(this.stencilWrite=e.stencilWrite),e.wireframe!==void 0&&(this.wireframe=e.wireframe),e.wireframeLinewidth!==void 0&&(this.wireframeLinewidth=e.wireframeLinewidth),e.wireframeLinecap!==void 0&&(this.wireframeLinecap=e.wireframeLinecap),e.wireframeLinejoin!==void 0&&(this.wireframeLinejoin=e.wireframeLinejoin),e.rotation!==void 0&&(this.rotation=e.rotation),e.linewidth!==void 0&&(this.linewidth=e.linewidth),e.linecap!==void 0&&(this.linecap=e.linecap),e.linejoin!==void 0&&(this.linejoin=e.linejoin),e.dashSize!==void 0&&(this.dashSize=e.dashSize),e.gapSize!==void 0&&(this.gapSize=e.gapSize),e.scale!==void 0&&(this.scale=e.scale),e.polygonOffset!==void 0&&(this.polygonOffset=e.polygonOffset),e.polygonOffsetFactor!==void 0&&(this.polygonOffsetFactor=e.polygonOffsetFactor),e.polygonOffsetUnits!==void 0&&(this.polygonOffsetUnits=e.polygonOffsetUnits),e.dithering!==void 0&&(this.dithering=e.dithering),e.alphaToCoverage!==void 0&&(this.alphaToCoverage=e.alphaToCoverage),e.premultipliedAlpha!==void 0&&(this.premultipliedAlpha=e.premultipliedAlpha),e.forceSinglePass!==void 0&&(this.forceSinglePass=e.forceSinglePass),e.allowOverride!==void 0&&(this.allowOverride=e.allowOverride),e.visible!==void 0&&(this.visible=e.visible),e.toneMapped!==void 0&&(this.toneMapped=e.toneMapped),e.userData!==void 0&&(this.userData=e.userData),e.vertexColors!==void 0&&(typeof e.vertexColors=="number"?this.vertexColors=e.vertexColors>0:this.vertexColors=e.vertexColors),e.size!==void 0&&(this.size=e.size),e.sizeAttenuation!==void 0&&(this.sizeAttenuation=e.sizeAttenuation),e.map!==void 0&&(this.map=t[e.map]||null),e.matcap!==void 0&&(this.matcap=t[e.matcap]||null),e.alphaMap!==void 0&&(this.alphaMap=t[e.alphaMap]||null),e.bumpMap!==void 0&&(this.bumpMap=t[e.bumpMap]||null),e.bumpScale!==void 0&&(this.bumpScale=e.bumpScale),e.normalMap!==void 0&&(this.normalMap=t[e.normalMap]||null),e.normalMapType!==void 0&&(this.normalMapType=e.normalMapType),e.normalScale!==void 0){let n=e.normalScale;Array.isArray(n)===!1&&(n=[n,n]),this.normalScale=new J().fromArray(n)}return e.displacementMap!==void 0&&(this.displacementMap=t[e.displacementMap]||null),e.displacementScale!==void 0&&(this.displacementScale=e.displacementScale),e.displacementBias!==void 0&&(this.displacementBias=e.displacementBias),e.roughnessMap!==void 0&&(this.roughnessMap=t[e.roughnessMap]||null),e.metalnessMap!==void 0&&(this.metalnessMap=t[e.metalnessMap]||null),e.emissiveMap!==void 0&&(this.emissiveMap=t[e.emissiveMap]||null),e.emissiveIntensity!==void 0&&(this.emissiveIntensity=e.emissiveIntensity),e.specularMap!==void 0&&(this.specularMap=t[e.specularMap]||null),e.specularIntensityMap!==void 0&&(this.specularIntensityMap=t[e.specularIntensityMap]||null),e.specularColorMap!==void 0&&(this.specularColorMap=t[e.specularColorMap]||null),e.envMap!==void 0&&(this.envMap=t[e.envMap]||null),e.envMapRotation!==void 0&&this.envMapRotation.fromArray(e.envMapRotation),e.envMapIntensity!==void 0&&(this.envMapIntensity=e.envMapIntensity),e.reflectivity!==void 0&&(this.reflectivity=e.reflectivity),e.refractionRatio!==void 0&&(this.refractionRatio=e.refractionRatio),e.lightMap!==void 0&&(this.lightMap=t[e.lightMap]||null),e.lightMapIntensity!==void 0&&(this.lightMapIntensity=e.lightMapIntensity),e.aoMap!==void 0&&(this.aoMap=t[e.aoMap]||null),e.aoMapIntensity!==void 0&&(this.aoMapIntensity=e.aoMapIntensity),e.gradientMap!==void 0&&(this.gradientMap=t[e.gradientMap]||null),e.clearcoatMap!==void 0&&(this.clearcoatMap=t[e.clearcoatMap]||null),e.clearcoatRoughnessMap!==void 0&&(this.clearcoatRoughnessMap=t[e.clearcoatRoughnessMap]||null),e.clearcoatNormalMap!==void 0&&(this.clearcoatNormalMap=t[e.clearcoatNormalMap]||null),e.clearcoatNormalScale!==void 0&&(this.clearcoatNormalScale=new J().fromArray(e.clearcoatNormalScale)),e.iridescenceMap!==void 0&&(this.iridescenceMap=t[e.iridescenceMap]||null),e.iridescenceThicknessMap!==void 0&&(this.iridescenceThicknessMap=t[e.iridescenceThicknessMap]||null),e.transmissionMap!==void 0&&(this.transmissionMap=t[e.transmissionMap]||null),e.thicknessMap!==void 0&&(this.thicknessMap=t[e.thicknessMap]||null),e.anisotropyMap!==void 0&&(this.anisotropyMap=t[e.anisotropyMap]||null),e.sheenColorMap!==void 0&&(this.sheenColorMap=t[e.sheenColorMap]||null),e.sheenRoughnessMap!==void 0&&(this.sheenRoughnessMap=t[e.sheenRoughnessMap]||null),this}clone(){return new this.constructor().copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,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.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;let t=e.clippingPlanes,n=null;if(t!==null){let i=t.length;n=new Array(i);for(let s=0;s!==i;++s)n[s]=t[s].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,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.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.allowOverride=e.allowOverride,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){e===!0&&this.version++}},Lr=class extends vt{constructor(e){super(),this.isSpriteMaterial=!0,this.type="SpriteMaterial",this.color=new ce(16777215),this.map=null,this.alphaMap=null,this.rotation=0,this.sizeAttenuation=!0,this.transparent=!0,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.alphaMap=e.alphaMap,this.rotation=e.rotation,this.sizeAttenuation=e.sizeAttenuation,this.fog=e.fog,this}},fr,Eo=new R,pr=new R,mr=new R,gr=new J,wo=new J,yg=new ze,jl=new R,Ro=new R,$l=new R,Ep=new J,zu=new J,wp=new J,$o=class extends st{constructor(e=new Lr){if(super(),this.isSprite=!0,this.type="Sprite",fr===void 0){fr=new Oe;let t=new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,-.5,.5,0,0,1]),n=new ci(t,5);fr.setIndex([0,1,2,0,2,3]),fr.setAttribute("position",new Kn(n,3,0,!1)),fr.setAttribute("uv",new Kn(n,2,3,!1))}this.geometry=fr,this.material=e,this.center=new J(.5,.5),this.count=1}intersectsFrustum(e){return e.intersectsSprite(this)}raycast(e,t){e.camera===null&&Pe('Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.'),pr.setFromMatrixScale(this.matrixWorld),yg.copy(e.camera.matrixWorld),this.modelViewMatrix.multiplyMatrices(e.camera.matrixWorldInverse,this.matrixWorld),mr.setFromMatrixPosition(this.modelViewMatrix),e.camera.isPerspectiveCamera&&this.material.sizeAttenuation===!1&&pr.multiplyScalar(-mr.z);let n=this.material.rotation,i,s;n!==0&&(s=Math.cos(n),i=Math.sin(n));let o=this.center;Ql(jl.set(-.5,-.5,0),mr,o,pr,i,s),Ql(Ro.set(.5,-.5,0),mr,o,pr,i,s),Ql($l.set(.5,.5,0),mr,o,pr,i,s),Ep.set(0,0),zu.set(1,0),wp.set(1,1);let a=e.ray.intersectTriangle(jl,Ro,$l,!1,Eo);if(a===null&&(Ql(Ro.set(-.5,.5,0),mr,o,pr,i,s),zu.set(0,1),a=e.ray.intersectTriangle(jl,$l,Ro,!1,Eo),a===null))return;let l=e.ray.origin.distanceTo(Eo);le.far||t.push({distance:l,point:Eo.clone(),uv:qn.getInterpolation(Eo,jl,Ro,$l,Ep,zu,wp,new J),face:null,object:this})}copy(e,t){return super.copy(e,t),e.center!==void 0&&this.center.copy(e.center),this.material=e.material,this}};function Ql(r,e,t,n,i,s){gr.subVectors(r,t).addScalar(.5).multiply(n),i!==void 0?(wo.x=s*gr.x-i*gr.y,wo.y=i*gr.x+s*gr.y):wo.copy(gr),r.copy(e),r.x+=wo.x,r.y+=wo.y,r.applyMatrix4(yg)}var ec=new R,Rp=new R,Qo=class extends st{constructor(){super(),this.isLOD=!0,this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}}),this.autoUpdate=!0}copy(e){super.copy(e,!1);let t=e.levels;for(let n=0,i=t.length;n0){let n,i;for(n=1,i=t.length;n0){ec.setFromMatrixPosition(this.matrixWorld);let i=e.ray.origin.distanceTo(ec);this.getObjectForDistance(i).raycast(e,t)}}update(e){let t=this.levels;if(t.length>1){ec.setFromMatrixPosition(e.matrixWorld),Rp.setFromMatrixPosition(this.matrixWorld);let n=ec.distanceTo(Rp)/e.zoom;t[0].object.visible=!0;let i,s;for(i=1,s=t.length;i=o)t[i-1].object.visible=!1,t[i].object.visible=!0;else break}for(this._currentLevel=i-1;i0)if(u=o*l-a,d=o*a-l,p=s*h,u>=0)if(d>=-p)if(d<=p){let _=1/h;u*=_,d*=_,f=u*(u+o*d+2*a)+d*(o*u+d+2*l)+c}else d=s,u=Math.max(0,-(o*d+a)),f=-u*u+d*(d+2*l)+c;else d=-s,u=Math.max(0,-(o*d+a)),f=-u*u+d*(d+2*l)+c;else d<=-p?(u=Math.max(0,-(-o*s+a)),d=u>0?-s:Math.min(Math.max(-s,-l),s),f=-u*u+d*(d+2*l)+c):d<=p?(u=0,d=Math.min(Math.max(-s,-l),s),f=d*(d+2*l)+c):(u=Math.max(0,-(o*s+a)),d=u>0?s:Math.min(Math.max(-s,-l),s),f=-u*u+d*(d+2*l)+c);else d=o>0?-s:s,u=Math.max(0,-(o*d+a)),f=-u*u+d*(d+2*l)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,u),i&&i.copy(ku).addScaledVector(tc,d),f}intersectSphere(e,t){if(e.radius<0)return null;Ei.subVectors(e.center,this.origin);let n=Ei.dot(this.direction),i=Ei.dot(Ei)-n*n,s=e.radius*e.radius;if(i>s)return null;let o=Math.sqrt(s-i),a=n-o,l=n+o;return l<0?null:a<0?this.at(l,t):this.at(a,t)}intersectsSphere(e){return e.radius<0?!1:this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){let t=e.normal.dot(this.direction);if(t===0)return e.distanceToPoint(this.origin)===0?0:null;let n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){let n=this.distanceToPlane(e);return n===null?null:this.at(n,t)}intersectsPlane(e){let t=e.distanceToPoint(this.origin);return t===0||e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,i,s,o,a,l,c=1/this.direction.x,h=1/this.direction.y,u=1/this.direction.z,d=this.origin;return c>=0?(n=(e.min.x-d.x)*c,i=(e.max.x-d.x)*c):(n=(e.max.x-d.x)*c,i=(e.min.x-d.x)*c),h>=0?(s=(e.min.y-d.y)*h,o=(e.max.y-d.y)*h):(s=(e.max.y-d.y)*h,o=(e.min.y-d.y)*h),n>o||s>i||((s>n||isNaN(n))&&(n=s),(o=0?(a=(e.min.z-d.z)*u,l=(e.max.z-d.z)*u):(a=(e.max.z-d.z)*u,l=(e.min.z-d.z)*u),n>l||a>i)||((a>n||n!==n)&&(n=a),(l=0?n:i,t)}intersectsBox(e){return this.intersectBox(e,Ei)!==null}intersectTriangle(e,t,n,i,s){let o=this.origin,a=this.direction,l=a.x,c=a.y,h=a.z,u=e.x-o.x,d=e.y-o.y,f=e.z-o.z,p=t.x-o.x,_=t.y-o.y,g=t.z-o.z,m=n.x-o.x,y=n.y-o.y,b=n.z-o.z,x=Math.abs(l),T=Math.abs(c),S=Math.abs(h),w,v,E,I,P,F,z,N,B,H,X,ie;if(x>=T&&x>=S?(E=l,F=u,B=p,ie=m,l>=0?(w=c,v=h,I=d,P=f,z=_,N=g,H=y,X=b):(w=h,v=c,I=f,P=d,z=g,N=_,H=b,X=y)):T>=S?(E=c,F=d,B=_,ie=y,c>=0?(w=h,v=l,I=f,P=u,z=g,N=p,H=b,X=m):(w=l,v=h,I=u,P=f,z=p,N=g,H=m,X=b)):(E=h,F=f,B=g,ie=b,h>=0?(w=l,v=c,I=u,P=d,z=p,N=_,H=m,X=y):(w=c,v=l,I=d,P=u,z=_,N=p,H=y,X=m)),E===0)return null;let q=w/E,Q=v/E,ne=1/E,Ne=I-q*F,we=P-Q*F,ct=z-q*B,tt=N-Q*B,ot=H-q*ie,K=X-Q*ie,ee=ot*tt-K*ct,ve=Ne*K-we*ot,Ge=ct*we-tt*Ne;if(i){if(ee<0||ve<0||Ge<0)return null}else if((ee<0||ve<0||Ge<0)&&(ee>0||ve>0||Ge>0))return null;let Te=ee+ve+Ge;if(Te===0)return null;let We=ne*(ee*F+ve*B+Ge*ie);return(Te>0?We<0:We>0)?null:this.at(We/Te,s)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}},Kt=class extends vt{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new ce(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new Dn,this.combine=no,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(e)}copy(e){return super.copy(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.envMapRotation.copy(e.envMapRotation),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.fog=e.fog,this}},Cp=new ze,ps=new Jn,ic=new Nt,Ip=new R,sc=new R,rc=new R,oc=new R,Vu=new R,ac=new R,Pp=new R,lc=new R,rt=class extends st{constructor(e=new Oe,t=new Kt){super(),this.isMesh=!0,this.type="Mesh",this.geometry=e,this.material=t,this.morphTargetDictionary=void 0,this.morphTargetInfluences=void 0,this.count=1,this.updateMorphTargets()}copy(e,t){return super.copy(e,t),e.morphTargetInfluences!==void 0&&(this.morphTargetInfluences=e.morphTargetInfluences.slice()),e.morphTargetDictionary!==void 0&&(this.morphTargetDictionary=Object.assign({},e.morphTargetDictionary)),this.material=Array.isArray(e.material)?e.material.slice():e.material,this.geometry=e.geometry,this}updateMorphTargets(){let t=this.geometry.morphAttributes,n=Object.keys(t);if(n.length>0){let i=t[n[0]];if(i!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let s=0,o=i.length;s(e.far-e.near)**2))&&(Cp.copy(s).invert(),ps.copy(e.ray).applyMatrix4(Cp),!(n.boundingBox!==null&&ps.intersectsBox(n.boundingBox)===!1)&&this._computeIntersections(e,t,ps)))}_computeIntersections(e,t,n){let i,s=this.geometry,o=this.material,a=s.index,l=s.attributes.position,c=s.attributes.uv,h=s.attributes.uv1,u=s.attributes.normal,d=s.groups,f=s.drawRange;if(a!==null)if(Array.isArray(o))for(let p=0,_=d.length;p<_;p++){let g=d[p],m=o[g.materialIndex],y=Math.max(g.start,f.start),b=Math.min(a.count,Math.min(g.start+g.count,f.start+f.count));for(let x=y,T=b;xt.far?null:{distance:c,point:lc.clone(),object:r}}function cc(r,e,t,n,i,s,o,a,l,c){r.getVertexPosition(a,sc),r.getVertexPosition(l,rc),r.getVertexPosition(c,oc);let h=a0(r,e,t,n,sc,rc,oc,Pp);if(h){let u=new R;qn.getBarycoord(Pp,sc,rc,oc,u),i&&(h.uv=qn.getInterpolatedAttribute(i,a,l,c,u,new J)),s&&(h.uv1=qn.getInterpolatedAttribute(s,a,l,c,u,new J)),o&&(h.normal=qn.getInterpolatedAttribute(o,a,l,c,u,new R),h.normal.dot(n.direction)>0&&h.normal.multiplyScalar(-1));let d={a,b:l,c,normal:new R,materialIndex:0};qn.getNormal(sc,rc,oc,d.normal),h.face=d,h.barycoord=u}return h}var Co=new mt,Lp=new mt,Np=new mt,l0=new mt,Dp=new ze,hc=new R,Gu=new Nt,Up=new ze,Hu=new Jn,Ls=class extends rt{constructor(e,t){super(e,t),this.isSkinnedMesh=!0,this.type="SkinnedMesh",this.bindMode=Nc,this.bindMatrix=new ze,this.bindMatrixInverse=new ze,this.boundingBox=null,this.boundingSphere=null}computeBoundingBox(){let e=this.geometry;this.boundingBox===null&&(this.boundingBox=new Ft),this.boundingBox.makeEmpty();let t=e.getAttribute("position");for(let n=0;n0?e.max.x:e.min.x,dc.y=i.normal.y>0?e.max.y:e.min.y,dc.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(dc)<0)return!1}return!0}containsPoint(e){let t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}},zp=new ze,ea=class r{constructor(){this.coordinateSystem=_n,this._frustums=[],this._count=0}setFromArrayCamera(e){let t=e.cameras,n=this._frustums;for(let i=0;i=s.length&&s.push({start:-1,count:-1,z:-1,index:-1});let a=s[this.index];o.push(a),this.index++,a.start=e,a.count=t,a.z=n,a.index=i}reset(){this.list.length=0,this.index=0}},pn=new ze,p0=new ce(1,1,1),m0=new hi,g0=new ea,fc=new Ft,gs=new Nt,Lo=new R,kp=new R,_0=new R,Xu=new sd,Qt=new rt,pc=[];function x0(r,e,t=0){let n=e.itemSize;if(r.isInterleavedBufferAttribute||r.array.constructor!==e.array.constructor){let i=r.count;for(let s=0;s65535?new Uint32Array(i):new Uint16Array(i);t.setIndex(new Qe(s,1))}this._geometryInitialized=!0}}_validateGeometry(e){let t=this.geometry;if(!!e.getIndex()!=!!t.getIndex())throw new Error('THREE.BatchedMesh: All geometries must consistently have "index".');for(let n in t.attributes){if(!e.hasAttribute(n))throw new Error(`THREE.BatchedMesh: Added geometry missing "${n}". All geometries must have consistent attributes.`);let i=e.getAttribute(n),s=t.getAttribute(n);if(i.itemSize!==s.itemSize||i.normalized!==s.normalized)throw new Error("THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}validateInstanceId(e){let t=this._instanceInfo;if(e<0||e>=t.length||t[e].active===!1)throw new Error(`THREE.BatchedMesh: Invalid instanceId ${e}. Instance is either out of range or has been deleted.`)}validateGeometryId(e){let t=this._geometryInfo;if(e<0||e>=t.length||t[e].active===!1)throw new Error(`THREE.BatchedMesh: Invalid geometryId ${e}. Geometry is either out of range or has been deleted.`)}setCustomSort(e){return this.customSort=e,this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new Ft);let e=this.boundingBox,t=this._instanceInfo;e.makeEmpty();for(let n=0,i=t.length;n=this.maxInstanceCount&&this._availableInstanceIds.length===0)throw new Error("THREE.BatchedMesh: Maximum item count reached.");let n={visible:!0,active:!0,geometryIndex:e},i=null;this._availableInstanceIds.length>0?(this._availableInstanceIds.sort(Wu),i=this._availableInstanceIds.shift(),this._instanceInfo[i]=n):(i=this._instanceInfo.length,this._instanceInfo.push(n));let s=this._matricesTexture;pn.identity().toArray(s.image.data,i*16),s.needsUpdate=!0;let o=this._colorsTexture;return o&&(p0.toArray(o.image.data,i*4),o.needsUpdate=!0),this._visibilityChanged=!0,i}addGeometry(e,t=-1,n=-1){this._initializeGeometry(e),this._validateGeometry(e);let i={vertexStart:-1,vertexCount:-1,reservedVertexCount:-1,indexStart:-1,indexCount:-1,reservedIndexCount:-1,start:-1,count:-1,boundingBox:null,boundingSphere:null,active:!0},s=this._geometryInfo;i.vertexStart=this._nextVertexStart,i.reservedVertexCount=t===-1?e.getAttribute("position").count:t;let o=e.getIndex();if(o!==null&&(i.indexStart=this._nextIndexStart,i.reservedIndexCount=n===-1?o.count:n),i.indexStart!==-1&&i.indexStart+i.reservedIndexCount>this._maxIndexCount||i.vertexStart+i.reservedVertexCount>this._maxVertexCount)throw new Error("THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.");let l;return this._availableGeometryIds.length>0?(this._availableGeometryIds.sort(Wu),l=this._availableGeometryIds.shift(),s[l]=i):(l=this._geometryCount,this._geometryCount++,s.push(i)),this.setGeometryAt(l,e),this._nextIndexStart=i.indexStart+i.reservedIndexCount,this._nextVertexStart=i.vertexStart+i.reservedVertexCount,l}setGeometryAt(e,t){if(e>=this._geometryCount)throw new Error("THREE.BatchedMesh: Maximum geometry count reached.");this._validateGeometry(t);let n=this.geometry,i=n.getIndex()!==null,s=n.getIndex(),o=t.getIndex(),a=this._geometryInfo[e];if(i&&o.count>a.reservedIndexCount||t.attributes.position.count>a.reservedVertexCount)throw new Error("THREE.BatchedMesh: Reserved space not large enough for provided geometry.");let l=a.vertexStart,c=a.reservedVertexCount;a.vertexCount=t.getAttribute("position").count;for(let h in n.attributes){let u=t.getAttribute(h),d=n.getAttribute(h);x0(u,d,l);let f=u.itemSize;for(let p=u.count,_=c;p<_;p++){let g=l+p;for(let m=0;m=t.length||t[e].active===!1)return this;let n=this._instanceInfo;for(let i=0,s=n.length;ia).sort((o,a)=>n[o].vertexStart-n[a].vertexStart),s=this.geometry;for(let o=0,a=n.length;o=this._geometryCount)return null;let n=this.geometry,i=this._geometryInfo[e];if(i.boundingBox===null){let s=new Ft,o=n.index,a=n.attributes.position;for(let l=i.start,c=i.start+i.count;l=this._geometryCount)return null;let n=this.geometry,i=this._geometryInfo[e];if(i.boundingSphere===null){let s=new Nt;this.getBoundingBoxAt(e,fc),fc.getCenter(s.center);let o=n.index,a=n.attributes.position,l=0;for(let c=i.start,h=i.start+i.count;ca.active);if(Math.max(...n.map(a=>a.vertexStart+a.reservedVertexCount))>e)throw new Error(`THREE.BatchedMesh: Geometry vertex values are being used outside the range ${t}. Cannot shrink further.`);if(this.geometry.index&&Math.max(...n.map(l=>l.indexStart+l.reservedIndexCount))>t)throw new Error(`THREE.BatchedMesh: Geometry index values are being used outside the range ${t}. Cannot shrink further.`);let s=this.geometry;s.dispose(),this._maxVertexCount=e,this._maxIndexCount=t,this._geometryInitialized&&(this._geometryInitialized=!1,this.geometry=new Oe,this._initializeGeometry(s));let o=this.geometry;s.index&&_s(s.index.array,o.index.array);for(let a in s.attributes)_s(s.attributes[a].array,o.attributes[a].array)}raycast(e,t){let n=this._instanceInfo,i=this._geometryInfo,s=this.matrixWorld,o=this.geometry;Qt.material=this.material,Qt.geometry.index=o.index,Qt.geometry.attributes=o.attributes,Qt.geometry.boundingBox===null&&(Qt.geometry.boundingBox=new Ft),Qt.geometry.boundingSphere===null&&(Qt.geometry.boundingSphere=new Nt);for(let a=0,l=n.length;a({...t,boundingBox:t.boundingBox!==null?t.boundingBox.clone():null,boundingSphere:t.boundingSphere!==null?t.boundingSphere.clone():null})),this._instanceInfo=e._instanceInfo.map(t=>({...t})),this._availableInstanceIds=e._availableInstanceIds.slice(),this._availableGeometryIds=e._availableGeometryIds.slice(),this._nextIndexStart=e._nextIndexStart,this._nextVertexStart=e._nextVertexStart,this._geometryCount=e._geometryCount,this._maxInstanceCount=e._maxInstanceCount,this._maxVertexCount=e._maxVertexCount,this._maxIndexCount=e._maxIndexCount,this._geometryInitialized=e._geometryInitialized,this._multiDrawCounts=e._multiDrawCounts.slice(),this._multiDrawStarts=e._multiDrawStarts.slice(),this._multiDrawBytesPerElement=e._multiDrawBytesPerElement,this._indirectTexture=e._indirectTexture.clone(),this._indirectTexture.image.data=this._indirectTexture.image.data.slice(),this._matricesTexture=e._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),this._colorsTexture!==null&&(this._colorsTexture=e._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){super.dispose(),this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,this._colorsTexture!==null&&(this._colorsTexture.dispose(),this._colorsTexture=null)}onBeforeRender(e,t,n,i,s){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;let o=i.getIndex(),a=o===null?1:o.array.BYTES_PER_ELEMENT,l=1;s.wireframe&&(l=2,a=i.attributes.position.count>65535?4:2);let c=this._instanceInfo,h=this._multiDrawStarts,u=this._multiDrawCounts,d=this._geometryInfo,f=this.perObjectFrustumCulled,p=this._indirectTexture,_=p.image.data,g=n.isArrayCamera?g0:m0;f&&(n.isArrayCamera?g.setFromArrayCamera(n):(pn.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse).multiply(this.matrixWorld),g.setFromProjectionMatrix(pn,n.coordinateSystem,n.reversedDepth)));let m=0;if(this.sortObjects){pn.copy(this.matrixWorld).invert(),Lo.setFromMatrixPosition(n.matrixWorld).applyMatrix4(pn),kp.set(0,0,-1).transformDirection(n.matrixWorld).transformDirection(pn);for(let x=0,T=c.length;x0){let i=t[n[0]];if(i!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let s=0,o=i.length;sn)return;qu.applyMatrix4(r.matrixWorld);let c=e.ray.origin.distanceTo(qu);if(!(ce.far))return{distance:c,point:Gp.clone().applyMatrix4(r.matrixWorld),index:o,face:null,faceIndex:null,barycoord:null,object:r}}var Hp=new R,Wp=new R,Xt=class extends En{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){let e=this.geometry;if(e.index===null){let t=e.attributes.position,n=[];for(let i=0,s=t.count;i0){let i=t[n[0]];if(i!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let s=0,o=i.length;si.far)return;s.push({distance:c,distanceToRay:Math.sqrt(a),point:l,index:e,face:null,faceIndex:null,barycoord:null,object:o})}}var na=class extends Et{constructor(e,t,n,i,s=pt,o=pt,a,l,c){super(e,t,n,i,s,o,a,l,c),this.isVideoTexture=!0,this.generateMipmaps=!1,this._requestVideoFrameCallbackId=0;let h=this;function u(){h.needsUpdate=!0,h._requestVideoFrameCallbackId=e.requestVideoFrameCallback(u)}"requestVideoFrameCallback"in e&&(this._requestVideoFrameCallbackId=e.requestVideoFrameCallback(u))}clone(){return new this.constructor(this.image).copy(this)}update(){let e=this.image;"requestVideoFrameCallback"in e===!1&&e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}dispose(){this._requestVideoFrameCallbackId!==0&&(this.source.data.cancelVideoFrameCallback(this._requestVideoFrameCallbackId),this._requestVideoFrameCallbackId=0),super.dispose()}},Yc=class extends na{constructor(e,t,n,i,s,o,a,l){super({},e,t,n,i,s,o,a,l),this.isVideoFrameTexture=!0}update(){}clone(){return new this.constructor().copy(this)}setFrame(e){this.image=e,this.needsUpdate=!0}},Zc=class extends Et{constructor(e,t){super({width:e,height:t}),this.isFramebufferTexture=!0,this.magFilter=At,this.minFilter=At,this.generateMipmaps=!1,this.needsUpdate=!0}},Us=class extends Et{constructor(e,t,n,i,s,o,a,l,c,h,u,d){super(null,o,a,l,c,h,i,s,u,d),this.isCompressedTexture=!0,this.image={width:t,height:n},this.mipmaps=e,this.flipY=!1,this.generateMipmaps=!1}},Kc=class extends Us{constructor(e,t,n,i,s,o){super(e,t,n,s,o),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=Yt,this.layerUpdates=new Set}copy(e){return super.copy(e),this.wrapR=e.wrapR,this}addLayerUpdate(e){this.layerUpdates.add(e)}clearLayerUpdates(){this.layerUpdates.clear()}},Jc=class extends Us{constructor(e,t,n){super(void 0,e[0].width,e[0].height,t,n,ni),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=e}},ss=class extends Et{constructor(e=[],t=ni,n,i,s,o,a,l,c,h){super(e,t,n,i,s,o,a,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}},jc=class extends Et{constructor(e,t,n,i,s,o,a,l,c){super(e,t,n,i,s,o,a,l,c),this.isCanvasTexture=!0,this.needsUpdate=!0}},$c=class extends Et{constructor(e,t,n,i,s,o,a,l,c){super(e,t,n,i,s,o,a,l,c),this.isHTMLTexture=!0,this.generateMipmaps=!1,this.needsUpdate=!0;let h=e?e.parentNode:null;h!==null&&"requestPaint"in h&&(h.onpaint=()=>{this.needsUpdate=!0},h.requestPaint())}dispose(){let e=this.image?this.image.parentNode:null;e!==null&&"onpaint"in e&&(e.onpaint=null),super.dispose()}},Pi=class extends Et{constructor(e,t,n=Cn,i,s,o,a=At,l=At,c,h=Zn,u=1){if(h!==Zn&&h!==zi)throw new Error("THREE.DepthTexture: format must be either THREE.DepthFormat or THREE.DepthStencilFormat");let d={width:e,height:t,depth:u};super(d,i,s,o,a,l,h,n,c),this.isDepthTexture=!0,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(e){return super.copy(e),this.source=new Ln(Object.assign({},e.image)),this.compareFunction=e.compareFunction,this}toJSON(e){let t=super.toJSON(e);return t.compareFunction=this.compareFunction,t}},ia=class extends Pi{constructor(e,t=Cn,n=ni,i,s,o=At,a=At,l,c=Zn){let h={width:e,height:e,depth:1},u=[h,h,h,h,h,h];super(e,e,t,n,i,s,o,a,l,c),this.image=u,this.isCubeDepthTexture=!0,this.isCubeTexture=!0}get images(){return this.image}set images(e){this.image=e}},Nr=class extends Et{constructor(e=null){super(),this.sourceTexture=e,this.isExternalTexture=!0}copy(e){return super.copy(e),this.sourceTexture=e.sourceTexture,this}},ui=class r extends Oe{constructor(e=1,t=1,n=1,i=1,s=1,o=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:n,widthSegments:i,heightSegments:s,depthSegments:o};let a=this;i=Math.floor(i),s=Math.floor(s),o=Math.floor(o);let l=[],c=[],h=[],u=[],d=0,f=0;p("z","y","x",-1,-1,n,t,e,o,s,0),p("z","y","x",1,-1,n,t,-e,o,s,1),p("x","z","y",1,1,e,n,t,i,o,2),p("x","z","y",1,-1,e,n,-t,i,o,3),p("x","y","z",1,-1,e,t,n,i,s,4),p("x","y","z",-1,-1,e,t,-n,i,s,5),this.setIndex(l),this.setAttribute("position",new fe(c,3)),this.setAttribute("normal",new fe(h,3)),this.setAttribute("uv",new fe(u,2));function p(_,g,m,y,b,x,T,S,w,v,E){let I=x/w,P=T/v,F=x/2,z=T/2,N=S/2,B=w+1,H=v+1,X=0,ie=0,q=new R;for(let Q=0;Q0?1:-1,h.push(q.x,q.y,q.z),u.push(Ne/w),u.push(1-Q/v),X+=1}}for(let Q=0;Q0){let E=(y-1)*_;for(let I=0;I0&&b(!0),t>0&&b(!1)),this.setIndex(h),this.setAttribute("position",new fe(u,3)),this.setAttribute("normal",new fe(d,3)),this.setAttribute("uv",new fe(f,2));function y(){let x=new R,T=new R,S=0,w=(t-e)/n;for(let v=0;v<=s;v++){let E=[],I=v/s,P=I*(t-e)+e;for(let F=0;F<=i;F++){let z=F/i,N=z*l+a,B=Math.sin(N),H=Math.cos(N);T.x=P*B,T.y=-I*n+g,T.z=P*H,u.push(T.x,T.y,T.z),x.set(B,w,H).normalize(),d.push(x.x,x.y,x.z),f.push(z,1-I),E.push(p++)}_.push(E)}for(let v=0;v0||E!==0)&&(h.push(I,P,z),S+=3),(t>0||E!==s-1)&&(h.push(P,F,z),S+=3)}c.addGroup(m,S,0),m+=S}function b(x){let T=p,S=new J,w=new R,v=0,E=x===!0?e:t,I=x===!0?1:-1;for(let F=1;F<=i;F++)u.push(0,g*I,0),d.push(0,I,0),f.push(.5,.5),p++;let P=p;for(let F=0;F<=i;F++){let N=F/i*l+a,B=Math.cos(N),H=Math.sin(N);w.x=E*H,w.y=g*I,w.z=E*B,u.push(w.x,w.y,w.z),d.push(0,I,0),S.x=B*.5+.5,S.y=H*.5*I+.5,f.push(S.x,S.y),p++}for(let F=0;F.9&&w<.1&&(b<.2&&(o[y+0]+=1),x<.2&&(o[y+2]+=1),T<.2&&(o[y+4]+=1))}}function d(y){s.push(y.x,y.y,y.z)}function f(y,b){let x=y*3;b.x=e[x+0],b.y=e[x+1],b.z=e[x+2]}function p(){let y=new R,b=new R,x=new R,T=new R,S=new J,w=new J,v=new J;for(let E=0,I=0;E0)l=i-1;else{l=i;break}if(i=l,n[i]===o)return i/(s-1);let h=n[i],d=n[i+1]-h,f=(o-h)/d;return(i+f)/(s-1)}getTangent(e,t){let i=e-1e-4,s=e+1e-4;i<0&&(i=0),s>1&&(s=1);let o=this.getPoint(i),a=this.getPoint(s),l=t||(o.isVector2?new J:new R);return l.copy(a).sub(o).normalize(),l}getTangentAt(e,t){let n=this.getUtoTmapping(e);return this.getTangent(n,t)}computeFrenetFrames(e,t=!1){let n=new R,i=[],s=[],o=[],a=new R,l=new ze;for(let f=0;f<=e;f++){let p=f/e;i[f]=this.getTangentAt(p,new R)}s[0]=new R,o[0]=new R;let c=Number.MAX_VALUE,h=Math.abs(i[0].x),u=Math.abs(i[0].y),d=Math.abs(i[0].z);h<=c&&(c=h,n.set(1,0,0)),u<=c&&(c=u,n.set(0,1,0)),d<=c&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),s[0].crossVectors(i[0],a),o[0].crossVectors(i[0],s[0]);for(let f=1;f<=e;f++){if(s[f]=s[f-1].clone(),o[f]=o[f-1].clone(),a.crossVectors(i[f-1],i[f]),a.length()>Number.EPSILON){a.normalize();let p=Math.acos(He(i[f-1].dot(i[f]),-1,1));s[f].applyMatrix4(l.makeRotationAxis(a,p))}o[f].crossVectors(i[f],s[f])}if(t===!0){let f=Math.acos(He(s[0].dot(s[e]),-1,1));f/=e,i[0].dot(a.crossVectors(s[0],s[e]))>0&&(f=-f);for(let p=1;p<=e;p++)s[p].applyMatrix4(l.makeRotationAxis(i[p],f*p)),o[p].crossVectors(i[p],s[p])}return{tangents:i,normals:s,binormals:o}}clone(){return new this.constructor().copy(this)}copy(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}toJSON(){let e={metadata:{version:4.7,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e}fromJSON(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}},Fs=class extends yn{constructor(e=0,t=0,n=1,i=1,s=0,o=Math.PI*2,a=!1,l=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=e,this.aY=t,this.xRadius=n,this.yRadius=i,this.aStartAngle=s,this.aEndAngle=o,this.aClockwise=a,this.aRotation=l}getPoint(e,t=new J){let n=t,i=Math.PI*2,s=this.aEndAngle-this.aStartAngle,o=Math.abs(s)i;)s-=i;s0?0:(Math.floor(Math.abs(a)/s)+1)*s:l===0&&a===s-1&&(a=s-2,l=1);let c,h;this.closed||a>0?c=i[(a-1)%s]:(Zp.subVectors(i[0],i[1]).add(i[0]),c=Zp);let u=i[a%s],d=i[(a+1)%s];if(this.closed||a+2i.length-2?i.length-1:o+1],u=i[o>i.length-3?i.length-1:o+2];return n.set(Kp(a,l.x,c.x,h.x,u.x),Kp(a,l.y,c.y,h.y,u.y)),n}copy(e){super.copy(e),this.points=[];for(let t=0,n=e.points.length;t=n){let o=i[s]-n,a=this.curves[s],l=a.getLength(),c=l===0?0:1-o/l;return a.getPointAt(c,t)}s++}return null}getLength(){let e=this.getCurveLengths();return e[e.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;let e=[],t=0;for(let n=0,i=this.curves.length;n1&&!t[t.length-1].equals(t[0])&&t.push(t[0]),t}copy(e){super.copy(e),this.curves=[];for(let t=0,n=e.curves.length;t0){let u=c.getPoint(0);u.equals(this.currentPoint)||this.lineTo(u.x,u.y)}this.curves.push(c);let h=c.getPoint(1);return this.currentPoint.copy(h),this}copy(e){return super.copy(e),this.currentPoint.copy(e.currentPoint),this}toJSON(){let e=super.toJSON();return e.currentPoint=this.currentPoint.toArray(),e}fromJSON(e){return super.fromJSON(e),this.currentPoint.fromArray(e.currentPoint),this}},os=class extends rs{constructor(e){super(e),this.uuid=Tn(),this.type="Shape",this.holes=[]}getPointsHoles(e){let t=[];for(let n=0,i=this.holes.length;n80*t){a=r[0],l=r[1];let h=a,u=l;for(let d=t;dh&&(h=f),p>u&&(u=p)}c=Math.max(h-a,u-l),c=c!==0?32767/c:0}return fa(s,o,t,a,l,c,0),o}function vg(r,e,t,n,i){let s;if(i===G0(r,e,t,n)>0)for(let o=e;o=e;o-=n)s=Jp(o/n|0,r[o],r[o+1],s);return s&&Vr(s,s.next)&&(ma(s),s=s.next),s}function Os(r,e){if(!r)return r;e||(e=r);let t=r,n;do if(n=!1,!t.steiner&&(Vr(t,t.next)||Ct(t.prev,t,t.next)===0)){if(ma(t),t=e=t.prev,t===t.next)break;n=!0}else t=t.next;while(n||t!==e);return e}function fa(r,e,t,n,i,s,o){if(!r)return;!o&&s&&F0(r,n,i,s);let a=r;for(;r.prev!==r.next;){let l=r.prev,c=r.next;if(s?R0(r,n,i,s):w0(r)){e.push(l.i,r.i,c.i),ma(r),r=c.next,a=c.next;continue}if(r=c,r===a){o?o===1?(r=C0(Os(r),e),fa(r,e,t,n,i,s,2)):o===2&&I0(r,e,t,n,i,s):fa(Os(r),e,t,n,i,s,1);break}}}function w0(r){let e=r.prev,t=r,n=r.next;if(Ct(e,t,n)>=0)return!1;let i=e.x,s=t.x,o=n.x,a=e.y,l=t.y,c=n.y,h=Math.min(i,s,o),u=Math.min(a,l,c),d=Math.max(i,s,o),f=Math.max(a,l,c),p=n.next;for(;p!==e;){if(p.x>=h&&p.x<=d&&p.y>=u&&p.y<=f&&Uo(i,a,s,l,o,c,p.x,p.y)&&Ct(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function R0(r,e,t,n){let i=r.prev,s=r,o=r.next;if(Ct(i,s,o)>=0)return!1;let a=i.x,l=s.x,c=o.x,h=i.y,u=s.y,d=o.y,f=Math.min(a,l,c),p=Math.min(h,u,d),_=Math.max(a,l,c),g=Math.max(h,u,d),m=od(f,p,e,t,n),y=od(_,g,e,t,n),b=r.prevZ,x=r.nextZ;for(;b&&b.z>=m&&x&&x.z<=y;){if(b.x>=f&&b.x<=_&&b.y>=p&&b.y<=g&&b!==i&&b!==o&&Uo(a,h,l,u,c,d,b.x,b.y)&&Ct(b.prev,b,b.next)>=0||(b=b.prevZ,x.x>=f&&x.x<=_&&x.y>=p&&x.y<=g&&x!==i&&x!==o&&Uo(a,h,l,u,c,d,x.x,x.y)&&Ct(x.prev,x,x.next)>=0))return!1;x=x.nextZ}for(;b&&b.z>=m;){if(b.x>=f&&b.x<=_&&b.y>=p&&b.y<=g&&b!==i&&b!==o&&Uo(a,h,l,u,c,d,b.x,b.y)&&Ct(b.prev,b,b.next)>=0)return!1;b=b.prevZ}for(;x&&x.z<=y;){if(x.x>=f&&x.x<=_&&x.y>=p&&x.y<=g&&x!==i&&x!==o&&Uo(a,h,l,u,c,d,x.x,x.y)&&Ct(x.prev,x,x.next)>=0)return!1;x=x.nextZ}return!0}function C0(r,e){let t=r;do{let n=t.prev,i=t.next.next;!Vr(n,i)&&Sg(n,t,t.next,i)&&pa(n,i)&&pa(i,n)&&(e.push(n.i,t.i,i.i),ma(t),ma(t.next),t=r=i),t=t.next}while(t!==r);return Os(t)}function I0(r,e,t,n,i,s){let o=r;do{let a=o.next.next;for(;a!==o.prev;){if(o.i!==a.i&&z0(o,a)){let l=bg(o,a);o=Os(o,o.next),l=Os(l,l.next),fa(o,e,t,n,i,s,0),fa(l,e,t,n,i,s,0);return}a=a.next}o=o.next}while(o!==r)}function P0(r,e,t,n){let i=[];for(let s=0,o=e.length;s=t.next.y&&t.next.y!==t.y){let u=t.x+(i-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(u<=n&&u>s&&(s=u,o=t.x=t.x&&t.x>=l&&n!==t.x&&Mg(io.x||t.x===o.x&&U0(o,t)))&&(o=t,h=u)}t=t.next}while(t!==a);return o}function U0(r,e){return Ct(r.prev,r,e.prev)<0&&Ct(e.next,r,r.next)<0}function F0(r,e,t,n){let i=r;do i.z===0&&(i.z=od(i.x,i.y,e,t,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next;while(i!==r);i.prevZ.nextZ=null,i.prevZ=null,O0(i)}function O0(r){let e,t=1;do{let n=r,i;r=null;let s=null;for(e=0;n;){e++;let o=n,a=0;for(let c=0;c0||l>0&&o;)a!==0&&(l===0||!o||n.z<=o.z)?(i=n,n=n.nextZ,a--):(i=o,o=o.nextZ,l--),s?s.nextZ=i:r=i,i.prevZ=s,s=i;n=o}s.nextZ=null,t*=2}while(e>1);return r}function od(r,e,t,n,i){return r=(r-t)*i|0,e=(e-n)*i|0,r=(r|r<<8)&16711935,r=(r|r<<4)&252645135,r=(r|r<<2)&858993459,r=(r|r<<1)&1431655765,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,r|e<<1}function B0(r){let e=r,t=r;do(e.x=(r-o)*(s-a)&&(r-o)*(n-a)>=(t-o)*(e-a)&&(t-o)*(s-a)>=(i-o)*(n-a)}function Uo(r,e,t,n,i,s,o,a){return!(r===o&&e===a)&&Mg(r,e,t,n,i,s,o,a)}function z0(r,e){return r.next.i!==e.i&&r.prev.i!==e.i&&!k0(r,e)&&(pa(r,e)&&pa(e,r)&&V0(r,e)&&(Ct(r.prev,r,e.prev)||Ct(r,e.prev,e))||Vr(r,e)&&Ct(r.prev,r,r.next)>0&&Ct(e.prev,e,e.next)>0)}function Ct(r,e,t){return(e.y-r.y)*(t.x-e.x)-(e.x-r.x)*(t.y-e.y)}function Vr(r,e){return r.x===e.x&&r.y===e.y}function Sg(r,e,t,n){let i=bc(Ct(r,e,t)),s=bc(Ct(r,e,n)),o=bc(Ct(t,n,r)),a=bc(Ct(t,n,e));return!!(i!==s&&o!==a||i===0&&Sc(r,t,e)||s===0&&Sc(r,n,e)||o===0&&Sc(t,r,n)||a===0&&Sc(t,e,n))}function Sc(r,e,t){return e.x<=Math.max(r.x,t.x)&&e.x>=Math.min(r.x,t.x)&&e.y<=Math.max(r.y,t.y)&&e.y>=Math.min(r.y,t.y)}function bc(r){return r>0?1:r<0?-1:0}function k0(r,e){let t=r;do{if(t.i!==r.i&&t.next.i!==r.i&&t.i!==e.i&&t.next.i!==e.i&&Sg(t,t.next,r,e))return!0;t=t.next}while(t!==r);return!1}function pa(r,e){return Ct(r.prev,r,r.next)<0?Ct(r,e,r.next)>=0&&Ct(r,r.prev,e)>=0:Ct(r,e,r.prev)<0||Ct(r,r.next,e)<0}function V0(r,e){let t=r,n=!1,i=(r.x+e.x)/2,s=(r.y+e.y)/2;do t.y>s!=t.next.y>s&&t.next.y!==t.y&&i<(t.next.x-t.x)*(s-t.y)/(t.next.y-t.y)+t.x&&(n=!n),t=t.next;while(t!==r);return n}function bg(r,e){let t=ad(r.i,r.x,r.y),n=ad(e.i,e.x,e.y),i=r.next,s=e.prev;return r.next=e,e.prev=r,t.next=i,i.prev=t,n.next=t,t.prev=n,s.next=n,n.prev=s,n}function Jp(r,e,t,n){let i=ad(r,e,t);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function ma(r){r.next.prev=r.prev,r.prev.next=r.next,r.prevZ&&(r.prevZ.nextZ=r.nextZ),r.nextZ&&(r.nextZ.prevZ=r.prevZ)}function ad(r,e,t){return{i:r,x:e,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function G0(r,e,t,n){let i=0;for(let s=e,o=t-n;s2&&r[e-1].equals(r[0])&&r.pop()}function $p(r,e){for(let t=0;tNumber.EPSILON){let C=Math.sqrt(ut),M=Math.sqrt(Ye*Ye+L*L),O=re.x-Xe/C,G=re.y+Be/C,Y=oe.x-L/M,le=oe.y+Ye/M,he=((Y-O)*L-(le-G)*Ye)/(Be*L-Xe*Ye);ae=O+Be*he-te.x,ue=G+Xe*he-te.y;let Z=ae*ae+ue*ue;if(Z<=2)return new J(ae,ue);ke=Math.sqrt(Z/2)}else{let C=!1;Be>Number.EPSILON?Ye>Number.EPSILON&&(C=!0):Be<-Number.EPSILON?Ye<-Number.EPSILON&&(C=!0):Math.sign(Xe)===Math.sign(L)&&(C=!0),C?(ae=-Xe,ue=Be,ke=Math.sqrt(ut)):(ae=Be,ue=Xe,ke=Math.sqrt(ut/2))}return new J(ae/ke,ue/ke)}let q=[];for(let te=0,re=B.length,oe=re-1,ae=te+1;te=0;te--){let re=te/g,oe=f*Math.cos(re*Math.PI/2),ae=p*Math.sin(re*Math.PI/2)+_;for(let ue=0,ke=B.length;ue=0;){let ae=oe,ue=oe-1;ue<0&&(ue=te.length-1);for(let ke=0,Be=h+g*2;ke0)&&f.push(b,x,S),(m!==n-1||l0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;let n={};for(let i in this.extensions)this.extensions[i]===!0&&(n[i]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}fromJSON(e,t){if(super.fromJSON(e,t),e.uniforms!==void 0)for(let n in e.uniforms){let i=e.uniforms[n];switch(this.uniforms[n]={},i.type){case"t":this.uniforms[n].value=t[i.value]||null;break;case"c":this.uniforms[n].value=new ce().setHex(i.value);break;case"v2":this.uniforms[n].value=new J().fromArray(i.value);break;case"v3":this.uniforms[n].value=new R().fromArray(i.value);break;case"v4":this.uniforms[n].value=new mt().fromArray(i.value);break;case"m3":this.uniforms[n].value=new qe().fromArray(i.value);break;case"m4":this.uniforms[n].value=new ze().fromArray(i.value);break;default:this.uniforms[n].value=i.value}}if(e.defines!==void 0&&(this.defines=e.defines),e.vertexShader!==void 0&&(this.vertexShader=e.vertexShader),e.fragmentShader!==void 0&&(this.fragmentShader=e.fragmentShader),e.glslVersion!==void 0&&(this.glslVersion=e.glslVersion),e.extensions!==void 0)for(let n in e.extensions)this.extensions[n]=e.extensions[n];return e.lights!==void 0&&(this.lights=e.lights),e.clipping!==void 0&&(this.clipping=e.clipping),this}},Wr=class extends un{constructor(e){super(e),this.isRawShaderMaterial=!0,this.type="RawShaderMaterial"}},Un=class extends vt{constructor(e){super(),this.isMeshStandardMaterial=!0,this.type="MeshStandardMaterial",this.defines={STANDARD:""},this.color=new ce(16777215),this.roughness=1,this.metalness=0,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ce(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xi,this.normalScale=new J(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new Dn,this.envMapIntensity=1,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(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.normalMapType=e.normalMapType,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.envMapRotation.copy(e.envMapRotation),this.envMapIntensity=e.envMapIntensity,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}},sn=class extends Un{constructor(e){super(),this.isMeshPhysicalMaterial=!0,this.defines={STANDARD:"",PHYSICAL:""},this.type="MeshPhysicalMaterial",this.anisotropyRotation=0,this.anisotropyMap=null,this.clearcoatMap=null,this.clearcoatRoughness=0,this.clearcoatRoughnessMap=null,this.clearcoatNormalScale=new J(1,1),this.clearcoatNormalMap=null,this.ior=1.5,Object.defineProperty(this,"reflectivity",{get:function(){return He(2.5*(this.ior-1)/(this.ior+1),0,1)},set:function(t){this.ior=(1+.4*t)/(1-.4*t)}}),this.iridescenceMap=null,this.iridescenceIOR=1.3,this.iridescenceThicknessRange=[100,400],this.iridescenceThicknessMap=null,this.sheenColor=new ce(0),this.sheenColorMap=null,this.sheenRoughness=1,this.sheenRoughnessMap=null,this.transmissionMap=null,this.thickness=0,this.thicknessMap=null,this.attenuationDistance=1/0,this.attenuationColor=new ce(1,1,1),this.specularIntensity=1,this.specularIntensityMap=null,this.specularColor=new ce(1,1,1),this.specularColorMap=null,this._anisotropy=0,this._clearcoat=0,this._dispersion=0,this._iridescence=0,this._retroreflectivity=0,this._sheen=0,this._transmission=0,this.setValues(e)}get anisotropy(){return this._anisotropy}set anisotropy(e){this._anisotropy>0!=e>0&&this.version++,this._anisotropy=e}get clearcoat(){return this._clearcoat}set clearcoat(e){this._clearcoat>0!=e>0&&this.version++,this._clearcoat=e}get iridescence(){return this._iridescence}set iridescence(e){this._iridescence>0!=e>0&&this.version++,this._iridescence=e}get dispersion(){return this._dispersion}set dispersion(e){this._dispersion>0!=e>0&&this.version++,this._dispersion=e}get retroreflectivity(){return this._retroreflectivity}set retroreflectivity(e){this._retroreflectivity>0!=e>0&&this.version++,this._retroreflectivity=e}get sheen(){return this._sheen}set sheen(e){this._sheen>0!=e>0&&this.version++,this._sheen=e}get transmission(){return this._transmission}set transmission(e){this._transmission>0!=e>0&&this.version++,this._transmission=e}copy(e){return super.copy(e),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=e.anisotropy,this.anisotropyRotation=e.anisotropyRotation,this.anisotropyMap=e.anisotropyMap,this.clearcoat=e.clearcoat,this.clearcoatMap=e.clearcoatMap,this.clearcoatRoughness=e.clearcoatRoughness,this.clearcoatRoughnessMap=e.clearcoatRoughnessMap,this.clearcoatNormalMap=e.clearcoatNormalMap,this.clearcoatNormalScale.copy(e.clearcoatNormalScale),this.dispersion=e.dispersion,this.ior=e.ior,this.iridescence=e.iridescence,this.iridescenceMap=e.iridescenceMap,this.iridescenceIOR=e.iridescenceIOR,this.iridescenceThicknessRange=[...e.iridescenceThicknessRange],this.iridescenceThicknessMap=e.iridescenceThicknessMap,this.retroreflectivity=e.retroreflectivity,this.sheen=e.sheen,this.sheenColor.copy(e.sheenColor),this.sheenColorMap=e.sheenColorMap,this.sheenRoughness=e.sheenRoughness,this.sheenRoughnessMap=e.sheenRoughnessMap,this.transmission=e.transmission,this.transmissionMap=e.transmissionMap,this.thickness=e.thickness,this.thicknessMap=e.thicknessMap,this.attenuationDistance=e.attenuationDistance,this.attenuationColor.copy(e.attenuationColor),this.specularIntensity=e.specularIntensity,this.specularIntensityMap=e.specularIntensityMap,this.specularColor.copy(e.specularColor),this.specularColorMap=e.specularColorMap,this}},zs=class extends vt{constructor(e){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new ce(16777215),this.specular=new ce(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ce(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xi,this.normalScale=new J(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new Dn,this.combine=no,this.reflectivity=1,this.envMapIntensity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(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.normalMapType=e.normalMapType,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.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,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.flatShading=e.flatShading,this.fog=e.fog,this}},wa=class extends vt{constructor(e){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new ce(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ce(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xi,this.normalScale=new J(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.gradientMap=e.gradientMap,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.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}},Ra=class extends vt{constructor(e){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xi,this.normalScale=new J(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(e)}copy(e){return super.copy(e),this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,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.flatShading=e.flatShading,this}},ks=class extends vt{constructor(e){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new ce(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ce(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xi,this.normalScale=new J(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new Dn,this.combine=no,this.reflectivity=1,this.envMapIntensity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(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.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,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.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,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.flatShading=e.flatShading,this.fog=e.fog,this}},Xr=class extends vt{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=Wd,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}},qr=class extends vt{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}},Ca=class extends vt{constructor(e){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new ce(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xi,this.normalScale=new J(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.defines={MATCAP:""},this.color.copy(e.color),this.matcap=e.matcap,this.map=e.map,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.flatShading=e.flatShading,this.fog=e.fog,this}},Ia=class extends Rt{constructor(e){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(e)}copy(e){return super.copy(e),this.scale=e.scale,this.dashSize=e.dashSize,this.gapSize=e.gapSize,this}};function Xn(r,e){return!r||r.constructor===e?r:typeof e.BYTES_PER_ELEMENT=="number"?new e(r):Array.prototype.slice.call(r)}function Vo(r){return r!==void 0&&r.inTangents!==void 0&&r.outTangents!==void 0}function Tg(r){function e(i,s){return r[i]-r[s]}let t=r.length,n=new Array(t);for(let i=0;i!==t;++i)n[i]=i;return n.sort(e),n}function cd(r,e,t){let n=r.length,i=new r.constructor(n);for(let s=0,o=0;o!==n;++s){let a=t[s]*e;for(let l=0;l!==e;++l)i[o++]=r[a+l]}return i}function Ag(r,e,t,n){let i=1,s=r[0];for(;s!==void 0&&s[n]===void 0;)s=r[i++];if(s===void 0)return;let o=s[n];if(o!==void 0)if(Array.isArray(o))do o=s[n],o!==void 0&&(e.push(s.time),t.push(...o)),s=r[i++];while(s!==void 0);else if(o.toArray!==void 0)do o=s[n],o!==void 0&&(e.push(s.time),o.toArray(t,t.length)),s=r[i++];while(s!==void 0);else do o=s[n],o!==void 0&&(e.push(s.time),t.push(o)),s=r[i++];while(s!==void 0)}function K0(r,e,t,n,i=30){let s=r.clone();s.name=e;let o=[];for(let l=0;l=n)){u.push(c.times[f]);for(let _=0;_s.tracks[l].times[0]&&(a=s.tracks[l].times[0]);for(let l=0;l=a.times[p]){let m=p*u+h,y=m+u-h;_=a.values.slice(m,y)}else{let m=a.createInterpolant(),y=h,b=u-h;m.evaluate(s),_=m.resultBuffer.slice(y,b)}l==="quaternion"&&new wt().fromArray(_).normalize().conjugate().toArray(_);let g=c.times.length;for(let m=0;m=s)){let a=t[1];e=s)break t}o=n,n=0;break n}break e}for(;n>>1;et;)--o;if(++o,s!==0||o!==i){s>=o&&(o=Math.max(o,1),s=o-1);let a=this.getValueSize();this.times=n.slice(s,o),this.values=this.values.slice(s*a,o*a)}return this}validate(){let e=!0,t=this.getValueSize();t-Math.floor(t)!==0&&(Pe("KeyframeTrack: Invalid value size in track.",this),e=!1);let n=this.times,i=this.values,s=n.length;s===0&&(Pe("KeyframeTrack: Track is empty.",this),e=!1);let o=null;for(let a=0;a!==s;a++){let l=n[a];if(typeof l=="number"&&isNaN(l)){Pe("KeyframeTrack: Time is not a valid number.",this,a,l),e=!1;break}if(o!==null&&o>l){Pe("KeyframeTrack: Out of order keys.",this,a,l,o),e=!1;break}o=l}if(i!==void 0&&dg(i))for(let a=0,l=i.length;a!==l;++a){let c=i[a];if(isNaN(c)){Pe("KeyframeTrack: Value is not a valid number.",this,a,c),e=!1;break}}return e}optimize(){let e=this.times.slice(),t=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===Fo,s=e.length-1,o=1;for(let a=1;a0){e[o]=e[s];for(let a=s*n,l=o*n,c=0;c!==n;++c)t[l+c]=t[a+c];++o}return o!==e.length?(this.times=e.slice(0,o),this.values=t.slice(0,o*n)):(this.times=e,this.values=t),this}clone(){let e=this.times.slice(),t=this.values.slice(),n=this.constructor,i=new n(this.name,e,t);return i.createInterpolant=this.createInterpolant,Vo(this.settings)&&(i.settings={inTangents:this.settings.inTangents.slice(),outTangents:this.settings.outTangents.slice()}),i}};function nm(r,e){for(let t=0,n=r.length;t!==n;t+=2)r[t]*=e}dn.prototype.ValueTypeName="";dn.prototype.TimeBufferType=Float32Array;dn.prototype.ValueBufferType=Float32Array;dn.prototype.DefaultInterpolation=es;var di=class extends dn{constructor(e,t,n){super(e,t,n)}};di.prototype.ValueTypeName="bool";di.prototype.ValueBufferType=Array;di.prototype.DefaultInterpolation=Qi;di.prototype.InterpolantFactoryMethodLinear=void 0;di.prototype.InterpolantFactoryMethodSmooth=void 0;var Zr=class extends dn{constructor(e,t,n,i){super(e,t,n,i)}};Zr.prototype.ValueTypeName="color";var fi=class extends dn{constructor(e,t,n,i){super(e,t,n,i)}};fi.prototype.ValueTypeName="number";var Da=class extends $n{constructor(e,t,n,i){super(e,t,n,i)}interpolate_(e,t,n,i){let s=this.resultBuffer,o=this.sampleValues,a=this.valueSize,l=(n-t)/(i-t),c=e*a;for(let h=c+a;c!==h;c+=4)wt.slerpFlat(s,0,o,c-a,o,c,l);return s}},pi=class extends dn{constructor(e,t,n,i){super(e,t,n,i)}InterpolantFactoryMethodLinear(e){return new Da(this.times,this.values,this.getValueSize(),e)}};pi.prototype.ValueTypeName="quaternion";pi.prototype.InterpolantFactoryMethodSmooth=void 0;var mi=class extends dn{constructor(e,t,n){super(e,t,n)}};mi.prototype.ValueTypeName="string";mi.prototype.ValueBufferType=Array;mi.prototype.DefaultInterpolation=Qi;mi.prototype.InterpolantFactoryMethodLinear=void 0;mi.prototype.InterpolantFactoryMethodSmooth=void 0;var Ni=class extends dn{constructor(e,t,n,i){super(e,t,n,i)}};Ni.prototype.ValueTypeName="vector";var gi=class{constructor(e="",t=-1,n=[],i=Ll){this.name=e,this.tracks=n,this.duration=t,this.blendMode=i,this.uuid=Tn(),this.userData={},this.duration<0&&this.resetDuration()}static parse(e){let t=[],n=e.tracks,i=1/(e.fps||1);for(let o=0,a=n.length;o!==a;++o)t.push(ex(n[o]).scale(i));let s=new this(e.name,e.duration,t,e.blendMode);return s.uuid=e.uuid,s.userData=JSON.parse(e.userData||"{}"),s}static toJSON(e){let t=[],n=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode,userData:JSON.stringify(e.userData)};for(let s=0,o=n.length;s!==o;++s)t.push(dn.toJSON(n[s]));return i}static CreateFromMorphTargetSequence(e,t,n,i){let s=t.length,o=[];for(let a=0;a1){let u=h[1],d=i[u];d||(i[u]=d=[]),d.push(c)}}let o=[];for(let a in i)o.push(this.CreateFromMorphTargetSequence(a,i[a],t,n));return o}resetDuration(){let e=this.tracks,t=0;for(let n=0,i=e.length;n!==i;++n){let s=this.tracks[n];t=Math.max(t,s.times[s.times.length-1])}return this.duration=t,this}trim(){for(let e=0;e{t&&t(s),this.manager.itemEnd(e)},0);return}if(wi[e]!==void 0){wi[e].push({onLoad:t,onProgress:n,onError:i});return}wi[e]=[],wi[e].push({onLoad:t,onProgress:n,onError:i});let o=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin",signal:typeof AbortSignal.any=="function"?AbortSignal.any([this._abortController.signal,this.manager.abortController.signal]):this._abortController.signal}),a=this.mimeType,l=this.responseType;fetch(o).then(c=>{if(c.status===200||c.status===0){if(c.status===0&&de("FileLoader: HTTP Status 0 received."),typeof ReadableStream>"u"||c.body===void 0||c.body.getReader===void 0)return c;let h=wi[e],u=c.body.getReader(),d=c.headers.get("X-File-Size")||c.headers.get("Content-Length"),f=d?parseInt(d):0,p=f!==0,_=0,g=new ReadableStream({start(m){y();function y(){u.read().then(({done:b,value:x})=>{if(b)m.close();else{_+=x.byteLength;let T=new ProgressEvent("progress",{lengthComputable:p,loaded:_,total:f});for(let S=0,w=h.length;S{m.error(b)})}}});return new Response(g)}else throw new hd(`fetch for "${c.url}" responded with ${c.status}: ${c.statusText}`,c)}).then(c=>{switch(l){case"arraybuffer":return c.arrayBuffer();case"blob":return c.blob();case"document":return c.text().then(h=>new DOMParser().parseFromString(h,a));case"json":return c.json();default:if(a==="")return c.text();{let u=/charset="?([^;"\s]*)"?/i.exec(a),d=u&&u[1]?u[1].toLowerCase():void 0,f=new TextDecoder(d);return c.arrayBuffer().then(p=>f.decode(p))}}}).then(c=>{Yn.add(`file:${e}`,c);let h=wi[e];delete wi[e];for(let u=0,d=h.length;u{let h=wi[e];if(h===void 0)throw this.manager.itemError(e),c;delete wi[e];for(let u=0,d=h.length;u{this.manager.itemEnd(e)}),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}abort(){return this._abortController.abort(),this._abortController=new AbortController,this}},th=class extends It{constructor(e){super(e)}load(e,t,n,i){let s=this,o=new kt(this.manager);o.setPath(this.path),o.setRequestHeader(this.requestHeader),o.setWithCredentials(this.withCredentials),o.load(e,function(a){try{t(s.parse(JSON.parse(a)))}catch(l){i?i(l):Pe(l),s.manager.itemError(e)}},n,i)}parse(e){let t=[];for(let n=0;n0){let l=new Kr(t);s=new as(l),s.setCrossOrigin(this.crossOrigin);for(let c=0,h=e.length;c0){i=new as(this.manager),i.setCrossOrigin(this.crossOrigin);for(let o=0,a=e.length;o{let m=null,y=null;return g.boundingBox!==void 0&&(m=new Ft().fromJSON(g.boundingBox)),g.boundingSphere!==void 0&&(y=new Nt().fromJSON(g.boundingSphere)),{...g,boundingBox:m,boundingSphere:y}}),o._instanceInfo=e.instanceInfo,o._availableInstanceIds=e._availableInstanceIds,o._availableGeometryIds=e._availableGeometryIds,o._nextIndexStart=e.nextIndexStart,o._nextVertexStart=e.nextVertexStart,o._geometryCount=e.geometryCount,o._maxInstanceCount=e.maxInstanceCount,o._maxVertexCount=e.maxVertexCount,o._maxIndexCount=e.maxIndexCount,o._geometryInitialized=e.geometryInitialized,o._matricesTexture=c(e.matricesTexture.uuid),o._indirectTexture=c(e.indirectTexture.uuid),e.colorsTexture!==void 0&&(o._colorsTexture=c(e.colorsTexture.uuid)),e.boundingSphere!==void 0&&(o.boundingSphere=new Nt().fromJSON(e.boundingSphere)),e.boundingBox!==void 0&&(o.boundingBox=new Ft().fromJSON(e.boundingBox));break;case"LOD":o=new Qo;break;case"Line":o=new En(a(e.geometry),l(e.material));break;case"LineLoop":o=new Ds(a(e.geometry),l(e.material));break;case"LineSegments":o=new Xt(a(e.geometry),l(e.material));break;case"PointCloud":case"Points":o=new jn(a(e.geometry),l(e.material));break;case"Sprite":o=new $o(l(e.material));break;case"Group":o=new cn;break;case"Bone":o=new is;break;default:o=new st}if(o.uuid=e.uuid,e.name!==void 0&&(o.name=e.name),e.matrix!==void 0?(o.matrix.fromArray(e.matrix),e.matrixAutoUpdate!==void 0&&(o.matrixAutoUpdate=e.matrixAutoUpdate),o.matrixAutoUpdate&&o.matrix.decompose(o.position,o.quaternion,o.scale)):(e.position!==void 0&&o.position.fromArray(e.position),e.rotation!==void 0&&o.rotation.fromArray(e.rotation),e.quaternion!==void 0&&o.quaternion.fromArray(e.quaternion),e.scale!==void 0&&o.scale.fromArray(e.scale)),e.up!==void 0&&o.up.fromArray(e.up),e.pivot!==void 0&&(o.pivot=new R().fromArray(e.pivot)),e.morphTargetDictionary!==void 0&&(o.morphTargetDictionary=Object.assign({},e.morphTargetDictionary)),e.morphTargetInfluences!==void 0&&(o.morphTargetInfluences=e.morphTargetInfluences.slice()),e.castShadow!==void 0&&(o.castShadow=e.castShadow),e.receiveShadow!==void 0&&(o.receiveShadow=e.receiveShadow),e.shadow&&(e.shadow.intensity!==void 0&&(o.shadow.intensity=e.shadow.intensity),e.shadow.bias!==void 0&&(o.shadow.bias=e.shadow.bias),e.shadow.normalBias!==void 0&&(o.shadow.normalBias=e.shadow.normalBias),e.shadow.radius!==void 0&&(o.shadow.radius=e.shadow.radius),e.shadow.blurSamples!==void 0&&(o.shadow.blurSamples=e.shadow.blurSamples),e.shadow.focus!==void 0&&(o.shadow.focus=e.shadow.focus),e.shadow.aspect!==void 0&&(o.shadow.aspect=e.shadow.aspect),e.shadow.mapSize!==void 0&&o.shadow.mapSize.fromArray(e.shadow.mapSize),e.shadow.camera!==void 0&&(o.shadow.camera=this.parseObject(e.shadow.camera))),e.visible!==void 0&&(o.visible=e.visible),e.frustumCulled!==void 0&&(o.frustumCulled=e.frustumCulled),e.renderOrder!==void 0&&(o.renderOrder=e.renderOrder),e.static!==void 0&&(o.static=e.static),e.userData!==void 0&&(o.userData=e.userData),e.layers!==void 0&&(o.layers.mask=e.layers),e.children!==void 0){let d=e.children;for(let f=0;f"u"&&de("ImageBitmapLoader: createImageBitmap() not supported."),typeof fetch>"u"&&de("ImageBitmapLoader: fetch() not supported."),this.options={premultiplyAlpha:"none"},this._abortController=new AbortController}setOptions(e){return this.options=e,this}load(e,t,n,i){e===void 0&&(e=""),this.path!==void 0&&(e=this.path+e),e=this.manager.resolveURL(e);let s=this,o=Yn.get(`image-bitmap:${e}`);if(o!==void 0){if(s.manager.itemStart(e),o.then){o.then(c=>{Qu.has(o)===!0?(i&&i(Qu.get(o)),s.manager.itemError(e),s.manager.itemEnd(e)):(t&&t(c),s.manager.itemEnd(e))});return}setTimeout(function(){t&&t(o),s.manager.itemEnd(e)},0);return}let a={};a.credentials=this.crossOrigin==="anonymous"?"same-origin":"include",a.headers=this.requestHeader,a.signal=typeof AbortSignal.any=="function"?AbortSignal.any([this._abortController.signal,this.manager.abortController.signal]):this._abortController.signal;let l=fetch(e,a).then(function(c){return c.blob()}).then(function(c){return createImageBitmap(c,Object.assign({},s.options,{colorSpaceConversion:"none"}))}).then(function(c){return Yn.add(`image-bitmap:${e}`,c),t&&t(c),s.manager.itemEnd(e),c}).catch(function(c){i&&i(c),Qu.set(l,c),Yn.remove(`image-bitmap:${e}`),s.manager.itemError(e),s.manager.itemEnd(e)});Yn.add(`image-bitmap:${e}`,l),s.manager.itemStart(e)}abort(){return this._abortController.abort(),this._abortController=new AbortController,this}},Ec,Qr=class{static getContext(){return Ec===void 0&&(Ec=new(window.AudioContext||window.webkitAudioContext)),Ec}static setContext(e){Ec=e}},oh=class extends It{constructor(e){super(e)}load(e,t,n,i){let s=this,o=new kt(this.manager);o.setResponseType("arraybuffer"),o.setPath(this.path),o.setRequestHeader(this.requestHeader),o.setWithCredentials(this.withCredentials),o.load(e,function(l){try{let c=l.slice(0),h=Qr.getContext(),u=e+"#decode";s.manager.itemStart(u),h.decodeAudioData(c,function(d){t(d),s.manager.itemEnd(u)}).catch(function(d){a(d),s.manager.itemEnd(u)})}catch(c){a(c)}},n,i);function a(l){i?i(l):Pe(l),s.manager.itemError(e)}}},um=new ze,dm=new ze,xs=new ze,ah=class{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new Lt,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new Lt,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(e){let t=this._cache;if(t.focus!==e.focus||t.fov!==e.fov||t.aspect!==e.aspect*this.aspect||t.near!==e.near||t.far!==e.far||t.zoom!==e.zoom||t.eyeSep!==this.eyeSep){t.focus=e.focus,t.fov=e.fov,t.aspect=e.aspect*this.aspect,t.near=e.near,t.far=e.far,t.zoom=e.zoom,t.eyeSep=this.eyeSep,xs.copy(e.projectionMatrix);let i=t.eyeSep/2,s=i*t.near/t.focus,o=t.near*Math.tan(Ts*t.fov*.5)/t.zoom,a,l;dm.elements[12]=-i,um.elements[12]=i,a=-o*t.aspect+s,l=o*t.aspect+s,xs.elements[0]=2*t.near/(l-a),xs.elements[8]=(l+a)/(l-a),this.cameraL.projectionMatrix.copy(xs),a=-o*t.aspect-s,l=o*t.aspect-s,xs.elements[0]=2*t.near/(l-a),xs.elements[8]=(l+a)/(l-a),this.cameraR.projectionMatrix.copy(xs)}this.cameraL.matrix.copy(e.matrixWorld).multiply(dm),this.cameraL.matrixWorldNeedsUpdate=!0,this.cameraR.matrix.copy(e.matrixWorld).multiply(um),this.cameraR.matrixWorldNeedsUpdate=!0}},yr=-90,vr=1,Ga=class extends st{constructor(e,t,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;let i=new Lt(yr,vr,e,t);i.layers=this.layers,this.add(i);let s=new Lt(yr,vr,e,t);s.layers=this.layers,this.add(s);let o=new Lt(yr,vr,e,t);o.layers=this.layers,this.add(o);let a=new Lt(yr,vr,e,t);a.layers=this.layers,this.add(a);let l=new Lt(yr,vr,e,t);l.layers=this.layers,this.add(l);let c=new Lt(yr,vr,e,t);c.layers=this.layers,this.add(c)}updateCoordinateSystem(){let e=this.coordinateSystem,t=this.children.concat(),[n,i,s,o,a,l]=t;for(let c of t)this.remove(c);if(e===_n)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),s.up.set(0,0,-1),s.lookAt(0,1,0),o.up.set(0,0,1),o.lookAt(0,-1,0),a.up.set(0,1,0),a.lookAt(0,0,1),l.up.set(0,1,0),l.lookAt(0,0,-1);else if(e===ts)n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),s.up.set(0,0,1),s.lookAt(0,1,0),o.up.set(0,0,-1),o.lookAt(0,-1,0),a.up.set(0,-1,0),a.lookAt(0,0,1),l.up.set(0,-1,0),l.lookAt(0,0,-1);else throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);for(let c of t)this.add(c),c.updateMatrixWorld()}update(e,t){this.parent===null&&this.updateMatrixWorld();let{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());let[s,o,a,l,c,h]=this.children,u=e.getRenderTarget(),d=e.getActiveCubeFace(),f=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;let _=n.texture.generateMipmaps;n.texture.generateMipmaps=!1;let g=!1;e.isWebGLRenderer===!0?g=e.state.buffers.depth.getReversed():g=e.reversedDepthBuffer,e.setRenderTarget(n,0,i),g&&e.autoClear===!1&&e.clearDepth(),e.render(t,s),e.setRenderTarget(n,1,i),g&&e.autoClear===!1&&e.clearDepth(),e.render(t,o),e.setRenderTarget(n,2,i),g&&e.autoClear===!1&&e.clearDepth(),e.render(t,a),e.setRenderTarget(n,3,i),g&&e.autoClear===!1&&e.clearDepth(),e.render(t,l),e.setRenderTarget(n,4,i),g&&e.autoClear===!1&&e.clearDepth(),e.render(t,c),n.texture.generateMipmaps=_,e.setRenderTarget(n,5,i),g&&e.autoClear===!1&&e.clearDepth(),e.render(t,h),e.setRenderTarget(u,d,f),e.xr.enabled=p,n.texture.needsPMREMUpdate=!0}},Ha=class extends Lt{constructor(e=[]){super(),this.isArrayCamera=!0,this.isMultiViewCamera=!1,this.cameras=e}},Wa=class{constructor(){this._previousTime=0,this._currentTime=0,this._startTime=performance.now(),this._delta=0,this._elapsed=0,this._timescale=1,this._document=null,this._pageVisibilityHandler=null}connect(e){this._document=e,e.hidden!==void 0&&(this._pageVisibilityHandler=nx.bind(this),e.addEventListener("visibilitychange",this._pageVisibilityHandler,!1))}disconnect(){this._pageVisibilityHandler!==null&&(this._document.removeEventListener("visibilitychange",this._pageVisibilityHandler),this._pageVisibilityHandler=null),this._document=null}getDelta(){return this._delta/1e3}getElapsed(){return this._elapsed/1e3}getTimescale(){return this._timescale}setTimescale(e){return this._timescale=e,this}reset(){return this._currentTime=performance.now()-this._startTime,this}dispose(){this.disconnect()}update(e){return this._pageVisibilityHandler!==null&&this._document.hidden===!0?this._delta=0:(this._previousTime=this._currentTime,this._currentTime=(e!==void 0?e:performance.now())-this._startTime,this._delta=(this._currentTime-this._previousTime)*this._timescale,this._elapsed+=this._delta),this}};function nx(){this._document.hidden===!1&&this.reset()}var ys=new R,ed=new wt,ix=new R,vs=new R,Ms=new R,lh=class extends st{constructor(){super(),this.type="AudioListener",this.context=Qr.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._timer=new Wa}getInput(){return this.gain}removeFilter(){return this.filter!==null&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(e){return this.filter!==null?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=e,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(e){return this.gain.gain.setTargetAtTime(e,this.context.currentTime,.01),this}updateMatrixWorld(e){super.updateMatrixWorld(e),this._timer.update();let t=this.context.listener;if(this.timeDelta=this._timer.getDelta(),this.matrixWorld.decompose(ys,ed,ix),vs.set(0,0,-1).applyQuaternion(ed),Ms.set(0,1,0).applyQuaternion(ed),t.positionX){let n=this.context.currentTime+this.timeDelta;t.positionX.linearRampToValueAtTime(ys.x,n),t.positionY.linearRampToValueAtTime(ys.y,n),t.positionZ.linearRampToValueAtTime(ys.z,n),t.forwardX.linearRampToValueAtTime(vs.x,n),t.forwardY.linearRampToValueAtTime(vs.y,n),t.forwardZ.linearRampToValueAtTime(vs.z,n),t.upX.linearRampToValueAtTime(Ms.x,n),t.upY.linearRampToValueAtTime(Ms.y,n),t.upZ.linearRampToValueAtTime(Ms.z,n)}else t.setPosition(ys.x,ys.y,ys.z),t.setOrientation(vs.x,vs.y,vs.z,Ms.x,Ms.y,Ms.z)}},Xa=class extends st{constructor(e){super(),this.type="Audio",this.listener=e,this.context=e.context,this.gain=this.context.createGain(),this.gain.connect(e.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(e){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=e,this.connect(),this}setMediaElementSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(e),this.connect(),this}setMediaStreamSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(e),this.connect(),this}setBuffer(e){return this.buffer=e,this.sourceType="buffer",this.autoplay&&this.play(),this}play(e=0){if(this.isPlaying===!0){de("Audio: Audio is already playing.");return}if(this.hasPlaybackControl===!1){de("Audio: this Audio has no playback control.");return}this._startedAt=this.context.currentTime+e;let t=this.context.createBufferSource();return t.buffer=this.buffer,t.loop=this.loop,t.loopStart=this.loopStart,t.loopEnd=this.loopEnd,t.onended=this.onEnded.bind(this),t.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=t,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(this.hasPlaybackControl===!1){de("Audio: this Audio has no playback control.");return}return this.isPlaying===!0&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,this.loop===!0&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this}stop(e=0){if(this.hasPlaybackControl===!1){de("Audio: this Audio has no playback control.");return}return this._progress=0,this.source!==null&&(this.source.stop(this.context.currentTime+e),this.source.onended=null),this.isPlaying=!1,this}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(let e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(let e=1,t=this.filters.length;e0&&this._mixBufferRegionAdditive(n,i,this._addIndex*t,1,t);for(let l=t,c=t+t;l!==c;++l)if(n[l]!==n[l+t]){a.setValue(n,i);break}}saveOriginalState(){let e=this.binding,t=this.buffer,n=this.valueSize,i=n*this._origIndex;e.getValue(t,i);for(let s=n,o=i;s!==o;++s)t[s]=t[i+s%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){let e=this.valueSize*3;this.binding.setValue(this.buffer,e)}_setAdditiveIdentityNumeric(){let e=this._addIndex*this.valueSize,t=e+this.valueSize;for(let n=e;n=.5)for(let o=0;o!==s;++o)e[t+o]=e[n+o]}_slerp(e,t,n,i){wt.slerpFlat(e,t,e,t,e,n,i)}_slerpAdditive(e,t,n,i,s){let o=this._workIndex*s;wt.multiplyQuaternionsFlat(e,o,e,t,e,n),wt.slerpFlat(e,t,e,t,e,o,i)}_lerp(e,t,n,i,s){let o=1-i;for(let a=0;a!==s;++a){let l=t+a;e[l]=e[l]*o+e[n+a]*i}}_lerpAdditive(e,t,n,i,s){for(let o=0;o!==s;++o){let a=t+o;e[a]=e[a]+e[n+o]*i}}},of="\\[\\]\\.:\\/",rx=new RegExp("["+of+"]","g"),af="[^"+of+"]",ox="[^"+of.replace("\\.","")+"]",ax=/((?:WC+[\/:])*)/.source.replace("WC",af),lx=/(WCOD+)?/.source.replace("WCOD",ox),cx=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",af),hx=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",af),ux=new RegExp("^"+ax+lx+cx+hx+"$"),dx=["material","materials","bones","map"],pd=class{constructor(e,t,n){let i=n||lt.parseTrackName(t);this._targetGroup=e,this._bindings=e.subscribe_(t,i)}getValue(e,t){this.bind();let n=this._targetGroup.nCachedObjects_,i=this._bindings[n];i!==void 0&&i.getValue(e,t)}setValue(e,t){let n=this._bindings;for(let i=this._targetGroup.nCachedObjects_,s=n.length;i!==s;++i)n[i].setValue(e,t)}bind(){let e=this._bindings;for(let t=this._targetGroup.nCachedObjects_,n=e.length;t!==n;++t)e[t].bind()}unbind(){let e=this._bindings;for(let t=this._targetGroup.nCachedObjects_,n=e.length;t!==n;++t)e[t].unbind()}},lt=class r{constructor(e,t,n){this.path=t,this.parsedPath=n||r.parseTrackName(t),this.node=r.findNode(e,this.parsedPath.nodeName),this.rootNode=e,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(e,t,n){return e&&e.isAnimationObjectGroup?new r.Composite(e,t,n):new r(e,t,n)}static sanitizeNodeName(e){return e.replace(/\s/g,"_").replace(rx,"")}static parseTrackName(e){let t=ux.exec(e);if(t===null)throw new Error("THREE.PropertyBinding: Cannot parse trackName: "+e);let n={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(i!==void 0&&i!==-1){let s=n.nodeName.substring(i+1);dx.indexOf(s)!==-1&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=s)}if(n.propertyName===null||n.propertyName.length===0)throw new Error("THREE.PropertyBinding: can not parse propertyName from trackName: "+e);return n}static findNode(e,t){if(t===void 0||t===""||t==="."||t===-1||t===e.name||t===e.uuid)return e;if(e.skeleton){let n=e.skeleton.getBoneByName(t);if(n!==void 0)return n}if(e.children){let n=function(s){for(let o=0;o=s){let u=s++,d=e[u];t[d.uuid]=h,e[h]=d,t[c]=u,e[u]=l;for(let f=0,p=i;f!==p;++f){let _=n[f],g=_[u],m=_[h];_[h]=g,_[u]=m}}}this.nCachedObjects_=s}uncache(){let e=this._objects,t=this._indicesByUUID,n=this._bindings,i=n.length,s=this.nCachedObjects_,o=e.length;for(let a=0,l=arguments.length;a!==l;++a){let c=arguments[a],h=c.uuid,u=t[h];if(u!==void 0)if(delete t[h],u0){let l=this._interpolants,c=this._propertyBindings;switch(this.blendMode){case iu:for(let h=0,u=l.length;h!==u;++h)l[h].evaluate(o),c[h].accumulateAdditive(a);break;case Ll:default:for(let h=0,u=l.length;h!==u;++h)l[h].evaluate(o),c[h].accumulate(i,a)}}}_updateWeight(e){let t=0;if(this.enabled){t=this.weight;let n=this._weightInterpolant;if(n!==null){let i=n.evaluate(e)[0];t*=i,e>n.parameterPositions[1]&&(this.stopFading(),i===0&&(this.enabled=!1))}}return this._effectiveWeight=t,t}_updateTimeScale(e){let t=0;if(!this.paused){t=this.timeScale;let n=this._timeScaleInterpolant;if(n!==null){let i=n.evaluate(e)[0];t*=i,e>n.parameterPositions[1]&&(t===0?this.paused=!0:(this._restoreTimeScale!==null&&(t=this._restoreTimeScale),this.timeScale=t),this.stopWarping())}}return this._effectiveTimeScale=t,t}_updateTime(e){let t=this._clip.duration,n=this.loop,i=this.time+e,s=this._loopCount,o=n===Hd;if(e===0)return s===-1?i:o&&(s&1)===1?t-i:i;if(n===Vd){s===-1&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(i>=t)i=t;else if(i<0)i=0;else{this.time=i;break e}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{if(s===-1&&(e>=0?(s=0,this._setEndings(!0,this.repetitions===0,o)):this._setEndings(this.repetitions===0,!0,o)),i>=t||i<0){let a=Math.floor(i/t);i-=t*a,s+=Math.abs(a);let l=this.repetitions-s;if(l<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=e>0?t:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(l===1){let c=e<0;this._setEndings(c,!c,o)}else this._setEndings(!1,!1,o);this._loopCount=s,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:a})}}else this._loopCount=s,this.time=i;if(o&&(s&1)===1)return t-i}return i}_setEndings(e,t,n){let i=this._interpolantSettings;n?(i.endingStart=ji,i.endingEnd=ji):(e?i.endingStart=this.zeroSlopeAtStart?ji:Ji:i.endingStart=Ar,t?i.endingEnd=this.zeroSlopeAtEnd?ji:Ji:i.endingEnd=Ar)}_scheduleFading(e,t,n){let i=this._mixer,s=i.time,o=this._weightInterpolant;o===null&&(o=i._lendControlInterpolant(),this._weightInterpolant=o);let a=o.parameterPositions,l=o.sampleValues;return a[0]=s,l[0]=t,a[1]=s+e,l[1]=n,this}},fx=new Float32Array(1),dh=class extends xn{constructor(e){super(),this._root=e,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1,typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}_bindAction(e,t){let n=e._localRoot||this._root,i=e._clip.tracks,s=i.length,o=e._propertyBindings,a=e._interpolants,l=n.uuid,c=this._bindingsByRootAndName,h=c[l];h===void 0&&(h={},c[l]=h);for(let u=0;u!==s;++u){let d=i[u],f=d.name,p=h[f];if(p!==void 0)++p.referenceCount,o[u]=p;else{if(p=o[u],p!==void 0){p._cacheIndex===null&&(++p.referenceCount,this._addInactiveBinding(p,l,f));continue}let _=t&&t._propertyBindings[u].binding.parsedPath;p=new qa(lt.create(n,f,_),d.ValueTypeName,d.getValueSize()),++p.referenceCount,this._addInactiveBinding(p,l,f),o[u]=p}a[u].resultBuffer=p.buffer}}_activateAction(e){if(!this._isActiveAction(e)){if(e._cacheIndex===null){let n=(e._localRoot||this._root).uuid,i=e._clip.uuid,s=this._actionsByClip[i];this._bindAction(e,s&&s.knownActions[0]),this._addInactiveAction(e,i,n)}let t=e._propertyBindings;for(let n=0,i=t.length;n!==i;++n){let s=t[n];s.useCount++===0&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}}_deactivateAction(e){if(this._isActiveAction(e)){let t=e._propertyBindings;for(let n=0,i=t.length;n!==i;++n){let s=t[n];--s.useCount===0&&(s.restoreOriginalState(),this._takeBackBinding(s))}this._takeBackAction(e)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;let 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(e){let t=e._cacheIndex;return t!==null&&t=0;--n)e[n].stop();return this}update(e){e*=this.timeScale;let t=this._actions,n=this._nActiveActions,i=this.time+=e,s=Math.sign(e),o=this._accuIndex^=1;for(let c=0;c!==n;++c)t[c]._update(i,e,s,o);let a=this._bindings,l=this._nActiveBindings;for(let c=0;c!==l;++c)a[c].apply(o);return this}setTime(e){this.time=0;for(let t=0;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y}containsBox(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(e,t){return 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(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,gm).distanceTo(e)}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}},_m=new R,wc=new R,Mr=new R,Sr=new R,td=new R,mx=new R,gx=new R,Sh=class{constructor(e=new R,t=new R){this.start=e,this.end=t}set(e,t){return this.start.copy(e),this.end.copy(t),this}copy(e){return this.start.copy(e.start),this.end.copy(e.end),this}getCenter(e){return e.addVectors(this.start,this.end).multiplyScalar(.5)}delta(e){return e.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(e,t){return this.delta(t).multiplyScalar(e).add(this.start)}closestPointToPointParameter(e,t){_m.subVectors(e,this.start),wc.subVectors(this.end,this.start);let n=wc.dot(wc);if(n===0)return 0;let s=wc.dot(_m)/n;return t&&(s=He(s,0,1)),s}closestPointToPoint(e,t,n){let i=this.closestPointToPointParameter(e,t);return this.delta(n).multiplyScalar(i).add(this.start)}distanceSqToLine3(e,t=mx,n=gx){let i=10000000000000001e-32,s,o,a=this.start,l=e.start,c=this.end,h=e.end;Mr.subVectors(c,a),Sr.subVectors(h,l),td.subVectors(a,l);let u=Mr.dot(Mr),d=Sr.dot(Sr),f=Sr.dot(td);if(u<=i&&d<=i)return t.copy(a),n.copy(l),t.sub(n),t.dot(t);if(u<=i)s=0,o=f/d,o=He(o,0,1);else{let p=Mr.dot(td);if(d<=i)o=0,s=He(-p/u,0,1);else{let _=Mr.dot(Sr),g=u*d-_*_;g!==0?s=He((_*f-p*d)/g,0,1):s=0,o=(_*s+f)/d,o<0?(o=0,s=He(-p/u,0,1)):o>1&&(o=1,s=He((_-p)/u,0,1))}}return t.copy(a).addScaledVector(Mr,s),n.copy(l).addScaledVector(Sr,o),t.distanceToSquared(n)}applyMatrix4(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this}equals(e){return e.start.equals(this.start)&&e.end.equals(this.end)}clone(){return new this.constructor().copy(this)}},xm=new R,bh=class extends st{constructor(e,t){super(),this.light=e,this.matrixAutoUpdate=!1,this.color=t,this.type="SpotLightHelper";let n=new Oe,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let o=0,a=1,l=32;o1)for(let u=0;u.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{bm.set(e.z,0,-e.x).normalize();let t=Math.acos(e.y);this.quaternion.setFromAxisAngle(bm,t)}}setLength(e,t=e*.2,n=t*.2){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(n,t,n),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){super.dispose(),this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},Uh=class extends Xt{constructor(e=1){let t=[0,0,0,e,0,0,0,0,0,0,e,0,0,0,0,0,0,e],n=[1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],i=new Oe;i.setAttribute("position",new fe(t,3)),i.setAttribute("color",new fe(n,3));let s=new Rt({vertexColors:!0,toneMapped:!1});super(i,s),this.type="AxesHelper"}setColors(e,t,n){let i=new ce,s=this.geometry.attributes.color.array;return i.set(e),i.toArray(s,0),i.toArray(s,3),i.set(t),i.toArray(s,6),i.toArray(s,9),i.set(n),i.toArray(s,12),i.toArray(s,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){super.dispose(),this.geometry.dispose(),this.material.dispose()}},Fh=class{constructor(){this.type="ShapePath",this.color=new ce,this.subPaths=[],this.currentPath=null,this.userData={}}moveTo(e,t){return this.currentPath=new rs,this.subPaths.push(this.currentPath),this.currentPath.moveTo(e,t),this}lineTo(e,t){return this.currentPath.lineTo(e,t),this}quadraticCurveTo(e,t,n,i){return this.currentPath.quadraticCurveTo(e,t,n,i),this}bezierCurveTo(e,t,n,i,s,o){return this.currentPath.bezierCurveTo(e,t,n,i,s,o),this}splineThru(e){return this.currentPath.splineThru(e),this}toShapes(){function e(l,c){let h=!1,u=c.length;for(let d=0,f=u-1;dl.y!=_.y>l.y&&l.x<(_.x-p.x)*(l.y-p.y)/(_.y-p.y)+p.x&&(h=!h)}return h}function t(l,c){let h=c.getCenter(new J);if(e(h,l))return h;let u=h.y,d=[],f=l.length;for(let p=0;pu!=g.y>u){let m=_.x+(u-_.y)*(g.x-_.x)/(g.y-_.y);d.push(m)}}return d.length>1&&(d.sort((p,_)=>p-_),h.x=(d[0]+d[1])/2),h}let n=this.userData.style&&this.userData.style.fillRule||"nonzero";n!=="nonzero"&&n!=="evenodd"&&(de('Fill-rule "'+n+'" is not supported, falling back to "nonzero".'),n="nonzero");let i=n==="nonzero"?(l=>l!==0):(l=>(l&1)!==0),s=[];for(let l of this.subPaths){let c=l.getPoints();if(c.length<3)continue;let h=Nn.area(c);if(h===0)continue;let u=new Za;for(let d=0;dc.absArea-l.absArea);for(let l=0;l=0;u--){let d=s[u];if(d.boundingBox.containsBox(c.boundingBox)&&e(c.interiorPoint,d.points)){c.container=d.exclude?d.container:d,h=d.winding,c.winding+=h;break}}i(c.winding)===i(h)&&(c.exclude=!0)}for(let l of s)l.exclude||(l.role=l.container===null||l.container.role==="hole"?"outer":"hole");let o=[],a=new Map;for(let l of s){if(l.exclude||l.role!=="outer")continue;let c=new os;c.curves=l.subPath.curves,o.push(c),a.set(l,c)}for(let l of s){if(l.exclude||l.role!=="hole")continue;let c=a.get(l.container);if(!c)continue;let h=new rs;h.curves=l.subPath.curves,c.holes.push(h)}return o}},eo=class extends xn{constructor(e,t=null){super(),this.object=e,this.domElement=t,this.enabled=!0,this.state=-1,this.keys={},this.mouseButtons={LEFT:null,MIDDLE:null,RIGHT:null},this.touches={ONE:null,TWO:null}}connect(e){this.domElement!==null&&this.disconnect(),this.domElement=e}disconnect(){}dispose(){}update(){}};function xx(r,e){let t=r.image&&r.image.width?r.image.width/r.image.height:1;return t>e?(r.repeat.x=1,r.repeat.y=t/e,r.offset.x=0,r.offset.y=(1-r.repeat.y)/2):(r.repeat.x=e/t,r.repeat.y=1,r.offset.x=(1-r.repeat.x)/2,r.offset.y=0),r}function yx(r,e){let t=r.image&&r.image.width?r.image.width/r.image.height:1;return t>e?(r.repeat.x=e/t,r.repeat.y=1,r.offset.x=(1-r.repeat.x)/2,r.offset.y=0):(r.repeat.x=1,r.repeat.y=t/e,r.offset.x=0,r.offset.y=(1-r.repeat.y)/2),r}function vx(r){return r.repeat.x=1,r.repeat.y=1,r.offset.x=0,r.offset.y=0,r}function ou(r,e,t,n){let i=Mx(n);switch(t){case tu:return r*e;case Qa:return r*e/i.components*i.byteLength;case oo:return r*e/i.components*i.byteLength;case ki:return r*e*2/i.components*i.byteLength;case el:return r*e*2/i.components*i.byteLength;case nu:return r*e*3/i.components*i.byteLength;case tn:return r*e*4/i.components*i.byteLength;case tl:return r*e*4/i.components*i.byteLength;case ao:case lo:return Math.floor((r+3)/4)*Math.floor((e+3)/4)*8;case co:case ho:return Math.floor((r+3)/4)*Math.floor((e+3)/4)*16;case il:case rl:return Math.max(r,16)*Math.max(e,8)/4;case nl:case sl:return Math.max(r,8)*Math.max(e,8)/2;case ol:case al:case cl:case hl:return Math.floor((r+3)/4)*Math.floor((e+3)/4)*8;case ll:case uo:case ul:return Math.floor((r+3)/4)*Math.floor((e+3)/4)*16;case dl:return Math.floor((r+3)/4)*Math.floor((e+3)/4)*16;case fl:return Math.floor((r+4)/5)*Math.floor((e+3)/4)*16;case pl:return Math.floor((r+4)/5)*Math.floor((e+4)/5)*16;case ml:return Math.floor((r+5)/6)*Math.floor((e+4)/5)*16;case gl:return Math.floor((r+5)/6)*Math.floor((e+5)/6)*16;case _l:return Math.floor((r+7)/8)*Math.floor((e+4)/5)*16;case xl:return Math.floor((r+7)/8)*Math.floor((e+5)/6)*16;case yl:return Math.floor((r+7)/8)*Math.floor((e+7)/8)*16;case vl:return Math.floor((r+9)/10)*Math.floor((e+4)/5)*16;case Ml:return Math.floor((r+9)/10)*Math.floor((e+5)/6)*16;case Sl:return Math.floor((r+9)/10)*Math.floor((e+7)/8)*16;case bl:return Math.floor((r+9)/10)*Math.floor((e+9)/10)*16;case Tl:return Math.floor((r+11)/12)*Math.floor((e+9)/10)*16;case Al:return Math.floor((r+11)/12)*Math.floor((e+11)/12)*16;case El:case wl:case Rl:return Math.ceil(r/4)*Math.ceil(e/4)*16;case Cl:case Il:return Math.ceil(r/4)*Math.ceil(e/4)*8;case fo:case Pl:return Math.ceil(r/4)*Math.ceil(e/4)*16}throw new Error(`Unable to determine texture byte length for ${t} format.`)}function Mx(r){switch(r){case fn:case jh:return{byteLength:1,components:1};case Ks:case $h:case Bn:return{byteLength:2,components:1};case ja:case $a:return{byteLength:2,components:4};case Cn:case Ja:case en:return{byteLength:4,components:1};case Qh:case eu:return{byteLength:4,components:3}}throw new Error(`THREE.TextureUtils: Unknown texture type ${r}.`)}var Oh=class{static contain(e,t){return xx(e,t)}static cover(e,t){return yx(e,t)}static fill(e){return vx(e)}static getByteLength(e,t,n,i){return ou(e,t,n,i)}};typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:"186"}}));typeof window<"u"&&(window.__THREE__?de("WARNING: Multiple instances of Three.js being imported."):window.__THREE__="186");function Kg(){let r=null,e=!1,t=null,n=null;function i(s,o){n=r.requestAnimationFrame(i),t(s,o)}return{start:function(){e!==!0&&t!==null&&r!==null&&(n=r.requestAnimationFrame(i),e=!0)},stop:function(){r!==null&&r.cancelAnimationFrame(n),e=!1},setAnimationLoop:function(s){t=s},setContext:function(s){r=s}}}function Sx(r){let e=new WeakMap;function t(a,l){let c=a.array,h=a.usage,u=c.byteLength,d=r.createBuffer();r.bindBuffer(l,d),r.bufferData(l,c,h),a.onUploadCallback();let f;if(c instanceof Float32Array)f=r.FLOAT;else if(typeof Float16Array<"u"&&c instanceof Float16Array)f=r.HALF_FLOAT;else if(c instanceof Uint16Array)a.isFloat16BufferAttribute?f=r.HALF_FLOAT:f=r.UNSIGNED_SHORT;else if(c instanceof Int16Array)f=r.SHORT;else if(c instanceof Uint32Array)f=r.UNSIGNED_INT;else if(c instanceof Int32Array)f=r.INT;else if(c instanceof Int8Array)f=r.BYTE;else if(c instanceof Uint8Array)f=r.UNSIGNED_BYTE;else if(c instanceof Uint8ClampedArray)f=r.UNSIGNED_BYTE;else throw new Error("THREE.WebGLAttributes: Unsupported buffer data format: "+c);return{buffer:d,type:f,bytesPerElement:c.BYTES_PER_ELEMENT,version:a.version,size:u}}function n(a,l,c){let h=l.array,u=l.updateRanges;if(r.bindBuffer(c,a),u.length===0)r.bufferSubData(c,0,h);else{u.sort((f,p)=>f.start-p.start);let d=0;for(let f=1;f 0 + vec4 plane; + #ifdef ALPHA_TO_COVERAGE + float distanceToPlane, distanceGradient; + float clipOpacity = 1.0; + #pragma unroll_loop_start + for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; + distanceGradient = fwidth( distanceToPlane ) / 2.0; + clipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); + if ( clipOpacity == 0.0 ) discard; + } + #pragma unroll_loop_end + #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES + float unionClipOpacity = 1.0; + #pragma unroll_loop_start + for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; + distanceGradient = fwidth( distanceToPlane ) / 2.0; + unionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); + } + #pragma unroll_loop_end + clipOpacity *= 1.0 - unionClipOpacity; + #endif + diffuseColor.a *= clipOpacity; + if ( diffuseColor.a == 0.0 ) discard; + #else + #pragma unroll_loop_start + for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard; + } + #pragma unroll_loop_end + #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES + bool clipped = true; + #pragma unroll_loop_start + for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped; + } + #pragma unroll_loop_end + if ( clipped ) discard; + #endif + #endif +#endif`,zx=`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; + uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ]; +#endif`,kx=`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; +#endif`,Vx=`#if NUM_CLIPPING_PLANES > 0 + vClipPosition = - mvPosition.xyz; +#endif`,Gx=`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) + diffuseColor *= vColor; +#endif`,Hx=`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) + varying vec4 vColor; +#endif`,Wx=`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) + varying vec4 vColor; +#endif`,Xx=`#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) + vColor = vec4( 1.0 ); +#endif +#ifdef USE_COLOR_ALPHA + vColor *= color; +#elif defined( USE_COLOR ) + vColor.rgb *= color; +#endif +#ifdef USE_INSTANCING_COLOR + vColor.rgb *= instanceColor.rgb; +#endif +#ifdef USE_BATCHING_COLOR + vColor *= getBatchingColor( getIndirectIndex( gl_DrawID ) ); +#endif`,qx=`#define PI 3.141592653589793 +#define PI2 6.283185307179586 +#define PI_HALF 1.5707963267948966 +#define RECIPROCAL_PI 0.3183098861837907 +#define RECIPROCAL_PI2 0.15915494309189535 +#define EPSILON 1e-6 +#ifndef saturate +#define saturate( a ) clamp( a, 0.0, 1.0 ) +#endif +#define whiteComplement( a ) ( 1.0 - saturate( a ) ) +float pow2( const in float x ) { return x*x; } +vec3 pow2( const in vec3 x ) { return x*x; } +float pow3( const in float x ) { return x*x*x; } +float pow4( const in float x ) { float x2 = x*x; return x2*x2; } +float max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); } +float average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); } +highp float rand( const in vec2 uv ) { + const highp float a = 12.9898, b = 78.233, c = 43758.5453; + highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI ); + return fract( sin( sn ) * c ); +} +#ifdef HIGH_PRECISION + float precisionSafeLength( vec3 v ) { return length( v ); } +#else + float precisionSafeLength( vec3 v ) { + float maxComponent = max3( abs( v ) ); + return length( v / maxComponent ) * maxComponent; + } +#endif +struct IncidentLight { + vec3 color; + vec3 direction; + bool visible; +}; +struct ReflectedLight { + vec3 directDiffuse; + vec3 directSpecular; + vec3 indirectDiffuse; + vec3 indirectSpecular; +}; +#ifdef USE_ALPHAHASH + varying vec3 vPosition; +#endif +vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); +} +#define inverseTransformDirection transformDirectionByInverseViewMatrix +vec3 transformNormalByInverseViewMatrix( in vec3 normal, in mat4 viewMatrix ) { + return normalize( ( vec4( normal, 0.0 ) * viewMatrix ).xyz ); +} +vec3 transformDirectionByInverseViewMatrix( in vec3 dir, in mat4 viewMatrix ) { + return normalize( ( vec4( dir, 0.0 ) * viewMatrix ).xyz ); +} +bool isPerspectiveMatrix( mat4 m ) { + return m[ 2 ][ 3 ] == - 1.0; +} +vec2 equirectUv( in vec3 dir ) { + float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5; + float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; + return vec2( u, v ); +} +vec3 BRDF_Lambert( const in vec3 diffuseColor ) { + return RECIPROCAL_PI * diffuseColor; +} +vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); +} +float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); +} // validated`,Yx=`#ifdef ENVMAP_TYPE_CUBE_UV + #define cubeUV_minMipLevel 4.0 + #define cubeUV_minTileSize 16.0 + float getFace( vec3 direction ) { + vec3 absDirection = abs( direction ); + float face = - 1.0; + if ( absDirection.x > absDirection.z ) { + if ( absDirection.x > absDirection.y ) + face = direction.x > 0.0 ? 0.0 : 3.0; + else + face = direction.y > 0.0 ? 1.0 : 4.0; + } else { + if ( absDirection.z > absDirection.y ) + face = direction.z > 0.0 ? 2.0 : 5.0; + else + face = direction.y > 0.0 ? 1.0 : 4.0; + } + return face; + } + vec2 getUV( vec3 direction, float face ) { + vec2 uv; + if ( face == 0.0 ) { + uv = vec2( direction.z, direction.y ) / abs( direction.x ); + } else if ( face == 1.0 ) { + uv = vec2( - direction.x, - direction.z ) / abs( direction.y ); + } else if ( face == 2.0 ) { + uv = vec2( - direction.x, direction.y ) / abs( direction.z ); + } else if ( face == 3.0 ) { + uv = vec2( - direction.z, direction.y ) / abs( direction.x ); + } else if ( face == 4.0 ) { + uv = vec2( - direction.x, direction.z ) / abs( direction.y ); + } else { + uv = vec2( direction.x, direction.y ) / abs( direction.z ); + } + return 0.5 * ( uv + 1.0 ); + } + vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) { + float face = getFace( direction ); + float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 ); + mipInt = max( mipInt, cubeUV_minMipLevel ); + float faceSize = exp2( mipInt ); + highp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0; + if ( face > 2.0 ) { + uv.y += faceSize; + face -= 3.0; + } + uv.x += face * faceSize; + uv.x += filterInt * 3.0 * cubeUV_minTileSize; + uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize ); + uv.x *= CUBEUV_TEXEL_WIDTH; + uv.y *= CUBEUV_TEXEL_HEIGHT; + #ifdef texture2DGradEXT + return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb; + #else + return texture2D( envMap, uv ).rgb; + #endif + } + #define cubeUV_r0 1.0 + #define cubeUV_m0 - 2.0 + #define cubeUV_r1 0.8 + #define cubeUV_m1 - 1.0 + #define cubeUV_r4 0.4 + #define cubeUV_m4 2.0 + #define cubeUV_r5 0.305 + #define cubeUV_m5 3.0 + #define cubeUV_r6 0.21 + #define cubeUV_m6 4.0 + float roughnessToMip( float roughness ) { + float mip = 0.0; + if ( roughness >= cubeUV_r1 ) { + mip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0; + } else if ( roughness >= cubeUV_r4 ) { + mip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1; + } else if ( roughness >= cubeUV_r5 ) { + mip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4; + } else if ( roughness >= cubeUV_r6 ) { + mip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5; + } else { + mip = - 2.0 * log2( 1.16 * roughness ); } + return mip; + } + vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) { + float mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); + float mipF = fract( mip ); + float mipInt = floor( mip ); + vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt ); + if ( mipF == 0.0 ) { + return vec4( color0, 1.0 ); + } else { + vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 ); + return vec4( mix( color0, color1, mipF ), 1.0 ); + } + } +#endif`,Zx=`vec3 transformedNormal = objectNormal; +#ifdef USE_TANGENT + vec3 transformedTangent = objectTangent; +#endif +#ifdef USE_BATCHING + mat3 bm = mat3( batchingMatrix ); + transformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) ); + transformedNormal = bm * transformedNormal; + #ifdef USE_TANGENT + transformedTangent = bm * transformedTangent; + #endif +#endif +#ifdef USE_INSTANCING + mat3 im = mat3( instanceMatrix ); + transformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) ); + transformedNormal = im * transformedNormal; + #ifdef USE_TANGENT + transformedTangent = im * transformedTangent; + #endif +#endif +transformedNormal = normalMatrix * transformedNormal; +#ifdef FLIP_SIDED + transformedNormal = - transformedNormal; +#endif +#ifdef USE_TANGENT + transformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz; +#endif`,Kx=`#ifdef USE_DISPLACEMENTMAP + uniform sampler2D displacementMap; + uniform float displacementScale; + uniform float displacementBias; +#endif`,Jx=`#ifdef USE_DISPLACEMENTMAP + transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias ); +#endif`,jx=`#ifdef USE_EMISSIVEMAP + vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv ); + #ifdef DECODE_VIDEO_TEXTURE_EMISSIVE + emissiveColor = sRGBTransferEOTF( emissiveColor ); + #endif + totalEmissiveRadiance *= emissiveColor.rgb; +#endif`,$x=`#ifdef USE_EMISSIVEMAP + uniform sampler2D emissiveMap; +#endif`,Qx="gl_FragColor = linearToOutputTexel( gl_FragColor );",ey=`vec4 LinearTransferOETF( in vec4 value ) { + return value; +} +vec4 sRGBTransferEOTF( in vec4 value ) { + return 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.a ); +} +vec4 sRGBTransferOETF( in vec4 value ) { + return 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.a ); +}`,ty=`#ifdef USE_ENVMAP + #ifdef ENV_WORLDPOS + vec3 cameraToFrag; + if ( isOrthographic ) { + cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); + } else { + cameraToFrag = normalize( vWorldPosition - cameraPosition ); + } + vec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix ); + #ifdef ENVMAP_MODE_REFLECTION + vec3 reflectVec = reflect( cameraToFrag, worldNormal ); + #else + vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio ); + #endif + #else + vec3 reflectVec = vReflect; + #endif + #ifdef ENVMAP_TYPE_CUBE + vec4 envColor = textureCube( envMap, envMapRotation * reflectVec ); + #ifdef ENVMAP_BLENDING_MULTIPLY + outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity ); + #elif defined( ENVMAP_BLENDING_MIX ) + outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity ); + #elif defined( ENVMAP_BLENDING_ADD ) + outgoingLight += envColor.xyz * specularStrength * reflectivity; + #endif + #endif +#endif`,ny=`#ifdef USE_ENVMAP + uniform float envMapIntensity; + uniform mat3 envMapRotation; + #ifdef ENVMAP_TYPE_CUBE + uniform samplerCube envMap; + #else + uniform sampler2D envMap; + #endif +#endif`,iy=`#ifdef USE_ENVMAP + uniform float reflectivity; + #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) + #define ENV_WORLDPOS + #endif + #ifdef ENV_WORLDPOS + varying vec3 vWorldPosition; + uniform float refractionRatio; + #else + varying vec3 vReflect; + #endif +#endif`,sy=`#ifdef USE_ENVMAP + #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) + #define ENV_WORLDPOS + #endif + #ifdef ENV_WORLDPOS + + varying vec3 vWorldPosition; + #else + varying vec3 vReflect; + uniform float refractionRatio; + #endif +#endif`,ry=`#ifdef USE_ENVMAP + #ifdef ENV_WORLDPOS + vWorldPosition = worldPosition.xyz; + #else + vec3 cameraToVertex; + if ( isOrthographic ) { + cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); + } else { + cameraToVertex = normalize( worldPosition.xyz - cameraPosition ); + } + vec3 worldNormal = transformNormalByInverseViewMatrix( transformedNormal, viewMatrix ); + #ifdef ENVMAP_MODE_REFLECTION + vReflect = reflect( cameraToVertex, worldNormal ); + #else + vReflect = refract( cameraToVertex, worldNormal, refractionRatio ); + #endif + #endif +#endif`,oy=`#ifdef USE_FOG + vFogDepth = - mvPosition.z; +#endif`,ay=`#ifdef USE_FOG + varying float vFogDepth; +#endif`,ly=`#ifdef USE_FOG + #ifdef FOG_EXP2 + float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth ); + #else + float fogFactor = smoothstep( fogNear, fogFar, vFogDepth ); + #endif + gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor ); +#endif`,cy=`#ifdef USE_FOG + uniform vec3 fogColor; + varying float vFogDepth; + #ifdef FOG_EXP2 + uniform float fogDensity; + #else + uniform float fogNear; + uniform float fogFar; + #endif +#endif`,hy=`#ifdef USE_GRADIENTMAP + uniform sampler2D gradientMap; +#endif +vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) { + float dotNL = dot( normal, lightDirection ); + vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 ); + #ifdef USE_GRADIENTMAP + return vec3( texture2D( gradientMap, coord ).r ); + #else + vec2 fw = fwidth( coord ) * 0.5; + return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) ); + #endif +}`,uy=`#ifdef USE_LIGHTMAP + uniform sampler2D lightMap; + uniform float lightMapIntensity; +#endif`,dy=`LambertMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.specularStrength = specularStrength;`,fy=`varying vec3 vViewPosition; +struct LambertMaterial { + vec3 diffuseColor; + float specularStrength; +}; +void RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_Lambert +#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,py=`uniform bool receiveShadow; +uniform vec3 ambientLightColor; +#if defined( USE_LIGHT_PROBES ) + uniform vec3 lightProbe[ 9 ]; +#endif +vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) { + float x = normal.x, y = normal.y, z = normal.z; + vec3 result = shCoefficients[ 0 ] * 0.886227; + result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y; + result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z; + result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x; + result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y; + result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z; + result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 ); + result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z; + result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y ); + return result; +} +vec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) { + vec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix ); + vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe ); + return irradiance; +} +vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) { + vec3 irradiance = ambientLightColor; + return irradiance; +} +float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) { + float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 ); + if ( cutoffDistance > 0.0 ) { + distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) ); + } + return distanceFalloff; +} +float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) { + return smoothstep( coneCosine, penumbraCosine, angleCosine ); +} +#if NUM_SUN_LIGHTS > 0 + struct SunLight { + vec3 direction; + vec3 color; + }; + uniform SunLight sunLights[ NUM_SUN_LIGHTS ]; + void getSunLightInfo( const in SunLight sunLight, out IncidentLight light ) { + light.color = sunLight.color; + light.direction = sunLight.direction; + light.visible = true; + } +#endif +#if NUM_DIR_LIGHTS > 0 + struct DirectionalLight { + vec3 direction; + vec3 color; + }; + uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ]; + void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) { + light.color = directionalLight.color; + light.direction = directionalLight.direction; + light.visible = true; + } +#endif +#if NUM_POINT_LIGHTS > 0 + struct PointLight { + vec3 position; + vec3 color; + float distance; + float decay; + }; + uniform PointLight pointLights[ NUM_POINT_LIGHTS ]; + void getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) { + vec3 lVector = pointLight.position - geometryPosition; + light.direction = normalize( lVector ); + float lightDistance = length( lVector ); + light.color = pointLight.color; + light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay ); + light.visible = ( light.color != vec3( 0.0 ) ); + } +#endif +#if NUM_SPOT_LIGHTS > 0 + struct SpotLight { + vec3 position; + vec3 direction; + vec3 color; + float distance; + float decay; + float coneCos; + float penumbraCos; + }; + uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ]; + void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) { + vec3 lVector = spotLight.position - geometryPosition; + light.direction = normalize( lVector ); + float angleCos = dot( light.direction, spotLight.direction ); + float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos ); + if ( spotAttenuation > 0.0 ) { + float lightDistance = length( lVector ); + light.color = spotLight.color * spotAttenuation; + light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay ); + light.visible = ( light.color != vec3( 0.0 ) ); + } else { + light.color = vec3( 0.0 ); + light.visible = false; + } + } +#endif +#if NUM_RECT_AREA_LIGHTS > 0 + struct RectAreaLight { + vec3 color; + vec3 position; + vec3 halfWidth; + vec3 halfHeight; + }; + uniform sampler2D ltc_1; uniform sampler2D ltc_2; + uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ]; +#endif +#if NUM_HEMI_LIGHTS > 0 + struct HemisphereLight { + vec3 direction; + vec3 skyColor; + vec3 groundColor; + }; + uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ]; + vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) { + float dotNL = dot( normal, hemiLight.direction ); + float hemiDiffuseWeight = 0.5 * dotNL + 0.5; + vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight ); + return irradiance; + } +#endif +#include `,my=`#ifdef USE_ENVMAP + vec3 getIBLIrradiance( const in vec3 normal ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 worldNormal = transformNormalByInverseViewMatrix( normal, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 ); + return PI * envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 reflectVec = reflect( - viewDir, normal ); + reflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) ); + reflectVec = transformDirectionByInverseViewMatrix( reflectVec, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness ); + return envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + #ifdef USE_RETROREFLECTION + vec3 getIBLRetroRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 retroVec = normalize( mix( viewDir, normal, pow4( roughness ) ) ); + retroVec = transformDirectionByInverseViewMatrix( retroVec, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * retroVec, roughness ); + return envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + #endif + #ifdef USE_ANISOTROPY + vec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 bentNormal = cross( bitangent, viewDir ); + bentNormal = normalize( cross( bentNormal, bitangent ) ); + bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ); + return getIBLRadiance( viewDir, bentNormal, roughness ); + #else + return vec3( 0.0 ); + #endif + } + #ifdef USE_RETROREFLECTION + vec3 getIBLAnisotropyRetroRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 bentNormal = cross( bitangent, viewDir ); + bentNormal = normalize( cross( bentNormal, bitangent ) ); + bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ); + return getIBLRetroRadiance( viewDir, bentNormal, roughness ); + #else + return vec3( 0.0 ); + #endif + } + #endif + #endif +#endif`,gy=`ToonMaterial material; +material.diffuseColor = diffuseColor.rgb;`,_y=`varying vec3 vViewPosition; +struct ToonMaterial { + vec3 diffuseColor; +}; +void RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { + vec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_Toon +#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,xy=`BlinnPhongMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.specularColor = specular; +material.specularShininess = shininess; +material.specularStrength = specularStrength;`,yy=`varying vec3 vViewPosition; +struct BlinnPhongMaterial { + vec3 diffuseColor; + vec3 specularColor; + float specularShininess; + float specularStrength; +}; +void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); + reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength; +} +void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_BlinnPhong +#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,vy=`PhysicalMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.diffuseContribution = diffuseColor.rgb * ( 1.0 - metalnessFactor ); +material.metalness = metalnessFactor; +vec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) ); +float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z ); +material.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness; +material.roughness = min( material.roughness, 1.0 ); +#ifdef IOR + material.ior = ior; + #ifdef USE_SPECULAR + float specularIntensityFactor = specularIntensity; + vec3 specularColorFactor = specularColor; + #ifdef USE_SPECULAR_COLORMAP + specularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb; + #endif + #ifdef USE_SPECULAR_INTENSITYMAP + specularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a; + #endif + material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor ); + #else + float specularIntensityFactor = 1.0; + vec3 specularColorFactor = vec3( 1.0 ); + material.specularF90 = 1.0; + #endif + material.specularColor = min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor; + material.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor ); +#else + material.specularColor = vec3( 0.04 ); + material.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor ); + material.specularF90 = 1.0; +#endif +#ifdef USE_CLEARCOAT + material.clearcoat = clearcoat; + material.clearcoatRoughness = clearcoatRoughness; + material.clearcoatF0 = vec3( 0.04 ); + material.clearcoatF90 = 1.0; + #ifdef USE_CLEARCOATMAP + material.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x; + #endif + #ifdef USE_CLEARCOAT_ROUGHNESSMAP + material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y; + #endif + material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 ); + material.clearcoatRoughness += geometryRoughness; + material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 ); +#endif +#ifdef USE_DISPERSION + material.dispersion = dispersion; +#endif +#ifdef USE_RETROREFLECTION + material.retroreflectivity = retroreflectivity; +#endif +#ifdef USE_IRIDESCENCE + material.iridescence = iridescence; + material.iridescenceIOR = iridescenceIOR; + #ifdef USE_IRIDESCENCEMAP + material.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r; + #endif + #ifdef USE_IRIDESCENCE_THICKNESSMAP + material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum; + #else + material.iridescenceThickness = iridescenceThicknessMaximum; + #endif +#endif +#ifdef USE_SHEEN + material.sheenColor = sheenColor; + #ifdef USE_SHEEN_COLORMAP + material.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb; + #endif + material.sheenRoughness = clamp( sheenRoughness, 0.0001, 1.0 ); + #ifdef USE_SHEEN_ROUGHNESSMAP + material.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a; + #endif +#endif +#ifdef USE_ANISOTROPY + #ifdef USE_ANISOTROPYMAP + mat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x ); + vec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb; + vec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b; + #else + vec2 anisotropyV = anisotropyVector; + #endif + material.anisotropy = length( anisotropyV ); + if( material.anisotropy == 0.0 ) { + anisotropyV = vec2( 1.0, 0.0 ); + } else { + anisotropyV /= material.anisotropy; + material.anisotropy = saturate( material.anisotropy ); + } + material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) ); + material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y; + material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y; +#endif`,My=`uniform sampler2D dfgLUT; +struct PhysicalMaterial { + vec3 diffuseColor; + vec3 diffuseContribution; + vec3 specularColor; + vec3 specularColorBlended; + float roughness; + float metalness; + float specularF90; + float dispersion; + vec2 dfg; + vec3 multiScatteringCompensation; + #ifdef USE_RETROREFLECTION + float retroreflectivity; + #endif + #ifdef USE_CLEARCOAT + float clearcoat; + float clearcoatRoughness; + vec3 clearcoatF0; + float clearcoatF90; + #endif + #ifdef USE_IRIDESCENCE + float iridescence; + float iridescenceIOR; + float iridescenceThickness; + vec3 iridescenceFresnel; + vec3 iridescenceF0Dielectric; + vec3 iridescenceF0Metallic; + #endif + #ifdef USE_SHEEN + vec3 sheenColor; + float sheenRoughness; + #endif + #ifdef IOR + float ior; + #endif + #ifdef USE_TRANSMISSION + float transmission; + float transmissionAlpha; + float thickness; + float attenuationDistance; + vec3 attenuationColor; + #endif + #ifdef USE_ANISOTROPY + float anisotropy; + float alphaT; + vec3 anisotropyT; + vec3 anisotropyB; + #endif +}; +vec3 clearcoatSpecularDirect = vec3( 0.0 ); +vec3 clearcoatSpecularIndirect = vec3( 0.0 ); +vec3 sheenSpecularDirect = vec3( 0.0 ); +vec3 sheenSpecularIndirect = vec3(0.0 ); +vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) { + float x = clamp( 1.0 - dotVH, 0.0, 1.0 ); + float x2 = x * x; + float x5 = clamp( x * x2 * x2, 0.0, 0.9999 ); + return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 ); +} +float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) { + float a2 = pow2( alpha ); + float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) ); + float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) ); + return 0.5 / max( gv + gl, EPSILON ); +} +float D_GGX( const in float alpha, const in float dotNH ) { + float a2 = pow2( alpha ); + float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; + return RECIPROCAL_PI * a2 / pow2( denom ); +} +#ifdef USE_ANISOTROPY + float V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) { + float gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) ); + float gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) ); + return 0.5 / max( gv + gl, EPSILON ); + } + float D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) { + float a2 = alphaT * alphaB; + highp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH ); + highp float v2 = dot( v, v ); + float w2 = a2 / v2; + return RECIPROCAL_PI * a2 * pow2 ( w2 ); + } +#endif +#ifdef USE_CLEARCOAT + vec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) { + vec3 f0 = material.clearcoatF0; + float f90 = material.clearcoatF90; + float roughness = material.clearcoatRoughness; + float alpha = pow2( roughness ); + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + vec3 F = F_Schlick( f0, f90, dotVH ); + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + float D = D_GGX( alpha, dotNH ); + return F * ( V * D ); + } +#endif +vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) { + vec3 f0 = material.specularColorBlended; + float f90 = material.specularF90; + float roughness = material.roughness; + float alpha = pow2( roughness ); + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + vec3 F = F_Schlick( f0, f90, dotVH ); + #ifdef USE_IRIDESCENCE + F = mix( F, material.iridescenceFresnel, material.iridescence ); + #endif + #ifdef USE_ANISOTROPY + float dotTL = dot( material.anisotropyT, lightDir ); + float dotTV = dot( material.anisotropyT, viewDir ); + float dotTH = dot( material.anisotropyT, halfDir ); + float dotBL = dot( material.anisotropyB, lightDir ); + float dotBV = dot( material.anisotropyB, viewDir ); + float dotBH = dot( material.anisotropyB, halfDir ); + float V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL ); + float D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH ); + #else + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + float D = D_GGX( alpha, dotNH ); + #endif + return F * ( V * D ); +} +vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) { + const float LUT_SIZE = 64.0; + const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const float LUT_BIAS = 0.5 / LUT_SIZE; + float dotNV = saturate( dot( N, V ) ); + vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) ); + uv = uv * LUT_SCALE + LUT_BIAS; + return uv; +} +float LTC_ClippedSphereFormFactor( const in vec3 f ) { + float l = length( f ); + return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 ); +} +vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) { + float x = dot( v1, v2 ); + float y = abs( x ); + float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y; + float b = 3.4175940 + ( 4.1616724 + y ) * y; + float v = a / b; + float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v; + return cross( v1, v2 ) * theta_sintheta; +} +vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) { + vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ]; + vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ]; + vec3 lightNormal = cross( v1, v2 ); + if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 ); + vec3 T1, T2; + T1 = normalize( V - N * dot( V, N ) ); + T2 = - cross( N, T1 ); + mat3 mat = mInv * transpose( mat3( T1, T2, N ) ); + vec3 coords[ 4 ]; + coords[ 0 ] = mat * ( rectCoords[ 0 ] - P ); + coords[ 1 ] = mat * ( rectCoords[ 1 ] - P ); + coords[ 2 ] = mat * ( rectCoords[ 2 ] - P ); + coords[ 3 ] = mat * ( rectCoords[ 3 ] - P ); + coords[ 0 ] = normalize( coords[ 0 ] ); + coords[ 1 ] = normalize( coords[ 1 ] ); + coords[ 2 ] = normalize( coords[ 2 ] ); + coords[ 3 ] = normalize( coords[ 3 ] ); + vec3 vectorFormFactor = vec3( 0.0 ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] ); + float result = LTC_ClippedSphereFormFactor( vectorFormFactor ); + return vec3( result ); +} +#if defined( USE_SHEEN ) +float D_Charlie( float roughness, float dotNH ) { + float alpha = pow2( roughness ); + float invAlpha = 1.0 / alpha; + float cos2h = dotNH * dotNH; + float sin2h = max( 1.0 - cos2h, 0.0078125 ); + return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); +} +float V_Neubelt( float dotNV, float dotNL ) { + return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); +} +vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) { + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float D = D_Charlie( sheenRoughness, dotNH ); + float V = V_Neubelt( dotNV, dotNL ); + return sheenColor * ( D * V ); +} +#endif +float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { + float dotNV = saturate( dot( normal, viewDir ) ); + float r2 = roughness * roughness; + float rInv = 1.0 / ( roughness + 0.1 ); + float a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv; + float b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv; + float DG = exp( a * dotNV + b ); + return saturate( DG ); +} +vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) { + float dotNV = saturate( dot( normal, viewDir ) ); + vec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg; + return specularColor * fab.x + specularF90 * fab.y; +} +#ifdef USE_IRIDESCENCE +void computeMultiscatteringIridescence( const in vec2 fab, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, inout vec3 singleScatter, inout vec3 multiScatter ) { +#else +void computeMultiscattering( const in vec2 fab, const in vec3 specularColor, const in float specularF90, inout vec3 singleScatter, inout vec3 multiScatter ) { +#endif + #ifdef USE_IRIDESCENCE + vec3 Fr = mix( specularColor, iridescenceF0, iridescence ); + #else + vec3 Fr = specularColor; + #endif + vec3 FssEss = Fr * fab.x + specularF90 * fab.y; + float Ess = fab.x + fab.y; + float Ems = 1.0 - Ess; + vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg ); + singleScatter += FssEss; + multiScatter += Fms * Ems; +} +#if NUM_RECT_AREA_LIGHTS > 0 + void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + vec3 normal = geometryNormal; + vec3 viewDir = geometryViewDir; + vec3 position = geometryPosition; + vec3 lightPos = rectAreaLight.position; + vec3 halfWidth = rectAreaLight.halfWidth; + vec3 halfHeight = rectAreaLight.halfHeight; + vec3 lightColor = rectAreaLight.color; + float roughness = material.roughness; + vec3 rectCoords[ 4 ]; + rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight; + rectCoords[ 2 ] = lightPos - halfWidth + halfHeight; + rectCoords[ 3 ] = lightPos + halfWidth + halfHeight; + vec2 uv = LTC_Uv( normal, viewDir, roughness ); + vec4 t1 = texture2D( ltc_1, uv ); + vec4 t2 = texture2D( ltc_2, uv ); + mat3 mInv = mat3( + vec3( t1.x, 0, t1.y ), + vec3( 0, 1, 0 ), + vec3( t1.z, 0, t1.w ) + ); + vec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y ); + reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords ); + reflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords ); + #ifdef USE_CLEARCOAT + vec3 Ncc = geometryClearcoatNormal; + vec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness ); + vec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat ); + vec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat ); + mat3 mInvClearcoat = mat3( + vec3( t1Clearcoat.x, 0, t1Clearcoat.y ), + vec3( 0, 1, 0 ), + vec3( t1Clearcoat.z, 0, t1Clearcoat.w ) + ); + vec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y; + clearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords ); + #endif + } +#endif +void RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + #ifdef USE_CLEARCOAT + float dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) ); + vec3 ccIrradiance = dotNLcc * directLight.color; + clearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material ); + #endif + #ifdef USE_SHEEN + + sheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness ); + + float sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ); + float sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness ); + + float sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL ); + + irradiance *= sheenEnergyComp; + + #endif + vec3 specularBRDF = BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material ); + #ifdef USE_RETROREFLECTION + vec3 retroViewDir = reflect( - geometryViewDir, geometryNormal ); + vec3 retroSpecularBRDF = BRDF_GGX( directLight.direction, retroViewDir, geometryNormal, material ); + specularBRDF = mix( specularBRDF, retroSpecularBRDF, saturate( material.retroreflectivity ) ); + #endif + reflectedLight.directSpecular += irradiance * specularBRDF * material.multiScatteringCompensation; + vec3 halfDir = normalize( directLight.direction + geometryViewDir ); + float dotVH = saturate( dot( geometryViewDir, halfDir ) ); + vec3 F = F_Schlick( material.specularColor, material.specularF90, dotVH ); + #ifdef USE_RETROREFLECTION + vec3 retroHalfDir = normalize( directLight.direction + retroViewDir ); + float dotRetroVH = saturate( dot( retroViewDir, retroHalfDir ) ); + vec3 retroF = F_Schlick( material.specularColor, material.specularF90, dotRetroVH ); + F = mix( F, retroF, saturate( material.retroreflectivity ) ); + #endif + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseContribution ) * ( 1.0 - F ); +} +void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + vec3 singleScattering = vec3( 0.0 ); + vec3 multiScattering = vec3( 0.0 ); + #ifdef USE_IRIDESCENCE + computeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScattering, multiScattering ); + #else + computeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScattering, multiScattering ); + #endif + vec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution ) * ( 1.0 - singleScattering - multiScattering ); + #ifdef USE_SHEEN + float sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ); + sheenSpecularIndirect += irradiance * material.sheenColor * sheenAlbedo * RECIPROCAL_PI; + float sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo; + diffuse *= sheenEnergyComp; + #endif + reflectedLight.indirectDiffuse += diffuse; +} +void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) { + #ifdef USE_CLEARCOAT + clearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness ); + #endif + #ifdef USE_SHEEN + sheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI; + #endif + vec3 singleScatteringDielectric = vec3( 0.0 ); + vec3 multiScatteringDielectric = vec3( 0.0 ); + vec3 singleScatteringMetallic = vec3( 0.0 ); + vec3 multiScatteringMetallic = vec3( 0.0 ); + #ifdef USE_IRIDESCENCE + computeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScatteringDielectric, multiScatteringDielectric ); + computeMultiscatteringIridescence( material.dfg, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceF0Metallic, singleScatteringMetallic, multiScatteringMetallic ); + #else + computeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScatteringDielectric, multiScatteringDielectric ); + computeMultiscattering( material.dfg, material.diffuseColor, material.specularF90, singleScatteringMetallic, multiScatteringMetallic ); + #endif + vec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness ); + vec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness ); + vec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric; + vec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric ); + vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI; + vec3 indirectSpecular = radiance * singleScattering; + indirectSpecular += multiScattering * cosineWeightedIrradiance; + vec3 indirectDiffuse = diffuse * cosineWeightedIrradiance; + #ifdef USE_SHEEN + float sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ); + float sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo; + indirectSpecular *= sheenEnergyComp; + indirectDiffuse *= sheenEnergyComp; + #endif + reflectedLight.indirectSpecular += indirectSpecular; + reflectedLight.indirectDiffuse += indirectDiffuse; +} +#define RE_Direct RE_Direct_Physical +#define RE_Direct_RectArea RE_Direct_RectArea_Physical +#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical +#define RE_IndirectSpecular RE_IndirectSpecular_Physical +float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) { + return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); +}`,Sy=` +vec3 geometryPosition = - vViewPosition; +vec3 geometryNormal = normal; +vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition ); +vec3 geometryClearcoatNormal = vec3( 0.0 ); +#ifdef USE_CLEARCOAT + geometryClearcoatNormal = clearcoatNormal; +#endif +#ifdef USE_IRIDESCENCE + float dotNVi = saturate( dot( normal, geometryViewDir ) ); + if ( material.iridescenceThickness == 0.0 ) { + material.iridescence = 0.0; + } else { + material.iridescence = saturate( material.iridescence ); + } + if ( material.iridescence > 0.0 ) { + vec3 iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor ); + vec3 iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor ); + material.iridescenceFresnel = mix( iridescenceFresnelDielectric, iridescenceFresnelMetallic, material.metalness ); + material.iridescenceF0Dielectric = Schlick_to_F0( iridescenceFresnelDielectric, 1.0, dotNVi ); + material.iridescenceF0Metallic = Schlick_to_F0( iridescenceFresnelMetallic, 1.0, dotNVi ); + } +#endif +#ifdef STANDARD + float dotNVms = saturate( dot( geometryNormal, geometryViewDir ) ); + material.dfg = texture2D( dfgLUT, vec2( material.roughness, dotNVms ) ).rg; + #if ( NUM_SUN_LIGHTS > 0 || NUM_DIR_LIGHTS > 0 || NUM_POINT_LIGHTS > 0 || NUM_SPOT_LIGHTS > 0 ) + float EssMs = material.dfg.x + material.dfg.y; + material.multiScatteringCompensation = 1.0 + material.specularColorBlended * ( 1.0 / EssMs - 1.0 ); + #endif +#endif +IncidentLight directLight; +#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct ) + PointLight pointLight; + #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0 + PointLightShadow pointLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) { + pointLight = pointLights[ i ]; + getPointLightInfo( pointLight, geometryPosition, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) ) + pointLightShadow = pointLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct ) + SpotLight spotLight; + vec4 spotColor; + vec3 spotLightCoord; + bool inSpotLightMap; + #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) { + spotLight = spotLights[ i ]; + getSpotLightInfo( spotLight, geometryPosition, directLight ); + #if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) + #define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX + #elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + #define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS + #else + #define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) + #endif + #if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS ) + spotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w; + inSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) ); + spotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy ); + directLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color; + #endif + #undef SPOT_LIGHT_MAP_INDEX + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + spotLightShadow = spotLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_SUN_LIGHTS > 0 ) && defined( RE_Direct ) + SunLight sunLight; + #if defined( USE_SHADOWMAP ) && NUM_SUN_LIGHT_SHADOWS > 0 + SunLightShadow sunLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SUN_LIGHTS; i ++ ) { + sunLight = sunLights[ i ]; + getSunLightInfo( sunLight, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SUN_LIGHT_SHADOWS ) + sunLightShadow = sunLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getSunShadow( sunShadowMap[ i ], sunLightShadow, UNROLLED_LOOP_INDEX ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct ) + DirectionalLight directionalLight; + #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { + directionalLight = directionalLights[ i ]; + getDirectionalLightInfo( directionalLight, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) + directionalLightShadow = directionalLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea ) + RectAreaLight rectAreaLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) { + rectAreaLight = rectAreaLights[ i ]; + RE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if defined( RE_IndirectDiffuse ) + vec3 iblIrradiance = vec3( 0.0 ); + vec3 irradiance = getAmbientLightIrradiance( ambientLightColor ); + #if defined( USE_LIGHT_PROBES ) + irradiance += getLightProbeIrradiance( lightProbe, geometryNormal ); + #endif + #if ( NUM_HEMI_LIGHTS > 0 ) + #pragma unroll_loop_start + for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) { + irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal ); + } + #pragma unroll_loop_end + #endif + #ifdef USE_LIGHT_PROBES_GRID + vec3 probeWorldPos = ( ( vec4( geometryPosition, 1.0 ) - viewMatrix[ 3 ] ) * viewMatrix ).xyz; + vec3 probeWorldNormal = transformNormalByInverseViewMatrix( geometryNormal, viewMatrix ); + irradiance += getLightProbeGridIrradiance( probeWorldPos, probeWorldNormal ); + #endif +#endif +#if defined( RE_IndirectSpecular ) + vec3 radiance = vec3( 0.0 ); + vec3 clearcoatRadiance = vec3( 0.0 ); +#endif`,by=`#if defined( RE_IndirectDiffuse ) + #ifdef USE_LIGHTMAP + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); + vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; + irradiance += lightMapIrradiance; + #endif + #if defined( USE_ENVMAP ) && defined( ENVMAP_TYPE_CUBE_UV ) + #if defined( STANDARD ) || defined( LAMBERT ) || defined( PHONG ) + iblIrradiance += getIBLIrradiance( geometryNormal ); + #endif + #endif +#endif +#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular ) + #ifdef USE_ANISOTROPY + vec3 iblRadiance = getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy ); + #else + vec3 iblRadiance = getIBLRadiance( geometryViewDir, geometryNormal, material.roughness ); + #endif + #ifdef USE_RETROREFLECTION + #ifdef USE_ANISOTROPY + vec3 retroIBLRadiance = getIBLAnisotropyRetroRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy ); + #else + vec3 retroIBLRadiance = getIBLRetroRadiance( geometryViewDir, geometryNormal, material.roughness ); + #endif + iblRadiance = mix( iblRadiance, retroIBLRadiance, saturate( material.retroreflectivity ) ); + #endif + radiance += iblRadiance; + #ifdef USE_CLEARCOAT + clearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness ); + #endif +#endif`,Ty=`#if defined( RE_IndirectDiffuse ) + #if defined( LAMBERT ) || defined( PHONG ) + irradiance += iblIrradiance; + #endif + RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); +#endif +#if defined( RE_IndirectSpecular ) + RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); +#endif`,Ay=`#ifdef USE_LIGHT_PROBES_GRID +uniform highp sampler3D probesSH; +uniform vec3 probesMin; +uniform vec3 probesMax; +uniform vec3 probesResolution; +vec3 getLightProbeGridIrradiance( vec3 worldPos, vec3 worldNormal ) { + vec3 res = probesResolution; + vec3 gridRange = probesMax - probesMin; + vec3 resMinusOne = res - 1.0; + vec3 probeSpacing = gridRange / resMinusOne; + vec3 samplePos = worldPos + worldNormal * probeSpacing * 0.5; + vec3 uvw = clamp( ( samplePos - probesMin ) / gridRange, 0.0, 1.0 ); + uvw = uvw * resMinusOne / res + 0.5 / res; + float nz = res.z; + float paddedSlices = nz + 2.0; + float atlasDepth = 7.0 * paddedSlices; + float uvZBase = uvw.z * nz + 1.0; + vec4 s0 = texture( probesSH, vec3( uvw.xy, ( uvZBase ) / atlasDepth ) ); + vec4 s1 = texture( probesSH, vec3( uvw.xy, ( uvZBase + paddedSlices ) / atlasDepth ) ); + vec4 s2 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) ); + vec4 s3 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) ); + vec4 s4 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) ); + vec4 s5 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) ); + vec4 s6 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) ); + vec3 c0 = s0.xyz; + vec3 c1 = vec3( s0.w, s1.xy ); + vec3 c2 = vec3( s1.zw, s2.x ); + vec3 c3 = s2.yzw; + vec3 c4 = s3.xyz; + vec3 c5 = vec3( s3.w, s4.xy ); + vec3 c6 = vec3( s4.zw, s5.x ); + vec3 c7 = s5.yzw; + vec3 c8 = s6.xyz; + float x = worldNormal.x, y = worldNormal.y, z = worldNormal.z; + vec3 result = c0 * 0.886227; + result += c1 * 2.0 * 0.511664 * y; + result += c2 * 2.0 * 0.511664 * z; + result += c3 * 2.0 * 0.511664 * x; + result += c4 * 2.0 * 0.429043 * x * y; + result += c5 * 2.0 * 0.429043 * y * z; + result += c6 * ( 0.743125 * z * z - 0.247708 ); + result += c7 * 2.0 * 0.429043 * x * z; + result += c8 * 0.429043 * ( x * x - y * y ); + return max( result, vec3( 0.0 ) ); +} +#endif`,Ey=`#if defined( USE_LOGARITHMIC_DEPTH_BUFFER ) + gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5; +#endif`,wy=`#if defined( USE_LOGARITHMIC_DEPTH_BUFFER ) + uniform float logDepthBufFC; + varying float vFragDepth; + varying float vIsPerspective; +#endif`,Ry=`#ifdef USE_LOGARITHMIC_DEPTH_BUFFER + varying float vFragDepth; + varying float vIsPerspective; +#endif`,Cy=`#ifdef USE_LOGARITHMIC_DEPTH_BUFFER + vFragDepth = 1.0 + gl_Position.w; + vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) ); +#endif`,Iy=`#ifdef USE_MAP + vec4 sampledDiffuseColor = texture2D( map, vMapUv ); + #ifdef DECODE_VIDEO_TEXTURE + sampledDiffuseColor = sRGBTransferEOTF( sampledDiffuseColor ); + #endif + diffuseColor *= sampledDiffuseColor; +#endif`,Py=`#ifdef USE_MAP + uniform sampler2D map; +#endif`,Ly=`#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + #if defined( USE_POINTS_UV ) + vec2 uv = vUv; + #else + vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; + #endif +#endif +#ifdef USE_MAP + diffuseColor *= texture2D( map, uv ); +#endif +#ifdef USE_ALPHAMAP + diffuseColor.a *= texture2D( alphaMap, uv ).g; +#endif`,Ny=`#if defined( USE_POINTS_UV ) + varying vec2 vUv; +#else + #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + uniform mat3 uvTransform; + #endif +#endif +#ifdef USE_MAP + uniform sampler2D map; +#endif +#ifdef USE_ALPHAMAP + uniform sampler2D alphaMap; +#endif`,Dy=`float metalnessFactor = metalness; +#ifdef USE_METALNESSMAP + vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv ); + metalnessFactor *= texelMetalness.b; +#endif`,Uy=`#ifdef USE_METALNESSMAP + uniform sampler2D metalnessMap; +#endif`,Fy=`#ifdef USE_INSTANCING_MORPH + float morphTargetInfluences[ MORPHTARGETS_COUNT ]; + float morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + morphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r; + } +#endif`,Oy=`#if defined( USE_MORPHCOLORS ) + vColor *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + #if defined( USE_COLOR_ALPHA ) + if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ]; + #elif defined( USE_COLOR ) + if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ]; + #endif + } +#endif`,By=`#ifdef USE_MORPHNORMALS + objectNormal *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ]; + } +#endif`,zy=`#ifdef USE_MORPHTARGETS + #ifndef USE_INSTANCING_MORPH + uniform float morphTargetBaseInfluence; + uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ]; + #endif + uniform sampler2DArray morphTargetsTexture; + uniform ivec2 morphTargetsTextureSize; + vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) { + int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset; + int y = texelIndex / morphTargetsTextureSize.x; + int x = texelIndex - y * morphTargetsTextureSize.x; + ivec3 morphUV = ivec3( x, y, morphTargetIndex ); + return texelFetch( morphTargetsTexture, morphUV, 0 ); + } +#endif`,ky=`#ifdef USE_MORPHTARGETS + transformed *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ]; + } +#endif`,Vy=`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; +#ifdef FLAT_SHADED + vec3 fdx = dFdx( vViewPosition ); + vec3 fdy = dFdy( vViewPosition ); + vec3 normal = normalize( cross( fdx, fdy ) ); +#else + vec3 normal = normalize( vNormal ); + #ifdef DOUBLE_SIDED + normal *= faceDirection; + #endif +#endif +#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) + #ifdef USE_TANGENT + mat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + #else + mat3 tbn = getTangentFrame( - vViewPosition, normal, + #if defined( USE_NORMALMAP ) + vNormalMapUv + #elif defined( USE_CLEARCOAT_NORMALMAP ) + vClearcoatNormalMapUv + #else + vUv + #endif + ); + #endif + #ifdef DOUBLE_SIDED + tbn[0] *= faceDirection; + tbn[1] *= faceDirection; + #endif +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + #ifdef USE_TANGENT + mat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + #else + mat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv ); + #endif + #ifdef DOUBLE_SIDED + tbn2[0] *= faceDirection; + tbn2[1] *= faceDirection; + #endif +#endif +vec3 nonPerturbedNormal = normal;`,Gy=`#ifdef USE_NORMALMAP_OBJECTSPACE + normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; + #ifdef FLIP_SIDED + normal = - normal; + #endif + #ifdef DOUBLE_SIDED + normal = normal * faceDirection; + #endif + normal = normalize( normalMatrix * normal ); +#elif defined( USE_NORMALMAP_TANGENTSPACE ) + vec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; + #if defined( USE_PACKED_NORMALMAP ) + mapN = vec3( mapN.xy, sqrt( saturate( 1.0 - dot( mapN.xy, mapN.xy ) ) ) ); + #endif + mapN.xy *= normalScale; + normal = normalize( tbn * mapN ); +#elif defined( USE_BUMPMAP ) + normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection ); +#endif`,Hy=`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,Wy=`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,Xy=`#ifndef FLAT_SHADED + vNormal = normalize( transformedNormal ); + #ifdef USE_TANGENT + vTangent = normalize( transformedTangent ); + vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w ); + #ifdef FLIP_SIDED + vBitangent = - vBitangent; + #endif + #endif +#endif`,qy=`#ifdef USE_NORMALMAP + uniform sampler2D normalMap; + uniform vec2 normalScale; +#endif +#ifdef USE_NORMALMAP_OBJECTSPACE + uniform mat3 normalMatrix; +#endif +#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) ) + mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) { + vec3 q0 = dFdx( eye_pos.xyz ); + vec3 q1 = dFdy( eye_pos.xyz ); + vec2 st0 = dFdx( uv.st ); + vec2 st1 = dFdy( uv.st ); + vec3 N = surf_norm; + vec3 q1perp = cross( q1, N ); + vec3 q0perp = cross( N, q0 ); + vec3 T = q1perp * st0.x + q0perp * st1.x; + vec3 B = q1perp * st0.y + q0perp * st1.y; + float det = max( dot( T, T ), dot( B, B ) ); + float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det ); + return mat3( T * scale, B * scale, N ); + } +#endif`,Yy=`#ifdef USE_CLEARCOAT + vec3 clearcoatNormal = nonPerturbedNormal; +#endif`,Zy=`#ifdef USE_CLEARCOAT_NORMALMAP + vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0; + clearcoatMapN.xy *= clearcoatNormalScale; + clearcoatNormal = normalize( tbn2 * clearcoatMapN ); +#endif`,Ky=`#ifdef USE_CLEARCOATMAP + uniform sampler2D clearcoatMap; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + uniform sampler2D clearcoatNormalMap; + uniform vec2 clearcoatNormalScale; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + uniform sampler2D clearcoatRoughnessMap; +#endif`,Jy=`#ifdef USE_IRIDESCENCEMAP + uniform sampler2D iridescenceMap; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + uniform sampler2D iridescenceThicknessMap; +#endif`,jy=`#ifdef OPAQUE +diffuseColor.a = 1.0; +#endif +#ifdef USE_TRANSMISSION +diffuseColor.a *= material.transmissionAlpha; +#endif +gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,$y=`vec3 packNormalToRGB( const in vec3 normal ) { + return normalize( normal ) * 0.5 + 0.5; +} +vec3 unpackRGBToNormal( const in vec3 rgb ) { + return 2.0 * rgb.xyz - 1.0; +} +const float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.; +const float Inv255 = 1. / 255.; +const vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 ); +const vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g ); +const vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b ); +const vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a ); +vec4 packDepthToRGBA( const in float v ) { + if( v <= 0.0 ) + return vec4( 0., 0., 0., 0. ); + if( v >= 1.0 ) + return vec4( 1., 1., 1., 1. ); + float vuf; + float af = modf( v * PackFactors.a, vuf ); + float bf = modf( vuf * ShiftRight8, vuf ); + float gf = modf( vuf * ShiftRight8, vuf ); + return vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af ); +} +vec3 packDepthToRGB( const in float v ) { + if( v <= 0.0 ) + return vec3( 0., 0., 0. ); + if( v >= 1.0 ) + return vec3( 1., 1., 1. ); + float vuf; + float bf = modf( v * PackFactors.b, vuf ); + float gf = modf( vuf * ShiftRight8, vuf ); + return vec3( vuf * Inv255, gf * PackUpscale, bf ); +} +vec2 packDepthToRG( const in float v ) { + if( v <= 0.0 ) + return vec2( 0., 0. ); + if( v >= 1.0 ) + return vec2( 1., 1. ); + float vuf; + float gf = modf( v * 256., vuf ); + return vec2( vuf * Inv255, gf ); +} +float unpackRGBAToDepth( const in vec4 v ) { + return dot( v, UnpackFactors4 ); +} +float unpackRGBToDepth( const in vec3 v ) { + return dot( v, UnpackFactors3 ); +} +float unpackRGToDepth( const in vec2 v ) { + return v.r * UnpackFactors2.r + v.g * UnpackFactors2.g; +} +vec4 pack2HalfToRGBA( const in vec2 v ) { + vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) ); + return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w ); +} +vec2 unpackRGBATo2Half( const in vec4 v ) { + return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) ); +} +float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) { + return ( viewZ + near ) / ( near - far ); +} +float orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) { + #ifdef USE_REVERSED_DEPTH_BUFFER + + return depth * ( far - near ) - far; + #else + return depth * ( near - far ) - near; + #endif +} +float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) { + return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ ); +} +float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) { + + #ifdef USE_REVERSED_DEPTH_BUFFER + return ( near * far ) / ( ( near - far ) * depth - near ); + #else + return ( near * far ) / ( ( far - near ) * depth - far ); + #endif +}`,Qy=`#ifdef PREMULTIPLIED_ALPHA + gl_FragColor.rgb *= gl_FragColor.a; +#endif`,ev=`vec4 mvPosition = vec4( transformed, 1.0 ); +#ifdef USE_BATCHING + mvPosition = batchingMatrix * mvPosition; +#endif +#ifdef USE_INSTANCING + mvPosition = instanceMatrix * mvPosition; +#endif +mvPosition = modelViewMatrix * mvPosition; +gl_Position = projectionMatrix * mvPosition;`,tv=`#ifdef DITHERING + gl_FragColor.rgb = dithering( gl_FragColor.rgb ); +#endif`,nv=`#ifdef DITHERING + vec3 dithering( vec3 color ) { + float grid_position = rand( gl_FragCoord.xy ); + vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 ); + dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position ); + return color + dither_shift_RGB; + } +#endif`,iv=`float roughnessFactor = roughness; +#ifdef USE_ROUGHNESSMAP + vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv ); + roughnessFactor *= texelRoughness.g; +#endif`,sv=`#ifdef USE_ROUGHNESSMAP + uniform sampler2D roughnessMap; +#endif`,rv=`#if NUM_SPOT_LIGHT_COORDS > 0 + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; +#endif +#if NUM_SPOT_LIGHT_MAPS > 0 + uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ]; +#endif +#ifdef USE_SHADOWMAP + #if NUM_SUN_LIGHT_SHADOWS > 0 + #define SUN_LIGHT_CASCADES 2 + #if defined( SHADOWMAP_TYPE_PCF ) + uniform sampler2DShadow sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ]; + #else + uniform sampler2D sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ]; + #endif + uniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * SUN_LIGHT_CASCADES ]; + uniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * SUN_LIGHT_CASCADES ]; + varying vec4 vSunShadowWorldPosition; + varying vec3 vSunShadowWorldNormal; + struct SunLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SunLightShadow sunLightShadows[ NUM_SUN_LIGHT_SHADOWS ]; + #endif + #if NUM_DIR_LIGHT_SHADOWS > 0 + #if defined( SHADOWMAP_TYPE_PCF ) + uniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ]; + #else + uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; + struct DirectionalLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + #if defined( SHADOWMAP_TYPE_PCF ) + uniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ]; + #else + uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + struct SpotLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + #if defined( SHADOWMAP_TYPE_PCF ) + uniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ]; + #elif defined( SHADOWMAP_TYPE_BASIC ) + uniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ]; + #endif + varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; + struct PointLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + float shadowCameraNear; + float shadowCameraFar; + }; + uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; + #endif + #if defined( SHADOWMAP_TYPE_PCF ) + float interleavedGradientNoise( vec2 position ) { + return fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ); + } + vec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) { + const float goldenAngle = 2.399963229728653; + float r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) ); + float theta = float( sampleIndex ) * goldenAngle + phi; + return vec2( cos( theta ), sin( theta ) ) * r; + } + #endif + #if defined( SHADOWMAP_TYPE_PCF ) + float getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) { + float shadow = 1.0; + shadowCoord.xyz /= shadowCoord.w; + shadowCoord.z += shadowBias; + bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0; + bool frustumTest = inFrustum && shadowCoord.z <= 1.0; + if ( frustumTest ) { + vec2 texelSize = vec2( 1.0 ) / shadowMapSize; + float radius = shadowRadius * texelSize.x; + float phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2; + shadow = ( + texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) + + texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) + + texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) + + texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) + + texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) ) + ) * 0.2; + } + return mix( 1.0, shadow, shadowIntensity ); + } + #elif defined( SHADOWMAP_TYPE_VSM ) + float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) { + float shadow = 1.0; + shadowCoord.xyz /= shadowCoord.w; + #ifdef USE_REVERSED_DEPTH_BUFFER + shadowCoord.z -= shadowBias; + #else + shadowCoord.z += shadowBias; + #endif + bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0; + bool frustumTest = inFrustum && shadowCoord.z <= 1.0; + if ( frustumTest ) { + vec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg; + float mean = distribution.x; + float variance = distribution.y * distribution.y; + #ifdef USE_REVERSED_DEPTH_BUFFER + float hard_shadow = step( mean, shadowCoord.z ); + #else + float hard_shadow = step( shadowCoord.z, mean ); + #endif + + if ( hard_shadow == 1.0 ) { + shadow = 1.0; + } else { + variance = max( variance, 0.0000001 ); + float d = shadowCoord.z - mean; + float p_max = variance / ( variance + d * d ); + p_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 ); + shadow = max( hard_shadow, p_max ); + } + } + return mix( 1.0, shadow, shadowIntensity ); + } + #else + float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) { + float shadow = 1.0; + shadowCoord.xyz /= shadowCoord.w; + #ifdef USE_REVERSED_DEPTH_BUFFER + shadowCoord.z -= shadowBias; + #else + shadowCoord.z += shadowBias; + #endif + bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0; + bool frustumTest = inFrustum && shadowCoord.z <= 1.0; + if ( frustumTest ) { + float depth = texture2D( shadowMap, shadowCoord.xy ).r; + #ifdef USE_REVERSED_DEPTH_BUFFER + shadow = step( depth, shadowCoord.z ); + #else + shadow = step( shadowCoord.z, depth ); + #endif + } + return mix( 1.0, shadow, shadowIntensity ); + } + #endif + #if NUM_SUN_LIGHT_SHADOWS > 0 + float getSunShadow( + #if defined( SHADOWMAP_TYPE_PCF ) + sampler2DShadow shadowMap, + #else + sampler2D shadowMap, + #endif + SunLightShadow sunLightShadow, + int shadowIndex + ) { + vec4 shadowWorldPosition = vec4( vSunShadowWorldPosition.xyz + vSunShadowWorldNormal * sunLightShadow.shadowNormalBias, 1.0 ); + float viewDepth = vSunShadowWorldPosition.w; + int cascadeOffset = shadowIndex * SUN_LIGHT_CASCADES; + float shadow = 1.0; + for ( int i = SUN_LIGHT_CASCADES - 1; i >= 0; i -- ) { + vec4 cascade = sunShadowCascade[ cascadeOffset + i ]; + if ( viewDepth >= cascade.x && viewDepth < cascade.y ) { + float cascadeShadow = getShadow( + shadowMap, + sunLightShadow.shadowMapSize, + sunLightShadow.shadowIntensity, + sunLightShadow.shadowBias, + sunLightShadow.shadowRadius, + sunShadowMatrix[ cascadeOffset + i ] * shadowWorldPosition + ); + shadow = mix( cascadeShadow, shadow, smoothstep( cascade.z, cascade.y, viewDepth ) ); + } + } + return shadow; + } + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + #if defined( SHADOWMAP_TYPE_PCF ) + float getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) { + float shadow = 1.0; + vec3 lightToPosition = shadowCoord.xyz; + vec3 bd3D = normalize( lightToPosition ); + vec3 absVec = abs( lightToPosition ); + float viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z ); + if ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) { + #ifdef USE_REVERSED_DEPTH_BUFFER + float dp = ( shadowCameraNear * ( shadowCameraFar - viewSpaceZ ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) ); + dp -= shadowBias; + #else + float dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) ); + dp += shadowBias; + #endif + float texelSize = shadowRadius / shadowMapSize.x; + vec3 absDir = abs( bd3D ); + vec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 ); + tangent = normalize( cross( bd3D, tangent ) ); + vec3 bitangent = cross( bd3D, tangent ); + float phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2; + vec2 sample0 = vogelDiskSample( 0, 5, phi ); + vec2 sample1 = vogelDiskSample( 1, 5, phi ); + vec2 sample2 = vogelDiskSample( 2, 5, phi ); + vec2 sample3 = vogelDiskSample( 3, 5, phi ); + vec2 sample4 = vogelDiskSample( 4, 5, phi ); + shadow = ( + texture( shadowMap, vec4( bd3D + ( tangent * sample0.x + bitangent * sample0.y ) * texelSize, dp ) ) + + texture( shadowMap, vec4( bd3D + ( tangent * sample1.x + bitangent * sample1.y ) * texelSize, dp ) ) + + texture( shadowMap, vec4( bd3D + ( tangent * sample2.x + bitangent * sample2.y ) * texelSize, dp ) ) + + texture( shadowMap, vec4( bd3D + ( tangent * sample3.x + bitangent * sample3.y ) * texelSize, dp ) ) + + texture( shadowMap, vec4( bd3D + ( tangent * sample4.x + bitangent * sample4.y ) * texelSize, dp ) ) + ) * 0.2; + } + return mix( 1.0, shadow, shadowIntensity ); + } + #elif defined( SHADOWMAP_TYPE_BASIC ) + float getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) { + float shadow = 1.0; + vec3 lightToPosition = shadowCoord.xyz; + vec3 absVec = abs( lightToPosition ); + float viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z ); + if ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) { + float dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) ); + dp += shadowBias; + vec3 bd3D = normalize( lightToPosition ); + float depth = textureCube( shadowMap, bd3D ).r; + #ifdef USE_REVERSED_DEPTH_BUFFER + depth = 1.0 - depth; + #endif + shadow = step( dp, depth ); + } + return mix( 1.0, shadow, shadowIntensity ); + } + #endif + #endif +#endif`,ov=`#if NUM_SPOT_LIGHT_COORDS > 0 + uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; +#endif +#ifdef USE_SHADOWMAP + #if NUM_SUN_LIGHT_SHADOWS > 0 + varying vec4 vSunShadowWorldPosition; + varying vec3 vSunShadowWorldNormal; + #endif + #if NUM_DIR_LIGHT_SHADOWS > 0 + uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ]; + varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; + struct DirectionalLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + struct SpotLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ]; + varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; + struct PointLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + float shadowCameraNear; + float shadowCameraFar; + }; + uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; + #endif +#endif`,av=`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SUN_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 ) + #ifdef HAS_NORMAL + vec3 shadowWorldNormal = transformNormalByInverseViewMatrix( transformedNormal, viewMatrix ); + #else + vec3 shadowWorldNormal = vec3( 0.0 ); + #endif + vec4 shadowWorldPosition; +#endif +#if defined( USE_SHADOWMAP ) + #if NUM_SUN_LIGHT_SHADOWS > 0 + vSunShadowWorldPosition = vec4( worldPosition.xyz, - mvPosition.z ); + vSunShadowWorldNormal = shadowWorldNormal; + #endif + #if NUM_DIR_LIGHT_SHADOWS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { + shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 ); + vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { + shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 ); + vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end + #endif +#endif +#if NUM_SPOT_LIGHT_COORDS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) { + shadowWorldPosition = worldPosition; + #if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + shadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias; + #endif + vSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end +#endif`,lv=`float getShadowMask() { + float shadow = 1.0; + #ifdef USE_SHADOWMAP + #if NUM_SUN_LIGHT_SHADOWS > 0 + SunLightShadow sunLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SUN_LIGHT_SHADOWS; i ++ ) { + sunLight = sunLightShadows[ i ]; + shadow *= receiveShadow ? getSunShadow( sunShadowMap[ i ], sunLight, UNROLLED_LOOP_INDEX ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { + directionalLight = directionalLightShadows[ i ]; + shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) { + spotLight = spotLightShadows[ i ]; + shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) ) + PointLightShadow pointLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { + pointLight = pointLightShadows[ i ]; + shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0; + } + #pragma unroll_loop_end + #endif + #endif + return shadow; +}`,cv=`#ifdef USE_SKINNING + mat4 boneMatX = getBoneMatrix( skinIndex.x ); + mat4 boneMatY = getBoneMatrix( skinIndex.y ); + mat4 boneMatZ = getBoneMatrix( skinIndex.z ); + mat4 boneMatW = getBoneMatrix( skinIndex.w ); +#endif`,hv=`#ifdef USE_SKINNING + uniform mat4 bindMatrix; + uniform mat4 bindMatrixInverse; + uniform highp sampler2D boneTexture; + mat4 getBoneMatrix( const in float i ) { + int size = textureSize( boneTexture, 0 ).x; + int j = int( i ) * 4; + int x = j % size; + int y = j / size; + vec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 ); + vec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 ); + vec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 ); + vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 ); + return mat4( v1, v2, v3, v4 ); + } +#endif`,uv=`#ifdef USE_SKINNING + vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 ); + vec4 skinned = vec4( 0.0 ); + skinned += boneMatX * skinVertex * skinWeight.x; + skinned += boneMatY * skinVertex * skinWeight.y; + skinned += boneMatZ * skinVertex * skinWeight.z; + skinned += boneMatW * skinVertex * skinWeight.w; + transformed = ( bindMatrixInverse * skinned ).xyz; +#endif`,dv=`#ifdef USE_SKINNING + mat4 skinMatrix = mat4( 0.0 ); + skinMatrix += skinWeight.x * boneMatX; + skinMatrix += skinWeight.y * boneMatY; + skinMatrix += skinWeight.z * boneMatZ; + skinMatrix += skinWeight.w * boneMatW; + skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix; + objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz; + #ifdef USE_TANGENT + objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz; + #endif +#endif`,fv=`float specularStrength; +#ifdef USE_SPECULARMAP + vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv ); + specularStrength = texelSpecular.r; +#else + specularStrength = 1.0; +#endif`,pv=`#ifdef USE_SPECULARMAP + uniform sampler2D specularMap; +#endif`,mv=`#if defined( TONE_MAPPING ) + gl_FragColor.rgb = toneMapping( gl_FragColor.rgb ); +#endif`,gv=`#ifndef saturate +#define saturate( a ) clamp( a, 0.0, 1.0 ) +#endif +uniform float toneMappingExposure; +vec3 LinearToneMapping( vec3 color ) { + return saturate( toneMappingExposure * color ); +} +vec3 ReinhardToneMapping( vec3 color ) { + color *= toneMappingExposure; + return saturate( color / ( vec3( 1.0 ) + color ) ); +} +vec3 CineonToneMapping( vec3 color ) { + color *= toneMappingExposure; + color = max( vec3( 0.0 ), color - 0.004 ); + return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) ); +} +vec3 RRTAndODTFit( vec3 v ) { + vec3 a = v * ( v + 0.0245786 ) - 0.000090537; + vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081; + return a / b; +} +vec3 ACESFilmicToneMapping( vec3 color ) { + const mat3 ACESInputMat = mat3( + vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ), + vec3( 0.04823, 0.01566, 0.83777 ) + ); + const mat3 ACESOutputMat = mat3( + vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ), + vec3( -0.07367, -0.00605, 1.07602 ) + ); + color *= toneMappingExposure / 0.6; + color = ACESInputMat * color; + color = RRTAndODTFit( color ); + color = ACESOutputMat * color; + return saturate( color ); +} +const mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3( + vec3( 1.6605, - 0.1246, - 0.0182 ), + vec3( - 0.5876, 1.1329, - 0.1006 ), + vec3( - 0.0728, - 0.0083, 1.1187 ) +); +const mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3( + vec3( 0.6274, 0.0691, 0.0164 ), + vec3( 0.3293, 0.9195, 0.0880 ), + vec3( 0.0433, 0.0113, 0.8956 ) +); +vec3 agxDefaultContrastApprox( vec3 x ) { + vec3 x2 = x * x; + vec3 x4 = x2 * x2; + return + 15.5 * x4 * x2 + - 40.14 * x4 * x + + 31.96 * x4 + - 6.868 * x2 * x + + 0.4298 * x2 + + 0.1191 * x + - 0.00232; +} +vec3 AgXToneMapping( vec3 color ) { + const mat3 AgXInsetMatrix = mat3( + vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), + vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), + vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) + ); + const mat3 AgXOutsetMatrix = mat3( + vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), + vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), + vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) + ); + const float AgxMinEv = - 12.47393; const float AgxMaxEv = 4.026069; + color *= toneMappingExposure; + color = LINEAR_SRGB_TO_LINEAR_REC2020 * color; + color = AgXInsetMatrix * color; + color = max( color, 1e-10 ); color = log2( color ); + color = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv ); + color = clamp( color, 0.0, 1.0 ); + color = agxDefaultContrastApprox( color ); + color = AgXOutsetMatrix * color; + color = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) ); + color = LINEAR_REC2020_TO_LINEAR_SRGB * color; + color = clamp( color, 0.0, 1.0 ); + return color; +} +vec3 NeutralToneMapping( vec3 color ) { + const float StartCompression = 0.8 - 0.04; + const float Desaturation = 0.15; + color *= toneMappingExposure; + float x = min( color.r, min( color.g, color.b ) ); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + float peak = max( color.r, max( color.g, color.b ) ); + if ( peak < StartCompression ) return color; + float d = 1. - StartCompression; + float newPeak = 1. - d * d / ( peak + d - StartCompression ); + color *= newPeak / peak; + float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ); + return mix( color, vec3( newPeak ), g ); +} +vec3 CustomToneMapping( vec3 color ) { return color; }`,_v=`#ifdef USE_TRANSMISSION + material.transmission = transmission; + material.transmissionAlpha = 1.0; + material.thickness = thickness; + material.attenuationDistance = attenuationDistance; + material.attenuationColor = attenuationColor; + #ifdef USE_TRANSMISSIONMAP + material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; + #endif + #ifdef USE_THICKNESSMAP + material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; + #endif + vec3 pos = vWorldPosition; + vec3 v = normalize( cameraPosition - pos ); + vec3 n = transformNormalByInverseViewMatrix( normal, viewMatrix ); + vec4 transmitted = getIBLVolumeRefraction( + n, v, material.roughness, material.diffuseContribution, material.specularColorBlended, material.specularF90, + pos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness, + material.attenuationColor, material.attenuationDistance ); + material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); + totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission ); +#endif`,xv=`#ifdef USE_TRANSMISSION + uniform float transmission; + uniform float thickness; + uniform float attenuationDistance; + uniform vec3 attenuationColor; + #ifdef USE_TRANSMISSIONMAP + uniform sampler2D transmissionMap; + #endif + #ifdef USE_THICKNESSMAP + uniform sampler2D thicknessMap; + #endif + uniform vec2 transmissionSamplerSize; + uniform sampler2D transmissionSamplerMap; + uniform mat4 modelMatrix; + uniform mat4 projectionMatrix; + varying vec3 vWorldPosition; + float w0( float a ) { + return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); + } + float w1( float a ) { + return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); + } + float w2( float a ){ + return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); + } + float w3( float a ) { + return ( 1.0 / 6.0 ) * ( a * a * a ); + } + float g0( float a ) { + return w0( a ) + w1( a ); + } + float g1( float a ) { + return w2( a ) + w3( a ); + } + float h0( float a ) { + return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); + } + float h1( float a ) { + return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); + } + vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { + uv = uv * texelSize.zw + 0.5; + vec2 iuv = floor( uv ); + vec2 fuv = fract( uv ); + float g0x = g0( fuv.x ); + float g1x = g1( fuv.x ); + float h0x = h0( fuv.x ); + float h1x = h1( fuv.x ); + float h0y = h0( fuv.y ); + float h1y = h1( fuv.y ); + vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + + g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); + } + vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { + vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); + vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); + vec2 fLodSizeInv = 1.0 / fLodSize; + vec2 cLodSizeInv = 1.0 / cLodSize; + vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); + vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); + return mix( fSample, cSample, fract( lod ) ); + } + vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { + vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); + vec3 modelScale; + modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); + modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); + modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); + return normalize( refractionVector ) * thickness * modelScale; + } + float applyIorToRoughness( const in float roughness, const in float ior ) { + return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); + } + vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { + float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); + return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); + } + vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { + if ( isinf( attenuationDistance ) ) { + return vec3( 1.0 ); + } else { + vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; + vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance; + } + } + vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, + const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, + const in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness, + const in vec3 attenuationColor, const in float attenuationDistance ) { + vec4 transmittedLight; + vec3 transmittance; + #ifdef USE_DISPERSION + float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion; + vec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread ); + for ( int i = 0; i < 3; i ++ ) { + vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix ); + vec3 refractedRayExit = position + transmissionRay; + vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); + vec2 refractionCoords = ndcPos.xy / ndcPos.w; + refractionCoords += 1.0; + refractionCoords /= 2.0; + vec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] ); + transmittedLight[ i ] = transmissionSample[ i ]; + transmittedLight.a += transmissionSample.a; + transmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ]; + } + transmittedLight.a /= 3.0; + #else + vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + vec3 refractedRayExit = position + transmissionRay; + vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); + vec2 refractionCoords = ndcPos.xy / ndcPos.w; + refractionCoords += 1.0; + refractionCoords /= 2.0; + transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); + transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); + #endif + vec3 attenuatedColor = transmittance * transmittedLight.rgb; + vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); + float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; + return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); + } +#endif`,yv=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + varying vec2 vUv; +#endif +#ifdef USE_MAP + varying vec2 vMapUv; +#endif +#ifdef USE_ALPHAMAP + varying vec2 vAlphaMapUv; +#endif +#ifdef USE_LIGHTMAP + varying vec2 vLightMapUv; +#endif +#ifdef USE_AOMAP + varying vec2 vAoMapUv; +#endif +#ifdef USE_BUMPMAP + varying vec2 vBumpMapUv; +#endif +#ifdef USE_NORMALMAP + varying vec2 vNormalMapUv; +#endif +#ifdef USE_EMISSIVEMAP + varying vec2 vEmissiveMapUv; +#endif +#ifdef USE_METALNESSMAP + varying vec2 vMetalnessMapUv; +#endif +#ifdef USE_ROUGHNESSMAP + varying vec2 vRoughnessMapUv; +#endif +#ifdef USE_ANISOTROPYMAP + varying vec2 vAnisotropyMapUv; +#endif +#ifdef USE_CLEARCOATMAP + varying vec2 vClearcoatMapUv; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + varying vec2 vClearcoatNormalMapUv; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + varying vec2 vClearcoatRoughnessMapUv; +#endif +#ifdef USE_IRIDESCENCEMAP + varying vec2 vIridescenceMapUv; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + varying vec2 vIridescenceThicknessMapUv; +#endif +#ifdef USE_SHEEN_COLORMAP + varying vec2 vSheenColorMapUv; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + varying vec2 vSheenRoughnessMapUv; +#endif +#ifdef USE_SPECULARMAP + varying vec2 vSpecularMapUv; +#endif +#ifdef USE_SPECULAR_COLORMAP + varying vec2 vSpecularColorMapUv; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + varying vec2 vSpecularIntensityMapUv; +#endif +#ifdef USE_TRANSMISSIONMAP + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; +#endif +#ifdef USE_THICKNESSMAP + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; +#endif`,vv=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + varying vec2 vUv; +#endif +#ifdef USE_MAP + uniform mat3 mapTransform; + varying vec2 vMapUv; +#endif +#ifdef USE_ALPHAMAP + uniform mat3 alphaMapTransform; + varying vec2 vAlphaMapUv; +#endif +#ifdef USE_LIGHTMAP + uniform mat3 lightMapTransform; + varying vec2 vLightMapUv; +#endif +#ifdef USE_AOMAP + uniform mat3 aoMapTransform; + varying vec2 vAoMapUv; +#endif +#ifdef USE_BUMPMAP + uniform mat3 bumpMapTransform; + varying vec2 vBumpMapUv; +#endif +#ifdef USE_NORMALMAP + uniform mat3 normalMapTransform; + varying vec2 vNormalMapUv; +#endif +#ifdef USE_DISPLACEMENTMAP + uniform mat3 displacementMapTransform; + varying vec2 vDisplacementMapUv; +#endif +#ifdef USE_EMISSIVEMAP + uniform mat3 emissiveMapTransform; + varying vec2 vEmissiveMapUv; +#endif +#ifdef USE_METALNESSMAP + uniform mat3 metalnessMapTransform; + varying vec2 vMetalnessMapUv; +#endif +#ifdef USE_ROUGHNESSMAP + uniform mat3 roughnessMapTransform; + varying vec2 vRoughnessMapUv; +#endif +#ifdef USE_ANISOTROPYMAP + uniform mat3 anisotropyMapTransform; + varying vec2 vAnisotropyMapUv; +#endif +#ifdef USE_CLEARCOATMAP + uniform mat3 clearcoatMapTransform; + varying vec2 vClearcoatMapUv; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + uniform mat3 clearcoatNormalMapTransform; + varying vec2 vClearcoatNormalMapUv; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + uniform mat3 clearcoatRoughnessMapTransform; + varying vec2 vClearcoatRoughnessMapUv; +#endif +#ifdef USE_SHEEN_COLORMAP + uniform mat3 sheenColorMapTransform; + varying vec2 vSheenColorMapUv; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + uniform mat3 sheenRoughnessMapTransform; + varying vec2 vSheenRoughnessMapUv; +#endif +#ifdef USE_IRIDESCENCEMAP + uniform mat3 iridescenceMapTransform; + varying vec2 vIridescenceMapUv; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + uniform mat3 iridescenceThicknessMapTransform; + varying vec2 vIridescenceThicknessMapUv; +#endif +#ifdef USE_SPECULARMAP + uniform mat3 specularMapTransform; + varying vec2 vSpecularMapUv; +#endif +#ifdef USE_SPECULAR_COLORMAP + uniform mat3 specularColorMapTransform; + varying vec2 vSpecularColorMapUv; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + uniform mat3 specularIntensityMapTransform; + varying vec2 vSpecularIntensityMapUv; +#endif +#ifdef USE_TRANSMISSIONMAP + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; +#endif +#ifdef USE_THICKNESSMAP + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; +#endif`,Mv=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + vUv = vec3( uv, 1 ).xy; +#endif +#ifdef USE_MAP + vMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ALPHAMAP + vAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_LIGHTMAP + vLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_AOMAP + vAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_BUMPMAP + vBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_NORMALMAP + vNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_DISPLACEMENTMAP + vDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_EMISSIVEMAP + vEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_METALNESSMAP + vMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ROUGHNESSMAP + vRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ANISOTROPYMAP + vAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOATMAP + vClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_IRIDESCENCEMAP + vIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SHEEN_COLORMAP + vSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULARMAP + vSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULAR_COLORMAP + vSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_TRANSMISSIONMAP + vTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_THICKNESSMAP + vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy; +#endif`,Sv=`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0 + vec4 worldPosition = vec4( transformed, 1.0 ); + #ifdef USE_BATCHING + worldPosition = batchingMatrix * worldPosition; + #endif + #ifdef USE_INSTANCING + worldPosition = instanceMatrix * worldPosition; + #endif + worldPosition = modelMatrix * worldPosition; +#endif`,bv=`varying vec2 vUv; +uniform mat3 uvTransform; +void main() { + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + gl_Position = vec4( position.xy, 1.0, 1.0 ); +}`,Tv=`uniform sampler2D t2D; +uniform float backgroundIntensity; +varying vec2 vUv; +void main() { + vec4 texColor = texture2D( t2D, vUv ); + #ifdef DECODE_VIDEO_TEXTURE + texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w ); + #endif + texColor.rgb *= backgroundIntensity; + gl_FragColor = texColor; + #include + #include +}`,Av=`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include + gl_Position.z = gl_Position.w; +}`,Ev=`#ifdef ENVMAP_TYPE_CUBE + uniform samplerCube envMap; +#elif defined( ENVMAP_TYPE_CUBE_UV ) + uniform sampler2D envMap; +#endif +uniform float backgroundBlurriness; +uniform float backgroundIntensity; +uniform mat3 backgroundRotation; +varying vec3 vWorldDirection; +#include +void main() { + #ifdef ENVMAP_TYPE_CUBE + vec4 texColor = textureCube( envMap, backgroundRotation * vWorldDirection ); + #elif defined( ENVMAP_TYPE_CUBE_UV ) + vec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness ); + #else + vec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + #endif + texColor.rgb *= backgroundIntensity; + gl_FragColor = texColor; + #include + #include +}`,wv=`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include + gl_Position.z = gl_Position.w; +}`,Rv=`uniform samplerCube tCube; +uniform float tFlip; +uniform float opacity; +varying vec3 vWorldDirection; +void main() { + vec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) ); + gl_FragColor = texColor; + gl_FragColor.a *= opacity; + #include + #include +}`,Cv=`#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW; +void main() { + #include + #include + #include + #include + #ifdef USE_DISPLACEMENTMAP + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + vHighPrecisionZW = gl_Position.zw; +}`,Iv=`#if DEPTH_PACKING == 3200 + uniform float opacity; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW; +void main() { + vec4 diffuseColor = vec4( 1.0 ); + #include + #if DEPTH_PACKING == 3200 + diffuseColor.a = opacity; + #endif + #include + #include + #include + #include + #include + #ifdef USE_REVERSED_DEPTH_BUFFER + float fragCoordZ = vHighPrecisionZW[ 0 ] / vHighPrecisionZW[ 1 ]; + #else + float fragCoordZ = 0.5 * vHighPrecisionZW[ 0 ] / vHighPrecisionZW[ 1 ] + 0.5; + #endif + #if DEPTH_PACKING == 3200 + gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity ); + #elif DEPTH_PACKING == 3201 + gl_FragColor = packDepthToRGBA( fragCoordZ ); + #elif DEPTH_PACKING == 3202 + gl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 ); + #elif DEPTH_PACKING == 3203 + gl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 ); + #endif +}`,Pv=`#define DISTANCE +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #ifdef USE_DISPLACEMENTMAP + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + vWorldPosition = worldPosition.xyz; +}`,Lv=`#define DISTANCE +uniform vec3 referencePosition; +uniform float nearDistance; +uniform float farDistance; +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( 1.0 ); + #include + #include + #include + #include + #include + float dist = length( vWorldPosition - referencePosition ); + dist = ( dist - nearDistance ) / ( farDistance - nearDistance ); + dist = saturate( dist ); + gl_FragColor = vec4( dist, 0.0, 0.0, 1.0 ); +}`,Nv=`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include +}`,Dv=`uniform sampler2D tEquirect; +varying vec3 vWorldDirection; +#include +void main() { + vec3 direction = normalize( vWorldDirection ); + vec2 sampleUV = equirectUv( direction ); + gl_FragColor = texture2D( tEquirect, sampleUV ); + #include + #include +}`,Uv=`uniform float scale; +attribute float lineDistance; +varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main() { + vLineDistance = scale * lineDistance; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,Fv=`uniform vec3 diffuse; +uniform float opacity; +uniform float dashSize; +uniform float totalSize; +varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + if ( mod( vLineDistance, totalSize ) > dashSize ) { + discard; + } + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include + #include +}`,Ov=`#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING ) + #include + #include + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,Bv=`uniform vec3 diffuse; +uniform float opacity; +#ifndef FLAT_SHADED + varying vec3 vNormal; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + #include + #include + #include + #include + #include + #include + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + #ifdef USE_LIGHTMAP + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); + reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI; + #else + reflectedLight.indirectDiffuse += vec3( 1.0 ); + #endif + #include + reflectedLight.indirectDiffuse *= diffuseColor.rgb; + vec3 outgoingLight = reflectedLight.indirectDiffuse; + #include + #include + #include + #include + #include + #include + #include +}`,zv=`#define LAMBERT +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include + #include +}`,kv=`#define LAMBERT +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include + #include +}`,Vv=`#define MATCAP +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; +}`,Gv=`#define MATCAP +uniform vec3 diffuse; +uniform float opacity; +uniform sampler2D matcap; +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 viewDir = normalize( vViewPosition ); + vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) ); + vec3 y = cross( viewDir, x ); + vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; + #ifdef USE_MATCAP + vec4 matcapColor = texture2D( matcap, uv ); + #else + vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 ); + #endif + vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb; + #include + #include + #include + #include + #include + #include +}`,Hv=`#define NORMAL +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + vViewPosition = - mvPosition.xyz; +#endif +}`,Wv=`#define NORMAL +uniform float opacity; +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity ); + #include + #include + #include + #include + gl_FragColor = vec4( normalize( normal ) * 0.5 + 0.5, diffuseColor.a ); + #ifdef OPAQUE + gl_FragColor.a = 1.0; + #endif +}`,Xv=`#define PHONG +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include + #include +}`,qv=`#define PHONG +uniform vec3 diffuse; +uniform vec3 emissive; +uniform vec3 specular; +uniform float shininess; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include + #include +}`,Yv=`#define STANDARD +varying vec3 vViewPosition; +#ifdef USE_TRANSMISSION + varying vec3 vWorldPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include +#ifdef USE_TRANSMISSION + vWorldPosition = worldPosition.xyz; +#endif +}`,Zv=`#define STANDARD +#ifdef PHYSICAL + #define IOR + #define USE_SPECULAR +#endif +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float roughness; +uniform float metalness; +uniform float opacity; +#ifdef IOR + uniform float ior; +#endif +#ifdef USE_SPECULAR + uniform float specularIntensity; + uniform vec3 specularColor; + #ifdef USE_SPECULAR_COLORMAP + uniform sampler2D specularColorMap; + #endif + #ifdef USE_SPECULAR_INTENSITYMAP + uniform sampler2D specularIntensityMap; + #endif +#endif +#ifdef USE_CLEARCOAT + uniform float clearcoat; + uniform float clearcoatRoughness; +#endif +#ifdef USE_DISPERSION + uniform float dispersion; +#endif +#ifdef USE_RETROREFLECTION + uniform float retroreflectivity; +#endif +#ifdef USE_IRIDESCENCE + uniform float iridescence; + uniform float iridescenceIOR; + uniform float iridescenceThicknessMinimum; + uniform float iridescenceThicknessMaximum; +#endif +#ifdef USE_SHEEN + uniform vec3 sheenColor; + uniform float sheenRoughness; + #ifdef USE_SHEEN_COLORMAP + uniform sampler2D sheenColorMap; + #endif + #ifdef USE_SHEEN_ROUGHNESSMAP + uniform sampler2D sheenRoughnessMap; + #endif +#endif +#ifdef USE_ANISOTROPY + uniform vec2 anisotropyVector; + #ifdef USE_ANISOTROPYMAP + uniform sampler2D anisotropyMap; + #endif +#endif +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse; + vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular; + #include + vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance; + #ifdef USE_SHEEN + + outgoingLight = outgoingLight + sheenSpecularDirect + sheenSpecularIndirect; + + #endif + #ifdef USE_CLEARCOAT + float dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) ); + vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc ); + outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat; + #endif + #include + #include + #include + #include + #include + #include +}`,Kv=`#define TOON +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include +}`,Jv=`#define TOON +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include +}`,jv=`uniform float size; +uniform float scale; +#include +#include +#include +#include +#include +#include +#ifdef USE_POINTS_UV + varying vec2 vUv; + uniform mat3 uvTransform; +#endif +void main() { + #ifdef USE_POINTS_UV + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + #endif + #include + #include + #include + #include + #include + #include + gl_PointSize = size; + #ifdef USE_SIZEATTENUATION + bool isPerspective = isPerspectiveMatrix( projectionMatrix ); + if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z ); + #endif + #include + #include + #include + #include +}`,$v=`uniform vec3 diffuse; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include + #include +}`,Qv=`#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,eM=`uniform vec3 color; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) ); + #include + #include + #include + #include +}`,tM=`uniform float rotation; +uniform vec2 center; +#include +#include +#include +#include +#include +void main() { + #include + vec4 mvPosition = modelViewMatrix[ 3 ]; + vec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) ); + #ifndef USE_SIZEATTENUATION + bool isPerspective = isPerspectiveMatrix( projectionMatrix ); + if ( isPerspective ) scale *= - mvPosition.z; + #endif + vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale; + vec2 rotatedPosition; + rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y; + rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y; + mvPosition.xy += rotatedPosition; + gl_Position = projectionMatrix * mvPosition; + #include + #include + #include +}`,nM=`uniform vec3 diffuse; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include +}`,je={alphahash_fragment:bx,alphahash_pars_fragment:Tx,alphamap_fragment:Ax,alphamap_pars_fragment:Ex,alphatest_fragment:wx,alphatest_pars_fragment:Rx,aomap_fragment:Cx,aomap_pars_fragment:Ix,batching_pars_vertex:Px,batching_vertex:Lx,begin_vertex:Nx,beginnormal_vertex:Dx,bsdfs:Ux,iridescence_fragment:Fx,bumpmap_pars_fragment:Ox,clipping_planes_fragment:Bx,clipping_planes_pars_fragment:zx,clipping_planes_pars_vertex:kx,clipping_planes_vertex:Vx,color_fragment:Gx,color_pars_fragment:Hx,color_pars_vertex:Wx,color_vertex:Xx,common:qx,cube_uv_reflection_fragment:Yx,defaultnormal_vertex:Zx,displacementmap_pars_vertex:Kx,displacementmap_vertex:Jx,emissivemap_fragment:jx,emissivemap_pars_fragment:$x,colorspace_fragment:Qx,colorspace_pars_fragment:ey,envmap_fragment:ty,envmap_common_pars_fragment:ny,envmap_pars_fragment:iy,envmap_pars_vertex:sy,envmap_physical_pars_fragment:my,envmap_vertex:ry,fog_vertex:oy,fog_pars_vertex:ay,fog_fragment:ly,fog_pars_fragment:cy,gradientmap_pars_fragment:hy,lightmap_pars_fragment:uy,lights_lambert_fragment:dy,lights_lambert_pars_fragment:fy,lights_pars_begin:py,lights_toon_fragment:gy,lights_toon_pars_fragment:_y,lights_phong_fragment:xy,lights_phong_pars_fragment:yy,lights_physical_fragment:vy,lights_physical_pars_fragment:My,lights_fragment_begin:Sy,lights_fragment_maps:by,lights_fragment_end:Ty,lightprobes_pars_fragment:Ay,logdepthbuf_fragment:Ey,logdepthbuf_pars_fragment:wy,logdepthbuf_pars_vertex:Ry,logdepthbuf_vertex:Cy,map_fragment:Iy,map_pars_fragment:Py,map_particle_fragment:Ly,map_particle_pars_fragment:Ny,metalnessmap_fragment:Dy,metalnessmap_pars_fragment:Uy,morphinstance_vertex:Fy,morphcolor_vertex:Oy,morphnormal_vertex:By,morphtarget_pars_vertex:zy,morphtarget_vertex:ky,normal_fragment_begin:Vy,normal_fragment_maps:Gy,normal_pars_fragment:Hy,normal_pars_vertex:Wy,normal_vertex:Xy,normalmap_pars_fragment:qy,clearcoat_normal_fragment_begin:Yy,clearcoat_normal_fragment_maps:Zy,clearcoat_pars_fragment:Ky,iridescence_pars_fragment:Jy,opaque_fragment:jy,packing:$y,premultiplied_alpha_fragment:Qy,project_vertex:ev,dithering_fragment:tv,dithering_pars_fragment:nv,roughnessmap_fragment:iv,roughnessmap_pars_fragment:sv,shadowmap_pars_fragment:rv,shadowmap_pars_vertex:ov,shadowmap_vertex:av,shadowmask_pars_fragment:lv,skinbase_vertex:cv,skinning_pars_vertex:hv,skinning_vertex:uv,skinnormal_vertex:dv,specularmap_fragment:fv,specularmap_pars_fragment:pv,tonemapping_fragment:mv,tonemapping_pars_fragment:gv,transmission_fragment:_v,transmission_pars_fragment:xv,uv_pars_fragment:yv,uv_pars_vertex:vv,uv_vertex:Mv,worldpos_vertex:Sv,background_vert:bv,background_frag:Tv,backgroundCube_vert:Av,backgroundCube_frag:Ev,cube_vert:wv,cube_frag:Rv,depth_vert:Cv,depth_frag:Iv,distance_vert:Pv,distance_frag:Lv,equirect_vert:Nv,equirect_frag:Dv,linedashed_vert:Uv,linedashed_frag:Fv,meshbasic_vert:Ov,meshbasic_frag:Bv,meshlambert_vert:zv,meshlambert_frag:kv,meshmatcap_vert:Vv,meshmatcap_frag:Gv,meshnormal_vert:Hv,meshnormal_frag:Wv,meshphong_vert:Xv,meshphong_frag:qv,meshphysical_vert:Yv,meshphysical_frag:Zv,meshtoon_vert:Kv,meshtoon_frag:Jv,points_vert:jv,points_frag:$v,shadow_vert:Qv,shadow_frag:eM,sprite_vert:tM,sprite_frag:nM},xe={common:{diffuse:{value:new ce(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new qe},alphaMap:{value:null},alphaMapTransform:{value:new qe},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new qe}},envmap:{envMap:{value:null},envMapRotation:{value:new qe},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98},dfgLUT:{value:null}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new qe}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new qe}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new qe},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new qe},normalScale:{value:new J(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new qe},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new qe}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new qe}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new qe}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new ce(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},sunLights:{value:[],properties:{direction:{},color:{}}},sunLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},sunShadowMatrix:{value:[]},sunShadowCascade:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null},probesSH:{value:null},probesMin:{value:new R},probesMax:{value:new R},probesResolution:{value:new R}},points:{diffuse:{value:new ce(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new qe},alphaTest:{value:0},uvTransform:{value:new qe}},sprite:{diffuse:{value:new ce(16777215)},opacity:{value:1},center:{value:new J(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new qe},alphaMap:{value:null},alphaMapTransform:{value:new qe},alphaTest:{value:0}}},ii={basic:{uniforms:rn([xe.common,xe.specularmap,xe.envmap,xe.aomap,xe.lightmap,xe.fog]),vertexShader:je.meshbasic_vert,fragmentShader:je.meshbasic_frag},lambert:{uniforms:rn([xe.common,xe.specularmap,xe.envmap,xe.aomap,xe.lightmap,xe.emissivemap,xe.bumpmap,xe.normalmap,xe.displacementmap,xe.fog,xe.lights,{emissive:{value:new ce(0)},envMapIntensity:{value:1}}]),vertexShader:je.meshlambert_vert,fragmentShader:je.meshlambert_frag},phong:{uniforms:rn([xe.common,xe.specularmap,xe.envmap,xe.aomap,xe.lightmap,xe.emissivemap,xe.bumpmap,xe.normalmap,xe.displacementmap,xe.fog,xe.lights,{emissive:{value:new ce(0)},specular:{value:new ce(1118481)},shininess:{value:30},envMapIntensity:{value:1}}]),vertexShader:je.meshphong_vert,fragmentShader:je.meshphong_frag},standard:{uniforms:rn([xe.common,xe.envmap,xe.aomap,xe.lightmap,xe.emissivemap,xe.bumpmap,xe.normalmap,xe.displacementmap,xe.roughnessmap,xe.metalnessmap,xe.fog,xe.lights,{emissive:{value:new ce(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:je.meshphysical_vert,fragmentShader:je.meshphysical_frag},toon:{uniforms:rn([xe.common,xe.aomap,xe.lightmap,xe.emissivemap,xe.bumpmap,xe.normalmap,xe.displacementmap,xe.gradientmap,xe.fog,xe.lights,{emissive:{value:new ce(0)}}]),vertexShader:je.meshtoon_vert,fragmentShader:je.meshtoon_frag},matcap:{uniforms:rn([xe.common,xe.bumpmap,xe.normalmap,xe.displacementmap,xe.fog,{matcap:{value:null}}]),vertexShader:je.meshmatcap_vert,fragmentShader:je.meshmatcap_frag},points:{uniforms:rn([xe.points,xe.fog]),vertexShader:je.points_vert,fragmentShader:je.points_frag},dashed:{uniforms:rn([xe.common,xe.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:je.linedashed_vert,fragmentShader:je.linedashed_frag},depth:{uniforms:rn([xe.common,xe.displacementmap]),vertexShader:je.depth_vert,fragmentShader:je.depth_frag},normal:{uniforms:rn([xe.common,xe.bumpmap,xe.normalmap,xe.displacementmap,{opacity:{value:1}}]),vertexShader:je.meshnormal_vert,fragmentShader:je.meshnormal_frag},sprite:{uniforms:rn([xe.sprite,xe.fog]),vertexShader:je.sprite_vert,fragmentShader:je.sprite_frag},background:{uniforms:{uvTransform:{value:new qe},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:je.background_vert,fragmentShader:je.background_frag},backgroundCube:{uniforms:{envMap:{value:null},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new qe}},vertexShader:je.backgroundCube_vert,fragmentShader:je.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:je.cube_vert,fragmentShader:je.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:je.equirect_vert,fragmentShader:je.equirect_frag},distance:{uniforms:rn([xe.common,xe.displacementmap,{referencePosition:{value:new R},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:je.distance_vert,fragmentShader:je.distance_frag},shadow:{uniforms:rn([xe.lights,xe.fog,{color:{value:new ce(0)},opacity:{value:1}}]),vertexShader:je.shadow_vert,fragmentShader:je.shadow_frag}};ii.physical={uniforms:rn([ii.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new qe},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new qe},clearcoatNormalScale:{value:new J(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new qe},dispersion:{value:0},retroreflectivity:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new qe},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new qe},sheen:{value:0},sheenColor:{value:new ce(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new qe},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new qe},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new qe},transmissionSamplerSize:{value:new J},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new qe},attenuationDistance:{value:0},attenuationColor:{value:new ce(0)},specularColor:{value:new ce(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new qe},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new qe},anisotropyVector:{value:new J},anisotropyMap:{value:null},anisotropyMapTransform:{value:new qe}}]),vertexShader:je.meshphysical_vert,fragmentShader:je.meshphysical_frag};var au={r:0,b:0,g:0},iM=new ze,Jg=new qe;Jg.set(-1,0,0,0,1,0,0,0,1);function sM(r,e,t,n,i,s){let o=new ce(0),a=i===!0?0:1,l,c,h=null,u=0,d=null;function f(y){let b=y.isScene===!0?y.background:null;if(b&&b.isTexture){let x=y.backgroundBlurriness>0;b=e.get(b,x)}return b}function p(y){let b=!1,x=f(y);x===null?g(o,a):x&&x.isColor&&(g(x,1),b=!0);let T=r.xr.getEnvironmentBlendMode();T==="additive"?t.buffers.color.setClear(0,0,0,1,s):T==="alpha-blend"&&t.buffers.color.setClear(0,0,0,0,s),(r.autoClear||b)&&(t.buffers.depth.setTest(!0),t.buffers.depth.setMask(!0),t.buffers.color.setMask(!0),r.clear(r.autoClearColor,r.autoClearDepth,r.autoClearStencil))}function _(y,b){let x=f(b);x&&(x.isCubeTexture||x.mapping===Zs)?(c===void 0&&(c=new rt(new ui(1,1,1),new un({name:"BackgroundCubeMaterial",uniforms:$s(ii.backgroundCube.uniforms),vertexShader:ii.backgroundCube.vertexShader,fragmentShader:ii.backgroundCube.fragmentShader,side:qt,depthTest:!1,depthWrite:!1,fog:!1,allowOverride:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(T,S,w){this.matrixWorld.copyPosition(w.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),n.update(c)),c.material.uniforms.envMap.value=x,c.material.uniforms.backgroundBlurriness.value=b.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=b.backgroundIntensity,c.material.uniforms.backgroundRotation.value.setFromMatrix4(iM.makeRotationFromEuler(b.backgroundRotation)).transpose(),x.isCubeTexture&&x.isRenderTargetTexture===!1&&c.material.uniforms.backgroundRotation.value.premultiply(Jg),c.material.toneMapped=Je.getTransfer(x.colorSpace)!==ht,(h!==x||u!==x.version||d!==r.toneMapping)&&(c.material.needsUpdate=!0,h=x,u=x.version,d=r.toneMapping),c.layers.enableAll(),y.unshift(c,c.geometry,c.material,0,0,null)):x&&x.isTexture&&(l===void 0&&(l=new rt(new Bs(2,2),new un({name:"BackgroundMaterial",uniforms:$s(ii.background.uniforms),vertexShader:ii.background.vertexShader,fragmentShader:ii.background.fragmentShader,side:ei,depthTest:!1,depthWrite:!1,fog:!1,allowOverride:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),n.update(l)),l.material.uniforms.t2D.value=x,l.material.uniforms.backgroundIntensity.value=b.backgroundIntensity,l.material.toneMapped=Je.getTransfer(x.colorSpace)!==ht,x.matrixAutoUpdate===!0&&x.updateMatrix(),l.material.uniforms.uvTransform.value.copy(x.matrix),(h!==x||u!==x.version||d!==r.toneMapping)&&(l.material.needsUpdate=!0,h=x,u=x.version,d=r.toneMapping),l.layers.enableAll(),y.unshift(l,l.geometry,l.material,0,0,null))}function g(y,b){y.getRGB(au,nf(r)),t.buffers.color.setClear(au.r,au.g,au.b,b,s)}function m(){c!==void 0&&(c.geometry.dispose(),c.material.dispose(),c=void 0),l!==void 0&&(l.geometry.dispose(),l.material.dispose(),l=void 0)}return{getClearColor:function(){return o},setClearColor:function(y,b=1){o.set(y),a=b,g(o,a)},getClearAlpha:function(){return a},setClearAlpha:function(y){a=y,g(o,a)},render:p,addToRenderList:_,dispose:m}}function rM(r,e){let t=r.getParameter(r.MAX_VERTEX_ATTRIBS),n={},i=d(null),s=i,o=!1;function a(P,F,z,N,B){let H=!1,X=u(P,N,z,F);s!==X&&(s=X,c(s.object)),H=f(P,N,z,B),H&&p(P,N,z,B),B!==null&&e.update(B,r.ELEMENT_ARRAY_BUFFER),(H||o)&&(o=!1,x(P,F,z,N),B!==null&&r.bindBuffer(r.ELEMENT_ARRAY_BUFFER,e.get(B).buffer))}function l(){return r.createVertexArray()}function c(P){return r.bindVertexArray(P)}function h(P){return r.deleteVertexArray(P)}function u(P,F,z,N){let B=N.wireframe===!0,H=n[F.id];H===void 0&&(H={},n[F.id]=H);let X=P.isInstancedMesh===!0?P.id:0,ie=H[X];ie===void 0&&(ie={},H[X]=ie);let q=ie[z.id];q===void 0&&(q={},ie[z.id]=q);let Q=q[B];return Q===void 0&&(Q=d(l()),q[B]=Q),Q}function d(P){let F=[],z=[],N=[];for(let B=0;B=0){let ne=B[q],Ne=H[q];if(Ne===void 0&&(q==="instanceMatrix"&&P.instanceMatrix&&(Ne=P.instanceMatrix),q==="instanceColor"&&P.instanceColor&&(Ne=P.instanceColor)),ne===void 0||ne.attribute!==Ne||Ne&&ne.data!==Ne.data)return!0;X++}return s.attributesNum!==X||s.index!==N}function p(P,F,z,N){let B={},H=F.attributes,X=0,ie=z.getAttributes();for(let q in ie)if(ie[q].location>=0){let ne=H[q];ne===void 0&&(q==="instanceMatrix"&&P.instanceMatrix&&(ne=P.instanceMatrix),q==="instanceColor"&&P.instanceColor&&(ne=P.instanceColor));let Ne={};Ne.attribute=ne,ne&&ne.data&&(Ne.data=ne.data),B[q]=Ne,X++}s.attributes=B,s.attributesNum=X,s.index=N}function _(){let P=s.newAttributes;for(let F=0,z=P.length;F=0){let Q=B[ie];if(Q===void 0&&(ie==="instanceMatrix"&&P.instanceMatrix&&(Q=P.instanceMatrix),ie==="instanceColor"&&P.instanceColor&&(Q=P.instanceColor)),Q!==void 0){let ne=Q.normalized,Ne=Q.itemSize,we=e.get(Q);if(we===void 0)continue;let ct=we.buffer,tt=we.type,ot=we.bytesPerElement,K=tt===r.INT||tt===r.UNSIGNED_INT||Q.gpuType===Ja;if(Q.isInterleavedBufferAttribute){let ee=Q.data,ve=ee.stride,Ge=Q.offset;if(ee.isInstancedInterleavedBuffer){for(let Te=0;Te0&&r.getShaderPrecisionFormat(r.FRAGMENT_SHADER,r.HIGH_FLOAT).precision>0)return"highp";w="mediump"}return w==="mediump"&&r.getShaderPrecisionFormat(r.VERTEX_SHADER,r.MEDIUM_FLOAT).precision>0&&r.getShaderPrecisionFormat(r.FRAGMENT_SHADER,r.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let c=t.precision!==void 0?t.precision:"highp",h=l(c);h!==c&&(de("WebGLRenderer:",c,"not supported, using",h,"instead."),c=h);let u=t.logarithmicDepthBuffer===!0,d=t.reversedDepthBuffer===!0&&e.has("EXT_clip_control");t.reversedDepthBuffer===!0&&d===!1&&de("WebGLRenderer: Unable to use reversed depth buffer due to missing EXT_clip_control extension. Fallback to default depth buffer.");let f=r.getParameter(r.MAX_TEXTURE_IMAGE_UNITS),p=r.getParameter(r.MAX_VERTEX_TEXTURE_IMAGE_UNITS),_=r.getParameter(r.MAX_TEXTURE_SIZE),g=r.getParameter(r.MAX_CUBE_MAP_TEXTURE_SIZE),m=r.getParameter(r.MAX_VERTEX_ATTRIBS),y=r.getParameter(r.MAX_VERTEX_UNIFORM_VECTORS),b=r.getParameter(r.MAX_VARYING_VECTORS),x=r.getParameter(r.MAX_FRAGMENT_UNIFORM_VECTORS),T=r.getParameter(r.MAX_SAMPLES),S=r.getParameter(r.SAMPLES);return{isWebGL2:!0,getMaxAnisotropy:s,getMaxPrecision:l,textureFormatReadable:o,textureTypeReadable:a,precision:c,logarithmicDepthBuffer:u,reversedDepthBuffer:d,maxTextures:f,maxVertexTextures:p,maxTextureSize:_,maxCubemapSize:g,maxAttributes:m,maxVertexUniforms:y,maxVaryings:b,maxFragmentUniforms:x,maxSamples:T,samples:S}}function lM(r){let e=this,t=null,n=0,i=!1,s=!1,o=new gn,a=new qe,l={value:null,needsUpdate:!1};this.uniform=l,this.numPlanes=0,this.numIntersection=0,this.init=function(u,d){let f=u.length!==0||d||n!==0||i;return i=d,n=u.length,f},this.beginShadows=function(){s=!0,h(null)},this.endShadows=function(){s=!1},this.setGlobalState=function(u,d){t=h(u,d,0)},this.setState=function(u,d,f){let p=u.clippingPlanes,_=u.clipIntersection,g=u.clipShadows,m=r.get(u);if(!i||p===null||p.length===0||s&&!g)s?h(null):c();else{let y=s?0:n,b=y*4,x=m.clippingState||null;l.value=x,x=h(p,d,b,f);for(let T=0;T!==b;++T)x[T]=t[T];m.clippingState=x,this.numIntersection=_?this.numPlanes:0,this.numPlanes+=y}};function c(){l.value!==t&&(l.value=t,l.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function h(u,d,f,p){let _=u!==null?u.length:0,g=null;if(_!==0){if(g=l.value,p!==!0||g===null){let m=f+_*4,y=d.matrixWorldInverse;a.getNormalMatrix(y),(g===null||g.length0&&this._blur(l,0,0,t),this._applyPMREM(l),this._cleanup(l),l}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){this._cubemapMaterial===null&&(this._cubemapMaterial=Pg(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){this._equirectMaterial===null&&(this._equirectMaterial=Ig(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),this._cubemapMaterial!==null&&this._cubemapMaterial.dispose(),this._equirectMaterial!==null&&this._equirectMaterial.dispose(),this._backgroundBox!==null&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){this._blurMaterial!==null&&this._blurMaterial.dispose(),this._ggxMaterial!==null&&this._ggxMaterial.dispose(),this._pingPongRenderTarget!==null&&this._pingPongRenderTarget.dispose();for(let e=0;e2?T:0,T,T),u.setRenderTarget(i),m&&u.render(_,l),u.render(e,l)}u.toneMapping=f,u.autoClear=d,e.background=y}_textureToCubeUV(e,t){let n=this._renderer,i=e.mapping===ni||e.mapping===Oi;i?(this._cubemapMaterial===null&&(this._cubemapMaterial=Pg()),this._cubemapMaterial.uniforms.flipEnvMap.value=e.isRenderTargetTexture===!1?-1:1):this._equirectMaterial===null&&(this._equirectMaterial=Ig());let s=i?this._cubemapMaterial:this._equirectMaterial,o=this._lodMeshes[0];o.material=s;let a=s.uniforms;a.envMap.value=e;let l=this._cubeSize;go(t,0,0,3*l,2*l),n.setRenderTarget(t),n.render(o,Fl)}_applyPMREM(e){let t=this._renderer,n=t.autoClear;t.autoClear=!1;let i=this._lodMeshes.length;for(let s=1;sp-_o?n-p+_o:0),m=4*(this._cubeSize-_);l.envMap.value=e.texture,l.roughness.value=f,l.mipInt.value=p-t,go(s,g,m,3*_,2*_),i.setRenderTarget(s),i.render(a,Fl),l.envMap.value=s.texture,l.roughness.value=0,l.mipInt.value=p-n,go(e,g,m,3*_,2*_),i.setRenderTarget(e),i.render(a,Fl)}_blur(e,t,n,i){let s=this._pingPongRenderTarget,o=Math.min(i,Math.PI)/Math.SQRT2;this._blurPass(e,s,t,n,o),this._blurPass(s,e,n,n,o)}_blurPass(e,t,n,i,s){let o=this._renderer,a=this._blurMaterial,l=this._lodMeshes[i];l.material=a;let c=a.uniforms;c.envMap.value=e.texture,c.sigma.value=s,c.mipInt.value=this._lodMax-n;let h=this._sizeLods[i],u=3*h*(i>this._lodMax-_o?i-this._lodMax+_o:0),d=4*(this._cubeSize-h);go(t,u,d,3*h,2*h),o.setRenderTarget(t),o.render(l,Fl)}};function fM(r){let e=[],t=[],n=r,i=r-_o+1+cM;for(let s=0;s2?0:-1,x=[y,b,0,y+2/3,b,0,y+2/3,b+1,0,y,b,0,y+2/3,b+1,0,y,b+1,0];p.set(x,f*d*m);for(let T=0;T_o&&n--}return{lodMeshes:t,sizeLods:e}}function Cg(r,e,t){let n=new Zt(r,e,t);return n.texture.mapping=Zs,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function go(r,e,t,n,i){r.viewport.set(e,t,n,i),r.scissor.set(e,t,n,i)}function pM(r,e,t){return new un({name:"PMREMGGXConvolution",defines:{GGX_SAMPLES:uM,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/t,CUBEUV_MAX_MIP:`${r}.0`},uniforms:{envMap:{value:null},roughness:{value:0},mipInt:{value:0}},vertexShader:cu(),fragmentShader:` + + precision highp float; + precision highp int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform float roughness; + uniform float mipInt; + + #define ENVMAP_TYPE_CUBE_UV + #include + + #define PI 3.14159265359 + + // Van der Corput radical inverse + float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 + } + + // Hammersley sequence + vec2 hammersley(uint i, uint N) { + return vec2(float(i) / float(N), radicalInverse_VdC(i)); + } + + // GGX VNDF importance sampling (Eric Heitz 2018) + // "Sampling the GGX Distribution of Visible Normals" + // https://jcgt.org/published/0007/04/01/ + vec3 importanceSampleGGX_VNDF(vec2 Xi, vec3 V, float roughness) { + float alpha = roughness * roughness; + + // Section 4.1: Orthonormal basis + vec3 T1 = vec3(1.0, 0.0, 0.0); + vec3 T2 = cross(V, T1); + + // Section 4.2: Parameterization of projected area + float r = sqrt(Xi.x); + float phi = 2.0 * PI * Xi.y; + float t1 = r * cos(phi); + float t2 = r * sin(phi); + float s = 0.5 * (1.0 + V.z); + t2 = (1.0 - s) * sqrt(1.0 - t1 * t1) + s * t2; + + // Section 4.3: Reprojection onto hemisphere + vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0, 1.0 - t1 * t1 - t2 * t2)) * V; + + // Section 3.4: Transform back to ellipsoid configuration + return normalize(vec3(alpha * Nh.x, alpha * Nh.y, max(0.0, Nh.z))); + } + + void main() { + vec3 N = normalize(vOutputDirection); + vec3 V = N; // Assume view direction equals normal for pre-filtering + + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + // For very low roughness, just sample the environment directly + if (roughness < 0.001) { + gl_FragColor = vec4(bilinearCubeUV(envMap, N, mipInt), 1.0); + return; + } + + // Tangent space basis for VNDF sampling + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + for(uint i = 0u; i < uint(GGX_SAMPLES); i++) { + vec2 Xi = hammersley(i, uint(GGX_SAMPLES)); + + // For PMREM, V = N, so in tangent space V is always (0, 0, 1) + vec3 H_tangent = importanceSampleGGX_VNDF(Xi, vec3(0.0, 0.0, 1.0), roughness); + + // Transform H back to world space + vec3 H = normalize(tangent * H_tangent.x + bitangent * H_tangent.y + N * H_tangent.z); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + + if(NdotL > 0.0) { + // Sample environment at fixed mip level + // VNDF importance sampling handles the distribution filtering + vec3 sampleColor = bilinearCubeUV(envMap, L, mipInt); + + // Weight by NdotL for the split-sum approximation + // VNDF PDF naturally accounts for the visible microfacet distribution + prefilteredColor += sampleColor * NdotL; + totalWeight += NdotL; + } + } + + if (totalWeight > 0.0) { + prefilteredColor = prefilteredColor / totalWeight; + } + + gl_FragColor = vec4(prefilteredColor, 1.0); + } + `,blending:ti,depthTest:!1,depthWrite:!1})}function mM(r,e,t){return new un({name:"SphericalGaussianBlur",defines:{SAMPLES:hM,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/t,CUBEUV_MAX_MIP:`${r}.0`},uniforms:{envMap:{value:null},sigma:{value:0},mipInt:{value:0}},vertexShader:cu(),fragmentShader:` + + precision highp float; + precision highp int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform float sigma; + uniform float mipInt; + + #define ENVMAP_TYPE_CUBE_UV + #include + + #define PI 3.14159265359 + #define GOLDEN_ANGLE 2.39996322973 + + void main() { + + if ( sigma == 0.0 ) { + + gl_FragColor = vec4( bilinearCubeUV( envMap, vOutputDirection, mipInt ), 1.0 ); + return; + + } + + vec3 outputDirection = normalize( vOutputDirection ); + + vec3 up = abs( outputDirection.z ) < 0.999 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 1.0, 0.0, 0.0 ); + vec3 tangent = normalize( cross( up, outputDirection ) ); + vec3 bitangent = cross( outputDirection, tangent ); + + // Truncate the kernel at three standard deviations or at the antipode. + float thetaMax = min( 3.0 * sigma, PI ); + float truncation = 1.0 - exp( - 0.5 * thetaMax * thetaMax / ( sigma * sigma ) ); + + vec3 accumColor = vec3( 0.0 ); + float accumWeight = 0.0; + + for ( int i = 0; i < SAMPLES; i ++ ) { + + // Stratified inverse-CDF sampling of the Gaussian, placed on a golden-angle spiral. + float stratum = ( float( i ) + 0.5 ) / float( SAMPLES ); + float theta = sigma * sqrt( - 2.0 * log( 1.0 - stratum * truncation ) ); + float phi = float( i ) * GOLDEN_ANGLE; + + vec3 offset = cos( phi ) * tangent + sin( phi ) * bitangent; + vec3 sampleDirection = cos( theta ) * outputDirection + sin( theta ) * offset; + + // Correct the planar sample density to solid angle. + float weight = sin( theta ) / theta; + + accumColor += weight * bilinearCubeUV( envMap, sampleDirection, mipInt ); + accumWeight += weight; + + } + + gl_FragColor = vec4( accumColor / accumWeight, 1.0 ); + + } + `,blending:ti,depthTest:!1,depthWrite:!1})}function Ig(){return new un({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:cu(),fragmentShader:` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + + #include + + void main() { + + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); + + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); + + } + `,blending:ti,depthTest:!1,depthWrite:!1})}function Pg(){return new un({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:cu(),fragmentShader:` + + precision mediump float; + precision mediump int; + + uniform float flipEnvMap; + + varying vec3 vOutputDirection; + + uniform samplerCube envMap; + + void main() { + + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); + + } + `,blending:ti,depthTest:!1,depthWrite:!1})}function cu(){return` + + precision mediump float; + precision mediump int; + + attribute vec3 outputDirection; + + varying vec3 vOutputDirection; + + void main() { + + vOutputDirection = outputDirection; + gl_Position = vec4( position, 1.0 ); + + } + `}var kl=class extends Zt{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;let n={width:e,height:e,depth:1},i=[n,n,n,n,n,n];this.texture=new ss(i),this._setTextureOptions(t),this.texture.isRenderTargetTexture=!0}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;let n={uniforms:{tEquirect:{value:null}},vertexShader:` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `,fragmentShader:` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + `},i=new ui(5,5,5),s=new un({name:"CubemapFromEquirect",uniforms:$s(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:qt,blending:ti});s.uniforms.tEquirect.value=t;let o=new rt(i,s),a=t.minFilter;return t.minFilter===vn&&(t.minFilter=pt),new Ga(1,10,this).update(e,o),t.minFilter=a,o.geometry.dispose(),o.material.dispose(),this}clear(e,t=!0,n=!0,i=!0){let s=e.getRenderTarget();for(let o=0;o<6;o++)e.setRenderTarget(this,o),e.clear(t,n,i);e.setRenderTarget(s)}};function gM(r){let e=new WeakMap,t=new WeakMap,n=null;function i(d,f=!1){return d==null?null:f?o(d):s(d)}function s(d){if(d&&d.isTexture){let f=d.mapping;if(f===io||f===so)if(e.has(d)){let p=e.get(d).texture;return a(p,d.mapping)}else{let p=d.image;if(p&&p.height>0){let _=new kl(p.height);return _.fromEquirectangularTexture(r,d),e.set(d,_),d.addEventListener("dispose",c),a(_.texture,d.mapping)}else return null}}return d}function o(d){if(d&&d.isTexture){let f=d.mapping,p=f===io||f===so,_=f===ni||f===Oi;if(p||_){let g=t.get(d),m=g!==void 0?g.texture.pmremVersion:0;if(d.isRenderTargetTexture&&d.pmremVersion!==m)return n===null&&(n=new zl(r)),g=p?n.fromEquirectangular(d,g):n.fromCubemap(d,g),g.texture.pmremVersion=d.pmremVersion,t.set(d,g),g.texture;if(g!==void 0)return g.texture;{let y=d.image;return p&&y&&y.height>0||_&&y&&l(y)?(n===null&&(n=new zl(r)),g=p?n.fromEquirectangular(d):n.fromCubemap(d),g.texture.pmremVersion=d.pmremVersion,t.set(d,g),d.addEventListener("dispose",h),g.texture):null}}}return d}function a(d,f){return f===io?d.mapping=ni:f===so&&(d.mapping=Oi),d}function l(d){let f=0,p=6;for(let _=0;_=65535?Pr:Ir)(d,1);g.version=_;let m=s.get(u);m&&e.remove(m),s.set(u,g)}function h(u){let d=s.get(u);if(d){let f=u.index;f!==null&&d.versione.maxTextureSize&&(T=Math.ceil(x/e.maxTextureSize),x=e.maxTextureSize);let S=new Float32Array(x*T*4*u),w=new ws(S,x,T,u);w.type=en,w.needsUpdate=!0;let v=b*4;for(let I=0;I + #include + + void main() { + gl_FragColor = texture2D( tDiffuse, vUv ); + + #ifdef LINEAR_TONE_MAPPING + gl_FragColor.rgb = LinearToneMapping( gl_FragColor.rgb ); + #elif defined( REINHARD_TONE_MAPPING ) + gl_FragColor.rgb = ReinhardToneMapping( gl_FragColor.rgb ); + #elif defined( CINEON_TONE_MAPPING ) + gl_FragColor.rgb = CineonToneMapping( gl_FragColor.rgb ); + #elif defined( ACES_FILMIC_TONE_MAPPING ) + gl_FragColor.rgb = ACESFilmicToneMapping( gl_FragColor.rgb ); + #elif defined( AGX_TONE_MAPPING ) + gl_FragColor.rgb = AgXToneMapping( gl_FragColor.rgb ); + #elif defined( NEUTRAL_TONE_MAPPING ) + gl_FragColor.rgb = NeutralToneMapping( gl_FragColor.rgb ); + #elif defined( CUSTOM_TONE_MAPPING ) + gl_FragColor.rgb = CustomToneMapping( gl_FragColor.rgb ); + #endif + + #ifdef SRGB_TRANSFER + gl_FragColor = sRGBTransferOETF( gl_FragColor ); + #endif + }`,depthTest:!1,depthWrite:!1}),u=new rt(c,h),d=new _i(-1,1,1,-1,0,1),f=null,p=null,_=!1,g,m=null,y=[],b=!1;this.setSize=function(x,T){o.setSize(x,T),a!==null&&a.setSize(x,T),l!==null&&l.setSize(x,T);for(let S=0;S0&&y[0].isRenderPass===!0;let T=o.width,S=o.height;y.length>0&&a===null&&(a=new Zt(T,S,{type:Bn,depthBuffer:!1,stencilBuffer:!1}),l=new Zt(T,S,{type:Bn,depthBuffer:!1,stencilBuffer:!1}));for(let w=0;w0)return r;let i=e*t,s=Lg[i];if(s===void 0&&(s=new Float32Array(i),Lg[i]=s),e!==0){n.toArray(s,0);for(let o=1,a=0;o!==e;++o)a+=t,r[o].toArray(s,a)}return s}function Vt(r,e){if(r.length!==e.length)return!1;for(let t=0,n=r.length;t0&&(this.seq=i.concat(s))}setValue(e,t,n,i){let s=this.map[t];s!==void 0&&s.setValue(e,n,i)}setOptional(e,t,n){let i=t[n];i!==void 0&&this.setValue(e,n,i)}static upload(e,t,n,i){for(let s=0,o=t.length;s!==o;++s){let a=t[s],l=n[a.id];l.needsUpdate!==!1&&a.setValue(e,l.value,i)}}static seqWithValue(e,t){let n=[];for(let i=0,s=e.length;i!==s;++i){let o=e[i];o.id in t&&n.push(o)}return n}};function Bg(r,e,t){let n=r.createShader(e);return r.shaderSource(n,t),r.compileShader(n),n}var dS=37297,fS=0;function pS(r,e){let t=r.split(` +`),n=[],i=Math.max(e-6,0),s=Math.min(e+6,t.length);for(let o=i;o":" "} ${a}: ${t[o]}`)}return n.join(` +`)}var zg=new qe;function mS(r){Je._getMatrix(zg,Je.workingColorSpace,r);let e=`mat3( ${zg.elements.map(t=>t.toFixed(4))} )`;switch(Je.getTransfer(r)){case Er:return[e,"LinearTransferOETF"];case ht:return[e,"sRGBTransferOETF"];default:return de("WebGLProgram: Unsupported color space: ",r),[e,"LinearTransferOETF"]}}function kg(r,e,t){let n=r.getShaderParameter(e,r.COMPILE_STATUS),s=(r.getShaderInfoLog(e)||"").trim();if(n&&s==="")return"";let o=/ERROR: 0:(\d+)/.exec(s);if(o){let a=parseInt(o[1]);return t.toUpperCase()+` + +`+s+` + +`+pS(r.getShaderSource(e),a)}else return s}function gS(r,e){let t=mS(e);return[`vec4 ${r}( vec4 value ) {`,` return ${t[1]}( vec4( value.rgb * ${t[0]}, value.a ) );`,"}"].join(` +`)}var _S={[Wh]:"Linear",[Xh]:"Reinhard",[qh]:"Cineon",[Yh]:"ACESFilmic",[Kh]:"AgX",[Jh]:"Neutral",[Zh]:"Custom"};function xS(r,e){let t=_S[e];return t===void 0?(de("WebGLProgram: Unsupported toneMapping:",e),"vec3 "+r+"( vec3 color ) { return LinearToneMapping( color ); }"):"vec3 "+r+"( vec3 color ) { return "+t+"ToneMapping( color ); }"}var lu=new R;function yS(){Je.getLuminanceCoefficients(lu);let r=lu.x.toFixed(4),e=lu.y.toFixed(4),t=lu.z.toFixed(4);return["float luminance( const in vec3 rgb ) {",` const vec3 weights = vec3( ${r}, ${e}, ${t} );`," return dot( weights, rgb );","}"].join(` +`)}function vS(r){return[r.extensionClipCullDistance?"#extension GL_ANGLE_clip_cull_distance : require":"",r.extensionMultiDraw?"#extension GL_ANGLE_multi_draw : require":""].filter(Bl).join(` +`)}function MS(r){let e=[];for(let t in r){let n=r[t];n!==!1&&e.push("#define "+t+" "+n)}return e.join(` +`)}function SS(r,e){let t={},n=r.getProgramParameter(e,r.ACTIVE_ATTRIBUTES);for(let i=0;i/gm;function xf(r){return r.replace(bS,AS)}var TS=new Map;function AS(r,e){let t=je[e];if(t===void 0){let n=TS.get(e);if(n!==void 0)t=je[n],de('WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',e,n);else throw new Error("THREE.WebGLProgram: Can not resolve #include <"+e+">")}return xf(t)}var ES=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Hg(r){return r.replace(ES,wS)}function wS(r,e,t,n){let i="";for(let s=parseInt(e);s0&&(g+=` +`),m=["#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,p].filter(Bl).join(` +`),m.length>0&&(m+=` +`)):(g=[Wg(t),"#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,p,t.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",t.batching?"#define USE_BATCHING":"",t.batchingColor?"#define USE_BATCHING_COLOR":"",t.instancing?"#define USE_INSTANCING":"",t.instancingColor?"#define USE_INSTANCING_COLOR":"",t.instancingMorph?"#define USE_INSTANCING_MORPH":"",t.useFog&&t.fog?"#define USE_FOG":"",t.useFog&&t.fogExp2?"#define FOG_EXP2":"",t.map?"#define USE_MAP":"",t.envMap?"#define USE_ENVMAP":"",t.envMap?"#define "+h:"",t.lightMap?"#define USE_LIGHTMAP":"",t.aoMap?"#define USE_AOMAP":"",t.bumpMap?"#define USE_BUMPMAP":"",t.normalMap?"#define USE_NORMALMAP":"",t.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",t.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",t.displacementMap?"#define USE_DISPLACEMENTMAP":"",t.emissiveMap?"#define USE_EMISSIVEMAP":"",t.anisotropy?"#define USE_ANISOTROPY":"",t.anisotropyMap?"#define USE_ANISOTROPYMAP":"",t.clearcoatMap?"#define USE_CLEARCOATMAP":"",t.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",t.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",t.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",t.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",t.specularMap?"#define USE_SPECULARMAP":"",t.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",t.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",t.roughnessMap?"#define USE_ROUGHNESSMAP":"",t.metalnessMap?"#define USE_METALNESSMAP":"",t.alphaMap?"#define USE_ALPHAMAP":"",t.alphaHash?"#define USE_ALPHAHASH":"",t.transmission?"#define USE_TRANSMISSION":"",t.transmissionMap?"#define USE_TRANSMISSIONMAP":"",t.thicknessMap?"#define USE_THICKNESSMAP":"",t.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",t.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",t.mapUv?"#define MAP_UV "+t.mapUv:"",t.alphaMapUv?"#define ALPHAMAP_UV "+t.alphaMapUv:"",t.lightMapUv?"#define LIGHTMAP_UV "+t.lightMapUv:"",t.aoMapUv?"#define AOMAP_UV "+t.aoMapUv:"",t.emissiveMapUv?"#define EMISSIVEMAP_UV "+t.emissiveMapUv:"",t.bumpMapUv?"#define BUMPMAP_UV "+t.bumpMapUv:"",t.normalMapUv?"#define NORMALMAP_UV "+t.normalMapUv:"",t.displacementMapUv?"#define DISPLACEMENTMAP_UV "+t.displacementMapUv:"",t.metalnessMapUv?"#define METALNESSMAP_UV "+t.metalnessMapUv:"",t.roughnessMapUv?"#define ROUGHNESSMAP_UV "+t.roughnessMapUv:"",t.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+t.anisotropyMapUv:"",t.clearcoatMapUv?"#define CLEARCOATMAP_UV "+t.clearcoatMapUv:"",t.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+t.clearcoatNormalMapUv:"",t.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+t.clearcoatRoughnessMapUv:"",t.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+t.iridescenceMapUv:"",t.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+t.iridescenceThicknessMapUv:"",t.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+t.sheenColorMapUv:"",t.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+t.sheenRoughnessMapUv:"",t.specularMapUv?"#define SPECULARMAP_UV "+t.specularMapUv:"",t.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+t.specularColorMapUv:"",t.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+t.specularIntensityMapUv:"",t.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+t.transmissionMapUv:"",t.thicknessMapUv?"#define THICKNESSMAP_UV "+t.thicknessMapUv:"",t.vertexTangents&&t.flatShading===!1?"#define USE_TANGENT":"",t.vertexNormals?"#define HAS_NORMAL":"",t.vertexColors?"#define USE_COLOR":"",t.vertexAlphas?"#define USE_COLOR_ALPHA":"",t.vertexUv1s?"#define USE_UV1":"",t.vertexUv2s?"#define USE_UV2":"",t.vertexUv3s?"#define USE_UV3":"",t.pointsUvs?"#define USE_POINTS_UV":"",t.flatShading?"#define FLAT_SHADED":"",t.skinning?"#define USE_SKINNING":"",t.morphTargets?"#define USE_MORPHTARGETS":"",t.morphNormals&&t.flatShading===!1?"#define USE_MORPHNORMALS":"",t.morphColors?"#define USE_MORPHCOLORS":"",t.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+t.morphTextureStride:"",t.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+t.morphTargetsCount:"",t.doubleSided?"#define DOUBLE_SIDED":"",t.flipSided?"#define FLIP_SIDED":"",t.shadowMapEnabled?"#define USE_SHADOWMAP":"",t.shadowMapEnabled?"#define "+l:"",t.sizeAttenuation?"#define USE_SIZEATTENUATION":"",t.numLightProbes>0?"#define USE_LIGHT_PROBES":"",t.logarithmicDepthBuffer?"#define USE_LOGARITHMIC_DEPTH_BUFFER":"",t.reversedDepthBuffer?"#define USE_REVERSED_DEPTH_BUFFER":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR"," attribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH"," uniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1"," attribute vec2 uv1;","#endif","#ifdef USE_UV2"," attribute vec2 uv2;","#endif","#ifdef USE_UV3"," attribute vec2 uv3;","#endif","#ifdef USE_TANGENT"," attribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )"," attribute vec4 color;","#elif defined( USE_COLOR )"," attribute vec3 color;","#endif","#ifdef USE_SKINNING"," attribute vec4 skinIndex;"," attribute vec4 skinWeight;","#endif",` +`].filter(Bl).join(` +`),m=[Wg(t),"#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,p,t.useFog&&t.fog?"#define USE_FOG":"",t.useFog&&t.fogExp2?"#define FOG_EXP2":"",t.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",t.map?"#define USE_MAP":"",t.matcap?"#define USE_MATCAP":"",t.envMap?"#define USE_ENVMAP":"",t.envMap?"#define "+c:"",t.envMap?"#define "+h:"",t.envMap?"#define "+u:"",d?"#define CUBEUV_TEXEL_WIDTH "+d.texelWidth:"",d?"#define CUBEUV_TEXEL_HEIGHT "+d.texelHeight:"",d?"#define CUBEUV_MAX_MIP "+d.maxMip+".0":"",t.lightMap?"#define USE_LIGHTMAP":"",t.aoMap?"#define USE_AOMAP":"",t.bumpMap?"#define USE_BUMPMAP":"",t.normalMap?"#define USE_NORMALMAP":"",t.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",t.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",t.packedNormalMap?"#define USE_PACKED_NORMALMAP":"",t.emissiveMap?"#define USE_EMISSIVEMAP":"",t.anisotropy?"#define USE_ANISOTROPY":"",t.anisotropyMap?"#define USE_ANISOTROPYMAP":"",t.clearcoat?"#define USE_CLEARCOAT":"",t.clearcoatMap?"#define USE_CLEARCOATMAP":"",t.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",t.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",t.dispersion?"#define USE_DISPERSION":"",t.retroreflection?"#define USE_RETROREFLECTION":"",t.iridescence?"#define USE_IRIDESCENCE":"",t.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",t.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",t.specularMap?"#define USE_SPECULARMAP":"",t.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",t.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",t.roughnessMap?"#define USE_ROUGHNESSMAP":"",t.metalnessMap?"#define USE_METALNESSMAP":"",t.alphaMap?"#define USE_ALPHAMAP":"",t.alphaTest?"#define USE_ALPHATEST":"",t.alphaHash?"#define USE_ALPHAHASH":"",t.sheen?"#define USE_SHEEN":"",t.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",t.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",t.transmission?"#define USE_TRANSMISSION":"",t.transmissionMap?"#define USE_TRANSMISSIONMAP":"",t.thicknessMap?"#define USE_THICKNESSMAP":"",t.vertexTangents&&t.flatShading===!1?"#define USE_TANGENT":"",t.vertexColors||t.instancingColor?"#define USE_COLOR":"",t.vertexAlphas||t.batchingColor?"#define USE_COLOR_ALPHA":"",t.vertexUv1s?"#define USE_UV1":"",t.vertexUv2s?"#define USE_UV2":"",t.vertexUv3s?"#define USE_UV3":"",t.pointsUvs?"#define USE_POINTS_UV":"",t.gradientMap?"#define USE_GRADIENTMAP":"",t.flatShading?"#define FLAT_SHADED":"",t.doubleSided?"#define DOUBLE_SIDED":"",t.flipSided?"#define FLIP_SIDED":"",t.shadowMapEnabled?"#define USE_SHADOWMAP":"",t.shadowMapEnabled?"#define "+l:"",t.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",t.numLightProbes>0?"#define USE_LIGHT_PROBES":"",t.numLightProbeGrids>0?"#define USE_LIGHT_PROBES_GRID":"",t.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",t.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",t.logarithmicDepthBuffer?"#define USE_LOGARITHMIC_DEPTH_BUFFER":"",t.reversedDepthBuffer?"#define USE_REVERSED_DEPTH_BUFFER":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",t.toneMapping!==On?"#define TONE_MAPPING":"",t.toneMapping!==On?je.tonemapping_pars_fragment:"",t.toneMapping!==On?xS("toneMapping",t.toneMapping):"",t.dithering?"#define DITHERING":"",t.opaque?"#define OPAQUE":"",je.colorspace_pars_fragment,gS("linearToOutputTexel",t.outputColorSpace),yS(),t.useDepthPacking?"#define DEPTH_PACKING "+t.depthPacking:"",` +`].filter(Bl).join(` +`)),o=xf(o),o=Vg(o,t),o=Gg(o,t),a=xf(a),a=Vg(a,t),a=Gg(a,t),o=Hg(o),a=Hg(a),t.isRawShaderMaterial!==!0&&(y=`#version 300 es +`,g=[f,"#define attribute in","#define varying out","#define texture2D texture"].join(` +`)+` +`+g,m=["#define varying in",t.glslVersion===ru?"":"layout(location = 0) out highp vec4 pc_fragColor;",t.glslVersion===ru?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join(` +`)+` +`+m);let b=y+g+o,x=y+m+a,T=Bg(i,i.VERTEX_SHADER,b),S=Bg(i,i.FRAGMENT_SHADER,x);i.attachShader(_,T),i.attachShader(_,S),t.index0AttributeName!==void 0?i.bindAttribLocation(_,0,t.index0AttributeName):t.hasPositionAttribute===!0&&i.bindAttribLocation(_,0,"position"),i.linkProgram(_);function w(P){if(r.debug.checkShaderErrors){let F=i.getProgramInfoLog(_)||"",z=i.getShaderInfoLog(T)||"",N=i.getShaderInfoLog(S)||"",B=F.trim(),H=z.trim(),X=N.trim(),ie=!0,q=!0;if(i.getProgramParameter(_,i.LINK_STATUS)===!1)if(ie=!1,typeof r.debug.onShaderError=="function")r.debug.onShaderError(i,_,T,S);else{let Q=kg(i,T,"vertex"),ne=kg(i,S,"fragment");Pe("WebGLProgram: Shader Error "+i.getError()+" - VALIDATE_STATUS "+i.getProgramParameter(_,i.VALIDATE_STATUS)+` + +Material Name: `+P.name+` +Material Type: `+P.type+` + +Program Info Log: `+B+` +`+Q+` +`+ne)}else B!==""?de("WebGLProgram: Program Info Log:",B):(H===""||X==="")&&(q=!1);q&&(P.diagnostics={runnable:ie,programLog:B,vertexShader:{log:H,prefix:g},fragmentShader:{log:X,prefix:m}})}i.deleteShader(T),i.deleteShader(S),v=new xo(i,_),E=SS(i,_)}let v;this.getUniforms=function(){return v===void 0&&w(this),v};let E;this.getAttributes=function(){return E===void 0&&w(this),E};let I=t.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return I===!1&&(I=i.getProgramParameter(_,dS)),I},this.destroy=function(){n.releaseStatesOfProgram(this),i.deleteProgram(_),this.program=void 0},this.type=t.shaderType,this.name=t.shaderName,this.id=fS++,this.cacheKey=e,this.usedTimes=1,this.program=_,this.vertexShader=T,this.fragmentShader=S,this}var BS=0,yf=class{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(e,t,n){let i=this._getShaderCacheForMaterial(e);return i.has(t)===!1&&(i.add(t),t.usedTimes++),i.has(n)===!1&&(i.add(n),n.usedTimes++),this}remove(e){let t=this.materialCache.get(e);for(let n of t)n.usedTimes--,n.usedTimes===0&&this.shaderCache.delete(n.code);return this.materialCache.delete(e),this}getVertexShaderStage(e){return this._getShaderStage(e.vertexShader)}getFragmentShaderStage(e){return this._getShaderStage(e.fragmentShader)}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(e){let t=this.materialCache,n=t.get(e);return n===void 0&&(n=new Set,t.set(e,n)),n}_getShaderStage(e){let t=this.shaderCache,n=t.get(e);return n===void 0&&(n=new vf(e),t.set(e,n)),n}},vf=class{constructor(e){this.id=BS++,this.code=e,this.usedTimes=0}};function zS(r){return r===ki||r===uo||r===fo}function kS(r,e,t,n,i,s){let o=new Cs,a=new yf,l=new Set,c=[],h=new Map,u=n.logarithmicDepthBuffer,d=n.precision,f={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distance",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function p(v){return l.add(v),v===0?"uv":`uv${v}`}function _(v,E,I,P,F,z){let N=P.fog,B=F.geometry,H=v.isMeshStandardMaterial||v.isMeshLambertMaterial||v.isMeshPhongMaterial?P.environment:null,X=v.isMeshStandardMaterial||v.isMeshLambertMaterial&&!v.envMap||v.isMeshPhongMaterial&&!v.envMap,ie=e.get(v.envMap||H,X),q=ie&&ie.mapping===Zs?ie.image.height:null,Q=f[v.type];v.precision!==null&&(d=n.getMaxPrecision(v.precision),d!==v.precision&&de("WebGLProgram.getParameters:",v.precision,"not supported, using",d,"instead."));let ne=B.morphAttributes.position||B.morphAttributes.normal||B.morphAttributes.color,Ne=ne!==void 0?ne.length:0,we=0;B.morphAttributes.position!==void 0&&(we=1),B.morphAttributes.normal!==void 0&&(we=2),B.morphAttributes.color!==void 0&&(we=3);let ct,tt,ot,K;if(Q){let Mt=ii[Q];ct=Mt.vertexShader,tt=Mt.fragmentShader}else{ct=v.vertexShader,tt=v.fragmentShader;let Mt=a.getVertexShaderStage(v),dt=a.getFragmentShaderStage(v);a.update(v,Mt,dt),ot=Mt.id,K=dt.id}let ee=r.getRenderTarget(),ve=r.state.buffers.depth.getReversed(),Ge=F.isInstancedMesh===!0,Te=F.isBatchedMesh===!0,We=!!v.map,gt=!!v.matcap,te=!!ie,re=!!v.aoMap,oe=!!v.lightMap,ae=!!v.bumpMap&&v.wireframe===!1,ue=!!v.normalMap,ke=!!v.displacementMap,Be=!!v.emissiveMap,Xe=!!v.metalnessMap,Ye=!!v.roughnessMap,L=v.anisotropy>0,ut=v.clearcoat>0,nt=v.dispersion>0,C=v.retroreflectivity>0,M=v.iridescence>0,O=v.sheen>0,G=v.transmission>0,Y=L&&!!v.anisotropyMap,le=ut&&!!v.clearcoatMap,he=ut&&!!v.clearcoatNormalMap,Z=ut&&!!v.clearcoatRoughnessMap,$=M&&!!v.iridescenceMap,pe=M&&!!v.iridescenceThicknessMap,De=O&&!!v.sheenColorMap,ye=O&&!!v.sheenRoughnessMap,me=!!v.specularMap,Ue=!!v.specularColorMap,Ve=!!v.specularIntensityMap,Ze=G&&!!v.transmissionMap,U=G&&!!v.thicknessMap,ge=!!v.gradientMap,j=!!v.alphaMap,_e=v.alphaTest>0,be=!!v.alphaHash,se=!!v.extensions,Fe=On;v.toneMapped&&(ee===null||ee.isXRRenderTarget===!0)&&(Fe=r.toneMapping);let Ie={shaderID:Q,shaderType:v.type,shaderName:v.name,vertexShader:ct,fragmentShader:tt,defines:v.defines,customVertexShaderID:ot,customFragmentShaderID:K,isRawShaderMaterial:v.isRawShaderMaterial===!0,glslVersion:v.glslVersion,precision:d,batching:Te,batchingColor:Te&&F._colorsTexture!==null,instancing:Ge,instancingColor:Ge&&F.instanceColor!==null,instancingMorph:Ge&&F.morphTexture!==null,outputColorSpace:ee===null?r.outputColorSpace:ee.isXRRenderTarget===!0?ee.texture.colorSpace:Je.workingColorSpace,alphaToCoverage:!!v.alphaToCoverage,map:We,matcap:gt,envMap:te,envMapMode:te&&ie.mapping,envMapCubeUVHeight:q,aoMap:re,lightMap:oe,bumpMap:ae,normalMap:ue,displacementMap:ke,emissiveMap:Be,normalMapObjectSpace:ue&&v.normalMapType===Xd,normalMapTangentSpace:ue&&v.normalMapType===xi,packedNormalMap:ue&&v.normalMapType===xi&&zS(v.normalMap.format),metalnessMap:Xe,roughnessMap:Ye,anisotropy:L,anisotropyMap:Y,clearcoat:ut,clearcoatMap:le,clearcoatNormalMap:he,clearcoatRoughnessMap:Z,dispersion:nt,retroreflection:C,iridescence:M,iridescenceMap:$,iridescenceThicknessMap:pe,sheen:O,sheenColorMap:De,sheenRoughnessMap:ye,specularMap:me,specularColorMap:Ue,specularIntensityMap:Ve,transmission:G,transmissionMap:Ze,thicknessMap:U,gradientMap:ge,opaque:v.transparent===!1&&v.blending===Ys&&v.alphaToCoverage===!1,alphaMap:j,alphaTest:_e,alphaHash:be,combine:v.combine,mapUv:We&&p(v.map.channel),aoMapUv:re&&p(v.aoMap.channel),lightMapUv:oe&&p(v.lightMap.channel),bumpMapUv:ae&&p(v.bumpMap.channel),normalMapUv:ue&&p(v.normalMap.channel),displacementMapUv:ke&&p(v.displacementMap.channel),emissiveMapUv:Be&&p(v.emissiveMap.channel),metalnessMapUv:Xe&&p(v.metalnessMap.channel),roughnessMapUv:Ye&&p(v.roughnessMap.channel),anisotropyMapUv:Y&&p(v.anisotropyMap.channel),clearcoatMapUv:le&&p(v.clearcoatMap.channel),clearcoatNormalMapUv:he&&p(v.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:Z&&p(v.clearcoatRoughnessMap.channel),iridescenceMapUv:$&&p(v.iridescenceMap.channel),iridescenceThicknessMapUv:pe&&p(v.iridescenceThicknessMap.channel),sheenColorMapUv:De&&p(v.sheenColorMap.channel),sheenRoughnessMapUv:ye&&p(v.sheenRoughnessMap.channel),specularMapUv:me&&p(v.specularMap.channel),specularColorMapUv:Ue&&p(v.specularColorMap.channel),specularIntensityMapUv:Ve&&p(v.specularIntensityMap.channel),transmissionMapUv:Ze&&p(v.transmissionMap.channel),thicknessMapUv:U&&p(v.thicknessMap.channel),alphaMapUv:j&&p(v.alphaMap.channel),vertexTangents:!!B.attributes.tangent&&(ue||L),vertexNormals:!!B.attributes.normal,vertexColors:v.vertexColors,vertexAlphas:v.vertexColors===!0&&!!B.attributes.color&&B.attributes.color.itemSize===4,pointsUvs:F.isPoints===!0&&!!B.attributes.uv&&(We||j),fog:!!N,useFog:v.fog===!0,fogExp2:!!N&&N.isFogExp2,flatShading:v.wireframe===!1&&(v.flatShading===!0||B.attributes.normal===void 0&&ue===!1&&(v.isMeshLambertMaterial||v.isMeshPhongMaterial||v.isMeshStandardMaterial||v.isMeshPhysicalMaterial)),sizeAttenuation:v.sizeAttenuation===!0,logarithmicDepthBuffer:u,reversedDepthBuffer:ve,skinning:F.isSkinnedMesh===!0,hasPositionAttribute:B.attributes.position!==void 0,morphTargets:B.morphAttributes.position!==void 0,morphNormals:B.morphAttributes.normal!==void 0,morphColors:B.morphAttributes.color!==void 0,morphTargetsCount:Ne,morphTextureStride:we,numSunLights:E.sun.length,numDirLights:E.directional.length,numPointLights:E.point.length,numSpotLights:E.spot.length,numSpotLightMaps:E.spotLightMap.length,numRectAreaLights:E.rectArea.length,numHemiLights:E.hemi.length,numSunLightShadows:E.sunShadowMap.length,numDirLightShadows:E.directionalShadowMap.length,numPointLightShadows:E.pointShadowMap.length,numSpotLightShadows:E.spotShadowMap.length,numSpotLightShadowsWithMaps:E.numSpotLightShadowsWithMaps,numLightProbes:E.numLightProbes,numLightProbeGrids:z.length,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:v.dithering,shadowMapEnabled:r.shadowMap.enabled&&I.length>0,shadowMapType:r.shadowMap.type,toneMapping:Fe,decodeVideoTexture:We&&v.map.isVideoTexture===!0&&Je.getTransfer(v.map.colorSpace)===ht,decodeVideoTextureEmissive:Be&&v.emissiveMap.isVideoTexture===!0&&Je.getTransfer(v.emissiveMap.colorSpace)===ht,premultipliedAlpha:v.premultipliedAlpha,doubleSided:v.side===Rn,flipSided:v.side===qt,useDepthPacking:v.depthPacking>=0,depthPacking:v.depthPacking||0,index0AttributeName:v.index0AttributeName,extensionClipCullDistance:se&&v.extensions.clipCullDistance===!0&&t.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(se&&v.extensions.multiDraw===!0||Te)&&t.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:t.has("KHR_parallel_shader_compile"),customProgramCacheKey:v.customProgramCacheKey()};return Ie.vertexUv1s=l.has(1),Ie.vertexUv2s=l.has(2),Ie.vertexUv3s=l.has(3),l.clear(),Ie}function g(v){let E=[];if(v.shaderID?E.push(v.shaderID):(E.push(v.customVertexShaderID),E.push(v.customFragmentShaderID)),v.defines!==void 0)for(let I in v.defines)E.push(I),E.push(v.defines[I]);return v.isRawShaderMaterial===!1&&(m(E,v),y(E,v),E.push(r.outputColorSpace)),E.push(v.customProgramCacheKey),E.join()}function m(v,E){v.push(E.precision),v.push(E.outputColorSpace),v.push(E.envMapMode),v.push(E.envMapCubeUVHeight),v.push(E.mapUv),v.push(E.alphaMapUv),v.push(E.lightMapUv),v.push(E.aoMapUv),v.push(E.bumpMapUv),v.push(E.normalMapUv),v.push(E.displacementMapUv),v.push(E.emissiveMapUv),v.push(E.metalnessMapUv),v.push(E.roughnessMapUv),v.push(E.anisotropyMapUv),v.push(E.clearcoatMapUv),v.push(E.clearcoatNormalMapUv),v.push(E.clearcoatRoughnessMapUv),v.push(E.iridescenceMapUv),v.push(E.iridescenceThicknessMapUv),v.push(E.sheenColorMapUv),v.push(E.sheenRoughnessMapUv),v.push(E.specularMapUv),v.push(E.specularColorMapUv),v.push(E.specularIntensityMapUv),v.push(E.transmissionMapUv),v.push(E.thicknessMapUv),v.push(E.combine),v.push(E.fogExp2),v.push(E.sizeAttenuation),v.push(E.morphTargetsCount),v.push(E.morphAttributeCount),v.push(E.numSunLights),v.push(E.numDirLights),v.push(E.numPointLights),v.push(E.numSpotLights),v.push(E.numSpotLightMaps),v.push(E.numHemiLights),v.push(E.numRectAreaLights),v.push(E.numSunLightShadows),v.push(E.numDirLightShadows),v.push(E.numPointLightShadows),v.push(E.numSpotLightShadows),v.push(E.numSpotLightShadowsWithMaps),v.push(E.numLightProbes),v.push(E.shadowMapType),v.push(E.toneMapping),v.push(E.numClippingPlanes),v.push(E.numClipIntersection),v.push(E.depthPacking)}function y(v,E){o.disableAll(),E.instancing&&o.enable(0),E.instancingColor&&o.enable(1),E.instancingMorph&&o.enable(2),E.matcap&&o.enable(3),E.envMap&&o.enable(4),E.normalMapObjectSpace&&o.enable(5),E.normalMapTangentSpace&&o.enable(6),E.clearcoat&&o.enable(7),E.iridescence&&o.enable(8),E.alphaTest&&o.enable(9),E.vertexColors&&o.enable(10),E.vertexAlphas&&o.enable(11),E.vertexUv1s&&o.enable(12),E.vertexUv2s&&o.enable(13),E.vertexUv3s&&o.enable(14),E.vertexTangents&&o.enable(15),E.anisotropy&&o.enable(16),E.alphaHash&&o.enable(17),E.batching&&o.enable(18),E.dispersion&&o.enable(19),E.retroreflection&&o.enable(24),E.batchingColor&&o.enable(20),E.gradientMap&&o.enable(21),E.packedNormalMap&&o.enable(22),E.vertexNormals&&o.enable(23),v.push(o.mask),o.disableAll(),E.fog&&o.enable(0),E.useFog&&o.enable(1),E.flatShading&&o.enable(2),E.logarithmicDepthBuffer&&o.enable(3),E.reversedDepthBuffer&&o.enable(4),E.skinning&&o.enable(5),E.morphTargets&&o.enable(6),E.morphNormals&&o.enable(7),E.morphColors&&o.enable(8),E.premultipliedAlpha&&o.enable(9),E.shadowMapEnabled&&o.enable(10),E.doubleSided&&o.enable(11),E.flipSided&&o.enable(12),E.useDepthPacking&&o.enable(13),E.dithering&&o.enable(14),E.transmission&&o.enable(15),E.sheen&&o.enable(16),E.opaque&&o.enable(17),E.pointsUvs&&o.enable(18),E.decodeVideoTexture&&o.enable(19),E.decodeVideoTextureEmissive&&o.enable(20),E.alphaToCoverage&&o.enable(21),E.numLightProbeGrids>0&&o.enable(22),E.hasPositionAttribute&&o.enable(23),v.push(o.mask)}function b(v){let E=f[v.type],I;if(E){let P=ii[E];I=sf.clone(P.uniforms)}else I=v.uniforms;return I}function x(v,E){let I=h.get(E);return I!==void 0?++I.usedTimes:(I=new OS(r,E,v,i),c.push(I),h.set(E,I)),I}function T(v){if(--v.usedTimes===0){let E=c.indexOf(v);c[E]=c[c.length-1],c.pop(),h.delete(v.cacheKey),v.destroy()}}function S(v){a.remove(v)}function w(){a.dispose()}return{getParameters:_,getProgramCacheKey:g,getUniforms:b,acquireProgram:x,releaseProgram:T,releaseShaderCache:S,programs:c,dispose:w}}function VS(){let r=new WeakMap;function e(o){return r.has(o)}function t(o){let a=r.get(o);return a===void 0&&(a={},r.set(o,a)),a}function n(o){r.delete(o)}function i(o,a,l){r.get(o)[a]=l}function s(){r=new WeakMap}return{has:e,get:t,remove:n,update:i,dispose:s}}function GS(r,e){return r.groupOrder!==e.groupOrder?r.groupOrder-e.groupOrder:r.renderOrder!==e.renderOrder?r.renderOrder-e.renderOrder:r.material.id!==e.material.id?r.material.id-e.material.id:r.materialVariant!==e.materialVariant?r.materialVariant-e.materialVariant:r.z!==e.z?r.z-e.z:r.id-e.id}function Xg(r,e){return r.groupOrder!==e.groupOrder?r.groupOrder-e.groupOrder:r.renderOrder!==e.renderOrder?r.renderOrder-e.renderOrder:r.z!==e.z?e.z-r.z:r.id-e.id}function qg(){let r=[],e=0,t=[],n=[],i=[];function s(){e=0,t.length=0,n.length=0,i.length=0}function o(d){let f=0;return d.isInstancedMesh&&(f+=2),d.isSkinnedMesh&&(f+=1),f}function a(d,f,p,_,g,m){let y=r[e];return y===void 0?(y={id:d.id,object:d,geometry:f,material:p,materialVariant:o(d),groupOrder:_,renderOrder:d.renderOrder,z:g,group:m},r[e]=y):(y.id=d.id,y.object=d,y.geometry=f,y.material=p,y.materialVariant=o(d),y.groupOrder=_,y.renderOrder=d.renderOrder,y.z=g,y.group=m),e++,y}function l(d,f,p,_,g,m,y){y.reversedDepth===!0&&(g=-g);let b=a(d,f,p,_,g,m);p.transmission>0?n.push(b):p.transparent===!0?i.push(b):t.push(b)}function c(d,f,p,_,g,m){let y=a(d,f,p,_,g,m);p.transmission>0?n.unshift(y):p.transparent===!0?i.unshift(y):t.unshift(y)}function h(d,f){t.length>1&&t.sort(d||GS),n.length>1&&n.sort(f||Xg),i.length>1&&i.sort(f||Xg)}function u(){for(let d=e,f=r.length;d=s.length?(o=new qg,s.push(o)):o=s[i],o}function t(){r=new WeakMap}return{get:e,dispose:t}}function WS(){let r={};return{get:function(e){if(r[e.id]!==void 0)return r[e.id];let t;switch(e.type){case"SunLight":case"DirectionalLight":t={direction:new R,color:new ce};break;case"SpotLight":t={position:new R,direction:new R,color:new ce,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":t={position:new R,color:new ce,distance:0,decay:0};break;case"HemisphereLight":t={direction:new R,skyColor:new ce,groundColor:new ce};break;case"RectAreaLight":t={color:new ce,position:new R,halfWidth:new R,halfHeight:new R};break}return r[e.id]=t,t}}}function XS(){let r={};return{get:function(e){if(r[e.id]!==void 0)return r[e.id];let t;switch(e.type){case"SunLight":case"DirectionalLight":t={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new J};break;case"SpotLight":t={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new J};break;case"PointLight":t={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new J,shadowCameraNear:1,shadowCameraFar:1e3};break}return r[e.id]=t,t}}}var qS=0;function YS(r,e){return(e.castShadow?2:0)-(r.castShadow?2:0)+(e.map?1:0)-(r.map?1:0)}function ZS(r){let e=new WS,t=XS(),n={version:0,hash:{sunLength:-1,directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numSunShadows:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],sun:[],sunShadow:[],sunShadowMap:[],sunShadowMatrix:[],sunShadowCascade:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let c=0;c<9;c++)n.probe.push(new R);let i=new R,s=new ze,o=new ze;function a(c){let h=0,u=0,d=0;for(let F=0;F<9;F++)n.probe[F].set(0,0,0);let f=0,p=0,_=0,g=0,m=0,y=0,b=0,x=0,T=0,S=0,w=0,v=0,E=0,I=0;c.sort(YS);for(let F=0,z=c.length;F0&&(r.has("OES_texture_float_linear")===!0?(n.rectAreaLTC1=xe.LTC_FLOAT_1,n.rectAreaLTC2=xe.LTC_FLOAT_2):(n.rectAreaLTC1=xe.LTC_HALF_1,n.rectAreaLTC2=xe.LTC_HALF_2)),n.ambient[0]=h,n.ambient[1]=u,n.ambient[2]=d;let P=n.hash;(P.sunLength!==f||P.directionalLength!==g||P.pointLength!==m||P.spotLength!==y||P.rectAreaLength!==b||P.hemiLength!==x||P.numSunShadows!==p||P.numDirectionalShadows!==T||P.numPointShadows!==S||P.numSpotShadows!==w||P.numSpotMaps!==v||P.numLightProbes!==I)&&(n.sun.length=f,n.directional.length=g,n.spot.length=y,n.rectArea.length=b,n.point.length=m,n.hemi.length=x,n.sunShadow.length=p,n.sunShadowMap.length=p,n.sunShadowMatrix.length=_,n.sunShadowCascade.length=_,n.directionalShadow.length=T,n.directionalShadowMap.length=T,n.directionalShadowMatrix.length=T,n.pointShadow.length=S,n.pointShadowMap.length=S,n.pointShadowMatrix.length=S,n.spotShadow.length=w,n.spotShadowMap.length=w,n.spotLightMatrix.length=w+v-E,n.spotLightMap.length=v,n.numSpotLightShadowsWithMaps=E,n.numLightProbes=I,P.sunLength=f,P.directionalLength=g,P.pointLength=m,P.spotLength=y,P.rectAreaLength=b,P.hemiLength=x,P.numSunShadows=p,P.numDirectionalShadows=T,P.numPointShadows=S,P.numSpotShadows=w,P.numSpotMaps=v,P.numLightProbes=I,n.version=qS++)}function l(c,h){let u=0,d=0,f=0,p=0,_=0,g=0,m=h.matrixWorldInverse;for(let y=0,b=c.length;y=o.length?(a=new Yg(r),o.push(a)):a=o[s],a}function n(){e=new WeakMap}return{get:t,dispose:n}}var JS=`void main() { + gl_Position = vec4( position, 1.0 ); +}`,jS=`uniform sampler2D shadow_pass; +uniform vec2 resolution; +uniform float radius; +void main() { + const float samples = float( VSM_SAMPLES ); + float mean = 0.0; + float squared_mean = 0.0; + float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 ); + float uvStart = samples <= 1.0 ? 0.0 : - 1.0; + for ( float i = 0.0; i < samples; i ++ ) { + float uvOffset = uvStart + i * uvStride; + #ifdef HORIZONTAL_PASS + vec2 distribution = texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ).rg; + mean += distribution.x; + squared_mean += distribution.y * distribution.y + distribution.x * distribution.x; + #else + float depth = texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ).r; + mean += depth; + squared_mean += depth * depth; + #endif + } + mean = mean / samples; + squared_mean = squared_mean / samples; + float std_dev = sqrt( max( 0.0, squared_mean - mean * mean ) ); + gl_FragColor = vec4( mean, std_dev, 0.0, 1.0 ); +}`,$S=[new R(1,0,0),new R(-1,0,0),new R(0,1,0),new R(0,-1,0),new R(0,0,1),new R(0,0,-1)],QS=[new R(0,-1,0),new R(0,-1,0),new R(0,0,1),new R(0,0,-1),new R(0,-1,0),new R(0,-1,0)],Zg=new ze,Ol=new R,ff=new R;function eb(r,e,t){let n=new hi,i=new J,s=new J,o=new mt,a=new Xr,l=new qr,c={},h=t.maxTextureSize,u={[ei]:qt,[qt]:ei,[Rn]:Rn},d=new un({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new J},radius:{value:4}},vertexShader:JS,fragmentShader:jS}),f=d.clone();f.defines.HORIZONTAL_PASS=1;let p=new Oe;p.setAttribute("position",new Qe(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));let _=new rt(p,d),g=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=to;let m=this.type;this.render=function(S,w,v){if(g.enabled===!1||g.autoUpdate===!1&&g.needsUpdate===!1||S.length===0)return;this.type===yd&&(de("WebGLShadowMap: PCFSoftShadowMap has been removed. Using PCFShadowMap instead."),this.type=to);let E=r.getRenderTarget(),I=r.getActiveCubeFace(),P=r.getActiveMipmapLevel(),F=r.state;F.setBlending(ti),F.buffers.depth.getReversed()===!0?F.buffers.color.setClear(0,0,0,0):F.buffers.color.setClear(1,1,1,1),F.buffers.depth.setTest(!0),F.setScissorTest(!1);let z=m!==this.type;z&&w.traverse(function(N){N.material&&(Array.isArray(N.material)?N.material.forEach(B=>B.needsUpdate=!0):N.material.needsUpdate=!0)});for(let N=0,B=S.length;Nh||i.y>h)&&(i.x>h&&(s.x=Math.floor(h/ie.x),i.x=s.x*ie.x,X.mapSize.x=s.x),i.y>h&&(s.y=Math.floor(h/ie.y),i.y=s.y*ie.y,X.mapSize.y=s.y));let q=r.state.buffers.depth.getReversed();if(X.camera._reversedDepth=q,X.map===null||z===!0){if(X.map!==null&&(X.map.depthTexture!==null&&(X.map.depthTexture.dispose(),X.map.depthTexture=null),X.map.dispose()),this.type===qs){if(H.isPointLight){de("WebGLShadowMap: VSM shadow maps are not supported for PointLights. Use PCF or BasicShadowMap instead.");continue}X.map=new Zt(i.x,i.y,{format:ki,type:Bn,minFilter:pt,magFilter:pt,generateMipmaps:!1}),X.map.texture.name=H.name+".shadowMap",X.map.depthTexture=new Pi(i.x,i.y,en),X.map.depthTexture.name=H.name+".shadowMapDepth",X.map.depthTexture.format=Zn,X.map.depthTexture.compareFunction=null,X.map.depthTexture.minFilter=At,X.map.depthTexture.magFilter=At}else H.isPointLight?(X.map=new kl(i.x),X.map.depthTexture=new ia(i.x,Cn)):(X.map=new Zt(i.x,i.y),X.map.depthTexture=new Pi(i.x,i.y,Cn)),X.map.depthTexture.name=H.name+".shadowMap",X.map.depthTexture.format=Zn,this.type===to?(X.map.depthTexture.compareFunction=q?Dl:Nl,X.map.depthTexture.minFilter=pt,X.map.depthTexture.magFilter=pt):(X.map.depthTexture.compareFunction=null,X.map.depthTexture.minFilter=At,X.map.depthTexture.magFilter=At);X.camera.updateProjectionMatrix()}X.map.isWebGLCubeRenderTarget!==!0&&(X.map.width!==i.x||X.map.height!==i.y)&&X.map.setSize(i.x,i.y);let Q=X.map.isWebGLCubeRenderTarget?6:X.getViewportCount();H.isPointLight!==!0&&X.updateMatrices(H,v);for(let ne=0;ne0||w.map&&w.alphaTest>0||w.alphaToCoverage===!0){let F=I.uuid,z=w.uuid,N=c[F];N===void 0&&(N={},c[F]=N);let B=N[z];B===void 0&&(B=I.clone(),N[z]=B,w.addEventListener("dispose",T)),I=B}if(I.visible=w.visible,I.wireframe=w.wireframe,E===qs?I.side=w.shadowSide!==null?w.shadowSide:w.side:I.side=w.shadowSide!==null?w.shadowSide:u[w.side],I.alphaMap=w.alphaMap,I.alphaTest=w.alphaToCoverage===!0?.5:w.alphaTest,I.map=w.map,I.clipShadows=w.clipShadows,I.clippingPlanes=w.clippingPlanes,I.clipIntersection=w.clipIntersection,I.displacementMap=w.displacementMap,I.displacementScale=w.displacementScale,I.displacementBias=w.displacementBias,I.wireframeLinewidth=w.wireframeLinewidth,I.linewidth=w.linewidth,v.isPointLight===!0&&I.isMeshDistanceMaterial===!0){let F=r.properties.get(I);F.light=v}return I}function x(S,w,v,E,I){if(S.visible===!1)return;if(S.layers.test(w.layers)&&(S.isMesh||S.isLine||S.isPoints)&&(S.castShadow||S.receiveShadow&&I===qs)&&(!S.frustumCulled||S.intersectsFrustum(n))){S.modelViewMatrix.multiplyMatrices(v.matrixWorldInverse,S.matrixWorld);let z=e.update(S),N=S.material;if(Array.isArray(N)){let B=z.groups;for(let H=0,X=B.length;H=1):q.indexOf("OpenGL ES")!==-1&&(ie=parseFloat(/^OpenGL ES (\d)/.exec(q)[1]),X=ie>=2);let Q=null,ne={},Ne=r.getParameter(r.SCISSOR_BOX),we=r.getParameter(r.VIEWPORT),ct=new mt().fromArray(Ne),tt=new mt().fromArray(we);function ot(U,ge,j,_e){let be=new Uint8Array(4),se=r.createTexture();r.bindTexture(U,se),r.texParameteri(U,r.TEXTURE_MIN_FILTER,r.NEAREST),r.texParameteri(U,r.TEXTURE_MAG_FILTER,r.NEAREST);for(let Fe=0;Fe"u"?!1:/OculusBrowser/g.test(navigator.userAgent),c=new J,h=new WeakMap,u=new Set,d,f=new WeakMap,p=!1;try{p=typeof OffscreenCanvas<"u"&&new OffscreenCanvas(1,1).getContext("2d")!==null}catch{}function _(C,M){return p?new OffscreenCanvas(C,M):wr("canvas")}function g(C,M,O){let G=1,Y=nt(C);if((Y.width>O||Y.height>O)&&(G=O/Math.max(Y.width,Y.height)),G<1)if(typeof HTMLImageElement<"u"&&C instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&C instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&C instanceof ImageBitmap||typeof VideoFrame<"u"&&C instanceof VideoFrame){let le=Math.floor(G*Y.width),he=Math.floor(G*Y.height);d===void 0&&(d=_(le,he));let Z=M?_(le,he):d;return Z.width=le,Z.height=he,Z.getContext("2d").drawImage(C,0,0,le,he),de("WebGLRenderer: Texture has been resized from ("+Y.width+"x"+Y.height+") to ("+le+"x"+he+")."),Z}else return"data"in C&&de("WebGLRenderer: Image in DataTexture is too big ("+Y.width+"x"+Y.height+")."),C;return C}function m(C){return C.generateMipmaps}function y(C){r.generateMipmap(C)}function b(C){return C.isWebGLCubeRenderTarget?r.TEXTURE_CUBE_MAP:C.isWebGL3DRenderTarget?r.TEXTURE_3D:C.isWebGLArrayRenderTarget||C.isCompressedArrayTexture?r.TEXTURE_2D_ARRAY:r.TEXTURE_2D}function x(C,M,O,G,Y,le=!1){if(C!==null){if(r[C]!==void 0)return r[C];de("WebGLRenderer: Attempt to use non-existing WebGL internal format '"+C+"'")}let he;G&&(he=e.get("EXT_texture_norm16"),he||de("WebGLRenderer: Unable to use normalized textures without EXT_texture_norm16 extension"));let Z=M;if(M===r.RED&&(O===r.FLOAT&&(Z=r.R32F),O===r.HALF_FLOAT&&(Z=r.R16F),O===r.UNSIGNED_BYTE&&(Z=r.R8),O===r.UNSIGNED_SHORT&&he&&(Z=he.R16_EXT),O===r.SHORT&&he&&(Z=he.R16_SNORM_EXT)),M===r.RED_INTEGER&&(O===r.UNSIGNED_BYTE&&(Z=r.R8UI),O===r.UNSIGNED_SHORT&&(Z=r.R16UI),O===r.UNSIGNED_INT&&(Z=r.R32UI),O===r.BYTE&&(Z=r.R8I),O===r.SHORT&&(Z=r.R16I),O===r.INT&&(Z=r.R32I)),M===r.RG&&(O===r.FLOAT&&(Z=r.RG32F),O===r.HALF_FLOAT&&(Z=r.RG16F),O===r.UNSIGNED_BYTE&&(Z=r.RG8),O===r.UNSIGNED_SHORT&&he&&(Z=he.RG16_EXT),O===r.SHORT&&he&&(Z=he.RG16_SNORM_EXT)),M===r.RG_INTEGER&&(O===r.UNSIGNED_BYTE&&(Z=r.RG8UI),O===r.UNSIGNED_SHORT&&(Z=r.RG16UI),O===r.UNSIGNED_INT&&(Z=r.RG32UI),O===r.BYTE&&(Z=r.RG8I),O===r.SHORT&&(Z=r.RG16I),O===r.INT&&(Z=r.RG32I)),M===r.RGB_INTEGER&&(O===r.UNSIGNED_BYTE&&(Z=r.RGB8UI),O===r.UNSIGNED_SHORT&&(Z=r.RGB16UI),O===r.UNSIGNED_INT&&(Z=r.RGB32UI),O===r.BYTE&&(Z=r.RGB8I),O===r.SHORT&&(Z=r.RGB16I),O===r.INT&&(Z=r.RGB32I)),M===r.RGBA_INTEGER&&(O===r.UNSIGNED_BYTE&&(Z=r.RGBA8UI),O===r.UNSIGNED_SHORT&&(Z=r.RGBA16UI),O===r.UNSIGNED_INT&&(Z=r.RGBA32UI),O===r.BYTE&&(Z=r.RGBA8I),O===r.SHORT&&(Z=r.RGBA16I),O===r.INT&&(Z=r.RGBA32I)),M===r.RGB&&(O===r.UNSIGNED_SHORT&&he&&(Z=he.RGB16_EXT),O===r.SHORT&&he&&(Z=he.RGB16_SNORM_EXT),O===r.UNSIGNED_INT_5_9_9_9_REV&&(Z=r.RGB9_E5),O===r.UNSIGNED_INT_10F_11F_11F_REV&&(Z=r.R11F_G11F_B10F)),M===r.RGBA){let $=le?Er:Je.getTransfer(Y);O===r.FLOAT&&(Z=r.RGBA32F),O===r.HALF_FLOAT&&(Z=r.RGBA16F),O===r.UNSIGNED_BYTE&&(Z=$===ht?r.SRGB8_ALPHA8:r.RGBA8),O===r.UNSIGNED_SHORT&&he&&(Z=he.RGBA16_EXT),O===r.SHORT&&he&&(Z=he.RGBA16_SNORM_EXT),O===r.UNSIGNED_SHORT_4_4_4_4&&(Z=r.RGBA4),O===r.UNSIGNED_SHORT_5_5_5_1&&(Z=r.RGB5_A1)}return(Z===r.R16F||Z===r.R32F||Z===r.RG16F||Z===r.RG32F||Z===r.RGBA16F||Z===r.RGBA32F)&&e.get("EXT_color_buffer_float"),Z}function T(C,M){let O;return C?M===null||M===Cn||M===Js?O=r.DEPTH24_STENCIL8:M===en?O=r.DEPTH32F_STENCIL8:M===Ks&&(O=r.DEPTH24_STENCIL8,de("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):M===null||M===Cn||M===Js?O=r.DEPTH_COMPONENT24:M===en?O=r.DEPTH_COMPONENT32F:M===Ks&&(O=r.DEPTH_COMPONENT16),O}function S(C,M){return m(C)===!0||C.isFramebufferTexture&&C.minFilter!==At&&C.minFilter!==pt?Math.log2(Math.max(M.width,M.height))+1:C.mipmaps!==void 0&&C.mipmaps.length>0?C.mipmaps.length:C.isCompressedTexture&&Array.isArray(C.image)?M.mipmaps.length:1}function w(C){let M=C.target;M.removeEventListener("dispose",w),E(M),M.isVideoTexture&&h.delete(M),M.isHTMLTexture&&u.delete(M)}function v(C){let M=C.target;M.removeEventListener("dispose",v),P(M)}function E(C){let M=n.get(C);if(M.__webglInit===void 0)return;let O=C.source,G=f.get(O);if(G){let Y=G[M.__cacheKey];Y.usedTimes--,Y.usedTimes===0&&I(C),Object.keys(G).length===0&&f.delete(O)}n.remove(C)}function I(C){let M=n.get(C);r.deleteTexture(M.__webglTexture);let O=C.source,G=f.get(O);delete G[M.__cacheKey],o.memory.textures--}function P(C){let M=n.get(C);if(C.depthTexture&&(C.depthTexture.dispose(),n.remove(C.depthTexture)),C.isWebGLCubeRenderTarget)for(let G=0;G<6;G++){if(Array.isArray(M.__webglFramebuffer[G]))for(let Y=0;Y=i.maxTextures&&de("WebGLTextures: Trying to use "+(C+1)+" texture units while this GPU supports only "+i.maxTextures),F+=1,C}function X(C){let M=[];return M.push(C.wrapS),M.push(C.wrapT),M.push(C.wrapR||0),M.push(C.magFilter),M.push(C.minFilter),M.push(C.anisotropy),M.push(C.internalFormat),M.push(C.format),M.push(C.type),M.push(C.generateMipmaps),M.push(C.premultiplyAlpha),M.push(C.flipY),M.push(C.unpackAlignment),M.push(C.colorSpace),M.join()}function ie(C,M){let O=n.get(C);if(C.isVideoTexture&&L(C),C.isRenderTargetTexture===!1&&C.isExternalTexture!==!0&&C.version>0&&O.__version!==C.version){let G=C.image;if(G===null)de("WebGLRenderer: Texture marked for update but no image data found.");else if(G.complete===!1)de("WebGLRenderer: Texture marked for update but image is incomplete");else{ve(O,C,M);return}}else C.isExternalTexture&&(O.__webglTexture=C.sourceTexture?C.sourceTexture:null);t.bindTexture(r.TEXTURE_2D,O.__webglTexture,r.TEXTURE0+M)}function q(C,M){let O=n.get(C);if(C.isRenderTargetTexture===!1&&C.version>0&&O.__version!==C.version){ve(O,C,M);return}else C.isExternalTexture&&(O.__webglTexture=C.sourceTexture?C.sourceTexture:null);t.bindTexture(r.TEXTURE_2D_ARRAY,O.__webglTexture,r.TEXTURE0+M)}function Q(C,M){let O=n.get(C);if(C.isRenderTargetTexture===!1&&C.version>0&&O.__version!==C.version){ve(O,C,M);return}t.bindTexture(r.TEXTURE_3D,O.__webglTexture,r.TEXTURE0+M)}function ne(C,M){let O=n.get(C);if(C.isCubeDepthTexture!==!0&&C.version>0&&O.__version!==C.version){Ge(O,C,M);return}t.bindTexture(r.TEXTURE_CUBE_MAP,O.__webglTexture,r.TEXTURE0+M)}let Ne={[li]:r.REPEAT,[Yt]:r.CLAMP_TO_EDGE,[$i]:r.MIRRORED_REPEAT},we={[At]:r.NEAREST,[ro]:r.NEAREST_MIPMAP_NEAREST,[Bi]:r.NEAREST_MIPMAP_LINEAR,[pt]:r.LINEAR,[cs]:r.LINEAR_MIPMAP_NEAREST,[vn]:r.LINEAR_MIPMAP_LINEAR},ct={[Yd]:r.NEVER,[$d]:r.ALWAYS,[Zd]:r.LESS,[Nl]:r.LEQUAL,[Kd]:r.EQUAL,[Dl]:r.GEQUAL,[Jd]:r.GREATER,[jd]:r.NOTEQUAL};function tt(C,M){if(M.type===en&&e.has("OES_texture_float_linear")===!1&&(M.magFilter===pt||M.magFilter===cs||M.magFilter===Bi||M.magFilter===vn||M.minFilter===pt||M.minFilter===cs||M.minFilter===Bi||M.minFilter===vn)&&de("WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),r.texParameteri(C,r.TEXTURE_WRAP_S,Ne[M.wrapS]),r.texParameteri(C,r.TEXTURE_WRAP_T,Ne[M.wrapT]),(C===r.TEXTURE_3D||C===r.TEXTURE_2D_ARRAY)&&r.texParameteri(C,r.TEXTURE_WRAP_R,Ne[M.wrapR]),r.texParameteri(C,r.TEXTURE_MAG_FILTER,we[M.magFilter]),r.texParameteri(C,r.TEXTURE_MIN_FILTER,we[M.minFilter]),M.compareFunction&&(r.texParameteri(C,r.TEXTURE_COMPARE_MODE,r.COMPARE_REF_TO_TEXTURE),r.texParameteri(C,r.TEXTURE_COMPARE_FUNC,ct[M.compareFunction])),e.has("EXT_texture_filter_anisotropic")===!0){if(M.magFilter===At||M.minFilter!==Bi&&M.minFilter!==vn||M.type===en&&e.has("OES_texture_float_linear")===!1)return;if(M.anisotropy>1||n.get(M).__currentAnisotropy){let O=e.get("EXT_texture_filter_anisotropic");r.texParameterf(C,O.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(M.anisotropy,i.getMaxAnisotropy())),n.get(M).__currentAnisotropy=M.anisotropy}}}function ot(C,M){let O=!1;C.__webglInit===void 0&&(C.__webglInit=!0,M.addEventListener("dispose",w));let G=M.source,Y=f.get(G);Y===void 0&&(Y={},f.set(G,Y));let le=X(M);if(le!==C.__cacheKey){Y[le]===void 0&&(Y[le]={texture:r.createTexture(),usedTimes:0},o.memory.textures++,O=!0),Y[le].usedTimes++;let he=Y[C.__cacheKey];he!==void 0&&(Y[C.__cacheKey].usedTimes--,he.usedTimes===0&&I(M)),C.__cacheKey=le,C.__webglTexture=Y[le].texture}return O}function K(C,M,O){return Math.floor(Math.floor(C/O)/M)}function ee(C,M,O,G){let le=C.updateRanges;if(le.length===0)t.texSubImage2D(r.TEXTURE_2D,0,0,0,M.width,M.height,O,G,M.data);else{le.sort((De,ye)=>De.start-ye.start);let he=0;for(let De=1;De0){Ve&&Ze&&t.texStorage2D(r.TEXTURE_2D,ge,ye,Ue[0].width,Ue[0].height);for(let j=0,_e=Ue.length;j<_e;j++)me=Ue[j],Ve?U&&t.texSubImage2D(r.TEXTURE_2D,j,0,0,me.width,me.height,pe,De,me.data):t.texImage2D(r.TEXTURE_2D,j,ye,me.width,me.height,0,pe,De,me.data);M.generateMipmaps=!1}else Ve?(Ze&&t.texStorage2D(r.TEXTURE_2D,ge,ye,$.width,$.height),U&&ee(M,$,pe,De)):t.texImage2D(r.TEXTURE_2D,0,ye,$.width,$.height,0,pe,De,$.data);else if(M.isCompressedTexture)if(M.isCompressedArrayTexture){Ve&&Ze&&t.texStorage3D(r.TEXTURE_2D_ARRAY,ge,ye,Ue[0].width,Ue[0].height,$.depth);for(let j=0,_e=Ue.length;j<_e;j++)if(me=Ue[j],M.format!==tn)if(pe!==null)if(Ve){if(U)if(M.layerUpdates.size>0){let be=ou(me.width,me.height,M.format,M.type);for(let se of M.layerUpdates){let Fe=me.data.subarray(se*be/me.data.BYTES_PER_ELEMENT,(se+1)*be/me.data.BYTES_PER_ELEMENT);t.compressedTexSubImage3D(r.TEXTURE_2D_ARRAY,j,0,0,se,me.width,me.height,1,pe,Fe)}}else t.compressedTexSubImage3D(r.TEXTURE_2D_ARRAY,j,0,0,0,me.width,me.height,$.depth,pe,me.data)}else t.compressedTexImage3D(r.TEXTURE_2D_ARRAY,j,ye,me.width,me.height,$.depth,0,me.data,0,0);else de("WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else Ve?U&&t.texSubImage3D(r.TEXTURE_2D_ARRAY,j,0,0,0,me.width,me.height,$.depth,pe,De,me.data):t.texImage3D(r.TEXTURE_2D_ARRAY,j,ye,me.width,me.height,$.depth,0,pe,De,me.data);M.layerUpdates.size>0&&M.clearLayerUpdates()}else{Ve&&Ze&&t.texStorage2D(r.TEXTURE_2D,ge,ye,Ue[0].width,Ue[0].height);for(let j=0,_e=Ue.length;j<_e;j++)me=Ue[j],M.format!==tn?pe!==null?Ve?U&&t.compressedTexSubImage2D(r.TEXTURE_2D,j,0,0,me.width,me.height,pe,me.data):t.compressedTexImage2D(r.TEXTURE_2D,j,ye,me.width,me.height,0,me.data):de("WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):Ve?U&&t.texSubImage2D(r.TEXTURE_2D,j,0,0,me.width,me.height,pe,De,me.data):t.texImage2D(r.TEXTURE_2D,j,ye,me.width,me.height,0,pe,De,me.data)}else if(M.isDataArrayTexture)if(Ve){if(Ze&&t.texStorage3D(r.TEXTURE_2D_ARRAY,ge,ye,$.width,$.height,$.depth),U)if(M.layerUpdates.size>0){let j=ou($.width,$.height,M.format,M.type);for(let _e of M.layerUpdates){let be=$.data.subarray(_e*j/$.data.BYTES_PER_ELEMENT,(_e+1)*j/$.data.BYTES_PER_ELEMENT);t.texSubImage3D(r.TEXTURE_2D_ARRAY,0,0,0,_e,$.width,$.height,1,pe,De,be)}M.clearLayerUpdates()}else t.texSubImage3D(r.TEXTURE_2D_ARRAY,0,0,0,0,$.width,$.height,$.depth,pe,De,$.data)}else t.texImage3D(r.TEXTURE_2D_ARRAY,0,ye,$.width,$.height,$.depth,0,pe,De,$.data);else if(M.isData3DTexture)Ve?(Ze&&t.texStorage3D(r.TEXTURE_3D,ge,ye,$.width,$.height,$.depth),U&&t.texSubImage3D(r.TEXTURE_3D,0,0,0,0,$.width,$.height,$.depth,pe,De,$.data)):t.texImage3D(r.TEXTURE_3D,0,ye,$.width,$.height,$.depth,0,pe,De,$.data);else if(M.isFramebufferTexture){if(Ze)if(Ve)t.texStorage2D(r.TEXTURE_2D,ge,ye,$.width,$.height);else{let j=$.width,_e=$.height;for(let be=0;be>=1,_e>>=1}}else if(M.isHTMLTexture){if("texElementImage2D"in r){let j=r.canvas;if(j.hasAttribute("layoutsubtree")||j.setAttribute("layoutsubtree","true"),$.parentNode!==j){j.appendChild($),u.add(M),j.onpaint=_e=>{let be=_e.changedElements;for(let se of u)be.includes(se.image)&&(se.needsUpdate=!0)},j.requestPaint();return}if(r.texElementImage2D.length===3)r.texElementImage2D(r.TEXTURE_2D,r.RGBA8,$);else{let be=r.RGBA,se=r.RGBA,Fe=r.UNSIGNED_BYTE;r.texElementImage2D(r.TEXTURE_2D,0,be,se,Fe,$)}r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE)}}else if(Ue.length>0){if(Ve&&Ze){let j=nt(Ue[0]);t.texStorage2D(r.TEXTURE_2D,ge,ye,j.width,j.height)}for(let j=0,_e=Ue.length;j<_e;j++)me=Ue[j],Ve?U&&t.texSubImage2D(r.TEXTURE_2D,j,0,0,pe,De,me):t.texImage2D(r.TEXTURE_2D,j,ye,pe,De,me);M.generateMipmaps=!1}else if(Ve){if(Ze){let j=nt($);t.texStorage2D(r.TEXTURE_2D,ge,ye,j.width,j.height)}U&&t.texSubImage2D(r.TEXTURE_2D,0,0,0,pe,De,$)}else t.texImage2D(r.TEXTURE_2D,0,ye,pe,De,$);m(M)&&y(G),he.__version=le.version,M.onUpdate&&M.onUpdate(M)}C.__version=M.version}function Ge(C,M,O){if(M.image.length!==6)return;let G=ot(C,M),Y=M.source;t.bindTexture(r.TEXTURE_CUBE_MAP,C.__webglTexture,r.TEXTURE0+O);let le=n.get(Y);if(Y.version!==le.__version||G===!0){t.activeTexture(r.TEXTURE0+O);let he=Je.getPrimaries(Je.workingColorSpace),Z=M.colorSpace===yi?null:Je.getPrimaries(M.colorSpace),$=M.colorSpace===yi||he===Z?r.NONE:r.BROWSER_DEFAULT_WEBGL;t.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,M.flipY),t.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,M.premultiplyAlpha),t.pixelStorei(r.UNPACK_ALIGNMENT,M.unpackAlignment),t.pixelStorei(r.UNPACK_COLORSPACE_CONVERSION_WEBGL,$);let pe=M.isCompressedTexture||M.image[0].isCompressedTexture,De=M.image[0]&&M.image[0].isDataTexture,ye=[];for(let se=0;se<6;se++)!pe&&!De?ye[se]=g(M.image[se],!0,i.maxCubemapSize):ye[se]=De?M.image[se].image:M.image[se],ye[se]=ut(M,ye[se]);let me=ye[0],Ue=s.convert(M.format,M.colorSpace),Ve=s.convert(M.type),Ze=x(M.internalFormat,Ue,Ve,M.normalized,M.colorSpace),U=M.isVideoTexture!==!0,ge=le.__version===void 0||G===!0,j=Y.dataReady,_e=S(M,me);tt(r.TEXTURE_CUBE_MAP,M);let be;if(pe){U&&ge&&t.texStorage2D(r.TEXTURE_CUBE_MAP,_e,Ze,me.width,me.height);for(let se=0;se<6;se++){be=ye[se].mipmaps;for(let Fe=0;Fe0&&_e++;let se=nt(ye[0]);t.texStorage2D(r.TEXTURE_CUBE_MAP,_e,Ze,se.width,se.height)}for(let se=0;se<6;se++)if(De){U?j&&t.texSubImage2D(r.TEXTURE_CUBE_MAP_POSITIVE_X+se,0,0,0,ye[se].width,ye[se].height,Ue,Ve,ye[se].data):t.texImage2D(r.TEXTURE_CUBE_MAP_POSITIVE_X+se,0,Ze,ye[se].width,ye[se].height,0,Ue,Ve,ye[se].data);for(let Fe=0;Fe>le),me=Math.max(1,M.height>>le);Y===r.TEXTURE_3D||Y===r.TEXTURE_2D_ARRAY?t.texImage3D(Y,le,$,ye,me,M.depth,0,he,Z,null):t.texImage2D(Y,le,$,ye,me,0,he,Z,null)}t.bindFramebuffer(r.FRAMEBUFFER,C),Ye(M)?a.framebufferTexture2DMultisampleEXT(r.FRAMEBUFFER,G,Y,De.__webglTexture,0,Xe(M)):(Y===r.TEXTURE_2D||Y>=r.TEXTURE_CUBE_MAP_POSITIVE_X&&Y<=r.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&r.framebufferTexture2D(r.FRAMEBUFFER,G,Y,De.__webglTexture,le),t.bindFramebuffer(r.FRAMEBUFFER,null)}function We(C,M,O){if(r.bindRenderbuffer(r.RENDERBUFFER,C),M.depthBuffer){let G=M.depthTexture,Y=G&&G.isDepthTexture?G.type:null,le=T(M.stencilBuffer,Y),he=M.stencilBuffer?r.DEPTH_STENCIL_ATTACHMENT:r.DEPTH_ATTACHMENT;Ye(M)?a.renderbufferStorageMultisampleEXT(r.RENDERBUFFER,Xe(M),le,M.width,M.height):O?r.renderbufferStorageMultisample(r.RENDERBUFFER,Xe(M),le,M.width,M.height):r.renderbufferStorage(r.RENDERBUFFER,le,M.width,M.height),r.framebufferRenderbuffer(r.FRAMEBUFFER,he,r.RENDERBUFFER,C)}else{let G=M.textures;for(let Y=0;Y{delete M.__boundDepthTexture,delete M.__depthDisposeCallback,G.removeEventListener("dispose",Y)};G.addEventListener("dispose",Y),M.__depthDisposeCallback=Y}M.__boundDepthTexture=G}if(C.depthTexture&&!M.__autoAllocateDepthBuffer)if(O)for(let G=0;G<6;G++)gt(M.__webglFramebuffer[G],C,G);else{let G=C.texture.mipmaps;G&&G.length>0?gt(M.__webglFramebuffer[0],C,0):gt(M.__webglFramebuffer,C,0)}else if(O){M.__webglDepthbuffer=[];for(let G=0;G<6;G++)if(t.bindFramebuffer(r.FRAMEBUFFER,M.__webglFramebuffer[G]),M.__webglDepthbuffer[G]===void 0)M.__webglDepthbuffer[G]=r.createRenderbuffer(),We(M.__webglDepthbuffer[G],C,!1);else{let Y=C.stencilBuffer?r.DEPTH_STENCIL_ATTACHMENT:r.DEPTH_ATTACHMENT,le=M.__webglDepthbuffer[G];r.bindRenderbuffer(r.RENDERBUFFER,le),r.framebufferRenderbuffer(r.FRAMEBUFFER,Y,r.RENDERBUFFER,le)}}else{let G=C.texture.mipmaps;if(G&&G.length>0?t.bindFramebuffer(r.FRAMEBUFFER,M.__webglFramebuffer[0]):t.bindFramebuffer(r.FRAMEBUFFER,M.__webglFramebuffer),M.__webglDepthbuffer===void 0)M.__webglDepthbuffer=r.createRenderbuffer(),We(M.__webglDepthbuffer,C,!1);else{let Y=C.stencilBuffer?r.DEPTH_STENCIL_ATTACHMENT:r.DEPTH_ATTACHMENT,le=M.__webglDepthbuffer;r.bindRenderbuffer(r.RENDERBUFFER,le),r.framebufferRenderbuffer(r.FRAMEBUFFER,Y,r.RENDERBUFFER,le)}}t.bindFramebuffer(r.FRAMEBUFFER,null)}function re(C,M,O){let G=n.get(C);M!==void 0&&Te(G.__webglFramebuffer,C,C.texture,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,0),O!==void 0&&te(C)}function oe(C){let M=C.texture,O=n.get(C),G=n.get(M);C.addEventListener("dispose",v);let Y=C.textures,le=C.isWebGLCubeRenderTarget===!0,he=Y.length>1;if(he||(G.__webglTexture===void 0&&(G.__webglTexture=r.createTexture()),G.__version=M.version,o.memory.textures++),le){O.__webglFramebuffer=[];for(let Z=0;Z<6;Z++)if(M.mipmaps&&M.mipmaps.length>0){O.__webglFramebuffer[Z]=[];for(let $=0;$0){O.__webglFramebuffer=[];for(let Z=0;Z0&&Ye(C)===!1){O.__webglMultisampledFramebuffer=r.createFramebuffer(),O.__webglColorRenderbuffer=[],t.bindFramebuffer(r.FRAMEBUFFER,O.__webglMultisampledFramebuffer);for(let Z=0;Z0)for(let $=0;$0)for(let $=0;$0){if(Ye(C)===!1){let M=C.textures,O=C.width,G=C.height,Y=r.COLOR_BUFFER_BIT,le=C.stencilBuffer?r.DEPTH_STENCIL_ATTACHMENT:r.DEPTH_ATTACHMENT,he=n.get(C),Z=M.length>1;if(Z)for(let pe=0;pe0?t.bindFramebuffer(r.DRAW_FRAMEBUFFER,he.__webglFramebuffer[0]):t.bindFramebuffer(r.DRAW_FRAMEBUFFER,he.__webglFramebuffer);for(let pe=0;pe0&&e.has("WEBGL_multisampled_render_to_texture")===!0&&M.__useRenderToTexture!==!1}function L(C){let M=o.render.frame;h.get(C)!==M&&(h.set(C,M),C.update())}function ut(C,M){let O=C.colorSpace,G=C.format,Y=C.type;return C.isCompressedTexture===!0||C.isVideoTexture===!0||O!==nn&&O!==yi&&(Je.getTransfer(O)===ht?(G!==tn||Y!==fn)&&de("WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):Pe("WebGLTextures: Unsupported texture color space:",O)),M}function nt(C){return typeof HTMLImageElement<"u"&&C instanceof HTMLImageElement?(c.width=C.naturalWidth||C.width,c.height=C.naturalHeight||C.height):typeof VideoFrame<"u"&&C instanceof VideoFrame?(c.width=C.displayWidth,c.height=C.displayHeight):(c.width=C.width,c.height=C.height),c}this.allocateTextureUnit=H,this.resetTextureUnits=z,this.getTextureUnits=N,this.setTextureUnits=B,this.setTexture2D=ie,this.setTexture2DArray=q,this.setTexture3D=Q,this.setTextureCube=ne,this.rebindTextures=re,this.setupRenderTarget=oe,this.updateRenderTargetMipmap=ae,this.updateMultisampleRenderTarget=Be,this.setupDepthRenderbuffer=te,this.setupFrameBufferTexture=Te,this.useMultisampledRTT=Ye,this.isReversedDepthBuffer=function(){return t.buffers.depth.getReversed()}}function t_(r,e){function t(n,i=yi){let s,o=Je.getTransfer(i);if(n===fn)return r.UNSIGNED_BYTE;if(n===ja)return r.UNSIGNED_SHORT_4_4_4_4;if(n===$a)return r.UNSIGNED_SHORT_5_5_5_1;if(n===Qh)return r.UNSIGNED_INT_5_9_9_9_REV;if(n===eu)return r.UNSIGNED_INT_10F_11F_11F_REV;if(n===jh)return r.BYTE;if(n===$h)return r.SHORT;if(n===Ks)return r.UNSIGNED_SHORT;if(n===Ja)return r.INT;if(n===Cn)return r.UNSIGNED_INT;if(n===en)return r.FLOAT;if(n===Bn)return r.HALF_FLOAT;if(n===tu)return r.ALPHA;if(n===nu)return r.RGB;if(n===tn)return r.RGBA;if(n===Zn)return r.DEPTH_COMPONENT;if(n===zi)return r.DEPTH_STENCIL;if(n===Qa)return r.RED;if(n===oo)return r.RED_INTEGER;if(n===ki)return r.RG;if(n===el)return r.RG_INTEGER;if(n===tl)return r.RGBA_INTEGER;if(n===ao||n===lo||n===co||n===ho)if(o===ht)if(s=e.get("WEBGL_compressed_texture_s3tc_srgb"),s!==null){if(n===ao)return s.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===lo)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===co)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===ho)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else return null;else if(s=e.get("WEBGL_compressed_texture_s3tc"),s!==null){if(n===ao)return s.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===lo)return s.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===co)return s.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===ho)return s.COMPRESSED_RGBA_S3TC_DXT5_EXT}else return null;if(n===nl||n===il||n===sl||n===rl)if(s=e.get("WEBGL_compressed_texture_pvrtc"),s!==null){if(n===nl)return s.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===il)return s.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===sl)return s.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===rl)return s.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}else return null;if(n===ol||n===al||n===ll||n===cl||n===hl||n===uo||n===ul)if(s=e.get("WEBGL_compressed_texture_etc"),s!==null){if(n===ol||n===al)return o===ht?s.COMPRESSED_SRGB8_ETC2:s.COMPRESSED_RGB8_ETC2;if(n===ll)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:s.COMPRESSED_RGBA8_ETC2_EAC;if(n===cl)return s.COMPRESSED_R11_EAC;if(n===hl)return s.COMPRESSED_SIGNED_R11_EAC;if(n===uo)return s.COMPRESSED_RG11_EAC;if(n===ul)return s.COMPRESSED_SIGNED_RG11_EAC}else return null;if(n===dl||n===fl||n===pl||n===ml||n===gl||n===_l||n===xl||n===yl||n===vl||n===Ml||n===Sl||n===bl||n===Tl||n===Al)if(s=e.get("WEBGL_compressed_texture_astc"),s!==null){if(n===dl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:s.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===fl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:s.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===pl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:s.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===ml)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:s.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===gl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:s.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===_l)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:s.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===xl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:s.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===yl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:s.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===vl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:s.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===Ml)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:s.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===Sl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:s.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===bl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:s.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===Tl)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:s.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===Al)return o===ht?s.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:s.COMPRESSED_RGBA_ASTC_12x12_KHR}else return null;if(n===El||n===wl||n===Rl)if(s=e.get("EXT_texture_compression_bptc"),s!==null){if(n===El)return o===ht?s.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:s.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===wl)return s.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===Rl)return s.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}else return null;if(n===Cl||n===Il||n===fo||n===Pl)if(s=e.get("EXT_texture_compression_rgtc"),s!==null){if(n===Cl)return s.COMPRESSED_RED_RGTC1_EXT;if(n===Il)return s.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===fo)return s.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===Pl)return s.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}else return null;return n===Js?r.UNSIGNED_INT_24_8:r[n]!==void 0?r[n]:null}return{convert:t}}var ib=` +void main() { + + gl_Position = vec4( position, 1.0 ); + +}`,sb=` +uniform sampler2DArray depthColor; +uniform float depthWidth; +uniform float depthHeight; + +void main() { + + vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); + + if ( coord.x >= 1.0 ) { + + gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; + + } else { + + gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; + + } + +}`,Mf=class{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t){if(this.texture===null){let n=new Nr(e.texture);(e.depthNear!==t.depthNear||e.depthFar!==t.depthFar)&&(this.depthNear=e.depthNear,this.depthFar=e.depthFar),this.texture=n}}getMesh(e){if(this.texture!==null&&this.mesh===null){let t=e.cameras[0].viewport,n=new un({vertexShader:ib,fragmentShader:sb,uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new rt(new Bs(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}},Sf=class extends xn{constructor(e,t){super();let n=this,i=null,s=1,o=null,a="local-floor",l=1,c=null,h=null,u=null,d=null,f=null,p=null,_=typeof XRWebGLBinding<"u",g=new Mf,m={},y=t.getContextAttributes(),b=null,x=null,T=[],S=[],w=new J,v=null,E=null,I=new Lt;I.viewport=new mt;let P=new Lt;P.viewport=new mt;let F=[I,P],z=new Ha,N=null,B=null;this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(K){let ee=T[K];return ee===void 0&&(ee=new Is,T[K]=ee),ee.getTargetRaySpace()},this.getControllerGrip=function(K){let ee=T[K];return ee===void 0&&(ee=new Is,T[K]=ee),ee.getGripSpace()},this.getHand=function(K){let ee=T[K];return ee===void 0&&(ee=new Is,T[K]=ee),ee.getHandSpace()};function H(K){let ee=S.indexOf(K.inputSource);if(ee===-1)return;let ve=T[ee];ve!==void 0&&(ve.update(K.inputSource,K.frame,c||o),ve.dispatchEvent({type:K.type,data:K.inputSource}))}function X(){i.removeEventListener("select",H),i.removeEventListener("selectstart",H),i.removeEventListener("selectend",H),i.removeEventListener("squeeze",H),i.removeEventListener("squeezestart",H),i.removeEventListener("squeezeend",H),i.removeEventListener("end",X),i.removeEventListener("inputsourceschange",ie);for(let K=0;K=0&&(S[Ge]=null,T[Ge].disconnect(ve))}for(let ee=0;ee=S.length){S.push(ve),Ge=We;break}else if(S[We]===null){S[We]=ve,Ge=We;break}if(Ge===-1)break}let Te=T[Ge];Te&&Te.connect(ve)}}let q=new R,Q=new R;function ne(K,ee,ve){q.setFromMatrixPosition(ee.matrixWorld),Q.setFromMatrixPosition(ve.matrixWorld);let Ge=q.distanceTo(Q),Te=ee.projectionMatrix.elements,We=ve.projectionMatrix.elements,gt=Te[14]/(Te[10]-1),te=Te[14]/(Te[10]+1),re=(Te[9]+1)/Te[5],oe=(Te[9]-1)/Te[5],ae=(Te[8]-1)/Te[0],ue=(We[8]+1)/We[0],ke=gt*ae,Be=gt*ue,Xe=Ge/(-ae+ue),Ye=Xe*-ae;if(ee.matrixWorld.decompose(K.position,K.quaternion,K.scale),K.translateX(Ye),K.translateZ(Xe),K.matrixWorld.compose(K.position,K.quaternion,K.scale),K.matrixWorldInverse.copy(K.matrixWorld).invert(),Te[10]===-1)K.projectionMatrix.copy(ee.projectionMatrix),K.projectionMatrixInverse.copy(ee.projectionMatrixInverse);else{let L=gt+Xe,ut=te+Xe,nt=ke-Ye,C=Be+(Ge-Ye),M=re*te/ut*L,O=oe*te/ut*L;K.projectionMatrix.makePerspective(nt,C,M,O,L,ut),K.projectionMatrixInverse.copy(K.projectionMatrix).invert()}}function Ne(K,ee){ee===null?K.matrixWorld.copy(K.matrix):K.matrixWorld.multiplyMatrices(ee.matrixWorld,K.matrix),K.matrixWorldInverse.copy(K.matrixWorld).invert()}this.updateCamera=function(K){if(i===null)return;let ee=K.near,ve=K.far;g.texture!==null&&(g.depthNear>0&&(ee=g.depthNear),g.depthFar>0&&(ve=g.depthFar)),z.near=P.near=I.near=ee,z.far=P.far=I.far=ve,(N!==z.near||B!==z.far)&&(i.updateRenderState({depthNear:z.near,depthFar:z.far}),N=z.near,B=z.far),z.layers.mask=K.layers.mask|6,I.layers.mask=z.layers.mask&-5,P.layers.mask=z.layers.mask&-3;let Ge=K.parent,Te=z.cameras;Ne(z,Ge);for(let We=0;We0&&(g.alphaTest.value=m.alphaTest);let y=e.get(m),b=y.envMap,x=y.envMapRotation;b&&(g.envMap.value=b,g.envMapRotation.value.setFromMatrix4(rb.makeRotationFromEuler(x)).transpose(),b.isCubeTexture&&b.isRenderTargetTexture===!1&&g.envMapRotation.value.premultiply(n_),g.reflectivity.value=m.reflectivity,g.ior.value=m.ior,g.refractionRatio.value=m.refractionRatio),m.lightMap&&(g.lightMap.value=m.lightMap,g.lightMapIntensity.value=m.lightMapIntensity,t(m.lightMap,g.lightMapTransform)),m.aoMap&&(g.aoMap.value=m.aoMap,g.aoMapIntensity.value=m.aoMapIntensity,t(m.aoMap,g.aoMapTransform))}function o(g,m){g.diffuse.value.copy(m.color),g.opacity.value=m.opacity,m.map&&(g.map.value=m.map,t(m.map,g.mapTransform))}function a(g,m){g.dashSize.value=m.dashSize,g.totalSize.value=m.dashSize+m.gapSize,g.scale.value=m.scale}function l(g,m,y,b){g.diffuse.value.copy(m.color),g.opacity.value=m.opacity,g.size.value=m.size*y,g.scale.value=b*.5,m.map&&(g.map.value=m.map,t(m.map,g.uvTransform)),m.alphaMap&&(g.alphaMap.value=m.alphaMap,t(m.alphaMap,g.alphaMapTransform)),m.alphaTest>0&&(g.alphaTest.value=m.alphaTest)}function c(g,m){g.diffuse.value.copy(m.color),g.opacity.value=m.opacity,g.rotation.value=m.rotation,m.map&&(g.map.value=m.map,t(m.map,g.mapTransform)),m.alphaMap&&(g.alphaMap.value=m.alphaMap,t(m.alphaMap,g.alphaMapTransform)),m.alphaTest>0&&(g.alphaTest.value=m.alphaTest)}function h(g,m){g.specular.value.copy(m.specular),g.shininess.value=Math.max(m.shininess,1e-4)}function u(g,m){m.gradientMap&&(g.gradientMap.value=m.gradientMap)}function d(g,m){g.metalness.value=m.metalness,m.metalnessMap&&(g.metalnessMap.value=m.metalnessMap,t(m.metalnessMap,g.metalnessMapTransform)),g.roughness.value=m.roughness,m.roughnessMap&&(g.roughnessMap.value=m.roughnessMap,t(m.roughnessMap,g.roughnessMapTransform)),m.envMap&&(g.envMapIntensity.value=m.envMapIntensity)}function f(g,m,y){g.ior.value=m.ior,m.sheen>0&&(g.sheenColor.value.copy(m.sheenColor).multiplyScalar(m.sheen),g.sheenRoughness.value=m.sheenRoughness,m.sheenColorMap&&(g.sheenColorMap.value=m.sheenColorMap,t(m.sheenColorMap,g.sheenColorMapTransform)),m.sheenRoughnessMap&&(g.sheenRoughnessMap.value=m.sheenRoughnessMap,t(m.sheenRoughnessMap,g.sheenRoughnessMapTransform))),m.clearcoat>0&&(g.clearcoat.value=m.clearcoat,g.clearcoatRoughness.value=m.clearcoatRoughness,m.clearcoatMap&&(g.clearcoatMap.value=m.clearcoatMap,t(m.clearcoatMap,g.clearcoatMapTransform)),m.clearcoatRoughnessMap&&(g.clearcoatRoughnessMap.value=m.clearcoatRoughnessMap,t(m.clearcoatRoughnessMap,g.clearcoatRoughnessMapTransform)),m.clearcoatNormalMap&&(g.clearcoatNormalMap.value=m.clearcoatNormalMap,t(m.clearcoatNormalMap,g.clearcoatNormalMapTransform),g.clearcoatNormalScale.value.copy(m.clearcoatNormalScale),m.side===qt&&g.clearcoatNormalScale.value.negate())),m.dispersion>0&&(g.dispersion.value=m.dispersion),m.retroreflectivity>0&&(g.retroreflectivity.value=m.retroreflectivity),m.iridescence>0&&(g.iridescence.value=m.iridescence,g.iridescenceIOR.value=m.iridescenceIOR,g.iridescenceThicknessMinimum.value=m.iridescenceThicknessRange[0],g.iridescenceThicknessMaximum.value=m.iridescenceThicknessRange[1],m.iridescenceMap&&(g.iridescenceMap.value=m.iridescenceMap,t(m.iridescenceMap,g.iridescenceMapTransform)),m.iridescenceThicknessMap&&(g.iridescenceThicknessMap.value=m.iridescenceThicknessMap,t(m.iridescenceThicknessMap,g.iridescenceThicknessMapTransform))),m.transmission>0&&(g.transmission.value=m.transmission,g.transmissionSamplerMap.value=y.texture,g.transmissionSamplerSize.value.set(y.width,y.height),m.transmissionMap&&(g.transmissionMap.value=m.transmissionMap,t(m.transmissionMap,g.transmissionMapTransform)),g.thickness.value=m.thickness,m.thicknessMap&&(g.thicknessMap.value=m.thicknessMap,t(m.thicknessMap,g.thicknessMapTransform)),g.attenuationDistance.value=m.attenuationDistance,g.attenuationColor.value.copy(m.attenuationColor)),m.anisotropy>0&&(g.anisotropyVector.value.set(m.anisotropy*Math.cos(m.anisotropyRotation),m.anisotropy*Math.sin(m.anisotropyRotation)),m.anisotropyMap&&(g.anisotropyMap.value=m.anisotropyMap,t(m.anisotropyMap,g.anisotropyMapTransform))),g.specularIntensity.value=m.specularIntensity,g.specularColor.value.copy(m.specularColor),m.specularColorMap&&(g.specularColorMap.value=m.specularColorMap,t(m.specularColorMap,g.specularColorMapTransform)),m.specularIntensityMap&&(g.specularIntensityMap.value=m.specularIntensityMap,t(m.specularIntensityMap,g.specularIntensityMapTransform))}function p(g,m){m.matcap&&(g.matcap.value=m.matcap)}function _(g,m){let y=e.get(m).light;g.referencePosition.value.setFromMatrixPosition(y.matrixWorld),g.nearDistance.value=y.shadow.camera.near,g.farDistance.value=y.shadow.camera.far}return{refreshFogUniforms:n,refreshMaterialUniforms:i}}function ab(r,e,t,n){let i={},s={},o=[],a=r.getParameter(r.MAX_UNIFORM_BUFFER_BINDINGS);function l(x,T){let S=T.program;n.uniformBlockBinding(x,S)}function c(x,T){let S=i[x.id];S===void 0&&(g(x),S=h(x),i[x.id]=S,x.addEventListener("dispose",y));let w=T.program;n.updateUBOMapping(x,w);let v=e.render.frame;s[x.id]!==v&&(d(x),s[x.id]=v)}function h(x){let T=u();x.__bindingPointIndex=T;let S=r.createBuffer(),w=x.__size,v=x.usage;return r.bindBuffer(r.UNIFORM_BUFFER,S),r.bufferData(r.UNIFORM_BUFFER,w,v),r.bindBuffer(r.UNIFORM_BUFFER,null),r.bindBufferBase(r.UNIFORM_BUFFER,T,S),S}function u(){for(let x=0;x0&&(S+=w-v),x.__size=S,x.__cache={},this}function m(x){let T={boundary:0,storage:0};return typeof x=="number"||typeof x=="boolean"?(T.boundary=4,T.storage=4):x.isVector2?(T.boundary=8,T.storage=8):x.isVector3||x.isColor?(T.boundary=16,T.storage=12):x.isVector4?(T.boundary=16,T.storage=16):x.isMatrix3?(T.boundary=48,T.storage=48):x.isMatrix4?(T.boundary=64,T.storage=64):x.isTexture?de("WebGLRenderer: Texture samplers can not be part of an uniforms group."):ArrayBuffer.isView(x)?(T.boundary=16,T.storage=x.byteLength):de("WebGLRenderer: Unsupported uniform value type.",x),T}function y(x){let T=x.target;T.removeEventListener("dispose",y);let S=o.indexOf(T.__bindingPointIndex);o.splice(S,1),r.deleteBuffer(i[T.id]),delete i[T.id],delete s[T.id]}function b(){for(let x in i)r.deleteBuffer(i[x]);o=[],i={},s={}}return{bind:l,update:c,dispose:b}}var lb=new Uint16Array([12469,15057,12620,14925,13266,14620,13807,14376,14323,13990,14545,13625,14713,13328,14840,12882,14931,12528,14996,12233,15039,11829,15066,11525,15080,11295,15085,10976,15082,10705,15073,10495,13880,14564,13898,14542,13977,14430,14158,14124,14393,13732,14556,13410,14702,12996,14814,12596,14891,12291,14937,11834,14957,11489,14958,11194,14943,10803,14921,10506,14893,10278,14858,9960,14484,14039,14487,14025,14499,13941,14524,13740,14574,13468,14654,13106,14743,12678,14818,12344,14867,11893,14889,11509,14893,11180,14881,10751,14852,10428,14812,10128,14765,9754,14712,9466,14764,13480,14764,13475,14766,13440,14766,13347,14769,13070,14786,12713,14816,12387,14844,11957,14860,11549,14868,11215,14855,10751,14825,10403,14782,10044,14729,9651,14666,9352,14599,9029,14967,12835,14966,12831,14963,12804,14954,12723,14936,12564,14917,12347,14900,11958,14886,11569,14878,11247,14859,10765,14828,10401,14784,10011,14727,9600,14660,9289,14586,8893,14508,8533,15111,12234,15110,12234,15104,12216,15092,12156,15067,12010,15028,11776,14981,11500,14942,11205,14902,10752,14861,10393,14812,9991,14752,9570,14682,9252,14603,8808,14519,8445,14431,8145,15209,11449,15208,11451,15202,11451,15190,11438,15163,11384,15117,11274,15055,10979,14994,10648,14932,10343,14871,9936,14803,9532,14729,9218,14645,8742,14556,8381,14461,8020,14365,7603,15273,10603,15272,10607,15267,10619,15256,10631,15231,10614,15182,10535,15118,10389,15042,10167,14963,9787,14883,9447,14800,9115,14710,8665,14615,8318,14514,7911,14411,7507,14279,7198,15314,9675,15313,9683,15309,9712,15298,9759,15277,9797,15229,9773,15166,9668,15084,9487,14995,9274,14898,8910,14800,8539,14697,8234,14590,7790,14479,7409,14367,7067,14178,6621,15337,8619,15337,8631,15333,8677,15325,8769,15305,8871,15264,8940,15202,8909,15119,8775,15022,8565,14916,8328,14804,8009,14688,7614,14569,7287,14448,6888,14321,6483,14088,6171,15350,7402,15350,7419,15347,7480,15340,7613,15322,7804,15287,7973,15229,8057,15148,8012,15046,7846,14933,7611,14810,7357,14682,7069,14552,6656,14421,6316,14251,5948,14007,5528,15356,5942,15356,5977,15353,6119,15348,6294,15332,6551,15302,6824,15249,7044,15171,7122,15070,7050,14949,6861,14818,6611,14679,6349,14538,6067,14398,5651,14189,5311,13935,4958,15359,4123,15359,4153,15356,4296,15353,4646,15338,5160,15311,5508,15263,5829,15188,6042,15088,6094,14966,6001,14826,5796,14678,5543,14527,5287,14377,4985,14133,4586,13869,4257,15360,1563,15360,1642,15358,2076,15354,2636,15341,3350,15317,4019,15273,4429,15203,4732,15105,4911,14981,4932,14836,4818,14679,4621,14517,4386,14359,4156,14083,3795,13808,3437,15360,122,15360,137,15358,285,15355,636,15344,1274,15322,2177,15281,2765,15215,3223,15120,3451,14995,3569,14846,3567,14681,3466,14511,3305,14344,3121,14037,2800,13753,2467,15360,0,15360,1,15359,21,15355,89,15346,253,15325,479,15287,796,15225,1148,15133,1492,15008,1749,14856,1882,14685,1886,14506,1783,14324,1608,13996,1398,13702,1183]),vi=null;function cb(){return vi===null&&(vi=new hn(lb,16,16,ki,Bn),vi.name="DFG_LUT",vi.minFilter=pt,vi.magFilter=pt,vi.wrapS=Yt,vi.wrapT=Yt,vi.generateMipmaps=!1,vi.needsUpdate=!0),vi}var bf=class{constructor(e={}){let{canvas:t=Qd(),context:n=null,depth:i=!0,stencil:s=!1,alpha:o=!1,antialias:a=!1,premultipliedAlpha:l=!0,preserveDrawingBuffer:c=!1,powerPreference:h="default",failIfMajorPerformanceCaveat:u=!1,reversedDepthBuffer:d=!1,outputBufferType:f=fn}=e;this.isWebGLRenderer=!0;let p;if(n!==null){if(typeof WebGLRenderingContext<"u"&&n instanceof WebGLRenderingContext)throw new Error("THREE.WebGLRenderer: WebGL 1 is not supported since r163.");p=n.getContextAttributes().alpha}else p=o;let _=f,g=new Set([tl,el,oo]),m=new Set([fn,Cn,Ks,Js,ja,$a]),y=new Uint32Array(4),b=new Int32Array(4),x=new R,T=null,S=null,w=[],v=[],E=null;this.domElement=t,this.debug={checkShaderErrors:!0,diagnostics:{keywords:!1},onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this.toneMapping=On,this.toneMappingExposure=1,this.transmissionResolutionScale=1;let I=this,P=!1,F=null,z=null,N=null,B=null;this._outputColorSpace=Tt;let H=0,X=0,ie=null,q=-1,Q=null,ne=new mt,Ne=new mt,we=null,ct=new ce(0),tt=0,ot=t.width,K=t.height,ee=1,ve=null,Ge=null,Te=new mt(0,0,ot,K),We=new mt(0,0,ot,K),gt=!1,te=new hi,re=!1,oe=!1,ae=new ze,ue=new R,ke=new mt,Be={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0},Xe=!1;function Ye(){return ie===null?ee:1}let L=n;function ut(A,D){return t.getContext(A,D)}let nt,C,M,O,G,Y,le,he,Z,$,pe,De,ye,me,Ue,Ve,Ze,U,ge,j,_e,be,se;try{let A={alpha:!0,depth:i,stencil:s,antialias:a,premultipliedAlpha:l,preserveDrawingBuffer:c,powerPreference:h,failIfMajorPerformanceCaveat:u};if("setAttribute"in t&&t.setAttribute("data-engine",`three.js r${"186"}`),t.addEventListener("webglcontextlost",Mt,!1),t.addEventListener("webglcontextrestored",dt,!1),t.addEventListener("webglcontextcreationerror",Vn,!1),L===null){let D="webgl2";if(L=ut(D,A),L===null)throw ut(D)?new Error("THREE.WebGLRenderer: Error creating WebGL context with your selected attributes."):new Error("THREE.WebGLRenderer: Error creating WebGL context.")}Fe()}catch(A){throw t.removeEventListener("webglcontextlost",Mt,!1),t.removeEventListener("webglcontextrestored",dt,!1),t.removeEventListener("webglcontextcreationerror",Vn,!1),Pe("WebGLRenderer: "+A.message),A}function Fe(){nt=new _M(L),nt.init(),_e=new t_(L,nt),C=new aM(L,nt,e,_e),M=new tb(L,nt),C.reversedDepthBuffer&&d&&M.buffers.depth.setReversed(!0),z=L.createFramebuffer(),N=L.createFramebuffer(),B=L.createFramebuffer(),O=new vM(L),G=new VS,Y=new nb(L,nt,M,G,C,_e,O),le=new gM(I),he=new Sx(L),be=new rM(L,he),Z=new xM(L,he,O,be),$=new SM(L,Z,he,be,O),U=new MM(L,C,Y),Ue=new lM(G),pe=new kS(I,le,nt,C,be,Ue),De=new ob(I,G),ye=new HS,me=new KS(nt),Ze=new sM(I,le,M,$,p,l),Ve=new eb(I,$,C),se=new ab(L,O,C,M),ge=new oM(L,nt,O),j=new yM(L,nt,O),O.programs=pe.programs,I.capabilities=C,I.extensions=nt,I.properties=G,I.renderLists=ye,I.shadowMap=Ve,I.state=M,I.info=O}_!==fn&&(E=new TM(_,t.width,t.height,a,i,s));let Ie=new Sf(I,L);this.xr=Ie,this.getContext=function(){return L},this.getContextAttributes=function(){return L.getContextAttributes()},this.forceContextLoss=function(){let A=nt.get("WEBGL_lose_context");A&&A.loseContext()},this.forceContextRestore=function(){let A=nt.get("WEBGL_lose_context");A&&A.restoreContext()},this.getPixelRatio=function(){return ee},this.setPixelRatio=function(A){A!==void 0&&(ee=A,this.setSize(ot,K,!1))},this.getSize=function(A){return A.set(ot,K)},this.setSize=function(A,D,W=!0){if(Ie.isPresenting){de("WebGLRenderer: Can't change size while VR device is presenting.");return}ot=A,K=D,t.width=Math.floor(A*ee),t.height=Math.floor(D*ee),W===!0&&(t.style.width=A+"px",t.style.height=D+"px"),E!==null&&E.setSize(t.width,t.height),this.setViewport(0,0,A,D)},this.getDrawingBufferSize=function(A){return A.set(ot*ee,K*ee).floor()},this.setDrawingBufferSize=function(A,D,W){ot=A,K=D,ee=W,t.width=Math.floor(A*W),t.height=Math.floor(D*W),this.setViewport(0,0,A,D)},this.setEffects=function(A){if(_===fn){Pe("WebGLRenderer: setEffects() requires outputBufferType set to HalfFloatType or FloatType.");return}if(A){for(let D=0;D{function Se(){if(k.forEach(function(Ee){let Re=G.get(Ee).currentProgram;(Re===void 0||Re.isReady())&&k.delete(Ee)}),k.size===0){V(A);return}setTimeout(Se,10)}nt.get("KHR_parallel_shader_compile")!==null?Se():setTimeout(Se,10)})};let vu=null;function y_(A){vu&&vu(A)}function sp(){us.stop()}function rp(){us.start()}let us=new Kg;us.setAnimationLoop(y_),typeof self<"u"&&us.setContext(self),this.setAnimationLoop=function(A){vu=A,Ie.setAnimationLoop(A),A===null?us.stop():us.start()},Ie.addEventListener("sessionstart",sp),Ie.addEventListener("sessionend",rp),this.render=function(A,D){if(D!==void 0&&D.isCamera!==!0){Pe("WebGLRenderer.render: camera is not an instance of THREE.Camera.");return}if(P===!0)return;F!==null&&F.renderStart(A,D);let W=Ie.enabled===!0&&Ie.isPresenting===!0,k=E!==null&&(ie===null||W)&&E.begin(I,ie);if(A.matrixWorldAutoUpdate===!0&&A.updateMatrixWorld(),D.parent===null&&D.matrixWorldAutoUpdate===!0&&D.updateMatrixWorld(),Ie.enabled===!0&&Ie.isPresenting===!0&&(E===null||E.isCompositing()===!1)&&(Ie.cameraAutoUpdate===!0&&Ie.updateCamera(D),D=Ie.getCamera()),A.isScene===!0&&A.onBeforeRender(I,A,D,ie),S=me.get(A,v.length),S.init(D),S.state.textureUnits=Y.getTextureUnits(),v.push(S),ae.multiplyMatrices(D.projectionMatrix,D.matrixWorldInverse),te.setFromProjectionMatrix(ae,_n,D.reversedDepth),oe=this.localClippingEnabled,re=Ue.init(this.clippingPlanes,oe),T=ye.get(A,w.length),T.init(),w.push(T),Ie.enabled===!0&&Ie.isPresenting===!0){let Ee=I.xr.getDepthSensingMesh();Ee!==null&&Mu(Ee,D,-1/0,I.sortObjects)}Mu(A,D,0,I.sortObjects),T.finish(),F!==null&&F.updateLights(S.state.lightsArray),I.sortObjects===!0&&T.sort(ve,Ge),Xe=Ie.enabled===!1||Ie.isPresenting===!1||Ie.hasDepthSensing()===!1,Xe&&Ze.addToRenderList(T,A),this.info.render.frame++,this.info.autoReset===!0&&this.info.reset(),re===!0&&Ue.beginShadows();let V=S.state.shadowsArray;if(Ve.render(V,A,D),re===!0&&Ue.endShadows(),(k&&E.hasRenderPass())===!1){let Ee=T.opaque,Me=T.transmissive;if(S.setupLights(),D.isArrayCamera){let Re=D.cameras;if(Me.length>0)for(let Le=0,$e=Re.length;Le<$e;Le++){let it=Re[Le];ap(Ee,Me,A,it)}Xe&&Ze.render(A);for(let Le=0,$e=Re.length;Le<$e;Le++){let it=Re[Le];op(T,A,it,it.viewport)}}else Me.length>0&&ap(Ee,Me,A,D),Xe&&Ze.render(A),op(T,A,D)}ie!==null&&X===0&&(Y.updateMultisampleRenderTarget(ie),Y.updateRenderTargetMipmap(ie)),k&&E.end(I),A.isScene===!0&&A.onAfterRender(I,A,D),be.resetDefaultState(),q=-1,Q=null,v.pop(),v.length>0?(S=v[v.length-1],Y.setTextureUnits(S.state.textureUnits),re===!0&&Ue.setGlobalState(I.clippingPlanes,S.state.camera)):S=null,w.pop(),w.length>0?T=w[w.length-1]:T=null,F!==null&&F.renderEnd()};function Mu(A,D,W,k){if(A.visible===!1)return;if(A.layers.test(D.layers)){if(A.isGroup)W=A.renderOrder;else if(A.isLOD)A.autoUpdate===!0&&A.update(D);else if(A.isLightProbeGrid)S.pushLightProbeGrid(A);else if(A.isLight)S.pushLight(A),A.castShadow&&S.pushShadow(A);else if(A.isSprite){if(!A.frustumCulled||A.intersectsFrustum(te)){k&&ke.setFromMatrixPosition(A.matrixWorld).applyMatrix4(ae);let Ee=$.update(A),Me=A.material;Me.visible&&T.push(A,Ee,Me,W,ke.z,null,D)}}else if((A.isMesh||A.isLine||A.isPoints)&&(!A.frustumCulled||A.intersectsFrustum(te))){let Ee=$.update(A),Me=A.material;if(k&&(A.boundingSphere!==void 0?(A.boundingSphere===null&&A.computeBoundingSphere(),ke.copy(A.boundingSphere.center)):(Ee.boundingSphere===null&&Ee.computeBoundingSphere(),ke.copy(Ee.boundingSphere.center)),ke.applyMatrix4(A.matrixWorld).applyMatrix4(ae)),Array.isArray(Me)){let Re=Ee.groups;for(let Le=0,$e=Re.length;Le<$e;Le++){let it=Re[Le],Ce=Me[it.materialIndex];Ce&&Ce.visible&&T.push(A,Ee,Ce,W,ke.z,it,D)}}else Me.visible&&T.push(A,Ee,Me,W,ke.z,null,D)}}let Se=A.children;for(let Ee=0,Me=Se.length;Ee0&&Gl(V,D,W),Se.length>0&&Gl(Se,D,W),Ee.length>0&&Gl(Ee,D,W),M.buffers.depth.setTest(!0),M.buffers.depth.setMask(!0),M.buffers.color.setMask(!0),M.setPolygonOffset(!1)}function ap(A,D,W,k){if((W.isScene===!0?W.overrideMaterial:null)!==null)return;if(S.state.transmissionRenderTarget[k.id]===void 0){let Ce=nt.has("EXT_color_buffer_half_float")||nt.has("EXT_color_buffer_float");S.state.transmissionRenderTarget[k.id]=new Zt(1,1,{generateMipmaps:!0,type:Ce?Bn:fn,minFilter:vn,samples:Math.max(4,C.samples),stencilBuffer:s,resolveDepthBuffer:!1,resolveStencilBuffer:!1,storeMultisampledDepthBuffer:!1,storeMultisampledStencilBuffer:!1,colorSpace:Je.workingColorSpace})}let Se=S.state.transmissionRenderTarget[k.id],Ee=k.viewport||ne;Se.setSize(Ee.z*I.transmissionResolutionScale,Ee.w*I.transmissionResolutionScale);let Me=I.getRenderTarget(),Re=I.getActiveCubeFace(),Le=I.getActiveMipmapLevel();I.setRenderTarget(Se),I.getClearColor(ct),tt=I.getClearAlpha(),tt<1&&I.setClearColor(16777215,.5),I.clear(),Xe&&Ze.render(W);let $e=I.toneMapping;I.toneMapping=On;let it=k.viewport;if(k.viewport!==void 0&&(k.viewport=void 0),S.setupLightsView(k),re===!0&&Ue.setGlobalState(I.clippingPlanes,k),Gl(A,W,k),Y.updateMultisampleRenderTarget(Se),Y.updateRenderTargetMipmap(Se),nt.has("WEBGL_multisampled_render_to_texture")===!1){let Ce=!1;for(let ft=0,Bt=D.length;ft0,k.currentProgram=it,k.uniformsList=null,it}function cp(A){if(A.uniformsList===null){let D=A.currentProgram.getUniforms();A.uniformsList=xo.seqWithValue(D.seq,A.uniforms)}return A.uniformsList}function hp(A,D){let W=G.get(A);W.outputColorSpace=D.outputColorSpace,W.batching=D.batching,W.batchingColor=D.batchingColor,W.instancing=D.instancing,W.instancingColor=D.instancingColor,W.instancingMorph=D.instancingMorph,W.skinning=D.skinning,W.morphTargets=D.morphTargets,W.morphNormals=D.morphNormals,W.morphColors=D.morphColors,W.morphTargetsCount=D.morphTargetsCount,W.numClippingPlanes=D.numClippingPlanes,W.numIntersection=D.numClipIntersection,W.vertexAlphas=D.vertexAlphas,W.vertexTangents=D.vertexTangents,W.toneMapping=D.toneMapping}function v_(A,D){if(A.length===0)return null;if(A.length===1)return A[0].texture!==null?A[0]:null;x.setFromMatrixPosition(D.matrixWorld);for(let W=0,k=A.length;W0),Ce=!!W.morphAttributes.position,ft=!!W.morphAttributes.normal,Bt=!!W.morphAttributes.color,bt=On;k.toneMapped&&(ie===null||ie.isXRRenderTarget===!0)&&(bt=I.toneMapping);let yt=W.morphAttributes.position||W.morphAttributes.normal||W.morphAttributes.color,Jt=yt!==void 0?yt.length:0,Ae=G.get(k),on=S.state.lights;if(re===!0&&(oe===!0||A!==Q)){let St=A===Q&&k.id===q;Ue.setState(k,A,St)}let at=!1;k.version===Ae.__version?(Ae.needsLights&&Ae.lightsStateVersion!==on.state.version||Ae.outputColorSpace!==Me||V.isBatchedMesh&&Ae.batching===!1||!V.isBatchedMesh&&Ae.batching===!0||V.isBatchedMesh&&Ae.batchingColor===!0&&V._colorsTexture===null||V.isBatchedMesh&&Ae.batchingColor===!1&&V._colorsTexture!==null||V.isInstancedMesh&&Ae.instancing===!1||!V.isInstancedMesh&&Ae.instancing===!0||V.isSkinnedMesh&&Ae.skinning===!1||!V.isSkinnedMesh&&Ae.skinning===!0||V.isInstancedMesh&&Ae.instancingColor===!0&&V.instanceColor===null||V.isInstancedMesh&&Ae.instancingColor===!1&&V.instanceColor!==null||V.isInstancedMesh&&Ae.instancingMorph===!0&&V.morphTexture===null||V.isInstancedMesh&&Ae.instancingMorph===!1&&V.morphTexture!==null||Ae.envMap!==Le||k.fog===!0&&Ae.fog!==Se||Ae.numClippingPlanes!==void 0&&(Ae.numClippingPlanes!==Ue.numPlanes||Ae.numIntersection!==Ue.numIntersection)||Ae.vertexAlphas!==$e||Ae.vertexTangents!==it||Ae.morphTargets!==Ce||Ae.morphNormals!==ft||Ae.morphColors!==Bt||Ae.toneMapping!==bt||Ae.morphTargetsCount!==Jt||!!Ae.lightProbeGrid!=S.state.lightProbeGridArray.length>0)&&(at=!0):(at=!0,Ae.__version=k.version);let In=Ae.currentProgram;at===!0&&(In=Hl(k,D,V),F&&k.isNodeMaterial&&F.onUpdateProgram(k,In,Ae));let ri=!1,Vi=!1,tr=!1,xt=In.getUniforms(),Dt=Ae.uniforms;if(M.useProgram(In.program)&&(ri=!0,Vi=!0,tr=!0),k.id!==q&&(q=k.id,Vi=!0),Ae.needsLights){let St=v_(S.state.lightProbeGridArray,V);Ae.lightProbeGrid!==St&&(Ae.lightProbeGrid=St,Vi=!0)}if(ri||Q!==A){M.buffers.depth.getReversed()&&A.reversedDepth!==!0&&(A._reversedDepth=!0,A.updateProjectionMatrix()),xt.setValue(L,"projectionMatrix",A.projectionMatrix),xt.setValue(L,"viewMatrix",A.matrixWorldInverse);let Hi=xt.map.cameraPosition;Hi!==void 0&&Hi.setValue(L,ue.setFromMatrixPosition(A.matrixWorld)),C.logarithmicDepthBuffer&&xt.setValue(L,"logDepthBufFC",2/(Math.log(A.far+1)/Math.LN2)),(k.isMeshPhongMaterial||k.isMeshToonMaterial||k.isMeshLambertMaterial||k.isMeshBasicMaterial||k.isMeshStandardMaterial||k.isShaderMaterial)&&xt.setValue(L,"isOrthographic",A.isOrthographicCamera===!0),Q!==A&&(Q=A,Vi=!0,tr=!0)}if(Ae.needsLights&&(on.state.sunShadowMap.length>0&&xt.setValue(L,"sunShadowMap",on.state.sunShadowMap,Y),on.state.directionalShadowMap.length>0&&xt.setValue(L,"directionalShadowMap",on.state.directionalShadowMap,Y),on.state.spotShadowMap.length>0&&xt.setValue(L,"spotShadowMap",on.state.spotShadowMap,Y),on.state.pointShadowMap.length>0&&xt.setValue(L,"pointShadowMap",on.state.pointShadowMap,Y)),V.isSkinnedMesh){xt.setOptional(L,V,"bindMatrix"),xt.setOptional(L,V,"bindMatrixInverse");let St=V.skeleton;St&&(St.boneTexture===null&&St.computeBoneTexture(),xt.setValue(L,"boneTexture",St.boneTexture,Y))}V.isBatchedMesh&&(xt.setOptional(L,V,"batchingTexture"),xt.setValue(L,"batchingTexture",V._matricesTexture,Y),xt.setOptional(L,V,"batchingIdTexture"),xt.setValue(L,"batchingIdTexture",V._indirectTexture,Y),xt.setOptional(L,V,"batchingColorTexture"),V._colorsTexture!==null&&xt.setValue(L,"batchingColorTexture",V._colorsTexture,Y));let Gi=W.morphAttributes;if((Gi.position!==void 0||Gi.normal!==void 0||Gi.color!==void 0)&&U.update(V,W,In),(Vi||Ae.receiveShadow!==V.receiveShadow)&&(Ae.receiveShadow=V.receiveShadow,xt.setValue(L,"receiveShadow",V.receiveShadow)),(k.isMeshStandardMaterial||k.isMeshLambertMaterial||k.isMeshPhongMaterial)&&k.envMap===null&&D.environment!==null&&(Dt.envMapIntensity.value=D.environmentIntensity),Dt.dfgLUT!==void 0&&(Dt.dfgLUT.value=cb()),Vi){if(xt.setValue(L,"toneMappingExposure",I.toneMappingExposure),Ae.needsLights&&S_(Dt,tr),Se&&k.fog===!0&&De.refreshFogUniforms(Dt,Se),De.refreshMaterialUniforms(Dt,k,ee,K,S.state.transmissionRenderTarget[A.id]),Ae.needsLights&&Ae.lightProbeGrid){let St=Ae.lightProbeGrid;Dt.probesSH.value=St.texture,Dt.probesMin.value.copy(St.boundingBox.min),Dt.probesMax.value.copy(St.boundingBox.max),Dt.probesResolution.value.copy(St.resolution)}xo.upload(L,cp(Ae),Dt,Y)}if(k.isShaderMaterial&&k.uniformsNeedUpdate===!0&&(xo.upload(L,cp(Ae),Dt,Y),k.uniformsNeedUpdate=!1),k.isSpriteMaterial&&xt.setValue(L,"center",V.center),xt.setValue(L,"modelViewMatrix",V.modelViewMatrix),xt.setValue(L,"normalMatrix",V.normalMatrix),xt.setValue(L,"modelMatrix",V.matrixWorld),k.uniformsGroups!==void 0){let St=k.uniformsGroups;for(let Hi=0,nr=St.length;Hi0&&Y.useMultisampledRTT(A)===!1?k=G.get(A).__webglMultisampledFramebuffer:Array.isArray(Le)?k=Le[W]:k=Le,ne.copy(A.viewport),Ne.copy(A.scissor),we=A.scissorTest}else ne.copy(Te).multiplyScalar(ee).floor(),Ne.copy(We).multiplyScalar(ee).floor(),we=gt;if(W!==0&&(k=z),M.bindFramebuffer(L.FRAMEBUFFER,k)&&M.drawBuffers(A,k),M.viewport(ne),M.scissor(Ne),M.setScissorTest(we),V){let Me=G.get(A.texture);L.framebufferTexture2D(L.FRAMEBUFFER,L.COLOR_ATTACHMENT0,L.TEXTURE_CUBE_MAP_POSITIVE_X+D,Me.__webglTexture,W)}else if(Se){let Me=D;for(let Re=0;Re1&&L.readBuffer(L.COLOR_ATTACHMENT0+Me);let Ce=up(Le);if(Ce.__formatReadable===!1){Pe("WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");return}if(Ce.__typeReadable===!1){Pe("WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");return}D>=0&&D<=A.width-k&&W>=0&&W<=A.height-V&&L.readPixels(D,W,k,V,_e.convert($e),_e.convert(it),Se)}finally{let Le=ie!==null?G.get(ie).__webglFramebuffer:null;M.bindFramebuffer(L.FRAMEBUFFER,Le)}}},this.readRenderTargetPixelsAsync=async function(A,D,W,k,V,Se,Ee,Me=0){if(!(A&&A.isWebGLRenderTarget))throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let Re=G.get(A).__webglFramebuffer;if(A.isWebGLCubeRenderTarget&&Ee!==void 0&&(Re=Re[Ee]),Re)if(D>=0&&D<=A.width-k&&W>=0&&W<=A.height-V){M.bindFramebuffer(L.FRAMEBUFFER,Re);let Le=A.textures[Me],$e=Le.format,it=Le.type;A.textures.length>1&&L.readBuffer(L.COLOR_ATTACHMENT0+Me);let Ce=up(Le);if(Ce.__formatReadable===!1)throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(Ce.__typeReadable===!1)throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");let ft=L.createBuffer();L.bindBuffer(L.PIXEL_PACK_BUFFER,ft),L.bufferData(L.PIXEL_PACK_BUFFER,Se.byteLength,L.STREAM_READ),L.readPixels(D,W,k,V,_e.convert($e),_e.convert(it),0),L.bindBuffer(L.PIXEL_PACK_BUFFER,null);let Bt=ie!==null?G.get(ie).__webglFramebuffer:null;M.bindFramebuffer(L.FRAMEBUFFER,Bt);let bt=L.fenceSync(L.SYNC_GPU_COMMANDS_COMPLETE,0);return L.flush(),await gg(L,bt,4),L.bindBuffer(L.PIXEL_PACK_BUFFER,ft),L.getBufferSubData(L.PIXEL_PACK_BUFFER,0,Se),L.bindBuffer(L.PIXEL_PACK_BUFFER,null),L.deleteBuffer(ft),L.deleteSync(bt),Se}else throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")},this.copyFramebufferToTexture=function(A,D=null,W=0){let k=Math.pow(2,-W),V=Math.floor(A.image.width*k),Se=Math.floor(A.image.height*k),Ee=D!==null?D.x:0,Me=D!==null?D.y:0;Y.setTexture2D(A,0),L.copyTexSubImage2D(L.TEXTURE_2D,W,0,0,Ee,Me,V,Se),M.unbindTexture()},this.copyTextureToTexture=function(A,D,W=null,k=null,V=0,Se=0){let Ee,Me,Re,Le,$e,it,Ce,ft,Bt,bt=A.isCompressedTexture?A.mipmaps[Se]:A.image;if(W!==null)Ee=W.max.x-W.min.x,Me=W.max.y-W.min.y,Re=W.isBox3?W.max.z-W.min.z:1,Le=W.min.x,$e=W.min.y,it=W.isBox3?W.min.z:0;else{let Dt=Math.pow(2,-V);Ee=Math.floor(bt.width*Dt),Me=Math.floor(bt.height*Dt),A.isDataArrayTexture?Re=bt.depth:A.isData3DTexture?Re=Math.floor(bt.depth*Dt):Re=1,Le=0,$e=0,it=0}k!==null?(Ce=k.x,ft=k.y,Bt=k.z):(Ce=0,ft=0,Bt=0);let yt=_e.convert(D.format),Jt=_e.convert(D.type),Ae;D.isData3DTexture?(Y.setTexture3D(D,0),Ae=L.TEXTURE_3D):D.isDataArrayTexture||D.isCompressedArrayTexture?(Y.setTexture2DArray(D,0),Ae=L.TEXTURE_2D_ARRAY):(Y.setTexture2D(D,0),Ae=L.TEXTURE_2D),M.activeTexture(L.TEXTURE0),M.pixelStorei(L.UNPACK_FLIP_Y_WEBGL,D.flipY),M.pixelStorei(L.UNPACK_PREMULTIPLY_ALPHA_WEBGL,D.premultiplyAlpha),M.pixelStorei(L.UNPACK_ALIGNMENT,D.unpackAlignment);let on=M.getParameter(L.UNPACK_ROW_LENGTH),at=M.getParameter(L.UNPACK_IMAGE_HEIGHT),In=M.getParameter(L.UNPACK_SKIP_PIXELS),ri=M.getParameter(L.UNPACK_SKIP_ROWS),Vi=M.getParameter(L.UNPACK_SKIP_IMAGES);M.pixelStorei(L.UNPACK_ROW_LENGTH,bt.width),M.pixelStorei(L.UNPACK_IMAGE_HEIGHT,bt.height),M.pixelStorei(L.UNPACK_SKIP_PIXELS,Le),M.pixelStorei(L.UNPACK_SKIP_ROWS,$e),M.pixelStorei(L.UNPACK_SKIP_IMAGES,it);let tr=A.isDataArrayTexture||A.isData3DTexture,xt=D.isDataArrayTexture||D.isData3DTexture;if(A.isDepthTexture){let Dt=G.get(A),Gi=G.get(D),St=G.get(Dt.__renderTarget),Hi=G.get(Gi.__renderTarget);M.bindFramebuffer(L.READ_FRAMEBUFFER,St.__webglFramebuffer),M.bindFramebuffer(L.DRAW_FRAMEBUFFER,Hi.__webglFramebuffer);for(let nr=0;nrMath.PI&&(n-=Mn),i<-Math.PI?i+=Mn:i>Math.PI&&(i-=Mn),n<=i?this._spherical.theta=Math.max(n,Math.min(i,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(n+i)/2?Math.max(n,this._spherical.theta):Math.min(i,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let s=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{let o=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),s=o!=this._spherical.radius}if(Ht.setFromSpherical(this._spherical),Ht.applyQuaternion(this._quatInverse),t.copy(this.target).add(Ht),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let o=null;if(this.object.isPerspectiveCamera){let a=Ht.length();o=this._clampDistance(a*this._scale);let l=a-o;this.object.position.addScaledVector(this._dollyDirection,l),this.object.updateMatrixWorld(),s=!!l}else if(this.object.isOrthographicCamera){let a=new R(this._mouse.x,this._mouse.y,0);a.unproject(this.object);let l=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),s=l!==this.object.zoom;let c=new R(this._mouse.x,this._mouse.y,0);c.unproject(this.object),this.object.position.sub(c).add(a),this.object.updateMatrixWorld(),o=Ht.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;o!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(o).add(this.object.position):(uu.origin.copy(this.object.position),uu.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(uu.direction))Af||8*(1-this._lastQuaternion.dot(this.object.quaternion))>Af||this._lastTargetPosition.distanceToSquared(this.target)>Af?(this.dispatchEvent(i_),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(e){return e!==null?Mn/60*this.autoRotateSpeed*e:Mn/60/60*this.autoRotateSpeed}_getZoomScale(e){let t=Math.abs(e*.01);return Math.pow(.95,this.zoomSpeed*t)}_rotateLeft(e){this._sphericalDelta.theta-=e}_rotateUp(e){this._sphericalDelta.phi-=e}_panLeft(e,t){Ht.setFromMatrixColumn(t,0),Ht.multiplyScalar(-e),this._panOffset.add(Ht)}_panUp(e,t){this.screenSpacePanning===!0?Ht.setFromMatrixColumn(t,1):(Ht.setFromMatrixColumn(t,0),Ht.crossVectors(this.object.up,Ht)),Ht.multiplyScalar(e),this._panOffset.add(Ht)}_pan(e,t){let n=this.domElement;if(this.object.isPerspectiveCamera){let i=this.object.position;Ht.copy(i).sub(this.target);let s=Ht.length();s*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*e*s/n.clientHeight,this.object.matrix),this._panUp(2*t*s/n.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(e*(this.object.right-this.object.left)/this.object.zoom/n.clientWidth,this.object.matrix),this._panUp(t*(this.object.top-this.object.bottom)/this.object.zoom/n.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(e){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(e){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(e,t){if(!this.zoomToCursor)return;this._performCursorZoom=!0;let n=this.domElement.getBoundingClientRect(),i=e-n.left,s=t-n.top,o=n.width,a=n.height;this._mouse.x=i/o*2-1,this._mouse.y=-(s/a)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(e){return Math.max(this.minDistance,Math.min(this.maxDistance,e))}_handleMouseDownRotate(e){this._rotateStart.set(e.clientX,e.clientY)}_handleMouseDownDolly(e){this._updateZoomParameters(e.clientX,e.clientX),this._dollyStart.set(e.clientX,e.clientY)}_handleMouseDownPan(e){this._panStart.set(e.clientX,e.clientY)}_handleMouseMoveRotate(e){this._rotateEnd.set(e.clientX,e.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);let t=this.domElement;this._rotateLeft(Mn*this._rotateDelta.x/t.clientHeight),this._rotateUp(Mn*this._rotateDelta.y/t.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(e){this._dollyEnd.set(e.clientX,e.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(e){this._panEnd.set(e.clientX,e.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(e){this._updateZoomParameters(e.clientX,e.clientY),e.deltaY<0?this._dollyIn(this._getZoomScale(e.deltaY)):e.deltaY>0&&this._dollyOut(this._getZoomScale(e.deltaY)),this.update()}_handleKeyDown(e){let t=!1;switch(e.code){case this.keys.UP:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateUp(Mn*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,this.keyPanSpeed),t=!0;break;case this.keys.BOTTOM:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateUp(-Mn*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,-this.keyPanSpeed),t=!0;break;case this.keys.LEFT:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateLeft(Mn*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(this.keyPanSpeed,0),t=!0;break;case this.keys.RIGHT:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateLeft(-Mn*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(-this.keyPanSpeed,0),t=!0;break}t&&(e.preventDefault(),this.update())}_handleTouchStartRotate(e){if(this._pointers.length===1)this._rotateStart.set(e.pageX,e.pageY);else{let t=this._getSecondPointerPosition(e),n=.5*(e.pageX+t.x),i=.5*(e.pageY+t.y);this._rotateStart.set(n,i)}}_handleTouchStartPan(e){if(this._pointers.length===1)this._panStart.set(e.pageX,e.pageY);else{let t=this._getSecondPointerPosition(e),n=.5*(e.pageX+t.x),i=.5*(e.pageY+t.y);this._panStart.set(n,i)}}_handleTouchStartDolly(e){let t=this._getSecondPointerPosition(e),n=e.pageX-t.x,i=e.pageY-t.y,s=Math.sqrt(n*n+i*i);this._dollyStart.set(0,s)}_handleTouchStartDollyPan(e){this.enableZoom&&this._handleTouchStartDolly(e),this.enablePan&&this._handleTouchStartPan(e)}_handleTouchStartDollyRotate(e){this.enableZoom&&this._handleTouchStartDolly(e),this.enableRotate&&this._handleTouchStartRotate(e)}_handleTouchMoveRotate(e){if(this._pointers.length==1)this._rotateEnd.set(e.pageX,e.pageY);else{let n=this._getSecondPointerPosition(e),i=.5*(e.pageX+n.x),s=.5*(e.pageY+n.y);this._rotateEnd.set(i,s)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);let t=this.domElement;this._rotateLeft(Mn*this._rotateDelta.x/t.clientHeight),this._rotateUp(Mn*this._rotateDelta.y/t.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(e){if(this._pointers.length===1)this._panEnd.set(e.pageX,e.pageY);else{let t=this._getSecondPointerPosition(e),n=.5*(e.pageX+t.x),i=.5*(e.pageY+t.y);this._panEnd.set(n,i)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(e){let t=this._getSecondPointerPosition(e),n=e.pageX-t.x,i=e.pageY-t.y,s=Math.sqrt(n*n+i*i);this._dollyEnd.set(0,s),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);let o=(e.pageX+t.x)*.5,a=(e.pageY+t.y)*.5;this._updateZoomParameters(o,a)}_handleTouchMoveDollyPan(e){this.enableZoom&&this._handleTouchMoveDolly(e),this.enablePan&&this._handleTouchMovePan(e)}_handleTouchMoveDollyRotate(e){this.enableZoom&&this._handleTouchMoveDolly(e),this.enableRotate&&this._handleTouchMoveRotate(e)}_addPointer(e){this._pointers.push(e.pointerId)}_removePointer(e){delete this._pointerPositions[e.pointerId];for(let t=0;t=2.0 are supported."));return}let c=new tp(s,{path:t||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let h=0;h=0&&a[u]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+u+'".')}}c.setExtensions(o),c.setPlugins(a),c.parse(n,i)}parseAsync(e,t){let n=this;return new Promise(function(i,s){n.parse(e,t,i,s)})}};function bb(){let r={};return{get:function(e){return r[e]},add:function(e,t){r[e]=t},remove:function(e){delete r[e]},removeAll:function(){r={}}}}function Ot(r,e,t){let n=r.json.materials[e];return n.extensions&&n.extensions[t]?n.extensions[t]:null}var et={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_DISPERSION:"KHR_materials_dispersion",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",KHR_MESHOPT_COMPRESSION:"KHR_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"},Pf=class{constructor(e){this.parser=e,this.name=et.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){let e=this.parser,t=this.parser.json.nodes||[];for(let n=0,i=t.length;n=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return t.loadTextureImage(e,s.source,o)}},Xf=class{constructor(e){this.parser=e,this.name=et.EXT_TEXTURE_WEBP}loadTexture(e){let t=this.name,n=this.parser,i=n.json,s=i.textures[e];if(!s.extensions||!s.extensions[t])return null;let o=s.extensions[t],a=i.images[o.source],l=n.textureLoader;if(a.uri){let c=n.options.manager.getHandler(a.uri);c!==null&&(l=c)}return n.loadTextureImage(e,o.source,l)}},qf=class{constructor(e){this.parser=e,this.name=et.EXT_TEXTURE_AVIF}loadTexture(e){let t=this.name,n=this.parser,i=n.json,s=i.textures[e];if(!s.extensions||!s.extensions[t])return null;let o=s.extensions[t],a=i.images[o.source],l=n.textureLoader;if(a.uri){let c=n.options.manager.getHandler(a.uri);c!==null&&(l=c)}return n.loadTextureImage(e,o.source,l)}},pu=class{constructor(e,t){this.name=t,this.parser=e}loadBufferView(e){let t=this.parser.json,n=t.bufferViews[e];if(n.extensions&&n.extensions[this.name]){let i=n.extensions[this.name],s=this.parser.getDependency("buffer",i.buffer),o=this.parser.options.meshoptDecoder;if(!o||!o.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return s.then(function(a){let l=i.byteOffset||0,c=i.byteLength||0,h=i.count,u=i.byteStride,d=new Uint8Array(a,l,c);return o.decodeGltfBufferAsync?o.decodeGltfBufferAsync(h,u,d,i.mode,i.filter).then(function(f){return f.buffer}):o.ready.then(function(){let f=new ArrayBuffer(h*u);return o.decodeGltfBuffer(new Uint8Array(f),h,u,d,i.mode,i.filter),f})})}else return null}},Yf=class{constructor(e){this.name=et.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){let t=this.parser.json,n=t.nodes[e];if(!n.extensions||!n.extensions[this.name]||n.mesh===void 0)return null;let i=t.meshes[n.mesh];for(let c of i.primitives)if(c.mode!==zn.TRIANGLES&&c.mode!==zn.TRIANGLE_STRIP&&c.mode!==zn.TRIANGLE_FAN&&c.mode!==void 0)return null;let o=n.extensions[this.name].attributes,a=[],l={};for(let c in o)a.push(this.parser.getDependency("accessor",o[c]).then(h=>(l[c]=h,l[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(e)),Promise.all(a).then(c=>{let h=c.pop(),u=h.isGroup?h.children:[h],d=c[0].count,f=[];for(let p of u){let _=new ze,g=new R,m=new wt,y=new R(1,1,1),b=new Ii(p.geometry,p.material,d);for(let T=0;T0||r.search(/^data\:image\/jpeg/)===0?"image/jpeg":r.search(/\.webp($|\?)/i)>0||r.search(/^data\:image\/webp/)===0?"image/webp":r.search(/\.ktx2($|\?)/i)>0||r.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}var Pb=new ze,tp=class{constructor(e={},t={}){this.json=e,this.extensions={},this.plugins={},this.options=t,this.cache=new bb,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let n=!1,i=-1,s=!1,o=-1;if(typeof navigator<"u"&&typeof navigator.userAgent<"u"){let a=navigator.userAgent;n=/^((?!chrome|android).)*safari/i.test(a)===!0;let l=a.match(/Version\/(\d+)/);i=n&&l?parseInt(l[1],10):-1,s=a.indexOf("Firefox")>-1,o=s?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||n&&i<17||s&&o<98?this.textureLoader=new Jr(this.options.manager):this.textureLoader=new $r(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new kt(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),this.options.crossOrigin==="use-credentials"&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){let n=this,i=this.json,s=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(o){return o._markDefs&&o._markDefs()}),Promise.all(this._invokeAll(function(o){return o.beforeRoot&&o.beforeRoot()})).then(function(){return Promise.all([n.getDependencies("scene"),n.getDependencies("animation"),n.getDependencies("camera")])}).then(function(o){let a={scene:o[0][i.scene||0],scenes:o[0],animations:o[1],cameras:o[2],asset:i.asset,parser:n,userData:{}};return er(s,a,i),Mi(a,i),Promise.all(n._invokeAll(function(l){return l.afterRoot&&l.afterRoot(a)})).then(function(){for(let l of a.scenes)l.updateMatrixWorld();e(a)})}).catch(t)}_markDefs(){let e=this.json.nodes||[],t=this.json.skins||[],n=this.json.meshes||[];for(let i=0,s=t.length;i{let l=this.associations.get(o);l!=null&&this.associations.set(a,l);for(let[c,h]of o.children.entries())s(h,a.children[c])};return s(n,i),i.name+="_instance_"+e.uses[t]++,i}_invokeOne(e){let t=Object.values(this.plugins);t.push(this);for(let n=0;n=2&&g.setY(E,S[w*l+1]),l>=3&&g.setZ(E,S[w*l+2]),l>=4&&g.setW(E,S[w*l+3]),l>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}g.normalized=p}return g})}loadTexture(e){let t=this.json,n=this.options,s=t.textures[e].source,o=t.images[s],a=this.textureLoader;if(o.uri){let l=n.manager.getHandler(o.uri);l!==null&&(a=l)}return this.loadTextureImage(e,s,a)}loadTextureImage(e,t,n){let i=this,s=this.json,o=s.textures[e],a=s.images[t],l=(a.uri||a.bufferView)+":"+o.sampler;if(this.textureCache[l])return this.textureCache[l];let c=this.loadImageSource(t,n).then(function(h){h.flipY=!1,h.name=o.name||a.name||"",h.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(h.name=a.uri);let d=(s.samplers||{})[o.sampler]||{};return h.magFilter=c_[d.magFilter]||pt,h.minFilter=c_[d.minFilter]||vn,h.wrapS=h_[d.wrapS]||li,h.wrapT=h_[d.wrapT]||li,h.generateMipmaps=!h.isCompressedTexture&&h.minFilter!==At&&h.minFilter!==pt,i.associations.set(h,{textures:e}),h}).catch(function(){return null});return this.textureCache[l]=c,c}loadImageSource(e,t){let n=this,i=this.json,s=this.options;if(this.sourceCache[e]!==void 0)return this.sourceCache[e].then(u=>u.clone());let o=i.images[e],a=self.URL||self.webkitURL,l=o.uri||"",c=!1;if(o.bufferView!==void 0)l=n.getDependency("bufferView",o.bufferView).then(function(u){c=!0;let d=new Blob([u],{type:o.mimeType});return l=a.createObjectURL(d),l});else if(o.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+e+" is missing URI and bufferView");let h=Promise.resolve(l).then(function(u){return new Promise(function(d,f){let p=d;t.isImageBitmapLoader===!0&&(p=function(_){let g=new Et(_);g.needsUpdate=!0,d(g)}),t.load(Fn.resolveURL(u,s.path),p,void 0,f)})}).then(function(u){return c===!0&&a.revokeObjectURL(l),Mi(u,o),u.userData.mimeType=o.mimeType||Ib(o.uri),u}).catch(function(u){throw console.error("THREE.GLTFLoader: Couldn't load texture",l),u});return this.sourceCache[e]=h,h}assignTexture(e,t,n,i){let s=this;return this.getDependency("texture",n.index).then(function(o){if(!o)return null;if(n.texCoord!==void 0&&n.texCoord>0&&(o=o.clone(),o.channel=n.texCoord),s.extensions[et.KHR_TEXTURE_TRANSFORM]){let a=n.extensions!==void 0?n.extensions[et.KHR_TEXTURE_TRANSFORM]:void 0;if(a){let l=s.associations.get(o);o=s.extensions[et.KHR_TEXTURE_TRANSFORM].extendTexture(o,a),s.associations.set(o,l)}}return i!==void 0&&(o.colorSpace=i),e[t]=o,o})}assignFinalMaterial(e){let t=e.geometry,n=e.material,i=t.attributes.tangent===void 0,s=t.attributes.color!==void 0,o=t.attributes.normal===void 0;if(e.isPoints){let a="PointsMaterial:"+n.uuid,l=this.cache.get(a);l||(l=new wn,vt.prototype.copy.call(l,n),l.color.copy(n.color),l.map=n.map,l.sizeAttenuation=!1,this.cache.add(a,l)),n=l}else if(e.isLine){let a="LineBasicMaterial:"+n.uuid,l=this.cache.get(a);l||(l=new Rt,vt.prototype.copy.call(l,n),l.color.copy(n.color),l.map=n.map,this.cache.add(a,l)),n=l}if(i||s||o){let a="ClonedMaterial:"+n.uuid+":";i&&(a+="derivative-tangents:"),s&&(a+="vertex-colors:"),o&&(a+="flat-shading:");let l=this.cache.get(a);l||(l=n.clone(),s&&(l.vertexColors=!0),o&&(l.flatShading=!0),i&&(l.normalScale&&(l.normalScale.y*=-1),l.clearcoatNormalScale&&(l.clearcoatNormalScale.y*=-1)),this.cache.add(a,l),this.associations.set(l,this.associations.get(n))),n=l}e.material=n}getMaterialType(){return Un}loadMaterial(e){let t=this,n=this.json,i=this.extensions,s=n.materials[e],o,a={},l=s.extensions||{},c=[];if(l[et.KHR_MATERIALS_UNLIT]){let u=i[et.KHR_MATERIALS_UNLIT];o=u.getMaterialType(),c.push(u.extendParams(a,s,t))}else{let u=s.pbrMetallicRoughness||{};if(a.color=new ce(1,1,1),a.opacity=1,Array.isArray(u.baseColorFactor)){let d=u.baseColorFactor;a.color.setRGB(d[0],d[1],d[2],nn),a.opacity=d[3]}u.baseColorTexture!==void 0&&c.push(t.assignTexture(a,"map",u.baseColorTexture,Tt)),a.metalness=u.metallicFactor!==void 0?u.metallicFactor:1,a.roughness=u.roughnessFactor!==void 0?u.roughnessFactor:1,u.metallicRoughnessTexture!==void 0&&(c.push(t.assignTexture(a,"metalnessMap",u.metallicRoughnessTexture)),c.push(t.assignTexture(a,"roughnessMap",u.metallicRoughnessTexture))),o=this._invokeOne(function(d){return d.getMaterialType&&d.getMaterialType(e)}),c.push(Promise.all(this._invokeAll(function(d){return d.extendMaterialParams&&d.extendMaterialParams(e,a)})))}s.doubleSided===!0&&(a.side=Rn);let h=s.alphaMode||Cf.OPAQUE;if(h===Cf.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,h===Cf.MASK&&(a.alphaTest=s.alphaCutoff!==void 0?s.alphaCutoff:.5)),s.normalTexture!==void 0&&o!==Kt&&(c.push(t.assignTexture(a,"normalMap",s.normalTexture)),a.normalScale=new J(1,1),s.normalTexture.scale!==void 0)){let u=s.normalTexture.scale;a.normalScale.set(u,u)}if(s.occlusionTexture!==void 0&&o!==Kt&&(c.push(t.assignTexture(a,"aoMap",s.occlusionTexture)),s.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=s.occlusionTexture.strength)),s.emissiveFactor!==void 0&&o!==Kt){let u=s.emissiveFactor;a.emissive=new ce().setRGB(u[0],u[1],u[2],nn)}return s.emissiveTexture!==void 0&&o!==Kt&&c.push(t.assignTexture(a,"emissiveMap",s.emissiveTexture,Tt)),Promise.all(c).then(function(){let u=new o(a);return s.name&&(u.name=s.name),Mi(u,s),t.associations.set(u,{materials:e}),s.extensions&&er(i,u,s),u})}createUniqueName(e){let t=lt.sanitizeNodeName(e||"");return t in this.nodeNamesUsed?t+"_"+ ++this.nodeNamesUsed[t]:(this.nodeNamesUsed[t]=0,t)}loadGeometries(e){let t=this,n=this.extensions,i=this.primitiveCache;function s(a){return n[et.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,t).then(function(l){return u_(l,a,t)})}let o=[];for(let a=0,l=e.length;awf(f,po)):c.mode===zn.TRIANGLE_FAN&&(d=d.then(f=>wf(f,js))),i[h]={primitive:c,promise:d},o.push(d)}}return Promise.all(o)}loadMesh(e){let t=this,n=this.json,i=this.extensions,s=n.meshes[e],o=s.primitives,a=[];for(let l=0,c=o.length;l0&&Rb(m,s),m.name=t.createUniqueName(s.name||"mesh_"+e),Mi(m,s),g.extensions&&er(i,m,g),t.assignFinalMaterial(m),u.push(m)}for(let f=0,p=u.length;f0){let f=h.userData.pivot,p=u[0];h.pivot=new R().fromArray(f),h.position.x-=f[0],h.position.y-=f[1],h.position.z-=f[2],p.position.set(0,0,0),delete h.userData.pivot}return h})}_loadNodeShallow(e){let t=this.json,n=this.extensions,i=this;if(this.nodeCache[e]!==void 0)return this.nodeCache[e];let s=t.nodes[e],o=s.name?i.createUniqueName(s.name):"",a=[],l=i._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(e)});return l&&a.push(l),s.camera!==void 0&&a.push(i.getDependency("camera",s.camera).then(function(c){return i._getNodeRef(i.cameraCache,s.camera,c)})),i._invokeAll(function(c){return c.createNodeAttachment&&c.createNodeAttachment(e)}).forEach(function(c){a.push(c)}),this.nodeCache[e]=Promise.all(a).then(function(c){let h;if(s.isBone===!0?h=new is:c.length>1?h=new cn:c.length===1?h=c[0]:h=new st,h!==c[0])for(let u=0,d=c.length;u1){let u=i.associations.get(h);i.associations.set(h,{...u})}return i.associations.get(h).nodes=e,h}),this.nodeCache[e]}loadScene(e){let t=this.extensions,n=this.json.scenes[e],i=this,s=new cn;n.name&&(s.name=i.createUniqueName(n.name)),Mi(s,n),n.extensions&&er(t,s,n);let o=n.nodes||[],a=[];for(let l=0,c=o.length;l{let u=new Map;for(let[d,f]of i.associations)(d instanceof vt||d instanceof Et)&&u.set(d,f);return h.traverse(d=>{let f=i.associations.get(d);f!=null&&u.set(d,f)}),u};return i.associations=c(s),s})}_createAnimationTracks(e,t,n,i,s){let o=[],a=e.name?e.name:e.uuid,l=[];function c(f){f.morphTargetInfluences&&l.push(f.name?f.name:f.uuid)}hs[s.path]===hs.weights?(c(e),e.isGroup&&e.children.forEach(c)):l.push(a);let h;switch(hs[s.path]){case hs.weights:h=fi;break;case hs.rotation:h=pi;break;case hs.translation:case hs.scale:h=Ni;break;default:n.itemSize===1?h=fi:h=Ni;break}let u=i.interpolation!==void 0?Ab[i.interpolation]:es,d=this._getArrayFromAccessor(n);for(let f=0,p=l.length;f>5&31)/31,p=(H>>10&31)/31):(d=m,f=y,p=b)}for(let H=1;H<=3;H++){let X=F+H*12,ie=P*3*3+(H-1)*3;v[ie]=h.getFloat32(X,!0),v[ie+1]=h.getFloat32(X+4,!0),v[ie+2]=h.getFloat32(X+8,!0),E[ie]=z,E[ie+1]=N,E[ie+2]=B,_&&(I.setRGB(d,f,p,Tt),g[ie]=I.r,g[ie+1]=I.g,g[ie+2]=I.b)}}return w.setAttribute("position",new Qe(v,3)),w.setAttribute("normal",new Qe(E,3)),_&&(w.setAttribute("color",new Qe(g,3)),w.hasColors=!0,w.alpha=x),w}function s(c){let h=new Oe,u=/solid([\s\S]*?)endsolid/g,d=/facet([\s\S]*?)endfacet/g,f=/solid\s(.+)/,p=0,_=/[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source,g=new RegExp("vertex"+_+_+_,"g"),m=new RegExp("normal"+_+_+_,"g"),y=[],b=[],x=[],T=new R,S,w=0,v=0,E=0;for(;(S=u.exec(c))!==null;){v=E;let I=S[0],P=(S=f.exec(I))!==null?S[1]:"";for(x.push(P);(S=d.exec(I))!==null;){let N=0,B=0,H=S[0];for(;(S=m.exec(H))!==null;)T.x=parseFloat(S[1]),T.y=parseFloat(S[2]),T.z=parseFloat(S[3]),B++;for(;(S=g.exec(H))!==null;)y.push(parseFloat(S[1]),parseFloat(S[2]),parseFloat(S[3])),b.push(T.x,T.y,T.z),N++,E++;B!==1&&console.error("THREE.STLLoader: Something isn't right with the normal of face number "+p),N!==3&&console.error("THREE.STLLoader: Something isn't right with the vertices of face number "+p),p++}let F=v,z=E-v;h.userData.groupNames=x,h.addGroup(F,z,w),w++}return h.setAttribute("position",new fe(y,3)),h.setAttribute("normal",new fe(b,3)),h}function o(c){return typeof c!="string"?new TextDecoder().decode(c):c}function a(c){if(typeof c=="string"){let h=new Uint8Array(c.length);for(let u=0;u0?s[s.length-1]:"",smooth:o!==void 0?o.smooth:this.smooth,groupStart:o!==void 0?o.groupEnd:0,groupEnd:-1,groupCount:-1,inherited:!1,clone:function(l){let c={index:typeof l=="number"?l:this.index,name:this.name,mtllib:this.mtllib,smooth:this.smooth,groupStart:0,groupEnd:-1,groupCount:-1,inherited:!1};return c.clone=this.clone.bind(c),c}};return this.materials.push(a),a},currentMaterial:function(){if(this.materials.length>0)return this.materials[this.materials.length-1]},_finalize:function(i){let s=this.currentMaterial();if(s&&s.groupEnd===-1&&(s.groupEnd=this.geometry.vertices.length/3,s.groupCount=s.groupEnd-s.groupStart,s.inherited=!1),i&&this.materials.length>1)for(let o=this.materials.length-1;o>=0;o--)this.materials[o].groupCount<=0&&this.materials.splice(o,1);return i&&this.materials.length===0&&this.materials.push({name:"",smooth:this.smooth}),s}},n&&n.name&&typeof n.clone=="function"){let i=n.clone(0);i.inherited=!0,this.object.materials.push(i)}this.objects.push(this.object)},finalize:function(){this.object&&typeof this.object._finalize=="function"&&this.object._finalize(!0)},parseVertexIndex:function(e,t){let n=parseInt(e,10);return(n>=0?n-1:n+t/3)*3},parseNormalIndex:function(e,t){let n=parseInt(e,10);return(n>=0?n-1:n+t/3)*3},parseUVIndex:function(e,t){let n=parseInt(e,10);return(n>=0?n-1:n+t/2)*2},addVertex:function(e,t,n){let i=this.vertices,s=this.object.geometry.vertices;s.push(i[e+0],i[e+1],i[e+2]),s.push(i[t+0],i[t+1],i[t+2]),s.push(i[n+0],i[n+1],i[n+2])},addVertexPoint:function(e){let t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addVertexLine:function(e){let t=this.vertices;this.object.geometry.vertices.push(t[e+0],t[e+1],t[e+2])},addNormal:function(e,t,n){let i=this.normals,s=this.object.geometry.normals;s.push(i[e+0],i[e+1],i[e+2]),s.push(i[t+0],i[t+1],i[t+2]),s.push(i[n+0],i[n+1],i[n+2])},addFaceNormal:function(e,t,n){let i=this.vertices,s=this.object.geometry.normals;p_.fromArray(i,e),np.fromArray(i,t),m_.fromArray(i,n),kn.subVectors(m_,np),g_.subVectors(p_,np),kn.cross(g_),kn.normalize(),s.push(kn.x,kn.y,kn.z),s.push(kn.x,kn.y,kn.z),s.push(kn.x,kn.y,kn.z)},addColor:function(e,t,n){let i=this.colors,s=this.object.geometry.colors;i[e]!==void 0&&s.push(i[e+0],i[e+1],i[e+2]),i[t]!==void 0&&s.push(i[t+0],i[t+1],i[t+2]),i[n]!==void 0&&s.push(i[n+0],i[n+1],i[n+2])},addUV:function(e,t,n){let i=this.uvs,s=this.object.geometry.uvs;s.push(i[e+0],i[e+1]),s.push(i[t+0],i[t+1]),s.push(i[n+0],i[n+1])},addDefaultUV:function(){let e=this.object.geometry.uvs;e.push(0,0),e.push(0,0),e.push(0,0)},addUVLine:function(e){let t=this.uvs;this.object.geometry.uvs.push(t[e+0],t[e+1])},addFace:function(e,t,n,i,s,o,a,l,c){let h=this.vertices.length,u=this.parseVertexIndex(e,h),d=this.parseVertexIndex(t,h),f=this.parseVertexIndex(n,h);if(this.addVertex(u,d,f),this.addColor(u,d,f),a!==void 0&&a!==""){let p=this.normals.length;u=this.parseNormalIndex(a,p),d=this.parseNormalIndex(l,p),f=this.parseNormalIndex(c,p),this.addNormal(u,d,f)}else this.addFaceNormal(u,d,f);if(i!==void 0&&i!==""){let p=this.uvs.length;u=this.parseUVIndex(i,p),d=this.parseUVIndex(s,p),f=this.parseUVIndex(o,p),this.addUV(u,d,f),this.object.geometry.hasUVIndices=!0}else this.addDefaultUV()},addPointGeometry:function(e){this.object.geometry.type="Points";let t=this.vertices.length;for(let n=0,i=e.length;n=7?(_u.setRGB(parseFloat(u[4]),parseFloat(u[5]),parseFloat(u[6]),Tt),t.colors.push(_u.r,_u.g,_u.b)):t.colors.push(void 0,void 0,void 0);break;case"vn":t.normals.push(parseFloat(u[1]),parseFloat(u[2]),parseFloat(u[3]));break;case"vt":t.uvs.push(parseFloat(u[1]),parseFloat(u[2]));break}}else if(h==="f"){let d=c.slice(1).trim().split(f_),f=[];for(let _=0,g=d.length;_0){let y=m.split("/");f.push(y)}}let p=f[0];for(let _=1,g=f.length-1;_1){let d=i[1].trim().toLowerCase();t.object.smooth=d!=="0"&&d!=="off"}else t.object.smooth=!0;let u=t.object.currentMaterial();u&&(u.smooth=t.object.smooth)}else{if(c==="\0")continue;console.warn('THREE.OBJLoader: Unexpected line: "'+c+'"')}}t.finalize();let s=new cn;if(s.materialLibraries=[].concat(t.materialLibraries),!(t.objects.length===1&&t.objects[0].geometry.vertices.length===0)===!0)for(let a=0,l=t.objects.length;a0&&_.setAttribute("normal",new fe(h.normals,3)),h.colors.length>0&&(p=!0,_.setAttribute("color",new fe(h.colors,3))),h.hasUVIndices===!0&&_.setAttribute("uv",new fe(h.uvs,2));let g=[];for(let y=0,b=u.length;y1){for(let y=0,b=u.length;y0){let a=new wn({size:1,sizeAttenuation:!1}),l=new Oe;l.setAttribute("position",new fe(t.vertices,3)),t.colors.length>0&&t.colors[0]!==void 0&&(l.setAttribute("color",new fe(t.colors,3)),a.vertexColors=!0);let c=new jn(l,a);s.add(c)}return s}};var yu=class extends Ps{constructor(){super(),this.name="RoomEnvironment",this.position.y=-3.5;let e=new ui;e.deleteAttribute("uv");let t=new Un({side:qt}),n=new Un,i=new Di(16777215,900,28,2);i.position.set(.418,16.199,.3),this.add(i);let s=new rt(e,t);s.position.set(-.757,13.219,.717),s.scale.set(31.713,28.305,28.591),this.add(s);let o=new Ii(e,n,6),a=new st;a.position.set(-10.906,2.009,1.846),a.rotation.set(0,-.195,0),a.scale.set(2.328,7.905,4.651),a.updateMatrix(),o.setMatrixAt(0,a.matrix),a.position.set(-5.607,-.754,-.758),a.rotation.set(0,.994,0),a.scale.set(1.97,1.534,3.955),a.updateMatrix(),o.setMatrixAt(1,a.matrix),a.position.set(6.167,.857,7.803),a.rotation.set(0,.561,0),a.scale.set(3.927,6.285,3.687),a.updateMatrix(),o.setMatrixAt(2,a.matrix),a.position.set(-2.017,.018,6.124),a.rotation.set(0,.333,0),a.scale.set(2.002,4.566,2.064),a.updateMatrix(),o.setMatrixAt(3,a.matrix),a.position.set(2.291,-.756,-2.621),a.rotation.set(0,-.286,0),a.scale.set(1.546,1.552,1.496),a.updateMatrix(),o.setMatrixAt(4,a.matrix),a.position.set(-2.193,-.369,-5.547),a.rotation.set(0,.516,0),a.scale.set(3.875,3.487,2.986),a.updateMatrix(),o.setMatrixAt(5,a.matrix),this.add(o);let l=new rt(e,Mo(50));l.position.set(-16.116,14.37,8.208),l.scale.set(.1,2.428,2.739),this.add(l);let c=new rt(e,Mo(50));c.position.set(-16.109,18.021,-8.207),c.scale.set(.1,2.425,2.751),this.add(c);let h=new rt(e,Mo(17));h.position.set(14.904,12.198,-1.832),h.scale.set(.15,4.265,6.331),this.add(h);let u=new rt(e,Mo(43));u.position.set(-.462,8.89,14.52),u.scale.set(4.38,5.441,.088),this.add(u);let d=new rt(e,Mo(20));d.position.set(3.235,11.486,-12.541),d.scale.set(2.5,2,.1),this.add(d);let f=new rt(e,Mo(100));f.position.set(0,20,0),f.scale.set(1,.1,1),this.add(f)}dispose(){let e=new Set;this.traverse(t=>{t.isMesh&&(e.add(t.geometry),e.add(t.material))});for(let t of e)t.dispose()}};function Mo(r){return new ks({color:0,emissive:16777215,emissiveIntensity:r})}window.FlashThree={THREE:Tf,OrbitControls:du,GLTFLoader:fu,STLLoader:gu,OBJLoader:xu,RoomEnvironment:yu};})(); diff --git a/flash/web/three/viewer.js b/flash/web/three/viewer.js new file mode 100644 index 0000000..d8f576f --- /dev/null +++ b/flash/web/three/viewer.js @@ -0,0 +1,231 @@ +/* Flash's 3D model viewer: draws a .glb, .stl or .obj file in a box, + lit like a studio, sitting on a soft shadow, to turn with the mouse. + The web UI's panel and the headless preview the agent looks at both + use this, so what the agent checks is what the user sees. Needs + three.min.js, which sets window.FlashThree, loaded first. */ +(function () { + "use strict"; + + const SKY = [1, 0.7, 1]; // where the camera starts, looking at the model + + function parse(T, data, suffix) { + return new Promise((resolve, reject) => { + if (suffix === ".glb") { + new T.GLTFLoader().parse(data, "", (gltf) => resolve(gltf.scene), reject); + return; + } + if (suffix === ".stl") { + const geometry = new T.STLLoader().parse(data); + geometry.computeVertexNormals(); + const material = new T.THREE.MeshStandardMaterial({ + color: geometry.hasColors ? 0xffffff : 0xb0b4bb, + vertexColors: !!geometry.hasColors, + roughness: 0.55, + metalness: 0.05, + }); + const mesh = new T.THREE.Mesh(geometry, material); + // STL files are made Z up, for printing; turn it to Y up. + mesh.rotation.x = -Math.PI / 2; + const group = new T.THREE.Group(); + group.add(mesh); + resolve(group); + return; + } + if (suffix === ".obj") { + const text = new TextDecoder().decode(data); + const group = new T.OBJLoader().parse(text); + group.traverse((node) => { + if (node.isMesh && (!node.material || node.material.type === "MeshPhongMaterial")) { + node.material = new T.THREE.MeshStandardMaterial({ color: 0xb0b4bb, roughness: 0.55 }); + } + }); + resolve(group); + return; + } + reject(new Error(`cannot show ${suffix} files`)); + }); + } + + function stats(root) { + let meshes = 0; + let triangles = 0; + root.traverse((node) => { + if (!node.isMesh || !node.geometry) return; + meshes += 1; + const g = node.geometry; + triangles += Math.floor((g.index ? g.index.count : g.attributes.position.count) / 3); + }); + return { meshes, triangles }; + } + + /* Draw DATA (an ArrayBuffer, or a URL to fetch) of type SUFFIX in + HOLDER. Resolves to a handle: reset() puts the camera back, + wireframe(on) shows the edges, spin(on) turns the model slowly, and + dispose() lets go of the GPU once the panel shows something else. + OPTIONS: light (a light background), still (draw once, for a + picture, with no animation). */ + async function show(holder, data, suffix, options) { + const opts = options || {}; + const T = window.FlashThree; + if (!T) throw new Error("three.js did not load"); + const THREE = T.THREE; + if (typeof data === "string") { + const response = await fetch(data, { credentials: "same-origin" }); + if (!response.ok) throw new Error(response.statusText || `HTTP ${response.status}`); + data = await response.arrayBuffer(); + } + const model = await parse(T, data, String(suffix || "").toLowerCase()); + + const renderer = new THREE.WebGLRenderer({ + antialias: true, alpha: true, preserveDrawingBuffer: !!opts.still, + }); + renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2)); + renderer.outputColorSpace = THREE.SRGBColorSpace; + renderer.toneMapping = THREE.ACESFilmicToneMapping; + renderer.toneMappingExposure = 1; + renderer.shadowMap.enabled = true; + renderer.shadowMap.type = THREE.PCFSoftShadowMap; + renderer.domElement.style.display = "block"; + renderer.domElement.style.width = "100%"; + renderer.domElement.style.height = "100%"; + renderer.domElement.style.touchAction = "none"; + holder.appendChild(renderer.domElement); + + const scene = new THREE.Scene(); + const pmrem = new THREE.PMREMGenerator(renderer); + const environment = pmrem.fromScene(new T.RoomEnvironment(), 0.04).texture; + scene.environment = environment; + pmrem.dispose(); + + model.traverse((node) => { + if (node.isMesh) { node.castShadow = true; node.receiveShadow = true; } + }); + scene.add(model); + + // Measure it, and set it on the ground where its lowest point is. + const box = new THREE.Box3().setFromObject(model); + if (box.isEmpty()) throw new Error("the model has nothing in it to draw"); + const size = box.getSize(new THREE.Vector3()); + const centre = box.getCenter(new THREE.Vector3()); + const radius = Math.max(size.length() / 2, 1e-3); + + const sun = new THREE.DirectionalLight(0xffffff, 1.6); + sun.position.set(centre.x + radius * 1.5, box.max.y + radius * 3, centre.z + radius * 2); + sun.target.position.copy(centre); + sun.castShadow = true; + sun.shadow.mapSize.set(2048, 2048); + sun.shadow.camera.left = sun.shadow.camera.bottom = -radius * 2; + sun.shadow.camera.right = sun.shadow.camera.top = radius * 2; + sun.shadow.camera.near = radius * 0.1; + sun.shadow.camera.far = radius * 10; + sun.shadow.bias = -0.0005; + sun.shadow.normalBias = radius * 0.004; + scene.add(sun, sun.target); + scene.add(new THREE.HemisphereLight(0xffffff, 0x888888, 0.4)); + + const light = opts.light !== undefined ? opts.light + : document.documentElement.dataset.theme === "light"; + const floor = new THREE.Mesh( + new THREE.PlaneGeometry(radius * 12, radius * 12), + new THREE.ShadowMaterial({ opacity: light ? 0.18 : 0.35 }), + ); + floor.rotation.x = -Math.PI / 2; + floor.position.set(centre.x, box.min.y - radius * 0.001, centre.z); + floor.receiveShadow = true; + scene.add(floor); + + const step = Math.pow(10, Math.floor(Math.log10(radius))); + const cells = Math.max(4, Math.min(40, Math.round((radius * 6) / step))); + const grid = new THREE.GridHelper(step * cells, cells, light ? 0xc8c8cc : 0x4a4a50, light ? 0xdedee2 : 0x34343a); + grid.position.set(centre.x, box.min.y, centre.z); + grid.material.transparent = true; + grid.material.opacity = 0.6; + grid.material.depthWrite = false; + scene.add(grid); + + const camera = new THREE.PerspectiveCamera(40, 1, radius / 100, radius * 100); + const controls = new T.OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + controls.dampingFactor = 0.08; + controls.minDistance = radius * 0.2; + controls.maxDistance = radius * 20; + + function reset() { + const toward = new THREE.Vector3(...SKY).normalize(); + // Far enough back that the whole model fits the narrower way. + const high = THREE.MathUtils.degToRad(camera.fov / 2); + const wide = Math.atan(Math.tan(high) * camera.aspect); + const fit = radius / Math.sin(Math.min(high, wide)); + camera.position.copy(centre).addScaledVector(toward, fit * 0.95); + controls.target.copy(centre); + camera.lookAt(centre); + controls.update(); + } + + let width = 0; + let height = 0; + function resize() { + const w = Math.max(1, holder.clientWidth); + const h = Math.max(1, holder.clientHeight); + if (w === width && h === height) return; + width = w; + height = h; + renderer.setSize(w, h, false); + camera.aspect = w / h; + camera.updateProjectionMatrix(); + } + resize(); + reset(); + + let frame = 0; + let alive = true; + const watcher = typeof ResizeObserver === "function" ? new ResizeObserver(resize) : null; + if (watcher) watcher.observe(holder); + // It turns slowly on its own until someone takes hold of it. + controls.autoRotate = !opts.still; + controls.autoRotateSpeed = 1.2; + controls.addEventListener("start", () => { controls.autoRotate = false; }); + + function tick() { + if (!alive) return; + frame = requestAnimationFrame(tick); + controls.update(); + renderer.render(scene, camera); + } + if (opts.still) renderer.render(scene, camera); else tick(); + + const counted = stats(model); + return { + size: [size.x, size.y, size.z], + meshes: counted.meshes, + triangles: counted.triangles, + reset, + spin(on) { controls.autoRotate = !!on; }, + wireframe(on) { + model.traverse((node) => { + if (!node.isMesh) return; + for (const m of [].concat(node.material)) m.wireframe = !!on; + }); + }, + dispose() { + alive = false; + cancelAnimationFrame(frame); + if (watcher) watcher.disconnect(); + controls.dispose(); + scene.traverse((node) => { + if (node.geometry) node.geometry.dispose(); + for (const m of [].concat(node.material || [])) { + for (const key in m) if (m[key] && m[key].isTexture) m[key].dispose(); + m.dispose(); + } + }); + environment.dispose(); + renderer.dispose(); + renderer.forceContextLoss(); + renderer.domElement.remove(); + }, + }; + } + + window.FlashModelView = { show }; +})(); diff --git a/flash/workspace.py b/flash/workspace.py index b87a07c..af6ced2 100644 --- a/flash/workspace.py +++ b/flash/workspace.py @@ -386,8 +386,14 @@ def folder_suggestions(typed: str) -> list[str]: ".md": "text/plain; charset=utf-8", ".markdown": "text/plain; charset=utf-8", ".txt": "text/plain; charset=utf-8", + # 3D models: turned and zoomed in the page's own viewer, which reads + # them as data. Nothing in one runs. + ".glb": "model/gltf-binary", + ".stl": "model/stl", + ".obj": "model/obj", } DOCUMENT_TYPES = (".md", ".markdown", ".txt") +MODEL_TYPES = (".glb", ".stl", ".obj") MAX_SHOWN_BYTES = 50 * 1024 * 1024 # A document is edited in the page as text, so it stays a size a browser # edits comfortably. @@ -407,7 +413,8 @@ def keep_file(source: str) -> dict: suffix = path.suffix.lower() if suffix not in SHOWN_TYPES: raise WorkspaceError( - f"{path.name} is not an image, a PDF, a web page, or a document" + f"{path.name} is not an image, a PDF, a web page, a document, " + "or a 3D model" ) size = path.stat().st_size @@ -434,6 +441,7 @@ def keep_file(source: str) -> dict: "pdf" if suffix == ".pdf" else "html" if SHOWN_TYPES[suffix] == "text/html" else "doc" if document + else "model" if suffix in MODEL_TYPES else "image" ), } @@ -485,8 +493,9 @@ def kept_file(file_id: str) -> Optional[tuple[Path, str]]: if path.is_file(): return path, mime uploaded = upload_path(file_id) - # An upload is served back only as a picture, a PDF, or a page: a - # text file the user attached is the model's to read, not the page's. + # An upload is served back only as a picture, a PDF, a page, or a + # 3D model: a text file the user attached is the model's to read, + # not the page's. suffix = uploaded.suffix.lower() if uploaded is not None else "" if suffix in SHOWN_TYPES and suffix not in DOCUMENT_TYPES: return uploaded, SHOWN_TYPES[suffix] @@ -527,7 +536,9 @@ def upload_info(file_id: str) -> Optional[dict]: "mime": mime, "kind": ( "image" if mime.startswith("image/") - else "pdf" if suffix == ".pdf" else "file" + else "pdf" if suffix == ".pdf" + else "model" if suffix in MODEL_TYPES + else "file" ), "path": str(path), } diff --git a/pyproject.toml b/pyproject.toml index 7ab4d56..afe0433 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,8 @@ flash = [ "web/*.svg", "web/katex/*.js", "web/katex/*.txt", + "web/three/*.js", + "web/three/*.txt", "web/*.txt", ] diff --git a/tests/test_model3d.py b/tests/test_model3d.py new file mode 100644 index 0000000..c878479 --- /dev/null +++ b/tests/test_model3d.py @@ -0,0 +1,276 @@ +# pylint: disable=C0114,C0115,C0116 + +import json +import math +import struct + +import pytest + +from flash import model3d, tools +from flash.tools import make_3d_model, send_3d_model, take_pending_images + + +def _volume(geo): + """Signed volume: positive only when every face points outwards.""" + + total = 0.0 + points = geo.positions + for i in range(0, len(geo.indices), 3): + a, b, c = (points[j] for j in geo.indices[i:i + 3]) + total += ( + a[0] * (b[1] * c[2] - b[2] * c[1]) + - a[1] * (b[0] * c[2] - b[2] * c[0]) + + a[2] * (b[0] * c[1] - b[1] * c[0]) + ) + return total / 6 + + +def _read_glb(data): + magic, version, length = struct.unpack_from("<4sII", data, 0) + assert (magic, version, length) == (b"glTF", 2, len(data)) + size, kind = struct.unpack_from("= 0, spec + + +def test_a_mesh_takes_polygons_and_checks_its_indices(): + square = { + "shape": "mesh", + "vertices": [[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1]], + "faces": [[0, 1, 2, 3]], + } + assert model3d.Part(0, square).geometry.triangles == 2 + + square["faces"] = [[0, 1, 9]] + with pytest.raises(model3d.ModelError, match="not in vertices"): + model3d.Part(0, square) + + +@pytest.mark.parametrize("spec, message", [ + ({"shape": "pyramid"}, "shape must be one of"), + ({"shape": "box", "size": [1, -1, 1]}, "more than 0"), + ({"shape": "box", "size": [1, 2]}, r"\[x, y, z\]"), + ({"shape": "sphere", "radius": "big"}, "must be a number"), + ({"shape": "box", "color": "sort of blue"}, "hex code"), + ({"shape": "extrude", "points": [[0, 0], [1, 1]]}, "at least 3"), + ({"shape": "lathe", "points": [[1, 0]]}, "at least 2"), +]) +def test_bad_parts_say_which_part_and_why(spec, message): + with pytest.raises(model3d.ModelError, match=message) as caught: + model3d.build_parts([{"shape": "box"}, spec]) + + assert str(caught.value).startswith("part 2") + + +def test_parts_can_arrive_as_a_json_string(): + built = model3d.build_parts('[{"shape": "box"}, {"shape": "sphere"}]') + + assert [p.shape for p in built] == ["box", "sphere"] + + +def test_colors_take_names_and_short_hex(): + assert model3d.parse_color("#f80") == pytest.approx((1, 0x88 / 255, 0)) + assert model3d.parse_color("White") == (1, 1, 1) + + +# --- The file ------------------------------------------------------------- + + +def test_glb_is_well_formed_and_places_every_part(): + built = model3d.build_parts([ + {"shape": "box", "name": "seat", "position": [0, 0.5, 0], + "color": "red"}, + {"shape": "sphere", "position": [1, 2, 3], "rotation": [0, 90, 0], + "scale": [1, 2, 1], "color": "red"}, + {"shape": "cone", "color": "#00f", "opacity": 0.5, + "emissive": "#ff0"}, + ]) + + data = model3d.to_glb(built, "Chair") + document = _read_glb(data) + + assert len(data) % 4 == 0 + assert document["scenes"][0]["name"] == "Chair" + assert [n["name"] for n in document["nodes"]] == [ + "seat", "sphere-2", "cone-3", + ] + assert document["nodes"][0]["translation"] == [0, 0.5, 0] + turned = document["nodes"][1]["rotation"] + assert turned == pytest.approx([0, math.sqrt(0.5), 0, math.sqrt(0.5)]) + assert document["nodes"][1]["scale"] == [1, 2, 1] + # The two red parts share one material. + assert len(document["materials"]) == 2 + see_through = document["materials"][1] + assert see_through["alphaMode"] == "BLEND" + assert see_through["emissiveFactor"] == pytest.approx([1, 1, 0]) + for view in document["bufferViews"]: + assert view["byteOffset"] % 4 == 0 + + +def test_describe_gives_the_size_and_notices_a_floating_model(): + built = model3d.build_parts([ + {"shape": "box", "size": [2, 1, 1], "position": [0, 0.5, 0]}, + ]) + text = model3d.describe(built) + assert "1 part, 12 triangles" in text + assert "Overall size (x, y, z): 2, 1, 1" in text + assert "does not sit on the ground" not in text + + built = model3d.build_parts([{"shape": "box", "position": [0, 3, 0]}]) + assert "does not sit on the ground" in model3d.describe(built) + + +def test_the_bounds_follow_the_turn(): + built = model3d.build_parts([ + {"shape": "box", "size": [2, 1, 1], "rotation": [0, 0, 90]}, + ]) + + low, high = model3d.bounds(built) + + assert high[0] - low[0] == pytest.approx(1) + assert high[1] - low[1] == pytest.approx(2) + + +# --- The tools ------------------------------------------------------------ + + +def _no_vision(monkeypatch): + monkeypatch.setattr(tools, "model_sees_images", lambda *_: False) + monkeypatch.setattr(tools, "_open_with_spinner", lambda path: "") + + +def test_make_3d_model_writes_a_glb(tmp_path, monkeypatch): + _no_vision(monkeypatch) + target = tmp_path / "out" / "lamp" + + result = make_3d_model(str(target), [ + {"shape": "cylinder", "radius": 0.1, "height": 0.4, + "position": [0, 0.2, 0]}, + ], title="Lamp") + + written = tmp_path / "out" / "lamp.glb" + assert _read_glb(written.read_bytes())["scenes"][0]["name"] == "Lamp" + assert f"Saved {written}" in result + assert "Overall size" in result + assert "no vision" in result + + +def test_make_3d_model_writes_nothing_for_a_bad_part(tmp_path, monkeypatch): + _no_vision(monkeypatch) + target = tmp_path / "bad.glb" + + result = make_3d_model(str(target), [{"shape": "blob"}]) + + assert result.startswith("Error: part 1") + assert not target.exists() + + +def test_make_3d_model_leaves_a_file_that_is_not_a_model( + tmp_path, monkeypatch +): + _no_vision(monkeypatch) + precious = tmp_path / "notes.glb" + precious.write_text("my notes") + + result = make_3d_model(str(precious), [{"shape": "box"}]) + + assert "left alone" in result + assert precious.read_text() == "my notes" + + +def test_make_3d_model_attaches_a_picture_for_a_model_that_sees( + tmp_path, monkeypatch +): + take_pending_images() + monkeypatch.setattr(tools, "model_sees_images", lambda *_: True) + monkeypatch.setattr(tools, "_open_with_spinner", lambda path: "") + monkeypatch.setattr(tools, "SCRATCH_DIR", str(tmp_path)) + pages = [] + + def capture(url, out, **_): + pages.append(url) + out.write_bytes(b"png bytes") + return [], "" + + monkeypatch.setattr(tools, "capture", capture) + + result = make_3d_model(str(tmp_path / "cube.glb"), [{"shape": "box"}]) + + assert "picture of it" in result + assert take_pending_images() == [b"png bytes"] + # The page draws the model with the web UI's own viewer. + page = (tmp_path / "model-1.html").read_text() + assert "FlashModelView.show" in page and "window.FlashThree" in page + assert pages == [(tmp_path / "model-1.html").resolve().as_uri()] + + +def test_send_3d_model_checks_what_it_is_given(tmp_path, monkeypatch): + _no_vision(monkeypatch) + fake = tmp_path / "fake.glb" + fake.write_text("not a model") + wrong = tmp_path / "model.fbx" + wrong.write_bytes(b"x") + stl = tmp_path / "part.stl" + stl.write_bytes(b"solid part\nendsolid part\n") + + assert "does not start like" in send_3d_model(str(fake)) + assert "not a .glb, .stl, or .obj" in send_3d_model(str(wrong)) + assert "no file" in send_3d_model(str(tmp_path / "gone.glb")) + assert send_3d_model(str(stl)).startswith("Sent part.stl") + + +def test_the_model_tools_are_offered(): + names = {t["function"]["name"] for t in tools.tools} + + assert {"make_3d_model", "send_3d_model"} <= names + assert tools.FUNCTIONS["make_3d_model"] is make_3d_model + assert tools.FUNCTIONS["send_3d_model"] is send_3d_model diff --git a/tests/test_web.py b/tests/test_web.py index 3b3c524..1d84465 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -588,6 +588,26 @@ def test_katex_is_served_for_math(self, server): ] assert (web.WEB_DIR / "katex" / "LICENSE.txt").is_file() + def test_three_js_is_served_for_3d_models(self, server): + port = server.port + for name in ("three.min.js", "viewer.js"): + conn = http.client.HTTPConnection("127.0.0.1", port, timeout=5) + conn.request("GET", f"/static/three/{name}", + headers={"Host": f"127.0.0.1:{port}"}) + response = conn.getresponse() + body = response.read() + conn.close() + + assert response.status == 200 + assert response.getheader("Content-Type").startswith( + "text/javascript" + ) + assert body + page = web.PAGE.read_bytes() + assert b"/static/three/three.min.js" in page + assert b"/static/three/viewer.js" in page + assert (web.WEB_DIR / "three" / "LICENSE.txt").is_file() + def test_but_nothing_else_is(self, server): assert request(server, "GET", "/static/index.html", token=False)[0] == 403 @@ -1361,6 +1381,36 @@ def test_a_page_is_served_sandboxed(self, server, tmp_path): assert policy.startswith("sandbox") assert "allow-same-origin" not in policy + def test_in_the_web_ui_a_3d_model_goes_to_the_page( + self, server, tmp_path, monkeypatch + ): + monkeypatch.setattr(tools, "model_sees_images", lambda *_: False) + opened = [] + monkeypatch.setattr(tools, "_open_with_spinner", + lambda path: opened.append(path) or "") + target = tmp_path / "chair.glb" + FakeClient.scripts = [ + [part(calls=[call("make_3d_model", path=str(target), parts=[ + {"shape": "box", "size": [0.5, 0.05, 0.5], + "position": [0, 0.45, 0]}, + ])]), part(done=True)], + [part("There it is."), part(done=True)], + ] + session = web.Session() + chat = session.new_chat() + + run(session, chat, "make me a chair") + + shown = [e for e in chat.log if e["type"] == "file"] + assert [(f["name"], f["kind"], f["mime"]) for f in shown] == [ + ("chair.glb", "model", "model/gltf-binary"), + ] + assert opened == [] + status, body = request(server, "GET", f"/api/files/{shown[0]['id']}") + assert status == 200 + assert body == target.read_bytes() + assert request.last.getheader("Content-Type") == "model/gltf-binary" + def test_send_document_checks_what_it_is_given(self, tmp_path): wrong = tmp_path / "page.html" wrong.write_text("

x

") From ca821b982e63a35f39d4862af7d1deeefc880658 Mon Sep 17 00:00:00 2001 From: "Nathan C." <149914029+Natuworkguy@users.noreply.github.com> Date: Tue, 29 Sep 2026 18:34:40 +0000 Subject: [PATCH 4/8] feat: give 3D models text, and show their true colours The agent had no way to make letters, so asked for the Minecraft logo it stood a plain box in for each one. Add a text shape: words in a blocky 5x7 pixel font (A-Z, 0-9, common punctuation, lines split by \n), one block per pixel with the faces between touching blocks left out, sized by the height of a capital. The tool's description now says to use it for any logo, sign or title, never a box per letter, and to colour parts like the real thing. The viewer now starts in front of the model (glTF's +Z) rather than 45 degrees off to one side, which squashed anything with a front, text most of all, and it fits wide models without clipping their ends. It also uses Khronos PBR Neutral tone mapping and a softer environment, so a face turned to the viewer shows about the colour it was given: a #9c9c9c grey rendered as 216 and now renders as 160. --- README.md | 2 +- flash/model3d.py | 175 +++++++++++++++++++++++++++++++++----- flash/tools.py | 33 ++++++- flash/web/three/viewer.js | 16 ++-- tests/test_model3d.py | 56 ++++++++++++ 5 files changed, 250 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 53c1f72..7f1777d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ FLASH (**F**ast **L**ocal **A**gent **SH**ell) CLI is an AI-powered command-line - Manually execute shell commands using the `!` prefix. - **`flash://` Links**: Open Flash from a browser or another app with a prompt ready to go (`flash://?prompt=What+is+Python`). - **Image Recognition**: Send a local image to a vision-capable model with `/image [prompt]`, or let the AI open one itself with its `view_image` tool. -- **3D Models**: Ask for a chair, a vase, or a floor plan and the AI builds it with its `make_3d_model` tool out of boxes, cylinders, spheres, lathed profiles, and extruded outlines, saved as a `.glb` that opens in Blender and every game engine. In the web UI it appears in a 3D viewer beside the chat that you can turn, zoom, and download; a vision model also gets a render of it, so it can see a leg floating off the table and fix it. `send_3d_model` shows an existing `.glb`, `.stl`, or `.obj`. +- **3D Models**: Ask for a chair, a vase, or a floor plan and the AI builds it with its `make_3d_model` tool out of boxes, cylinders, spheres, lathed profiles, extruded outlines, and blocky pixel-font text for logos and signs, saved as a `.glb` that opens in Blender and every game engine. In the web UI it appears in a 3D viewer beside the chat that you can turn, zoom, and download; a vision model also gets a render of it, so it can see a leg floating off the table and fix it. `send_3d_model` shows an existing `.glb`, `.stl`, or `.obj`. - **Page Screenshots**: The AI renders a page it built in a headless browser with its `screenshot` tool and looks at the result, so it can see a broken layout instead of guessing from the HTML. - **Page Control**: The AI opens a page with `open_page` and then clicks buttons, fills forms, presses keys, and runs JavaScript on it with `interact`, seeing a fresh screenshot, the page's elements, and its console errors after every step, so it can debug what a page *does*, not just how it looks. - **Voice Mode**: `/voice on` downloads a Vosk speech model and a Piper voice, then lets you talk to Flash and hear its replies, with typing still available at any time. diff --git a/flash/model3d.py b/flash/model3d.py index 16fae51..eb939a0 100644 --- a/flash/model3d.py +++ b/flash/model3d.py @@ -1,10 +1,11 @@ """3D models the agent builds out of parts. The model describes a model as a list of parts, each a shape (a box, a -sphere, a cylinder, a lathed profile, an extruded outline, or a mesh of -its own) with a place, a turn, a size and a colour. This turns that list -into a binary glTF (.glb) file: one file that the web UI's viewer, Blender, -Windows' 3D Viewer and every game engine open as it is. +sphere, a cylinder, a lathed profile, an extruded outline, blocky text, +or a mesh of its own) with a place, a turn, a size and a colour. This +turns that list into a binary glTF (.glb) file: one file that the web +UI's viewer, Blender, Windows' 3D Viewer and every game engine open as +it is. Pure Python on purpose, with no numpy or trimesh to install, since a model of a few hundred parts is a few hundred thousand floats at most. @@ -21,7 +22,7 @@ # Every shape is built around the origin, Y up, in metres, as glTF has it. SHAPES = ( "box", "sphere", "cylinder", "cone", "torus", "plane", "lathe", - "extrude", "mesh", + "extrude", "mesh", "text", ) MODEL_SUFFIXES = (".glb", ".stl", ".obj") @@ -203,23 +204,26 @@ def _fraction(value: Any, what: str, fallback: float) -> float: # --- The shapes ----------------------------------------------------------- -def _box(part: dict) -> Geometry: - sx, sy, sz = _vector(part.get("size"), "size", (1.0, 1.0, 1.0), - positive=True) - x, y, z = sx / 2, sy / 2, sz / 2 - geo = Geometry() - # Each face as its normal and two edges, walked counter-clockwise. - faces = ( - ((1, 0, 0), (0, 0, -1), (0, 1, 0)), - ((-1, 0, 0), (0, 0, 1), (0, 1, 0)), - ((0, 1, 0), (1, 0, 0), (0, 0, -1)), - ((0, -1, 0), (1, 0, 0), (0, 0, 1)), - ((0, 0, 1), (1, 0, 0), (0, 1, 0)), - ((0, 0, -1), (-1, 0, 0), (0, 1, 0)), - ) - half = (x, y, z) - for normal, u, v in faces: - centre = tuple(normal[i] * half[i] for i in range(3)) +# A box's faces, each as its normal and two edges, walked +# counter-clockwise as seen from outside. +_BOX_FACES = ( + ((1, 0, 0), (0, 0, -1), (0, 1, 0)), + ((-1, 0, 0), (0, 0, 1), (0, 1, 0)), + ((0, 1, 0), (1, 0, 0), (0, 0, -1)), + ((0, -1, 0), (1, 0, 0), (0, 0, 1)), + ((0, 0, 1), (1, 0, 0), (0, 1, 0)), + ((0, 0, -1), (-1, 0, 0), (0, 1, 0)), +) + + +def _add_box(geo: Geometry, middle, half, hidden=()) -> None: + """A box around MIDDLE, HALF its size each way, leaving out the + faces whose normals are in HIDDEN, where another box touches it.""" + + for normal, u, v in _BOX_FACES: + if normal in hidden: + continue + centre = tuple(middle[i] + normal[i] * half[i] for i in range(3)) corners = [] for a, b in ((-1, -1), (1, -1), (1, 1), (-1, 1)): corners.append(tuple( @@ -229,6 +233,132 @@ def _box(part: dict) -> Geometry: first = [geo.vertex(c, normal) for c in corners] geo.triangle(first[0], first[1], first[2]) geo.triangle(first[0], first[2], first[3]) + + +def _box(part: dict) -> Geometry: + sx, sy, sz = _vector(part.get("size"), "size", (1.0, 1.0, 1.0), + positive=True) + geo = Geometry() + _add_box(geo, (0, 0, 0), (sx / 2, sy / 2, sz / 2)) + return geo + + +# A blocky 5x7 font for the text shape, "#" for a block, drawn top row +# first. Narrow marks are narrower rows. +FONT = { + "A": (".###.", "#...#", "#...#", "#####", "#...#", "#...#", "#...#"), + "B": ("####.", "#...#", "#...#", "####.", "#...#", "#...#", "####."), + "C": (".###.", "#...#", "#....", "#....", "#....", "#...#", ".###."), + "D": ("####.", "#...#", "#...#", "#...#", "#...#", "#...#", "####."), + "E": ("#####", "#....", "#....", "####.", "#....", "#....", "#####"), + "F": ("#####", "#....", "#....", "####.", "#....", "#....", "#...."), + "G": (".###.", "#...#", "#....", "#.###", "#...#", "#...#", ".###."), + "H": ("#...#", "#...#", "#...#", "#####", "#...#", "#...#", "#...#"), + "I": ("###", ".#.", ".#.", ".#.", ".#.", ".#.", "###"), + "J": ("..###", "...#.", "...#.", "...#.", "#..#.", "#..#.", ".##.."), + "K": ("#...#", "#..#.", "#.#..", "##...", "#.#..", "#..#.", "#...#"), + "L": ("#....", "#....", "#....", "#....", "#....", "#....", "#####"), + "M": ("#...#", "##.##", "#.#.#", "#.#.#", "#...#", "#...#", "#...#"), + "N": ("#...#", "##..#", "#.#.#", "#..##", "#...#", "#...#", "#...#"), + "O": (".###.", "#...#", "#...#", "#...#", "#...#", "#...#", ".###."), + "P": ("####.", "#...#", "#...#", "####.", "#....", "#....", "#...."), + "Q": (".###.", "#...#", "#...#", "#...#", "#.#.#", "#..#.", ".##.#"), + "R": ("####.", "#...#", "#...#", "####.", "#.#..", "#..#.", "#...#"), + "S": (".####", "#....", "#....", ".###.", "....#", "....#", "####."), + "T": ("#####", "..#..", "..#..", "..#..", "..#..", "..#..", "..#.."), + "U": ("#...#", "#...#", "#...#", "#...#", "#...#", "#...#", ".###."), + "V": ("#...#", "#...#", "#...#", "#...#", "#...#", ".#.#.", "..#.."), + "W": ("#...#", "#...#", "#...#", "#.#.#", "#.#.#", "##.##", "#...#"), + "X": ("#...#", "#...#", ".#.#.", "..#..", ".#.#.", "#...#", "#...#"), + "Y": ("#...#", "#...#", ".#.#.", "..#..", "..#..", "..#..", "..#.."), + "Z": ("#####", "....#", "...#.", "..#..", ".#...", "#....", "#####"), + "0": (".###.", "#...#", "#..##", "#.#.#", "##..#", "#...#", ".###."), + "1": ("..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###."), + "2": (".###.", "#...#", "....#", "...#.", "..#..", ".#...", "#####"), + "3": ("####.", "....#", "....#", ".###.", "....#", "....#", "####."), + "4": ("...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#."), + "5": ("#####", "#....", "####.", "....#", "....#", "#...#", ".###."), + "6": (".###.", "#....", "#....", "####.", "#...#", "#...#", ".###."), + "7": ("#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..."), + "8": (".###.", "#...#", "#...#", ".###.", "#...#", "#...#", ".###."), + "9": (".###.", "#...#", "#...#", ".####", "....#", "....#", ".###."), + " ": ("...",) * 7, + ".": (".", ".", ".", ".", ".", ".", "#"), + ",": (".", ".", ".", ".", ".", "#", "#"), + "!": ("#", "#", "#", "#", "#", ".", "#"), + "?": (".###.", "#...#", "....#", "...#.", "..#..", ".....", "..#.."), + "-": ("...", "...", "...", "###", "...", "...", "..."), + ":": (".", "#", ".", ".", ".", "#", "."), + "'": ("#", "#", ".", ".", ".", ".", "."), + "&": (".##..", "#..#.", "#.#..", ".#...", "#.#.#", "#..#.", ".##.#"), + "/": ("....#", "...#.", "...#.", "..#..", ".#...", ".#...", "#...."), +} +FONT_ROWS = 7 +MAX_TEXT = 200 + + +def _text(part: dict) -> Geometry: + """Words in blocks, one block to a pixel of the font, reading along + X and facing +Z: a logo, a sign, a name over a door.""" + + words = str(part.get("text") or "").upper() + if not words.strip(): + raise ModelError("a text part needs text") + if len(words) > MAX_TEXT: + raise ModelError(f"a text part can have at most {MAX_TEXT} letters") + unknown = sorted({c for c in words if c not in FONT and c != "\n"}) + if unknown: + raise ModelError( + f"the font has no {' '.join(repr(c) for c in unknown)}; it has " + "A-Z, 0-9, spaces and . , ! ? - : ' & /" + ) + # The height of a capital, and the block that makes it. + height = _number(part.get("height", part.get("size", 1)), "height", + positive=True) + block = height / FONT_ROWS + depth = _number(part.get("depth", block), "depth", positive=True) + + # Each line as columns of blocks, a column of space between letters. + lines = [] + for line in words.split("\n"): + columns: list[str] = [] + for n, char in enumerate(line): + if n: + columns.append("." * FONT_ROWS) + rows = FONT[char] + for x in range(len(rows[0])): + columns.append("".join(row[x] for row in rows)) + lines.append(columns) + widest = max(len(columns) for columns in lines) + # Lines two blocks apart, each centred. + tall = len(lines) * (FONT_ROWS + 2) - 2 + filled = set() + for k, columns in enumerate(lines): + left = (widest - len(columns)) // 2 + top = tall - 1 - k * (FONT_ROWS + 2) + for x, column in enumerate(columns): + for y, pixel in enumerate(column): + if pixel == "#": + filled.add((left + x, top - y)) + if not filled: + raise ModelError("a text part needs at least one letter") + + geo = Geometry() + half = (block / 2, block / 2, depth / 2) + for x, y in filled: + hidden = tuple( + normal for normal, step in ( + ((1, 0, 0), (1, 0)), ((-1, 0, 0), (-1, 0)), + ((0, 1, 0), (0, 1)), ((0, -1, 0), (0, -1)), + ) + if (x + step[0], y + step[1]) in filled + ) + middle = ( + (x + 0.5 - widest / 2) * block, + (y + 0.5 - tall / 2) * block, + 0.0, + ) + _add_box(geo, middle, half, hidden) return geo @@ -517,6 +647,7 @@ def _mesh(part: dict) -> Geometry: "lathe": _lathe, "extrude": _extrude, "mesh": _mesh, + "text": _text, } diff --git a/flash/tools.py b/flash/tools.py index 038b09e..93e9485 100644 --- a/flash/tools.py +++ b/flash/tools.py @@ -140,7 +140,8 @@ quoting the words it is about. To make a 3D model (an object, a prop, a room, a layout), use the make_3d_model tool: it builds the model from parts such as boxes, - cylinders, spheres, lathed profiles, and extruded outlines, saves a + cylinders, spheres, lathed profiles, extruded outlines, and blocky + text for any words, logos, or signs, saves a .glb, and shows it in a 3D viewer. Use send_3d_model to show a .glb, .stl, or .obj file that already exists. When you make an image, PDF, web page, or document for the user, send it @@ -3568,7 +3569,9 @@ def interact( "so a part rests on it when its position's y is half its " "height. Every shape is centred on its position. Build " "the object from many parts, sized in proportion to the " - "real thing. The result gives the model's overall size, " + "real thing and coloured like it. Anything with words on " + "it (a logo, a sign, a title) gets a text part for them. " + "The result gives the model's overall size, " "and a picture of it when you can see images: check both " "and fix what is off. To revise, call again with the " "whole changed list and the same path." @@ -3608,12 +3611,34 @@ def interact( "pieces); extrude (points " "[[x,z],...], an outline seen " "from above, raised to height: " - "walls, letters, gears, " - "L-shapes); mesh (vertices " + "walls, floor plans, gears, " + "L-shapes); text (text, height " + "of a capital, depth: words in a " + "blocky pixel font, reading " + "along X and facing +Z, lines " + "split by \\n: logos, signs, " + "names; never stand a box in " + "for a letter); mesh (vertices " "[[x,y,z],...] and faces, each a " "list of vertex indices from 0)." ), }, + "text": { + "type": "string", + "description": ( + "For text: the words. A-Z, " + "0-9, spaces, and . , ! ? - : " + "' & /." + ), + }, + "depth": { + "type": "number", + "description": ( + "For text: how thick the " + "letters are; one block of the " + "font (height / 7) by default." + ), + }, "name": { "type": "string", "description": ( diff --git a/flash/web/three/viewer.js b/flash/web/three/viewer.js index d8f576f..38d51da 100644 --- a/flash/web/three/viewer.js +++ b/flash/web/three/viewer.js @@ -6,7 +6,9 @@ (function () { "use strict"; - const SKY = [1, 0.7, 1]; // where the camera starts, looking at the model + // Where the camera starts: in front (glTF faces +Z), a little right + // and above, so a front reads straight on and the model still has depth. + const SKY = [0.45, 0.5, 1]; function parse(T, data, suffix) { return new Promise((resolve, reject) => { @@ -81,7 +83,8 @@ }); renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2)); renderer.outputColorSpace = THREE.SRGBColorSpace; - renderer.toneMapping = THREE.ACESFilmicToneMapping; + // Neutral keeps a colour the colour it was given; ACES bleaches greys. + renderer.toneMapping = THREE.NeutralToneMapping; renderer.toneMappingExposure = 1; renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; @@ -95,6 +98,9 @@ const pmrem = new THREE.PMREMGenerator(renderer); const environment = pmrem.fromScene(new T.RoomEnvironment(), 0.04).texture; scene.environment = environment; + // Soft enough that a face turned to the viewer shows about its own + // colour, rather than a paler one. + scene.environmentIntensity = 0.5; pmrem.dispose(); model.traverse((node) => { @@ -109,7 +115,7 @@ const centre = box.getCenter(new THREE.Vector3()); const radius = Math.max(size.length() / 2, 1e-3); - const sun = new THREE.DirectionalLight(0xffffff, 1.6); + const sun = new THREE.DirectionalLight(0xffffff, 1.0); sun.position.set(centre.x + radius * 1.5, box.max.y + radius * 3, centre.z + radius * 2); sun.target.position.copy(centre); sun.castShadow = true; @@ -121,7 +127,7 @@ sun.shadow.bias = -0.0005; sun.shadow.normalBias = radius * 0.004; scene.add(sun, sun.target); - scene.add(new THREE.HemisphereLight(0xffffff, 0x888888, 0.4)); + scene.add(new THREE.HemisphereLight(0xffffff, 0x666666, 0.25)); const light = opts.light !== undefined ? opts.light : document.documentElement.dataset.theme === "light"; @@ -156,7 +162,7 @@ const high = THREE.MathUtils.degToRad(camera.fov / 2); const wide = Math.atan(Math.tan(high) * camera.aspect); const fit = radius / Math.sin(Math.min(high, wide)); - camera.position.copy(centre).addScaledVector(toward, fit * 0.95); + camera.position.copy(centre).addScaledVector(toward, fit * 1.1); controls.target.copy(centre); camera.lookAt(centre); controls.update(); diff --git a/tests/test_model3d.py b/tests/test_model3d.py index c878479..25ae739 100644 --- a/tests/test_model3d.py +++ b/tests/test_model3d.py @@ -70,6 +70,7 @@ def test_normals_agree_with_the_faces_they_light(): {"shape": "box"}, {"shape": "sphere"}, {"shape": "cylinder"}, {"shape": "cone"}, {"shape": "torus"}, {"shape": "lathe", "points": [[0.2, 0], [0.5, 0.5], [0.1, 1]]}, + {"shape": "text", "text": "Hi!"}, ): geo = model3d.Part(0, spec).geometry for i in range(0, len(geo.indices), 3): @@ -82,6 +83,61 @@ def test_normals_agree_with_the_faces_they_light(): assert sum(f * n for f, n in zip(face, normal)) >= 0, spec +def _pixels(char): + return sum(row.count("#") for row in model3d.FONT[char]) + + +def test_text_is_one_closed_block_to_a_pixel_of_the_font(): + part = model3d.Part(0, {"shape": "text", "text": "minecraft", + "height": 7, "depth": 2}) + blocks = sum(_pixels(c) for c in "MINECRAFT") + + # Closed and facing out, whatever blocks touch. + assert _volume(part.geometry) == pytest.approx(blocks * 2) + low = [min(p[i] for p in part.geometry.positions) for i in range(3)] + high = [max(p[i] for p in part.geometry.positions) for i in range(3)] + # Nine letters, a block of space between each; centred. + widths = sum(len(model3d.FONT[c][0]) for c in "MINECRAFT") + 8 + assert high[0] - low[0] == pytest.approx(widths) + assert high[1] - low[1] == pytest.approx(7) + assert low[0] == pytest.approx(-high[0]) + assert (low[2], high[2]) == pytest.approx((-1, 1)) + + +def test_touching_blocks_share_no_hidden_faces(): + part = model3d.Part(0, {"shape": "text", "text": "-"}) + + # Three blocks in a row: each keeps its front, back, top and bottom + # (4 faces, 8 triangles), and only the two ends of the run show. + assert part.geometry.triangles == 3 * 4 + 3 * 4 + 2 * 2 + + +def test_text_lines_stack_centred(): + one = model3d.Part(0, {"shape": "text", "text": "AB", "height": 7}) + two = model3d.Part(0, {"shape": "text", "text": "AB\nC", "height": 7}) + + tall = max(p[1] for p in two.geometry.positions) - \ + min(p[1] for p in two.geometry.positions) + assert tall == pytest.approx(7 + 2 + 7) + assert _volume(two.geometry) == pytest.approx( + _volume(one.geometry) + _pixels("C") * 1, + ) + + +def test_text_says_which_letters_the_font_lacks(): + with pytest.raises(model3d.ModelError, match=r"no '#' '@'"): + model3d.Part(0, {"shape": "text", "text": "a@b#"}) + with pytest.raises(model3d.ModelError, match="needs text"): + model3d.Part(0, {"shape": "text", "text": " "}) + + +def test_every_glyph_is_seven_rows_of_one_width(): + for char, rows in model3d.FONT.items(): + assert len(rows) == model3d.FONT_ROWS, char + assert len({len(r) for r in rows}) == 1, char + assert set("".join(rows)) <= {"#", "."}, char + + def test_a_mesh_takes_polygons_and_checks_its_indices(): square = { "shape": "mesh", From 6203cf4222bfaefa0e888182fa25db071bb735bb Mon Sep 17 00:00:00 2001 From: "Nathan C." <149914029+Natuworkguy@users.noreply.github.com> Date: Tue, 29 Sep 2026 18:58:57 +0000 Subject: [PATCH 5/8] fix: keep going when the model says what it will do and stops A reply with no tool call ends the turn, so a model that looked at its 3D render, saw the grass block hiding the logo, and wrote "I'll move the logo text forward" left the model broken, with no way to act on what it had just noticed. The same happens after a failing test or a bad screenshot. When a reply ends by announcing its next step without the tool call that takes it, Flash now keeps the reply on screen and in the history, tells the model to do it (or say in one line why not), and carries on the turn, at most twice a turn so a model that only ever promises is let go. Only the last two sentences count, and offers, questions, and waiting on a sub-agent or the user ("I'll report back", "let me know") are not promises. The nudge is a system message, so like the wrap-up nudge it is not kept once the turn ends. Both the terminal and the web UI do this. make_3d_model's preview note also now says to fix anything wrong in the picture by calling the tool again before writing the reply. --- flash/ai.py | 109 +++++++++++++++++++++++++++++++++++++++++++--- flash/tools.py | 4 +- flash/web.py | 14 +++++- tests/test_ai.py | 74 +++++++++++++++++++++++++++++++ tests/test_web.py | 56 ++++++++++++++++++++++++ 5 files changed, 249 insertions(+), 8 deletions(-) diff --git a/flash/ai.py b/flash/ai.py index 5a3eb1f..d8d2540 100644 --- a/flash/ai.py +++ b/flash/ai.py @@ -987,6 +987,58 @@ def _tool_limit_message() -> dict: } +# A reply that ends by saying what it will do next, with no tool call +# to do it: the model saw something to fix (in a render, a test run, a +# screenshot) and wrote the plan down instead of carrying it out. The +# turn would end there with nothing done, so Flash asks it to go on. +_PROMISE = re.compile( + r"\b(?:I['’]ll|I will|I['’]m going to|I am going to|let me|" + r"let['’]s)\s+" + # Waiting on a sub-agent or the user is a right place to stop. + r"(?!know\b|be\b|leave\b|keep\b|stop\b|wait\b|report\b|notify\b" + r"|let you\b|get back\b|check back\b|update you\b|tell you\b)" + r"[a-z]+", + re.IGNORECASE, +) +# Offers and questions leave the next move to the user, rightly. +_OFFER = re.compile( + r"\b(?:if you(?:['’]d)? (?:like|want|prefer)|would you like|" + r"want me to|shall I|should I|let me know|happy to|just say|" + r"can also|could also)\b", + re.IGNORECASE, +) +_SENTENCE_END = re.compile(r"(?<=[.!?:])\s+") +MAX_PROMISE_NUDGES = 2 +PROMISE_NOTE = ( + "Your last reply said what you would do next, but it called no " + "tool, so nothing was done and your turn would end there. Do it now " + "with the tools, and keep going until it is finished and checked. " + "If you have decided not to, say why in one line instead." +) + + +def unkept_promise(text: str) -> bool: + """Whether a reply ends promising work it did not start.""" + + paragraphs = [p for p in re.split(r"\n\s*\n", text.strip()) if p] + if not paragraphs: + return False + # Only how it ends counts: "I'll" early on is usually a summary of + # what was done, while the last words are what happens next. + sentences = _SENTENCE_END.split(paragraphs[-1].strip()) + tail = " ".join(sentences[-2:]) + if tail.rstrip().endswith("?") or _OFFER.search(tail): + return False + return bool(_PROMISE.search(tail)) + + +def promise_nudge() -> dict: + """Flash telling the model to do what it just said it would. A + system message, so it is not kept in the history after the turn.""" + + return {"role": "system", "content": PROMISE_NOTE} + + def _response_parts(response) -> tuple[str, str, list]: message = getattr(response, "message", None) @@ -1334,6 +1386,40 @@ def _chat_retry_until_response( return final, thinking, tool_calls, None +def _chat_until_acted( + console: Console, + client: "ollama.Client", + convo: list, + tools_arg, + nudged: list, + *, + is_image: bool = False, + turn: Optional[Turn] = None, + bar: Optional[Callable[[], str]] = None, +) -> tuple[str, str, list, Optional[str]]: + """`_chat_retry_until_response`, except that a reply promising work + it made no tool call for is shown, and the model is told to do it, + up to MAX_PROMISE_NUDGES times a turn. CONVO grows by that reply + and the nudge; NUDGED, a one-item list, counts the turn's nudges.""" + + while True: + final, thinking, tool_calls, err = _chat_retry_until_response( + console, client, convo, tools_arg, + is_image=is_image, turn=turn, bar=bar, + ) + if (err or tool_calls or not tools_arg + or nudged[0] >= MAX_PROMISE_NUDGES + or not unkept_promise(final)): + return final, thinking, tool_calls, err + nudged[0] += 1 + _render_thinking(thinking) + _render_markdown(console, final) + convo.append(_message("assistant", final)) + convo.append(promise_nudge()) + # Any picture went with the call just made. + is_image = False + + def _context_ceiling() -> Optional[int]: """The longest window the active model could do, asked once.""" @@ -2928,14 +3014,25 @@ def redraw_banner() -> None: def bar() -> Text: return _bar_text(messages) - final, thinking, tool_calls, err = _chat_retry_until_response( - console, client, [system_message] + messages, offered, + nudged = [0] + first = [system_message] + messages + final, thinking, tool_calls, err = _chat_until_acted( + console, client, first, offered, nudged, is_image=bool(pending_images), turn=turn, bar=bar, ) - if err: + if err and not nudged[0]: _print_backend_error(err) messages.pop() continue + # A reply that promised work and was told to do it stays in + # the history, as the user saw it; the nudge does not. + messages.extend( + m for m in first[1 + len(messages):] + if m.get("role") != "system" + ) + if err: + _print_backend_error(err) + continue subagents.mark_delivered(delivered_ids) if not woken: @@ -3009,9 +3106,9 @@ def bar() -> Text: _message("user", TOOL_IMAGE_NOTE, tool_images) ) - final, thinking, tool_calls, err = _chat_retry_until_response( - console, client, tool_messages, offered, turn=turn, - is_image=bool(tool_images), bar=bar, + final, thinking, tool_calls, err = _chat_until_acted( + console, client, tool_messages, offered, nudged, + turn=turn, is_image=bool(tool_images), bar=bar, ) if err: tool_error = err diff --git a/flash/tools.py b/flash/tools.py index 93e9485..f53f813 100644 --- a/flash/tools.py +++ b/flash/tools.py @@ -2636,7 +2636,9 @@ def _model_preview(model_path: Path) -> str: note = ( "A picture of it, as the user's viewer first shows it (from the " "front right, above), is attached, so judge the shape from what " - "you can see there." + "you can see there. If anything is wrong in it (a part hidden, " + "floating, or out of place), fix it now by calling the tool " + "again, before you write your reply." ) if problems: note += " The viewer reported: " + "; ".join( diff --git a/flash/web.py b/flash/web.py index 506a85c..b08bae2 100644 --- a/flash/web.py +++ b/flash/web.py @@ -1483,6 +1483,7 @@ def run_turn( convo = [system, *chat.messages] keep_from = len(convo) tool_count = 0 + nudged = 0 reply = Streamed() for _round in range(ai.Config.max_tool_rounds): @@ -1490,7 +1491,18 @@ def run_turn( tokens += reply.tokens generating += reply.seconds - if reply.stopped or not reply.calls: + if reply.stopped: + break + if not reply.calls: + # It said what it would do next and stopped short of + # doing it: keep what it said, and tell it to go on. + if (offered and nudged < ai.MAX_PROMISE_NUDGES + and ai.unkept_promise(reply.content)): + nudged += 1 + _finish_reply(session, chat, reply) + convo.append(ai._message("assistant", reply.content)) + convo.append(ai.promise_nudge()) + continue break _finish_reply(session, chat, reply) diff --git a/tests/test_ai.py b/tests/test_ai.py index 2bc5af1..4ea09ec 100644 --- a/tests/test_ai.py +++ b/tests/test_ai.py @@ -532,3 +532,77 @@ def test_a_bang_command_with_no_output_or_a_timeout(monkeypatch): assert "$ touch x\nexit 0\n" in block # nosec B101 assert "$ sleep 999\ntimed out after 600s" in block # nosec B101 + + +# --- Promises the model does not keep -------------------------------------- + + +@pytest.mark.parametrize("text", [ + "Wait, the block is completely covering the text. I'll move the " + "logo text forward so it sits in front of the grass block.", + "The fin is off. Let me fix that.", + "The test still fails.\n\nNow I\u2019ll update the fixture.", + "Next, I will add windows to the house.", + "I'm going to rerun the build.", +]) +def test_a_reply_ending_in_a_plan_is_a_promise(text): + assert ai.unkept_promise(text) # nosec B101 + + +@pytest.mark.parametrize("text", [ + "Done! The model is saved as chair.glb.", + "I'll move it forward if you'd like.", + "Would you like me to add a door?", + "Let me know if you want changes.", + "Want me to add a roof? I can also make it red.", + "I'll be here if you need anything.", + "Started a sub-agent; I'll report back.", + "I'll wait for the build, then let you know.", + "I'll let you know when it finishes.", + "Now I have finished everything.", + # A plan early on, then a finish, is a summary. + "I'll start with the legs.\n\nEverything is built and checked.", + "", +]) +def test_a_finished_reply_or_an_offer_is_not(text): + assert not ai.unkept_promise(text) # nosec B101 + + +def test_the_terminal_tells_a_promising_model_to_go_on(monkeypatch): + replies = [ + ("I'll move the text forward.", "", [], None), + ("", "", ["a call"], None), + ] + seen = [] + + def fake(console, client, convo, tools_arg, **_): + seen.append(list(convo)) + return replies.pop(0) + + monkeypatch.setattr(ai, "_chat_retry_until_response", fake) + monkeypatch.setattr(ai, "_render_markdown", lambda *a, **k: None) + convo = [{"role": "user", "content": "logo"}] + nudged = [0] + + final, _, calls, err = ai._chat_until_acted( + None, None, convo, ["tools"], nudged, + ) + + assert (calls, err, nudged) == (["a call"], None, [1]) # nosec B101 + assert convo[-2:] == [ # nosec B101 + {"role": "assistant", "content": "I'll move the text forward."}, + ai.promise_nudge(), + ] + assert len(seen) == 2 # nosec B101 + + +def test_without_tools_there_is_nothing_to_nudge_towards(monkeypatch): + monkeypatch.setattr( + ai, "_chat_retry_until_response", + lambda *a, **k: ("I'll fix it.", "", [], None), + ) + nudged = [0] + + final, *_ = ai._chat_until_acted(None, None, [], None, nudged) + + assert (final, nudged) == ("I'll fix it.", [0]) # nosec B101 diff --git a/tests/test_web.py b/tests/test_web.py index 1d84465..7eee04b 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -107,6 +107,62 @@ def test_a_reply_streams_token_by_token(self): stats = next(e for e in seen if e["type"] == "stats") assert (stats["tokens"], stats["rate"]) == (4, 10.0) + def test_a_reply_that_promises_work_is_told_to_do_it(self): + FakeClient.scripts = [ + [part(calls=[call("get_date")]), part(done=True)], + # It sees the problem and says what it will do, then stops. + [part("Wait, the block covers the text. I'll move the logo " + "text forward."), part(done=True)], + [part(calls=[call("get_date")]), part(done=True)], + [part("Fixed: the text is in front now."), part(done=True)], + ] + session = web.Session() + drain = events_of(session) + chat = session.new_chat() + + run(session, chat, "make the minecraft logo") + + said = [e["text"] for e in drain() + if e["type"] == "assistant" and e["text"]] + assert said[-2:] == [ + "Wait, the block covers the text. I'll move the logo text " + "forward.", + "Fixed: the text is in front now.", + ] + # The model was told to go on, right after its promise. + sent = FakeClient.requests[-1]["messages"] + at = sent.index({"role": "system", "content": ai.PROMISE_NOTE}) + assert "I'll move the logo" in sent[at - 1]["content"] + assert len(FakeClient.requests) == 4 + # The history keeps what the user saw, not Flash's nudge. + kept = [m.get("content") for m in chat.messages] + assert ai.PROMISE_NOTE not in kept + assert kept[-1] == "Fixed: the text is in front now." + assert any("I'll move the logo" in (c or "") for c in kept) + + def test_a_model_that_keeps_promising_is_let_go(self): + promise = [part("I'll fix it."), part(done=True)] + FakeClient.scripts = [promise, promise, promise] + session = web.Session() + chat = session.new_chat() + + run(session, chat, "fix it") + + # Asked twice, then its word is taken as the answer. + assert len(FakeClient.requests) == 1 + ai.MAX_PROMISE_NUDGES + assert chat.messages[-1]["content"] == "I'll fix it." + + def test_an_offer_is_not_a_promise(self): + FakeClient.scripts = [ + [part("Done. I'll add a roof if you'd like."), part(done=True)], + ] + session = web.Session() + chat = session.new_chat() + + run(session, chat, "make a house") + + assert len(FakeClient.requests) == 1 + def test_a_streamed_reply_comes_without_dashes(self): FakeClient.scripts = [[ part("It works \u2014"), part(" mostly, pages 1\u2013"), From f5be77ddc86a48714e07c070ca4ea7cd2865f6a9 Mon Sep 17 00:00:00 2001 From: "Nathan C." <149914029+Natuworkguy@users.noreply.github.com> Date: Tue, 29 Sep 2026 22:51:35 +0000 Subject: [PATCH 6/8] prompt: test scripts go in scratch, what the user asked for in Downloads The prompt disagreed with itself about where files go: charts went to the scratch directory (gone when Flash exits), documents to the working directory, and Downloads was only a fallback for when that directory was too broad. Replace the scratch section with one rule, three places: - scratch: test scripts, check scripts, the scripts that draw charts or build documents, samples, drafts, and anything downloaded on the way - Downloads: a finished thing the user asked for (a picture, chart, PDF, document, page, 3D model, or a script to keep), with a clear name, never overwriting a file of theirs - the project: changes to the codebase, including tests the user asked to add to its suite A place the user names always wins. The agent finds the Downloads folder itself with a shell command, once, rather than guessing, since Windows often moves it and Linux names it in the user's language. The chart, document, and make_3d_model instructions now follow the same rule. --- flash/system_prompt.txt | 17 ++++++++++------- flash/tools.py | 20 +++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/flash/system_prompt.txt b/flash/system_prompt.txt index 8cc0da5..e7acdcc 100644 --- a/flash/system_prompt.txt +++ b/flash/system_prompt.txt @@ -46,7 +46,7 @@ When you make an image, a PDF, a web page, a document, or a 3D model for the use Check before you send, and check for the exact problem the user reported (overlapping lines, a wrong arrow, cut-off text). If you can still see it, or cannot tell, say so plainly. Never tell the user a problem is fixed because you changed the code meant to fix it: it is fixed when you looked and it was gone. -Revise in place: `edit` the script that makes the file and overwrite the same output, instead of writing numbered copies (v2, fixed, final_v8) that pile up. Scripts and drafts belong in the scratch directory; only the finished file goes where the user wants it. A file that is part of a codebase you are editing (a component, a template, a source file) is not a deliverable: don't send those. +Revise in place: `edit` the script that makes the file and overwrite the same output, instead of writing numbered copies (v2, fixed, final_v8) that pile up. Scripts and drafts belong in the scratch directory; only the finished file goes to Downloads, or wherever the user asked. A file that is part of a codebase you are editing (a component, a template, a source file) is not a deliverable: don't send those. == Reading a web page (fetch) == `fetch` takes an http:// or https:// URL and returns the page as text. It is the cheap way to read what a page says: documentation, an article, a README, a changelog, an API reference, a raw file, a JSON endpoint (non-HTML content comes back untouched). Follow a `web_search` result by fetching the URL it gave you, because a search snippet is an advertisement for a page and the qualifier that changes your answer is usually inside the page itself. @@ -126,11 +126,14 @@ Sending a natural-language reply ends your turn, so gather everything you need b When a question needs working out (math, logic, a tricky bug), work it out step by step in your reply before you give the answer, and put the answer last. An answer written first and justified after is a guess. -== Scratch directory == -Every dummy, sample, test, placeholder, or throwaway file goes in the scratch directory, always, even when the user asked you to make it: a file to try a command on, sample data, a test image, a quick script to check something. Only a location the user names changes that. -Write it by its full path inside the scratch directory, in every tool and every shell command. A bare file name, with no folder in front, lands in the working directory, which is the user's project. +== Where files go == +Every file you write goes in one of three places. A place the user names always wins. -Your scratch directory path is given verbatim in the Tool System Prompt below: copy it exactly, character for character, and never look it up. If a write there fails, the path is wrong: copy it again, never write into the user's project instead. Put downloads and intermediate output there too, never in the user's project, home directory, or working directory, and delete each temp file with `shell` as soon as you're done with it, before you reply, unless the user wants to look at it. Files the user asked for to keep and use (a script for their project, a config, a report) are real output: write those where they belong and leave them. If the destination is unclear and the working directory is too broad to write into (a home directory, a filesystem root), use a sensible default such as Downloads, or ask. +1. The scratch directory, for everything that helps you work: test scripts, a quick script to check something, the script that draws a chart or builds a document, sample data, a file to try a command on, drafts, files you download along the way, and any other dummy, sample, test, placeholder, or throwaway file, even one the user asked you to make. Delete each one with `shell` once you are done with it, before you reply, unless the user wants to look at it. +2. The user's Downloads folder, for a finished thing the user asked you to make: a picture, chart, PDF, document, spreadsheet, web page, 3D model, or a standalone script or program for them to keep. Give it a short, clear name, and pick a new name rather than overwrite a file of theirs already there; a new version of something you made in this chat replaces your own earlier file. +3. The project, for changes to the codebase you are working in: its source, its config, and tests the user asked you to add to its test suite. Put those where the project keeps them. + +The scratch directory's path is given verbatim in the Tool System Prompt below: copy it exactly, character for character, and never look it up. The Downloads folder you find yourself, once per session, before the first file you save there: with `shell`, ask the system where it is rather than guessing (on Windows it is often moved, into OneDrive or onto another drive, and `(New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path` gives it; on Linux, `xdg-user-dir DOWNLOAD`, which may be a name in the user's language; on macOS, `~/Downloads`), and create it if it is missing. Write every file by its full path, in every tool and every shell command. A bare file name, with no folder in front, lands in the working directory, which is the user's project; never leave scripts, tests, or output there by accident. If a write to the scratch directory fails, the path is wrong: copy it again, never write into the user's project instead. When you finish, tell the user the full path of anything you saved for them. == Charts and diagrams == Making a chart, graph, plot, or diagram means writing a Python script that draws it, running that script with `shell`, and sending the picture it made with `send_image`. @@ -141,12 +144,12 @@ Mermaid and other diagram code do not render here: a diagram written as text rea 3. Look at the PNG with `view_image`: labels readable, nothing overlapping, axes and title named. 4. Send it with `send_image`. To change it, `edit` the script, run it again, and send the new version. -Save the PNG where the user asked, or in the scratch directory when they named no place: sending it is how they get it. +Save the PNG in Downloads, or where the user asked, and send it. == Documents (.docx and .pdf) == `read` opens .pdf and .docx files directly and returns their text with line numbers; don't shell out to a script just to read one. A legacy .doc isn't supported: tell the user to save it as .docx. A PDF with no extractable text (a scan) comes back as an explicit error: treat it as unreadable, not empty. -To make one, run a short Python script with `shell`: `python-docx` (imported as `docx`) for .docx, `fpdf2` (imported as `fpdf`) for simple PDFs, `reportlab` for finer layout. Install the library non-interactively first (`python -m pip install --quiet `, `python3` outside Windows); if that fails, tell the user which package to install. Write the script in the scratch directory and delete it afterwards, write the document where the user asked (or the working directory with a sensible name), check it exists and is non-empty, report its full path, and send a PDF with `send_pdf`. +To make one, run a short Python script with `shell`: `python-docx` (imported as `docx`) for .docx, `fpdf2` (imported as `fpdf`) for simple PDFs, `reportlab` for finer layout. Install the library non-interactively first (`python -m pip install --quiet `, `python3` outside Windows); if that fails, tell the user which package to install. Write the script in the scratch directory and delete it afterwards, write the document to Downloads with a sensible name (or where the user asked), check it exists and is non-empty, report its full path, and send a PDF with `send_pdf`. == Describing a project == Never answer from a directory listing, file name, or repo name alone. Gather evidence from inside the folder the user named, by full path: list a couple of levels of the tree, read its README (try README.rst, README.txt, docs/README.md if the obvious name fails), read the manifest (pyproject.toml, package.json, Cargo.toml, go.mod, pom.xml), and if both are missing, read the entry point and the central source files. Then explain, naming the file each claim came from: what it is and the problem it solves, how it's built and run, how it's laid out, and what a new contributor needs to know (entry points, configuration, tests). If you find yourself writing "likely" or "it appears", go read more first. Skip the git status unless asked. diff --git a/flash/tools.py b/flash/tools.py index f53f813..a8bddf1 100644 --- a/flash/tools.py +++ b/flash/tools.py @@ -208,11 +208,16 @@ Your temporary scratch directory is: {SCRATCH_DIR} It will be deleted when the program exits. Use it for temporary files, but do not assume it will persist across runs. -Always use the scratch directory for temporary files, including dummy, - sample, and test files the user asks for, and write them by their full - path there. Never write them to the user's home directory, other - directories, or the current working directory unless the user names - that place. +Always use the scratch directory for temporary files, including test + scripts, and dummy, sample, and test files the user asks for, and write + them by their full path there. Never write them to the user's home + directory, other directories, or the current working directory unless + the user names that place. +Save a finished file the user asked for (a picture, chart, PDF, document, + page, 3D model, or a script for them to keep) in their Downloads folder + by its full path, unless they name another place or it is a change to + the project you are working in. Find that folder's path once with a + shell command before the first such write. """.strip() now = datetime.now() # noqa: DTZ005 @@ -3584,8 +3589,9 @@ def interact( "path": { "type": "string", "description": ( - "Where to save it, ending in .glb, such as " - "chair.glb." + "Full path to save it at, ending in .glb: in " + "the user's Downloads folder, as chair.glb " + "there, unless they named another place." ), }, "parts": { From 111125effcc584d29c7c3a625000964b8521bf53 Mon Sep 17 00:00:00 2001 From: "Nathan C." <149914029+Natuworkguy@users.noreply.github.com> Date: Wed, 30 Sep 2026 02:33:30 +0000 Subject: [PATCH 7/8] Bump version to 0.5.12 --- flash/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flash/version.py b/flash/version.py index 942c51a..a48e612 100644 --- a/flash/version.py +++ b/flash/version.py @@ -1,4 +1,4 @@ -__version__ = "0.5.11" +__version__ = "0.5.12" REPO = "Natuworkguy/Flash" REPO_URL = f"https://github.com/{REPO}" From 172245c0b58ff01cda3b0b0b9c8b7cbecd72632b Mon Sep 17 00:00:00 2001 From: "Nathan C." <149914029+Natuworkguy@users.noreply.github.com> Date: Wed, 30 Sep 2026 02:38:58 +0000 Subject: [PATCH 8/8] fix: refuse a web UI port already in use on Windows Python's HTTP server binds with SO_REUSEADDR. On Linux and macOS that only lets a restart take back a port its closed connections still hold, but on Windows it lets a second server bind a port another is already listening on, and the two then split its connections: a second `flash --web` would quietly share port 7433 with the first instead of saying the port is taken. Which bind wins is not fixed, so test_a_port_in_use_says_so failed on Windows only some of the time. Leave SO_REUSEADDR off on Windows, where a plain bind already refuses a port in use and still reuses one straight after a LAN switch closes it. --- flash/web.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flash/web.py b/flash/web.py index b08bae2..fc29494 100644 --- a/flash/web.py +++ b/flash/web.py @@ -2678,6 +2678,12 @@ def _events(self) -> None: class Server(ThreadingHTTPServer): daemon_threads = True + # SO_REUSEADDR only lets a restart take back a port its old + # connections still hold, on Linux and macOS. On Windows it lets a + # second server bind a port another is listening on, and the two + # then split its connections; and Windows lets a port be reused + # without it anyway. + allow_reuse_address = os.name != "nt" def __init__( self,