diff --git a/PROJECT-PLAN.md b/PROJECT-PLAN.md index cea97e9..5f49ab8 100644 --- a/PROJECT-PLAN.md +++ b/PROJECT-PLAN.md @@ -1,9 +1,10 @@ # Project Maharajong Development Plan -## Current Status (Updated 2026-06-08) -- **Active branch**: `design-playing-mat` (PR #20 open) +## Current Status (Updated 2026-07-12) +- **Active branch**: `feat/materials-and-outreach` - **Blocked on**: Shopify domain propagation (maharajong.com purchased, awaiting DNS) -- **Next up**: Order prototype tile blanks from Amazon; contact Jayi/Promlogo for custom samples; fix tile aspect ratio +- **Decided**: Acrylic tiles confirmed; two build variants specified (see `design/variant-01/` and `design/variant-02/`); Indian artisan sourcing for racks/brass/mat +- **Next up**: Order GUSTARIA prototype blanks; send Jayi/Promlogo inquiries (add Variant 02 clear-back note); contact Moradabad/Jodhpur artisans - **Deferred**: #3, #5, #8 (business/research tasks — on hold until game design is finished) ## Phases & Milestones @@ -26,9 +27,26 @@ - [ ] #17 Adapt tile designs for UV printer — audit done, action items: fix aspect ratio (3:4→32:23), CMYK test strips, transparent backgrounds - [ ] #18 Adapt tile designs for laser engraver — audit done, action items: create SVG engraving overlays, test print-then-engrave workflow - [ ] #21 Social media teaser image — 3 variants generated (square, story, landscape) in PR #20 -- [ ] Tile blank material selection — sourcing spec done (`design/tile-blanks-spec.md`), 3 suppliers evaluated +- [x] Tile blank material selection — **decided (2026-07-11)**: four-layer acrylic from Jayi/Promlogo; wood/stone alternatives evaluated and ruled out (see `design/variant-01/materials-spec.md`) +- [x] Tile blank design variants — **two variants specified (2026-07-12)**: + - Variant 01 (MJ-TILE-BLK-001): Ivory / Gold / Navy / Ivory — `design/variant-01/` + - Variant 02 (MJ-TILE-BLK-002): Ivory / Gold / Navy / Clear — `design/variant-02/` + - Sample decision: request both variants from Jayi/Promlogo, choose after physical comparison +- [x] Manufacturer spec sheet assets — **generated (2026-07-12)** for both variants: + - Engineering drawing (SVG + Chromium PNG, exact proportions) — `design//manufacturer-docs/tile-blank-technical-drawing.*` + - Photorealistic renders (Grok 3-view composite) — `design//manufacturer-docs/tile-blank-spec-sheet-rendered.png` + - 3D Blender render (Cycles, HDRI, exact geometry) — `design//manufacturer-docs/tile-blank-3d-render.png` + - Generator scripts: `design/generate_tile_spec_sheet.py`, `design/generate_tile_blender_render.py` + - Layout reference: `design/TILE-SPEC-SHEET-LAYOUT.md` +- [ ] Source sheesham racks + pushers from Indian artisans — contact Jodhpur/Saharanpur via IndiaMART (`business/outreach/sheesham-racks-inquiry.md`) +- [ ] Source brass dice + scoring trinkets from Moradabad — contact via IndiaMART (`business/outreach/moradabad-brass-inquiry.md`) +- [ ] Source playing mat from Surat sublimation printer with gold satin-stitch embroidery +- [ ] Contact Itz3d Solutions (Chennai) — resin tile marketing batch inquiry (`business/outreach/itz3d-resin-brief.md`) +- [ ] Send Jayi + Promlogo inquiry emails (attach engineering drawings; request both Variant 01 and 02 samples) +- [ ] Order GUSTARIA blanks from Amazon (64 tiles) for immediate UV print/engrave workflow testing - [ ] Tile mockups, playtesting simulations - [ ] Digital prototype (medium TBD) +- [ ] **Post-launch**: Makrana marble collector's edition — limited ultra-premium SKU, hand-cut by Jaipur artisans, priced $2,000–$5,000+ (display/heirloom, not active gameplay) ### Phase 3: Ecommerce Setup - [ ] #22 Shopify store setup & domain — account created, domain purchased, awaiting DNS propagation @@ -50,13 +68,20 @@ - `/design/moodboard/` — 37 moodboard images (rangoli, temples, peacock, spice) - `/design/tiles/` — 51 tile images, `generate_tiles.py`, `tile-design-spec.md` - `/design/mat/` — Mat design final + spec + `generate_mat.py` -- `/design/racks/` — Tile rack design spec +- `/design/racks/` — Tile rack design spec (Indian artisan sourcing notes) - `/design/dice/` — Dice design spec - `/design/trinkets/` — Trinkets & accessories design spec - `/design/marketing/` — Social media teaser images (square, story, landscape) -- `/design/tile-blanks-spec.md` — Tile blank sourcing: 3 suppliers, material comparison, next steps +- `/design/variant-01/` — Tile blank Variant 01: Ivory/Gold/Navy/Ivory (confirmed spec) + - `materials-spec.md`, `tile-blanks-spec.md`, `manufacturer-docs/` +- `/design/variant-02/` — Tile blank Variant 02: Ivory/Gold/Navy/Clear (design proposal) + - `materials-spec.md`, `tile-blanks-spec.md`, `manufacturer-docs/` +- `/design/generate_tile_spec_sheet.py` — Generates SVG engineering drawing + Grok render for any variant +- `/design/generate_tile_blender_render.py` — Generates photorealistic 3D render via Blender Cycles +- `/design/TILE-SPEC-SHEET-LAYOUT.md` — SVG layout reference + variant creation guide +- `/design/lib/` — Three.js r152 + Poly Haven studio HDRI (required by generators) - `/production/engraving/` — xTool F2 Ultra UV laser engraver spec - `/production/printing/` — eufyMake E1 UV printer spec - `/production/tile-production-audit.md` — Compatibility audit: tiles vs. both machines +- `/business/outreach/` — Supplier inquiry email drafts (Jayi, Promlogo, Itz3d, Moradabad, Jodhpur) - `/research/` — Competitor analysis and user research (placeholder) -- `/business/` — Business model and plans (placeholder) diff --git a/business/outreach/itz3d-resin-brief.md b/business/outreach/itz3d-resin-brief.md new file mode 100644 index 0000000..c39e1a6 --- /dev/null +++ b/business/outreach/itz3d-resin-brief.md @@ -0,0 +1,139 @@ +# Itz3d Solutions — Custom Resin Tile Brief (draft) + +**To**: Pravin Ganesh Kumar Duraisamy, Itz3d Solutions +**Contact via**: `indiamart.com/itz-3d-solutions` inquiry form +**From**: ccwells@gmail.com +**Attachments when sending**: + - 1 sample tile face render (from `design/tiles/print-ready/`) for visual reference + - `design/variant-01/manufacturer-docs/tile-blank-technical-drawing.svg` (engineering drawing) + - `design/variant-01/manufacturer-docs/tile-blank-spec-sheet-rendered.png` (rendered product image) + +--- + +**Subject**: Custom cast epoxy resin tiles — silicone mold + small batch quote, 32 × 23 × 13 mm + +--- + +Hello, + +I'm developing **Maharajong** (maharajong.com), a premium Indian-fusion mahjong game +launching direct-to-consumer in the US. Before committing to a large-scale production +run, I need a small hand-cast batch of resin tiles for marketing photography, press +kits, and demo sets — and I'm specifically looking for an Indian manufacturer so the +marketing sets can be described as "hand-crafted in India." + +I found your IndiaMART listing for silicone mold-making and resin casting services and +would like to request a quote. + +--- + +## Tile Specification + +**Dimensions**: 32 mm (width) × 23 mm (height) × 13 mm (depth) + +**Construction**: Four-layer cast epoxy, poured in sequence: + +``` +TOP FACE (shown to player during gameplay) +┌─────────────────────────────┐ +│ Layer 1: Ivory/cream │ ~3 mm — warm ivory, opaque +│─────────────────────────────│ +│ Layer 2: Gold hairline │ ~1 mm — metallic gold (mica/foil or pigment) +│─────────────────────────────│ +│ Layer 3: Navy core │ ~6 mm — deep lapis navy, opaque +│─────────────────────────────│ +│ Layer 4: Ivory back │ ~3 mm — matching ivory to Layer 1 +└─────────────────────────────┘ +BACK FACE +``` + +**Color references** (approximate — we will supply Pantone references if needed): +- Ivory/cream: warm off-white (similar to Pantone 9183 C or equivalent) +- Gold hairline: metallic gold, mica pigment or gold leaf insert +- Navy core: deep lapis blue (similar to Pantone 289 C or equivalent) + +**Surface finish**: +- All six faces must be sanded and polished to a smooth, glossy finish after demolding +- The face (32 × 23 mm) surface will receive UV printing in-house after delivery — + it must be flat, even, and suitable for UV inkjet adhesion (similar to acrylic or + polished resin surfaces) +- No pre-applied artwork or printing required from you — blank tiles only + +**Weight target**: Approximately 11–15 g per tile (standard clear epoxy density is +acceptable; weighted filler optional if you offer it) + +--- + +## Batch Quantities + +This is a **marketing batch only** — not production volume. We need: + +| Phase | Quantity | Purpose | +|-------|----------|---------| +| **Phase 1 — Proof of concept** | 20 tiles (1 mold × 20 pours) | Test mold accuracy, layer appearance, surface polish quality | +| **Phase 2 — Marketing sets** | 456 tiles (3 complete sets × 152 tiles/set) | Photography, press kits, investor demo sets | + +If Phase 1 is satisfactory, we proceed to Phase 2. Please quote both phases separately. + +--- + +## Questions + +1. **Mold design**: Can you produce a silicone (or aluminium-backed silicone) mold for + the 32 × 23 × 13 mm tile? How many cavities per mold, and what is the mold cost? + +2. **Multi-layer pour**: Can you execute the four-layer color sequence described above? + What is your recommended approach for the gold hairline layer — liquid pigment pour, + mica powder insert, or metallic foil sheet between layers? + +3. **Surface finish**: Can you deliver tiles sanded and polished to a glossy surface + suitable for UV inkjet printing? What grit sequence do you use? + +4. **Pricing**: Please quote separately: + - Mold fabrication cost (one-time) + - Per-tile cost for Phase 1 (20 tiles) + - Per-tile cost for Phase 2 (456 tiles) + +5. **Lead time**: Estimated turnaround for Phase 1 after order confirmation? + +6. **Resin type**: What casting resin do you use? (We are open to EPOKE, MR. JO, or + equivalent premium Indian art resins — please advise what gives the best ivory + opacity and polish.) + +7. **Shipping**: Can you ship finished tiles to a US address (DHL/FedEx)? Approximate + shipping cost for 456 tiles? + +--- + +## Context for Your Reference + +The full Maharajong tile set contains 152 unique tiles (across 8 design categories). +The marketing batch tiles will receive custom UV-printed artwork on the face after we +receive them. The four-layer construction is important because the navy core and gold +hairline are visible on the tile edges during gameplay — this is the key visual +differentiator we want to show in marketing photos. + +We are also in parallel requesting quotes from Chinese OEM suppliers (Jayi Acrylic, +Promlogo) for the production run of 100+ sets. The Indian resin batch serves a different +purpose: provenance, artisan story, and marketing materials. + +Happy to share a full design brief, moodboard, and sample tile renders after an initial +exchange. I can also provide a physical 3D-printed reference tile if that helps with +mold design. + +Best regards, +Charlie Wells +Maharajong — maharajong.com +ccwells@gmail.com + +--- + +## Pre-send checklist + +- [ ] Attach 1–2 sample tile face renders from `design/tiles/print-ready/` +- [ ] Prepare a simple layer diagram (can be hand-sketched and photographed) +- [ ] Consider ordering a 3D-printed reference tile at 32×23×13mm before sending — + gives Itz3d a physical object to mold from (use any online 3D print service, + ~$5–10 for a single rectangular block) +- [ ] Confirm Pantone color references for ivory and navy before sending + (check `design/materials-spec.md` for any finalized references) diff --git a/business/outreach/jayi-inquiry-email.md b/business/outreach/jayi-inquiry-email.md new file mode 100644 index 0000000..aab4672 --- /dev/null +++ b/business/outreach/jayi-inquiry-email.md @@ -0,0 +1,44 @@ +# Jayi Acrylic — OEM quote inquiry (draft) + +**To**: via https://www.jayiacrylic.com/custom-mahjong-set/ contact form or sales email +**From**: ccwells@gmail.com +**Attachments when sending**: tile face renders (a few samples from `design/tiles/print-ready/`), `design/variant-01/manufacturer-docs/tile-blank-technical-drawing.svg` (engineering drawing). Note: Jayi will sign an NDA before receiving full artwork — request that first. + +--- + +**Subject**: Custom 4-layer mahjong tile quote — 152-tile premium set, 100-set initial run + +Hello, + +I'm developing Maharajong, a premium Indian-fusion mahjong set sold direct-to-consumer in the US (maharajong.com), and I'm looking for an OEM partner for our tiles and potentially the full set. Your custom mahjong work and multi-layer capabilities look like a strong fit. + +**What I'd like quoted:** + +1. **Tiles — the core of the inquiry** + - Quantity: 152 tiles per set × 100 sets (15,200 tiles) for the initial production run — plus a prototype sample set first + - Size: 32 × 23 × 13 mm + - Construction: four-layer cast acrylic — + - Face layer: warm ivory (Pantone TBD — we'll supply a target chip) + - Thin gold hairline layer (~0.5–1 mm) + - Core layer: deep lapis navy (~5–6 mm) + - Back layer: matching ivory + - Surface: polished, ready to accept our own UV printing and UV laser engraving (we produce tile faces in-house; blanks only — no artwork application needed from you for the main run) + - Target weight: 16–19 g per tile — please advise whether your standard 4-layer acrylic reaches this, and if not, what options exist (higher-density material, thicker build) to get there +2. **Prototype sample**: 1 sample set (or partial, e.g. 20 tiles) of the exact 4-layer build above, before mass production — please quote sample cost and lead time separately +3. **Optional full-set OEM quote** (separate line items, for comparison against sourcing components individually): + - 4 tile racks (19") + 4 pushers with magnets — solid sheesham/rosewood with a thin brass inlay line, or your closest equivalent + - Presentation case sized for 152 tiles + racks + accessories + +**Questions:** +- MOQ confirmation for the tile spec above, and price breaks at 100 / 250 / 500 sets +- Lead time for prototype and for the 100-set run +- Landed-cost guidance: do you ship DDP to the US, or FOB (we arrange freight)? Any recent experience with US tariff classification for acrylic game tiles? +- Pantone matching process for the ivory/gold/navy layers +- Can you sign an NDA before we send full artwork and dielines? + +We're in active prototyping with a public waitlist, targeting a Founding Edition pre-order later this year. Happy to get on a call. + +Best regards, +Charlie Wells +Maharajong — maharajong.com +ccwells@gmail.com diff --git a/business/outreach/moradabad-brass-inquiry.md b/business/outreach/moradabad-brass-inquiry.md new file mode 100644 index 0000000..201f868 --- /dev/null +++ b/business/outreach/moradabad-brass-inquiry.md @@ -0,0 +1,72 @@ +# Moradabad Brass Manufacturer — dice and scoring trinkets inquiry (draft) + +**To**: [identified via IndiaMART — search "custom brass dice manufacturer moradabad" +or "brass enamel game pieces manufacturer india"] +**From**: ccwells@gmail.com +**Attachments when sending**: dice pip layout diagram, trinket design reference images, +Pantone color references for enamel fills + +--- + +**Subject**: Custom solid brass dice + scoring tokens — premium board game set, OEM quote + +Hello, + +I'm developing Maharajong, a premium Indian-fusion mahjong set sold direct-to-consumer +in the US (maharajong.com), and I'm looking for a Moradabad brass manufacturer for two +custom components: dice and scoring tokens. The entire set's metal language is antique +brass — dice and trinkets are the showcase pieces. + +**Component 1: Solid brass dice** +- Type: 6-sided (d6), standard 16 mm +- Material: Solid brass, no hollow core — weight is a premium cue +- Corners: Rounded for comfortable rolling and premium hand-feel +- Finish: Antique brass patina — warm, slightly aged gold-bronze tone (not bright + polished); light brushed or tumbled texture to reduce fingerprint visibility +- Pip design: + - Faces 2–6: recessed pips filled with deep navy enamel + (Pantone 2767 C or closest match — to be confirmed with physical chip) + - Face 1: single decorative motif — a lotus bud or peacock-feather eye (~3 mm + diameter), recessed and navy-filled, instead of a plain dot + - Each face has a subtle recessed border line framing the pips +- Optional branding: tiny engraved Maharajong logo mark in one corner of the 6-pip face + +**Component 2: Scoring tokens (trinkets)** +- Per our design spec (full brief shared after intro): small solid brass tokens + with jewel enamel fills in two motif types — + - Teal peacock-eye motif (enamel: Pantone 326 C or similar) + - Magenta lotus motif (enamel: Pantone 233 C or similar) +- Finish: Matching antique brass patina +- Quantity per set: TBD (finalized in design spec — we will share full brief) + +**Quantities:** +- Prototype: 1 pair of dice (2 pieces) + sample tokens — please quote sample cost + and lead time separately before committing to production +- Initial production run: 100 sets + +**Questions:** +- Sample / prototype cost and lead time +- MOQ and pricing tiers at 100 / 250 / 500 sets +- Enamel fill: can you Pantone-match navy, teal, and magenta hard enamel fills? + Do you use cold enamel or vitreous enamel? +- Antique patina process: chemical patina or electroplating? +- Do you CNC machine the dice, or investment cast? +- Shipping: DDP to the US, or FOB? +- Do you sign NDAs before receiving full artwork and specifications? + +We're targeting a Founding Edition pre-order launch later this year. The brass dice +are a signature component — we want them to feel unmistakably Indian-made and +unmistakably premium. Happy to get on a call. + +Best regards, +Charlie Wells +Maharajong — maharajong.com +ccwells@gmail.com + +--- + +**Source contacts to send this to:** +- Moradabad brass exporters: search IndiaMART "custom brass dice manufacturer moradabad" + or "brass enamel token game piece manufacturer" +- Jaipur meenakari artisans (for enamel fills if Moradabad supplier doesn't offer): + search IndiaMART "meenakari brass enamel manufacturer jaipur export" diff --git a/business/outreach/promlogo-inquiry-email.md b/business/outreach/promlogo-inquiry-email.md new file mode 100644 index 0000000..aee6d9f --- /dev/null +++ b/business/outreach/promlogo-inquiry-email.md @@ -0,0 +1,40 @@ +# Promlogo — blank tile sample pack inquiry (draft) + +**To**: via https://promlogo.com/blank-mahjong-tiles/ contact form or sales email +**From**: ccwells@gmail.com + +--- + +**Attachments when sending**: `design/variant-01/manufacturer-docs/tile-blank-technical-drawing.svg` (engineering drawing) + +--- + +**Subject**: Sample pack request — blank mahjong tiles, 3 materials, 32 × 23 × 13 mm + +Hello, + +I'm developing a premium custom mahjong set (Maharajong, maharajong.com) and evaluating blank tile materials before committing to a production run. We apply our own artwork in-house via UV printing and UV laser engraving, so we need polished blanks only. + +**Sample pack request — 3 material variants, ~20 tiles each if possible:** + +1. **Four-layer acrylic** — ivory face / thin gold layer / deep navy core / ivory back (or your closest stock equivalent to an ivory face with colored edge layers) +2. **Melamine** — classic ivory/cream, single layer +3. **Acrylic face + wood back** — your premium wood-back option, ivory face + +**Specs for all samples:** +- Size: 32 × 23 × 13 mm (within your stated 30–40 mm custom range) +- Surface: finely polished, suitable for UV print and laser engraving +- Please include per-tile weight for each material in your response — hand-feel weight is a key selection criterion for us (target 16–19 g) + +**Questions:** +- Sample pack cost and shipping to the US (we'll pay — please invoice) +- If we proceed: MOQ and pricing tiers for the chosen material at 15,000–80,000 tiles (100–500 sets of 152) +- For the 4-layer acrylic: can layer colors be custom-matched to Pantone references at production volume? +- Lead times for samples and production + +We're targeting a decision within a few weeks of receiving samples. + +Best regards, +Charlie Wells +Maharajong — maharajong.com +ccwells@gmail.com diff --git a/business/outreach/sheesham-racks-inquiry.md b/business/outreach/sheesham-racks-inquiry.md new file mode 100644 index 0000000..428f977 --- /dev/null +++ b/business/outreach/sheesham-racks-inquiry.md @@ -0,0 +1,66 @@ +# Indian Sheesham Manufacturer — tile racks and pushers inquiry (draft) + +**To**: [identified via IndiaMART — search "custom sheesham wood rack manufacturer" or +"wooden game component OEM jodhpur saharanpur"] +**From**: ccwells@gmail.com +**Attachments when sending**: rack dimension diagram, brass inlay detail sketch, +Maharajong logo file for engraving reference + +--- + +**Subject**: Custom sheesham tile racks + pushers — premium board game set, OEM quote + +Hello, + +I'm developing Maharajong, a premium Indian-fusion mahjong set sold direct-to-consumer +in the US (maharajong.com), and I'm looking for an Indian sheesham wood manufacturer +for our tile racks and pushers. Sheesham is central to the set's design identity — +it's a deliberate provenance statement over walnut, and we want these components +made in India. + +**Component 1: Tile racks** — 4 per set +- Material: Solid sheesham (Indian rosewood), hand-rubbed oil finish (satin, not glossy) +- Length: 19 inches (482 mm); standard tile rack profile — holds 32 mm-wide tiles + upright in a single row +- Inlay: One thin (~2 mm) antique-brass rule line inlaid along the full length of the + top outer edge of each rack +- Branding: Small Maharajong lotus-peacock logo laser-engraved on one end face + (artwork vector file provided) +- Optional: Wind direction symbol in Devanagari (पू / द / प / उ) engraved on the + outer-facing side of each rack, one per rack, to mark player seats + +**Component 2: Tile pushers** — 4 per set (one per rack) +- Material: Matching solid sheesham, same oil finish as rack +- Form: Flat pusher that slides along the rack channel +- Feature: Built-in rare-earth magnets (we can specify strength) to hold the pusher + securely against the rack during play; releases easily when pulled + +**Quantities:** +- Prototype: 1 complete set (4 racks + 4 pushers) — please quote sample cost and + lead time separately +- Initial production run: 100 sets (400 racks + 400 pushers) + +**Questions:** +- MOQ confirmation and pricing tiers at 100 / 250 / 500 sets +- Can you source the antique-brass inlay strip and do the inlay work in-house? +- Can you install rare-earth magnets in the pusher during production? +- What sheesham grades/sources do you use? (We want consistent dark chocolate grain, + sustainably sourced if possible) +- Lead time: prototype, then mass production +- Shipping: DDP to the US, or FOB (we arrange freight)? +- Do you sign NDAs before receiving detailed artwork and dielines? + +We're targeting a Founding Edition pre-order launch later this year, with racks as a +key premium component. Happy to share full dielines and artwork after an intro exchange. + +Best regards, +Charlie Wells +Maharajong — maharajong.com +ccwells@gmail.com + +--- + +**Source contacts to send this to:** +- Jodhpur, Rajasthan artisans: search IndiaMART "sheesham wood custom rack manufacturer jodhpur" +- Saharanpur, UP: search IndiaMART "wooden game component manufacturer saharanpur export" +- Pravat Timbers, Kolkata: `pravattimbers.com` / info@woodengiftcompany.com / +91 905 105 1051 diff --git a/business/shopify/store-configuration.md b/business/shopify/store-configuration.md new file mode 100644 index 0000000..9f82d88 --- /dev/null +++ b/business/shopify/store-configuration.md @@ -0,0 +1,159 @@ +# Maharajong — Shopify Store Configuration Guide + +**Store URL**: maharajong.myshopify.com/admin +**Custom domain**: maharajong.com (DNS propagated ✅ 2026-07-12) +**Shopify plan**: Basic +**Closes**: GitHub issue #22 + +--- + +## DNS & SSL status + +| Record | Value | Status | +|--------|-------|--------| +| `maharajong.com` A | `23.227.38.71` (Shopify) | ✅ Propagated | +| `www.maharajong.com` CNAME | `shops.myshopify.com` | ✅ Propagated | +| SSL certificate | HTTPS / HTTP2 active | ✅ Active | + +--- + +## 1. Store settings +**Path**: Settings → General + +| Field | Value | +|-------|-------| +| Store name | Maharajong | +| Store email | hello@maharajong.com | +| Store currency | USD — United States Dollar | +| Unit system | Imperial | +| Default weight unit | Pounds (lb) | +| Time zone | *(set to your local timezone)* | + +--- + +## 2. Domain configuration +**Path**: Settings → Domains + +1. Confirm `maharajong.com` is listed and set as **Primary domain** +2. Enable **"Redirect all traffic to this domain"** so `www.maharajong.com` → `maharajong.com` +3. Verify the green "Connected" indicator appears next to maharajong.com + +--- + +## 3. Branded email +**Path**: Settings → Notifications → Sender email + +1. Set sender email to `hello@maharajong.com` +2. Shopify will send a verification email — click the link to confirm +3. If using Google Workspace: + - Set up `hello@maharajong.com` in Google Workspace Admin + - Add Shopify's SPF record to DNS: `v=spf1 include:shops.myshopify.com ~all` + - This ensures transactional emails (order confirmations, shipping) pass spam filters + +--- + +## 4. Brand assets +**Path**: Settings → Brand + +### Interim logo (placeholder until issue #42 is resolved) +The standalone vector logo does not yet exist (see issue #42). +Use the tile back image as a placeholder: + +1. Open `design/tiles/tile-back/tile-back.png` +2. Crop to a square, centred on the lotus-peacock motif +3. Export at **512 × 512 px PNG** with white or transparent background +4. Upload at Settings → Brand → **Logo** +5. Add a note internally: *"Placeholder — replace when #42 (logo design) is complete"* + +### Favicon (placeholder) +1. From the same cropped square, export at **32 × 32 px** as `.png` +2. Upload at Settings → Brand → **Favicon image** + +### Brand colours +Configure these under Settings → Brand → **Brand colours** if your theme supports it: + +| Role | Colour | Hex | +|------|--------|-----| +| Primary / accent | Gold | `#D4AF37` | +| Background / base | Lapis navy | `#1C2E5E` | +| Surface | Ivory cream | `#F5EDD8` | +| Highlight | Magenta | `#C2185B` | +| Highlight 2 | Teal | `#00897B` | + +--- + +## 5. Staff accounts +**Path**: Settings → Users and permissions + +- Add collaborators with **Limited permissions** (Staff role) — do not share the Owner credential +- Owner account should use 2FA; enforce 2FA for staff in Settings → Security + +--- + +## 6. Checkout & payments (preliminary — full setup in issue #25) +**Path**: Settings → Payments + +Enable now to avoid blocking test orders: +- Activate **Shopify Payments** (primary, eliminates 2% transaction fee on Basic) +- Enable **PayPal** as backup +- Enable **Shop Pay**, **Apple Pay**, **Google Pay** under express checkout + +--- + +## 7. Contact information +**Path**: Settings → Store details → Contact information + +Ensure the following are set (required for policy pages and invoices): +- Business legal name +- Business address (used on tax invoices) +- Country: United States + +--- + +## 8. Customer accounts +**Path**: Settings → Customer accounts + +- Set to **Optional** (do not force account creation at checkout — reduces friction) + +--- + +## 9. Checkout settings +**Path**: Settings → Checkout + +| Setting | Value | +|---------|-------| +| Customer accounts | Guest checkout allowed | +| Require first and last name | Yes | +| Company name | Optional | +| Address line 2 | Optional | +| Shipping address phone number | Required | +| Tipping | Off (premium product, not applicable) | +| Order processing | Automatically fulfil only the gift cards of the order | + +--- + +## 10. Post-setup checklist + +- [ ] Store name set to "Maharajong" +- [ ] Currency set to USD +- [ ] maharajong.com confirmed as primary domain with redirect enabled +- [ ] SSL green in Settings → Domains +- [ ] hello@maharajong.com set as sender and verified +- [ ] Placeholder logo uploaded (512×512px, tile-back.png cropped) +- [ ] Favicon uploaded (32×32px) +- [ ] Brand colours configured +- [ ] Shopify Payments activated +- [ ] Customer accounts set to Optional +- [ ] Staff accounts created if needed +- [ ] Issue #42 (logo design) created and assigned ✅ + +--- + +## Next steps + +| Issue | Task | +|-------|------| +| #42 | Replace placeholder logo with final vector logo mark | +| #23 | Storefront theme design & brand customisation | +| #25 | Payment processing & checkout optimisation (full setup) | +| #27 | Legal compliance — Privacy Policy, Terms, Refund Policy | diff --git a/design/TILE-SPEC-SHEET-LAYOUT.md b/design/TILE-SPEC-SHEET-LAYOUT.md new file mode 100644 index 0000000..f7b6706 --- /dev/null +++ b/design/TILE-SPEC-SHEET-LAYOUT.md @@ -0,0 +1,213 @@ +# Tile Spec Sheet — SVG Layout Reference + +Generator script: `design/generate_tile_spec_sheet.py` + +## Quick commands + +```bash +# SVG only (no API, no Chromium) +python3 design/generate_tile_spec_sheet.py --svg-only --variant variant-01 + +# PNG rasterisation of SVG via Chromium (pixel-accurate, no AI) +python3 design/generate_tile_spec_sheet.py --png-only --variant variant-01 + +# Grok 3D rendered image only (marketing impression) +python3 design/generate_tile_spec_sheet.py --img-only --variant variant-01 + +# Full pipeline: SVG + Chromium PNG + Grok render +python3 design/generate_tile_spec_sheet.py --variant variant-01 + +# Regenerate all variants +for v in variant-01 variant-02; do + python3 design/generate_tile_spec_sheet.py --variant $v +done +``` + +Outputs go to `design//manufacturer-docs/`: +- `tile-blank-technical-drawing.svg` — engineering drawing source (Letter landscape, 11×8.5in) +- `tile-blank-technical-drawing.png` — **pixel-accurate** rasterisation via Playwright/Chromium +- `tile-blank-spec-sheet-rendered.png` — Grok 3D perspective render (marketing impression only) + +**Use the Chromium PNG for supplier submissions** — it has mathematically correct layer +proportions. The Grok render is approximate and suitable for marketing materials only. + +Playwright/Chromium must be installed to generate the PNG: +```bash +python3.11 -m pip install playwright +python3.11 -m playwright install chromium +``` + +--- + +## Canvas and print dimensions + +| Property | Value | +|----------|-------| +| SVG `width` / `height` | `11in` / `8.5in` (Letter landscape) | +| ViewBox | `0 0 1100 850` (100 units per inch) | +| Working units | px — 1px = 0.01in = 0.254mm | +| Margin | 20px all sides | + +--- + +## Scale system + +Two scales are used simultaneously. Both are defined at the top of `generate_svg()`: + +| Variable | Value | Used for | +|----------|-------|----------| +| `SC` | `8 px/mm` | Main orthographic views (Views A, B, C) — 1:1 effective scale | +| `SC2` | `16 px/mm` | Detail D layer cross-section — 2:1 scale | + +Derived tile dimensions (computed automatically from `SC`/`SC2`): + +| Variable | Formula | Value at SC=8 | +|----------|---------|---------------| +| `W` | `TILE_W_MM × SC` | 256 px (32mm) | +| `H` | `TILE_H_MM × SC` | 184 px (23mm) | +| `D` | `TILE_D_MM × SC` | 104 px (13mm) | +| `l1..l4` | `LAYER_n_MM × SC` | 24 / 8 / 48 / 24 px | +| `d1..d4` | `LAYER_n_MM × SC2` | 48 / 16 / 96 / 48 px | +| `DETAIL_H` | `TILE_D_MM × SC2` | 208 px | + +--- + +## Layout zones + +``` +┌──────────────────────────────────────────────────────────────┐ +│ HEADER — title, variant label, drawing number y: 0–100 │ +├───────────────────────────────┬──────────────────────────────┤ +│ LEFT PANEL x: 20–614 │ RIGHT PANEL x: 614–1080 │ +│ │ │ +│ View A face (32×23mm) │ Detail D layer cross-sec. │ +│ View B long edge (32×13mm) │ Spec table (14 rows) │ +│ View C short edge (23×13mm) │ │ +│ │ y: 100–698 │ +├───────────────────────────────┴──────────────────────────────┤ +│ FOOTER — general notes + title block y: 700– │ +│ Notes box x: 20–484 │ Title block x: 510–1080 │ +└──────────────────────────────────────────────────────────────┘ +``` + +--- + +## Key position variables + +All defined near the top of `generate_svg()`: + +### Left panel + +| Variable | Value | Description | +|----------|-------|-------------| +| `VX` | `70` | Left edge of face/edge views | +| `VY` | `115` | Top of face view (View A) | +| `FX, FY` | `VX, VY` | Face view origin | +| `EX, EY` | `VX, FY+H+85` | Long-edge view origin | +| `SEX, SEY` | `EX+W+60, EY` | Short-edge view origin | + +### Right panel + +| Variable | Value | Description | +|----------|-------|-------------| +| `DIVIDER_X` | `614` | Vertical divider between panels | +| `DX` | `640` | Left edge of Detail D diagram | +| `DY` | `VY` | Top of Detail D (aligned with left panel) | +| `DETAIL_SECTION_W` | `155` | Width of Detail D diagram | +| `DETAIL_H` | `208` | Height of Detail D (`TILE_D_MM × SC2`) | + +### Spec table + +| Variable | Formula | Value | +|----------|---------|-------| +| `SPEC_X` | `DX - 4` | Left edge | +| `SPEC_Y` | `DY + DETAIL_H + 36` | Top (below Detail D) | +| `SPEC_W` | `CANVAS_W - SPEC_X - 22` | Width (to right margin) | +| `SPEC_ROW_H` | `19` | Row height (px) | +| `SPEC_COL2` | `SPEC_X + 195` | Value column x position | + +### Footer + +| Variable | Value | Description | +|----------|-------|-------------| +| `FOOTER_Y` | `700` | Top of footer strip | +| `FOOTER_H` | `CANVAS_H - FOOTER_Y - 18` | Footer height | +| `TB_X` | `510` | Title block left edge | +| `TB_Y` | `FOOTER_Y` | Title block top | +| `TB_W` | `CANVAS_W - TB_X - 20` | Title block width | +| `TB_H` | `FOOTER_H` | Title block height | +| Notes box | `x=20, w=TB_X-26` | Left of title block | + +--- + +## Spec table vertical budget + +With current values: +- `SPEC_Y` = 115 + 208 + 36 = **359** +- 14 rows × 19px = 266px → `SPEC_Y + 266` = **625** +- `FOOTER_Y` = **700** +- Clearance: 700 − 625 = **75 px** ← comfortable + +For a new variant with more spec rows: +- Each extra row costs 19px +- Budget for extra rows: `(FOOTER_Y - SPEC_Y - 20) / SPEC_ROW_H` ≈ **35 rows max** + +--- + +## Adding a new variant + +1. **Create the variant folder**: + ```bash + mkdir -p design/variant-03 + ``` + +2. **Copy and edit the spec files** from the closest existing variant: + ```bash + cp design/variant-02/materials-spec.md design/variant-03/materials-spec.md + cp design/variant-02/tile-blanks-spec.md design/variant-03/tile-blanks-spec.md + ``` + +3. **Add the variant to `generate_svg()`** in `generate_tile_spec_sheet.py`: + - Add `is_v3 = (variant == "variant-03")` near the other `is_v2` flags + - Add layer fill/label/spec/back-note overrides following the existing pattern + - Add a `dwg_number` entry: `"MJ-TILE-BLK-003"` + - Add a `variant_label` entry + +4. **Add a Grok prompt** in `get_rendered_prompt(variant)`: + ```python + if variant == "variant-03": + return "...describe the new visual..." + ``` + +5. **Generate**: + ```bash + python3 design/generate_tile_spec_sheet.py --variant variant-03 + ``` + +6. **Open in Safari / browser** to review the SVG before sending to suppliers. + +7. **Validate XML** (catches any unescaped `&` or malformed tags): + ```bash + xmllint --noout design/variant-03/manufacturer-docs/tile-blank-technical-drawing.svg + ``` + +--- + +## Common pitfalls + +| Issue | Cause | Fix | +|-------|-------|-----| +| Safari XML error | Unescaped `&` in text content | Use `&` in all SVG text strings | +| Spec table overflows footer | Too many rows or large `SPEC_ROW_H` | Reduce `SPEC_ROW_H` or increase `FOOTER_Y` | +| View C overlaps divider | `SEX + TILE_H_MM*SC > DIVIDER_X` | Increase `DIVIDER_X` or reduce `SEX` | +| Right-panel labels overlap | `DX + DETAIL_SECTION_W + 56 + label_width > CANVAS_W - 20` | Shorten label text or reduce `DETAIL_SECTION_W` | +| Leader text off-canvas | SC2 too large, DETAIL_H too tall | Reduce SC2 | + +--- + +## Variant registry + +| Variant | Drawing No. | Layer stack | Status | +|---------|-------------|-------------|--------| +| variant-01 | MJ-TILE-BLK-001 | Ivory / Gold / Navy / **Ivory** | Confirmed spec | +| variant-02 | MJ-TILE-BLK-002 | Ivory / Gold / Navy / **Clear** | Design proposal | diff --git a/design/dice/dice-design-spec.md b/design/dice/dice-design-spec.md index 4925f5d..0574d5c 100644 --- a/design/dice/dice-design-spec.md +++ b/design/dice/dice-design-spec.md @@ -14,9 +14,9 @@ Antique brass dice, 6-sided brass dice, six-sided solid brass dice, brass dice s ### Pip design - **Standard pips** replaced with small lotus-bud engravings (or traditional dot pips with a decorative ring — TBD after prototype) -- Pips are **recessed and filled** with enamel or paint in a contrasting color: - - **Option A**: Deep teal enamel fill (matches the mat and tile back palette) - - **Option B**: Ivory/cream enamel fill (matches the tile face) +- Pips are **recessed and filled** with enamel in a contrasting color: + - **Selected (2026-07-03)**: Deep navy enamel fill — matches the tile core layer and mat field, so dice, tiles, and mat share one blue (see `design/materials-spec.md`) + - Alternatives considered: deep teal (close second — revisit at sample stage), ivory/cream (too low-contrast on brass) - The 1-pip face features a single larger motif — a peacock-feather eye or the Maharajong lotus — instead of a plain dot ### Surface finish diff --git a/design/diya/diya-design-spec.md b/design/diya/diya-design-spec.md new file mode 100644 index 0000000..21b9757 --- /dev/null +++ b/design/diya/diya-design-spec.md @@ -0,0 +1,41 @@ +# Maharajong Diya Light Design Spec + +**Added**: 2026-07-03 — new set component (see `design/materials-spec.md`) + +## Concept +A solid brass diya (traditional Indian oil lamp) that lights the table at the +start of play. No competitor set includes one; it photographs beautifully and +turns setup into a small ritual — place the diya, light the lamp, build the +wall. Echoes the lit diya featured throughout the teaser photography. + +## Physical Specifications +- **Material**: Solid brass, antique patina finish (matching dice and trinkets) +- **Form**: Classic leaf-spout diya, ~70–80 mm long × ~25 mm tall, on a low + lotus-petal foot; decorative engraving around the bowl rim echoing the + rangoli-dot border from the mat +- **Light source**: Removable flameless LED insert — warm amber flicker + (~1600K), replaceable coin cell, subtle on/off underside switch +- **Real-flame option**: The bowl retains a functional wick cup and can burn + ghee or oil for those who want the true ritual — LED insert simply lifts out +- **Safety note**: LED is the default recommendation in all product copy; the + set's micro-suede mat and fabric packaging make an open flame something the + buyer opts into deliberately +- **Quantity per set**: 1 + +## Art Direction +- Antique brass patina, warm and slightly aged — never shiny/polished +- Engraved lotus-petal band around the foot; tiny peacock-feather eye at the + spout base +- Optional: "Maharajong" in Devanagari-styled lettering engraved underneath + the foot (hidden delight, not visible in play) + +## Packaging +- Sits in its own felt-lined recess in the game box, beside the dice pouch +- Include one spare LED insert battery + +## Production Notes +- Source alongside the brass dice/trinkets from the same metalworker for + consistent patina (investment cast or spun brass + hand engraving) +- LED insert is an off-the-shelf flameless tealight mechanism (38 mm standard) + — verify the bowl inner diameter accepts it with a felt retention ring +- Request patina sample chips before committing the full brass order diff --git a/design/generate_tile_3d_render.py b/design/generate_tile_3d_render.py new file mode 100644 index 0000000..ef108d9 --- /dev/null +++ b/design/generate_tile_3d_render.py @@ -0,0 +1,382 @@ +#!/usr/bin/env python3 +""" +Generate a photorealistic 3D render of the Maharajong blank tile using +a Three.js scene rendered via Playwright/Chromium. + +The tile is built as four stacked BoxGeometry meshes — one per layer — +so layer proportions are mathematically exact, not AI-approximated. + +Outputs: + design//manufacturer-docs/tile-blank-3d-render.png + +Usage: + python3 design/generate_tile_3d_render.py --variant variant-01 + python3 design/generate_tile_3d_render.py --variant variant-02 +""" + +import argparse +import http.server +import subprocess +import sys +import tempfile +import threading +import time +import urllib.request +from pathlib import Path + +# ── Paths ──────────────────────────────────────────────────────────────────── +DESIGN_DIR = Path(__file__).parent +LIB_DIR = DESIGN_DIR / "lib" +THREE_JS = LIB_DIR / "three.min.js" +THREE_URL = "https://unpkg.com/three@0.152.2/build/three.min.js" + +# ── Tile constants (mm = scene units) ──────────────────────────────────────── +W = 32 # tile width (X) +TH = 23 # tile face height (Z — the tile lies face-up, Z is its length) +D = 13 # tile depth (Y — layers run along Y, face on top) +L1 = 3 # Layer 1: ivory face (top) +L2 = 1 # Layer 2: gold hairline +L3 = 6 # Layer 3: lapis navy core +L4 = 3 # Layer 4: back (ivory V01 / crystal-clear V02) + +RENDER_W = 2560 +RENDER_H = 1600 + + +# ── Three.js download ──────────────────────────────────────────────────────── + +def ensure_threejs() -> None: + LIB_DIR.mkdir(exist_ok=True) + if THREE_JS.exists(): + return + print(f"Downloading Three.js r152 → {THREE_JS.relative_to(DESIGN_DIR)} ...", + end=" ", flush=True) + urllib.request.urlretrieve(THREE_URL, THREE_JS) + print(f"OK ({THREE_JS.stat().st_size // 1024} KB)") + + +# ── HTML scene template ────────────────────────────────────────────────────── +# Written as a plain string (no f-string) to avoid curly-brace escaping hell. +# Two placeholders are substituted: BACK_MAT_CODE and VARIANT_LABEL. + +SCENE_TEMPLATE = """\ + + + + + + + + + + + +""" + + +def build_html(variant: str) -> str: + is_v2 = (variant == "variant-02") + + if is_v2: + # Crystal-clear acrylic back — navy core visible through it. + # MeshPhysicalMaterial with transmission approximates this. + back_mat = ( + "new THREE.MeshPhysicalMaterial({" + " color: 0x2A4070," # navy tinted (seen through 3mm clear) + " roughness: 0.02," + " metalness: 0.0," + " transmission: 0.70," # let light pass through + " thickness: 3.0," + " transparent: true," + " ior: 1.49," # acrylic IOR + " clearcoat: 1.0," + " clearcoatRoughness: 0.01" + "})" + ) + else: + back_mat = ( + "new THREE.MeshStandardMaterial({" + " color: 0xE8DFC8," + " roughness: 0.06," + " metalness: 0.0" + "})" + ) + + html = (SCENE_TEMPLATE + .replace("BACK_MAT_CODE", back_mat) + .replace("TILE_W", str(W)) + .replace("TILE_TH", str(TH)) + .replace("TILE_D", str(D)) + .replace("LAYER_1", str(L1)) + .replace("LAYER_2", str(L2)) + .replace("LAYER_3", str(L3)) + .replace("LAYER_4", str(L4)) + .replace("REND_W", str(RENDER_W)) + .replace("REND_H", str(RENDER_H))) + return html + + +# ── Local HTTP server ───────────────────────────────────────────────────────── + +class _SilentHTTPHandler(http.server.SimpleHTTPRequestHandler): + def log_message(self, *_): + pass # suppress request logs + + +def start_server(directory: Path) -> tuple[http.server.HTTPServer, int]: + import socket + sock = socket.socket() + sock.bind(("127.0.0.1", 0)) + port = sock.getsockname()[1] + sock.close() + server = http.server.HTTPServer( + ("127.0.0.1", port), + lambda *a, **k: _SilentHTTPHandler(*a, directory=str(directory), **k), + ) + thread = threading.Thread(target=server.serve_forever, daemon=True) + thread.start() + return server, port + + +# ── Playwright capture (subprocess to python3.11 if needed) ────────────────── + +_CAPTURE_SCRIPT = """\ +import sys +from playwright.sync_api import sync_playwright +url, out, w, h = sys.argv[1], sys.argv[2], int(sys.argv[3]), int(sys.argv[4]) +with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={"width": w, "height": h}) + page.goto(url) + page.wait_for_load_state("domcontentloaded") + # Wait until Three.js signals rendering is complete + page.wait_for_function("window._renderDone === true", timeout=20000) + page.wait_for_timeout(200) + page.screenshot(path=out, + clip={"x": 0, "y": 0, "width": w, "height": h}, + timeout=30000) + browser.close() +""" + + +def capture(url: str, out_path: Path) -> None: + # Try current interpreter first + try: + from playwright.sync_api import sync_playwright # noqa: F401 + _capture_inline(url, out_path) + return + except ImportError: + pass + + # Fall back to a Python that has playwright + with tempfile.NamedTemporaryFile(suffix=".py", mode="w", delete=False) as f: + f.write(_CAPTURE_SCRIPT) + script = f.name + + try: + for py in ["python3.11", "python3.10", "python3.13"]: + try: + chk = subprocess.run([py, "-c", "import playwright"], + capture_output=True) + if chk.returncode != 0: + continue + res = subprocess.run( + [py, script, url, str(out_path), + str(RENDER_W), str(RENDER_H)], + capture_output=True, text=True, timeout=60, + ) + if res.returncode != 0: + raise RuntimeError(res.stderr[-600:]) + return + except FileNotFoundError: + continue + raise RuntimeError( + "playwright not found. Run: " + "python3.11 -m pip install playwright && " + "python3.11 -m playwright install chromium" + ) + finally: + Path(script).unlink(missing_ok=True) + + +def _capture_inline(url: str, out_path: Path) -> None: + from playwright.sync_api import sync_playwright + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={"width": RENDER_W, "height": RENDER_H}) + page.goto(url) + page.wait_for_load_state("domcontentloaded") + page.wait_for_function("window._renderDone === true", timeout=20000) + page.wait_for_timeout(200) + page.screenshot(path=str(out_path), + clip={"x": 0, "y": 0, + "width": RENDER_W, "height": RENDER_H}, + timeout=30000) + browser.close() + + +# ── Entry point ─────────────────────────────────────────────────────────────── + +def main() -> None: + parser = argparse.ArgumentParser( + description="Render a 3D product image of the Maharajong blank tile " + "using Three.js geometry (exact proportions)." + ) + parser.add_argument("--variant", default="variant-01", + help="Tile variant (default: variant-01)") + args = parser.parse_args() + + # Ensure Three.js is available locally + ensure_threejs() + + # Write the scene HTML into the design dir (served by local HTTP server) + html_path = DESIGN_DIR / "_tile_3d_scene.html" + html_path.write_text(build_html(args.variant), encoding="utf-8") + + out_dir = DESIGN_DIR / args.variant / "manufacturer-docs" + out_dir.mkdir(parents=True, exist_ok=True) + out_path = out_dir / "tile-blank-3d-render.png" + + # Start local HTTP server rooted at design/ so /lib/three.min.js resolves + server, port = start_server(DESIGN_DIR) + url = f"http://127.0.0.1:{port}/_tile_3d_scene.html" + + try: + print(f"Rendering {args.variant} via Three.js + Chromium ...", + end=" ", flush=True) + capture(url, out_path) + print(f"OK ({out_path.stat().st_size // 1024} KB) → {out_path}") + finally: + server.shutdown() + html_path.unlink(missing_ok=True) + + +if __name__ == "__main__": + main() diff --git a/design/generate_tile_blender_render.py b/design/generate_tile_blender_render.py new file mode 100644 index 0000000..4697ac0 --- /dev/null +++ b/design/generate_tile_blender_render.py @@ -0,0 +1,349 @@ +#!/usr/bin/env python3 +""" +Generate a photorealistic 3D render of the Maharajong blank tile via Blender. + +The tile is built as four stacked box meshes (one per material layer), so +proportions are mathematically exact. + +Renderer: Cycles (path-traced, Metal GPU on Apple Silicon) with: + - HDRI studio lighting (studio_small_08 from Poly Haven) + - Edge bevels (0.35mm chamfer, catches specular highlights) + - Surface imperfections (noise-driven roughness + bump on acrylic faces) + - Shadow-catching floor plane + - Subtle camera depth of field + +Outputs: + design//manufacturer-docs/tile-blank-3d-render.png + +Usage: + python3 design/generate_tile_blender_render.py --variant variant-01 + python3 design/generate_tile_blender_render.py --variant variant-02 + python3 design/generate_tile_blender_render.py --variant variant-01 --eevee +""" + +import sys +from pathlib import Path + +BLENDER = "/Applications/Blender.app/Contents/MacOS/Blender" +DESIGN_DIR = Path(__file__).parent +HDRI_PATH = DESIGN_DIR / "lib" / "studio_small_08_1k.hdr" +HDRI_URL = "https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/1k/studio_small_08_1k.hdr" + +# ── Tile constants (mm = Blender units) ──────────────────────────────────────────── +W, H, D = 32, 23, 13 # width (X), face-height (Y), depth (Z) +L1, L2, L3, L4 = 3, 1, 6, 3 # layer thicknesses (Z, top → bottom) +RENDER_W, RENDER_H = 2560, 1600 + + +# ============================================================================= +# WRAPPER — called when the script is run directly (bpy not available) +# ============================================================================= + +def run_as_wrapper() -> None: + import argparse, subprocess + + parser = argparse.ArgumentParser( + description="Render the Maharajong tile in 3D via Blender." + ) + parser.add_argument("--variant", default="variant-01") + parser.add_argument("--eevee", action="store_true", + help="Use EEVEE Next instead of Cycles (faster, less photorealistic)") + args = parser.parse_args() + + out_dir = DESIGN_DIR / args.variant / "manufacturer-docs" + out_dir.mkdir(parents=True, exist_ok=True) + out_path = out_dir / "tile-blank-3d-render.png" + + blender_args = [ + BLENDER, "--background", + "--python", str(Path(__file__).resolve()), + "--", + args.variant, + str(out_path), + "eevee" if args.eevee else "cycles", + ] + + engine_name = "EEVEE Next" if args.eevee else "Cycles" + print(f"Rendering {args.variant} via Blender ({engine_name}) ...", + end=" ", flush=True) + + result = subprocess.run(blender_args, capture_output=True, text=True, + timeout=300) + + if result.returncode != 0: + print("FAILED") + # Show only the relevant Blender error lines + for line in result.stderr.splitlines(): + if any(k in line for k in ("Error", "Traceback", "error", "Python")): + print(" ", line) + sys.exit(1) + + kb = out_path.stat().st_size // 1024 + print(f"OK ({kb} KB) → {out_path}") + + +# ============================================================================= +# BLENDER SCENE — called by Blender's Python interpreter (bpy available) +# ============================================================================= + +def run_as_blender_scene() -> None: + import bpy + from mathutils import Vector + + # ── Parse Blender args (after "--") ────────────────────────────────────────── + sep = sys.argv.index("--") if "--" in sys.argv else len(sys.argv) + argv = sys.argv[sep + 1:] + variant = argv[0] if len(argv) > 0 else "variant-01" + output = argv[1] if len(argv) > 1 else "/tmp/tile_render.png" + engine = argv[2] if len(argv) > 2 else "cycles" + is_v2 = (variant == "variant-02") + print(f"[blender] variant={variant} engine={engine} output={output}") + + # ── Fresh scene ────────────────────────────────────────────────── + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + scene.name = "TileRender" + + # ── sRGB hex → linear float triple ───────────────────────────────────── + def srgb(h): + def lin(v): + c = v / 255.0 + return ((c + 0.055) / 1.055) ** 2.4 if c > 0.04045 else c / 12.92 + return (lin(int(h[0:2],16)), lin(int(h[2:4],16)), lin(int(h[4:6],16))) + + # ── Material builder with noise-driven surface imperfections ───────────── + def make_mat(name, base_rgb, roughness=0.1, metallic=0.0, + transmission=0.0, ior=1.45, add_noise=False, add_bump=False): + mat = bpy.data.materials.new(name) + mat.use_nodes = True + nt = mat.node_tree + nodes, links = nt.nodes, nt.links + nodes.clear() + + out = nodes.new("ShaderNodeOutputMaterial") + bsdf = nodes.new("ShaderNodeBsdfPrincipled") + links.new(bsdf.outputs["BSDF"], out.inputs["Surface"]) + + bsdf.inputs["Base Color"].default_value = (*base_rgb, 1.0) + bsdf.inputs["Metallic"].default_value = metallic + bsdf.inputs["IOR"].default_value = ior + + for key in ("Transmission Weight", "Transmission"): + if key in bsdf.inputs: + bsdf.inputs[key].default_value = transmission + break + if transmission > 0: + mat.blend_method = "HASHED" + + # Shared noise source for roughness + bump + if add_noise or add_bump: + coord = nodes.new("ShaderNodeTexCoord") + mapping = nodes.new("ShaderNodeMapping") + noise = nodes.new("ShaderNodeTexNoise") + mapping.inputs["Scale"].default_value = (60.0, 60.0, 60.0) + noise.inputs["Scale"].default_value = 1.0 + noise.inputs["Detail"].default_value = 8.0 + noise.inputs["Roughness"].default_value = 0.55 + noise.inputs["Distortion"].default_value = 0.12 + links.new(coord.outputs["Object"], mapping.inputs["Vector"]) + links.new(mapping.outputs["Vector"], noise.inputs["Vector"]) + + if add_noise: + # Map noise 0–1 to a narrow roughness band (subtle variation) + mr = nodes.new("ShaderNodeMapRange") + mr.inputs["From Min"].default_value = 0.3 + mr.inputs["From Max"].default_value = 0.7 + mr.inputs["To Min"].default_value = max(0.0, roughness - 0.025) + mr.inputs["To Max"].default_value = roughness + 0.035 + links.new(noise.outputs["Fac"], mr.inputs["Value"]) + links.new(mr.outputs["Result"], bsdf.inputs["Roughness"]) + else: + bsdf.inputs["Roughness"].default_value = roughness + + if add_bump: + # Very subtle surface micro-bump (polished acrylic micro-texture) + bump = nodes.new("ShaderNodeBump") + bump.inputs["Strength"].default_value = 0.04 + bump.inputs["Distance"].default_value = 0.08 + links.new(noise.outputs["Fac"], bump.inputs["Height"]) + links.new(bump.outputs["Normal"], bsdf.inputs["Normal"]) + + return mat + + # ── Materials ───────────────────────────────────────────────────── + m_ivory = make_mat("Ivory_Face", srgb("F5EDD8"), + roughness=0.04, add_noise=True, add_bump=True) + m_gold = make_mat("Gold", srgb("D4AF37"), + roughness=0.09, metallic=0.94, add_noise=True) + m_navy = make_mat("Navy", srgb("1C2E5E"), + roughness=0.07, add_noise=True) + if is_v2: + m_back = make_mat("Clear_Back", srgb("1E3060"), + roughness=0.02, transmission=0.72, ior=1.49) + else: + m_back = make_mat("Ivory_Back", srgb("E8DFC8"), + roughness=0.05, add_noise=True, add_bump=True) + + # ── Tile geometry: 4 stacked layers along Z ──────────────────────────── + # Z-up. Face on top (+Z). Layers: L1 ivory / L2 gold / L3 navy / L4 back. + layer_defs = [ + (L1, m_ivory, "L1_Ivory_Face"), + (L2, m_gold, "L2_Gold"), + (L3, m_navy, "L3_Navy"), + (L4, m_back, "L4_Back"), + ] + tile_objs = [] + cur_z = D / 2.0 + for thickness, mat, name in layer_defs: + bpy.ops.mesh.primitive_cube_add(size=1.0, + location=(0.0, 0.0, cur_z - thickness / 2.0)) + obj = bpy.context.active_object + obj.name = name + obj.scale = (float(W), float(H), float(thickness)) + bpy.ops.object.transform_apply(scale=True) + obj.data.materials.clear() + obj.data.materials.append(mat) + + # ── Edge bevel: 0.35mm chamfer, angle-limited to outer edges only + bev = obj.modifiers.new("Bevel", type="BEVEL") + bev.width = 0.35 # mm — tight chamfer, just enough to catch light + bev.segments = 3 # smooth curve + bev.profile = 0.7 + bev.limit_method = "ANGLE" + bev.angle_limit = 1.22 # ~70° — only bevel hard exterior corners + bpy.context.view_layer.objects.active = obj + bpy.ops.object.modifier_apply(modifier=bev.name) + + tile_objs.append(obj) + cur_z -= thickness + + # ── Shadow-catching floor plane ────────────────────────────────────── + bpy.ops.mesh.primitive_plane_add(size=600, location=(0, 0, -D / 2 - 0.05)) + floor = bpy.context.active_object + floor.name = "Floor" + floor_mat = bpy.data.materials.new("Floor") + floor_mat.use_nodes = True + fn, fl = floor_mat.node_tree.nodes, floor_mat.node_tree.links + fn.clear() + fo = fn.new("ShaderNodeOutputMaterial") + fd = fn.new("ShaderNodeBsdfDiffuse") + fd.inputs["Color"].default_value = (0.980, 0.980, 0.975, 1.0) + fd.inputs["Roughness"].default_value = 1.0 + fl.new(fd.outputs["BSDF"], fo.inputs["Surface"]) + floor.data.materials.clear() + floor.data.materials.append(floor_mat) + # Cycles shadow catcher: tile shadow on near-white floor + floor.is_shadow_catcher = True + + # ── Camera ────────────────────────────────────────────────────────── + cam_data = bpy.data.cameras.new("Camera") + cam_data.lens = 65 + cam_data.sensor_width = 36 + cam_data.dof.use_dof = True + cam_data.dof.aperture_fstop = 11.0 # f/11 — very slight DOF, keeps tile sharp + cam_obj = bpy.data.objects.new("Camera", cam_data) + scene.collection.objects.link(cam_obj) + scene.camera = cam_obj + + cam_obj.location = Vector((18.0, -72.0, 44.0)) + target = Vector((0.0, 0.0, 1.5)) + direction = target - cam_obj.location + cam_obj.rotation_euler = direction.to_track_quat("-Z", "Y").to_euler() + + # Focus distance = distance from camera to tile centre + cam_data.dof.focus_distance = (cam_obj.location - Vector((0, 0, 0))).length + + # ── HDRI world lighting ──────────────────────────────────────────── + hdri_path = str(HDRI_PATH) + world = bpy.data.worlds.new("World") + scene.world = world + world.use_nodes = True + wn, wl = world.node_tree.nodes, world.node_tree.links + wn.clear() + + w_out = wn.new("ShaderNodeOutputWorld") + w_bg = wn.new("ShaderNodeBackground") + w_env = wn.new("ShaderNodeTexEnvironment") + w_map = wn.new("ShaderNodeMapping") + w_tc = wn.new("ShaderNodeTexCoord") + + try: + w_env.image = bpy.data.images.load(hdri_path) + w_bg.inputs["Strength"].default_value = 1.2 + # Rotate HDRI so key light comes from upper-left (matching scene intent) + w_map.inputs["Rotation"].default_value[2] = 0.9 # ~52° + wl.new(w_tc.outputs["Generated"], w_map.inputs["Vector"]) + wl.new(w_map.outputs["Vector"], w_env.inputs["Vector"]) + wl.new(w_env.outputs["Color"], w_bg.inputs["Color"]) + print("[blender] HDRI loaded") + except Exception as e: + # Fallback: plain near-white background + print(f"[blender] HDRI load failed ({e}), using flat background") + w_bg.inputs[0].default_value = (0.98, 0.98, 0.975, 1.0) + w_bg.inputs["Strength"].default_value = 1.0 + + wl.new(w_bg.outputs["Background"], w_out.inputs["Surface"]) + + # ── Supplemental area lights (boost key + rim over HDRI) ───────────── + def add_area(name, loc, energy, color=(1,1,1), size=50): + ld = bpy.data.lights.new(name, type="AREA") + ld.energy, ld.color, ld.size = energy, color, size + lo = bpy.data.objects.new(name, ld) + lo.location = loc + scene.collection.objects.link(lo) + d = Vector((0,0,0)) - Vector(loc) + lo.rotation_euler = d.to_track_quat("-Z", "Y").to_euler() + + add_area("Key", (-50, -65, 85), energy=8000, + color=(1.00, 0.97, 0.91), size=55) + add_area("Rim", ( 10, 85, -18), energy=4000, + color=(1.00, 0.95, 0.88), size=40) + + # ── Render settings ──────────────────────────────────────────────── + scene.render.resolution_x = RENDER_W + scene.render.resolution_y = RENDER_H + scene.render.resolution_percentage = 100 + scene.render.filepath = output + scene.render.image_settings.file_format = "PNG" + scene.render.image_settings.color_mode = "RGB" + scene.render.image_settings.color_depth = "8" + scene.render.film_transparent = False + + if engine == "cycles": + scene.render.engine = "CYCLES" + scene.cycles.samples = 256 + scene.cycles.use_denoising = True + scene.cycles.denoiser = "OPENIMAGEDENOISE" + # Enable Metal GPU on Apple Silicon + try: + cprefs = bpy.context.preferences.addons["cycles"].preferences + cprefs.compute_device_type = "METAL" + cprefs.get_devices() + for dev in cprefs.devices: + dev.use = True + scene.cycles.device = "GPU" + print("[blender] Cycles Metal GPU enabled") + except Exception as e: + print(f"[blender] GPU setup failed ({e}), falling back to CPU") + else: + scene.render.engine = "BLENDER_EEVEE_NEXT" + scene.eevee.use_gtao = True + scene.eevee.gtao_distance = 0.3 + try: + scene.eevee.use_shadows = True + except Exception: + pass + + # ── Render ───────────────────────────────────────────────────────────── + bpy.ops.render.render(write_still=True) + + +# ============================================================================= +# Dispatch +# ============================================================================= + +try: + import bpy # succeeds only when running inside Blender + run_as_blender_scene() +except ImportError: + run_as_wrapper() diff --git a/design/generate_tile_spec_sheet.py b/design/generate_tile_spec_sheet.py new file mode 100644 index 0000000..12e8e48 --- /dev/null +++ b/design/generate_tile_spec_sheet.py @@ -0,0 +1,838 @@ +#!/usr/bin/env python3 +""" +Generate manufacturer spec sheet assets for the Maharajong blank tile. + +Outputs (in design/manufacturer-docs/): + tile-blank-technical-drawing.svg — precise SVG engineering drawing for manufacturing + tile-blank-spec-sheet-rendered.png — Grok-rendered product image for human review + +Usage: + python3 design/generate_tile_spec_sheet.py # generate both + python3 design/generate_tile_spec_sheet.py --svg-only + python3 design/generate_tile_spec_sheet.py --img-only +""" + +import argparse +import base64 +import json +import os +import sys +import urllib.request +import urllib.error +from pathlib import Path + +# Set VARIANT to "variant-01" or "variant-02" (or pass --variant on the CLI) +DEFAULT_VARIANT = "variant-01" +OUT_DIR = Path(__file__).parent / DEFAULT_VARIANT / "manufacturer-docs" + +# --------------------------------------------------------------------------- +# Tile specification constants +# --------------------------------------------------------------------------- +TILE_W_MM = 32 # width (face, left-right) +TILE_H_MM = 23 # height (face, top-bottom) +TILE_D_MM = 13 # depth (thickness) +LAYER_1_MM = 3 # ivory face +LAYER_2_MM = 1 # gold hairline +LAYER_3_MM = 6 # lapis-navy core +LAYER_4_MM = 3 # ivory back +TOL_MM = 0.2 # dimensional tolerance ± +WEIGHT_G_MIN = 16 +WEIGHT_G_MAX = 19 + +# Colors +C_IVORY = "#F5EDD8" +C_IVORY_DRK = "#E8DFC8" # for back face (slight shadow) +C_GOLD = "#D4AF37" +C_GOLD_LIGHT = "#F0D060" +C_NAVY = "#1C2E5E" +C_NAVY_MID = "#263D7A" +C_BLACK = "#1A1A1A" +C_GRAY = "#555555" +C_LIGHTGRAY = "#AAAAAA" +C_DIMLINE = "#222222" +C_BGPAPER = "#FAFAF8" +C_BORDER = "#222222" +C_TITLE_BG = "#F0EFE8" +# Variant-02: clear acrylic back — represented as navy-tinted with hatch +C_CLEAR_FILL = "#D6E6F0" # light blue-white: navy core seen through 3mm clear PMMA +C_CLEAR_HATCH = "#8AAEC8" # hatch lines indicating transparent material + + +# --------------------------------------------------------------------------- +# SVG helpers +# --------------------------------------------------------------------------- + +def _rect(x, y, w, h, fill, stroke=None, sw=1, rx=0, extra=""): + s = f' stroke="{stroke}" stroke-width="{sw}"' if stroke else ' stroke="none"' + r = f' rx="{rx}"' if rx else "" + return f'' + + +def _line(x1, y1, x2, y2, stroke=C_DIMLINE, sw=1.2, dash=""): + d = f' stroke-dasharray="{dash}"' if dash else "" + return f'' + + +def _text(x, y, content, size=12, fill=C_BLACK, anchor="middle", + weight="normal", family="'Helvetica Neue', Arial, sans-serif", extra=""): + return (f'' + f'{content}') + + +def _dim_line_h(x1, x2, y, label, ext_len=20, text_size=11): + """Horizontal dimension line between x1 and x2 at height y.""" + mid = (x1 + x2) / 2 + lines = [ + # extension lines + _line(x1, y - ext_len, x1, y + ext_len, sw=0.8), + _line(x2, y - ext_len, x2, y + ext_len, sw=0.8), + # dimension line with arrows + (f''), + _text(mid, y - 6, label, size=text_size), + ] + return "\n".join(lines) + + +def _dim_line_v(y1, y2, x, label, ext_len=20, text_size=11): + """Vertical dimension line between y1 and y2 at position x.""" + mid = (y1 + y2) / 2 + lines = [ + _line(x - ext_len, y1, x + ext_len, y1, sw=0.8), + _line(x - ext_len, y2, x + ext_len, y2, sw=0.8), + (f''), + (f'{label}'), + ] + return "\n".join(lines) + + +def _leader(x1, y1, x2, y2, label, size=11, anchor="start"): + return (f'' + f'\n' + _text(x2 + (6 if anchor == "start" else -6), y2 + 4, + label, size=size, anchor=anchor, fill=C_GRAY)) + + +# --------------------------------------------------------------------------- +# SVG technical drawing +# --------------------------------------------------------------------------- + +def generate_svg(variant: str = "variant-01") -> str: + SC = 8 # px per mm — reduced for Letter landscape + SC2 = 16 # px per mm (layer detail at 2:1) + W = TILE_W_MM * SC # 320 + H = TILE_H_MM * SC # 230 + D = TILE_D_MM * SC # 130 + + # Layer heights at main scale + l1 = LAYER_1_MM * SC # 30 – ivory face + l2 = LAYER_2_MM * SC # 10 – gold + l3 = LAYER_3_MM * SC # 60 – navy + l4 = LAYER_4_MM * SC # 30 – ivory back + + # Layer heights at detail scale + d1 = LAYER_1_MM * SC2 + d2 = LAYER_2_MM * SC2 + d3 = LAYER_3_MM * SC2 + d4 = LAYER_4_MM * SC2 + + # Variant-specific Layer 4 rendering + is_v2 = (variant == "variant-02") + l4_fill = C_CLEAR_FILL if is_v2 else C_IVORY_DRK + l4_label = "L4: CRYSTAL CLEAR ACRYLIC" if is_v2 else "L4: IVORY ACRYLIC" + l4_spec = (f"Crystal-clear PMMA, {LAYER_4_MM} mm — water-white, zero haze" + if is_v2 else + f"Ivory/cream, {LAYER_4_MM} mm — match Layer 1") + l4_back_note = ("Back: apparent navy (L3 visible through clear L4)" + if is_v2 else + "Back: ivory (matches face)") + variant_label = "Variant 02: Ivory / Gold / Navy / Clear" if is_v2 else "Variant 01: Ivory / Gold / Navy / Ivory" + dwg_number = "MJ-TILE-BLK-002" if is_v2 else "MJ-TILE-BLK-001" + back_label = ("\u2190 BACK (NAVY THROUGH CLEAR) \u2192" + if is_v2 else "\u2190 BACK \u2192") + + # Canvas sized for Letter landscape (11\u00d78.5 in) at 100 units/inch + CANVAS_W = 1100 + CANVAS_H = 850 + + # Left panel view origins (x: 20–590, y: 95–660) + VX = 70 # left edge of face/edge views + VY = 115 # top of face view + + # Face view (top view, 32×23mm) + FX, FY = VX, VY + + # Long-edge cross-section (32×13mm): below face view + EX = VX + EY = FY + H + 85 + + # Short-edge cross-section (23×13mm): right of long-edge + SEX = EX + W + 60 + SEY = EY + + # Vertical panel divider x position (right of View C) + DIVIDER_X = 614 + + # Right panel: layer detail diagram + DX = 640 # left edge of detail diagram + DY = VY # aligned with VY + DETAIL_SECTION_W = 155 + DETAIL_H = TILE_D_MM * SC2 # 13×16 = 208px + + # Right panel: spec table (starts below detail diagram) + SPEC_X = DX - 4 # left edge of spec table + SPEC_Y = DY + DETAIL_H + 36 # start below detail + SPEC_W = CANVAS_W - SPEC_X - 22 # to near-right margin + SPEC_ROW_H = 19 # compact row height + SPEC_COL2 = SPEC_X + 195 # value column x + + # Footer: notes + title block + FOOTER_Y = 700 + FOOTER_H = CANVAS_H - FOOTER_Y - 18 + TB_X = 510 + TB_Y = FOOTER_Y + TB_W = CANVAS_W - TB_X - 20 + TB_H = FOOTER_H + + svg_parts = [ + f'', + + # ── Arrowhead markers ──────────────────────────────────────────────── + f''' + + + + + + + + + + + + +''', + + # ── Background ─────────────────────────────────────────────────────── + _rect(0, 0, CANVAS_W, CANVAS_H, C_BGPAPER), + # Outer border + _rect(10, 10, CANVAS_W - 20, CANVAS_H - 20, "none", C_BORDER, sw=2), + # Inner border + _rect(20, 20, CANVAS_W - 40, CANVAS_H - 40, "none", C_BORDER, sw=0.5), + + # ── Sheet title ────────────────────────────────────────────────────── + _text(CANVAS_W // 2, 55, + "MAHARAJONG — BLANK TILE SPECIFICATION", + size=18, weight="bold", fill=C_BLACK), + _text(CANVAS_W // 2, 72, + variant_label, + size=12, fill=C_NAVY, weight="bold"), + _text(CANVAS_W // 2, 88, + f"Drawing No: {dwg_number} | Scale 1:1 (main views) | Units: mm", + size=11, fill=C_GRAY), + + # ── Section dividers ───────────────────────────────────────────────── + _line(DIVIDER_X, 100, DIVIDER_X, FOOTER_Y - 4, C_LIGHTGRAY, sw=0.8, dash="6,3"), + _line(20, FOOTER_Y - 6, CANVAS_W - 20, FOOTER_Y - 6, C_LIGHTGRAY, sw=0.8), + + # ════════════════════════════════════════════════════════════════════ + # VIEW 1: FACE VIEW (Top / Front face — 32mm × 23mm) + # ════════════════════════════════════════════════════════════════════ + _text(FX + W // 2, FY - 14, + "VIEW A — FACE (Top)", size=11, weight="bold", fill=C_GRAY), + + # Face fill: ivory (plain black engineering border — no artwork border on blank tile spec) + _rect(FX, FY, W, H, C_IVORY, C_BLACK, sw=1.5), + # Centre cross (registration marks, light) + _line(FX + W // 2 - 12, FY + H // 2, FX + W // 2 + 12, FY + H // 2, + C_LIGHTGRAY, sw=0.5), + _line(FX + W // 2, FY + H // 2 - 12, FX + W // 2, FY + H // 2 + 12, + C_LIGHTGRAY, sw=0.5), + + # UV print area label + _text(FX + W // 2, FY + H // 2 + 5, + "UV PRINT AREA", size=9, fill=C_LIGHTGRAY, weight="bold"), + _text(FX + W // 2, FY + H // 2 + 18, + "DO NOT MARK", size=8, fill=C_LIGHTGRAY), + + # "FACE" label corner + _text(FX + 10, FY + 14, "FACE", size=8, fill=C_GOLD, anchor="start", + weight="bold"), + + # ── Dimension lines for face view ──────────────────────────────────── + # Width: 32mm (below face view) + _dim_line_h(FX, FX + W, FY + H + 28, f"32.0 ±{TOL_MM}"), + # Height: 23mm (left of face view) + _dim_line_v(FY, FY + H, FX - 34, f"23.0 ±{TOL_MM}"), + + # ════════════════════════════════════════════════════════════════════ + # VIEW 2: LONG EDGE CROSS-SECTION (32mm × 13mm, showing all 4 layers) + # ════════════════════════════════════════════════════════════════════ + _text(EX + W // 2, EY - 14, + "VIEW B — LONG EDGE CROSS-SECTION (32mm × 13mm)", + size=11, weight="bold", fill=C_GRAY), + + # Layer 1: Ivory face (top, l1 px) + _rect(EX, EY, W, l1, C_IVORY, C_BLACK, sw=0.6), + # Layer 2: Gold hairline + _rect(EX, EY + l1, W, l2, C_GOLD, C_BLACK, sw=0.6), + # Layer 3: Navy core + _rect(EX, EY + l1 + l2, W, l3, C_NAVY, C_BLACK, sw=0.6), + # Layer 4: back (ivory V01 / clear V02) + _rect(EX, EY + l1 + l2 + l3, W, l4, l4_fill, C_BLACK, sw=0.6), + # Clear hatch overlay for V02 + *([ + _rect(EX, EY + l1 + l2 + l3, W, l4, + "url(#clear-hatch)", "none"), + ] if is_v2 else []), + + # Overall border + _rect(EX, EY, W, D, "none", C_BLACK, sw=1.5), + + # Face / back labels inside + _text(EX + W // 2, EY + l1 - 6, + "← FACE (UV PRINT SURFACE) →", size=8, fill=C_IVORY_DRK), + _text(EX + W // 2, EY + l1 + l2 + l3 // 2 + 4, + "CORE", size=9, fill="#AABDE0"), + _text(EX + W // 2, EY + D - 8, + back_label, size=8, fill=C_GRAY), + + # Width dimension (same as face, aligned below) + _dim_line_h(EX, EX + W, EY + D + 28, f"32.0 ±{TOL_MM}"), + # Depth/thickness dimension (left of this view) + _dim_line_v(EY, EY + D, EX - 34, f"13.0 ±{TOL_MM}"), + + # ════════════════════════════════════════════════════════════════════ + # VIEW 3: SHORT EDGE CROSS-SECTION (23mm × 13mm) + # ════════════════════════════════════════════════════════════════════ + _text(SEX + (TILE_H_MM * SC) // 2, SEY - 14, + "VIEW C — SHORT EDGE (23mm × 13mm)", + size=11, weight="bold", fill=C_GRAY), + + _rect(SEX, SEY, TILE_H_MM * SC, l1, C_IVORY, C_BLACK, sw=0.6), + _rect(SEX, SEY + l1, TILE_H_MM * SC, l2, C_GOLD, C_BLACK, sw=0.6), + _rect(SEX, SEY + l1 + l2, TILE_H_MM * SC, l3, C_NAVY, C_BLACK, sw=0.6), + _rect(SEX, SEY + l1 + l2 + l3, TILE_H_MM * SC, l4, l4_fill, C_BLACK, sw=0.6), + *([ + _rect(SEX, SEY + l1 + l2 + l3, TILE_H_MM * SC, l4, + "url(#clear-hatch)", "none"), + ] if is_v2 else []), + _rect(SEX, SEY, TILE_H_MM * SC, D, "none", C_BLACK, sw=1.5), + + # Short edge dimension + _dim_line_h(SEX, SEX + TILE_H_MM * SC, SEY + D + 28, f"23.0 ±{TOL_MM}"), + + # ════════════════════════════════════════════════════════════════════ + # LAYER DETAIL (right panel, ~2:1 scale) + # ════════════════════════════════════════════════════════════════════ + _text(DX + DETAIL_SECTION_W // 2, DY - 14, + "DETAIL D — LAYER CROSS-SECTION (Scale 2:1)", + size=11, weight="bold", fill=C_GRAY), + + # Draw a partial-width slice showing all 4 layers at 2× scale + _rect(DX, DY, DETAIL_SECTION_W, d1, C_IVORY, C_BLACK, sw=0.8), + _rect(DX, DY + d1, DETAIL_SECTION_W, d2, C_GOLD, C_BLACK, sw=0.8), + _rect(DX, DY + d1 + d2, DETAIL_SECTION_W, d3, C_NAVY, C_BLACK, sw=0.8), + _rect(DX, DY + d1 + d2 + d3, DETAIL_SECTION_W, d4, l4_fill, C_BLACK, sw=0.8), + *([ + _rect(DX, DY + d1 + d2 + d3, DETAIL_SECTION_W, d4, + "url(#clear-hatch)", "none"), + ] if is_v2 else []), + _rect(DX, DY, DETAIL_SECTION_W, DETAIL_H, "none", C_BLACK, sw=2), + + # Hatching on layers (light diagonal lines for engineering convention) + # Ivory face hatching (light) + '\n'.join([ + _line(DX + i * 8, DY, DX + min(i * 8 + d1, DETAIL_SECTION_W), DY + d1, + "#C8BFA8", 0.5) + for i in range(0, DETAIL_SECTION_W // 8 + 2) + ]), + # Navy core hatching (light navy cross-hatch) + '\n'.join([ + _line(DX, DY + d1 + d2 + i * 8, + DX + DETAIL_SECTION_W, DY + d1 + d2 + i * 8, + "#2A3D6E", 0.4) + for i in range(0, int(d3 / 8) + 1) + ]), + + # Layer dimension callouts (right side of detail) + _dim_line_v(DY, DY + d1, + DX + DETAIL_SECTION_W + 34, f"{LAYER_1_MM}mm", ext_len=12, text_size=10), + _dim_line_v(DY + d1, DY + d1 + d2, + DX + DETAIL_SECTION_W + 34, f"{LAYER_2_MM}mm", ext_len=12, text_size=10), + _dim_line_v(DY + d1 + d2, DY + d1 + d2 + d3, + DX + DETAIL_SECTION_W + 34, f"{LAYER_3_MM}mm", ext_len=12, text_size=10), + _dim_line_v(DY + d1 + d2 + d3, DY + DETAIL_H, + DX + DETAIL_SECTION_W + 34, f"{LAYER_4_MM}mm", ext_len=12, text_size=10), + + # Material labels — right of dim callouts (no left-side leaders to avoid view overlap) + *[ + _text(DX + DETAIL_SECTION_W + 56, y + 4, label, size=9, fill=C_GRAY, anchor="start") + for y, label in [ + (DY + d1 // 2, "L1: IVORY ACRYLIC"), + (DY + d1 + d2 // 2, "L2: GOLD HAIRLINE"), + (DY + d1 + d2 + d3 // 2, "L3: LAPIS NAVY CORE"), + (DY + d1 + d2 + d3 + d4 // 2, l4_label), + ] + ], + + # ════════════════════════════════════════════════════════════════════ + # SPECIFICATIONS TABLE (right panel, below layer detail) + # ════════════════════════════════════════════════════════════════════ + _text(SPEC_X + SPEC_W // 2, SPEC_Y - 8, + "MATERIAL & PROCESS SPECIFICATIONS", + size=11, weight="bold", fill=C_BLACK, anchor="middle"), + + # Spec rows + *[ + ( + _rect(SPEC_X, SPEC_Y + 2 + i * SPEC_ROW_H, SPEC_W, SPEC_ROW_H - 1, + "#F0EFE8" if i % 2 == 0 else C_BGPAPER, C_LIGHTGRAY, sw=0.4) + + "\n" + + _text(SPEC_X + 6, SPEC_Y + 13 + i * SPEC_ROW_H, + label, size=9, fill=C_GRAY, anchor="start") + + "\n" + + _text(SPEC_COL2, SPEC_Y + 13 + i * SPEC_ROW_H, + value, size=9, fill=C_BLACK, anchor="start", weight="bold") + ) + for i, (label, value) in enumerate([ + ("Material", "Four-layer cast acrylic (PMMA)"), + ("Overall dimensions", f"{TILE_W_MM} × {TILE_H_MM} × {TILE_D_MM} mm"), + ("Dimensional tolerance", f"±{TOL_MM} mm all faces"), + ("Target weight", f"{WEIGHT_G_MIN}–{WEIGHT_G_MAX} g per tile"), + ("Quantity per set", "152 tiles"), + ("Layer 1 (face)", f"Ivory/cream, {LAYER_1_MM} mm — Pantone ~9183 C"), + ("Layer 2", f"Metallic gold, {LAYER_2_MM} mm — Pantone ~874 C"), + ("Layer 3 (core)", f"Lapis navy, {LAYER_3_MM} mm — Pantone ~289 C"), + ("Layer 4 (back)", l4_spec), + ("Back face appearance", l4_back_note), + ("Face surface finish", "Mirror polished, Ra ≤ 0.4 μm (all 6 faces)"), + ("UV print surface", "Face (L1): must accept UV inkjet, zero texture"), + ("Laser engrave", "Face (L1): compatible with UV cold laser"), + ("Edge visibility", "All 4 layers visible on both 23mm edges"), + ]) + ], + + # ════════════════════════════════════════════════════════════════════ + # TITLE BLOCK + # ════════════════════════════════════════════════════════════════════ + # Variant badge (top-right corner of title block) + _rect(TB_X + TB_W - 116, TB_Y - 26, 116, 20, C_NAVY, "none"), + _text(TB_X + TB_W - 58, TB_Y - 11, + dwg_number, size=9, fill="#FFFFFF", weight="bold"), + + _rect(TB_X, TB_Y, TB_W, TB_H, C_TITLE_BG, C_BLACK, sw=1.5), + + # Title block inner dividers + _line(TB_X, TB_Y + 24, TB_X + TB_W, TB_Y + 24, C_BLACK, sw=0.8), + _line(TB_X, TB_Y + 44, TB_X + TB_W, TB_Y + 44, C_BLACK, sw=0.5), + _line(TB_X, TB_Y + 64, TB_X + TB_W, TB_Y + 64, C_BLACK, sw=0.5), + _line(TB_X, TB_Y + 84, TB_X + TB_W, TB_Y + 84, C_BLACK, sw=0.5), + _line(TB_X, TB_Y + 104, TB_X + TB_W, TB_Y + 104, C_BLACK, sw=0.5), + _line(TB_X + 190, TB_Y + 24, TB_X + 190, TB_Y + TB_H, C_BLACK, sw=0.5), + _line(TB_X + 360, TB_Y + 24, TB_X + 360, TB_Y + TB_H, C_BLACK, sw=0.5), + + _text(TB_X + TB_W // 2, TB_Y + 17, + "MAHARAJONG BLANK TILE — 4-LAYER ACRYLIC", + size=12, weight="bold", fill=C_BLACK), + + # Row labels + *[ + _text(TB_X + ox + 5, TB_Y + oy + 8, label, + size=7, fill=C_GRAY, anchor="start") + for (ox, oy, label) in [ + (0, 24, "COMPONENT"), (190, 24, "DWG No."), (360, 24, "REV"), + (0, 44, "PROJECT"), (190, 44, "SCALE"), (360, 44, "UNITS"), + (0, 64, "PREPARED BY"), (190, 64, "DATE"), (360, 64, "SHEET"), + (0, 84, "SUPPLIER: CONFIRM WEIGHT & PANTONE BEFORE PRODUCTION"), + ] + ], + + # Row values + *[ + _text(TB_X + ox + 5, TB_Y + oy + 20, value, + size=9, fill=C_BLACK, anchor="start", weight="bold") + for (ox, oy, value) in [ + (0, 24, "Blank Tile (4-Layer Acrylic)"), (190, 24, dwg_number), (360, 24, "A"), + (0, 44, "Maharajong"), (190, 44, "1:1 (main)"), (360, 44, "mm"), + (0, 64, "ccwells@gmail.com"), (190, 64, "2026-07-12"), (360, 64, "1/1"), + ] + ], + + # ── Notes box (bottom-left, narrower than right-panel) ────────────────── + _rect(20, FOOTER_Y, TB_X - 26, FOOTER_H, C_TITLE_BG, C_BLACK, sw=1), + _text(28, FOOTER_Y + 14, "GENERAL NOTES:", size=9, weight="bold", + fill=C_BLACK, anchor="start"), + *[ + _text(28, FOOTER_Y + 27 + i * 16, note, size=8, fill=C_GRAY, anchor="start") + for i, note in enumerate( + [ + "1. All dims in mm. Tolerances \u00b10.2mm unless noted.", + "2. All faces mirror-polished (Ra \u2264 0.4\u03bcm). Zero orange-peel.", + "3. Layer 1 face must accept UV inkjet without priming.", + "4. Gold hairline (L2) visible on both 23mm short edges.", + "5. L1\u2013L3 Pantone-matched; supplier submits chip for approval.", + "6. L4 CRYSTAL CLEAR — water-white, zero haze. No buffing on clear face.", + "7. QC: per-tile back-face clarity check — navy core uniform, no milky patches.", + "8. Weight 16\u201319g/tile. Advise if ballast fill needed.", + "9. 20-tile prototype required before production MOQ commitment.", + ] if is_v2 else [ + "1. All dims in mm. Tolerances \u00b10.2mm unless noted.", + "2. All faces mirror-polished (Ra \u2264 0.4\u03bcm). Zero orange-peel.", + "3. Layer 1 face must accept UV inkjet without priming.", + "4. Gold hairline (L2) visible on both 23mm short edges.", + "5. All layers Pantone-matched; supplier submits colour chip for approval.", + "6. Weight 16\u201319g/tile. Advise if ballast fill/drill needed.", + "7. 20-tile prototype required before production MOQ commitment.", + ] + ) + ], + + '', + ] + + return "\n".join(svg_parts) + + +# --------------------------------------------------------------------------- +# Grok rendered image +# --------------------------------------------------------------------------- + +# View-specific prompts — one Grok call per view for maximum accuracy. +# Multi-view composite rendered later in Python (not by Grok). + +def get_view_prompts(variant: str) -> dict: + """Return {view_name: prompt} for top, side, and back views.""" + is_v2 = (variant == "variant-02") + + base = ( + "Photorealistic studio product macro photography. " + "Single blank mahjong tile, polished cast acrylic, no artwork. " + "Pure white background, soft studio lighting, sharp focus throughout. " + "No text, no labels, no annotations. No border or frame around the image." + ) + + top = ( + f"{base} " + "CAMERA DIRECTLY OVERHEAD, looking straight down at the tile face (top view). " + "The tile lies flat. Face surface is a single uninterrupted warm ivory cream " + "(#F5EDD8), highly polished mirror-smooth acrylic. " + "Tile is 32mm wide × 23mm tall — a portrait-ish rectangle. " + "Soft specular highlight from overhead studio light. Very soft drop shadow at edges. " + "The tile fills most of the frame, centred on white." + ) + + if is_v2: + back = ( + f"{base} " + "CAMERA DIRECTLY OVERHEAD, looking straight down at the tile back face (bottom view). " + "The tile lies flat, back face up. " + "Back surface appears deep lapis navy blue (#1C2E5E) — " + "this is the navy acrylic core seen through a crystal-clear 3mm transparent acrylic top layer. " + "The colour is rich, deep, dark navy with a subtle glossy depth and slight translucency. " + "Tile is 32mm wide × 23mm tall. Soft specular highlight. Very soft drop shadow. " + "The tile fills most of the frame, centred on white." + ) + else: + back = ( + f"{base} " + "CAMERA DIRECTLY OVERHEAD, looking straight down at the tile back face (bottom view). " + "The tile lies flat, back face up. " + "Back surface is warm ivory cream (#E8DFC8), slightly darker than the face, " + "highly polished acrylic. " + "Tile is 32mm wide × 23mm tall. Soft specular highlight. Very soft drop shadow. " + "The tile fills most of the frame, centred on white." + ) + + if is_v2: + back_band = ( + "4th band at the VERY BOTTOM: crystal-clear transparent acrylic, " + "same height as the top ivory band. The navy is faintly visible through it " + "as a dark lapis tint. This clear band is at the bottom only." + ) + else: + back_band = ( + "4th band at the VERY BOTTOM: warm ivory cream, " + "same height as the top ivory band." + ) + + side = ( + f"{base} " + "CAMERA PERFECTLY LEVEL with the tile edge, flat orthographic straight-on view, " + "no perspective angle, no 3D foreshortening. " + "Looking directly at the 32mm long edge of the tile from the side. " + "The tile is 13mm tall in this view. " + "PROPORTION IS CRITICAL — the tile is predominantly navy blue when viewed from the side. " + "EXACTLY FOUR horizontal bands, strict order top to bottom: " + "1st band (TOP): warm ivory cream — a NARROW band, less than one quarter of total height. " + "2nd band: ONE single metallic gold hairline — extremely thin, " + "barely a line, much thinner than the ivory top. THIS IS THE ONLY GOLD. " + "3rd band: deep lapis navy blue — by far the TALLEST band, " + "nearly half the total height, clearly the dominant element. " + "The tile looks mostly navy from the side because this band is so wide. " + f"{back_band} " + "CRITICAL: the ivory top and ivory bottom are BOTH narrow — " + "together they take less space than the navy alone. " + "EXACTLY ONE gold stripe. NO gold between navy and the bottom band. " + "Photorealistic polished acrylic, studio lighting." + ) + + return {"top": top, "side": side, "back": back} + + +def _grok_image(api_key: str, prompt: str, aspect: str = "1:1") -> bytes: + payload = json.dumps({ + "model": "grok-imagine-image-quality", + "prompt": prompt, + "n": 1, + "response_format": "b64_json", + "aspect_ratio": aspect, + "resolution": "2k", + }).encode() + req = urllib.request.Request( + "https://api.x.ai/v1/images/generations", + data=payload, + headers={"Content-Type": "application/json", + "Authorization": f"Bearer {api_key}"}, + method="POST", + ) + with urllib.request.urlopen(req, timeout=120) as resp: + body = json.loads(resp.read()) + return base64.b64decode(body["data"][0]["b64_json"]) + + +def composite_views(view_bytes: dict) -> bytes: + """Stitch top / side / back renders into one landscape image using Pillow.""" + import subprocess, tempfile, importlib + + # Find a Python with Pillow + pil = None + for py in [sys.executable, "python3.10", "python3.11", "python3"]: + try: + r = subprocess.run([py, "-c", "from PIL import Image; print('ok')"], + capture_output=True, timeout=5) + if r.returncode == 0: + pil = py + break + except FileNotFoundError: + continue + if pil is None: + raise RuntimeError("Pillow not found. Run: python3.10 -m pip install Pillow") + + # Write view images to temp files, composite via subprocess + import os + tmp = tempfile.mkdtemp() + for name, data in view_bytes.items(): + Path(tmp, f"{name}.png").write_bytes(data) + + out = Path(tmp, "composite.png") + script = f""" +import io +from pathlib import Path +from PIL import Image, ImageDraw + +tmp = Path({repr(tmp)}) +out = Path({repr(str(out))}) + +PANEL_H = 1200 # px, height each panel is scaled to +GAP = 60 # px between panels +PAD = 80 # px outer padding +LABEL_H = 72 # px for label area below each panel +BG = (250, 250, 248) +FG = (90, 90, 90) + +views = [] +for name, label in [("top", "TOP"), ("side", "SIDE"), ("back", "BACK")]: + img = Image.open(tmp / f"{{name}}.png").convert("RGB") + scale = PANEL_H / img.height + img = img.resize((int(img.width * scale), PANEL_H), Image.LANCZOS) + views.append((img, label)) + +total_w = PAD * 2 + sum(v.width for v, _ in views) + GAP * (len(views) - 1) +total_h = PAD + PANEL_H + LABEL_H + PAD + +canvas = Image.new("RGB", (total_w, total_h), BG) +draw = ImageDraw.Draw(canvas) + +x = PAD +for img, label in views: + canvas.paste(img, (x, PAD)) + draw.text((x + img.width // 2, PAD + PANEL_H + LABEL_H // 2), + label, fill=FG, anchor="mm") + x += img.width + GAP + +canvas.save(str(out), "PNG") +print(f"composite: {{total_w}}x{{total_h}}") +""" + r = subprocess.run([pil, "-c", script], capture_output=True, text=True) + if r.returncode != 0: + raise RuntimeError(r.stderr) + print(f" ({r.stdout.strip()})", end="", flush=True) + data = out.read_bytes() + # cleanup + for f in Path(tmp).iterdir(): + f.unlink() + os.rmdir(tmp) + return data + + +def generate_rendered_image(api_key: str, variant: str = "variant-01") -> bytes: + """Generate top/side/back views separately then composite them.""" + prompts = get_view_prompts(variant) + view_bytes = {} + for view, prompt in prompts.items(): + aspect = "16:9" if view == "side" else "1:1" + print(f"\n [{view}]", end=" ", flush=True) + view_bytes[view] = _grok_image(api_key, prompt, aspect=aspect) + print("\n compositing", end="", flush=True) + return composite_views(view_bytes) + + +def render_svg_to_png(svg_path, out_path, width=1100, height=850): + """Render the SVG engineering drawing to PNG via headless Chromium. + Produces a pixel-accurate rasterisation — correct layer proportions, + exact dimensions, no AI hallucination. + Falls back to python3.11 subprocess if playwright isn’t on the current interpreter.""" + import subprocess, tempfile + from pathlib import Path + svg_path = Path(svg_path) + out_path = Path(out_path) + + # Try importing directly first + try: + from playwright.sync_api import sync_playwright + _run_playwright_inline(svg_path, out_path, width, height) + return + except ImportError: + pass + + # Fall back: find a Python that has playwright and run as subprocess + for py in ["python3.11", "python3.10", "python3.13", "python3"]: + try: + check = subprocess.run([py, "-c", "import playwright"], + capture_output=True) + if check.returncode != 0: + continue + with tempfile.NamedTemporaryFile(suffix=".py", mode="w", + delete=False) as f: + f.write(_PLAYWRIGHT_SCRIPT) + script = f.name + result = subprocess.run( + [py, script, + str(svg_path), str(out_path), str(width), str(height)], + capture_output=True, text=True, timeout=60, + ) + Path(script).unlink(missing_ok=True) + if result.returncode != 0: + raise RuntimeError(result.stderr[-400:]) + return + except FileNotFoundError: + continue + raise RuntimeError( + "playwright not found on any Python. Run: " + "python3.11 -m pip install playwright && python3.11 -m playwright install chromium" + ) + + +def _run_playwright_inline(svg_path, out_path, width, height): + import textwrap + from playwright.sync_api import sync_playwright + html = textwrap.dedent(f""" + + +{svg_path.read_text()}""") + tmp = svg_path.parent / "_tmp_render.html" + tmp.write_text(html) + try: + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={"width": width, "height": height}) + page.goto(f"file://{tmp}") + page.wait_for_load_state("domcontentloaded") + page.wait_for_timeout(800) + page.screenshot(path=str(out_path), + clip={"x":0,"y":0,"width":width,"height":height}, + timeout=30000) + browser.close() + finally: + tmp.unlink(missing_ok=True) + + + +# --------------------------------------------------------------------------- +# Entry point +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser( + description="Generate Maharajong blank tile manufacturer spec sheet assets" + ) + parser.add_argument("--svg-only", action="store_true", + help="Generate SVG technical drawing only (no API call)") + parser.add_argument("--img-only", action="store_true", + help="Generate Grok rendered image only (no SVG)") + parser.add_argument("--png-only", action="store_true", + help="Render SVG → PNG via Playwright/Chromium (exact proportions, no API call)") + parser.add_argument("--variant", default=DEFAULT_VARIANT, + help=f"Tile variant folder to write outputs into (default: {DEFAULT_VARIANT})") + args = parser.parse_args() + + out_dir = Path(__file__).parent / args.variant / "manufacturer-docs" + out_dir.mkdir(parents=True, exist_ok=True) + + # ── SVG technical drawing ──────────────────────────────────────────────── + svg_path = out_dir / "tile-blank-technical-drawing.svg" + if not args.img_only and not args.png_only: + print("Generating SVG technical drawing...", end=" ", flush=True) + svg_content = generate_svg(variant=args.variant) + svg_path.write_text(svg_content, encoding="utf-8") + print(f"OK \u2192 {svg_path}") + + # ── Playwright PNG (pixel-accurate rasterisation of the SVG) ─────────── + if args.png_only or (not args.img_only and not args.svg_only): + png_path = out_dir / "tile-blank-technical-drawing.png" + print("Rendering SVG \u2192 PNG via Chromium...", end=" ", flush=True) + try: + render_svg_to_png(svg_path, png_path) + print(f"OK ({png_path.stat().st_size // 1024} KB) \u2192 {png_path}") + except Exception as e: + print(f"SKIP ({e})") + if args.png_only: + return + + # ── Grok rendered image ────────────────────────────────────────────────── + if not args.svg_only: + api_key = os.environ.get("GROK_API_KEY") or os.environ.get("XAI_API_KEY") + if not api_key: + print("ERROR: Set GROK_API_KEY or XAI_API_KEY to generate the rendered image.", + file=sys.stderr) + if args.img_only: + sys.exit(1) + else: + print("Skipping rendered image (no API key).") + return + + img_path = out_dir / "tile-blank-spec-sheet-rendered.png" + print("Generating Grok rendered spec sheet image...", end=" ", flush=True) + try: + img_bytes = generate_rendered_image(api_key, variant=args.variant) + img_path.write_bytes(img_bytes) + size_kb = len(img_bytes) / 1024 + print(f"OK ({size_kb:.0f} KB) → {img_path}") + except urllib.error.HTTPError as e: + body = e.read().decode() if e.readable() else str(e) + print(f"FAILED ({e.code}): {body[:200]}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/design/lib/studio_small_08_1k.hdr b/design/lib/studio_small_08_1k.hdr new file mode 100644 index 0000000..fd9f69a Binary files /dev/null and b/design/lib/studio_small_08_1k.hdr differ diff --git a/design/lib/three.min.js b/design/lib/three.min.js new file mode 100644 index 0000000..9b71020 --- /dev/null +++ b/design/lib/three.min.js @@ -0,0 +1,7 @@ +console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated with r150+, and will be removed with r160. Please use ES Modules or alternatives: https://threejs.org/docs/index.html#manual/en/introduction/Installation' ); +/** + * @license + * Copyright 2010-2023 Three.js Authors + * SPDX-License-Identifier: MIT + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE={})}(this,(function(t){"use strict";const e="152",n=100,i=300,r=301,s=302,a=303,o=304,l=306,c=1e3,h=1001,u=1002,d=1003,p=1004,m=1005,f=1006,g=1007,v=1008,_=1009,x=1012,y=1014,M=1015,S=1016,b=1020,E=1023,T=1026,w=1027,A=33776,R=33777,C=33778,L=33779,P=35840,I=35841,U=35842,D=35843,N=37492,O=37496,F=37808,B=37809,z=37810,G=37811,H=37812,k=37813,V=37814,W=37815,X=37816,j=37817,q=37818,Y=37819,Z=37820,J=37821,K=36492,$=36284,Q=36285,tt=36286,et=2300,nt=2301,it=2302,rt=2400,st=2401,at=2402,ot=2500,lt=2501,ct=3e3,ht=3001,ut="",dt="srgb",pt="srgb-linear",mt="display-p3",ft=7680,gt=35044,vt="300 es",_t=1035;class xt{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[t]&&(n[t]=[]),-1===n[t].indexOf(e)&&n[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&&-1!==n[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const n=this._listeners[t];if(void 0!==n){const t=n.indexOf(e);-1!==t&&n.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const n=e.slice(0);for(let e=0,i=n.length;e>8&255]+yt[t>>16&255]+yt[t>>24&255]+"-"+yt[255&e]+yt[e>>8&255]+"-"+yt[e>>16&15|64]+yt[e>>24&255]+"-"+yt[63&n|128]+yt[n>>8&255]+"-"+yt[n>>16&255]+yt[n>>24&255]+yt[255&i]+yt[i>>8&255]+yt[i>>16&255]+yt[i>>24&255]).toLowerCase()}function Tt(t,e,n){return Math.max(e,Math.min(n,t))}function wt(t,e){return(t%e+e)%e}function At(t,e,n){return(1-n)*t+n*e}function Rt(t){return 0==(t&t-1)&&0!==t}function Ct(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Lt(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function Pt(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function It(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const Ut={DEG2RAD:St,RAD2DEG:bt,generateUUID:Et,clamp:Tt,euclideanModulo:wt,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:At,damp:function(t,e,n,i){return At(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(wt(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(Mt=t);let e=Mt+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*St},radToDeg:function(t){return t*bt},isPowerOfTwo:Rt,ceilPowerOfTwo:Ct,floorPowerOfTwo:Lt,setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:It,denormalize:Pt};class Dt{constructor(t=0,e=0){Dt.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}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=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.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(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Tt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Nt{constructor(){Nt.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1]}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],_=i[4],x=i[7],y=i[2],M=i[5],S=i[8];return r[0]=s*m+a*v+o*y,r[3]=s*f+a*_+o*M,r[6]=s*g+a*x+o*S,r[1]=l*m+c*v+h*y,r[4]=l*f+c*_+h*M,r[7]=l*g+c*x+h*S,r[2]=u*m+d*v+p*y,r[5]=u*f+d*_+p*M,r[8]=u*g+d*x+p*S,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(Ot.makeScale(t,e)),this}rotate(t){return this.premultiply(Ot.makeRotation(-t)),this}translate(t,e){return this.premultiply(Ot.makeTranslation(t,e)),this}makeTranslation(t,e){return this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const Ot=new Nt;function Ft(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const Bt={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function zt(t,e){return new Bt[t](e)}function Gt(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}const Ht={};function kt(t){t in Ht||(Ht[t]=!0,console.warn(t))}function Vt(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Wt(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const Xt=(new Nt).fromArray([.8224621,.0331941,.0170827,.177538,.9668058,.0723974,-1e-7,1e-7,.9105199]),jt=(new Nt).fromArray([1.2249401,-.0420569,-.0196376,-.2249404,1.0420571,-.0786361,1e-7,0,1.0982735]);const qt={[pt]:t=>t,[dt]:t=>t.convertSRGBToLinear(),[mt]:function(t){return t.convertSRGBToLinear().applyMatrix3(jt)}},Yt={[pt]:t=>t,[dt]:t=>t.convertLinearToSRGB(),[mt]:function(t){return t.applyMatrix3(Xt).convertLinearToSRGB()}},Zt={enabled:!0,get legacyMode(){return console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),!this.enabled},set legacyMode(t){console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),this.enabled=!t},get workingColorSpace(){return pt},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,n){if(!1===this.enabled||e===n||!e||!n)return t;const i=qt[e],r=Yt[n];if(void 0===i||void 0===r)throw new Error(`Unsupported color space conversion, "${e}" to "${n}".`);return r(i(t))},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}};let Jt;class Kt{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===Jt&&(Jt=Gt("canvas")),Jt.width=t.width,Jt.height=t.height;const n=Jt.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=Jt}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=Gt("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==i)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case c:t.x=t.x-Math.floor(t.x);break;case h:t.x=t.x<0?0:1;break;case u:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case c:t.y=t.y-Math.floor(t.y);break;case h:t.y=t.y<0?0:1;break;case u:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}get encoding(){return kt("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace===dt?ht:ct}set encoding(t){kt("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace=t===ht?dt:ut}}ee.DEFAULT_IMAGE=null,ee.DEFAULT_MAPPING=i,ee.DEFAULT_ANISOTROPY=1;class ne{constructor(t=0,e=0,n=0,i=1){ne.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,i,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Tt(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,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(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._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 t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=n,this._y=i,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=Math.random(),e=Math.sqrt(1-t),n=Math.sqrt(t),i=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(i),n*Math.sin(r),n*Math.cos(r),e*Math.sin(i))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class oe{constructor(t=0,e=0,n=0){oe.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(ce.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ce.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*i-a*n,c=o*n+a*e-r*i,h=o*i+r*n-s*e,u=-r*e-s*n-a*i;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}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=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.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(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return le.copy(this).projectOnVector(t),this.sub(le)}reflect(t){return this.sub(le.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Tt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,n=Math.sqrt(1-t**2);return this.x=n*Math.cos(e),this.y=n*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const le=new oe,ce=new ae;class he{constructor(t=new oe(1/0,1/0,1/0),e=new oe(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,de),de.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(ye),Me.subVectors(this.max,ye),me.subVectors(t.a,ye),fe.subVectors(t.b,ye),ge.subVectors(t.c,ye),ve.subVectors(fe,me),_e.subVectors(ge,fe),xe.subVectors(me,ge);let e=[0,-ve.z,ve.y,0,-_e.z,_e.y,0,-xe.z,xe.y,ve.z,0,-ve.x,_e.z,0,-_e.x,xe.z,0,-xe.x,-ve.y,ve.x,0,-_e.y,_e.x,0,-xe.y,xe.x,0];return!!Ee(e,me,fe,ge,Me)&&(e=[1,0,0,0,1,0,0,0,1],!!Ee(e,me,fe,ge,Me)&&(Se.crossVectors(ve,_e),e=[Se.x,Se.y,Se.z],Ee(e,me,fe,ge,Me)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,de).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(de).length()),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(ue[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),ue[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),ue[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),ue[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),ue[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),ue[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),ue[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),ue[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(ue)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const ue=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],de=new oe,pe=new he,me=new oe,fe=new oe,ge=new oe,ve=new oe,_e=new oe,xe=new oe,ye=new oe,Me=new oe,Se=new oe,be=new oe;function Ee(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){be.fromArray(t,s);const a=r.x*Math.abs(be.x)+r.y*Math.abs(be.y)+r.z*Math.abs(be.z),o=e.dot(be),l=n.dot(be),c=i.dot(be);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const Te=new he,we=new oe,Ae=new oe;class Re{constructor(t=new oe,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):Te.setFromPoints(t).getCenter(n);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;we.subVectors(t,this.center);const e=we.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.addScaledVector(we,n/t),this.radius+=n}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Ae.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(we.copy(t.center).add(Ae)),this.expandByPoint(we.copy(t.center).sub(Ae))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Ce=new oe,Le=new oe,Pe=new oe,Ie=new oe,Ue=new oe,De=new oe,Ne=new oe;class Oe{constructor(t=new oe,e=new oe(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Ce)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Ce.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Ce.copy(this.origin).addScaledVector(this.direction,e),Ce.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){Le.copy(t).add(e).multiplyScalar(.5),Pe.copy(e).sub(t).normalize(),Ie.copy(this.origin).sub(Le);const r=.5*t.distanceTo(e),s=-this.direction.dot(Pe),a=Ie.dot(this.direction),o=-Ie.dot(Pe),l=Ie.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(Le).addScaledVector(Pe,u),d}intersectSphere(t,e){Ce.subVectors(t.center,this.origin);const n=Ce.dot(this.direction),i=Ce.dot(Ce)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,i,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),n>s||r>i?null:((r>n||isNaN(n))&&(n=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,Ce)}intersectTriangle(t,e,n,i,r){Ue.subVectors(e,t),De.subVectors(n,t),Ne.crossVectors(Ue,De);let s,a=this.direction.dot(Ne);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Ie.subVectors(this.origin,t);const o=s*this.direction.dot(De.crossVectors(Ie,De));if(o<0)return null;const l=s*this.direction.dot(Ue.cross(Ie));if(l<0)return null;if(o+l>a)return null;const c=-s*Ie.dot(Ne);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Fe{constructor(){Fe.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Fe).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/Be.setFromMatrixColumn(t,0).length(),r=1/Be.setFromMatrixColumn(t,1).length(),s=1/Be.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=n*h-i,e[2]=i*h-n,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Ge,t,He)}lookAt(t,e,n){const i=this.elements;return We.subVectors(t,e),0===We.lengthSq()&&(We.z=1),We.normalize(),ke.crossVectors(n,We),0===ke.lengthSq()&&(1===Math.abs(n.z)?We.x+=1e-4:We.z+=1e-4,We.normalize(),ke.crossVectors(n,We)),ke.normalize(),Ve.crossVectors(We,ke),i[0]=ke.x,i[4]=Ve.x,i[8]=We.x,i[1]=ke.y,i[5]=Ve.y,i[9]=We.y,i[2]=ke.z,i[6]=Ve.z,i[10]=We.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],_=n[7],x=n[11],y=n[15],M=i[0],S=i[4],b=i[8],E=i[12],T=i[1],w=i[5],A=i[9],R=i[13],C=i[2],L=i[6],P=i[10],I=i[14],U=i[3],D=i[7],N=i[11],O=i[15];return r[0]=s*M+a*T+o*C+l*U,r[4]=s*S+a*w+o*L+l*D,r[8]=s*b+a*A+o*P+l*N,r[12]=s*E+a*R+o*I+l*O,r[1]=c*M+h*T+u*C+d*U,r[5]=c*S+h*w+u*L+d*D,r[9]=c*b+h*A+u*P+d*N,r[13]=c*E+h*R+u*I+d*O,r[2]=p*M+m*T+f*C+g*U,r[6]=p*S+m*w+f*L+g*D,r[10]=p*b+m*A+f*P+g*N,r[14]=p*E+m*R+f*I+g*O,r[3]=v*M+_*T+x*C+y*U,r[7]=v*S+_*w+x*L+y*D,r[11]=v*b+_*A+x*P+y*N,r[15]=v*E+_*R+x*I+y*O,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],i=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,_=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,x=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,y=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+n*_+i*x+r*y;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const S=1/M;return t[0]=v*S,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*S,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*S,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*S,t[4]=_*S,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*S,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*S,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*S,t[8]=x*S,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*S,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*S,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*S,t[12]=y*S,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*S,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*S,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*S,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,_=o*c,x=o*h,y=n.x,M=n.y,S=n.z;return i[0]=(1-(m+g))*y,i[1]=(d+x)*y,i[2]=(p-_)*y,i[3]=0,i[4]=(d-x)*M,i[5]=(1-(u+g))*M,i[6]=(f+v)*M,i[7]=0,i[8]=(p+_)*S,i[9]=(f-v)*S,i[10]=(1-(u+m))*S,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=Be.set(i[0],i[1],i[2]).length();const s=Be.set(i[4],i[5],i[6]).length(),a=Be.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],ze.copy(this);const o=1/r,l=1/s,c=1/a;return ze.elements[0]*=o,ze.elements[1]*=o,ze.elements[2]*=o,ze.elements[4]*=l,ze.elements[5]*=l,ze.elements[6]*=l,ze.elements[8]*=c,ze.elements[9]*=c,ze.elements[10]*=c,e.setFromRotationMatrix(ze),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s){const a=this.elements,o=2*r/(e-t),l=2*r/(n-i),c=(e+t)/(e-t),h=(n+i)/(n-i),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,n,i,r,s){const a=this.elements,o=1/(e-t),l=1/(n-i),c=1/(s-r),h=(e+t)*o,u=(n+i)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const Be=new oe,ze=new Fe,Ge=new oe(0,0,0),He=new oe(1,1,1),ke=new oe,Ve=new oe,We=new oe,Xe=new Fe,je=new ae;class qe{constructor(t=0,e=0,n=0,i=qe.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Tt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-Tt(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(Tt(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-Tt(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(Tt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-Tt(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return Xe.makeRotationFromQuaternion(t),this.setFromRotationMatrix(Xe,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return je.setFromEuler(this),this.setFromQuaternion(je,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}qe.DEFAULT_ORDER="XYZ";class Ye{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0&&(n=n.concat(r))}return n}getWorldPosition(t){return this.updateWorldMatrix(!0,!1),t.setFromMatrixPosition(this.matrixWorld)}getWorldQuaternion(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(tn,t,en),t}getWorldScale(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(tn,nn,t),t}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(e[8],e[9],e[10]).normalize()}raycast(){}traverse(t){t(this);const e=this.children;for(let n=0,i=e.length;n0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const n=e.shapes;if(Array.isArray(n))for(let e=0,i=n.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){hn.subVectors(i,e),un.subVectors(n,e),dn.subVectors(t,e);const s=hn.dot(hn),a=hn.dot(un),o=hn.dot(dn),l=un.dot(un),c=un.dot(dn),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,n,i){return this.getBarycoord(t,e,n,i,pn),pn.x>=0&&pn.y>=0&&pn.x+pn.y<=1}static getUV(t,e,n,i,r,s,a,o){return!1===yn&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),yn=!0),this.getInterpolation(t,e,n,i,r,s,a,o)}static getInterpolation(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,pn),o.setScalar(0),o.addScaledVector(r,pn.x),o.addScaledVector(s,pn.y),o.addScaledVector(a,pn.z),o}static isFrontFacing(t,e,n,i){return hn.subVectors(n,e),un.subVectors(t,e),hn.cross(un).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return hn.subVectors(this.c,this.b),un.subVectors(this.a,this.b),.5*hn.cross(un).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Mn.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Mn.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return!1===yn&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),yn=!0),Mn.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}getInterpolation(t,e,n,i,r){return Mn.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return Mn.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Mn.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;mn.subVectors(i,n),fn.subVectors(r,n),vn.subVectors(t,n);const o=mn.dot(vn),l=fn.dot(vn);if(o<=0&&l<=0)return e.copy(n);_n.subVectors(t,i);const c=mn.dot(_n),h=fn.dot(_n);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(mn,s);xn.subVectors(t,r);const d=mn.dot(xn),p=fn.dot(xn);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(n).addScaledVector(fn,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return gn.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(gn,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(mn,s).addScaledVector(fn,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let Sn=0;class bn extends xt{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:Sn++}),this.uuid=Et(),this.name="",this.type="Material",this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=n,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=ft,this.stencilZFail=ft,this.stencilZPass=ft,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.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),0!==this.side&&(n.side=this.side),this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=this.transparent),n.depthFunc=this.depthFunc,n.depthTest=this.depthTest,n.depthWrite=this.depthWrite,n.colorWrite=this.colorWrite,n.stencilWrite=this.stencilWrite,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,void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(n.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.forceSinglePass&&(n.forceSinglePass=this.forceSinglePass),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=this.flatShading),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}const En={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},Tn={h:0,s:0,l:0},wn={h:0,s:0,l:0};function An(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}class Rn{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,void 0===e&&void 0===n?this.set(t):this.setRGB(t,e,n)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=dt){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,Zt.toWorkingColorSpace(this,e),this}setRGB(t,e,n,i=Zt.workingColorSpace){return this.r=t,this.g=e,this.b=n,Zt.toWorkingColorSpace(this,i),this}setHSL(t,e,n,i=Zt.workingColorSpace){if(t=wt(t,1),e=Tt(e,0,1),n=Tt(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=An(r,i,t+1/3),this.g=An(r,i,t),this.b=An(r,i,t-1/3)}return Zt.toWorkingColorSpace(this,i),this}setStyle(t,e=dt){function n(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const s=i[1],a=i[2];switch(s){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(n,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=dt){const n=En[t.toLowerCase()];return void 0!==n?this.setHex(n,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=Vt(t.r),this.g=Vt(t.g),this.b=Vt(t.b),this}copyLinearToSRGB(t){return this.r=Wt(t.r),this.g=Wt(t.g),this.b=Wt(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=dt){return Zt.fromWorkingColorSpace(Cn.copy(this),t),65536*Math.round(Tt(255*Cn.r,0,255))+256*Math.round(Tt(255*Cn.g,0,255))+Math.round(Tt(255*Cn.b,0,255))}getHexString(t=dt){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=Zt.workingColorSpace){Zt.fromWorkingColorSpace(Cn.copy(this),e);const n=Cn.r,i=Cn.g,r=Cn.b,s=Math.max(n,i,r),a=Math.min(n,i,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case n:o=(i-r)/t+(i>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,n=0;for(;0==(8388608&e);)e<<=1,n-=8388608;e&=-8388609,n+=947912704,s[t]=e|n}for(let t=1024;t<2048;++t)s[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)a[t]=t<<23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t<63;++t)a[t]=2147483648+(t-32<<23);a[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(o[t]=1024);return{floatView:e,uint32View:n,baseTable:i,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}function Un(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=Tt(t,-65504,65504),Pn.floatView[0]=t;const e=Pn.uint32View[0],n=e>>23&511;return Pn.baseTable[n]+((8388607&e)>>Pn.shiftTable[n])}function Dn(t){const e=t>>10;return Pn.uint32View[0]=Pn.mantissaTable[Pn.offsetTable[e]+(1023&t)]+Pn.exponentTable[e],Pn.floatView[0]}const Nn={toHalfFloat:Un,fromHalfFloat:Dn},On=new oe,Fn=new Dt;class Bn{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=n,this.usage=gt,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t(t.far-t.near)**2)return}Jn.copy(r).invert(),Kn.copy(t.ray).applyMatrix4(Jn),null!==n.boundingBox&&!1===Kn.intersectsBox(n.boundingBox)||this._computeIntersections(t,e)}}_computeIntersections(t,e){let n;const i=this.geometry,r=this.material,s=i.index,a=i.attributes.position,o=i.attributes.uv,l=i.attributes.uv1,c=i.attributes.normal,h=i.groups,u=i.drawRange;if(null!==s)if(Array.isArray(r))for(let i=0,a=h.length;in.far?null:{distance:c,point:di.clone(),object:t}}(t,e,n,i,ti,ei,ni,ui);if(h){r&&(si.fromBufferAttribute(r,o),ai.fromBufferAttribute(r,l),oi.fromBufferAttribute(r,c),h.uv=Mn.getInterpolation(ui,ti,ei,ni,si,ai,oi,new Dt)),s&&(si.fromBufferAttribute(s,o),ai.fromBufferAttribute(s,l),oi.fromBufferAttribute(s,c),h.uv1=Mn.getInterpolation(ui,ti,ei,ni,si,ai,oi,new Dt),h.uv2=h.uv1),a&&(li.fromBufferAttribute(a,o),ci.fromBufferAttribute(a,l),hi.fromBufferAttribute(a,c),h.normal=Mn.getInterpolation(ui,ti,ei,ni,li,ci,hi,new oe),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const t={a:o,b:l,c:c,normal:new oe,materialIndex:0};Mn.getNormal(ti,ei,ni,t.normal),h.face=t}return h}class fi extends Zn{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const _=s/f,x=p/g,y=s/2,M=p/2,S=m/2,b=f+1,E=g+1;let T=0,w=0;const A=new oe;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class Mi extends cn{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new Fe,this.projectionMatrix=new Fe,this.projectionMatrixInverse=new Fe}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class Si extends Mi{constructor(t=50,e=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*bt*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*St*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*bt*Math.atan(Math.tan(.5*St*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,n,i,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*St*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const bi=-90;class Ei extends cn{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n;const i=new Si(bi,1,t,e);i.layers=this.layers,i.up.set(0,1,0),i.lookAt(1,0,0),this.add(i);const r=new Si(bi,1,t,e);r.layers=this.layers,r.up.set(0,1,0),r.lookAt(-1,0,0),this.add(r);const s=new Si(bi,1,t,e);s.layers=this.layers,s.up.set(0,0,-1),s.lookAt(0,1,0),this.add(s);const a=new Si(bi,1,t,e);a.layers=this.layers,a.up.set(0,0,1),a.lookAt(0,-1,0),this.add(a);const o=new Si(bi,1,t,e);o.layers=this.layers,o.up.set(0,1,0),o.lookAt(0,0,1),this.add(o);const l=new Si(bi,1,t,e);l.layers=this.layers,l.up.set(0,1,0),l.lookAt(0,0,-1),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const n=this.renderTarget,[i,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=0,t.xr.enabled=!1;const d=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0),t.render(e,i),t.setRenderTarget(n,1),t.render(e,r),t.setRenderTarget(n,2),t.render(e,s),t.setRenderTarget(n,3),t.render(e,a),t.setRenderTarget(n,4),t.render(e,o),n.texture.generateMipmaps=d,t.setRenderTarget(n,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,n.texture.needsPMREMUpdate=!0}}class Ti extends ee{constructor(t,e,n,i,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,n,i,s,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class wi extends ie{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},i=[n,n,n,n,n,n];void 0!==e.encoding&&(kt("THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace."),e.colorSpace=e.encoding===ht?dt:ut),this.texture=new Ti(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:f}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new fi(5,5,5),r=new yi({name:"CubemapFromEquirect",uniforms:gi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new pi(i,r),a=e.minFilter;e.minFilter===v&&(e.minFilter=f);return new Ei(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}const Ai=new oe,Ri=new oe,Ci=new Nt;class Li{constructor(t=new oe(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=Ai.subVectors(n,e).cross(Ri.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(t).addScaledVector(this.normal,-this.distanceToPoint(t))}intersectLine(t,e){const n=t.delta(Ai),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||Ci.getNormalMatrix(t),i=this.coplanarPoint(Ai).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const Pi=new Re,Ii=new oe;class Ui{constructor(t=new Li,e=new Li,n=new Li,i=new Li,r=new Li,s=new Li){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t){const e=this.planes,n=t.elements,i=n[0],r=n[1],s=n[2],a=n[3],o=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],m=n[11],f=n[12],g=n[13],v=n[14],_=n[15];return e[0].setComponents(a-i,h-o,m-u,_-f).normalize(),e[1].setComponents(a+i,h+o,m+u,_+f).normalize(),e[2].setComponents(a+r,h+l,m+d,_+g).normalize(),e[3].setComponents(a-r,h-l,m-d,_-g).normalize(),e[4].setComponents(a-s,h-c,m-p,_-v).normalize(),e[5].setComponents(a+s,h+c,m+p,_+v).normalize(),this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),Pi.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),Pi.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(Pi)}intersectsSprite(t){return Pi.center.set(0,0,0),Pi.radius=.7071067811865476,Pi.applyMatrix4(t.matrixWorld),this.intersectsSphere(Pi)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,Ii.y=i.normal.y>0?t.max.y:t.min.y,Ii.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(Ii)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function Di(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function Ni(t,e){const n=e.isWebGL2,i=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),i.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const n=i.get(e);n&&(t.deleteBuffer(n.buffer),i.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=i.get(e);return void((!t||t.version 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, vMapUv );\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_NORMALMAP_TANGENTSPACE\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},Bi={common:{diffuse:{value:new Rn(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new Nt},alphaMap:{value:null},alphaMapTransform:{value:new Nt},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new Nt}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new Nt}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new Nt}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new Nt},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new Nt},normalScale:{value:new Dt(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new Nt},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new Nt}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new Nt}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new Nt}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Rn(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Rn(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Nt}},sprite:{diffuse:{value:new Rn(16777215)},opacity:{value:1},center:{value:new Dt(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new Nt},alphaMap:{value:null},alphaTest:{value:0}}},zi={basic:{uniforms:vi([Bi.common,Bi.specularmap,Bi.envmap,Bi.aomap,Bi.lightmap,Bi.fog]),vertexShader:Fi.meshbasic_vert,fragmentShader:Fi.meshbasic_frag},lambert:{uniforms:vi([Bi.common,Bi.specularmap,Bi.envmap,Bi.aomap,Bi.lightmap,Bi.emissivemap,Bi.bumpmap,Bi.normalmap,Bi.displacementmap,Bi.fog,Bi.lights,{emissive:{value:new Rn(0)}}]),vertexShader:Fi.meshlambert_vert,fragmentShader:Fi.meshlambert_frag},phong:{uniforms:vi([Bi.common,Bi.specularmap,Bi.envmap,Bi.aomap,Bi.lightmap,Bi.emissivemap,Bi.bumpmap,Bi.normalmap,Bi.displacementmap,Bi.fog,Bi.lights,{emissive:{value:new Rn(0)},specular:{value:new Rn(1118481)},shininess:{value:30}}]),vertexShader:Fi.meshphong_vert,fragmentShader:Fi.meshphong_frag},standard:{uniforms:vi([Bi.common,Bi.envmap,Bi.aomap,Bi.lightmap,Bi.emissivemap,Bi.bumpmap,Bi.normalmap,Bi.displacementmap,Bi.roughnessmap,Bi.metalnessmap,Bi.fog,Bi.lights,{emissive:{value:new Rn(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Fi.meshphysical_vert,fragmentShader:Fi.meshphysical_frag},toon:{uniforms:vi([Bi.common,Bi.aomap,Bi.lightmap,Bi.emissivemap,Bi.bumpmap,Bi.normalmap,Bi.displacementmap,Bi.gradientmap,Bi.fog,Bi.lights,{emissive:{value:new Rn(0)}}]),vertexShader:Fi.meshtoon_vert,fragmentShader:Fi.meshtoon_frag},matcap:{uniforms:vi([Bi.common,Bi.bumpmap,Bi.normalmap,Bi.displacementmap,Bi.fog,{matcap:{value:null}}]),vertexShader:Fi.meshmatcap_vert,fragmentShader:Fi.meshmatcap_frag},points:{uniforms:vi([Bi.points,Bi.fog]),vertexShader:Fi.points_vert,fragmentShader:Fi.points_frag},dashed:{uniforms:vi([Bi.common,Bi.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Fi.linedashed_vert,fragmentShader:Fi.linedashed_frag},depth:{uniforms:vi([Bi.common,Bi.displacementmap]),vertexShader:Fi.depth_vert,fragmentShader:Fi.depth_frag},normal:{uniforms:vi([Bi.common,Bi.bumpmap,Bi.normalmap,Bi.displacementmap,{opacity:{value:1}}]),vertexShader:Fi.meshnormal_vert,fragmentShader:Fi.meshnormal_frag},sprite:{uniforms:vi([Bi.sprite,Bi.fog]),vertexShader:Fi.sprite_vert,fragmentShader:Fi.sprite_frag},background:{uniforms:{uvTransform:{value:new Nt},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Fi.background_vert,fragmentShader:Fi.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:Fi.backgroundCube_vert,fragmentShader:Fi.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Fi.cube_vert,fragmentShader:Fi.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Fi.equirect_vert,fragmentShader:Fi.equirect_frag},distanceRGBA:{uniforms:vi([Bi.common,Bi.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Fi.distanceRGBA_vert,fragmentShader:Fi.distanceRGBA_frag},shadow:{uniforms:vi([Bi.lights,Bi.fog,{color:{value:new Rn(0)},opacity:{value:1}}]),vertexShader:Fi.shadow_vert,fragmentShader:Fi.shadow_frag}};zi.physical={uniforms:vi([zi.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new Nt},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new Nt},clearcoatNormalScale:{value:new Dt(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new Nt},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new Nt},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new Nt},sheen:{value:0},sheenColor:{value:new Rn(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new Nt},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new Nt},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new Nt},transmissionSamplerSize:{value:new Dt},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new Nt},attenuationDistance:{value:0},attenuationColor:{value:new Rn(0)},specularColor:{value:new Rn(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new Nt},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new Nt}}]),vertexShader:Fi.meshphysical_vert,fragmentShader:Fi.meshphysical_frag};const Gi={r:0,b:0,g:0};function Hi(t,e,n,i,r,s,a){const o=new Rn(0);let c,h,u=!0===s?0:1,d=null,p=0,m=null;function f(e,n){e.getRGB(Gi,_i(t)),i.buffers.color.setClear(Gi.r,Gi.g,Gi.b,n,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),u=e,f(o,u)},getClearAlpha:function(){return u},setClearAlpha:function(t){u=t,f(o,u)},render:function(s,g){let v=!1,_=!0===g.isScene?g.background:null;if(_&&_.isTexture){_=(g.backgroundBlurriness>0?n:e).get(_)}switch(null===_?f(o,u):_&&_.isColor&&(f(_,1),v=!0),t.xr.getEnvironmentBlendMode()){case"opaque":v=!0;break;case"additive":i.buffers.color.setClear(0,0,0,1,a),v=!0;break;case"alpha-blend":i.buffers.color.setClear(0,0,0,0,a),v=!0}(t.autoClear||v)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),_&&(_.isCubeTexture||_.mapping===l)?(void 0===h&&(h=new pi(new fi(1,1,1),new yi({name:"BackgroundCubeMaterial",uniforms:gi(zi.backgroundCube.uniforms),vertexShader:zi.backgroundCube.vertexShader,fragmentShader:zi.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(h)),h.material.uniforms.envMap.value=_,h.material.uniforms.flipEnvMap.value=_.isCubeTexture&&!1===_.isRenderTargetTexture?-1:1,h.material.uniforms.backgroundBlurriness.value=g.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=g.backgroundIntensity,h.material.toneMapped=_.colorSpace!==dt,d===_&&p===_.version&&m===t.toneMapping||(h.material.needsUpdate=!0,d=_,p=_.version,m=t.toneMapping),h.layers.enableAll(),s.unshift(h,h.geometry,h.material,0,0,null)):_&&_.isTexture&&(void 0===c&&(c=new pi(new Oi(2,2),new yi({name:"BackgroundMaterial",uniforms:gi(zi.background.uniforms),vertexShader:zi.background.vertexShader,fragmentShader:zi.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(c)),c.material.uniforms.t2D.value=_,c.material.uniforms.backgroundIntensity.value=g.backgroundIntensity,c.material.toneMapped=_.colorSpace!==dt,!0===_.matrixAutoUpdate&&_.updateMatrix(),c.material.uniforms.uvTransform.value.copy(_.matrix),d===_&&p===_.version&&m===t.toneMapping||(c.material.needsUpdate=!0,d=_,p=_.version,m=t.toneMapping),c.layers.enableAll(),s.unshift(c,c.geometry,c.material,0,0,null))}}}function ki(t,e,n,i){const r=t.getParameter(t.MAX_VERTEX_ATTRIBS),s=i.isWebGL2?null:e.get("OES_vertex_array_object"),a=i.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return i.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return i.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],n=[],i=[];for(let t=0;t=0){const n=r[e];let i=s[e];if(void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;a++}}return c.attributesNum!==a||c.index!==i}(r,x,d,y),M&&function(t,e,n,i){const r={},s=e.attributes;let a=0;const o=n.getAttributes();for(const e in o){if(o[e].location>=0){let n=s[e];void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[e]=i,a++}}c.attributes=r,c.attributesNum=a,c.index=i}(r,x,d,y)}else{const t=!0===l.wireframe;c.geometry===x.id&&c.program===d.id&&c.wireframe===t||(c.geometry=x.id,c.program=d.id,c.wireframe=t,M=!0)}null!==y&&n.update(y,t.ELEMENT_ARRAY_BUFFER),(M||h)&&(h=!1,function(r,s,a,o){if(!1===i.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const i=c[e];if(i.location>=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=n.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const n=s.data,l=n.stride,d=s.offset;if(n.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.HIGH_FLOAT).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.MEDIUM_FLOAT).precision>0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&"WebGL2RenderingContext"===t.constructor.name;let a=void 0!==n.precision?n.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===n.logarithmicDepthBuffer,h=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),u=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS),d=t.getParameter(t.MAX_TEXTURE_SIZE),p=t.getParameter(t.MAX_CUBE_MAP_TEXTURE_SIZE),m=t.getParameter(t.MAX_VERTEX_ATTRIBS),f=t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),g=t.getParameter(t.MAX_VARYING_VECTORS),v=t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),_=u>0,x=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==i)return i;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");i=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else i=0;return i},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:_,floatFragmentTextures:x,floatVertexTextures:_&&x,maxSamples:s?t.getParameter(t.MAX_SAMPLES):0}}function Xi(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new Li,o=new Nt,l={value:null,needsUpdate:!1};function c(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);e.numPlanes=i,e.numIntersection=0}();else{const t=s?0:i,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=n[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function ji(t){let e=new WeakMap;function n(t,e){return e===a?t.mapping=r:e===o&&(t.mapping=s),t}function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture&&!1===r.isRenderTargetTexture){const s=r.mapping;if(s===a||s===o){if(e.has(r)){return n(e.get(r).texture,r.mapping)}{const s=r.image;if(s&&s.height>0){const a=new wi(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class qi extends Mi{constructor(t=-1,e=1,n=1,i=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=i,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,n,i,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const Yi=[.125,.215,.35,.446,.526,.582],Zi=20,Ji=new qi,Ki=new Rn;let $i=null;const Qi=(1+Math.sqrt(5))/2,tr=1/Qi,er=[new oe(1,1,1),new oe(-1,1,1),new oe(1,1,-1),new oe(-1,1,-1),new oe(0,Qi,tr),new oe(0,Qi,-tr),new oe(tr,0,Qi),new oe(-tr,0,Qi),new oe(Qi,tr,0),new oe(-Qi,tr,0)];class nr{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){$i=this._renderer.getRenderTarget(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,i,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=ar(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=sr(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;tt-4?o=Yi[a-t+4-1]:0===a&&(o=0),i.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),_=new Float32Array(f*p*d),x=new Float32Array(g*p*d);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];v.set(i,m*p*t),_.set(u,f*p*t);const r=[t,t,t,t,t,t];x.set(r,g*p*t)}const y=new Zn;y.setAttribute("position",new Bn(v,m)),y.setAttribute("uv",new Bn(_,f)),y.setAttribute("faceIndex",new Bn(x,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(t,e,n){const i=new Float32Array(Zi),r=new oe(0,1,0),s=new yi({name:"SphericalGaussianBlur",defines:{n:Zi,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:or(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1});return s}(i,t,e)}return i}_compileMaterial(t){const e=new pi(this._lodPlanes[0],t);this._renderer.compile(e,Ji)}_sceneToCubeUV(t,e,n,i){const r=new Si(90,1,e,n),s=[1,-1,1,1,1,1],a=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(Ki),o.toneMapping=0,o.autoClear=!1;const h=new Ln({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new pi(new fi,h);let d=!1;const p=t.background;p?p.isColor&&(h.color.copy(p),t.background=null,d=!0):(h.color.copy(Ki),d=!0);for(let e=0;e<6;e++){const n=e%3;0===n?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===n?(r.up.set(0,0,s[e]),r.lookAt(0,a[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,a[e]));const l=this._cubeSize;rr(i,n*l,e>2?l:0,l,l),o.setRenderTarget(i),d&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=p}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===r||t.mapping===s;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=ar()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=sr());const a=i?this._cubemapMaterial:this._equirectMaterial,o=new pi(this._lodPlanes[0],a);a.uniforms.envMap.value=t;const l=this._cubeSize;rr(e,0,0,3*l,2*l),n.setRenderTarget(e),n.render(o,Ji)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;eZi&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;tv-4?i-v+4:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(e),o.render(c,Ji)}}function ir(t,e,n){const i=new ie(t,e,n);return i.texture.mapping=l,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function rr(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function sr(){return new yi({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:or(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function ar(){return new yi({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:or(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function or(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function lr(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(l){if(l&&l.isTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(l.isRenderTargetTexture&&!0===l.needsPMREMUpdate){l.needsPMREMUpdate=!1;let i=e.get(l);return null===n&&(n=new nr(t)),i=h?n.fromEquirectangular(l,i):n.fromCubemap(l,i),e.set(l,i),i.texture}if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const n=6;for(let i=0;ie.maxTextureSize&&(w=Math.ceil(T/e.maxTextureSize),T=e.maxTextureSize);const A=new Float32Array(T*w*4*p),R=new re(A,T,w,p);R.type=M,R.needsUpdate=!0;const C=4*E;for(let P=0;P0)return t;const r=e*n;let s=Mr[r];if(void 0===s&&(s=new Float32Array(r),Mr[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function Ar(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n":" "} ${r}: ${n[t]}`)}return i.join("\n")}(t.getShaderSource(e),i)}return r}function Es(t,e){const n=function(t){switch(t){case pt:return["Linear","( value )"];case dt:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+n[0]+n[1]+"; }"}function Ts(t,e){let n;switch(e){case 1:n="Linear";break;case 2:n="Reinhard";break;case 3:n="OptimizedCineon";break;case 4:n="ACESFilmic";break;case 5:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),n="Linear"}return"vec3 "+t+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}function ws(t){return""!==t}function As(t,e){const n=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function Rs(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const Cs=/^[ \t]*#include +<([\w\d./]+)>/gm;function Ls(t){return t.replace(Cs,Ps)}function Ps(t,e){const n=Fi[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return Ls(n)}const Is=/#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 Us(t){return t.replace(Is,Ds)}function Ds(t,e,n,i){let r="";for(let t=parseInt(e);t0&&(x+="\n"),y=[g,v].filter(ws).join("\n"),y.length>0&&(y+="\n")):(x=[Ns(n),"#define SHADER_NAME "+n.shaderName,v,n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors&&n.isWebGL2?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(ws).join("\n"),y=[g,Ns(n),"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.useLegacyLights?"#define LEGACY_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?Fi.tonemapping_pars_fragment:"",0!==n.toneMapping?Ts("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",Fi.encodings_pars_fragment,Es("linearToOutputTexel",n.outputColorSpace),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(ws).join("\n")),c=Ls(c),c=As(c,n),c=Rs(c,n),h=Ls(h),h=As(h,n),h=Rs(h,n),c=Us(c),h=Us(h),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(M="#version 300 es\n",x=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+x,y=["#define varying in",n.glslVersion===vt?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===vt?"":"#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("\n")+"\n"+y);const S=M+x+c,b=M+y+h,E=Ms(a,a.VERTEX_SHADER,S),T=Ms(a,a.FRAGMENT_SHADER,b);if(a.attachShader(_,E),a.attachShader(_,T),void 0!==n.index0AttributeName?a.bindAttribLocation(_,0,n.index0AttributeName):!0===n.morphTargets&&a.bindAttribLocation(_,0,"position"),a.linkProgram(_),t.debug.checkShaderErrors){const e=a.getProgramInfoLog(_).trim(),n=a.getShaderInfoLog(E).trim(),i=a.getShaderInfoLog(T).trim();let r=!0,s=!0;if(!1===a.getProgramParameter(_,a.LINK_STATUS))if(r=!1,"function"==typeof t.debug.onShaderError)t.debug.onShaderError(a,_,E,T);else{const t=bs(a,E,"vertex"),n=bs(a,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(_,a.VALIDATE_STATUS)+"\n\nProgram Info Log: "+e+"\n"+t+"\n"+n)}else""!==e?console.warn("THREE.WebGLProgram: Program Info Log:",e):""!==n&&""!==i||(s=!1);s&&(this.diagnostics={runnable:r,programLog:e,vertexShader:{log:n,prefix:x},fragmentShader:{log:i,prefix:y}})}let w,A;return a.deleteShader(E),a.deleteShader(T),this.getUniforms=function(){return void 0===w&&(w=new ys(a,_)),w},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const n={},i=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES);for(let r=0;r0,j=s.iridescence>0,q=s.sheen>0,Y=s.transmission>0,Z=X&&!!s.clearcoatMap,J=X&&!!s.clearcoatNormalMap,K=X&&!!s.clearcoatRoughnessMap,$=j&&!!s.iridescenceMap,Q=j&&!!s.iridescenceThicknessMap,tt=q&&!!s.sheenColorMap,et=q&&!!s.sheenRoughnessMap,nt=!!s.specularMap,it=!!s.specularColorMap,rt=!!s.specularIntensityMap,st=Y&&!!s.transmissionMap,at=Y&&!!s.thicknessMap,ot=!!s.gradientMap,lt=!!s.alphaMap,ct=s.alphaTest>0,ht=!!s.extensions,ut=!!y.attributes.uv1,dt=!!y.attributes.uv2,mt=!!y.attributes.uv3;return{isWebGL2:u,shaderID:E,shaderName:s.type,vertexShader:A,fragmentShader:R,defines:s.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:m,instancing:U,instancingColor:U&&null!==_.instanceColor,supportsVertexTextures:p,outputColorSpace:null===I?t.outputColorSpace:!0===I.isXRRenderTarget?I.texture.colorSpace:pt,map:D,matcap:N,envMap:O,envMapMode:O&&S.mapping,envMapCubeUVHeight:b,aoMap:F,lightMap:B,bumpMap:z,normalMap:G,displacementMap:p&&H,emissiveMap:k,normalMapObjectSpace:G&&1===s.normalMapType,normalMapTangentSpace:G&&0===s.normalMapType,metalnessMap:V,roughnessMap:W,clearcoat:X,clearcoatMap:Z,clearcoatNormalMap:J,clearcoatRoughnessMap:K,iridescence:j,iridescenceMap:$,iridescenceThicknessMap:Q,sheen:q,sheenColorMap:tt,sheenRoughnessMap:et,specularMap:nt,specularColorMap:it,specularIntensityMap:rt,transmission:Y,transmissionMap:st,thicknessMap:at,gradientMap:ot,opaque:!1===s.transparent&&1===s.blending,alphaMap:lt,alphaTest:ct,combine:s.combine,mapUv:D&&g(s.map.channel),aoMapUv:F&&g(s.aoMap.channel),lightMapUv:B&&g(s.lightMap.channel),bumpMapUv:z&&g(s.bumpMap.channel),normalMapUv:G&&g(s.normalMap.channel),displacementMapUv:H&&g(s.displacementMap.channel),emissiveMapUv:k&&g(s.emissiveMap.channel),metalnessMapUv:V&&g(s.metalnessMap.channel),roughnessMapUv:W&&g(s.roughnessMap.channel),clearcoatMapUv:Z&&g(s.clearcoatMap.channel),clearcoatNormalMapUv:J&&g(s.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:K&&g(s.clearcoatRoughnessMap.channel),iridescenceMapUv:$&&g(s.iridescenceMap.channel),iridescenceThicknessMapUv:Q&&g(s.iridescenceThicknessMap.channel),sheenColorMapUv:tt&&g(s.sheenColorMap.channel),sheenRoughnessMapUv:et&&g(s.sheenRoughnessMap.channel),specularMapUv:nt&&g(s.specularMap.channel),specularColorMapUv:it&&g(s.specularColorMap.channel),specularIntensityMapUv:rt&&g(s.specularIntensityMap.channel),transmissionMapUv:st&&g(s.transmissionMap.channel),thicknessMapUv:at&&g(s.thicknessMap.channel),alphaMapUv:lt&&g(s.alphaMap.channel),vertexTangents:G&&!!y.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!y.attributes.color&&4===y.attributes.color.itemSize,vertexUv1s:ut,vertexUv2s:dt,vertexUv3s:mt,pointsUvs:!0===_.isPoints&&!!y.attributes.uv&&(D||lt),fog:!!x,useFog:!0===s.fog,fogExp2:x&&x.isFogExp2,flatShading:!0===s.flatShading,sizeAttenuation:!0===s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===_.isSkinnedMesh,morphTargets:void 0!==y.morphAttributes.position,morphNormals:void 0!==y.morphAttributes.normal,morphColors:void 0!==y.morphAttributes.color,morphTargetsCount:w,morphTextureStride:P,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,useLegacyLights:t.useLegacyLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,useDepthPacking:s.depthPacking>=0,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:ht&&!0===s.extensions.derivatives,extensionFragDepth:ht&&!0===s.extensions.fragDepth,extensionDrawBuffers:ht&&!0===s.extensions.drawBuffers,extensionShaderTextureLOD:ht&&!0===s.extensions.shaderTextureLOD,rendererExtensionFragDepth:u||i.has("EXT_frag_depth"),rendererExtensionDrawBuffers:u||i.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:u||i.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputColorSpace),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.mapUv),t.push(e.alphaMapUv),t.push(e.lightMapUv),t.push(e.aoMapUv),t.push(e.bumpMapUv),t.push(e.normalMapUv),t.push(e.displacementMapUv),t.push(e.emissiveMapUv),t.push(e.metalnessMapUv),t.push(e.roughnessMapUv),t.push(e.clearcoatMapUv),t.push(e.clearcoatNormalMapUv),t.push(e.clearcoatRoughnessMapUv),t.push(e.iridescenceMapUv),t.push(e.iridescenceThicknessMapUv),t.push(e.sheenColorMapUv),t.push(e.sheenRoughnessMapUv),t.push(e.specularMapUv),t.push(e.specularColorMapUv),t.push(e.specularIntensityMapUv),t.push(e.transmissionMapUv),t.push(e.thicknessMapUv),t.push(e.combine),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(n,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.matcap&&o.enable(4);e.envMap&&o.enable(5);e.normalMapObjectSpace&&o.enable(6);e.normalMapTangentSpace&&o.enable(7);e.clearcoat&&o.enable(8);e.iridescence&&o.enable(9);e.alphaTest&&o.enable(10);e.vertexColors&&o.enable(11);e.vertexAlphas&&o.enable(12);e.vertexUv1s&&o.enable(13);e.vertexUv2s&&o.enable(14);e.vertexUv3s&&o.enable(15);e.vertexTangents&&o.enable(16);t.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.skinning&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.morphColors&&o.enable(7);e.premultipliedAlpha&&o.enable(8);e.shadowMapEnabled&&o.enable(9);e.useLegacyLights&&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);t.push(o.mask)}(n,e),n.push(t.outputColorSpace)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=f[t.type];let n;if(e){const t=zi[e];n=xi.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=h.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||ks),i.length>1&&i.sort(e||Vs),r.length>1&&r.sort(e||Vs)}}}function Xs(){let t=new WeakMap;return{get:function(e,n){const i=t.get(e);let r;return void 0===i?(r=new Ws,t.set(e,[r])):n>=i.length?(r=new Ws,i.push(r)):r=i[n],r},dispose:function(){t=new WeakMap}}}function js(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new oe,color:new Rn};break;case"SpotLight":n={position:new oe,direction:new oe,color:new Rn,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new oe,color:new Rn,distance:0,decay:0};break;case"HemisphereLight":n={direction:new oe,skyColor:new Rn,groundColor:new Rn};break;case"RectAreaLight":n={color:new Rn,position:new oe,halfWidth:new oe,halfHeight:new oe}}return t[e.id]=n,n}}}let qs=0;function Ys(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function Zs(t,e){const n=new js,i=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Dt};break;case"PointLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Dt,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let t=0;t<9;t++)r.probe.push(new oe);const s=new oe,a=new Fe,o=new Fe;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,_=0,x=0;s.sort(Ys);const y=!0===a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=Bi.LTC_FLOAT_1,r.rectAreaLTC2=Bi.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=Bi.LTC_HALF_1,r.rectAreaLTC2=Bi.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const M=r.hash;M.directionalLength===h&&M.pointLength===u&&M.spotLength===d&&M.rectAreaLength===p&&M.hemiLength===m&&M.numDirectionalShadows===f&&M.numPointShadows===g&&M.numSpotShadows===v&&M.numSpotMaps===_||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=v+_-x,r.spotLightMap.length=_,r.numSpotLightShadowsWithMaps=x,M.directionalLength=h,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=m,M.numDirectionalShadows=f,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=_,r.version=qs++)},setupView:function(t,e){let n=0,i=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=s.length?(a=new Js(t,e),s.push(a)):a=s[r],a},dispose:function(){n=new WeakMap}}}class $s extends bn{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Qs extends bn{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function ta(t,e,n){let i=new Ui;const r=new Dt,s=new Dt,a=new ne,o=new $s({depthPacking:3201}),l=new Qs,c={},h=n.maxTextureSize,u={0:1,1:0,2:2},p=new yi({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Dt},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=p.clone();m.defines.HORIZONTAL_PASS=1;const f=new Zn;f.setAttribute("position",new Bn(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new pi(f,p),v=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=1;let _=this.type;function x(n,i){const s=e.update(g);p.defines.VSM_SAMPLES!==n.blurSamples&&(p.defines.VSM_SAMPLES=n.blurSamples,m.defines.VSM_SAMPLES=n.blurSamples,p.needsUpdate=!0,m.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new ie(r.x,r.y)),p.uniforms.shadow_pass.value=n.map.texture,p.uniforms.resolution.value=n.mapSize,p.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,s,p,g,null),m.uniforms.shadow_pass.value=n.mapPass.texture,m.uniforms.resolution.value=n.mapSize,m.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,s,m,g,null)}function y(e,n,i,r){let s=null;const a=!0===i.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==a)s=a;else if(s=!0===i.isPointLight?l:o,t.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const t=s.uuid,e=n.uuid;let i=c[t];void 0===i&&(i={},c[t]=i);let r=i[e];void 0===r&&(r=s.clone(),i[e]=r),s=r}if(s.visible=n.visible,s.wireframe=n.wireframe,s.side=3===r?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:u[n.side],s.alphaMap=n.alphaMap,s.alphaTest=n.alphaTest,s.map=n.map,s.clipShadows=n.clipShadows,s.clippingPlanes=n.clippingPlanes,s.clipIntersection=n.clipIntersection,s.displacementMap=n.displacementMap,s.displacementScale=n.displacementScale,s.displacementBias=n.displacementBias,s.wireframeLinewidth=n.wireframeLinewidth,s.linewidth=n.linewidth,!0===i.isPointLight&&!0===s.isMeshDistanceMaterial){t.properties.get(s).light=i}return s}function M(n,r,s,a,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),r=n.material;if(Array.isArray(r)){const e=i.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/g.x),r.x=s.x*g.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/g.y),r.y=s.y*g.y,u.mapSize.y=s.y)),null===u.map||!0===m||!0===f){const t=3!==this.type?{minFilter:d,magFilter:d}:{};null!==u.map&&u.map.dispose(),u.map=new ie(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const v=u.getViewportCount();for(let t=0;t=1):-1!==I.indexOf("OpenGL ES")&&(P=parseFloat(/^OpenGL ES (\d)/.exec(I)[1]),L=P>=2);let U=null,D={};const N=t.getParameter(t.SCISSOR_BOX),O=t.getParameter(t.VIEWPORT),F=(new ne).fromArray(N),B=(new ne).fromArray(O);function z(e,n,i,s){const a=new Uint8Array(4),o=t.createTexture();t.bindTexture(e,o),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let o=0;oi||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const i=e?Lt:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===U&&(U=O(s,a));const o=n?O(s,a):U;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function B(t){return Rt(t.width)&&Rt(t.height)}function z(t,e){return t.generateMipmaps&&e&&t.minFilter!==d&&t.minFilter!==f}function G(e){t.generateMipmap(e)}function H(n,i,r,s,a=!1){if(!1===o)return i;if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let l=i;return i===t.RED&&(r===t.FLOAT&&(l=t.R32F),r===t.HALF_FLOAT&&(l=t.R16F),r===t.UNSIGNED_BYTE&&(l=t.R8)),i===t.RG&&(r===t.FLOAT&&(l=t.RG32F),r===t.HALF_FLOAT&&(l=t.RG16F),r===t.UNSIGNED_BYTE&&(l=t.RG8)),i===t.RGBA&&(r===t.FLOAT&&(l=t.RGBA32F),r===t.HALF_FLOAT&&(l=t.RGBA16F),r===t.UNSIGNED_BYTE&&(l=s===dt&&!1===a?t.SRGB8_ALPHA8:t.RGBA8),r===t.UNSIGNED_SHORT_4_4_4_4&&(l=t.RGBA4),r===t.UNSIGNED_SHORT_5_5_5_1&&(l=t.RGB5_A1)),l!==t.R16F&&l!==t.R32F&&l!==t.RG16F&&l!==t.RG32F&&l!==t.RGBA16F&&l!==t.RGBA32F||e.get("EXT_color_buffer_float"),l}function k(t,e,n){return!0===z(t,n)||t.isFramebufferTexture&&t.minFilter!==d&&t.minFilter!==f?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function V(e){return e===d||e===p||e===m?t.NEAREST:t.LINEAR}function W(t){const e=t.target;e.removeEventListener("dispose",W),function(t){const e=i.get(t);if(void 0===e.__webglInit)return;const n=t.source,r=D.get(n);if(r){const i=r[e.__cacheKey];i.usedTimes--,0===i.usedTimes&&j(t),0===Object.keys(r).length&&D.delete(n)}i.remove(t)}(e),e.isVideoTexture&&I.delete(e)}function X(e){const n=e.target;n.removeEventListener("dispose",X),function(e){const n=e.texture,r=i.get(e),s=i.get(n);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e0&&s.__version!==e.version){const t=e.image;if(null===t)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==t.complete)return void Q(s,e,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(t.TEXTURE_2D,s.__webglTexture,t.TEXTURE0+r)}const Z={[c]:t.REPEAT,[h]:t.CLAMP_TO_EDGE,[u]:t.MIRRORED_REPEAT},J={[d]:t.NEAREST,[p]:t.NEAREST_MIPMAP_NEAREST,[m]:t.NEAREST_MIPMAP_LINEAR,[f]:t.LINEAR,[g]:t.LINEAR_MIPMAP_NEAREST,[v]:t.LINEAR_MIPMAP_LINEAR};function K(n,s,a){if(a?(t.texParameteri(n,t.TEXTURE_WRAP_S,Z[s.wrapS]),t.texParameteri(n,t.TEXTURE_WRAP_T,Z[s.wrapT]),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,Z[s.wrapR]),t.texParameteri(n,t.TEXTURE_MAG_FILTER,J[s.magFilter]),t.texParameteri(n,t.TEXTURE_MIN_FILTER,J[s.minFilter])):(t.texParameteri(n,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(n,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),s.wrapS===h&&s.wrapT===h||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(n,t.TEXTURE_MAG_FILTER,V(s.magFilter)),t.texParameteri(n,t.TEXTURE_MIN_FILTER,V(s.minFilter)),s.minFilter!==d&&s.minFilter!==f&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),!0===e.has("EXT_texture_filter_anisotropic")){const a=e.get("EXT_texture_filter_anisotropic");if(s.magFilter===d)return;if(s.minFilter!==m&&s.minFilter!==v)return;if(s.type===M&&!1===e.has("OES_texture_float_linear"))return;if(!1===o&&s.type===S&&!1===e.has("OES_texture_half_float_linear"))return;(s.anisotropy>1||i.get(s).__currentAnisotropy)&&(t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy)}}function $(e,n){let i=!1;void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",W));const r=n.source;let s=D.get(r);void 0===s&&(s={},D.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.colorSpace),e.join()}(n);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,i=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&j(n)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return i}function Q(e,r,a){let l=t.TEXTURE_2D;(r.isDataArrayTexture||r.isCompressedArrayTexture)&&(l=t.TEXTURE_2D_ARRAY),r.isData3DTexture&&(l=t.TEXTURE_3D);const c=$(e,r),u=r.source;n.bindTexture(l,e.__webglTexture,t.TEXTURE0+a);const p=i.get(u);if(u.version!==p.__version||!0===c){n.activeTexture(t.TEXTURE0+a),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,r.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,r.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,t.NONE);const e=function(t){return!o&&(t.wrapS!==h||t.wrapT!==h||t.minFilter!==d&&t.minFilter!==f)}(r)&&!1===B(r.image);let i=F(r.image,e,!1,R);i=st(r,i);const m=B(i)||o,g=s.convert(r.format,r.colorSpace);let v,_=s.convert(r.type),S=H(r.internalFormat,g,_,r.colorSpace);K(l,r,m);const A=r.mipmaps,C=o&&!0!==r.isVideoTexture,L=void 0===p.__version||!0===c,P=k(r,i,m);if(r.isDepthTexture)S=t.DEPTH_COMPONENT,o?S=r.type===M?t.DEPTH_COMPONENT32F:r.type===y?t.DEPTH_COMPONENT24:r.type===b?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT16:r.type===M&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),r.format===T&&S===t.DEPTH_COMPONENT&&r.type!==x&&r.type!==y&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=y,_=s.convert(r.type)),r.format===w&&S===t.DEPTH_COMPONENT&&(S=t.DEPTH_STENCIL,r.type!==b&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=b,_=s.convert(r.type))),L&&(C?n.texStorage2D(t.TEXTURE_2D,1,S,i.width,i.height):n.texImage2D(t.TEXTURE_2D,0,S,i.width,i.height,0,g,_,null));else if(r.isDataTexture)if(A.length>0&&m){C&&L&&n.texStorage2D(t.TEXTURE_2D,P,S,A[0].width,A[0].height);for(let e=0,i=A.length;e>=1,r>>=1}}else if(A.length>0&&m){C&&L&&n.texStorage2D(t.TEXTURE_2D,P,S,A[0].width,A[0].height);for(let e=0,i=A.length;e=t.TEXTURE_CUBE_MAP_POSITIVE_X&&l<=t.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&t.framebufferTexture2D(t.FRAMEBUFFER,o,l,i.get(a).__webglTexture,0),n.bindFramebuffer(t.FRAMEBUFFER,null)}function et(e,n,i){if(t.bindRenderbuffer(t.RENDERBUFFER,e),n.depthBuffer&&!n.stencilBuffer){let r=t.DEPTH_COMPONENT16;if(i||rt(n)){const e=n.depthTexture;e&&e.isDepthTexture&&(e.type===M?r=t.DEPTH_COMPONENT32F:e.type===y&&(r=t.DEPTH_COMPONENT24));const i=it(n);rt(n)?L.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,i,r,n.width,n.height):t.renderbufferStorageMultisample(t.RENDERBUFFER,i,r,n.width,n.height)}else t.renderbufferStorage(t.RENDERBUFFER,r,n.width,n.height);t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.RENDERBUFFER,e)}else if(n.depthBuffer&&n.stencilBuffer){const r=it(n);i&&!1===rt(n)?t.renderbufferStorageMultisample(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):rt(n)?L.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,n.width,n.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,e)}else{const e=!0===n.isWebGLMultipleRenderTargets?n.texture:[n.texture];for(let r=0;r0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function st(t,n){const i=t.colorSpace,r=t.format,s=t.type;return!0===t.isCompressedTexture||t.format===_t||i!==pt&&i!==ut&&(i===dt?!1===o?!0===e.has("EXT_sRGB")&&r===E?(t.format=_t,t.minFilter=f,t.generateMipmaps=!1):n=Kt.sRGBToLinear(n):r===E&&s===_||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",i)),n}this.allocateTextureUnit=function(){const t=q;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),q+=1,t},this.resetTextureUnits=function(){q=0},this.setTexture2D=Y,this.setTexture2DArray=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?Q(s,e,r):n.bindTexture(t.TEXTURE_2D_ARRAY,s.__webglTexture,t.TEXTURE0+r)},this.setTexture3D=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?Q(s,e,r):n.bindTexture(t.TEXTURE_3D,s.__webglTexture,t.TEXTURE0+r)},this.setTextureCube=function(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,r,a){if(6!==r.image.length)return;const l=$(e,r),c=r.source;n.bindTexture(t.TEXTURE_CUBE_MAP,e.__webglTexture,t.TEXTURE0+a);const h=i.get(c);if(c.version!==h.__version||!0===l){n.activeTexture(t.TEXTURE0+a),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,r.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,r.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,t.NONE);const e=r.isCompressedTexture||r.image[0].isCompressedTexture,i=r.image[0]&&r.image[0].isDataTexture,u=[];for(let t=0;t<6;t++)u[t]=e||i?i?r.image[t].image:r.image[t]:F(r.image[t],!1,!0,A),u[t]=st(r,u[t]);const d=u[0],p=B(d)||o,m=s.convert(r.format,r.colorSpace),f=s.convert(r.type),g=H(r.internalFormat,m,f,r.colorSpace),v=o&&!0!==r.isVideoTexture,_=void 0===h.__version||!0===l;let x,y=k(r,d,p);if(K(t.TEXTURE_CUBE_MAP,r,p),e){v&&_&&n.texStorage2D(t.TEXTURE_CUBE_MAP,y,g,d.width,d.height);for(let e=0;e<6;e++){x=u[e].mipmaps;for(let i=0;i0&&y++,n.texStorage2D(t.TEXTURE_CUBE_MAP,y,g,u[0].width,u[0].height));for(let e=0;e<6;e++)if(i){v?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,u[e].width,u[e].height,m,f,u[e].data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,g,u[e].width,u[e].height,0,m,f,u[e].data);for(let i=0;i0&&!1===rt(e)){const i=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],n.bindFramebuffer(t.FRAMEBUFFER,c.__webglMultisampledFramebuffer);for(let n=0;n0&&!1===rt(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=t.COLOR_BUFFER_BIT;const l=[],c=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,h=i.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&&(i=e.getPose(t.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(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(aa)))}return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const n=new sa;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class la extends ee{constructor(t,e,n,i,r,s,a,o,l,c){if((c=void 0!==c?c:T)!==T&&c!==w)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===n&&c===T&&(n=y),void 0===n&&c===w&&(n=b),super(null,i,r,s,a,o,c,n,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:d,this.minFilter=void 0!==o?o:d,this.flipY=!1,this.generateMipmaps=!1}}class ca extends xt{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=e.getContextAttributes();let f=null,g=null;const v=[],x=[],M=new Set,S=new Map,A=new Si;A.layers.enable(1),A.viewport=new ne;const R=new Si;R.layers.enable(2),R.viewport=new ne;const C=[A,R],L=new ra;L.layers.enable(1),L.layers.enable(2);let P=null,I=null;function U(t){const e=x.indexOf(t.inputSource);if(-1===e)return;const n=v[e];void 0!==n&&(n.update(t.inputSource,t.frame,l||s),n.dispatchEvent({type:t.type,data:t.inputSource}))}function D(){i.removeEventListener("select",U),i.removeEventListener("selectstart",U),i.removeEventListener("selectend",U),i.removeEventListener("squeeze",U),i.removeEventListener("squeezestart",U),i.removeEventListener("squeezeend",U),i.removeEventListener("end",D),i.removeEventListener("inputsourceschange",N);for(let t=0;t=0&&(x[i]=null,v[i].disconnect(n))}for(let e=0;e=x.length){x.push(n),i=t;break}if(null===x[t]){x[t]=n,i=t;break}}if(-1===i)break}const r=v[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(t){let e=v[t];return void 0===e&&(e=new oa,v[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=v[t];return void 0===e&&(e=new oa,v[t]=e),e.getGripSpace()},this.getHand=function(t){let e=v[t];return void 0===e&&(e=new oa,v[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){a=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(f=t.getRenderTarget(),i.addEventListener("select",U),i.addEventListener("selectstart",U),i.addEventListener("selectend",U),i.addEventListener("squeeze",U),i.addEventListener("squeezestart",U),i.addEventListener("squeezeend",U),i.addEventListener("end",D),i.addEventListener("inputsourceschange",N),!0!==m.xrCompatible&&await e.makeXRCompatible(),void 0===i.renderState.layers||!1===t.capabilities.isWebGL2){const n={antialias:void 0!==i.renderState.layers||m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,e,n),i.updateRenderState({baseLayer:d}),g=new ie(d.framebufferWidth,d.framebufferHeight,{format:E,type:_,colorSpace:t.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,s=null,a=null;m.depth&&(a=m.stencil?e.DEPTH24_STENCIL8:e.DEPTH_COMPONENT24,n=m.stencil?w:T,s=m.stencil?b:y);const o={colorFormat:e.RGBA8,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(i,e),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),g=new ie(u.textureWidth,u.textureHeight,{format:E,type:_,depthTexture:new la(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:t.outputColorSpace,samples:m.antialias?4:0});t.properties.get(g).__ignoreDepthValues=u.ignoreDepthValues}g.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await i.requestReferenceSpace(a),G.setContext(i),G.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode};const O=new oe,F=new oe;function B(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCamera=function(t){if(null===i)return;L.near=R.near=A.near=t.near,L.far=R.far=A.far=t.far,P===L.near&&I===L.far||(i.updateRenderState({depthNear:L.near,depthFar:L.far}),P=L.near,I=L.far);const e=t.parent,n=L.cameras;B(L,e);for(let t=0;te&&(S.set(t,t.lastChangedTime),n.dispatchEvent({type:"planechanged",data:t}))}else M.add(t),S.set(t,i.lastChangedTime),n.dispatchEvent({type:"planeadded",data:t})}p=null})),this.setAnimationLoop=function(t){z=t},this.dispose=function(){}}}function ha(t,e){function n(t,e){!0===t.matrixAutoUpdate&&t.updateMatrix(),e.value.copy(t.matrix)}function i(i,r){i.opacity.value=r.opacity,r.color&&i.diffuse.value.copy(r.color),r.emissive&&i.emissive.value.copy(r.emissive).multiplyScalar(r.emissiveIntensity),r.map&&(i.map.value=r.map,n(r.map,i.mapTransform)),r.alphaMap&&(i.alphaMap.value=r.alphaMap,n(r.alphaMap,i.alphaMapTransform)),r.bumpMap&&(i.bumpMap.value=r.bumpMap,n(r.bumpMap,i.bumpMapTransform),i.bumpScale.value=r.bumpScale,1===r.side&&(i.bumpScale.value*=-1)),r.normalMap&&(i.normalMap.value=r.normalMap,n(r.normalMap,i.normalMapTransform),i.normalScale.value.copy(r.normalScale),1===r.side&&i.normalScale.value.negate()),r.displacementMap&&(i.displacementMap.value=r.displacementMap,n(r.displacementMap,i.displacementMapTransform),i.displacementScale.value=r.displacementScale,i.displacementBias.value=r.displacementBias),r.emissiveMap&&(i.emissiveMap.value=r.emissiveMap,n(r.emissiveMap,i.emissiveMapTransform)),r.specularMap&&(i.specularMap.value=r.specularMap,n(r.specularMap,i.specularMapTransform)),r.alphaTest>0&&(i.alphaTest.value=r.alphaTest);const s=e.get(r).envMap;if(s&&(i.envMap.value=s,i.flipEnvMap.value=s.isCubeTexture&&!1===s.isRenderTargetTexture?-1:1,i.reflectivity.value=r.reflectivity,i.ior.value=r.ior,i.refractionRatio.value=r.refractionRatio),r.lightMap){i.lightMap.value=r.lightMap;const e=!0===t.useLegacyLights?Math.PI:1;i.lightMapIntensity.value=r.lightMapIntensity*e,n(r.lightMap,i.lightMapTransform)}r.aoMap&&(i.aoMap.value=r.aoMap,i.aoMapIntensity.value=r.aoMapIntensity,n(r.aoMap,i.aoMapTransform))}return{refreshFogUniforms:function(e,n){n.color.getRGB(e.fogColor.value,_i(t)),n.isFog?(e.fogNear.value=n.near,e.fogFar.value=n.far):n.isFogExp2&&(e.fogDensity.value=n.density)},refreshMaterialUniforms:function(t,r,s,a,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(t,r):r.isMeshToonMaterial?(i(t,r),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,r)):r.isMeshPhongMaterial?(i(t,r),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,r)):r.isMeshStandardMaterial?(i(t,r),function(t,i){t.metalness.value=i.metalness,i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap,n(i.metalnessMap,t.metalnessMapTransform));t.roughness.value=i.roughness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap,n(i.roughnessMap,t.roughnessMapTransform));const r=e.get(i).envMap;r&&(t.envMapIntensity.value=i.envMapIntensity)}(t,r),r.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap,n(e.sheenColorMap,t.sheenColorMapTransform)),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap,n(e.sheenRoughnessMap,t.sheenRoughnessMapTransform)));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap,n(e.clearcoatMap,t.clearcoatMapTransform)),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap,n(e.clearcoatRoughnessMap,t.clearcoatRoughnessMapTransform)),e.clearcoatNormalMap&&(t.clearcoatNormalMap.value=e.clearcoatNormalMap,n(e.clearcoatNormalMap,t.clearcoatNormalMapTransform),t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),1===e.side&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap,n(e.iridescenceMap,t.iridescenceMapTransform)),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap,n(e.iridescenceThicknessMap,t.iridescenceThicknessMapTransform)));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap,n(e.transmissionMap,t.transmissionMapTransform)),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap,n(e.thicknessMap,t.thicknessMapTransform)),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap,n(e.specularColorMap,t.specularColorMapTransform));e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap,n(e.specularIntensityMap,t.specularIntensityMapTransform))}(t,r,o)):r.isMeshMatcapMaterial?(i(t,r),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,r)):r.isMeshDepthMaterial?i(t,r):r.isMeshDistanceMaterial?(i(t,r),function(t,n){const i=e.get(n).light;t.referencePosition.value.setFromMatrixPosition(i.matrixWorld),t.nearDistance.value=i.shadow.camera.near,t.farDistance.value=i.shadow.camera.far}(t,r)):r.isMeshNormalMaterial?i(t,r):r.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform))}(t,r),r.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,r)):r.isPointsMaterial?function(t,e,i,r){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*r,e.map&&(t.map.value=e.map,n(e.map,t.uvTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r,s,a):r.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r):r.isShadowMaterial?(t.color.value.copy(r.color),t.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function ua(t,e,n,i){let r={},s={},a=[];const o=n.isWebGL2?t.getParameter(t.MAX_UNIFORM_BUFFER_BINDINGS):0;function l(t,e,n){const i=t.value;if(void 0===n[e]){if("number"==typeof i)n[e]=i;else{const t=Array.isArray(i)?i:[i],r=[];for(let e=0;e0){r=n%i;0!==r&&i-r-a.boundary<0&&(n+=i-r,s.__offset=n)}n+=a.storage}r=n%i,r>0&&(n+=i-r);t.__size=n,t.__cache={}}(n),d=function(e){const n=function(){for(let t=0;t0&&function(t,e,n,i){if(null===V){const t=Z.isWebGL2;V=new ie(1024,1024,{generateMipmaps:!0,type:Y.has("EXT_color_buffer_half_float")?S:_,minFilter:v,samples:t&&!0===o?4:0})}const r=x.getRenderTarget();x.setRenderTarget(V),x.clear();const s=x.toneMapping;x.toneMapping=0,Dt(t,n,i),Q.updateMultisampleRenderTarget(V),Q.updateRenderTargetMipmap(V);let a=!1;for(let t=0,r=e.length;t0&&Dt(r,e,n),s.length>0&&Dt(s,e,n),a.length>0&&Dt(a,e,n),J.buffers.depth.setTest(!0),J.buffers.depth.setMask(!0),J.buffers.color.setMask(!0),J.setPolygonOffset(!1)}function Dt(t,e,n){const i=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?g[g.length-1]:null,f.pop(),p=f.length>0?f[f.length-1]:null},this.getActiveCubeFace=function(){return b},this.getActiveMipmapLevel=function(){return T},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(t,e,n){$.get(t.texture).__webglTexture=e,$.get(t.depthTexture).__webglTexture=n;const i=$.get(t);i.__hasExternalTextures=!0,i.__hasExternalTextures&&(i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===Y.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const n=$.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){w=t,b=e,T=n;let i=!0,r=null,s=!1,a=!1;if(t){const n=$.get(t);void 0!==n.__useDefaultFramebuffer?(J.bindFramebuffer(yt.FRAMEBUFFER,null),i=!1):void 0===n.__webglFramebuffer?Q.setupRenderTarget(t):n.__hasExternalTextures&&Q.rebindTextures(t,$.get(t.texture).__webglTexture,$.get(t.depthTexture).__webglTexture);const o=t.texture;(o.isData3DTexture||o.isDataArrayTexture||o.isCompressedArrayTexture)&&(a=!0);const l=$.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=l[e],s=!0):r=Z.isWebGL2&&t.samples>0&&!1===Q.useMultisampledRTT(t)?$.get(t).__webglMultisampledFramebuffer:l,C.copy(t.viewport),L.copy(t.scissor),P=t.scissorTest}else C.copy(F).multiplyScalar(D).floor(),L.copy(B).multiplyScalar(D).floor(),P=z;if(J.bindFramebuffer(yt.FRAMEBUFFER,r)&&Z.drawBuffers&&i&&J.drawBuffers(t,r),J.viewport(C),J.scissor(L),J.setScissorTest(P),s){const i=$.get(t.texture);yt.framebufferTexture2D(yt.FRAMEBUFFER,yt.COLOR_ATTACHMENT0,yt.TEXTURE_CUBE_MAP_POSITIVE_X+e,i.__webglTexture,n)}else if(a){const i=$.get(t.texture),r=e||0;yt.framebufferTextureLayer(yt.FRAMEBUFFER,yt.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}A=-1},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=$.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){J.bindFramebuffer(yt.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==E&&vt.convert(o)!==yt.getParameter(yt.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===S&&(Y.has("EXT_color_buffer_half_float")||Z.isWebGL2&&Y.has("EXT_color_buffer_float"));if(!(l===_||vt.convert(l)===yt.getParameter(yt.IMPLEMENTATION_COLOR_READ_TYPE)||l===M&&(Z.isWebGL2||Y.has("OES_texture_float")||Y.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&yt.readPixels(e,n,i,r,vt.convert(o),vt.convert(l),s)}finally{const t=null!==w?$.get(w).__webglFramebuffer:null;J.bindFramebuffer(yt.FRAMEBUFFER,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i);Q.setTexture2D(e,0),yt.copyTexSubImage2D(yt.TEXTURE_2D,n,0,0,t.x,t.y,r,s),J.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=vt.convert(n.format),o=vt.convert(n.type);Q.setTexture2D(n,0),yt.pixelStorei(yt.UNPACK_FLIP_Y_WEBGL,n.flipY),yt.pixelStorei(yt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),yt.pixelStorei(yt.UNPACK_ALIGNMENT,n.unpackAlignment),e.isDataTexture?yt.texSubImage2D(yt.TEXTURE_2D,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?yt.compressedTexSubImage2D(yt.TEXTURE_2D,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):yt.texSubImage2D(yt.TEXTURE_2D,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&&yt.generateMipmap(yt.TEXTURE_2D),J.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(x.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=vt.convert(i.format),c=vt.convert(i.type);let h;if(i.isData3DTexture)Q.setTexture3D(i,0),h=yt.TEXTURE_3D;else{if(!i.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");Q.setTexture2DArray(i,0),h=yt.TEXTURE_2D_ARRAY}yt.pixelStorei(yt.UNPACK_FLIP_Y_WEBGL,i.flipY),yt.pixelStorei(yt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,i.premultiplyAlpha),yt.pixelStorei(yt.UNPACK_ALIGNMENT,i.unpackAlignment);const u=yt.getParameter(yt.UNPACK_ROW_LENGTH),d=yt.getParameter(yt.UNPACK_IMAGE_HEIGHT),p=yt.getParameter(yt.UNPACK_SKIP_PIXELS),m=yt.getParameter(yt.UNPACK_SKIP_ROWS),f=yt.getParameter(yt.UNPACK_SKIP_IMAGES),g=n.isCompressedTexture?n.mipmaps[0]:n.image;yt.pixelStorei(yt.UNPACK_ROW_LENGTH,g.width),yt.pixelStorei(yt.UNPACK_IMAGE_HEIGHT,g.height),yt.pixelStorei(yt.UNPACK_SKIP_PIXELS,t.min.x),yt.pixelStorei(yt.UNPACK_SKIP_ROWS,t.min.y),yt.pixelStorei(yt.UNPACK_SKIP_IMAGES,t.min.z),n.isDataTexture||n.isData3DTexture?yt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g.data):n.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),yt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,g.data)):yt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g),yt.pixelStorei(yt.UNPACK_ROW_LENGTH,u),yt.pixelStorei(yt.UNPACK_IMAGE_HEIGHT,d),yt.pixelStorei(yt.UNPACK_SKIP_PIXELS,p),yt.pixelStorei(yt.UNPACK_SKIP_ROWS,m),yt.pixelStorei(yt.UNPACK_SKIP_IMAGES,f),0===r&&i.generateMipmaps&&yt.generateMipmap(h),J.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?Q.setTextureCube(t,0):t.isData3DTexture?Q.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?Q.setTexture2DArray(t,0):Q.setTexture2D(t,0),J.unbindTexture()},this.resetState=function(){b=0,T=0,w=null,J.reset(),_t.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get physicallyCorrectLights(){return console.warn("THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),!this.useLegacyLights}set physicallyCorrectLights(t){console.warn("THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),this.useLegacyLights=!t}get outputEncoding(){return console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace===dt?ht:ct}set outputEncoding(t){console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace=t===ht?dt:pt}}class ma extends pa{}ma.prototype.isWebGL1Renderer=!0;class fa{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new Rn(t),this.density=e}clone(){return new fa(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class ga{constructor(t,e=1,n=1e3){this.isFog=!0,this.name="",this.color=new Rn(t),this.near=e,this.far=n}clone(){return new ga(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class va extends cn{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e}get autoUpdate(){return console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate}set autoUpdate(t){console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate=t}}class _a{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=gt,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=Et()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:ba.clone(),uv:Mn.getInterpolation(ba,Ca,La,Pa,Ia,Ua,Da,new Dt),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function Oa(t,e,n,i,r,s){wa.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(Aa.x=s*wa.x-r*wa.y,Aa.y=r*wa.x+s*wa.y):Aa.copy(wa),t.copy(e),t.x+=Aa.x,t.y+=Aa.y,t.applyMatrix4(Ra)}const Fa=new oe,Ba=new oe;class za extends cn{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){Fa.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(Fa);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Fa.setFromMatrixPosition(t.matrixWorld),Ba.setFromMatrixPosition(this.matrixWorld);const n=Fa.distanceTo(Ba)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;io)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}else{for(let n=Math.max(0,s.start),i=Math.min(m.count,s.start+s.count)-1;no)continue;u.applyMatrix4(this.matrixWorld);const i=t.ray.origin.distanceTo(u);it.far||e.push({distance:i,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}class wo extends ee{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Ao{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new Dt:new oe);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new oe,i=[],r=[],s=[],a=new oe,o=new Fe;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new oe)}r[0]=new oe,s[0]=new oe;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(Tt(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Tt(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Ro extends Ao{constructor(t=0,e=0,n=1,i=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const n=e||new Dt,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=i[(l-1)%r]:(Po.subVectors(i[0],i[1]).add(i[0]),a=Po);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(Oo(a,o.x,l.x,c.x,h.x),Oo(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class Zo extends Zn{constructor(t=[new Dt(0,-.5),new Dt(.5,0),new Dt(0,.5)],e=12,n=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:n,phiLength:i},e=Math.floor(e),i=Tt(i,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new oe,u=new Dt,d=new oe,p=new oe,m=new oe;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=n+r*c*i,p=Math.sin(d),m=Math.cos(d);for(let n=0;n<=t.length-1;n++){h.x=t[n].x*p,h.y=t[n].y,h.z=t[n].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=n/(t.length-1),a.push(u.x,u.y);const i=o[3*n+0]*p,c=o[3*n+1],d=o[3*n+0]*m;l.push(i,c,d)}}for(let n=0;n0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new Hn(h,3)),this.setAttribute("normal",new Hn(u,3)),this.setAttribute("uv",new Hn(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new $o(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Qo extends $o{constructor(t=1,e=1,n=32,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new Qo(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class tl extends Zn{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new Hn(r,3)),this.setAttribute("normal",new Hn(r.slice(),3)),this.setAttribute("uv",new Hn(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new tl(t.vertices,t.indices,t.radius,t.details)}}class el extends tl{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new el(t.radius,t.detail)}}const nl=new oe,il=new oe,rl=new oe,sl=new Mn;class al extends Zn{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(St*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return ul(s,a,n,o,l,p,0),a};function cl(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=Ll(s,t[s],t[s+1],a);return a&&El(a,a.next)&&(Pl(a),a=a.next),a}function hl(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!El(i,i.next)&&0!==bl(i.prev,i,i.next))i=i.next;else{if(Pl(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function ul(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{0===r.z&&(r.z=xl(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?pl(t,i,r,s):dl(t))e.push(o.i/n|0),e.push(t.i/n|0),e.push(l.i/n|0),Pl(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?ul(t=ml(hl(t),e,n),e,n,i,r,s,2):2===a&&fl(t,e,n,i,r,s):ul(hl(t),e,n,i,r,s,1);break}}function dl(t){const e=t.prev,n=t,i=t.next;if(bl(e,n,i)>=0)return!1;const r=e.x,s=n.x,a=i.x,o=e.y,l=n.y,c=i.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=i.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&Ml(r,o,s,l,a,c,m.x,m.y)&&bl(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function pl(t,e,n,i){const r=t.prev,s=t,a=t.next;if(bl(r,s,a)>=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=ol?o>c?o:c:l>c?l:c,g=h>u?h>d?h:d:u>d?u:d,v=xl(p,m,e,n,i),_=xl(f,g,e,n,i);let x=t.prevZ,y=t.nextZ;for(;x&&x.z>=v&&y&&y.z<=_;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Ml(o,h,l,u,c,d,x.x,x.y)&&bl(x.prev,x,x.next)>=0)return!1;if(x=x.prevZ,y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Ml(o,h,l,u,c,d,y.x,y.y)&&bl(y.prev,y,y.next)>=0)return!1;y=y.nextZ}for(;x&&x.z>=v;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Ml(o,h,l,u,c,d,x.x,x.y)&&bl(x.prev,x,x.next)>=0)return!1;x=x.prevZ}for(;y&&y.z<=_;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Ml(o,h,l,u,c,d,y.x,y.y)&&bl(y.prev,y,y.next)>=0)return!1;y=y.nextZ}return!0}function ml(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!El(r,s)&&Tl(r,i,i.next,s)&&Rl(r,s)&&Rl(s,r)&&(e.push(r.i/n|0),e.push(i.i/n|0),e.push(s.i/n|0),Pl(i),Pl(i.next),i=t=s),i=i.next}while(i!==t);return hl(i)}function fl(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&Sl(a,t)){let o=Cl(a,t);return a=hl(a,a.next),o=hl(o,o.next),ul(a,e,n,i,r,s,0),void ul(o,e,n,i,r,s,0)}t=t.next}a=a.next}while(a!==t)}function gl(t,e){return t.x-e.x}function vl(t,e){const n=function(t,e){let n,i=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){const t=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=s&&t>r&&(r=t,n=i.x=i.x&&i.x>=l&&s!==i.x&&Ml(an.x||i.x===n.x&&_l(n,i)))&&(n=i,u=h)),i=i.next}while(i!==o);return n}(t,e);if(!n)return e;const i=Cl(n,t);return hl(i,i.next),hl(n,n.next)}function _l(t,e){return bl(t.prev,t,e.prev)<0&&bl(e.next,t,t.next)<0}function xl(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-n)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function yl(t){let e=t,n=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(i-o)>=(n-a)*(e-o)&&(n-a)*(s-o)>=(r-a)*(i-o)}function Sl(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&Tl(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(Rl(t,e)&&Rl(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(bl(t.prev,t,e.prev)||bl(t,e.prev,e))||El(t,e)&&bl(t.prev,t,t.next)>0&&bl(e.prev,e,e.next)>0)}function bl(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function El(t,e){return t.x===e.x&&t.y===e.y}function Tl(t,e,n,i){const r=Al(bl(t,e,n)),s=Al(bl(t,e,i)),a=Al(bl(n,i,t)),o=Al(bl(n,i,e));return r!==s&&a!==o||(!(0!==r||!wl(t,n,e))||(!(0!==s||!wl(t,i,e))||(!(0!==a||!wl(n,t,i))||!(0!==o||!wl(n,e,i)))))}function wl(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function Al(t){return t>0?1:t<0?-1:0}function Rl(t,e){return bl(t.prev,t,t.next)<0?bl(t,e,t.next)>=0&&bl(t,t.prev,e)>=0:bl(t,e,t.prev)<0||bl(t,t.next,e)<0}function Cl(t,e){const n=new Il(t.i,t.x,t.y),i=new Il(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function Ll(t,e,n,i){const r=new Il(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function Pl(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function Il(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class Ul{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function Nl(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new Dt(i,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new Dt(i/s,r/s)}const P=[];for(let t=0,e=w.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=w.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class tc extends bn{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Rn(16777215),this.specular=new Rn(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Rn(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Dt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class ec extends bn{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Rn(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Rn(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Dt(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(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class nc extends bn{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Dt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class ic extends bn{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Rn(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Rn(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Dt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class rc extends bn{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Rn(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Dt(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class sc extends oo{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function ac(t,e,n){return lc(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)}function oc(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function lc(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function cc(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n}function hc(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r}function uc(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)}const dc={arraySlice:ac,convertArray:oc,isTypedArray:lc,getKeyframeOrder:cc,sortedArray:hc,flattenJSON:uc,subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=ac(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=ac(t.resultBuffer,e,n)}if("quaternion"===r){(new ae).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=ac(n,r,s),this.values=ac(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&lc(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=ac(this.times),e=ac(this.values),n=this.getValueSize(),i=this.getInterpolation()===it,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=ac(t,0,s),this.values=ac(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=ac(this.times,0),e=ac(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}vc.prototype.TimeBufferType=Float32Array,vc.prototype.ValueBufferType=Float32Array,vc.prototype.DefaultInterpolation=nt;class _c extends vc{}_c.prototype.ValueTypeName="bool",_c.prototype.ValueBufferType=Array,_c.prototype.DefaultInterpolation=et,_c.prototype.InterpolantFactoryMethodLinear=void 0,_c.prototype.InterpolantFactoryMethodSmooth=void 0;class xc extends vc{}xc.prototype.ValueTypeName="color";class yc extends vc{}yc.prototype.ValueTypeName="number";class Mc extends pc{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)ae.slerpFlat(r,0,s,l-a,s,l,o);return r}}class Sc extends vc{InterpolantFactoryMethodLinear(t){return new Mc(this.times,this.values,this.getValueSize(),t)}}Sc.prototype.ValueTypeName="quaternion",Sc.prototype.DefaultInterpolation=nt,Sc.prototype.InterpolantFactoryMethodSmooth=void 0;class bc extends vc{}bc.prototype.ValueTypeName="string",bc.prototype.ValueBufferType=Array,bc.prototype.DefaultInterpolation=et,bc.prototype.InterpolantFactoryMethodLinear=void 0,bc.prototype.InterpolantFactoryMethodSmooth=void 0;class Ec extends vc{}Ec.prototype.ValueTypeName="vector";class Tc{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=Et(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(wc(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(vc.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];uc(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==Pc[t])return void Pc[t].push({onLoad:e,onProgress:n,onError:i});Pc[t]=[],Pc[t].push({onLoad:e,onProgress:n,onError:i});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const n=Pc[t],i=e.body.getReader(),r=e.headers.get("Content-Length")||e.headers.get("X-File-Size"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),n=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(n);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{Ac.add(t,e);const n=Pc[t];delete Pc[t];for(let t=0,i=n.length;t{const n=Pc[t];if(void 0===n)throw this.manager.itemError(t),e;delete Pc[t];for(let t=0,i=n.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class Dc extends Lc{constructor(t){super(t)}load(t,e,n,i){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=Ac.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=Gt("img");function o(){c(),Ac.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),i&&i(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.slice(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class Nc extends cn{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new Rn(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&&(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(e.object.distance=this.distance),void 0!==this.angle&&(e.object.angle=this.angle),void 0!==this.decay&&(e.object.decay=this.decay),void 0!==this.penumbra&&(e.object.penumbra=this.penumbra),void 0!==this.shadow&&(e.object.shadow=this.shadow.toJSON()),e}}class Oc extends Nc{constructor(t,e,n){super(t,n),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(cn.DEFAULT_UP),this.updateMatrix(),this.groundColor=new Rn(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const Fc=new Fe,Bc=new oe,zc=new oe;class Gc{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new Dt(512,512),this.map=null,this.mapPass=null,this.matrix=new Fe,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Ui,this._frameExtents=new Dt(1,1),this._viewportCount=1,this._viewports=[new ne(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,n=this.matrix;Bc.setFromMatrixPosition(t.matrixWorld),e.position.copy(Bc),zc.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(zc),e.updateMatrixWorld(),Fc.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Fc),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(Fc)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&&(t.bias=this.bias),0!==this.normalBias&&(t.normalBias=this.normalBias),1!==this.radius&&(t.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class Hc extends Gc{constructor(){super(new Si(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,n=2*bt*t.angle*this.focus,i=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;n===e.fov&&i===e.aspect&&r===e.far||(e.fov=n,e.aspect=i,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class kc extends Nc{constructor(t,e,n=0,i=Math.PI/3,r=0,s=2){super(t,e),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(cn.DEFAULT_UP),this.updateMatrix(),this.target=new cn,this.distance=n,this.angle=i,this.penumbra=r,this.decay=s,this.map=null,this.shadow=new Hc}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const Vc=new Fe,Wc=new oe,Xc=new oe;class jc extends Gc{constructor(){super(new Si(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new Dt(4,2),this._viewportCount=6,this._viewports=[new ne(2,1,1,1),new ne(0,1,1,1),new ne(3,1,1,1),new ne(1,1,1,1),new ne(3,0,1,1),new ne(1,0,1,1)],this._cubeDirections=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],this._cubeUps=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)]}updateMatrices(t,e=0){const n=this.camera,i=this.matrix,r=t.distance||n.far;r!==n.far&&(n.far=r,n.updateProjectionMatrix()),Wc.setFromMatrixPosition(t.matrixWorld),n.position.copy(Wc),Xc.copy(n.position),Xc.add(this._cubeDirections[e]),n.up.copy(this._cubeUps[e]),n.lookAt(Xc),n.updateMatrixWorld(),i.makeTranslation(-Wc.x,-Wc.y,-Wc.z),Vc.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Vc)}}class qc extends Nc{constructor(t,e,n=0,i=2){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=n,this.decay=i,this.shadow=new jc}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class Yc extends Gc{constructor(){super(new qi(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Zc extends Nc{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(cn.DEFAULT_UP),this.updateMatrix(),this.target=new cn,this.shadow=new Yc}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class Jc extends Nc{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type="AmbientLight"}}class Kc extends Nc{constructor(t,e,n=10,i=10){super(t,e),this.isRectAreaLight=!0,this.type="RectAreaLight",this.width=n,this.height=i}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class $c{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t<9;t++)this.coefficients.push(new oe)}set(t){for(let e=0;e<9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t<9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const n=t.x,i=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*i),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*n),e.addScaledVector(s[4],n*i*1.092548),e.addScaledVector(s[5],i*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],n*r*1.092548),e.addScaledVector(s[8],.546274*(n*n-i*i)),e}getIrradianceAt(t,e){const n=t.x,i=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*i),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*n),e.addScaledVector(s[4],.858086*n*i),e.addScaledVector(s[5],.858086*i*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*n*r),e.addScaledVector(s[8],.429043*(n*n-i*i)),e}add(t){for(let e=0;e<9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let n=0;n<9;n++)this.coefficients[n].addScaledVector(t.coefficients[n],e);return this}scale(t){for(let e=0;e<9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let n=0;n<9;n++)this.coefficients[n].lerp(t.coefficients[n],e);return this}equals(t){for(let e=0;e<9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const n=this.coefficients;for(let i=0;i<9;i++)n[i].fromArray(t,e+3*i);return this}toArray(t=[],e=0){const n=this.coefficients;for(let i=0;i<9;i++)n[i].toArray(t,e+3*i);return t}static getBasisAt(t,e){const n=t.x,i=t.y,r=t.z;e[0]=.282095,e[1]=.488603*i,e[2]=.488603*r,e[3]=.488603*n,e[4]=1.092548*n*i,e[5]=1.092548*i*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*n*r,e[8]=.546274*(n*n-i*i)}}class Qc extends Nc{constructor(t=new $c,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class th extends Lc{constructor(t){super(t),this.textures={}}load(t,e,n,i){const r=this,s=new Uc(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=this.textures;function n(t){return void 0===e[t]&&console.warn("THREE.MaterialLoader: Undefined texture",t),e[t]}const i=th.createMaterialFromType(t.type);if(void 0!==t.uuid&&(i.uuid=t.uuid),void 0!==t.name&&(i.name=t.name),void 0!==t.color&&void 0!==i.color&&i.color.setHex(t.color),void 0!==t.roughness&&(i.roughness=t.roughness),void 0!==t.metalness&&(i.metalness=t.metalness),void 0!==t.sheen&&(i.sheen=t.sheen),void 0!==t.sheenColor&&(i.sheenColor=(new Rn).setHex(t.sheenColor)),void 0!==t.sheenRoughness&&(i.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&&void 0!==i.emissive&&i.emissive.setHex(t.emissive),void 0!==t.specular&&void 0!==i.specular&&i.specular.setHex(t.specular),void 0!==t.specularIntensity&&(i.specularIntensity=t.specularIntensity),void 0!==t.specularColor&&void 0!==i.specularColor&&i.specularColor.setHex(t.specularColor),void 0!==t.shininess&&(i.shininess=t.shininess),void 0!==t.clearcoat&&(i.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&&(i.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&&(i.iridescence=t.iridescence),void 0!==t.iridescenceIOR&&(i.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&&(i.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&&(i.transmission=t.transmission),void 0!==t.thickness&&(i.thickness=t.thickness),void 0!==t.attenuationDistance&&(i.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&&void 0!==i.attenuationColor&&i.attenuationColor.setHex(t.attenuationColor),void 0!==t.fog&&(i.fog=t.fog),void 0!==t.flatShading&&(i.flatShading=t.flatShading),void 0!==t.blending&&(i.blending=t.blending),void 0!==t.combine&&(i.combine=t.combine),void 0!==t.side&&(i.side=t.side),void 0!==t.shadowSide&&(i.shadowSide=t.shadowSide),void 0!==t.opacity&&(i.opacity=t.opacity),void 0!==t.transparent&&(i.transparent=t.transparent),void 0!==t.alphaTest&&(i.alphaTest=t.alphaTest),void 0!==t.depthTest&&(i.depthTest=t.depthTest),void 0!==t.depthWrite&&(i.depthWrite=t.depthWrite),void 0!==t.colorWrite&&(i.colorWrite=t.colorWrite),void 0!==t.stencilWrite&&(i.stencilWrite=t.stencilWrite),void 0!==t.stencilWriteMask&&(i.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&&(i.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&&(i.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&&(i.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&&(i.stencilFail=t.stencilFail),void 0!==t.stencilZFail&&(i.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&&(i.stencilZPass=t.stencilZPass),void 0!==t.wireframe&&(i.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&&(i.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&&(i.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&&(i.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&&(i.rotation=t.rotation),1!==t.linewidth&&(i.linewidth=t.linewidth),void 0!==t.dashSize&&(i.dashSize=t.dashSize),void 0!==t.gapSize&&(i.gapSize=t.gapSize),void 0!==t.scale&&(i.scale=t.scale),void 0!==t.polygonOffset&&(i.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&&(i.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&&(i.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&&(i.dithering=t.dithering),void 0!==t.alphaToCoverage&&(i.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&&(i.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.forceSinglePass&&(i.forceSinglePass=t.forceSinglePass),void 0!==t.visible&&(i.visible=t.visible),void 0!==t.toneMapped&&(i.toneMapped=t.toneMapped),void 0!==t.userData&&(i.userData=t.userData),void 0!==t.vertexColors&&("number"==typeof t.vertexColors?i.vertexColors=t.vertexColors>0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new Rn).setHex(r.value);break;case"v2":i.uniforms[e].value=(new Dt).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new oe).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new ne).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new Nt).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new Fe).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new Dt).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Dt).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=n(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=n(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:Jl,SpriteMaterial:Ma,RawShaderMaterial:Kl,ShaderMaterial:yi,PointsMaterial:xo,MeshPhysicalMaterial:Ql,MeshStandardMaterial:$l,MeshPhongMaterial:tc,MeshToonMaterial:ec,MeshNormalMaterial:nc,MeshLambertMaterial:ic,MeshDepthMaterial:$s,MeshDistanceMaterial:Qs,MeshBasicMaterial:Ln,MeshMatcapMaterial:rc,LineDashedMaterial:sc,LineBasicMaterial:oo,Material:bn}[t]}}class eh{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){ae.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;ae.multiplyQuaternionsFlat(t,s,t,e,t,n),ae.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const Eh="\\[\\]\\.:\\/",Th=new RegExp("["+Eh+"]","g"),wh="[^"+Eh+"]",Ah="[^"+Eh.replace("\\.","")+"]",Rh=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",wh)+/(WCOD+)?/.source.replace("WCOD",Ah)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",wh)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",wh)+"$"),Ch=["material","materials","bones","map"];class Lh{constructor(t,e,n){this.path=e,this.parsedPath=n||Lh.parseTrackName(e),this.node=Lh.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new Lh.Composite(t,e,n):new Lh(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(Th,"")}static parseTrackName(t){const e=Rh.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==Ch.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===lt)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=st,i.endingEnd=st):(i.endingStart=t?this.zeroSlopeAtStart?st:rt:at,i.endingEnd=e?this.zeroSlopeAtEnd?st:rt:at)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}const Ih=new Float32Array(1);class Uh{constructor(t){this.value=t}clone(){return new Uh(void 0===this.value.clone?this.value:this.value.clone())}}let Dh=0;function Nh(t,e){return t.distance-e.distance}function Oh(t,e,n,i){if(t.layers.test(e.layers)&&t.raycast(e,n),!0===i){const i=t.children;for(let t=0,r=i.length;t=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new Lh(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}},t.AnimationUtils=dc,t.ArcCurve=Co,t.ArrayCamera=ra,t.ArrowHelper=class extends cn{constructor(t=new oe(0,0,1),e=new oe(0,0,0),n=1,i=16776960,r=.2*n,s=.2*r){super(),this.type="ArrowHelper",void 0===nu&&(nu=new Zn,nu.setAttribute("position",new Hn([0,0,0,0,1,0],3)),iu=new $o(0,.5,1,5,1),iu.translate(0,-.5,0)),this.position.copy(e),this.line=new mo(nu,new oo({color:i,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new pi(iu,new Ln({color:i,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(n,r,s)}setDirection(t){if(t.y>.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{eu.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(eu,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},t.Audio=_h,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let n=0;nthis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Fh).distanceTo(t)}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}},t.Box3=he,t.Box3Helper=class extends vo{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new Zn;i.setIndex(new Bn(n,1)),i.setAttribute("position",new Hn([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(i,new oo({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BoxBufferGeometry=class extends fi{constructor(t,e,n,i,r,s){console.warn("THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry."),super(t,e,n,i,r,s)}},t.BoxGeometry=fi,t.BoxHelper=class extends vo{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new Float32Array(24),r=new Zn;r.setIndex(new Bn(n,1)),r.setAttribute("position",new Bn(i,3)),super(r,new oo({color:e,toneMapped:!1})),this.object=t,this.type="BoxHelper",this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&&console.warn("THREE.BoxHelper: .update() has no longer arguments."),void 0!==this.object&&tu.setFromObject(this.object),tu.isEmpty())return;const e=tu.min,n=tu.max,i=this.geometry.attributes.position,r=i.array;r[0]=n.x,r[1]=n.y,r[2]=n.z,r[3]=e.x,r[4]=n.y,r[5]=n.z,r[6]=e.x,r[7]=e.y,r[8]=n.z,r[9]=n.x,r[10]=e.y,r[11]=n.z,r[12]=n.x,r[13]=n.y,r[14]=e.z,r[15]=e.x,r[16]=n.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=n.x,r[22]=e.y,r[23]=e.z,i.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BufferAttribute=Bn,t.BufferGeometry=Zn,t.BufferGeometryLoader=ih,t.ByteType=1010,t.Cache=Ac,t.Camera=Mi,t.CameraHelper=class extends vo{constructor(t){const e=new Zn,n=new oo({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={};function a(t,e){o(t),o(e)}function o(t){i.push(0,0,0),r.push(0,0,0),void 0===s[t]&&(s[t]=[]),s[t].push(i.length/3-1)}a("n1","n2"),a("n2","n4"),a("n4","n3"),a("n3","n1"),a("f1","f2"),a("f2","f4"),a("f4","f3"),a("f3","f1"),a("n1","f1"),a("n2","f2"),a("n3","f3"),a("n4","f4"),a("p","n1"),a("p","n2"),a("p","n3"),a("p","n4"),a("u1","u2"),a("u2","u3"),a("u3","u1"),a("c","t"),a("p","c"),a("cn1","cn2"),a("cn3","cn4"),a("cf1","cf2"),a("cf3","cf4"),e.setAttribute("position",new Hn(i,3)),e.setAttribute("color",new Hn(r,3)),super(e,n),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update();const l=new Rn(16755200),c=new Rn(16711680),h=new Rn(43775),u=new Rn(16777215),d=new Rn(3355443);this.setColors(l,c,h,u,d)}setColors(t,e,n,i,r){const s=this.geometry.getAttribute("color");s.setXYZ(0,t.r,t.g,t.b),s.setXYZ(1,t.r,t.g,t.b),s.setXYZ(2,t.r,t.g,t.b),s.setXYZ(3,t.r,t.g,t.b),s.setXYZ(4,t.r,t.g,t.b),s.setXYZ(5,t.r,t.g,t.b),s.setXYZ(6,t.r,t.g,t.b),s.setXYZ(7,t.r,t.g,t.b),s.setXYZ(8,t.r,t.g,t.b),s.setXYZ(9,t.r,t.g,t.b),s.setXYZ(10,t.r,t.g,t.b),s.setXYZ(11,t.r,t.g,t.b),s.setXYZ(12,t.r,t.g,t.b),s.setXYZ(13,t.r,t.g,t.b),s.setXYZ(14,t.r,t.g,t.b),s.setXYZ(15,t.r,t.g,t.b),s.setXYZ(16,t.r,t.g,t.b),s.setXYZ(17,t.r,t.g,t.b),s.setXYZ(18,t.r,t.g,t.b),s.setXYZ(19,t.r,t.g,t.b),s.setXYZ(20,t.r,t.g,t.b),s.setXYZ(21,t.r,t.g,t.b),s.setXYZ(22,t.r,t.g,t.b),s.setXYZ(23,t.r,t.g,t.b),s.setXYZ(24,e.r,e.g,e.b),s.setXYZ(25,e.r,e.g,e.b),s.setXYZ(26,e.r,e.g,e.b),s.setXYZ(27,e.r,e.g,e.b),s.setXYZ(28,e.r,e.g,e.b),s.setXYZ(29,e.r,e.g,e.b),s.setXYZ(30,e.r,e.g,e.b),s.setXYZ(31,e.r,e.g,e.b),s.setXYZ(32,n.r,n.g,n.b),s.setXYZ(33,n.r,n.g,n.b),s.setXYZ(34,n.r,n.g,n.b),s.setXYZ(35,n.r,n.g,n.b),s.setXYZ(36,n.r,n.g,n.b),s.setXYZ(37,n.r,n.g,n.b),s.setXYZ(38,i.r,i.g,i.b),s.setXYZ(39,i.r,i.g,i.b),s.setXYZ(40,r.r,r.g,r.b),s.setXYZ(41,r.r,r.g,r.b),s.setXYZ(42,r.r,r.g,r.b),s.setXYZ(43,r.r,r.g,r.b),s.setXYZ(44,r.r,r.g,r.b),s.setXYZ(45,r.r,r.g,r.b),s.setXYZ(46,r.r,r.g,r.b),s.setXYZ(47,r.r,r.g,r.b),s.setXYZ(48,r.r,r.g,r.b),s.setXYZ(49,r.r,r.g,r.b),s.needsUpdate=!0}update(){const t=this.geometry,e=this.pointMap;$h.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),Qh("c",e,t,$h,0,0,-1),Qh("t",e,t,$h,0,0,1),Qh("n1",e,t,$h,-1,-1,-1),Qh("n2",e,t,$h,1,-1,-1),Qh("n3",e,t,$h,-1,1,-1),Qh("n4",e,t,$h,1,1,-1),Qh("f1",e,t,$h,-1,-1,1),Qh("f2",e,t,$h,1,-1,1),Qh("f3",e,t,$h,-1,1,1),Qh("f4",e,t,$h,1,1,1),Qh("u1",e,t,$h,.7,1.1,-1),Qh("u2",e,t,$h,-.7,1.1,-1),Qh("u3",e,t,$h,0,2,-1),Qh("cf1",e,t,$h,-1,0,1),Qh("cf2",e,t,$h,1,0,1),Qh("cf3",e,t,$h,0,-1,1),Qh("cf4",e,t,$h,0,1,1),Qh("cn1",e,t,$h,-1,0,-1),Qh("cn2",e,t,$h,1,0,-1),Qh("cn3",e,t,$h,0,-1,-1),Qh("cn4",e,t,$h,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends ee{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleBufferGeometry=class extends Jo{constructor(t,e,n,i){console.warn("THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry."),super(t,e,n,i)}},t.CapsuleGeometry=Jo,t.CatmullRomCurve3=No,t.CineonToneMapping=3,t.CircleBufferGeometry=class extends Ko{constructor(t,e,n,i){console.warn("THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry."),super(t,e,n,i)}},t.CircleGeometry=Ko,t.ClampToEdgeWrapping=h,t.Clock=dh,t.Color=Rn,t.ColorKeyframeTrack=xc,t.ColorManagement=Zt,t.CompressedArrayTexture=class extends wo{constructor(t,e,n,i,r,s){super(t,e,n,r,s),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=h}},t.CompressedTexture=wo,t.CompressedTextureLoader=class extends Lc{constructor(t){super(t)}load(t,e,n,i){const r=this,s=[],a=new wo,o=new Uc(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const n=r.parse(t,!0);s[c]={width:n.width,height:n.height,format:n.format,mipmaps:n.mipmaps},l+=1,6===l&&(1===n.mipmapCount&&(a.minFilter=f),a.image=s,a.format=n.format,a.needsUpdate=!0,e&&e(a))}),n,i)}if(Array.isArray(t))for(let e=0,n=t.length;e0){const n=new Rc(e);r=new Dc(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new Dc(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e1)for(let n=0;nNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const n=Ul.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,s,a;const o=[];if(1===i.length)return s=i[0],a=new ol,a.curves=s.curves,o.push(a),o;let l=!n(i[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=i.length;e1){let t=!1,n=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},t.WebGL1Renderer=ma,t.WebGL3DRenderTarget=class extends ie{constructor(t=1,e=1,n=1){super(t,e),this.isWebGL3DRenderTarget=!0,this.depth=n,this.texture=new se(null,t,e,n),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends ie{constructor(t=1,e=1,n=1){super(t,e),this.isWebGLArrayRenderTarget=!0,this.depth=n,this.texture=new re(null,t,e,n),this.texture.isRenderTargetTexture=!0}},t.WebGLCubeRenderTarget=wi,t.WebGLMultipleRenderTargets=class extends ie{constructor(t=1,e=1,n=1,i={}){super(t,e,i),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t + + + + + + + + + + + + + + + + + +MAHARAJONG — BLANK TILE SPECIFICATION +Variant 01: Ivory / Gold / Navy / Ivory +Drawing No: MJ-TILE-BLK-001 | Scale 1:1 (main views) | Units: mm + + +VIEW A — FACE (Top) + + + +UV PRINT AREA +DO NOT MARK +FACE + + + +32.0 ±0.2 + + + +23.0 ±0.2 +VIEW B — LONG EDGE CROSS-SECTION (32mm × 13mm) + + + + + +← FACE (UV PRINT SURFACE) → +CORE +← BACK → + + + +32.0 ±0.2 + + + +13.0 ±0.2 +VIEW C — SHORT EDGE (23mm × 13mm) + + + + + + + + +23.0 ±0.2 +DETAIL D — LAYER CROSS-SECTION (Scale 2:1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3mm + + + +1mm + + + +6mm + + + +3mm +L1: IVORY ACRYLIC +L2: GOLD HAIRLINE +L3: LAPIS NAVY CORE +L4: IVORY ACRYLIC +MATERIAL & PROCESS SPECIFICATIONS + +Material +Four-layer cast acrylic (PMMA) + +Overall dimensions +32 × 23 × 13 mm + +Dimensional tolerance +±0.2 mm all faces + +Target weight +16–19 g per tile + +Quantity per set +152 tiles + +Layer 1 (face) +Ivory/cream, 3 mm — Pantone ~9183 C + +Layer 2 +Metallic gold, 1 mm — Pantone ~874 C + +Layer 3 (core) +Lapis navy, 6 mm — Pantone ~289 C + +Layer 4 (back) +Ivory/cream, 3 mm — match Layer 1 + +Back face appearance +Back: ivory (matches face) + +Face surface finish +Mirror polished, Ra ≤ 0.4 μm (all 6 faces) + +UV print surface +Face (L1): must accept UV inkjet, zero texture + +Laser engrave +Face (L1): compatible with UV cold laser + +Edge visibility +All 4 layers visible on both 23mm edges + +MJ-TILE-BLK-001 + + + + + + + + +MAHARAJONG BLANK TILE — 4-LAYER ACRYLIC +COMPONENT +DWG No. +REV +PROJECT +SCALE +UNITS +PREPARED BY +DATE +SHEET +SUPPLIER: CONFIRM WEIGHT & PANTONE BEFORE PRODUCTION +Blank Tile (4-Layer Acrylic) +MJ-TILE-BLK-001 +A +Maharajong +1:1 (main) +mm +ccwells@gmail.com +2026-07-12 +1/1 + +GENERAL NOTES: +1. All dims in mm. Tolerances ±0.2mm unless noted. +2. All faces mirror-polished (Ra ≤ 0.4μm). Zero orange-peel. +3. Layer 1 face must accept UV inkjet without priming. +4. Gold hairline (L2) visible on both 23mm short edges. +5. All layers Pantone-matched; supplier submits colour chip for approval. +6. Weight 16–19g/tile. Advise if ballast fill/drill needed. +7. 20-tile prototype required before production MOQ commitment. + \ No newline at end of file diff --git a/design/variant-01/materials-spec.md b/design/variant-01/materials-spec.md new file mode 100644 index 0000000..90dddc7 --- /dev/null +++ b/design/variant-01/materials-spec.md @@ -0,0 +1,88 @@ +# Maharajong Materials Specification — Variant 01 + +> **Variant 01: Ivory / Gold / Navy / Ivory** — all four layers opaque acrylic. +> See `design/variant-02/materials-spec.md` for the clear-back alternative. + +**Date**: 2026-07-11 +**Status**: Confirmed — acrylic for tiles (Chinese OEM); Indian artisan sourcing for wood and brass components +**Informs**: tile blank orders, supplier quotes, component spec updates + +## The material language + +Three materials, used consistently across every component, with navy and gold +as the connective palette (matching the tile artwork and mat design): + +1. **Ivory cast acrylic** — the playing surface (tiles) +2. **Antique brass** — everything metal (dice, trinkets, rack inlay, diya) +3. **Dark rosewood (sheesham)** — everything wooden (racks, pushers) + +The coherence is the luxury cue: one metal, one wood, one ivory. Competitor +research (`research/competitor-analysis.md`) shows premium sets ($375–900) +consistently pair layered acrylic tiles with walnut and brass; Maharajong +substitutes sheesham for walnut as a deliberate provenance statement. + +## Component decisions + +| Component | Material | Key detail | +|-----------|----------|------------| +| Tiles (152) | Four-layer cast acrylic, 32×23×13 mm | Ivory face / gold hairline / lapis-navy core / ivory back — colored edge visible in the wall | +| Racks + pushers (4+4) | Solid sheesham, hand-rubbed oil finish | Single inlaid brass rule line along the top edge | +| Dice (2) | Solid brass, antique patina | Engraved pips filled with navy enamel; rounded corners | +| Scoring trinkets | Solid brass + jewel enamel | Teal peacock-eye, magenta lotus fills (per trinkets spec) | +| Playing mat | Printed micro-suede top, 5 mm dense rubber base | Gold satin-stitch border; same sublimation print as existing mat design | +| Diya light | Solid brass diya, flameless LED insert | Amber flicker LED; real wick cup retained (see `design/diya/diya-design-spec.md`) | + +## Why four-layer acrylic for tiles + +- **Production-validated**: the only material confirmed against both the + eufyMake E1 (UV print) and xTool F2 Ultra (laser engraving) in + `production/tile-production-audit.md` +- **Market-aligned**: layered acrylic is the construction used by The Mahjong + Line ($375–495) and Oh My Mahjong ($640–900); melamine reads mid-market +- **Visible differentiation**: the navy core + gold hairline shows on every + tile edge — a from-across-the-room premium cue that echoes the mat border +- **Rejected**: bone/jade (ethics scrutiny per personas research, incompatible + with UV workflow), melamine (feel), wood-back hybrid (kept as sample only) + +## Validation plan (before committing to 100-set MOQ) + +1. Order Promlogo sample pack: 4-layer acrylic + melamine + wood-back at + 32×23×13 mm (melamine sample doubles as the "$79 set" marketing reference) +2. Order GUSTARIA Amazon blanks for immediate print/engrave workflow testing +3. Request Jayi prototype sample of the exact 4-layer ivory/gold/navy build +4. Run CMYK test strips + print-then-engrave workflow on all samples +5. Confirm final weight target: 16–19 g per tile (drilled/filled acrylic if + standard 4-layer comes in light — confirm option with Jayi) + +## Supplier outreach + +Acrylic tile blanks: `business/outreach/jayi-inquiry-email.md` and +`business/outreach/promlogo-inquiry-email.md` + +Indian artisan components: `business/outreach/sheesham-racks-inquiry.md` (racks/pushers) +and `business/outreach/moradabad-brass-inquiry.md` (dice/trinkets). + +## Indian artisan sourcing (2026-07-11) + +Wood and stone alternatives for tiles were evaluated against the five-constraint tile +spec (UV printable, UV laser engravable, 16–19 g, multi-layer colored edge, 32 × 23 × 13 mm +precision at 152-tile volume) and ruled out: + +- **Sheesham**: weight ~8 g/tile (target 16–19 g); cannot produce navy/gold colored edge; + UV print adhesion requires untested priming workflow; grain variation creates 152-tile QC risk. +- **Makrana marble**: weight ~25.8 g/tile (full set >3.9 kg); material cost 5–15× acrylic; + brittle under gameplay shuffling; UV print adhesion on polished stone untested. + +The three-material language (acrylic / brass / sheesham) is confirmed. Indian artisan +sourcing is directed to the components where it is genuinely superior: + +| Component | Indian sourcing cluster | +|-----------|-------------------------| +| Racks + pushers | Jodhpur / Saharanpur / Pravat Timbers (Kolkata) — sheesham with CNC + hand-finish | +| Dice + scoring trinkets | Moradabad — India's brass hub; Jaipur meenakari for enamel fills | +| Diya insert | Moradabad / Jaipur brass workshops | +| Playing mat | Surat — sublimation printing + gold satin-stitch embroidery | + +**Post-launch milestone**: Makrana marble collector's edition — limited ultra-premium SKU +(display/heirloom object, not for active gameplay), hand-cut by Jaipur artisans. See +`PROJECT-PLAN.md`. diff --git a/design/tile-blanks-spec.md b/design/variant-01/tile-blanks-spec.md similarity index 89% rename from design/tile-blanks-spec.md rename to design/variant-01/tile-blanks-spec.md index b40e4c1..e064e1c 100644 --- a/design/tile-blanks-spec.md +++ b/design/variant-01/tile-blanks-spec.md @@ -1,4 +1,15 @@ -# Maharajong Tile Blanks Sourcing Spec +# Maharajong Tile Blanks Sourcing Spec — Variant 01 + +> **Variant 01: Ivory / Gold / Navy / Ivory** — all four layers opaque acrylic. +> See `design/variant-02/tile-blanks-spec.md` for the clear-back alternative. + +> **Material decision (2026-07-11)**: Four-layer cast acrylic — ivory face / +> gold hairline / lapis-navy core / ivory back — **confirmed**. Indian artisan +> alternatives evaluated and ruled out: sheesham fails on weight (~8 g/tile), colored +> edge, and UV print adhesion; Makrana marble fails on weight (~25.8 g/tile), cost +> (5–15× acrylic), and gameplay fragility. Full rationale: `design/materials-spec.md`. +> Supplier inquiries: `business/outreach/jayi-inquiry-email.md` (OEM) and +> `business/outreach/promlogo-inquiry-email.md` (blanks). ## Target Tile Dimensions - **Size**: 32 × 23 × 13 mm (per gameplay-rules.md tile spec) diff --git a/design/variant-02/manufacturer-docs/tile-blank-spec-sheet-rendered.png b/design/variant-02/manufacturer-docs/tile-blank-spec-sheet-rendered.png new file mode 100644 index 0000000..05a85d5 Binary files /dev/null and b/design/variant-02/manufacturer-docs/tile-blank-spec-sheet-rendered.png differ diff --git a/design/variant-02/manufacturer-docs/tile-blank-technical-drawing.png b/design/variant-02/manufacturer-docs/tile-blank-technical-drawing.png new file mode 100644 index 0000000..2fc2ad8 Binary files /dev/null and b/design/variant-02/manufacturer-docs/tile-blank-technical-drawing.png differ diff --git a/design/variant-02/manufacturer-docs/tile-blank-technical-drawing.svg b/design/variant-02/manufacturer-docs/tile-blank-technical-drawing.svg new file mode 100644 index 0000000..0086847 --- /dev/null +++ b/design/variant-02/manufacturer-docs/tile-blank-technical-drawing.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + +MAHARAJONG — BLANK TILE SPECIFICATION +Variant 02: Ivory / Gold / Navy / Clear +Drawing No: MJ-TILE-BLK-002 | Scale 1:1 (main views) | Units: mm + + +VIEW A — FACE (Top) + + + +UV PRINT AREA +DO NOT MARK +FACE + + + +32.0 ±0.2 + + + +23.0 ±0.2 +VIEW B — LONG EDGE CROSS-SECTION (32mm × 13mm) + + + + + + +← FACE (UV PRINT SURFACE) → +CORE +← BACK (NAVY THROUGH CLEAR) → + + + +32.0 ±0.2 + + + +13.0 ±0.2 +VIEW C — SHORT EDGE (23mm × 13mm) + + + + + + + + + +23.0 ±0.2 +DETAIL D — LAYER CROSS-SECTION (Scale 2:1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3mm + + + +1mm + + + +6mm + + + +3mm +L1: IVORY ACRYLIC +L2: GOLD HAIRLINE +L3: LAPIS NAVY CORE +L4: CRYSTAL CLEAR ACRYLIC +MATERIAL & PROCESS SPECIFICATIONS + +Material +Four-layer cast acrylic (PMMA) + +Overall dimensions +32 × 23 × 13 mm + +Dimensional tolerance +±0.2 mm all faces + +Target weight +16–19 g per tile + +Quantity per set +152 tiles + +Layer 1 (face) +Ivory/cream, 3 mm — Pantone ~9183 C + +Layer 2 +Metallic gold, 1 mm — Pantone ~874 C + +Layer 3 (core) +Lapis navy, 6 mm — Pantone ~289 C + +Layer 4 (back) +Crystal-clear PMMA, 3 mm — water-white, zero haze + +Back face appearance +Back: apparent navy (L3 visible through clear L4) + +Face surface finish +Mirror polished, Ra ≤ 0.4 μm (all 6 faces) + +UV print surface +Face (L1): must accept UV inkjet, zero texture + +Laser engrave +Face (L1): compatible with UV cold laser + +Edge visibility +All 4 layers visible on both 23mm edges + +MJ-TILE-BLK-002 + + + + + + + + +MAHARAJONG BLANK TILE — 4-LAYER ACRYLIC +COMPONENT +DWG No. +REV +PROJECT +SCALE +UNITS +PREPARED BY +DATE +SHEET +SUPPLIER: CONFIRM WEIGHT & PANTONE BEFORE PRODUCTION +Blank Tile (4-Layer Acrylic) +MJ-TILE-BLK-002 +A +Maharajong +1:1 (main) +mm +ccwells@gmail.com +2026-07-12 +1/1 + +GENERAL NOTES: +1. All dims in mm. Tolerances ±0.2mm unless noted. +2. All faces mirror-polished (Ra ≤ 0.4μm). Zero orange-peel. +3. Layer 1 face must accept UV inkjet without priming. +4. Gold hairline (L2) visible on both 23mm short edges. +5. L1–L3 Pantone-matched; supplier submits chip for approval. +6. L4 CRYSTAL CLEAR — water-white, zero haze. No buffing on clear face. +7. QC: per-tile back-face clarity check — navy core uniform, no milky patches. +8. Weight 16–19g/tile. Advise if ballast fill needed. +9. 20-tile prototype required before production MOQ commitment. + \ No newline at end of file diff --git a/design/variant-02/materials-spec.md b/design/variant-02/materials-spec.md new file mode 100644 index 0000000..dde6140 --- /dev/null +++ b/design/variant-02/materials-spec.md @@ -0,0 +1,111 @@ +# Maharajong Materials Specification — Variant 02 + +> **Variant 02: Ivory / Gold / Navy / Clear** — clear acrylic back face; navy core +> visible through the back. See `design/variant-01/materials-spec.md` for the +> all-opaque original. + +**Date**: 2026-07-12 +**Status**: Design proposal — pending sample validation +**Informs**: tile blank orders, supplier quotes, component spec updates + +## What changed from Variant 01 + +A single layer substitution: the **back face (Layer 4) changes from opaque ivory +acrylic to crystal-clear cast acrylic**. Everything else — dimensions, suppliers, +material language, production workflow — remains identical. + +| | Variant 01 | Variant 02 | +|---|---|---| +| Layer 1 — Face | Ivory/cream acrylic, 3 mm | Ivory/cream acrylic, 3 mm ✓ | +| Layer 2 | Gold hairline, 1 mm | Gold hairline, 1 mm ✓ | +| Layer 3 — Core | Lapis navy, 6 mm | Lapis navy, 6 mm ✓ | +| Layer 4 — Back | **Ivory/cream acrylic, 3 mm** | **Crystal-clear acrylic, 3 mm** | +| Back face appearance | Ivory (matches face) | Deep navy (seen through clear) | + +## Why clear back + +The Grok-rendered spec sheet inadvertently showed the tile back appearing deep navy — +and the visual was stronger than the all-ivory back. The design rationale: + +- **Stronger identity**: the tile now has two fully distinct faces. Ivory face for play; + navy back for the wall. Players reading their tiles see ivory; opponents see a solid + navy wall. +- **"Made of navy"**: the navy core — visible from every edge and through the clear back + — reads as the tile's true material identity. Ivory is the surface, navy is the soul. +- **Wall theatrics**: 152 tiles face-down in the wall form a solid navy field. The + current mahjong market (all-ivory or all-green) has nothing like this. +- **Edge coherence**: the edge already shows ivory / gold / navy / [new: clear → navy]. + The clear back closes the loop — both the edge and the back resolve to navy. +- **No added cost**: clear cast acrylic is standard stock at all suppliers; no Pantone + matching required for Layer 4. + +## The material language (updated) + +Three materials, with navy and gold as the connective palette: + +1. **Ivory cast acrylic** — the playing surface (tile face, Layer 1) +2. **Antique brass** — everything metal (dice, trinkets, rack inlay, diya) +3. **Dark rosewood (sheesham)** — everything wooden (racks, pushers) + +The tile back is no longer ivory — it is **apparent navy** (the navy core seen through +crystal-clear acrylic). This adds a fourth visual element: the table field during play +is navy rather than ivory, connecting the tiles to the mat border and dice pips. + +## Component decisions + +| Component | Material | Key detail | +|-----------|----------|------------| +| Tiles (152) | Four-layer cast acrylic, 32×23×13 mm | Ivory face / gold hairline / lapis-navy core / **crystal-clear back** — navy visible from back and edges | +| Racks + pushers (4+4) | Solid sheesham, hand-rubbed oil finish | Single inlaid brass rule line along the top edge | +| Dice (2) | Solid brass, antique patina | Engraved pips filled with navy enamel; rounded corners | +| Scoring trinkets | Solid brass + jewel enamel | Teal peacock-eye, magenta lotus fills | +| Playing mat | Printed micro-suede top, 5 mm dense rubber base | Gold satin-stitch border | +| Diya light | Solid brass diya, flameless LED insert | Amber flicker LED | + +## Production considerations specific to Variant 02 + +**Clear back sourcing**: Crystal-clear cast acrylic (PMMA) is standard stock — actually +simpler to source than matched ivory for Layer 4. No Pantone reference needed; specify +"optical clarity, water-white, zero haze". + +**UV printing**: Face (Layer 1) only. The back (Layer 4) is intentionally left clear +and unmarked. Confirm with Jayi/Promlogo that the clear layer is not accidentally +frosted or textured during their polishing process — it must remain optically clear. + +**Laser engraving**: Face (Layer 1) only. No change from Variant 01. + +**Weight**: Unchanged. Clear PMMA has the same density as ivory/colored PMMA (~1,190 +kg/m³). The 16–19 g target applies identically. + +**Visual QC**: Add a back-face clarity check to the QC process — the navy core must +be uniformly visible through the clear layer with no milky patches, adhesive bleed, or +delamination at the Layer 3/4 interface. + +## Validation plan + +Same as Variant 01, with one addition: +1. Request Jayi prototype sample of the 4-layer ivory/gold/navy/**clear** build +2. Order Promlogo sample in 4-layer acrylic with clear back option (if available) +3. Inspect back-face clarity on samples — confirm no haze, no interface artifacts +4. Compare side-by-side with Variant 01 sample on the table during mock gameplay +5. Run UV print on face; confirm clear back is unaffected + +## Supplier outreach + +Same suppliers as Variant 01. When contacting Jayi/Promlogo, specify Variant 02 by +adding to the inquiry: "Alternative sample request: same tile but with Layer 4 (back) +in crystal-clear acrylic instead of ivory — we want to evaluate the clear-back visual." + +Supplier inquiries: `business/outreach/jayi-inquiry-email.md` and +`business/outreach/promlogo-inquiry-email.md` (both apply; add the clear-back note). + +## Indian artisan sourcing + +Same as Variant 01. The clear back does not affect racks, brass, or mat sourcing. + +| Component | Indian sourcing cluster | +|-----------|-------------------------| +| Racks + pushers | Jodhpur / Saharanpur / Pravat Timbers (Kolkata) | +| Dice + scoring trinkets | Moradabad / Jaipur meenakari | +| Diya insert | Moradabad / Jaipur brass workshops | +| Playing mat | Surat — sublimation printing + gold satin-stitch embroidery | diff --git a/design/variant-02/tile-blanks-spec.md b/design/variant-02/tile-blanks-spec.md new file mode 100644 index 0000000..e8c2a3d --- /dev/null +++ b/design/variant-02/tile-blanks-spec.md @@ -0,0 +1,137 @@ +# Maharajong Tile Blanks Sourcing Spec — Variant 02 + +> **Variant 02: Ivory / Gold / Navy / Clear** — crystal-clear acrylic back face; +> navy core visible through the back. See `design/variant-01/tile-blanks-spec.md` +> for the all-opaque original. + +> **Material decision (2026-07-12)**: Four-layer cast acrylic — ivory face / +> gold hairline / lapis-navy core / **crystal-clear back** — design proposal, +> pending physical sample comparison against Variant 01. +> Full rationale: `design/variant-02/materials-spec.md`. +> Supplier inquiries: `business/outreach/jayi-inquiry-email.md` (add clear-back +> note) and `business/outreach/promlogo-inquiry-email.md` (add clear-back note). + +## Target Tile Dimensions + +Same as Variant 01 — no change. + +- **Size**: 32 × 23 × 13 mm +- **Quantity per set**: 152 tiles +- **Surface**: Smooth, polished — face must accept UV printing and UV laser engraving +- **Face color**: Ivory/cream (Layer 1) +- **Back appearance**: Deep navy (Layer 3 seen through crystal-clear Layer 4) + +## Layer Stack + +``` +FACE (UV print surface) +┌─────────────────────────────────┐ +│ L1 Ivory/cream acrylic 3 mm │ Pantone ~9183 C — UV print here +│─────────────────────────────────│ +│ L2 Metallic gold 1 mm │ Pantone ~874 C — edge hairline +│─────────────────────────────────│ +│ L3 Lapis navy 6 mm │ Pantone ~289 C — core / visible through back +│─────────────────────────────────│ +│ L4 Crystal-clear acrylic 3 mm │ Water-white, zero haze — back face +└─────────────────────────────────┘ +BACK (navy visible through clear) +``` + +**Key difference from Variant 01**: Layer 4 is optically clear instead of ivory. +The navy core (Layer 3) shows through the clear back face — the back of the tile +appears deep navy without any printing. + +--- + +## Supplier 1: Jayi Acrylic (OEM/ODM — recommended for production) + +Same capabilities as documented in `design/variant-01/tile-blanks-spec.md`. + +### Variant 02 amendment for Jayi inquiry + +Add the following to the Jayi inquiry email (`business/outreach/jayi-inquiry-email.md`): + +> **Additional sample request (Variant 02)**: In addition to the ivory-back +> sample, please also quote a version where Layer 4 (back face, 3mm) is +> **crystal-clear cast acrylic** instead of ivory — optically clear, water-white, +> zero haze or frosting. We want to compare the ivory-back and clear-back builds +> side-by-side. Please confirm: +> - Is crystal-clear PMMA available as a standard layer option? +> - Will the polishing process leave the clear layer optically clear (no +> accidental frosting from buffing compounds)? +> - Is there any price difference vs. the ivory-back build? + +### Maharajong fit (Variant 02) + +- ✅ Crystal-clear PMMA is standard stock for all acrylic manufacturers +- ✅ No Pantone matching needed for Layer 4 — simpler than matched ivory +- ✅ Navy core visibility through clear back confirmed (physics — no additional + process needed) +- ⚠️ **New QC requirement**: back-face clarity must be inspected per tile — + no milky patches, no interface delamination at Layer 3/4 boundary +- ⚠️ Polishing process must not frost the clear back — confirm with Jayi that + buffing compounds used on ivory are not applied to the clear layer + +--- + +## Supplier 2: Promlogo (blank tile supplier) + +Same capabilities as Variant 01. When requesting samples, add: + +> **Variant 02 sample**: Please include one additional sample batch of 20 tiles +> in the 4-layer acrylic build where the back layer is **crystal-clear** (not +> ivory/cream). We want to see the navy core visible through the clear back. +> If you do not offer clear-back as a standard option, please let us know. + +### Maharajong fit (Variant 02) + +- ✅ Promlogo lists "jelly / candy / transparent" layer options — clear back + likely available as a standard configuration +- ✅ Blank surface on face for UV printing unchanged +- ⚠️ Request confirmation that their clear layer is optically water-white + (some transparent acrylics have a slight blue or green tint) + +--- + +## Supplier 3: GUSTARIA via Amazon (prototyping only) + +White plastic tiles — not applicable for Variant 02 testing. The clear-back effect +requires a genuine multi-layer acrylic construction; the GUSTARIA single-layer plastic +tile cannot replicate it. Use Jayi/Promlogo samples only for Variant 02 evaluation. + +--- + +## Material Comparison: Variant 01 vs. Variant 02 + +| Property | Variant 01 (Ivory back) | Variant 02 (Clear back) | +|----------|------------------------|------------------------| +| Back face appearance | Ivory/cream | Deep navy (through clear) | +| Table field during play | Ivory field when tiles face-down | Navy field when tiles face-down | +| Edge profile | Ivory / Gold / Navy / Ivory | Ivory / Gold / Navy / Clear(→Navy) | +| Layer 4 sourcing | Pantone-matched ivory PMMA | Standard water-white clear PMMA | +| Layer 4 QC | Color match to Layer 1 | Optical clarity (no haze) | +| UV printing | Face only | Face only (back intentionally clear) | +| Weight | 16–19 g (same) | 16–19 g (same — clear PMMA = same density) | +| Manufacturer complexity | Standard | Marginally simpler (no ivory match for L4) | +| Visual differentiation | Strong (ivory face, colored edge) | Stronger (navy back adds second distinct face) | +| Market precedent | Standard premium acrylic mahjong | No known competitor offers this | + +### Recommendation + +Request **both variants** in the Jayi and Promlogo sample packs. The clear-back +variant is a potentially stronger differentiator at negligible added manufacturing +complexity, but the real-world visual needs physical validation — does the navy +core read clearly, or is the clear acrylic layer too thick/tinted to produce a +saturated navy back? Samples will answer this question definitively. + +--- + +## Next Steps + +1. **Add Variant 02 note** to Jayi and Promlogo inquiry emails before sending +2. **Request dual samples** — both ivory-back (Variant 01) and clear-back (Variant 02) + in a single sample order from each supplier +3. **Compare on the table**: Place both variants face-down in a simulated wall; evaluate + the navy-back effect at table distance (~60 cm) in normal room lighting +4. **Decide variant** before committing to production MOQ +5. **Update PROJECT-PLAN.md** once variant is chosen diff --git a/production/tile-production-audit.md b/production/tile-production-audit.md index b9684ee..07de586 100644 --- a/production/tile-production-audit.md +++ b/production/tile-production-audit.md @@ -78,7 +78,7 @@ - **Verdict**: ✅ The laser can handle all text and fine details at tile size. Even the finest rangoli dot patterns (estimated ~0.5mm dots) are 25× larger than the spot size. ### Material compatibility -- **Tile material**: TBD (resin, acrylic, or melamine — not yet decided) +- **Tile material**: Four-layer cast acrylic (decided — see `design/variant-01/materials-spec.md`) - **Engraver supports**: Acrylic ✅, plastic ✅, ceramic ✅, resin ✅ - **UV cold processing**: No burning/charring on any of these materials - **Action needed**: ⚠️ Decide on tile blank material, then run test engravings