@plasius/gpu-shared 0.1.10 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -1
- package/README.md +59 -2
- package/assets/brigantine.gltf +549 -24
- package/assets/cutter.gltf +538 -0
- package/assets/harbor-dock.gltf +680 -0
- package/assets/lighthouse.gltf +604 -0
- package/dist/chunk-2FIFSBB4.js +74 -0
- package/dist/chunk-2FIFSBB4.js.map +1 -0
- package/dist/chunk-DABW627O.js +113 -0
- package/dist/chunk-DABW627O.js.map +1 -0
- package/dist/chunk-DQX4DXBR.js +369 -0
- package/dist/chunk-DQX4DXBR.js.map +1 -0
- package/dist/chunk-NCPJWLX3.js +17 -0
- package/dist/chunk-NCPJWLX3.js.map +1 -0
- package/dist/gltf-loader-WAM23F37.js +9 -0
- package/dist/index.cjs +1265 -281
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +19 -6
- package/dist/index.js.map +1 -1
- package/dist/showcase-inline-assets-B7U7VX5H.js +7 -0
- package/dist/{showcase-runtime-55OVDYWT.js → showcase-runtime-PN7N3FZY.js} +818 -239
- package/dist/showcase-runtime-PN7N3FZY.js.map +1 -0
- package/package.json +15 -1
- package/src/asset-url.js +62 -11
- package/src/feature-flags.js +1 -0
- package/src/gltf-loader.js +322 -32
- package/src/i18n.js +71 -0
- package/src/index.d.ts +115 -1
- package/src/index.js +9 -1
- package/src/showcase-inline-assets.js +3 -0
- package/src/showcase-runtime.js +924 -190
- package/src/translations/en-GB.js +55 -0
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-OTCJ3VOK.js +0 -35
- package/dist/chunk-OTCJ3VOK.js.map +0 -1
- package/dist/chunk-QBMXJ3V2.js +0 -142
- package/dist/chunk-QBMXJ3V2.js.map +0 -1
- package/dist/gltf-loader-LKALCZAV.js +0 -8
- package/dist/showcase-runtime-55OVDYWT.js.map +0 -1
- /package/dist/{chunk-DGUM43GV.js.map → gltf-loader-WAM23F37.js.map} +0 -0
- /package/dist/{gltf-loader-LKALCZAV.js.map → showcase-inline-assets-B7U7VX5H.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -19,9 +19,24 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
};
|
|
20
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
21
|
|
|
22
|
+
// src/showcase-inline-assets.js
|
|
23
|
+
var showcase_inline_assets_exports = {};
|
|
24
|
+
__export(showcase_inline_assets_exports, {
|
|
25
|
+
INLINE_SHOWCASE_ASSET_URLS: () => INLINE_SHOWCASE_ASSET_URLS
|
|
26
|
+
});
|
|
27
|
+
var INLINE_SHOWCASE_ASSET_URLS;
|
|
28
|
+
var init_showcase_inline_assets = __esm({
|
|
29
|
+
"src/showcase-inline-assets.js"() {
|
|
30
|
+
INLINE_SHOWCASE_ASSET_URLS = Object.freeze({
|
|
31
|
+
"brigantine": "data:application/json;base64,ewogICJhc3NldCI6IHsKICAgICJ2ZXJzaW9uIjogIjIuMCIsCiAgICAiZ2VuZXJhdG9yIjogIkBwbGFzaXVzL2dwdS1zaGFyZWQgc2hvd2Nhc2UgYXNzZXQgZ2VuZXJhdG9yIgogIH0sCiAgInNjZW5lIjogMCwKICAic2NlbmVzIjogWwogICAgewogICAgICAibm9kZXMiOiBbCiAgICAgICAgMAogICAgICBdCiAgICB9CiAgXSwKICAibm9kZXMiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImJyaWdhbnRpbmUiLAogICAgICAiY2hpbGRyZW4iOiBbCiAgICAgICAgMSwKICAgICAgICAyLAogICAgICAgIDMKICAgICAgXSwKICAgICAgImV4dHJhcyI6IHsKICAgICAgICAicGh5c2ljcyI6IHsKICAgICAgICAgICJzaGFwZSI6ICJib3giLAogICAgICAgICAgImhhbGZFeHRlbnRzIjogWwogICAgICAgICAgICAxLjU4LAogICAgICAgICAgICAxLjEyLAogICAgICAgICAgICA0LjQKICAgICAgICAgIF0sCiAgICAgICAgICAibWFzcyI6IDQ3MDAsCiAgICAgICAgICAicmVzdGl0dXRpb24iOiAwLjIsCiAgICAgICAgICAibGluZWFyRGFtcGluZyI6IDAuMDM4LAogICAgICAgICAgImFuZ3VsYXJEYW1waW5nIjogMC4wNzYsCiAgICAgICAgICAid2F0ZXJsaW5lIjogMC40NAogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgIHsKICAgICAgIm5hbWUiOiAiYnJpZ2FudGluZS1odWxsIiwKICAgICAgIm1lc2giOiAwCiAgICB9LAogICAgewogICAgICAibmFtZSI6ICJicmlnYW50aW5lLXJpZyIsCiAgICAgICJtZXNoIjogMQogICAgfSwKICAgIHsKICAgICAgIm5hbWUiOiAiYnJpZ2FudGluZS1sYW50ZXJucyIsCiAgICAgICJtZXNoIjogMgogICAgfQogIF0sCiAgIm1lc2hlcyI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAiYnJpZ2FudGluZS1odWxsIiwKICAgICAgInByaW1pdGl2ZXMiOiBbCiAgICAgICAgewogICAgICAgICAgImF0dHJpYnV0ZXMiOiB7CiAgICAgICAgICAgICJQT1NJVElPTiI6IDAsCiAgICAgICAgICAgICJOT1JNQUwiOiAxCiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiAyLAogICAgICAgICAgIm1hdGVyaWFsIjogMAogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImF0dHJpYnV0ZXMiOiB7CiAgICAgICAgICAgICJQT1NJVElPTiI6IDMsCiAgICAgICAgICAgICJOT1JNQUwiOiA0CiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiA1LAogICAgICAgICAgIm1hdGVyaWFsIjogMQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImF0dHJpYnV0ZXMiOiB7CiAgICAgICAgICAgICJQT1NJVElPTiI6IDYsCiAgICAgICAgICAgICJOT1JNQUwiOiA3CiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiA4LAogICAgICAgICAgIm1hdGVyaWFsIjogMgogICAgICAgIH0KICAgICAgXQogICAgfSwKICAgIHsKICAgICAgIm5hbWUiOiAiYnJpZ2FudGluZS1yaWciLAogICAgICAicHJpbWl0aXZlcyI6IFsKICAgICAgICB7CiAgICAgICAgICAiYXR0cmlidXRlcyI6IHsKICAgICAgICAgICAgIlBPU0lUSU9OIjogOSwKICAgICAgICAgICAgIk5PUk1BTCI6IDEwCiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiAxMSwKICAgICAgICAgICJtYXRlcmlhbCI6IDMKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJhdHRyaWJ1dGVzIjogewogICAgICAgICAgICAiUE9TSVRJT04iOiAxMiwKICAgICAgICAgICAgIk5PUk1BTCI6IDEzCiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiAxNCwKICAgICAgICAgICJtYXRlcmlhbCI6IDQKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJhdHRyaWJ1dGVzIjogewogICAgICAgICAgICAiUE9TSVRJT04iOiAxNSwKICAgICAgICAgICAgIk5PUk1BTCI6IDE2CiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiAxNywKICAgICAgICAgICJtYXRlcmlhbCI6IDUKICAgICAgICB9CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgICJuYW1lIjogImJyaWdhbnRpbmUtbGFudGVybnMiLAogICAgICAicHJpbWl0aXZlcyI6IFsKICAgICAgICB7CiAgICAgICAgICAiYXR0cmlidXRlcyI6IHsKICAgICAgICAgICAgIlBPU0lUSU9OIjogMTgsCiAgICAgICAgICAgICJOT1JNQUwiOiAxOQogICAgICAgICAgfSwKICAgICAgICAgICJpbmRpY2VzIjogMjAsCiAgICAgICAgICAibWF0ZXJpYWwiOiA2CiAgICAgICAgfQogICAgICBdCiAgICB9CiAgXSwKICAibWF0ZXJpYWxzIjogWwogICAgewogICAgICAibmFtZSI6ICJwYWludGVkLWh1bGwiLAogICAgICAicGJyTWV0YWxsaWNSb3VnaG5lc3MiOiB7CiAgICAgICAgImJhc2VDb2xvckZhY3RvciI6IFsKICAgICAgICAgIDAuNDIsCiAgICAgICAgICAwLjI0LAogICAgICAgICAgMC4xNiwKICAgICAgICAgIDEKICAgICAgICBdLAogICAgICAgICJtZXRhbGxpY0ZhY3RvciI6IDAuMDgsCiAgICAgICAgInJvdWdobmVzc0ZhY3RvciI6IDAuNzYKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgIm5hbWUiOiAiZGVjay1wbGFuayIsCiAgICAgICJwYnJNZXRhbGxpY1JvdWdobmVzcyI6IHsKICAgICAgICAiYmFzZUNvbG9yRmFjdG9yIjogWwogICAgICAgICAgMC41MywKICAgICAgICAgIDAuMzksCiAgICAgICAgICAwLjI2LAogICAgICAgICAgMQogICAgICAgIF0sCiAgICAgICAgIm1ldGFsbGljRmFjdG9yIjogMC4wMiwKICAgICAgICAicm91Z2huZXNzRmFjdG9yIjogMC45CiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJuYW1lIjogImh1bGwtdHJpbSIsCiAgICAgICJwYnJNZXRhbGxpY1JvdWdobmVzcyI6IHsKICAgICAgICAiYmFzZUNvbG9yRmFjdG9yIjogWwogICAgICAgICAgMC43MiwKICAgICAgICAgIDAuNzEsCiAgICAgICAgICAwLjY2LAogICAgICAgICAgMQogICAgICAgIF0sCiAgICAgICAgIm1ldGFsbGljRmFjdG9yIjogMC4xOCwKICAgICAgICAicm91Z2huZXNzRmFjdG9yIjogMC40MgogICAgICB9CiAgICB9LAogICAgewogICAgICAibmFtZSI6ICJtYXN0LXdvb2QiLAogICAgICAicGJyTWV0YWxsaWNSb3VnaG5lc3MiOiB7CiAgICAgICAgImJhc2VDb2xvckZhY3RvciI6IFsKICAgICAgICAgIDAuMzcsCiAgICAgICAgICAwLjI3LAogICAgICAgICAgMC4xOCwKICAgICAgICAgIDEKICAgICAgICBdLAogICAgICAgICJtZXRhbGxpY0ZhY3RvciI6IDAuMDIsCiAgICAgICAgInJvdWdobmVzc0ZhY3RvciI6IDAuODIKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgIm5hbWUiOiAic2FpbC1jYW52YXMiLAogICAgICAicGJyTWV0YWxsaWNSb3VnaG5lc3MiOiB7CiAgICAgICAgImJhc2VDb2xvckZhY3RvciI6IFsKICAgICAgICAgIDAuODIsCiAgICAgICAgICAwLjc5LAogICAgICAgICAgMC43MiwKICAgICAgICAgIDEKICAgICAgICBdLAogICAgICAgICJtZXRhbGxpY0ZhY3RvciI6IDAsCiAgICAgICAgInJvdWdobmVzc0ZhY3RvciI6IDAuOTYKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgIm5hbWUiOiAibWV0YWwtZGFyayIsCiAgICAgICJwYnJNZXRhbGxpY1JvdWdobmVzcyI6IHsKICAgICAgICAiYmFzZUNvbG9yRmFjdG9yIjogWwogICAgICAgICAgMC4yMSwKICAgICAgICAgIDAuMjIsCiAgICAgICAgICAwLjI0LAogICAgICAgICAgMQogICAgICAgIF0sCiAgICAgICAgIm1ldGFsbGljRmFjdG9yIjogMC44NCwKICAgICAgICAicm91Z2huZXNzRmFjdG9yIjogMC4zNAogICAgICB9CiAgICB9LAogICAgewogICAgICAibmFtZSI6ICJ3YXJtLWdsYXNzIiwKICAgICAgInBick1ldGFsbGljUm91Z2huZXNzIjogewogICAgICAgICJiYXNlQ29sb3JGYWN0b3IiOiBbCiAgICAgICAgICAwLjk1LAogICAgICAgICAgMC44MiwKICAgICAgICAgIDAuNTYsCiAgICAgICAgICAwLjg0CiAgICAgICAgXSwKICAgICAgICAibWV0YWxsaWNGYWN0b3IiOiAwLjAyLAogICAgICAgICJyb3VnaG5lc3NGYWN0b3IiOiAwLjE2CiAgICAgIH0sCiAgICAgICJlbWlzc2l2ZUZhY3RvciI6IFsKICAgICAgICAwLjkyLAogICAgICAgIDAuNywKICAgICAgICAwLjM0CiAgICAgIF0sCiAgICAgICJhbHBoYU1vZGUiOiAiQkxFTkQiCiAgICB9CiAgXSwKICAiYnVmZmVycyI6IFsKICAgIHsKICAgICAgInVyaSI6ICJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsQUFBQUFJWHJVYi9Oekl6QWZQS3dQc2U2dUw3TnpJekFsLzhRUDlQZTRMNEFBRkRBQUFBQUFJWHJVYi9Oekl6QWwvOFFQOVBlNEw0QUFGREFBQUFBQUkvQ2RiOEFBRkRBZlBLd1BzZTZ1TDdOekl6QW5ETWlQeHBSMmo3TnpJekFTK3FFUDBJKzZENEFBRkRBZlBLd1BzZTZ1TDdOekl6QVMrcUVQMEkrNkQ0QUFGREFsLzhRUDlQZTRMNEFBRkRBbkRNaVB4cFIyajdOekl6QTdGRTRQNFhyVVQvTnpJekFQUXFYUDJabVpqOEFBRkRBbkRNaVB4cFIyajdOekl6QVBRcVhQMlptWmo4QUFGREFTK3FFUDBJKzZENEFBRkRBN0ZFNHY0WHJVVC9Oekl6QW5ETWl2eHBSMmo3TnpJekFTK3FFdjBJKzZENEFBRkRBN0ZFNHY0WHJVVC9Oekl6QVMrcUV2MEkrNkQ0QUFGREFQUXFYdjJabVpqOEFBRkRBbkRNaXZ4cFIyajdOekl6QWZQS3d2c2U2dUw3TnpJekFsLzhRdjlQZTRMNEFBRkRBbkRNaXZ4cFIyajdOekl6QWwvOFF2OVBlNEw0QUFGREFTK3FFdjBJKzZENEFBRkRBZlBLd3ZzZTZ1TDdOekl6QUFBQUFBSVhyVWIvTnpJekFBQUFBQUkvQ2RiOEFBRkRBZlBLd3ZzZTZ1TDdOekl6QUFBQUFBSS9DZGI4QUFGREFsLzhRdjlQZTRMNEFBRkRBQUFBQUFJL0NkYjhBQUZEQWwvOFFQOVBlNEw0QUFGREFvV2N6UDQvazhyNW1aZ2JBQUFBQUFJL0NkYjhBQUZEQW9XY3pQNC9rOHI1bVpnYkFBQUFBQUxnZWhiOW1aZ2JBbC84UVA5UGU0TDRBQUZEQVMrcUVQMEkrNkQ0QUFGREFWSFNrUDl1Sy9UNW1aZ2JBbC84UVA5UGU0TDRBQUZEQVZIU2tQOXVLL1Q1bVpnYkFvV2N6UDQvazhyNW1aZ2JBUytxRVAwSSs2RDRBQUZEQVBRcVhQMlptWmo4QUFGREFTT0c2UDBqaGVqOW1aZ2JBUytxRVAwSSs2RDRBQUZEQVNPRzZQMGpoZWo5bVpnYkFWSFNrUDl1Sy9UNW1aZ2JBUFFxWHYyWm1aajhBQUZEQVMrcUV2MEkrNkQ0QUFGREFWSFNrdjl1Sy9UNW1aZ2JBUFFxWHYyWm1aajhBQUZEQVZIU2t2OXVLL1Q1bVpnYkFTT0c2djBqaGVqOW1aZ2JBUytxRXYwSSs2RDRBQUZEQWwvOFF2OVBlNEw0QUFGREFvV2N6djQvazhyNW1aZ2JBUytxRXYwSSs2RDRBQUZEQW9XY3p2NC9rOHI1bVpnYkFWSFNrdjl1Sy9UNW1aZ2JBbC84UXY5UGU0TDRBQUZEQUFBQUFBSS9DZGI4QUFGREFBQUFBQUxnZWhiOW1aZ2JBbC84UXY5UGU0TDRBQUZEQUFBQUFBTGdlaGI5bVpnYkFvV2N6djQvazhyNW1aZ2JBQUFBQUFMZ2VoYjltWmdiQW9XY3pQNC9rOHI1bVpnYkFnU1pDUDIzbis3NHpNek8vQUFBQUFMZ2VoYjltWmdiQWdTWkNQMjNuKzc0ek16Ty9BQUFBQUhFOWlyOHpNek8vb1djelA0L2s4cjVtWmdiQVZIU2tQOXVLL1Q1bVpnYkFvZml4UDVNWUJEOHpNek8vb1djelA0L2s4cjVtWmdiQW9maXhQNU1ZQkQ4ek16Ty9nU1pDUDIzbis3NHpNek8vVkhTa1A5dUsvVDVtWmdiQVNPRzZQMGpoZWo5bVpnYkFjVDNLUDF5UGdqOHpNek8vVkhTa1A5dUsvVDVtWmdiQWNUM0tQMXlQZ2o4ek16Ty9vZml4UDVNWUJEOHpNek8vU09HNnYwamhlajltWmdiQVZIU2t2OXVLL1Q1bVpnYkFvZml4djVNWUJEOHpNek8vU09HNnYwamhlajltWmdiQW9maXh2NU1ZQkQ4ek16Ty9jVDNLdjF5UGdqOHpNek8vVkhTa3Y5dUsvVDVtWmdiQW9XY3p2NC9rOHI1bVpnYkFnU1pDdjIzbis3NHpNek8vVkhTa3Y5dUsvVDVtWmdiQWdTWkN2MjNuKzc0ek16Ty9vZml4djVNWUJEOHpNek8vb1djenY0L2s4cjVtWmdiQUFBQUFBTGdlaGI5bVpnYkFBQUFBQUhFOWlyOHpNek8vb1djenY0L2s4cjVtWmdiQUFBQUFBSEU5aXI4ek16Ty9nU1pDdjIzbis3NHpNek8vQUFBQUFIRTlpcjh6TXpPL2dTWkNQMjNuKzc0ek16Ty9WbjB1UDBDazM3NW1ab1kvQUFBQUFIRTlpcjh6TXpPL1ZuMHVQMENrMzc1bVpvWS9BQUFBQUVqaGVyOW1ab1kvZ1NaQ1AyM24rNzR6TXpPL29maXhQNU1ZQkQ4ek16Ty81ZktmUC84aC9UNW1ab1kvZ1NaQ1AyM24rNzR6TXpPLzVmS2ZQLzhoL1Q1bVpvWS9WbjB1UDBDazM3NW1ab1kvb2ZpeFA1TVlCRDh6TXpPL2NUM0tQMXlQZ2o4ek16Ty9qOEsxUDQvQ2RUOW1ab1kvb2ZpeFA1TVlCRDh6TXpPL2o4SzFQNC9DZFQ5bVpvWS81ZktmUC84aC9UNW1ab1kvY1QzS3YxeVBnajh6TXpPL29maXh2NU1ZQkQ4ek16Ty81Zktmdi84aC9UNW1ab1kvY1QzS3YxeVBnajh6TXpPLzVmS2Z2LzhoL1Q1bVpvWS9qOEsxdjQvQ2RUOW1ab1kvb2ZpeHY1TVlCRDh6TXpPL2dTWkN2MjNuKzc0ek16Ty9WbjB1djBDazM3NW1ab1kvb2ZpeHY1TVlCRDh6TXpPL1ZuMHV2MENrMzc1bVpvWS81Zktmdi84aC9UNW1ab1kvZ1NaQ3YyM24rNzR6TXpPL0FBQUFBSEU5aXI4ek16Ty9BQUFBQUVqaGVyOW1ab1kvZ1NaQ3YyM24rNzR6TXpPL0FBQUFBRWpoZXI5bVpvWS9WbjB1djBDazM3NW1ab1kvQUFBQUFFamhlcjltWm9ZL1ZuMHVQMENrMzc1bVpvWS9zQVBuUGpTQXQ3NHpNeU5BQUFBQUFFamhlcjltWm9ZL3NBUG5QalNBdDc0ek15TkFBQUFBQUQwS1Y3OHpNeU5BVm4wdVAwQ2szNzVtWm9ZLzVmS2ZQLzhoL1Q1bVpvWS9ZY05UUDljMDd6NHpNeU5BVm4wdVAwQ2szNzVtWm9ZL1ljTlRQOWMwN3o0ek15TkFzQVBuUGpTQXQ3NHpNeU5BNWZLZlAvOGgvVDVtWm9ZL2o4SzFQNC9DZFQ5bVpvWS8xNk53UDY1SFlUOHpNeU5BNWZLZlAvOGgvVDVtWm9ZLzE2TndQNjVIWVQ4ek15TkFZY05UUDljMDd6NHpNeU5BajhLMXY0L0NkVDltWm9ZLzVmS2Z2LzhoL1Q1bVpvWS9ZY05UdjljMDd6NHpNeU5BajhLMXY0L0NkVDltWm9ZL1ljTlR2OWMwN3o0ek15TkExNk53djY1SFlUOHpNeU5BNWZLZnYvOGgvVDVtWm9ZL1ZuMHV2MENrMzc1bVpvWS9zQVBudmpTQXQ3NHpNeU5BNWZLZnYvOGgvVDVtWm9ZL3NBUG52alNBdDc0ek15TkFZY05UdjljMDd6NHpNeU5BVm4wdXYwQ2szNzVtWm9ZL0FBQUFBRWpoZXI5bVpvWS9BQUFBQUQwS1Y3OHpNeU5BVm4wdXYwQ2szNzVtWm9ZL0FBQUFBRDBLVjc4ek15TkFzQVBudmpTQXQ3NHpNeU5BQUFBQUFEMEtWNzh6TXlOQXNBUG5QalNBdDc0ek15TkErdTNyUGJyYWlyNmFtWGxBQUFBQUFEMEtWNzh6TXlOQSt1M3JQYnJhaXI2YW1YbEFBQUFBQUhzVUxyK2FtWGxBc0FQblBqU0F0NzR6TXlOQVljTlRQOWMwN3o0ek15TkEwRVJZUG9qMDJ6NmFtWGxBc0FQblBqU0F0NzR6TXlOQTBFUllQb2owMno2YW1YbEErdTNyUGJyYWlyNmFtWGxBWWNOVFA5YzA3ejR6TXlOQTE2TndQNjVIWVQ4ek15TkFqOEoxUGhTdVJ6K2FtWGxBWWNOVFA5YzA3ejR6TXlOQWo4SjFQaFN1UnorYW1YbEEwRVJZUG9qMDJ6NmFtWGxBMTZOd3Y2NUhZVDh6TXlOQVljTlR2OWMwN3o0ek15TkEwRVJZdm9qMDJ6NmFtWGxBMTZOd3Y2NUhZVDh6TXlOQTBFUll2b2owMno2YW1YbEFqOEoxdmhTdVJ6K2FtWGxBWWNOVHY5YzA3ejR6TXlOQXNBUG52alNBdDc0ek15TkErdTNydmJyYWlyNmFtWGxBWWNOVHY5YzA3ejR6TXlOQSt1M3J2YnJhaXI2YW1YbEEwRVJZdm9qMDJ6NmFtWGxBc0FQbnZqU0F0NzR6TXlOQUFBQUFBRDBLVjc4ek15TkFBQUFBQUhzVUxyK2FtWGxBc0FQbnZqU0F0NzR6TXlOQUFBQUFBSHNVTHIrYW1YbEErdTNydmJyYWlyNmFtWGxBajhKMVBoU3VSeithbVhsQUFBQUFBTTNNVEQrYW1YbEFqOEoxdmhTdVJ6K2FtWGxBajhKMVBoU3VSeithbVhsQWo4SjF2aFN1UnorYW1YbEEwRVJZdm9qMDJ6NmFtWGxBajhKMVBoU3VSeithbVhsQTBFUll2b2owMno2YW1YbEErdTNydmJyYWlyNmFtWGxBajhKMVBoU3VSeithbVhsQSt1M3J2YnJhaXI2YW1YbEFBQUFBQUhzVUxyK2FtWGxBajhKMVBoU3VSeithbVhsQUFBQUFBSHNVTHIrYW1YbEErdTNyUGJyYWlyNmFtWGxBajhKMVBoU3VSeithbVhsQSt1M3JQYnJhaXI2YW1YbEEwRVJZUG9qMDJ6NmFtWGxBN0ZFNHY0WHJVVC9Oekl6QUFBQUFBUFlvWEQvTnpJekE3RkU0UDRYclVUL056SXpBN0ZFNHY0WHJVVC9Oekl6QTdGRTRQNFhyVVQvTnpJekFuRE1pUHhwUjJqN056SXpBN0ZFNHY0WHJVVC9Oekl6QW5ETWlQeHBSMmo3TnpJekFmUEt3UHNlNnVMN056SXpBN0ZFNHY0WHJVVC9Oekl6QWZQS3dQc2U2dUw3TnpJekFBQUFBQUlYclViL056SXpBN0ZFNHY0WHJVVC9Oekl6QUFBQUFBSVhyVWIvTnpJekFmUEt3dnNlNnVMN056SXpBN0ZFNHY0WHJVVC9Oekl6QWZQS3d2c2U2dUw3TnpJekFuRE1pdnhwUjJqN056SXpBeHNoSVArY2NGNy8vYUVPK3hzaElQK2NjRjcvL2FFTyt4c2hJUCtjY0Y3Ly9hRU8rUHBVc1A2V3hPNzh0ekxhOVBwVXNQNld4Tzc4dHpMYTlQcFVzUDZXeE83OHR6TGE5aGRCa1A5OXNwNzRlSUoyK2hkQmtQOTlzcDc0ZUlKMitoZEJrUDk5c3A3NGVJSjIrN05wZFAvcVQ2cjUxWGtxKzdOcGRQL3FUNnI1MVhrcSs3TnBkUC9xVDZyNTFYa3ErekJCcVAyS0ZUYjZiR3JTK3pCQnFQMktGVGI2YkdyUyt6QkJxUDJLRlRiNmJHclMrbk5ablA0a1VrNzVEdkorK25OWm5QNGtVazc1RHZKKytuTlpuUDRrVWs3NUR2SisrN3ROc3YwanlUNzZDUktTKzd0TnN2MGp5VDc2Q1JLUys3dE5zdjBqeVQ3NkNSS1MrVDVObHZ3YWxrYjVPaDYyK1Q1Tmx2d2Fsa2I1T2g2MitUNU5sdndhbGtiNU9oNjIrZHBOcnYybGZyTDdQYkV5K2RwTnJ2Mmxmckw3UGJFeStkcE5ydjJsZnJMN1BiRXkrSE1SWXYzTXk1YjZxTHBPK0hNUll2M015NWI2cUxwTytITVJZdjNNeTViNnFMcE8rVFA5THYvS0hHYitnaHBXOVRQOUx2L0tIR2IrZ2hwVzlUUDlMdi9LSEdiK2docFc5b0ljcXZ3RjJPYitSaWpXK29JY3F2d0YyT2IrUmlqVytvSWNxdndGMk9iK1JpalcrOG1Jc1AvSjZPNzhFRmMrOThtSXNQL0o2Tzc4RUZjKzk4bUlzUC9KNk83OEVGYys5allzZ1ArbnJScitIYUYyOWpZc2dQK25yUnIrSGFGMjlqWXNnUCtuclJyK0hhRjI5UUFaZlAzblE2NzY2RkM2K1FBWmZQM25RNjc2NkZDNitRQVpmUDNuUTY3NjZGQzYrQjlaWlAzTTBBNytaeSt1OUI5WlpQM00wQTcrWnkrdTlCOVpaUDNNMEE3K1p5K3U5S01KdVAyeDRsNzZ2ZEZPK0tNSnVQMng0bDc2dmRGTytLTUp1UDJ4NGw3NnZkRk8rTXBCc1B6djdxcjc0WHo2K01wQnNQenY3cXI3NFh6NitNcEJzUHp2N3FyNzRYejYrUnBWdnYxditsNzQwVmtLK1JwVnZ2MXYrbDc0MFZrSytScFZ2djF2K2w3NDBWa0srQTlkcnYyTjFxcjY1K0UyK0E5ZHJ2Mk4xcXI2NStFMitBOWRydjJOMXFyNjUrRTIrNThSZ3Y3Mm83YjVFUCsrOTU4Umd2NzJvN2I1RVArKzk1OFJndjcybzdiNUVQKys5aGw5WXYrRlNBcjk3bFNhK2hsOVl2K0ZTQXI5N2xTYStobDlZditGU0FyOTdsU2ErUGd3dHZ4RXpQTDltZVZHOVBnd3R2eEV6UEw5bWVWRzlQZ3d0dnhFelBMOW1lVkc5bGdZZ3Z5cEhScjlhSzhhOWxnWWd2eXBIUnI5YUs4YTlsZ1lndnlwSFJyOWFLOGE5bzYwZ1B5VVdSNzhwMFJHOW82MGdQeVVXUjc4cDBSRzlvNjBnUHlVV1I3OHAwUkc5Z2RFY1A0RkRTcjlEN2JpOGdkRWNQNEZEU3I5RDdiaThnZEVjUDRGRFNyOUQ3Ymk4alBCYVA1M2VBNyt2NFdpOWpQQmFQNTNlQTcrdjRXaTlqUEJhUDUzZUE3K3Y0V2k5QTdWWVB6WGZCNzhlL0NtOUE3VllQelhmQjc4ZS9DbTlBN1ZZUHpYZkI3OGUvQ205WXlod1AxS1VyYjZMMTVDOVl5aHdQMUtVcmI2TDE1QzlZeWh3UDFLVXJiNkwxNUM5bWhodlB5L2tzNzQwbG9XOW1oaHZQeS9rczc0MGxvVzltaGh2UHkva3M3NDBsb1c5WGoxd3YzeWpyYjcvcFlhOVhqMXd2M3lqcmI3L3BZYTlYajF3djN5anJiNy9wWWE5eXdSdnYwalZzNzZnV0krOXl3UnZ2MGpWczc2Z1dJKzl5d1J2djBqVnM3NmdXSSs5aWhwYnYrajNBNy8reGlxOWlocGJ2K2ozQTcvK3hpcTlpaHBiditqM0E3Lyt4aXE5OG8xWXY3YkdCNzhKRTJXOThvMVl2N2JHQjc4SkUyVzk4bzFZdjdiR0I3OEpFMlc5ajcwZ3Y5OHBSNytvRjdhOGo3MGd2OThwUjcrb0Y3YThqNzBndjk4cFI3K29GN2E4OXNJY3Y4QXdTci94M0ErOTlzSWN2OEF3U3IveDNBKzk5c0ljdjhBd1NyL3gzQSs5NzZVY1AwOExTcjl5OWxNOTc2VWNQMDhMU3I5eTlsTTk3NlVjUDA4TFNyOXk5bE05MjJNZlB5QUFTTCtMMnpZOTIyTWZQeUFBU0wrTDJ6WTkyMk1mUHlBQVNMK0wyelk5eEh0WVAxQzdCNytQNEhzOXhIdFlQMUM3QjcrUDRIczl4SHRZUDFDN0I3K1A0SHM5R3p4YVA2QWRCYjk2YTF3OUd6eGFQNkFkQmI5NmExdzlHenhhUDZBZEJiOTZhMXc5TlBadVAwN0tzNzVpSUpZOU5QWnVQMDdLczc1aUlKWTlOUFp1UDA3S3M3NWlJSlk5OWN0dlAzU0ZyNzVlcnBFOTljdHZQM1NGcjc1ZXJwRTk5Y3R2UDNTRnI3NWVycEU5WWdGdnY3ZlNzNzZjOVpBOVlnRnZ2N2ZTczc2YzlaQTlZZ0Z2djdmU3M3NmM5WkE5czc5dnYzdDhyNzdlU3BjOXM3OXZ2M3Q4cjc3ZVNwYzlzNzl2djN0OHI3N2VTcGM5UVpSWXY2dktCNytZbTF3OVFaUll2NnZLQjcrWW0xdzlRWlJZdjZ2S0I3K1ltMXc5RFNGYXZ4OE5CYjlsaG40OURTRmF2eDhOQmI5bGhuNDlEU0Zhdng4TkJiOWxobjQ5MnJJY3Yva2JTcjhleVRnOTJySWN2L2tiU3I4ZXlUZzkyckljdi9rYlNyOGV5VGc5YlZVZnZ3WHVSNzhCeUZROWJWVWZ2d1h1Ujc4QnlGUTliVlVmdndYdVI3OEJ5RlE5dlJRZVA2QmJScjlTbUFvK3ZSUWVQNkJiUnI5U21Bbyt2UlFlUDZCYlJyOVNtQW8rdlhBNlAvYXJMci9yYTRJOXZYQTZQL2FyTHIvcmE0STl2WEE2UC9hckxyL3JhNEk5RC9KVVA3VGpBYi9IY0dZK0QvSlVQN1RqQWIvSGNHWStEL0pVUDdUakFiL0hjR1kraXY5bFA1WiswYjdHTlNNK2l2OWxQNVorMGI3R05TTStpdjlsUDVaKzBiN0dOU00rNjE1blA1ZGFxYjZMQzRzKzYxNW5QNWRhcWI2TEM0cys2MTVuUDVkYXFiNkxDNHMrdnBodVAxWmxncjVjQTRRK3ZwaHVQMVpsZ3I1Y0E0USt2cGh1UDFabGdyNWNBNFErWGNWb3YvVmdxcjdQQVlBK1hjVm92L1ZncXI3UEFZQStYY1Zvdi9WZ3FyN1BBWUErR2VGc3Z4RjFnYjdJc3BBK0dlRnN2eEYxZ2I3SXNwQStHZUZzdnhGMWdiN0lzcEErcU54WHZ4cXJBNzh1SnlBK3FOeFh2eHFyQTc4dUp5QStxTnhYdnhxckE3OHVKeUErRkJaaXYyanV6Yjd5TVhjK0ZCWml2Mmp1emI3eU1YYytGQlppdjJqdXpiN3lNWGMrTmlBZnZ6K3JSNzhORnBVOU5pQWZ2eityUjc4TkZwVTlOaUFmdnorclI3OE5GcFU5cXM4NHZ6Y2xMYjgydnhVK3FzODR2emNsTGI4MnZ4VStxczg0dnpjbExiODJ2eFUrWnpzMlA2RzZLcitRaUdFK1p6czJQNkc2S3IrUWlHRStaenMyUDZHNktyK1FpR0UrcTBaMlB5Zk5pcjZ4bWdNOXEwWjJQeWZOaXI2eG1nTTlxMFoyUHlmTmlyNnhtZ005Q3dsWVA4REd4TDd4cTc4K0N3bFlQOERHeEw3eHE3OCtDd2xZUDhER3hMN3hxNzgrOWI1MVA4S25Ccjc1V1gwKzliNTFQOEtuQnI3NVdYMCs5YjUxUDhLbkJyNzVXWDArSjVKZVAzSkdjNzdaemQwK0o1SmVQM0pHYzc3WnpkMCtKNUplUDNKR2M3N1p6ZDArZFhOb1B6SFltTDJkRWRNK2RYTm9QekhZbUwyZEVkTStkWE5vUHpIWW1MMmRFZE0rTXFGaXZ5UzJkNzcyWHNzK01xRml2eVMyZDc3MlhzcytNcUZpdnlTMmQ3NzJYc3MrNkRoanZ3eG9sYjBFMytnKzZEaGp2d3hvbGIwRTMrZys2RGhqdnd4b2xiMEUzK2crWGRoaHZ6RzJ6YjZVYW5zK1hkaGh2ekcyemI2VWFucytYZGhodnpHMnpiNlVhbnMrZW5CbnY5YWgvYjJlY2RFK2VuQm52OWFoL2IyZWNkRStlbkJudjlhaC9iMmVjZEUra2pVNnY0ZDBMci9NYUtVOWtqVTZ2NGQwTHIvTWFLVTlralU2djRkMExyL01hS1U5dmFSdXYrdC9ocjVQOVg0K3ZhUnV2K3QvaHI1UDlYNCt2YVJ1dit0L2hyNVA5WDQrQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQkFBSUFBd0FFQUFVQUJnQUhBQWdBQ1FBS0FBc0FEQUFOQUE0QUR3QVFBQkVBRWdBVEFCUUFGUUFXQUJjQUdBQVpBQm9BR3dBY0FCMEFIZ0FmQUNBQUlRQWlBQ01BSkFBbEFDWUFKd0FvQUNrQUtnQXJBQ3dBTFFBdUFDOEFNQUF4QURJQU13QTBBRFVBTmdBM0FEZ0FPUUE2QURzQVBBQTlBRDRBUHdCQUFFRUFRZ0JEQUVRQVJRQkdBRWNBU0FCSkFFb0FTd0JNQUUwQVRnQlBBRkFBVVFCU0FGTUFWQUJWQUZZQVZ3QllBRmtBV2dCYkFGd0FYUUJlQUY4QVlBQmhBR0lBWXdCa0FHVUFaZ0JuQUdnQWFRQnFBR3NBYkFCdEFHNEFid0J3QUhFQWNnQnpBSFFBZFFCMkFIY0FlQUI1QUhvQWV3QjhBSDBBZmdCL0FJQUFnUUNDQUlNQWhBQ0ZBSVlBaHdDSUFJa0FpZ0NMQUl3QWpRQ09BSThBa0FDUkFKSUFrd0NVQUpVQWxnQ1hBSmdBbVFDYUFKc0FuQUNkQUo0QW53Q2dBS0VBb2dDakFLUUFwUUNtQUtjQXFBQ3BBS29BcXdDc0FLMEFyZ0N2QUxBQXNRQ3lBTE1BdEFDMUFMWUF0d0M0QUxrQXVnQzdBTHdBdlFDK0FMOEF3QURCQU1JQXd3REVBTVVBeGdESEFNZ0F5UURLQU1zQXpBRE5BTTRBendEUUFORUEwZ0RUQU5RQTFRRFdBTmNBMkFEWkFOb0Eyd0RjQU4wQTNnRGZBT0FBNFFEaUFPTUE1QURsQU9ZQTV3RG9BT2tBNmdEckFPd0E3UUR1QU84QThBRHhBUElBOHdEMEFQVUE5Z0QzQVBnQStRRDZBUHNBQUFBQUFQWW9YRC9Oekl6QTdGRTRQNFhyVVQvTnpJekFQUXFYUDJabVpqOEFBRkRBQUFBQUFQWW9YRC9Oekl6QVBRcVhQMlptWmo4QUFGREFBQUFBQURNemN6OEFBRkRBN0ZFNHY0WHJVVC9Oekl6QUFBQUFBUFlvWEQvTnpJekFBQUFBQURNemN6OEFBRkRBN0ZFNHY0WHJVVC9Oekl6QUFBQUFBRE16Y3o4QUFGREFQUXFYdjJabVpqOEFBRkRBQUFBQUFETXpjejhBQUZEQVBRcVhQMlptWmo4QUFGREFTT0c2UDBqaGVqOW1aZ2JBQUFBQUFETXpjejhBQUZEQVNPRzZQMGpoZWo5bVpnYkFBQUFBQUFyWGd6OW1aZ2JBUFFxWHYyWm1aajhBQUZEQUFBQUFBRE16Y3o4QUFGREFBQUFBQUFyWGd6OW1aZ2JBUFFxWHYyWm1aajhBQUZEQUFBQUFBQXJYZ3o5bVpnYkFTT0c2djBqaGVqOW1aZ2JBQUFBQUFBclhnejltWmdiQVNPRzZQMGpoZWo5bVpnYkFjVDNLUDF5UGdqOHpNek8vQUFBQUFBclhnejltWmdiQWNUM0tQMXlQZ2o4ek16Ty9BQUFBQUhFOWlqOHpNek8vU09HNnYwamhlajltWmdiQUFBQUFBQXJYZ3o5bVpnYkFBQUFBQUhFOWlqOHpNek8vU09HNnYwamhlajltWmdiQUFBQUFBSEU5aWo4ek16Ty9jVDNLdjF5UGdqOHpNek8vQUFBQUFIRTlpajh6TXpPL2NUM0tQMXlQZ2o4ek16Ty9qOEsxUDQvQ2RUOW1ab1kvQUFBQUFIRTlpajh6TXpPL2o4SzFQNC9DZFQ5bVpvWS9BQUFBQUs1SGdUOW1ab1kvY1QzS3YxeVBnajh6TXpPL0FBQUFBSEU5aWo4ek16Ty9BQUFBQUs1SGdUOW1ab1kvY1QzS3YxeVBnajh6TXpPL0FBQUFBSzVIZ1Q5bVpvWS9qOEsxdjQvQ2RUOW1ab1kvQUFBQUFLNUhnVDltWm9ZL2o4SzFQNC9DZFQ5bVpvWS8xNk53UDY1SFlUOHpNeU5BQUFBQUFLNUhnVDltWm9ZLzE2TndQNjVIWVQ4ek15TkFBQUFBQUIrRmF6OHpNeU5BajhLMXY0L0NkVDltWm9ZL0FBQUFBSzVIZ1Q5bVpvWS9BQUFBQUIrRmF6OHpNeU5BajhLMXY0L0NkVDltWm9ZL0FBQUFBQitGYXo4ek15TkExNk53djY1SFlUOHpNeU5BQUFBQUFCK0Zhejh6TXlOQTE2TndQNjVIWVQ4ek15TkFqOEoxUGhTdVJ6K2FtWGxBQUFBQUFCK0Zhejh6TXlOQWo4SjFQaFN1UnorYW1YbEFBQUFBQU0zTVREK2FtWGxBMTZOd3Y2NUhZVDh6TXlOQUFBQUFBQitGYXo4ek15TkFBQUFBQU0zTVREK2FtWGxBMTZOd3Y2NUhZVDh6TXlOQUFBQUFBTTNNVEQrYW1YbEFqOEoxdmhTdVJ6K2FtWGxBZXhRdXZ3QUFnRCthbVJtL2V4UXVQd0FBZ0QrYW1SbS9leFF1UDdnZXhUK2FtUm0vZXhRdXZ3QUFnRCthbVJtL2V4UXVQN2dleFQrYW1SbS9leFF1djdnZXhUK2FtUm0vZXhRdVB3QUFnRDltWmhiQWV4UXV2d0FBZ0Q5bVpoYkFleFF1djdnZXhUOW1aaGJBZXhRdVB3QUFnRDltWmhiQWV4UXV2N2dleFQ5bVpoYkFleFF1UDdnZXhUOW1aaGJBZXhRdXZ3QUFnRDltWmhiQWV4UXV2d0FBZ0QrYW1SbS9leFF1djdnZXhUK2FtUm0vZXhRdXZ3QUFnRDltWmhiQWV4UXV2N2dleFQrYW1SbS9leFF1djdnZXhUOW1aaGJBZXhRdVB3QUFnRCthbVJtL2V4UXVQd0FBZ0Q5bVpoYkFleFF1UDdnZXhUOW1aaGJBZXhRdVB3QUFnRCthbVJtL2V4UXVQN2dleFQ5bVpoYkFleFF1UDdnZXhUK2FtUm0vZXhRdXY3Z2V4VCthbVJtL2V4UXVQN2dleFQrYW1SbS9leFF1UDdnZXhUOW1aaGJBZXhRdXY3Z2V4VCthbVJtL2V4UXVQN2dleFQ5bVpoYkFleFF1djdnZXhUOW1aaGJBZXhRdXZ3QUFnRDltWmhiQWV4UXVQd0FBZ0Q5bVpoYkFleFF1UHdBQWdEK2FtUm0vZXhRdXZ3QUFnRDltWmhiQWV4UXVQd0FBZ0QrYW1SbS9leFF1dndBQWdEK2FtUm0vcmtmaHZseVBnaithbWRrL3JrZmhQbHlQZ2orYW1kay9ya2ZoUHRlanNEK2FtZGsvcmtmaHZseVBnaithbWRrL3JrZmhQdGVqc0QrYW1kay9ya2ZodnRlanNEK2FtZGsvcmtmaFBseVBnajhBQUFBL3JrZmh2bHlQZ2o4QUFBQS9ya2ZodnRlanNEOEFBQUEvcmtmaFBseVBnajhBQUFBL3JrZmh2dGVqc0Q4QUFBQS9ya2ZoUHRlanNEOEFBQUEvcmtmaHZseVBnajhBQUFBL3JrZmh2bHlQZ2orYW1kay9ya2ZodnRlanNEK2FtZGsvcmtmaHZseVBnajhBQUFBL3JrZmh2dGVqc0QrYW1kay9ya2ZodnRlanNEOEFBQUEvcmtmaFBseVBnaithbWRrL3JrZmhQbHlQZ2o4QUFBQS9ya2ZoUHRlanNEOEFBQUEvcmtmaFBseVBnaithbWRrL3JrZmhQdGVqc0Q4QUFBQS9ya2ZoUHRlanNEK2FtZGsvcmtmaHZ0ZWpzRCthbWRrL3JrZmhQdGVqc0QrYW1kay9ya2ZoUHRlanNEOEFBQUEvcmtmaHZ0ZWpzRCthbWRrL3JrZmhQdGVqc0Q4QUFBQS9ya2ZodnRlanNEOEFBQUEvcmtmaHZseVBnajhBQUFBL3JrZmhQbHlQZ2o4QUFBQS9ya2ZoUGx5UGdqK2FtZGsvcmtmaHZseVBnajhBQUFBL3JrZmhQbHlQZ2orYW1kay9ya2Zodmx5UGdqK2FtZGsvekVGaXZRYUtmcjl4NkxvOXpFRml2UWFLZnI5eDZMbzl6RUZpdlFhS2ZyOXg2TG85UnVBc3ZRRCtmcisxcFo4OVJ1QXN2UUQrZnIrMXBaODlSdUFzdlFEK2ZyKzFwWjg5eElOaVBUM1VmcitQaTU4OXhJTmlQVDNVZnIrUGk1ODl4SU5pUFQzVWZyK1BpNTg5Y3NJc1BRTFNmcjl2WGJBOWNzSXNQUUxTZnI5dlhiQTljc0lzUFFMU2ZyOXZYYkE5cGRvc3ZiUDFmcjhMNzZJOXBkb3N2YlAxZnI4TDc2STlwZG9zdmJQMWZyOEw3Nkk5ck5vTHZlRTdmNzhRQzQ0OXJOb0x2ZUU3Zjc4UUM0NDlyTm9MdmVFN2Y3OFFDNDQ5aGZ3c1Bhc25mNy9SLzQwOWhmd3NQYXNuZjcvUi80MDloZndzUGFzbmY3L1IvNDA5ME1RTFBmc1RmNy9KK0o0OTBNUUxQZnNUZjcvSitKNDkwTVFMUGZzVGY3L0orSjQ5VVI4TXZTaTVmNytkNlFBOVVSOE12U2k1ZjcrZDZRQTlVUjhNdlNpNWY3K2Q2UUE5V0ZVYnZTS25mNzljRmhJOVdGVWJ2U0tuZjc5Y0ZoSTlXRlVidlNLbmY3OWNGaEk5UWhvTVBldXZmNzlpR3hJOVFob01QZXV2Zjc5aUd4STlRaG9NUGV1dmY3OWlHeEk5amxvYlBiU3ZmNytETXdJOWpsb2JQYlN2ZjcrRE13STlqbG9iUGJTdmY3K0RNd0k5WGxJYnZUdWlmNzhvYnhxOVhsSWJ2VHVpZjc4b2J4cTlYbElidlR1aWY3OG9ieHE5WUFVUXZTU2pmNytjbXlPOVlBVVF2U1NqZjcrY215TzlZQVVRdlNTamY3K2NteU85Nms0YlBZdWNmNzlqbHlPOTZrNGJQWXVjZjc5amx5Tzk2azRiUFl1Y2Y3OWpseU85N2dnUVBYU3BmNy93YWhtOTdnZ1FQWFNwZjcvd2FobTk3Z2dRUFhTcGY3L3dhaG05S3RZUHZWZFBmNzh6OG9POUt0WVB2VmRQZjc4ejhvTzlLdFlQdlZkUGY3OHo4b085QjlRdHZXdFBmNzhLR1hXOUI5UXR2V3RQZjc4S0dYVzlCOVF0dld0UGY3OEtHWFc5cXVBUFBmdGhmNy9kS25XOXF1QVBQZnRoZjcvZEtuVzlxdUFQUGZ0aGY3L2RLblc5aE1BdFBjRXlmNzlXcjRpOWhNQXRQY0V5Zjc5V3I0aTloTUF0UGNFeWY3OVdyNGk5cmxjdHZjZVlmcjhWME1POXJsY3R2Y2VZZnI4VjBNTzlybGN0dmNlWWZyOFYwTU85N1dtcHZlTWVmcjlCdGJTOTdXbXB2ZU1lZnI5QnRiUzk3V21wdmVNZWZyOUJ0YlM5SlhVdFBRN0VmcisxS3JXOUpYVXRQUTdFZnIrMUtyVzlKWFV0UFE3RWZyKzFLclc5WCsyb1BRNWtmYi9idisyOVgrMm9QUTVrZmIvYnYrMjlYKzJvUFE1a2ZiL2J2KzI5QUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQkFBSUFBd0FFQUFVQUJnQUhBQWdBQ1FBS0FBc0FEQUFOQUE0QUR3QVFBQkVBRWdBVEFCUUFGUUFXQUJjQUdBQVpBQm9BR3dBY0FCMEFIZ0FmQUNBQUlRQWlBQ01BSkFBbEFDWUFKd0FvQUNrQUtnQXJBQ3dBTFFBdUFDOEFNQUF4QURJQU13QTBBRFVBTmdBM0FEZ0FPUUE2QURzQVBBQTlBRDRBUHdCQUFFRUFRZ0JEQUVRQVJRQkdBRWNBU0FCSkFFb0FTd0JNQUUwQVRnQlBBRkFBVVFCU0FGTUFWQUJWQUZZQVZ3QllBRmtBV2dCYkFGd0FYUUJlQUY4QVlBQmhBR0lBWXdCa0FHVUFaZ0JuQUdnQWFRQnFBR3NBYkFCdEFHNEFid0J3QUhFQWNnQnpBSFFBZFFCMkFIY0FlQUI1QUhvQWV3QjhBSDBBZmdCL0FJQUFnUUNDQUlNQWhBQ0ZBSVlBaHdDSUFJa0FpZ0NMQUl3QWpRQ09BSThBcEhDOXZ6MEtWeithbVJsQXBIQzlQejBLVnorYW1SbEFwSEM5UHpNemN6K2FtUmxBcEhDOXZ6MEtWeithbVJsQXBIQzlQek16Y3orYW1SbEFwSEM5dnpNemN6K2FtUmxBcEhDOVB6MEtWei9OekF6QXBIQzl2ejBLVnovTnpBekFwSEM5dnpNemN6L056QXpBcEhDOVB6MEtWei9OekF6QXBIQzl2ek16Y3ovTnpBekFwSEM5UHpNemN6L056QXpBcEhDOXZ6MEtWei9OekF6QXBIQzl2ejBLVnorYW1SbEFwSEM5dnpNemN6K2FtUmxBcEhDOXZ6MEtWei9OekF6QXBIQzl2ek16Y3orYW1SbEFwSEM5dnpNemN6L056QXpBcEhDOVB6MEtWeithbVJsQXBIQzlQejBLVnovTnpBekFwSEM5UHpNemN6L056QXpBcEhDOVB6MEtWeithbVJsQXBIQzlQek16Y3ovTnpBekFwSEM5UHpNemN6K2FtUmxBcEhDOXZ6TXpjeithbVJsQXBIQzlQek16Y3orYW1SbEFwSEM5UHpNemN6L056QXpBcEhDOXZ6TXpjeithbVJsQXBIQzlQek16Y3ovTnpBekFwSEM5dnpNemN6L056QXpBcEhDOXZ6MEtWei9OekF6QXBIQzlQejBLVnovTnpBekFwSEM5UHowS1Z6K2FtUmxBcEhDOXZ6MEtWei9OekF6QXBIQzlQejBLVnorYW1SbEFwSEM5dnowS1Z6K2FtUmxBS1Z3UHZ4K0Zxejk3Rkc2L0tWd1BQeCtGcXo5N0ZHNi9oZXZSUGlsY3p6OTdGRzYvS1Z3UHZ4K0Zxejk3Rkc2L2hldlJQaWxjeno5N0ZHNi9oZXZSdmlsY3p6OTdGRzYvS1Z3UFB4K0ZxeitGNndIQUtWd1B2eCtGcXorRjZ3SEFoZXZSdmlsY3p6K0Y2d0hBS1Z3UFB4K0ZxeitGNndIQWhldlJ2aWxjenorRjZ3SEFoZXZSUGlsY3p6K0Y2d0hBS1Z3UHZ4K0ZxeitGNndIQUtWd1B2eCtGcXo5N0ZHNi9oZXZSdmlsY3p6OTdGRzYvS1Z3UHZ4K0ZxeitGNndIQWhldlJ2aWxjeno5N0ZHNi9oZXZSdmlsY3p6K0Y2d0hBS1Z3UFB4K0Zxejk3Rkc2L0tWd1BQeCtGcXorRjZ3SEFoZXZSUGlsY3p6K0Y2d0hBS1Z3UFB4K0Zxejk3Rkc2L2hldlJQaWxjenorRjZ3SEFoZXZSUGlsY3p6OTdGRzYvaGV2UnZpbGN6ejk3Rkc2L2hldlJQaWxjeno5N0ZHNi9oZXZSUGlsY3p6K0Y2d0hBaGV2UnZpbGN6ejk3Rkc2L2hldlJQaWxjenorRjZ3SEFoZXZSdmlsY3p6K0Y2d0hBS1Z3UHZ4K0ZxeitGNndIQUtWd1BQeCtGcXorRjZ3SEFLVndQUHgrRnF6OTdGRzYvS1Z3UHZ4K0ZxeitGNndIQUtWd1BQeCtGcXo5N0ZHNi9LVndQdngrRnF6OTdGRzYvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvcktoaHZ3SEg4VDRBQUFBQXJLaGh2d0hIOFQ0QUFBQUFyS2hodndISDhUNEFBQUFBcktoaHZ3SEg4VDRBQUFBQXJLaGh2d0hIOFQ0QUFBQUFyS2hodndISDhUNEFBQUFBcktoaFB3SEg4VDRBQUFBQXJLaGhQd0hIOFQ0QUFBQUFyS2hoUHdISDhUNEFBQUFBcktoaFB3SEg4VDRBQUFBQXJLaGhQd0hIOFQ0QUFBQUFyS2hoUHdISDhUNEFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQkFBSUFBd0FFQUFVQUJnQUhBQWdBQ1FBS0FBc0FEQUFOQUE0QUR3QVFBQkVBRWdBVEFCUUFGUUFXQUJjQUdBQVpBQm9BR3dBY0FCMEFIZ0FmQUNBQUlRQWlBQ01BSkFBbEFDWUFKd0FvQUNrQUtnQXJBQ3dBTFFBdUFDOEFNQUF4QURJQU13QTBBRFVBTmdBM0FEZ0FPUUE2QURzQVBBQTlBRDRBUHdCQUFFRUFRZ0JEQUVRQVJRQkdBRWNBemN6TVBacVpXVDhmaFd1L0tWeVBQUUFBeUVBZmhXdS8zN2FHUFFBQXlFQVpaR1cvemN6TVBacVpXVDhmaFd1LzM3YUdQUUFBeUVBWlpHVy85WExBUFpxWldUK293MksvOVhMQVBacVpXVCtvdzJLLzM3YUdQUUFBeUVBWlpHVy82S05iUFFBQXlFQlNBR0MvOVhMQVBacVpXVCtvdzJLLzZLTmJQUUFBeUVCU0FHQy95dUtjUFpxWldUK01FRnUveXVLY1BacVpXVCtNRUZ1LzZLTmJQUUFBeUVCU0FHQy9LVndQUFFBQXlFQTJBRnkveXVLY1BacVpXVCtNRUZ1L0tWd1BQUUFBeUVBMkFGeS96Y3hNUFpxWldUK0pXVlcvemN4TVBacVpXVCtKV1ZXL0tWd1BQUUFBeUVBMkFGeS9WQ2RIUEFBQXlFQkwzMW0vemN4TVBacVpXVCtKV1ZXL1ZDZEhQQUFBeUVCTDMxbS9xa0NPUEpxWldUOFZUMUsvcWtDT1BKcVpXVDhWVDFLL1ZDZEhQQUFBeUVCTDMxbS9WQ2RIdkFBQXlFQkwzMW0vcWtDT1BKcVpXVDhWVDFLL1ZDZEh2QUFBeUVCTDMxbS9xa0NPdkpxWldUOFZUMUsvcWtDT3ZKcVpXVDhWVDFLL1ZDZEh2QUFBeUVCTDMxbS9LVndQdlFBQXlFQTJBRnkvcWtDT3ZKcVpXVDhWVDFLL0tWd1B2UUFBeUVBMkFGeS96Y3hNdlpxWldUK0pXVlcvemN4TXZacVpXVCtKV1ZXL0tWd1B2UUFBeUVBMkFGeS82S05idlFBQXlFQlNBR0MvemN4TXZacVpXVCtKV1ZXLzZLTmJ2UUFBeUVCU0FHQy95dUtjdlpxWldUK01FRnUveXVLY3ZacVpXVCtNRUZ1LzZLTmJ2UUFBeUVCU0FHQy8zN2FHdlFBQXlFQVpaR1cveXVLY3ZacVpXVCtNRUZ1LzM3YUd2UUFBeUVBWlpHVy85WExBdlpxWldUK293MksvOVhMQXZacVpXVCtvdzJLLzM3YUd2UUFBeUVBWlpHVy9LVnlQdlFBQXlFQWZoV3UvOVhMQXZacVpXVCtvdzJLL0tWeVB2UUFBeUVBZmhXdS96Y3pNdlpxWldUOGZoV3UvemN6TXZacVpXVDhmaFd1L0tWeVB2UUFBeUVBZmhXdS8zN2FHdlFBQXlFQWxwbkcvemN6TXZacVpXVDhmaFd1LzM3YUd2UUFBeUVBbHBuRy85WExBdlpxWldUK1ZSblMvOVhMQXZacVpXVCtWUm5TLzM3YUd2UUFBeUVBbHBuRy82S05idlFBQXlFRHNDWGUvOVhMQXZacVpXVCtWUm5TLzZLTmJ2UUFBeUVEc0NYZS95dUtjdlpxWldUK3grWHUveXVLY3ZacVpXVCt4K1h1LzZLTmJ2UUFBeUVEc0NYZS9LVndQdlFBQXlFQUhDbnUveXVLY3ZacVpXVCt4K1h1L0tWd1B2UUFBeUVBSENudS96Y3hNdlpxWldUOWEySUMvemN4TXZacVpXVDlhMklDL0tWd1B2UUFBeUVBSENudS9WQ2RIdkFBQXlFRHlLbjIvemN4TXZacVpXVDlhMklDL1ZDZEh2QUFBeUVEeUtuMi9xa0NPdkpxWldUK1VYWUsvcWtDT3ZKcVpXVCtVWFlLL1ZDZEh2QUFBeUVEeUtuMi9WQ2RIUEFBQXlFRHlLbjIvcWtDT3ZKcVpXVCtVWFlLL1ZDZEhQQUFBeUVEeUtuMi9xa0NPUEpxWldUK1VYWUsvcWtDT1BKcVpXVCtVWFlLL1ZDZEhQQUFBeUVEeUtuMi9LVndQUFFBQXlFQUhDbnUvcWtDT1BKcVpXVCtVWFlLL0tWd1BQUUFBeUVBSENudS96Y3hNUFpxWldUOWEySUMvemN4TVBacVpXVDlhMklDL0tWd1BQUUFBeUVBSENudS82S05iUFFBQXlFRHNDWGUvemN4TVBacVpXVDlhMklDLzZLTmJQUUFBeUVEc0NYZS95dUtjUFpxWldUK3grWHUveXVLY1BacVpXVCt4K1h1LzZLTmJQUUFBeUVEc0NYZS8zN2FHUFFBQXlFQWxwbkcveXVLY1BacVpXVCt4K1h1LzM3YUdQUUFBeUVBbHBuRy85WExBUFpxWldUK1ZSblMvOVhMQVBacVpXVCtWUm5TLzM3YUdQUUFBeUVBbHBuRy9LVnlQUFFBQXlFQWZoV3UvOVhMQVBacVpXVCtWUm5TL0tWeVBQUUFBeUVBZmhXdS96Y3pNUFpxWldUOGZoV3UvMzdhR1BRQUF5RUFscG5HLzZLTmJQUUFBeUVEc0NYZS9LVndQUFFBQXlFQUhDbnUvMzdhR1BRQUF5RUFscG5HL0tWd1BQUUFBeUVBSENudS9WQ2RIUEFBQXlFRHlLbjIvMzdhR1BRQUF5RUFscG5HL1ZDZEhQQUFBeUVEeUtuMi9WQ2RIdkFBQXlFRHlLbjIvMzdhR1BRQUF5RUFscG5HL1ZDZEh2QUFBeUVEeUtuMi9LVndQdlFBQXlFQUhDbnUvMzdhR1BRQUF5RUFscG5HL0tWd1B2UUFBeUVBSENudS82S05idlFBQXlFRHNDWGUvMzdhR1BRQUF5RUFscG5HLzZLTmJ2UUFBeUVEc0NYZS8zN2FHdlFBQXlFQWxwbkcvMzdhR1BRQUF5RUFscG5HLzM3YUd2UUFBeUVBbHBuRy9LVnlQdlFBQXlFQWZoV3UvMzdhR1BRQUF5RUFscG5HL0tWeVB2UUFBeUVBZmhXdS8zN2FHdlFBQXlFQVpaR1cvMzdhR1BRQUF5RUFscG5HLzM3YUd2UUFBeUVBWlpHVy82S05idlFBQXlFQlNBR0MvMzdhR1BRQUF5RUFscG5HLzZLTmJ2UUFBeUVCU0FHQy9LVndQdlFBQXlFQTJBRnkvMzdhR1BRQUF5RUFscG5HL0tWd1B2UUFBeUVBMkFGeS9WQ2RIdkFBQXlFQkwzMW0vMzdhR1BRQUF5RUFscG5HL1ZDZEh2QUFBeUVCTDMxbS9WQ2RIUEFBQXlFQkwzMW0vMzdhR1BRQUF5RUFscG5HL1ZDZEhQQUFBeUVCTDMxbS9LVndQUFFBQXlFQTJBRnkvMzdhR1BRQUF5RUFscG5HL0tWd1BQUUFBeUVBMkFGeS82S05iUFFBQXlFQlNBR0MvMzdhR1BRQUF5RUFscG5HLzZLTmJQUUFBeUVCU0FHQy8zN2FHUFFBQXlFQVpaR1cvMzdhR1BRQUF5RUFscG5HLzM3YUdQUUFBeUVBWlpHVy9LVnlQUFFBQXlFQWZoV3UvemN6TVBacVpXVDhmaFd1LzlYTEFQWnFaV1Qrb3cySy95dUtjUFpxWldUK01FRnUvemN6TVBacVpXVDhmaFd1L3l1S2NQWnFaV1QrTUVGdS96Y3hNUFpxWldUK0pXVlcvemN6TVBacVpXVDhmaFd1L3pjeE1QWnFaV1QrSldWVy9xa0NPUEpxWldUOFZUMUsvemN6TVBacVpXVDhmaFd1L3FrQ09QSnFaV1Q4VlQxSy9xa0NPdkpxWldUOFZUMUsvemN6TVBacVpXVDhmaFd1L3FrQ092SnFaV1Q4VlQxSy96Y3hNdlpxWldUK0pXVlcvemN6TVBacVpXVDhmaFd1L3pjeE12WnFaV1QrSldWVy95dUtjdlpxWldUK01FRnUvemN6TVBacVpXVDhmaFd1L3l1S2N2WnFaV1QrTUVGdS85WExBdlpxWldUK293MksvemN6TVBacVpXVDhmaFd1LzlYTEF2WnFaV1Qrb3cySy96Y3pNdlpxWldUOGZoV3UvemN6TVBacVpXVDhmaFd1L3pjek12WnFaV1Q4ZmhXdS85WExBdlpxWldUK1ZSblMvemN6TVBacVpXVDhmaFd1LzlYTEF2WnFaV1QrVlJuUy95dUtjdlpxWldUK3grWHUvemN6TVBacVpXVDhmaFd1L3l1S2N2WnFaV1QreCtYdS96Y3hNdlpxWldUOWEySUMvemN6TVBacVpXVDhmaFd1L3pjeE12WnFaV1Q5YTJJQy9xa0NPdkpxWldUK1VYWUsvemN6TVBacVpXVDhmaFd1L3FrQ092SnFaV1QrVVhZSy9xa0NPUEpxWldUK1VYWUsvemN6TVBacVpXVDhmaFd1L3FrQ09QSnFaV1QrVVhZSy96Y3hNUFpxWldUOWEySUMvemN6TVBacVpXVDhmaFd1L3pjeE1QWnFaV1Q5YTJJQy95dUtjUFpxWldUK3grWHUvemN6TVBacVpXVDhmaFd1L3l1S2NQWnFaV1QreCtYdS85WExBUFpxWldUK1ZSblMvQUFBQUFJL0NkVDlJNFRyQWo4TDF2T3hSbUVCSTRUckFJRHNIdmV4Um1FQVp5VG5BQUFBQUFJL0NkVDlJNFRyQUlEc0h2ZXhSbUVBWnlUbkFtUmVldTQvQ2RULzlJRG5BbVJlZXU0L0NkVC85SURuQUlEc0h2ZXhSbUVBWnlUbkFTc3NxdmV4Um1FQzEwampBbVJlZXU0L0NkVC85SURuQVNzc3F2ZXhSbUVDMTBqakFPMU9adkkvQ2RUL0VsamZBTzFPWnZJL0NkVC9FbGpmQVNzc3F2ZXhSbUVDMTBqakFya2RodmV4Um1FRFZHempBTzFPWnZJL0NkVC9FbGpmQXJrZGh2ZXhSbUVEVkd6akFDdGNqdlkvQ2RUOHFjamJBQ3RjanZZL0NkVDhxY2piQXJrZGh2ZXhSbUVEVkd6akE5UTZTdmV4Um1FQ0h1amZBQ3RjanZZL0NkVDhxY2piQTlRNlN2ZXhSbUVDSHVqZkF0V09IdlkvQ2RUOTUxalhBdFdPSHZZL0NkVDk1MWpYQTlRNlN2ZXhSbUVDSHVqZkFINSsxdmV4Um1FQ0h1amZBdFdPSHZZL0NkVDk1MWpYQUg1KzF2ZXhSbUVDSHVqZkFYMHJBdlkvQ2RUOTUxalhBWDByQXZZL0NkVDk1MWpYQUg1KzF2ZXhSbUVDSHVqZkFQUXJYdmV4Um1FRFZHempBWDByQXZZL0NkVDk1MWpYQVBRclh2ZXhSbUVEVkd6akFqOEwxdlkvQ2RUOHFjamJBajhMMXZZL0NkVDhxY2piQVBRclh2ZXhSbUVEVkd6akFiMGp5dmV4Um1FQzEwampBajhMMXZZL0NkVDhxY2piQWIwanl2ZXhSbUVDMTBqakFvNndRdm8vQ2RUL0VsamZBbzZ3UXZvL0NkVC9FbGpmQWIwanl2ZXhSbUVDMTBqakFRZ2dDdnV4Um1FQVp5VG5BbzZ3UXZvL0NkVC9FbGpmQVFnZ0N2dXhSbUVBWnlUbkFUZVlldm8vQ2RULzlJRG5BVGVZZXZvL0NkVC85SURuQVFnZ0N2dXhSbUVBWnlUbkF1QjRGdnV4Um1FQkk0VHJBVGVZZXZvL0NkVC85SURuQXVCNEZ2dXhSbUVCSTRUckFDdGNqdm8vQ2RUOUk0VHJBQ3RjanZvL0NkVDlJNFRyQXVCNEZ2dXhSbUVCSTRUckFRZ2dDdnV4Um1FQjMrVHZBQ3RjanZvL0NkVDlJNFRyQVFnZ0N2dXhSbUVCMytUdkFUZVlldm8vQ2RUK1RvVHpBVGVZZXZvL0NkVCtUb1R6QVFnZ0N2dXhSbUVCMytUdkFiMGp5dmV4Um1FRGE3enpBVGVZZXZvL0NkVCtUb1R6QWIwanl2ZXhSbUVEYTd6ekFvNndRdm8vQ2RUL0xLejdBbzZ3UXZvL0NkVC9MS3o3QWIwanl2ZXhSbUVEYTd6ekFQUXJYdmV4Um1FQzZwajNBbzZ3UXZvL0NkVC9MS3o3QVBRclh2ZXhSbUVDNnBqM0FqOEwxdlkvQ2RUOW1VRC9BajhMMXZZL0NkVDltVUQvQVBRclh2ZXhSbUVDNnBqM0FINSsxdmV4Um1FQUpDRDdBajhMMXZZL0NkVDltVUQvQUg1KzF2ZXhSbUVBSkNEN0FYMHJBdlkvQ2RUOFc3RC9BWDByQXZZL0NkVDhXN0QvQUg1KzF2ZXhSbUVBSkNEN0E5UTZTdmV4Um1FQUpDRDdBWDByQXZZL0NkVDhXN0QvQTlRNlN2ZXhSbUVBSkNEN0F0V09IdlkvQ2RUOFc3RC9BdFdPSHZZL0NkVDhXN0QvQTlRNlN2ZXhSbUVBSkNEN0Fya2RodmV4Um1FQzZwajNBdFdPSHZZL0NkVDhXN0QvQXJrZGh2ZXhSbUVDNnBqM0FDdGNqdlkvQ2RUOW1VRC9BQ3RjanZZL0NkVDltVUQvQXJrZGh2ZXhSbUVDNnBqM0FTc3NxdmV4Um1FRGE3enpBQ3RjanZZL0NkVDltVUQvQVNzc3F2ZXhSbUVEYTd6ekFPMU9adkkvQ2RUL0xLejdBTzFPWnZJL0NkVC9MS3o3QVNzc3F2ZXhSbUVEYTd6ekFJRHNIdmV4Um1FQjMrVHZBTzFPWnZJL0NkVC9MS3o3QUlEc0h2ZXhSbUVCMytUdkFtUmVldTQvQ2RUK1RvVHpBbVJlZXU0L0NkVCtUb1R6QUlEc0h2ZXhSbUVCMytUdkFqOEwxdk94Um1FQkk0VHJBbVJlZXU0L0NkVCtUb1R6QWo4TDF2T3hSbUVCSTRUckFBQUFBQUkvQ2RUOUk0VHJBSURzSHZleFJtRUIzK1R2QVNzc3F2ZXhSbUVEYTd6ekFya2RodmV4Um1FQzZwajNBSURzSHZleFJtRUIzK1R2QXJrZGh2ZXhSbUVDNnBqM0E5UTZTdmV4Um1FQUpDRDdBSURzSHZleFJtRUIzK1R2QTlRNlN2ZXhSbUVBSkNEN0FINSsxdmV4Um1FQUpDRDdBSURzSHZleFJtRUIzK1R2QUg1KzF2ZXhSbUVBSkNEN0FQUXJYdmV4Um1FQzZwajNBSURzSHZleFJtRUIzK1R2QVBRclh2ZXhSbUVDNnBqM0FiMGp5dmV4Um1FRGE3enpBSURzSHZleFJtRUIzK1R2QWIwanl2ZXhSbUVEYTd6ekFRZ2dDdnV4Um1FQjMrVHZBSURzSHZleFJtRUIzK1R2QVFnZ0N2dXhSbUVCMytUdkF1QjRGdnV4Um1FQkk0VHJBSURzSHZleFJtRUIzK1R2QXVCNEZ2dXhSbUVCSTRUckFRZ2dDdnV4Um1FQVp5VG5BSURzSHZleFJtRUIzK1R2QVFnZ0N2dXhSbUVBWnlUbkFiMGp5dmV4Um1FQzEwampBSURzSHZleFJtRUIzK1R2QWIwanl2ZXhSbUVDMTBqakFQUXJYdmV4Um1FRFZHempBSURzSHZleFJtRUIzK1R2QVBRclh2ZXhSbUVEVkd6akFINSsxdmV4Um1FQ0h1amZBSURzSHZleFJtRUIzK1R2QUg1KzF2ZXhSbUVDSHVqZkE5UTZTdmV4Um1FQ0h1amZBSURzSHZleFJtRUIzK1R2QTlRNlN2ZXhSbUVDSHVqZkFya2RodmV4Um1FRFZHempBSURzSHZleFJtRUIzK1R2QXJrZGh2ZXhSbUVEVkd6akFTc3NxdmV4Um1FQzEwampBSURzSHZleFJtRUIzK1R2QVNzc3F2ZXhSbUVDMTBqakFJRHNIdmV4Um1FQVp5VG5BSURzSHZleFJtRUIzK1R2QUlEc0h2ZXhSbUVBWnlUbkFqOEwxdk94Um1FQkk0VHJBQUFBQUFJL0NkVDlJNFRyQW1SZWV1NC9DZFQvOUlEbkFPMU9adkkvQ2RUL0VsamZBQUFBQUFJL0NkVDlJNFRyQU8xT1p2SS9DZFQvRWxqZkFDdGNqdlkvQ2RUOHFjamJBQUFBQUFJL0NkVDlJNFRyQUN0Y2p2WS9DZFQ4cWNqYkF0V09IdlkvQ2RUOTUxalhBQUFBQUFJL0NkVDlJNFRyQXRXT0h2WS9DZFQ5NTFqWEFYMHJBdlkvQ2RUOTUxalhBQUFBQUFJL0NkVDlJNFRyQVgwckF2WS9DZFQ5NTFqWEFqOEwxdlkvQ2RUOHFjamJBQUFBQUFJL0NkVDlJNFRyQWo4TDF2WS9DZFQ4cWNqYkFvNndRdm8vQ2RUL0VsamZBQUFBQUFJL0NkVDlJNFRyQW82d1F2by9DZFQvRWxqZkFUZVlldm8vQ2RULzlJRG5BQUFBQUFJL0NkVDlJNFRyQVRlWWV2by9DZFQvOUlEbkFDdGNqdm8vQ2RUOUk0VHJBQUFBQUFJL0NkVDlJNFRyQUN0Y2p2by9DZFQ5STRUckFUZVlldm8vQ2RUK1RvVHpBQUFBQUFJL0NkVDlJNFRyQVRlWWV2by9DZFQrVG9UekFvNndRdm8vQ2RUL0xLejdBQUFBQUFJL0NkVDlJNFRyQW82d1F2by9DZFQvTEt6N0FqOEwxdlkvQ2RUOW1VRC9BQUFBQUFJL0NkVDlJNFRyQWo4TDF2WS9DZFQ5bVVEL0FYMHJBdlkvQ2RUOFc3RC9BQUFBQUFJL0NkVDlJNFRyQVgwckF2WS9DZFQ4VzdEL0F0V09IdlkvQ2RUOFc3RC9BQUFBQUFJL0NkVDlJNFRyQXRXT0h2WS9DZFQ4VzdEL0FDdGNqdlkvQ2RUOW1VRC9BQUFBQUFJL0NkVDlJNFRyQUN0Y2p2WS9DZFQ5bVVEL0FPMU9adkkvQ2RUL0xLejdBQUFBQUFJL0NkVDlJNFRyQU8xT1p2SS9DZFQvTEt6N0FtUmVldTQvQ2RUK1RvVHpBQ3RlanZUTXpVMEN1UjJHL0g0VUxRRE16VTBDdVIyRy9INFVMUU94UldFQ3VSMkcvQ3RlanZUTXpVMEN1UjJHL0g0VUxRT3hSV0VDdVIyRy9DdGVqdmV4UldFQ3VSMkcvSDRVTFFETXpVMEFBQUlDL0N0ZWp2VE16VTBBQUFJQy9DdGVqdmV4UldFQUFBSUMvSDRVTFFETXpVMEFBQUlDL0N0ZWp2ZXhSV0VBQUFJQy9INFVMUU94UldFQUFBSUMvQ3RlanZUTXpVMEFBQUlDL0N0ZWp2VE16VTBDdVIyRy9DdGVqdmV4UldFQ3VSMkcvQ3RlanZUTXpVMEFBQUlDL0N0ZWp2ZXhSV0VDdVIyRy9DdGVqdmV4UldFQUFBSUMvSDRVTFFETXpVMEN1UjJHL0g0VUxRRE16VTBBQUFJQy9INFVMUU94UldFQUFBSUMvSDRVTFFETXpVMEN1UjJHL0g0VUxRT3hSV0VBQUFJQy9INFVMUU94UldFQ3VSMkcvQ3RlanZleFJXRUN1UjJHL0g0VUxRT3hSV0VDdVIyRy9INFVMUU94UldFQUFBSUMvQ3RlanZleFJXRUN1UjJHL0g0VUxRT3hSV0VBQUFJQy9DdGVqdmV4UldFQUFBSUMvQ3RlanZUTXpVMEFBQUlDL0g0VUxRRE16VTBBQUFJQy9INFVMUURNelUwQ3VSMkcvQ3RlanZUTXpVMEFBQUlDL0g0VUxRRE16VTBDdVIyRy9DdGVqdlRNelUwQ3VSMkcvS1Z3UHZwcVpHVUNhbVRuQUN0ZWpQNXFaR1VDYW1UbkFDdGVqUDFLNEhrQ2FtVG5BS1Z3UHZwcVpHVUNhbVRuQUN0ZWpQMUs0SGtDYW1UbkFLVndQdmxLNEhrQ2FtVG5BQ3RlalA1cVpHVUFBQUVEQUtWd1B2cHFaR1VBQUFFREFLVndQdmxLNEhrQUFBRURBQ3RlalA1cVpHVUFBQUVEQUtWd1B2bEs0SGtBQUFFREFDdGVqUDFLNEhrQUFBRURBS1Z3UHZwcVpHVUFBQUVEQUtWd1B2cHFaR1VDYW1UbkFLVndQdmxLNEhrQ2FtVG5BS1Z3UHZwcVpHVUFBQUVEQUtWd1B2bEs0SGtDYW1UbkFLVndQdmxLNEhrQUFBRURBQ3RlalA1cVpHVUNhbVRuQUN0ZWpQNXFaR1VBQUFFREFDdGVqUDFLNEhrQUFBRURBQ3RlalA1cVpHVUNhbVRuQUN0ZWpQMUs0SGtBQUFFREFDdGVqUDFLNEhrQ2FtVG5BS1Z3UHZsSzRIa0NhbVRuQUN0ZWpQMUs0SGtDYW1UbkFDdGVqUDFLNEhrQUFBRURBS1Z3UHZsSzRIa0NhbVRuQUN0ZWpQMUs0SGtBQUFFREFLVndQdmxLNEhrQUFBRURBS1Z3UHZwcVpHVUFBQUVEQUN0ZWpQNXFaR1VBQUFFREFDdGVqUDVxWkdVQ2FtVG5BS1Z3UHZwcVpHVUFBQUVEQUN0ZWpQNXFaR1VDYW1UbkFLVndQdnBxWkdVQ2FtVG5BQ3RjanZZL0N0VCthbWFGQWo4SjFQWS9DdFQrYW1hRkFqOEoxUFFBQXdEK2FtYUZBQ3RjanZZL0N0VCthbWFGQWo4SjFQUUFBd0QrYW1hRkFDdGNqdlFBQXdEK2FtYUZBajhKMVBZL0N0VC9Oekd4QUN0Y2p2WS9DdFQvTnpHeEFDdGNqdlFBQXdEL056R3hBajhKMVBZL0N0VC9Oekd4QUN0Y2p2UUFBd0QvTnpHeEFqOEoxUFFBQXdEL056R3hBQ3RjanZZL0N0VC9Oekd4QUN0Y2p2WS9DdFQrYW1hRkFDdGNqdlFBQXdEK2FtYUZBQ3RjanZZL0N0VC9Oekd4QUN0Y2p2UUFBd0QrYW1hRkFDdGNqdlFBQXdEL056R3hBajhKMVBZL0N0VCthbWFGQWo4SjFQWS9DdFQvTnpHeEFqOEoxUFFBQXdEL056R3hBajhKMVBZL0N0VCthbWFGQWo4SjFQUUFBd0QvTnpHeEFqOEoxUFFBQXdEK2FtYUZBQ3RjanZRQUF3RCthbWFGQWo4SjFQUUFBd0QrYW1hRkFqOEoxUFFBQXdEL056R3hBQ3RjanZRQUF3RCthbWFGQWo4SjFQUUFBd0QvTnpHeEFDdGNqdlFBQXdEL056R3hBQ3RjanZZL0N0VC9Oekd4QWo4SjFQWS9DdFQvTnpHeEFqOEoxUFkvQ3RUK2FtYUZBQ3RjanZZL0N0VC9Oekd4QWo4SjFQWS9DdFQrYW1hRkFDdGNqdlkvQ3RUK2FtYUZBL2Y1L1A2a0t0anNBQUFBQS9mNS9QNmtLdGpzQUFBQUF2NDV3UDZrS3RqdVRISzgrL2Y1L1A2a0t0anNBQUFBQXY0NXdQNmtLdGp1VEhLOCt2NDV3UDZrS3RqdVRISzgrdjQ1d1A2a0t0anVUSEs4K3Y0NXdQNmtLdGp1VEhLOCt0eHBFUDZrS3Rqc1VqU1EvdjQ1d1A2a0t0anVUSEs4K3R4cEVQNmtLdGpzVWpTUS90eHBFUDZrS3Rqc1VqU1EvdHhwRVA2a0t0anNValNRL3R4cEVQNmtLdGpzVWpTUS8vZjcvUHFrS3RqdjNzbDAvdHhwRVA2a0t0anNValNRLy9mNy9QcWtLdGp2M3NsMC8vZjcvUHFrS3RqdjNzbDAvL2Y3L1Bxa0t0anYzc2wwLy9mNy9QcWtLdGp2M3NsMC9JTkF4UHFrS3RqdGRHM3cvL2Y3L1Bxa0t0anYzc2wwL0lOQXhQcWtLdGp0ZEczdy9JTkF4UHFrS3RqdGRHM3cvSU5BeFBxa0t0anRkRzN3L0lOQXhQcWtLdGp0ZEczdy9JTkF4dnFrS3RqdGRHM3cvSU5BeFBxa0t0anRkRzN3L0lOQXh2cWtLdGp0ZEczdy9JTkF4dnFrS3RqdGRHM3cvSU5BeHZxa0t0anRkRzN3L0lOQXh2cWtLdGp0ZEczdy8vZjcvdnFrS3RqdjNzbDAvSU5BeHZxa0t0anRkRzN3Ly9mNy92cWtLdGp2M3NsMC8vZjcvdnFrS3RqdjNzbDAvL2Y3L3Zxa0t0anYzc2wwLy9mNy92cWtLdGp2M3NsMC90eHBFdjZrS3Rqc1VqU1EvL2Y3L3Zxa0t0anYzc2wwL3R4cEV2NmtLdGpzVWpTUS90eHBFdjZrS3Rqc1VqU1EvdHhwRXY2a0t0anNValNRL3R4cEV2NmtLdGpzVWpTUS92NDV3djZrS3RqdVRISzgrdHhwRXY2a0t0anNValNRL3Y0NXd2NmtLdGp1VEhLOCt2NDV3djZrS3RqdVRISzgrdjQ1d3Y2a0t0anVUSEs4K3Y0NXd2NmtLdGp1VEhLOCsvZjUvdjZrS3RqdWpNQTBsdjQ1d3Y2a0t0anVUSEs4Ky9mNS92NmtLdGp1ak1BMGwvZjUvdjZrS3RqdWpNQTBsL2Y1L3Y2a0t0anVqTUEwbC9mNS92NmtLdGp1ak1BMGx2NDV3djZrS3RqdVRISysrL2Y1L3Y2a0t0anVqTUEwbHY0NXd2NmtLdGp1VEhLKyt2NDV3djZrS3RqdVRISysrdjQ1d3Y2a0t0anVUSEsrK3Y0NXd2NmtLdGp1VEhLKyt0eHBFdjZrS3Rqc1VqU1MvdjQ1d3Y2a0t0anVUSEsrK3R4cEV2NmtLdGpzVWpTUy90eHBFdjZrS3Rqc1VqU1MvdHhwRXY2a0t0anNValNTL3R4cEV2NmtLdGpzVWpTUy8vZjcvdnFrS3RqdjNzbDIvdHhwRXY2a0t0anNValNTLy9mNy92cWtLdGp2M3NsMi8vZjcvdnFrS3RqdjNzbDIvL2Y3L3Zxa0t0anYzc2wyLy9mNy92cWtLdGp2M3NsMi9JTkF4dnFrS3RqdGRHM3kvL2Y3L3Zxa0t0anYzc2wyL0lOQXh2cWtLdGp0ZEczeS9JTkF4dnFrS3RqdGRHM3kvSU5BeHZxa0t0anRkRzN5L0lOQXh2cWtLdGp0ZEczeS9JTkF4UHFrS3RqdGRHM3kvSU5BeHZxa0t0anRkRzN5L0lOQXhQcWtLdGp0ZEczeS9JTkF4UHFrS3RqdGRHM3kvSU5BeFBxa0t0anRkRzN5L0lOQXhQcWtLdGp0ZEczeS8vZjcvUHFrS3RqdjNzbDIvSU5BeFBxa0t0anRkRzN5Ly9mNy9QcWtLdGp2M3NsMi8vZjcvUHFrS3RqdjNzbDIvL2Y3L1Bxa0t0anYzc2wyLy9mNy9QcWtLdGp2M3NsMi90eHBFUDZrS3Rqc1VqU1MvL2Y3L1Bxa0t0anYzc2wyL3R4cEVQNmtLdGpzVWpTUy90eHBFUDZrS3Rqc1VqU1MvdHhwRVA2a0t0anNValNTL3R4cEVQNmtLdGpzVWpTUy92NDV3UDZrS3RqdVRISysrdHhwRVA2a0t0anNValNTL3Y0NXdQNmtLdGp1VEhLKyt2NDV3UDZrS3RqdVRISysrdjQ1d1A2a0t0anVUSEsrK3Y0NXdQNmtLdGp1VEhLKysvZjUvUDZrS3Rqc0FBQUFBdjQ1d1A2a0t0anVUSEsrKy9mNS9QNmtLdGpzQUFBQUEvZjUvUDZrS3Rqc0FBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFDQUFBQUFBQUFBZ0Q4QUFBQ0FBQUFBQUFBQWdEOEFBQUNBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQWdBQUFnTDhBQUFBQUFBQUFnQUFBZ0w4QUFBQUFBQUFBZ0FBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBOWYxL1ArVlhBVHdBQUFBQTlmMS9QK1ZYQVR3QUFBQUF4NDF3UCtWWEFUemVHNjgrOWYxL1ArVlhBVHdBQUFBQXg0MXdQK1ZYQVR6ZUc2OCt4NDF3UCtWWEFUemVHNjgreDQxd1ArVlhBVHplRzY4K3g0MXdQK1ZYQVR6ZUc2OCs3UmxFUCtWWEFUeHJqQ1EveDQxd1ArVlhBVHplRzY4KzdSbEVQK1ZYQVR4cmpDUS83UmxFUCtWWEFUeHJqQ1EvN1JsRVArVlhBVHhyakNRLzdSbEVQK1ZYQVR4cmpDUS85ZjMvUHVWWEFUd1NzbDAvN1JsRVArVlhBVHhyakNRLzlmMy9QdVZYQVR3U3NsMC85ZjMvUHVWWEFUd1NzbDAvOWYzL1B1VlhBVHdTc2wwLzlmMy9QdVZYQVR3U3NsMC9hYzh4UHVWWEFUeGFHbncvOWYzL1B1VlhBVHdTc2wwL2FjOHhQdVZYQVR4YUdudy9hYzh4UHVWWEFUeGFHbncvYWM4eFB1VlhBVHhhR253L2FjOHhQdVZYQVR4YUdudy9hYzh4dnVWWEFUeGFHbncvYWM4eFB1VlhBVHhhR253L2FjOHh2dVZYQVR4YUdudy9hYzh4dnVWWEFUeGFHbncvYWM4eHZ1VlhBVHhhR253L2FjOHh2dVZYQVR4YUdudy85ZjMvdnVWWEFUd1NzbDAvYWM4eHZ1VlhBVHhhR253LzlmMy92dVZYQVR3U3NsMC85ZjMvdnVWWEFUd1NzbDAvOWYzL3Z1VlhBVHdTc2wwLzlmMy92dVZYQVR3U3NsMC83UmxFditWWEFUeHJqQ1EvOWYzL3Z1VlhBVHdTc2wwLzdSbEV2K1ZYQVR4cmpDUS83UmxFditWWEFUeHJqQ1EvN1JsRXYrVlhBVHhyakNRLzdSbEV2K1ZYQVR4cmpDUS94NDF3ditWWEFUemVHNjgrN1JsRXYrVlhBVHhyakNRL3g0MXd2K1ZYQVR6ZUc2OCt4NDF3ditWWEFUemVHNjgreDQxd3YrVlhBVHplRzY4K3g0MXd2K1ZYQVR6ZUc2OCs5ZjEvditWWEFUd1JNQTBseDQxd3YrVlhBVHplRzY4KzlmMS92K1ZYQVR3Uk1BMGw5ZjEvditWWEFUd1JNQTBsOWYxL3YrVlhBVHdSTUEwbDlmMS92K1ZYQVR3Uk1BMGx4NDF3ditWWEFUemVHNisrOWYxL3YrVlhBVHdSTUEwbHg0MXd2K1ZYQVR6ZUc2Kyt4NDF3ditWWEFUemVHNisreDQxd3YrVlhBVHplRzYrK3g0MXd2K1ZYQVR6ZUc2Kys3UmxFditWWEFUeHJqQ1MveDQxd3YrVlhBVHplRzYrKzdSbEV2K1ZYQVR4cmpDUy83UmxFditWWEFUeHJqQ1MvN1JsRXYrVlhBVHhyakNTLzdSbEV2K1ZYQVR4cmpDUy85ZjMvdnVWWEFUd1NzbDIvN1JsRXYrVlhBVHhyakNTLzlmMy92dVZYQVR3U3NsMi85ZjMvdnVWWEFUd1NzbDIvOWYzL3Z1VlhBVHdTc2wyLzlmMy92dVZYQVR3U3NsMi9hYzh4dnVWWEFUeGFHbnkvOWYzL3Z1VlhBVHdTc2wyL2FjOHh2dVZYQVR4YUdueS9hYzh4dnVWWEFUeGFHbnkvYWM4eHZ1VlhBVHhhR255L2FjOHh2dVZYQVR4YUdueS9hYzh4UHVWWEFUeGFHbnkvYWM4eHZ1VlhBVHhhR255L2FjOHhQdVZYQVR4YUdueS9hYzh4UHVWWEFUeGFHbnkvYWM4eFB1VlhBVHhhR255L2FjOHhQdVZYQVR4YUdueS85ZjMvUHVWWEFUd1NzbDIvYWM4eFB1VlhBVHhhR255LzlmMy9QdVZYQVR3U3NsMi85ZjMvUHVWWEFUd1NzbDIvOWYzL1B1VlhBVHdTc2wyLzlmMy9QdVZYQVR3U3NsMi83UmxFUCtWWEFUeHJqQ1MvOWYzL1B1VlhBVHdTc2wyLzdSbEVQK1ZYQVR4cmpDUy83UmxFUCtWWEFUeHJqQ1MvN1JsRVArVlhBVHhyakNTLzdSbEVQK1ZYQVR4cmpDUy94NDF3UCtWWEFUemVHNisrN1JsRVArVlhBVHhyakNTL3g0MXdQK1ZYQVR6ZUc2Kyt4NDF3UCtWWEFUemVHNisreDQxd1ArVlhBVHplRzYrK3g0MXdQK1ZYQVR6ZUc2Kys5ZjEvUCtWWEFUd0FBQUFBeDQxd1ArVlhBVHplRzYrKzlmMS9QK1ZYQVR3QUFBQUE5ZjEvUCtWWEFUd0FBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFDQUFBQUFBQUFBZ0Q4QUFBQ0FBQUFBQUFBQWdEOEFBQUNBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQWdBQUFnTDhBQUFBQUFBQUFnQUFBZ0w4QUFBQUFBQUFBZ0FBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQkFBSUFBd0FFQUFVQUJnQUhBQWdBQ1FBS0FBc0FEQUFOQUE0QUR3QVFBQkVBRWdBVEFCUUFGUUFXQUJjQUdBQVpBQm9BR3dBY0FCMEFIZ0FmQUNBQUlRQWlBQ01BSkFBbEFDWUFKd0FvQUNrQUtnQXJBQ3dBTFFBdUFDOEFNQUF4QURJQU13QTBBRFVBTmdBM0FEZ0FPUUE2QURzQVBBQTlBRDRBUHdCQUFFRUFRZ0JEQUVRQVJRQkdBRWNBU0FCSkFFb0FTd0JNQUUwQVRnQlBBRkFBVVFCU0FGTUFWQUJWQUZZQVZ3QllBRmtBV2dCYkFGd0FYUUJlQUY4QVlBQmhBR0lBWXdCa0FHVUFaZ0JuQUdnQWFRQnFBR3NBYkFCdEFHNEFid0J3QUhFQWNnQnpBSFFBZFFCMkFIY0FlQUI1QUhvQWV3QjhBSDBBZmdCL0FJQUFnUUNDQUlNQWhBQ0ZBSVlBaHdDSUFJa0FpZ0NMQUl3QWpRQ09BSThBa0FDUkFKSUFrd0NVQUpVQWxnQ1hBSmdBbVFDYUFKc0FuQUNkQUo0QW53Q2dBS0VBb2dDakFLUUFwUUNtQUtjQXFBQ3BBS29BcXdDc0FLMEFyZ0N2QUxBQXNRQ3lBTE1BdEFDMUFMWUF0d0M0QUxrQXVnQzdBTHdBdlFDK0FMOEF3QURCQU1JQXd3REVBTVVBeGdESEFNZ0F5UURLQU1zQXpBRE5BTTRBendEUUFORUEwZ0RUQU5RQTFRRFdBTmNBMkFEWkFOb0Eyd0RjQU4wQTNnRGZBT0FBNFFEaUFPTUE1QURsQU9ZQTV3RG9BT2tBNmdEckFPd0E3UUR1QU84QThBRHhBUElBOHdEMEFQVUE5Z0QzQVBnQStRRDZBUHNBL0FEOUFQNEEvd0FBQVFFQkFnRURBUVFCQlFFR0FRY0JDQUVKQVFvQkN3RU1BUTBCRGdFUEFSQUJFUUVTQVJNQkZBRVZBUllCRndFWUFSa0JHZ0ViQVJ3QkhRRWVBUjhCSUFFaEFTSUJJd0VrQVNVQkpnRW5BU2dCS1FFcUFTc0JMQUV0QVM0Qkx3RXdBVEVCTWdFekFUUUJOUUUyQVRjQk9BRTVBVG9CT3dFOEFUMEJQZ0UvQVVBQlFRRkNBVU1CUkFGRkFVWUJSd0ZJQVVrQlNnRkxBVXdCVFFGT0FVOEJVQUZSQVZJQlV3RlVBVlVCVmdGWEFWZ0JXUUZhQVZzQlhBRmRBVjRCWHdGZ0FXRUJZZ0ZqQVdRQlpRRm1BV2NCYUFGcEFXb0Jhd0ZzQVcwQmJnRnZBWEFCY1FGeUFYTUJkQUYxQVhZQmR3RjRBWGtCZWdGN0FYd0JmUUYrQVg4QmdBR0JBWUlCZ3dHRUFZVUJoZ0dIQVlnQmlRR0tBWXNCakFHTkFZNEJqd0dRQVpFQmtnR1RBWlFCbFFHV0FaY0JtQUdaQVpvQm13R2NBWjBCbmdHZkFhQUJvUUdpQWFNQnBBR2xBYVlCcHdHb0Fha0JxZ0dyQWF3QnJRR3VBYThCc0FHeEFiSUJzd0cwQWJVQnRnRzNBYmdCdVFHNkFic0J2QUc5QWI0QnZ3SEFBY0VCd2dIREFjUUJ4UUhHQWNjQnlBSEpBY29CeXdITUFjMEJ6Z0hQQWRBQjBRSFNBZE1CMUFIVkFkWUIxd0hZQWRrQjJnSGJBZHdCM1FIZUFkOEI0QUhoQWVJQjR3SGtBZVVCNWdIbkFlZ0I2UUhxQWVzQjdBSHRBZTRCN3dId0FmRUI4Z0h6QWZRQjlRSDJBZmNCK0FINUFmb0Ird0g4QWYwQi9nSC9BUUFDQVFJQ0FnTUNDdGVqUFhFOW1rQWZoV3UvZXhUdVAwamhXa0E5Q2xlL3VCN0ZQeWxjenora2NEMi9DdGVqUFhFOW1rQWZoV3UvdUI3RlB5bGN6eitrY0QyL0N0ZWpQTGdlQlVEMktGeS96Y3hNdlQwS2QwQ2tjRDNBTXpPVFA2UndIVUE5Q2pmQWo4SjFQeWxjanorRjZ6SEF6Y3hNdlQwS2QwQ2tjRDNBajhKMVB5bGNqeitGNnpIQUN0ZWp2UlN1eHo5STRUckExMWFQT3JyL1k3MWFtbisvMTFhUE9yci9ZNzFhbW4rLzExYVBPcnIvWTcxYW1uKy8rYmVTUFZxNnY3eWNSWCsvK2JlU1BWcTZ2N3ljUlgrLytiZVNQVnE2djd5Y1JYKy9tdmMvUE1IZGVyMTJnSCsvbXZjL1BNSGRlcjEyZ0grL212Yy9QTUhkZXIxMmdIKy9TNHdBUGdtN21yekY3WDIvUzR3QVBnbTdtcnpGN1gyL1M0d0FQZ203bXJ6RjdYMi9BQUFCQUFJQUF3QUVBQVVBQmdBSEFBZ0FDUUFLQUFzQWo4SjF2eFN1Unovc1ViZy9qOEoxUHhTdVJ6L3NVYmcvajhKMVA2NUhZVC9zVWJnL2o4SjF2eFN1Unovc1ViZy9qOEoxUDY1SFlUL3NVYmcvajhKMXY2NUhZVC9zVWJnL2o4SjFQeFN1UnordVI2RS9qOEoxdnhTdVJ6K3VSNkUvajhKMXY2NUhZVCt1UjZFL2o4SjFQeFN1UnordVI2RS9qOEoxdjY1SFlUK3VSNkUvajhKMVA2NUhZVCt1UjZFL2o4SjF2eFN1UnordVI2RS9qOEoxdnhTdVJ6L3NVYmcvajhKMXY2NUhZVC9zVWJnL2o4SjF2eFN1UnordVI2RS9qOEoxdjY1SFlUL3NVYmcvajhKMXY2NUhZVCt1UjZFL2o4SjFQeFN1Unovc1ViZy9qOEoxUHhTdVJ6K3VSNkUvajhKMVA2NUhZVCt1UjZFL2o4SjFQeFN1Unovc1ViZy9qOEoxUDY1SFlUK3VSNkUvajhKMVA2NUhZVC9zVWJnL2o4SjF2NjVIWVQvc1ViZy9qOEoxUDY1SFlUL3NVYmcvajhKMVA2NUhZVCt1UjZFL2o4SjF2NjVIWVQvc1ViZy9qOEoxUDY1SFlUK3VSNkUvajhKMXY2NUhZVCt1UjZFL2o4SjF2eFN1UnordVI2RS9qOEoxUHhTdVJ6K3VSNkUvajhKMVB4U3VSei9zVWJnL2o4SjF2eFN1UnordVI2RS9qOEoxUHhTdVJ6L3NVYmcvajhKMXZ4U3VSei9zVWJnL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQS9BQUFBQUFBQUFBQUFBSUEvQUFBQUFBQUFBQUFBQUlBL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQUFBQUFBQUFBQUFJQy9BQUFBQUFBQUFBQUFBSUMvQUFBQUFBQUFBQUFBQUlDL0FBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0F2d0FBQUFBQUFBQUFBQUNBdndBQUFBQUFBQUFBQUFDQXZ3QUFBQUFBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQ0FQd0FBQUlBQUFBQUFBQUNBUHdBQUFJQUFBQUFBQUFDQVB3QUFBSUFBQUFBQUFBQUFnQUFBZ0Q4QUFBQUFBQUFBZ0FBQWdEOEFBQUFBQUFBQWdBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUJBQUlBQXdBRUFBVUFCZ0FIQUFnQUNRQUtBQXNBREFBTkFBNEFEd0FRQUJFQUVnQVRBQlFBRlFBV0FCY0FHQUFaQUJvQUd3QWNBQjBBSGdBZkFDQUFJUUFpQUNNQXpjeE1QeWxjanorUHduVS96Y3hNUDNzVXJqK1B3blUvdGoxTFAzc1Vyai9zbUgwL3pjeE1QeWxjanorUHduVS90ajFMUDNzVXJqL3NtSDAvdGoxTFB5bGNqei9zbUgwL3RqMUxQeWxjanovc21IMC90ajFMUDNzVXJqL3NtSDAvTXMxR1Azc1Vyai9ySG9JL3RqMUxQeWxjanovc21IMC9NczFHUDNzVXJqL3JIb0kvTXMxR1B5bGNqei9ySG9JL01zMUdQeWxjanovckhvSS9NczFHUDNzVXJqL3JIb0kvU1NoQVAzc1Vyajh0VjRRL01zMUdQeWxjanovckhvSS9TU2hBUDNzVXJqOHRWNFEvU1NoQVB5bGNqejh0VjRRL1NTaEFQeWxjano4dFY0US9TU2hBUDNzVXJqOHRWNFEvN0ZFNFAzc1Vyais0SG9VL1NTaEFQeWxjano4dFY0US83RkU0UDNzVXJqKzRIb1UvN0ZFNFB5bGNqeis0SG9VLzdGRTRQeWxjanorNEhvVS83RkU0UDNzVXJqKzRIb1UvajNzd1Azc1Vyajh0VjRRLzdGRTRQeWxjanorNEhvVS9qM3N3UDNzVXJqOHRWNFEvajNzd1B5bGNqejh0VjRRL2ozc3dQeWxjano4dFY0US9qM3N3UDNzVXJqOHRWNFEvcGRZcFAzc1Vyai9ySG9JL2ozc3dQeWxjano4dFY0US9wZFlwUDNzVXJqL3JIb0kvcGRZcFB5bGNqei9ySG9JL3BkWXBQeWxjanovckhvSS9wZFlwUDNzVXJqL3JIb0kvSVdZbFAzc1Vyai9zbUgwL3BkWXBQeWxjanovckhvSS9JV1lsUDNzVXJqL3NtSDAvSVdZbFB5bGNqei9zbUgwL0lXWWxQeWxjanovc21IMC9JV1lsUDNzVXJqL3NtSDAvQ3RjalAzc1VyaitQd25VL0lXWWxQeWxjanovc21IMC9DdGNqUDNzVXJqK1B3blUvQ3RjalB5bGNqeitQd25VL0N0Y2pQeWxjanorUHduVS9DdGNqUDNzVXJqK1B3blUvSVdZbFAzc1Vyajh5N0cwL0N0Y2pQeWxjanorUHduVS9JV1lsUDNzVXJqOHk3RzAvSVdZbFB5bGNqejh5N0cwL0lXWWxQeWxjano4eTdHMC9JV1lsUDNzVXJqOHk3RzAvcGRZcFAzc1VyajlKUjJjL0lXWWxQeWxjano4eTdHMC9wZFlwUDNzVXJqOUpSMmMvcGRZcFB5bGNqejlKUjJjL3BkWXBQeWxjano5SlIyYy9wZFlwUDNzVXJqOUpSMmMvajNzd1Azc1Vyai9GMW1JL3BkWXBQeWxjano5SlIyYy9qM3N3UDNzVXJqL0YxbUkvajNzd1B5bGNqei9GMW1JL2ozc3dQeWxjanovRjFtSS9qM3N3UDNzVXJqL0YxbUkvN0ZFNFAzc1Vyait1UjJFL2ozc3dQeWxjanovRjFtSS83RkU0UDNzVXJqK3VSMkUvN0ZFNFB5bGNqeit1UjJFLzdGRTRQeWxjanordVIyRS83RkU0UDNzVXJqK3VSMkUvU1NoQVAzc1Vyai9GMW1JLzdGRTRQeWxjanordVIyRS9TU2hBUDNzVXJqL0YxbUkvU1NoQVB5bGNqei9GMW1JL1NTaEFQeWxjanovRjFtSS9TU2hBUDNzVXJqL0YxbUkvTXMxR1Azc1VyajlKUjJjL1NTaEFQeWxjanovRjFtSS9NczFHUDNzVXJqOUpSMmMvTXMxR1B5bGNqejlKUjJjL01zMUdQeWxjano5SlIyYy9NczFHUDNzVXJqOUpSMmMvdGoxTFAzc1Vyajh5N0cwL01zMUdQeWxjano5SlIyYy90ajFMUDNzVXJqOHk3RzAvdGoxTFB5bGNqejh5N0cwL3RqMUxQeWxjano4eTdHMC90ajFMUDNzVXJqOHk3RzAvemN4TVAzc1VyaitQd25VL3RqMUxQeWxjano4eTdHMC96Y3hNUDNzVXJqK1B3blUvemN4TVB5bGNqeitQd25VL3RqMUxQM3NVcmo4eTdHMC9NczFHUDNzVXJqOUpSMmMvU1NoQVAzc1Vyai9GMW1JL3RqMUxQM3NVcmo4eTdHMC9TU2hBUDNzVXJqL0YxbUkvN0ZFNFAzc1Vyait1UjJFL3RqMUxQM3NVcmo4eTdHMC83RkU0UDNzVXJqK3VSMkUvajNzd1Azc1Vyai9GMW1JL3RqMUxQM3NVcmo4eTdHMC9qM3N3UDNzVXJqL0YxbUkvcGRZcFAzc1VyajlKUjJjL3RqMUxQM3NVcmo4eTdHMC9wZFlwUDNzVXJqOUpSMmMvSVdZbFAzc1Vyajh5N0cwL3RqMUxQM3NVcmo4eTdHMC9JV1lsUDNzVXJqOHk3RzAvQ3RjalAzc1VyaitQd25VL3RqMUxQM3NVcmo4eTdHMC9DdGNqUDNzVXJqK1B3blUvSVdZbFAzc1Vyai9zbUgwL3RqMUxQM3NVcmo4eTdHMC9JV1lsUDNzVXJqL3NtSDAvcGRZcFAzc1Vyai9ySG9JL3RqMUxQM3NVcmo4eTdHMC9wZFlwUDNzVXJqL3JIb0kvajNzd1Azc1Vyajh0VjRRL3RqMUxQM3NVcmo4eTdHMC9qM3N3UDNzVXJqOHRWNFEvN0ZFNFAzc1Vyais0SG9VL3RqMUxQM3NVcmo4eTdHMC83RkU0UDNzVXJqKzRIb1UvU1NoQVAzc1Vyajh0VjRRL3RqMUxQM3NVcmo4eTdHMC9TU2hBUDNzVXJqOHRWNFEvTXMxR1Azc1Vyai9ySG9JL3RqMUxQM3NVcmo4eTdHMC9NczFHUDNzVXJqL3JIb0kvdGoxTFAzc1Vyai9zbUgwL3RqMUxQM3NVcmo4eTdHMC90ajFMUDNzVXJqL3NtSDAvemN4TVAzc1VyaitQd25VL3pjeE1QeWxjanorUHduVS90ajFMUHlsY2p6L3NtSDAvTXMxR1B5bGNqei9ySG9JL3pjeE1QeWxjanorUHduVS9NczFHUHlsY2p6L3JIb0kvU1NoQVB5bGNqejh0VjRRL3pjeE1QeWxjanorUHduVS9TU2hBUHlsY2p6OHRWNFEvN0ZFNFB5bGNqeis0SG9VL3pjeE1QeWxjanorUHduVS83RkU0UHlsY2p6KzRIb1UvajNzd1B5bGNqejh0VjRRL3pjeE1QeWxjanorUHduVS9qM3N3UHlsY2p6OHRWNFEvcGRZcFB5bGNqei9ySG9JL3pjeE1QeWxjanorUHduVS9wZFlwUHlsY2p6L3JIb0kvSVdZbFB5bGNqei9zbUgwL3pjeE1QeWxjanorUHduVS9JV1lsUHlsY2p6L3NtSDAvQ3RjalB5bGNqeitQd25VL3pjeE1QeWxjanorUHduVS9DdGNqUHlsY2p6K1B3blUvSVdZbFB5bGNqejh5N0cwL3pjeE1QeWxjanorUHduVS9JV1lsUHlsY2p6OHk3RzAvcGRZcFB5bGNqejlKUjJjL3pjeE1QeWxjanorUHduVS9wZFlwUHlsY2p6OUpSMmMvajNzd1B5bGNqei9GMW1JL3pjeE1QeWxjanorUHduVS9qM3N3UHlsY2p6L0YxbUkvN0ZFNFB5bGNqeit1UjJFL3pjeE1QeWxjanorUHduVS83RkU0UHlsY2p6K3VSMkUvU1NoQVB5bGNqei9GMW1JL3pjeE1QeWxjanorUHduVS9TU2hBUHlsY2p6L0YxbUkvTXMxR1B5bGNqejlKUjJjL3pjeE1QeWxjanorUHduVS9NczFHUHlsY2p6OUpSMmMvdGoxTFB5bGNqejh5N0cwL0N0Y2p2eFN1aHorNEhzVy9DdGNqdjJabXBqKzRIc1cvSVdZbHYyWm1waitLTThHL0N0Y2p2eFN1aHorNEhzVy9JV1lsdjJabXBqK0tNOEcvSVdZbHZ4U3VoeitLTThHL0lXWWx2eFN1aHorS004Ry9JV1lsdjJabXBqK0tNOEcvcGRZcHYyWm1wajhWNGIyL0lXWWx2eFN1aHorS004Ry9wZFlwdjJabXBqOFY0YjIvcGRZcHZ4U3VoejhWNGIyL3BkWXB2eFN1aHo4VjRiMi9wZFlwdjJabXBqOFY0YjIvajNzd3YyWm1wai9UcUx1L3BkWXB2eFN1aHo4VjRiMi9qM3N3djJabXBqL1RxTHUvajNzd3Z4U3Voei9UcUx1L2ozc3d2eFN1aHovVHFMdS9qM3N3djJabXBqL1RxTHUvN0ZFNHYyWm1wajlJNGJxL2ozc3d2eFN1aHovVHFMdS83RkU0djJabXBqOUk0YnEvN0ZFNHZ4U3VoejlJNGJxLzdGRTR2eFN1aHo5STRicS83RkU0djJabXBqOUk0YnEvU1NoQXYyWm1wai9UcUx1LzdGRTR2eFN1aHo5STRicS9TU2hBdjJabXBqL1RxTHUvU1NoQXZ4U3Voei9UcUx1L1NTaEF2eFN1aHovVHFMdS9TU2hBdjJabXBqL1RxTHUvTXMxR3YyWm1wajhWNGIyL1NTaEF2eFN1aHovVHFMdS9NczFHdjJabXBqOFY0YjIvTXMxR3Z4U3VoejhWNGIyL01zMUd2eFN1aHo4VjRiMi9NczFHdjJabXBqOFY0YjIvdGoxTHYyWm1waitLTThHL01zMUd2eFN1aHo4VjRiMi90ajFMdjJabXBqK0tNOEcvdGoxTHZ4U3VoeitLTThHL3RqMUx2eFN1aHorS004Ry90ajFMdjJabXBqK0tNOEcvemN4TXYyWm1wais0SHNXL3RqMUx2eFN1aHorS004Ry96Y3hNdjJabXBqKzRIc1cvemN4TXZ4U3Voeis0SHNXL3pjeE12eFN1aHorNEhzVy96Y3hNdjJabXBqKzRIc1cvdGoxTHYyWm1wai9uQ2NtL3pjeE12eFN1aHorNEhzVy90ajFMdjJabXBqL25DY20vdGoxTHZ4U3Voei9uQ2NtL3RqMUx2eFN1aHovbkNjbS90ajFMdjJabXBqL25DY20vTXMxR3YyWm1wajljWE15L3RqMUx2eFN1aHovbkNjbS9NczFHdjJabXBqOWNYTXkvTXMxR3Z4U3VoejljWE15L01zMUd2eFN1aHo5Y1hNeS9NczFHdjJabXBqOWNYTXkvU1NoQXYyWm1waitkbE02L01zMUd2eFN1aHo5Y1hNeS9TU2hBdjJabXBqK2RsTTYvU1NoQXZ4U3VoeitkbE02L1NTaEF2eFN1aHorZGxNNi9TU2hBdjJabXBqK2RsTTYvN0ZFNHYyWm1wajhwWE0rL1NTaEF2eFN1aHorZGxNNi83RkU0djJabXBqOHBYTSsvN0ZFNHZ4U3VoejhwWE0rLzdGRTR2eFN1aHo4cFhNKy83RkU0djJabXBqOHBYTSsvajNzd3YyWm1waitkbE02LzdGRTR2eFN1aHo4cFhNKy9qM3N3djJabXBqK2RsTTYvajNzd3Z4U3VoeitkbE02L2ozc3d2eFN1aHorZGxNNi9qM3N3djJabXBqK2RsTTYvcGRZcHYyWm1wajljWE15L2ozc3d2eFN1aHorZGxNNi9wZFlwdjJabXBqOWNYTXkvcGRZcHZ4U3VoejljWE15L3BkWXB2eFN1aHo5Y1hNeS9wZFlwdjJabXBqOWNYTXkvSVdZbHYyWm1wai9uQ2NtL3BkWXB2eFN1aHo5Y1hNeS9JV1lsdjJabXBqL25DY20vSVdZbHZ4U3Voei9uQ2NtL0lXWWx2eFN1aHovbkNjbS9JV1lsdjJabXBqL25DY20vQ3RjanYyWm1wais0SHNXL0lXWWx2eFN1aHovbkNjbS9DdGNqdjJabXBqKzRIc1cvQ3RjanZ4U3Voeis0SHNXL0lXWWx2MlptcGovbkNjbS9wZFlwdjJabXBqOWNYTXkvajNzd3YyWm1waitkbE02L0lXWWx2MlptcGovbkNjbS9qM3N3djJabXBqK2RsTTYvN0ZFNHYyWm1wajhwWE0rL0lXWWx2MlptcGovbkNjbS83RkU0djJabXBqOHBYTSsvU1NoQXYyWm1waitkbE02L0lXWWx2MlptcGovbkNjbS9TU2hBdjJabXBqK2RsTTYvTXMxR3YyWm1wajljWE15L0lXWWx2MlptcGovbkNjbS9NczFHdjJabXBqOWNYTXkvdGoxTHYyWm1wai9uQ2NtL0lXWWx2MlptcGovbkNjbS90ajFMdjJabXBqL25DY20vemN4TXYyWm1wais0SHNXL0lXWWx2MlptcGovbkNjbS96Y3hNdjJabXBqKzRIc1cvdGoxTHYyWm1waitLTThHL0lXWWx2MlptcGovbkNjbS90ajFMdjJabXBqK0tNOEcvTXMxR3YyWm1wajhWNGIyL0lXWWx2MlptcGovbkNjbS9NczFHdjJabXBqOFY0YjIvU1NoQXYyWm1wai9UcUx1L0lXWWx2MlptcGovbkNjbS9TU2hBdjJabXBqL1RxTHUvN0ZFNHYyWm1wajlJNGJxL0lXWWx2MlptcGovbkNjbS83RkU0djJabXBqOUk0YnEvajNzd3YyWm1wai9UcUx1L0lXWWx2MlptcGovbkNjbS9qM3N3djJabXBqL1RxTHUvcGRZcHYyWm1wajhWNGIyL0lXWWx2MlptcGovbkNjbS9wZFlwdjJabXBqOFY0YjIvSVdZbHYyWm1waitLTThHL0lXWWx2MlptcGovbkNjbS9JV1lsdjJabXBqK0tNOEcvQ3RjanYyWm1wais0SHNXL0N0Y2p2eFN1aHorNEhzVy9JV1lsdnhTdWh6K0tNOEcvcGRZcHZ4U3VoejhWNGIyL0N0Y2p2eFN1aHorNEhzVy9wZFlwdnhTdWh6OFY0YjIvajNzd3Z4U3Voei9UcUx1L0N0Y2p2eFN1aHorNEhzVy9qM3N3dnhTdWh6L1RxTHUvN0ZFNHZ4U3VoejlJNGJxL0N0Y2p2eFN1aHorNEhzVy83RkU0dnhTdWh6OUk0YnEvU1NoQXZ4U3Voei9UcUx1L0N0Y2p2eFN1aHorNEhzVy9TU2hBdnhTdWh6L1RxTHUvTXMxR3Z4U3VoejhWNGIyL0N0Y2p2eFN1aHorNEhzVy9NczFHdnhTdWh6OFY0YjIvdGoxTHZ4U3VoeitLTThHL0N0Y2p2eFN1aHorNEhzVy90ajFMdnhTdWh6K0tNOEcvemN4TXZ4U3Voeis0SHNXL0N0Y2p2eFN1aHorNEhzVy96Y3hNdnhTdWh6KzRIc1cvdGoxTHZ4U3Voei9uQ2NtL0N0Y2p2eFN1aHorNEhzVy90ajFMdnhTdWh6L25DY20vTXMxR3Z4U3VoejljWE15L0N0Y2p2eFN1aHorNEhzVy9NczFHdnhTdWh6OWNYTXkvU1NoQXZ4U3VoeitkbE02L0N0Y2p2eFN1aHorNEhzVy9TU2hBdnhTdWh6K2RsTTYvN0ZFNHZ4U3VoejhwWE0rL0N0Y2p2eFN1aHorNEhzVy83RkU0dnhTdWh6OHBYTSsvajNzd3Z4U3VoeitkbE02L0N0Y2p2eFN1aHorNEhzVy9qM3N3dnhTdWh6K2RsTTYvcGRZcHZ4U3VoejljWE15L0N0Y2p2eFN1aHorNEhzVy9wZFlwdnhTdWh6OWNYTXkvSVdZbHZ4U3Voei9uQ2NtL0FBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBWG9Oc1B3QUFBQUFWNzhNK0FBQ0FQd0FBQUFBQUFBQUFYb05zUHdBQUFBQVY3OE0rWG9Oc1B3QUFBQUFWNzhNK1hvTnNQd0FBQUFBVjc4TStYb05zUHdBQUFBQVY3OE0rOHdRMVB3QUFBQUR6QkRVL1hvTnNQd0FBQUFBVjc4TSs4d1ExUHdBQUFBRHpCRFUvOHdRMVB3QUFBQUR6QkRVLzh3UTFQd0FBQUFEekJEVS84d1ExUHdBQUFBRHpCRFUvRmUvRFBnQUFBQUJlZzJ3Lzh3UTFQd0FBQUFEekJEVS9GZS9EUGdBQUFBQmVnMncvRmUvRFBnQUFBQUJlZzJ3L0ZlL0RQZ0FBQUFCZWcydy9GZS9EUGdBQUFBQmVnMncvTWpHTkpBQUFBQUFBQUlBL0ZlL0RQZ0FBQUFCZWcydy9NakdOSkFBQUFBQUFBSUEvTWpHTkpBQUFBQUFBQUlBL01qR05KQUFBQUFBQUFJQS9NakdOSkFBQUFBQUFBSUEvRmUvRHZnQUFBQUJlZzJ3L01qR05KQUFBQUFBQUFJQS9GZS9EdmdBQUFBQmVnMncvRmUvRHZnQUFBQUJlZzJ3L0ZlL0R2Z0FBQUFCZWcydy9GZS9EdmdBQUFBQmVnMncvOHdRMXZ3QUFBQUR6QkRVL0ZlL0R2Z0FBQUFCZWcydy84d1ExdndBQUFBRHpCRFUvOHdRMXZ3QUFBQUR6QkRVLzh3UTF2d0FBQUFEekJEVS84d1ExdndBQUFBRHpCRFUvWG9Oc3Z3QUFBQUFWNzhNKzh3UTF2d0FBQUFEekJEVS9Yb05zdndBQUFBQVY3OE0rWG9Oc3Z3QUFBQUFWNzhNK1hvTnN2d0FBQUFBVjc4TStYb05zdndBQUFBQVY3OE0rQUFDQXZ3QUFBQUF5TVEwbFhvTnN2d0FBQUFBVjc4TStBQUNBdndBQUFBQXlNUTBsQUFDQXZ3QUFBQUF5TVEwbEFBQ0F2d0FBQUFBeU1RMGxBQUNBdndBQUFBQXlNUTBsWG9Oc3Z3QUFBQUFWNzhPK0FBQ0F2d0FBQUFBeU1RMGxYb05zdndBQUFBQVY3OE8rWG9Oc3Z3QUFBQUFWNzhPK1hvTnN2d0FBQUFBVjc4TytYb05zdndBQUFBQVY3OE8rOHdRMXZ3QUFBQUR6QkRXL1hvTnN2d0FBQUFBVjc4Tys4d1ExdndBQUFBRHpCRFcvOHdRMXZ3QUFBQUR6QkRXLzh3UTF2d0FBQUFEekJEVy84d1ExdndBQUFBRHpCRFcvRmUvRHZnQUFBQUJlZzJ5Lzh3UTF2d0FBQUFEekJEVy9GZS9EdmdBQUFBQmVnMnkvRmUvRHZnQUFBQUJlZzJ5L0ZlL0R2Z0FBQUFCZWcyeS9GZS9EdmdBQUFBQmVnMnkveXNsVHBRQUFBQUFBQUlDL0ZlL0R2Z0FBQUFCZWcyeS95c2xUcFFBQUFBQUFBSUMveXNsVHBRQUFBQUFBQUlDL3lzbFRwUUFBQUFBQUFJQy95c2xUcFFBQUFBQUFBSUMvRmUvRFBnQUFBQUJlZzJ5L3lzbFRwUUFBQUFBQUFJQy9GZS9EUGdBQUFBQmVnMnkvRmUvRFBnQUFBQUJlZzJ5L0ZlL0RQZ0FBQUFCZWcyeS9GZS9EUGdBQUFBQmVnMnkvOHdRMVB3QUFBQUR6QkRXL0ZlL0RQZ0FBQUFCZWcyeS84d1ExUHdBQUFBRHpCRFcvOHdRMVB3QUFBQUR6QkRXLzh3UTFQd0FBQUFEekJEVy84d1ExUHdBQUFBRHpCRFcvWG9Oc1B3QUFBQUFWNzhPKzh3UTFQd0FBQUFEekJEVy9Yb05zUHdBQUFBQVY3OE8rWG9Oc1B3QUFBQUFWNzhPK1hvTnNQd0FBQUFBVjc4TytYb05zUHdBQUFBQVY3OE8rQUFDQVB3QUFBQUFBQUFBQVhvTnNQd0FBQUFBVjc4TytBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQ0FBQUFBQUFBQWdEOEFBQUNBQUFBQUFBQUFnRDhBQUFDQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFnQUFBZ0w4QUFBQUFBQUFBZ0FBQWdMOEFBQUFBQUFBQWdBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQ0FQd0FBQUFBQUFBQUFBQUNBUHdBQUFBQUFBQUFBWG9Oc1B3QUFBQUFWNzhNK0FBQ0FQd0FBQUFBQUFBQUFYb05zUHdBQUFBQVY3OE0rWG9Oc1B3QUFBQUFWNzhNK1hvTnNQd0FBQUFBVjc4TStYb05zUHdBQUFBQVY3OE0rOHdRMVB3QUFBQUR6QkRVL1hvTnNQd0FBQUFBVjc4TSs4d1ExUHdBQUFBRHpCRFUvOHdRMVB3QUFBQUR6QkRVLzh3UTFQd0FBQUFEekJEVS84d1ExUHdBQUFBRHpCRFUvRmUvRFBnQUFBQUJlZzJ3Lzh3UTFQd0FBQUFEekJEVS9GZS9EUGdBQUFBQmVnMncvRmUvRFBnQUFBQUJlZzJ3L0ZlL0RQZ0FBQUFCZWcydy9GZS9EUGdBQUFBQmVnMncvTWpHTkpBQUFBQUFBQUlBL0ZlL0RQZ0FBQUFCZWcydy9NakdOSkFBQUFBQUFBSUEvTWpHTkpBQUFBQUFBQUlBL01qR05KQUFBQUFBQUFJQS9NakdOSkFBQUFBQUFBSUEvRmUvRHZnQUFBQUJlZzJ3L01qR05KQUFBQUFBQUFJQS9GZS9EdmdBQUFBQmVnMncvRmUvRHZnQUFBQUJlZzJ3L0ZlL0R2Z0FBQUFCZWcydy9GZS9EdmdBQUFBQmVnMncvOHdRMXZ3QUFBQUR6QkRVL0ZlL0R2Z0FBQUFCZWcydy84d1ExdndBQUFBRHpCRFUvOHdRMXZ3QUFBQUR6QkRVLzh3UTF2d0FBQUFEekJEVS84d1ExdndBQUFBRHpCRFUvWG9Oc3Z3QUFBQUFWNzhNKzh3UTF2d0FBQUFEekJEVS9Yb05zdndBQUFBQVY3OE0rWG9Oc3Z3QUFBQUFWNzhNK1hvTnN2d0FBQUFBVjc4TStYb05zdndBQUFBQVY3OE0rQUFDQXZ3QUFBQUF5TVEwbFhvTnN2d0FBQUFBVjc4TStBQUNBdndBQUFBQXlNUTBsQUFDQXZ3QUFBQUF5TVEwbEFBQ0F2d0FBQUFBeU1RMGxBQUNBdndBQUFBQXlNUTBsWG9Oc3Z3QUFBQUFWNzhPK0FBQ0F2d0FBQUFBeU1RMGxYb05zdndBQUFBQVY3OE8rWG9Oc3Z3QUFBQUFWNzhPK1hvTnN2d0FBQUFBVjc4TytYb05zdndBQUFBQVY3OE8rOHdRMXZ3QUFBQUR6QkRXL1hvTnN2d0FBQUFBVjc4Tys4d1ExdndBQUFBRHpCRFcvOHdRMXZ3QUFBQUR6QkRXLzh3UTF2d0FBQUFEekJEVy84d1ExdndBQUFBRHpCRFcvRmUvRHZnQUFBQUJlZzJ5Lzh3UTF2d0FBQUFEekJEVy9GZS9EdmdBQUFBQmVnMnkvRmUvRHZnQUFBQUJlZzJ5L0ZlL0R2Z0FBQUFCZWcyeS9GZS9EdmdBQUFBQmVnMnkveXNsVHBRQUFBQUFBQUlDL0ZlL0R2Z0FBQUFCZWcyeS95c2xUcFFBQUFBQUFBSUMveXNsVHBRQUFBQUFBQUlDL3lzbFRwUUFBQUFBQUFJQy95c2xUcFFBQUFBQUFBSUMvRmUvRFBnQUFBQUJlZzJ5L3lzbFRwUUFBQUFBQUFJQy9GZS9EUGdBQUFBQmVnMnkvRmUvRFBnQUFBQUJlZzJ5L0ZlL0RQZ0FBQUFCZWcyeS9GZS9EUGdBQUFBQmVnMnkvOHdRMVB3QUFBQUR6QkRXL0ZlL0RQZ0FBQUFCZWcyeS84d1ExUHdBQUFBRHpCRFcvOHdRMVB3QUFBQUR6QkRXLzh3UTFQd0FBQUFEekJEVy84d1ExUHdBQUFBRHpCRFcvWG9Oc1B3QUFBQUFWNzhPKzh3UTFQd0FBQUFEekJEVy9Yb05zUHdBQUFBQVY3OE8rWG9Oc1B3QUFBQUFWNzhPK1hvTnNQd0FBQUFBVjc4TytYb05zUHdBQUFBQVY3OE8rQUFDQVB3QUFBQUFBQUFBQVhvTnNQd0FBQUFBVjc4TytBQUNBUHdBQUFBQUFBQUFBQUFDQVB3QUFBQUFBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0Q4QUFBQ0FBQUFBQUFBQWdEOEFBQUNBQUFBQUFBQUFnRDhBQUFDQUFBQUFBQUFBZ0Q4QUFBQUFBQUFBQUFBQWdEOEFBQUFBQUFBQUFBQUFnRDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFnQUFBZ0w4QUFBQUFBQUFBZ0FBQWdMOEFBQUFBQUFBQWdBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUFBQUFBZ0w4QUFBQUFBQUFBQUFBQWdMOEFBQUFBQUFBQUFBQUFnTDhBQUFBQUFBQUJBQUlBQXdBRUFBVUFCZ0FIQUFnQUNRQUtBQXNBREFBTkFBNEFEd0FRQUJFQUVnQVRBQlFBRlFBV0FCY0FHQUFaQUJvQUd3QWNBQjBBSGdBZkFDQUFJUUFpQUNNQUpBQWxBQ1lBSndBb0FDa0FLZ0FyQUN3QUxRQXVBQzhBTUFBeEFESUFNd0EwQURVQU5nQTNBRGdBT1FBNkFEc0FQQUE5QUQ0QVB3QkFBRUVBUWdCREFFUUFSUUJHQUVjQVNBQkpBRW9BU3dCTUFFMEFUZ0JQQUZBQVVRQlNBRk1BVkFCVkFGWUFWd0JZQUZrQVdnQmJBRndBWFFCZUFGOEFZQUJoQUdJQVl3QmtBR1VBWmdCbkFHZ0FhUUJxQUdzQWJBQnRBRzRBYndCd0FIRUFjZ0J6QUhRQWRRQjJBSGNBZUFCNUFIb0Fld0I4QUgwQWZnQi9BSUFBZ1FDQ0FJTUFoQUNGQUlZQWh3Q0lBSWtBaWdDTEFJd0FqUUNPQUk4QWtBQ1JBSklBa3dDVUFKVUFsZ0NYQUpnQW1RQ2FBSnNBbkFDZEFKNEFud0NnQUtFQW9nQ2pBS1FBcFFDbUFLY0FxQUNwQUtvQXF3Q3NBSzBBcmdDdkFMQUFzUUN5QUxNQXRBQzFBTFlBdHdDNEFMa0F1Z0M3QUx3QXZRQytBTDhBd0FEQkFNSUF3d0RFQU1VQXhnREhBTWdBeVFES0FNc0F6QUROQU00QXp3RFFBTkVBMGdEVEFOUUExUURXQU5jQTJBRFpBTm9BMndEY0FOMEEzZ0RmQU9BQTRRRGlBT01BNUFEbEFPWUE1d0RvQU9rQTZnRHJBT3dBN1FEdUFPOEE4QUR4QVBJQTh3RDBBUFVBOWdEM0FQZ0ErUUQ2QVBzQS9BRDlBUDRBL3dBQUFRRUJBZ0VEQVFRQkJRRUdBUWNCQ0FFSkFRb0JDd0VNQVEwQkRnRVBBUkFCRVFFU0FSTUJGQUVWQVJZQkZ3RVlBUmtCR2dFYkFSd0JIUUVlQVI4QklBRWhBU0lCSXdFa0FTVUJKZ0VuQVNnQktRRXFBU3NCTEFFdEFTNEJMd0V3QVRFQk1nRXpBVFFCTlFFMkFUY0JPQUU1QVRvQk93RThBVDBCUGdFL0FVQUJRUUZDQVVNQlJBRkZBVVlCUndGSUFVa0JTZ0ZMQVV3QlRRRk9BVThCVUFGUkFWSUJVd0ZVQVZVQlZnRlhBVmdCV1FGYUFWc0JYQUZkQVY0Qlh3RmdBV0VCWWdGakFXUUJaUUZtQVdjQiIsCiAgICAgICJieXRlTGVuZ3RoIjogMzYxOTIKICAgIH0KICBdLAogICJidWZmZXJWaWV3cyI6IFsKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImJ5dGVMZW5ndGgiOiAzMDI0LAogICAgICAidGFyZ2V0IjogMzQ5NjIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDMwMjQsCiAgICAgICJieXRlTGVuZ3RoIjogMzAyNCwKICAgICAgInRhcmdldCI6IDM0OTYyCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiA2MDQ4LAogICAgICAiYnl0ZUxlbmd0aCI6IDUwNCwKICAgICAgInRhcmdldCI6IDM0OTYzCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiA2NTUyLAogICAgICAiYnl0ZUxlbmd0aCI6IDE3MjgsCiAgICAgICJ0YXJnZXQiOiAzNDk2MgogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogODI4MCwKICAgICAgImJ5dGVMZW5ndGgiOiAxNzI4LAogICAgICAidGFyZ2V0IjogMzQ5NjIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDEwMDA4LAogICAgICAiYnl0ZUxlbmd0aCI6IDI4OCwKICAgICAgInRhcmdldCI6IDM0OTYzCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAxMDI5NiwKICAgICAgImJ5dGVMZW5ndGgiOiA4NjQsCiAgICAgICJ0YXJnZXQiOiAzNDk2MgogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMTExNjAsCiAgICAgICJieXRlTGVuZ3RoIjogODY0LAogICAgICAidGFyZ2V0IjogMzQ5NjIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDEyMDI0LAogICAgICAiYnl0ZUxlbmd0aCI6IDE0NCwKICAgICAgInRhcmdldCI6IDM0OTYzCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAxMjE2OCwKICAgICAgImJ5dGVMZW5ndGgiOiA2MTkyLAogICAgICAidGFyZ2V0IjogMzQ5NjIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDE4MzYwLAogICAgICAiYnl0ZUxlbmd0aCI6IDYxOTIsCiAgICAgICJ0YXJnZXQiOiAzNDk2MgogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMjQ1NTIsCiAgICAgICJieXRlTGVuZ3RoIjogMTAzMiwKICAgICAgInRhcmdldCI6IDM0OTYzCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAyNTU4NCwKICAgICAgImJ5dGVMZW5ndGgiOiAxNDQsCiAgICAgICJ0YXJnZXQiOiAzNDk2MgogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMjU3MjgsCiAgICAgICJieXRlTGVuZ3RoIjogMTQ0LAogICAgICAidGFyZ2V0IjogMzQ5NjIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDI1ODcyLAogICAgICAiYnl0ZUxlbmd0aCI6IDI0LAogICAgICAidGFyZ2V0IjogMzQ5NjMKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDI1ODk2LAogICAgICAiYnl0ZUxlbmd0aCI6IDQzMiwKICAgICAgInRhcmdldCI6IDM0OTYyCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAyNjMyOCwKICAgICAgImJ5dGVMZW5ndGgiOiA0MzIsCiAgICAgICJ0YXJnZXQiOiAzNDk2MgogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMjY3NjAsCiAgICAgICJieXRlTGVuZ3RoIjogNzIsCiAgICAgICJ0YXJnZXQiOiAzNDk2MwogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlciI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMjY4MzIsCiAgICAgICJieXRlTGVuZ3RoIjogNDMyMCwKICAgICAgInRhcmdldCI6IDM0OTYyCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAzMTE1MiwKICAgICAgImJ5dGVMZW5ndGgiOiA0MzIwLAogICAgICAidGFyZ2V0IjogMzQ5NjIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXIiOiAwLAogICAgICAiYnl0ZU9mZnNldCI6IDM1NDcyLAogICAgICAiYnl0ZUxlbmd0aCI6IDcyMCwKICAgICAgInRhcmdldCI6IDM0OTYzCiAgICB9CiAgXSwKICAiYWNjZXNzb3JzIjogWwogICAgewogICAgICAiYnVmZmVyVmlldyI6IDAsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiAyNTIsCiAgICAgICJ0eXBlIjogIlZFQzMiLAogICAgICAibWluIjogWwogICAgICAgIC0xLjU4LAogICAgICAgIC0xLjA4LAogICAgICAgIC00LjQKICAgICAgXSwKICAgICAgIm1heCI6IFsKICAgICAgICAxLjU4LAogICAgICAgIDEuMDIsCiAgICAgICAgMy45CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMSwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjYsCiAgICAgICJjb3VudCI6IDI1MiwKICAgICAgInR5cGUiOiAiVkVDMyIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMiwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjMsCiAgICAgICJjb3VudCI6IDI1MiwKICAgICAgInR5cGUiOiAiU0NBTEFSIiwKICAgICAgIm1pbiI6IFsKICAgICAgICAwCiAgICAgIF0sCiAgICAgICJtYXgiOiBbCiAgICAgICAgMjUxCiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMywKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjYsCiAgICAgICJjb3VudCI6IDE0NCwKICAgICAgInR5cGUiOiAiVkVDMyIsCiAgICAgICJtaW4iOiBbCiAgICAgICAgLTEuNTgsCiAgICAgICAgMC43OCwKICAgICAgICAtNC40CiAgICAgIF0sCiAgICAgICJtYXgiOiBbCiAgICAgICAgMS41OCwKICAgICAgICAxLjU0LAogICAgICAgIDMuOQogICAgICBdCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDQsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiAxNDQsCiAgICAgICJ0eXBlIjogIlZFQzMiCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDUsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTIzLAogICAgICAiY291bnQiOiAxNDQsCiAgICAgICJ0eXBlIjogIlNDQUxBUiIsCiAgICAgICJtaW4iOiBbCiAgICAgICAgMAogICAgICBdLAogICAgICAibWF4IjogWwogICAgICAgIDE0MwogICAgICBdCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDYsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiA3MiwKICAgICAgInR5cGUiOiAiVkVDMyIsCiAgICAgICJtaW4iOiBbCiAgICAgICAgLTEuNDgsCiAgICAgICAgMC44NCwKICAgICAgICAtMi4yCiAgICAgIF0sCiAgICAgICJtYXgiOiBbCiAgICAgICAgMS40OCwKICAgICAgICAxLjYyLAogICAgICAgIDIuNAogICAgICBdCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDcsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiA3MiwKICAgICAgInR5cGUiOiAiVkVDMyIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogOCwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjMsCiAgICAgICJjb3VudCI6IDcyLAogICAgICAidHlwZSI6ICJTQ0FMQVIiLAogICAgICAibWluIjogWwogICAgICAgIDAKICAgICAgXSwKICAgICAgIm1heCI6IFsKICAgICAgICA3MQogICAgICBdCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDksCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiA1MTYsCiAgICAgICJ0eXBlIjogIlZFQzMiLAogICAgICAibWluIjogWwogICAgICAgIC0wLjE2LAogICAgICAgIDAuODQ5OTk5OTk5OTk5OTk5NiwKICAgICAgICAtMwogICAgICBdLAogICAgICAibWF4IjogWwogICAgICAgIDIuMTgsCiAgICAgICAgNi4yNSwKICAgICAgICA1LjA1CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMTAsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiA1MTYsCiAgICAgICJ0eXBlIjogIlZFQzMiCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDExLAogICAgICAiYnl0ZU9mZnNldCI6IDAsCiAgICAgICJjb21wb25lbnRUeXBlIjogNTEyMywKICAgICAgImNvdW50IjogNTE2LAogICAgICAidHlwZSI6ICJTQ0FMQVIiLAogICAgICAibWluIjogWwogICAgICAgIDAKICAgICAgXSwKICAgICAgIm1heCI6IFsKICAgICAgICA1MTUKICAgICAgXQogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlclZpZXciOiAxMiwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjYsCiAgICAgICJjb3VudCI6IDEyLAogICAgICAidHlwZSI6ICJWRUMzIiwKICAgICAgIm1pbiI6IFsKICAgICAgICAtMC4wOCwKICAgICAgICAxLjEyLAogICAgICAgIC0yLjk2CiAgICAgIF0sCiAgICAgICJtYXgiOiBbCiAgICAgICAgMS44NiwKICAgICAgICA0LjgyLAogICAgICAgIC0wLjc0CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMTMsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiAxMiwKICAgICAgInR5cGUiOiAiVkVDMyIKICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMTQsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTIzLAogICAgICAiY291bnQiOiAxMiwKICAgICAgInR5cGUiOiAiU0NBTEFSIiwKICAgICAgIm1pbiI6IFsKICAgICAgICAwCiAgICAgIF0sCiAgICAgICJtYXgiOiBbCiAgICAgICAgMTEKICAgICAgXQogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlclZpZXciOiAxNSwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjYsCiAgICAgICJjb3VudCI6IDM2LAogICAgICAidHlwZSI6ICJWRUMzIiwKICAgICAgIm1pbiI6IFsKICAgICAgICAtMC45NiwKICAgICAgICAwLjc4LAogICAgICAgIDEuMjYKICAgICAgXSwKICAgICAgIm1heCI6IFsKICAgICAgICAwLjk2LAogICAgICAgIDAuODgsCiAgICAgICAgMS40NAogICAgICBdCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDE2LAogICAgICAiYnl0ZU9mZnNldCI6IDAsCiAgICAgICJjb21wb25lbnRUeXBlIjogNTEyNiwKICAgICAgImNvdW50IjogMzYsCiAgICAgICJ0eXBlIjogIlZFQzMiCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDE3LAogICAgICAiYnl0ZU9mZnNldCI6IDAsCiAgICAgICJjb21wb25lbnRUeXBlIjogNTEyMywKICAgICAgImNvdW50IjogMzYsCiAgICAgICJ0eXBlIjogIlNDQUxBUiIsCiAgICAgICJtaW4iOiBbCiAgICAgICAgMAogICAgICBdLAogICAgICAibWF4IjogWwogICAgICAgIDM1CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMTgsCiAgICAgICJieXRlT2Zmc2V0IjogMCwKICAgICAgImNvbXBvbmVudFR5cGUiOiA1MTI2LAogICAgICAiY291bnQiOiAzNjAsCiAgICAgICJ0eXBlIjogIlZFQzMiLAogICAgICAibWluIjogWwogICAgICAgIC0wLjc5OTk5OTk5OTk5OTk5OTksCiAgICAgICAgMS4wNiwKICAgICAgICAtMS42MgogICAgICBdLAogICAgICAibWF4IjogWwogICAgICAgIDAuNzk5OTk5OTk5OTk5OTk5OSwKICAgICAgICAxLjM1OTk5OTk5OTk5OTk5OTksCiAgICAgICAgMS4wNAogICAgICBdCiAgICB9LAogICAgewogICAgICAiYnVmZmVyVmlldyI6IDE5LAogICAgICAiYnl0ZU9mZnNldCI6IDAsCiAgICAgICJjb21wb25lbnRUeXBlIjogNTEyNiwKICAgICAgImNvdW50IjogMzYwLAogICAgICAidHlwZSI6ICJWRUMzIgogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlclZpZXciOiAyMCwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjMsCiAgICAgICJjb3VudCI6IDM2MCwKICAgICAgInR5cGUiOiAiU0NBTEFSIiwKICAgICAgIm1pbiI6IFsKICAgICAgICAwCiAgICAgIF0sCiAgICAgICJtYXgiOiBbCiAgICAgICAgMzU5CiAgICAgIF0KICAgIH0KICBdCn0K"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
22
36
|
// src/asset-url.js
|
|
23
|
-
function createInlineShowcaseAssetUrl() {
|
|
24
|
-
|
|
37
|
+
function createInlineShowcaseAssetUrl(assetName) {
|
|
38
|
+
const inlineUrl = INLINE_SHOWCASE_ASSET_URLS[assetName];
|
|
39
|
+
return inlineUrl ? new URL(inlineUrl) : null;
|
|
25
40
|
}
|
|
26
41
|
function getBrowserBaseUrl() {
|
|
27
42
|
if (typeof document !== "undefined" && typeof document.baseURI === "string" && document.baseURI.length > 0) {
|
|
@@ -32,27 +47,177 @@ function getBrowserBaseUrl() {
|
|
|
32
47
|
}
|
|
33
48
|
return null;
|
|
34
49
|
}
|
|
35
|
-
function
|
|
50
|
+
function normalizeAssetName(assetName) {
|
|
51
|
+
return typeof assetName === "string" && assetName in SHOWCASE_ASSET_FILES ? assetName : "brigantine";
|
|
52
|
+
}
|
|
53
|
+
function parseResolveArgs(baseUrlOrAssetName, assetName) {
|
|
54
|
+
if (typeof baseUrlOrAssetName === "string" && baseUrlOrAssetName in SHOWCASE_ASSET_FILES && typeof assetName === "undefined") {
|
|
55
|
+
return {
|
|
56
|
+
baseUrl: import_meta.url,
|
|
57
|
+
assetName: baseUrlOrAssetName
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
baseUrl: baseUrlOrAssetName ?? import_meta.url,
|
|
62
|
+
assetName: normalizeAssetName(assetName)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function resolveShowcaseAssetUrl(baseUrlOrAssetName, assetName) {
|
|
66
|
+
const resolved = parseResolveArgs(baseUrlOrAssetName, assetName);
|
|
67
|
+
const fileName = SHOWCASE_ASSET_FILES[resolved.assetName];
|
|
36
68
|
try {
|
|
37
|
-
return new URL(
|
|
69
|
+
return new URL(`../assets/${fileName}`, resolved.baseUrl);
|
|
38
70
|
} catch {
|
|
39
71
|
const browserBaseUrl = getBrowserBaseUrl();
|
|
40
72
|
if (browserBaseUrl) {
|
|
41
73
|
try {
|
|
42
|
-
const normalizedBaseUrl = new URL(
|
|
43
|
-
return new URL(
|
|
74
|
+
const normalizedBaseUrl = new URL(resolved.baseUrl, browserBaseUrl);
|
|
75
|
+
return new URL(`../assets/${fileName}`, normalizedBaseUrl);
|
|
44
76
|
} catch {
|
|
45
|
-
|
|
77
|
+
const inlineAsset = createInlineShowcaseAssetUrl(resolved.assetName);
|
|
78
|
+
if (inlineAsset) {
|
|
79
|
+
return inlineAsset;
|
|
80
|
+
}
|
|
46
81
|
}
|
|
47
82
|
}
|
|
48
|
-
|
|
83
|
+
try {
|
|
84
|
+
return new URL(`../assets/${fileName}`, import_meta.url);
|
|
85
|
+
} catch {
|
|
86
|
+
return new URL(`assets/${fileName}`, "file:///");
|
|
87
|
+
}
|
|
49
88
|
}
|
|
50
89
|
}
|
|
51
|
-
|
|
90
|
+
function shouldUseInlineShowcaseFallback(url) {
|
|
91
|
+
const href = url instanceof URL ? url.href : String(url ?? "");
|
|
92
|
+
return href.includes("/assets/");
|
|
93
|
+
}
|
|
94
|
+
var import_meta, SHOWCASE_ASSET_FILES;
|
|
52
95
|
var init_asset_url = __esm({
|
|
53
96
|
"src/asset-url.js"() {
|
|
97
|
+
init_showcase_inline_assets();
|
|
54
98
|
import_meta = {};
|
|
55
|
-
|
|
99
|
+
SHOWCASE_ASSET_FILES = Object.freeze({
|
|
100
|
+
brigantine: "brigantine.gltf",
|
|
101
|
+
cutter: "cutter.gltf",
|
|
102
|
+
lighthouse: "lighthouse.gltf",
|
|
103
|
+
"harbor-dock": "harbor-dock.gltf"
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// src/translations/en-GB.js
|
|
109
|
+
var gpuSharedEnGbTranslations;
|
|
110
|
+
var init_en_GB = __esm({
|
|
111
|
+
"src/translations/en-GB.js"() {
|
|
112
|
+
gpuSharedEnGbTranslations = Object.freeze({
|
|
113
|
+
"gpuShared.showcase.title": "Flag by the Sea",
|
|
114
|
+
"gpuShared.showcase.subtitle": "Shared 3D validation scene using GLTF ships, cloth, fluid continuity, adaptive performance, and telemetry.",
|
|
115
|
+
"gpuShared.showcase.status.booting": "Booting 3D scene...",
|
|
116
|
+
"gpuShared.showcase.status.live": "3D scene live - {fps} FPS",
|
|
117
|
+
"gpuShared.showcase.details.booting": "Preparing a moonlit harbor scene, GLTF hull data, cloth and fluid continuity plans, and adaptive quality metadata.",
|
|
118
|
+
"gpuShared.showcase.details.physics": "Stable world snapshots are emitted from {snapshotStageId} after the authoritative solver; the heavier hull now carries momentum through mass-aware collision impulses while cloth and fluid remain downstream.",
|
|
119
|
+
"gpuShared.showcase.details.realistic": "Moonlit GLTF ships now mix a brigantine and a cutter against modeled harbor assets; cloth, fluid, and ship-local lighting stay continuous while the governor pressure is {pressureLevel}.",
|
|
120
|
+
"gpuShared.showcase.details.legacy": "Moonlit GLTF ships use the legacy brigantine and placeholder harbor blocks while cloth, fluid, and ship-local lighting stay continuous while the governor pressure is {pressureLevel}.",
|
|
121
|
+
"gpuShared.showcase.action.pause": "Pause",
|
|
122
|
+
"gpuShared.showcase.action.resume": "Resume",
|
|
123
|
+
"gpuShared.showcase.control.stressMode": "Stress mode",
|
|
124
|
+
"gpuShared.showcase.control.focus": "Focus",
|
|
125
|
+
"gpuShared.showcase.focus.integrated": "integrated",
|
|
126
|
+
"gpuShared.showcase.focus.lighting": "lighting",
|
|
127
|
+
"gpuShared.showcase.focus.cloth": "cloth",
|
|
128
|
+
"gpuShared.showcase.focus.fluid": "fluid",
|
|
129
|
+
"gpuShared.showcase.focus.physics": "physics",
|
|
130
|
+
"gpuShared.showcase.focus.performance": "performance",
|
|
131
|
+
"gpuShared.showcase.focus.debug": "debug",
|
|
132
|
+
"gpuShared.showcase.legend.title": "Scene",
|
|
133
|
+
"gpuShared.showcase.legend.shipMetadata": "GLTF ships carry hull mass and damping metadata.",
|
|
134
|
+
"gpuShared.showcase.legend.lighting": "Lanterns and torches warm the moonlit harbor.",
|
|
135
|
+
"gpuShared.showcase.legend.collisions": "Mass-aware collisions stay authoritative near the camera.",
|
|
136
|
+
"gpuShared.showcase.section.sceneState": "Scene State",
|
|
137
|
+
"gpuShared.showcase.section.qualityBudgets": "Quality + Budgets",
|
|
138
|
+
"gpuShared.showcase.section.debugTelemetry": "Debug Telemetry",
|
|
139
|
+
"gpuShared.showcase.section.notes": "Notes",
|
|
140
|
+
"gpuShared.showcase.note.assetLoading": "Ships are loaded from a GLTF asset and carry mass, damping, restitution, and hull extents from node extras.",
|
|
141
|
+
"gpuShared.showcase.note.moonlight": "Moonlight sets the cold ambient read while deck lanterns and harbor torches provide warm local contrast.",
|
|
142
|
+
"gpuShared.showcase.note.continuity": "Cloth and fluid continuity stay coherent across near, mid, far, and horizon bands even in the darker night palette.",
|
|
143
|
+
"gpuShared.showcase.note.performance": "Performance pressure reduces visual detail before mass-weighted authoritative collision motion is touched.",
|
|
144
|
+
"gpuShared.showcase.note.physicsSnapshots": "Stable world snapshots are taken after the authoritative rigid-body commit and before visual follow-up work.",
|
|
145
|
+
"gpuShared.showcase.note.physicsCollisions": "The ships collide with mass-weighted impulses and positional correction, so the heavier hull keeps more of its line.",
|
|
146
|
+
"gpuShared.showcase.note.physicsLighting": "Moonlight keeps the overall read legible while lanterns and torches make collision moments easy to track against the water.",
|
|
147
|
+
"gpuShared.debug.adapter.showcase": "3D showcase",
|
|
148
|
+
"gpuShared.debug.allocation.mainColorBuffer": "Main color buffer",
|
|
149
|
+
"gpuShared.debug.allocation.shadowImpressionAtlas": "Shadow impression atlas"
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// src/i18n.js
|
|
155
|
+
function formatTranslation(template, args = {}) {
|
|
156
|
+
return template.replace(/\{([A-Za-z0-9_]+)\}/g, (match, name) => {
|
|
157
|
+
if (!Object.prototype.hasOwnProperty.call(args, name)) {
|
|
158
|
+
return match;
|
|
159
|
+
}
|
|
160
|
+
const value = args[name];
|
|
161
|
+
return value == null ? "" : String(value);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function translateGpuSharedText(key, args, translate) {
|
|
165
|
+
const translated = translate?.(key, args);
|
|
166
|
+
if (translated && translated !== key) {
|
|
167
|
+
return translated;
|
|
168
|
+
}
|
|
169
|
+
const fallback = gpuSharedEnGbTranslations[key];
|
|
170
|
+
return fallback ? formatTranslation(fallback, args) : key;
|
|
171
|
+
}
|
|
172
|
+
function createGpuSharedTranslator(translate) {
|
|
173
|
+
return (key, args) => translateGpuSharedText(key, args, translate);
|
|
174
|
+
}
|
|
175
|
+
var gpuSharedTranslationKeys, gpuSharedTranslations;
|
|
176
|
+
var init_i18n = __esm({
|
|
177
|
+
"src/i18n.js"() {
|
|
178
|
+
init_en_GB();
|
|
179
|
+
gpuSharedTranslationKeys = Object.freeze({
|
|
180
|
+
showcaseTitle: "gpuShared.showcase.title",
|
|
181
|
+
showcaseSubtitle: "gpuShared.showcase.subtitle",
|
|
182
|
+
statusBooting: "gpuShared.showcase.status.booting",
|
|
183
|
+
statusLive: "gpuShared.showcase.status.live",
|
|
184
|
+
detailsBooting: "gpuShared.showcase.details.booting",
|
|
185
|
+
detailsPhysics: "gpuShared.showcase.details.physics",
|
|
186
|
+
detailsRealistic: "gpuShared.showcase.details.realistic",
|
|
187
|
+
detailsLegacy: "gpuShared.showcase.details.legacy",
|
|
188
|
+
pause: "gpuShared.showcase.action.pause",
|
|
189
|
+
resume: "gpuShared.showcase.action.resume",
|
|
190
|
+
stressMode: "gpuShared.showcase.control.stressMode",
|
|
191
|
+
focus: "gpuShared.showcase.control.focus",
|
|
192
|
+
focusIntegrated: "gpuShared.showcase.focus.integrated",
|
|
193
|
+
focusLighting: "gpuShared.showcase.focus.lighting",
|
|
194
|
+
focusCloth: "gpuShared.showcase.focus.cloth",
|
|
195
|
+
focusFluid: "gpuShared.showcase.focus.fluid",
|
|
196
|
+
focusPhysics: "gpuShared.showcase.focus.physics",
|
|
197
|
+
focusPerformance: "gpuShared.showcase.focus.performance",
|
|
198
|
+
focusDebug: "gpuShared.showcase.focus.debug",
|
|
199
|
+
legendTitle: "gpuShared.showcase.legend.title",
|
|
200
|
+
legendShipMetadata: "gpuShared.showcase.legend.shipMetadata",
|
|
201
|
+
legendLighting: "gpuShared.showcase.legend.lighting",
|
|
202
|
+
legendCollisions: "gpuShared.showcase.legend.collisions",
|
|
203
|
+
sceneState: "gpuShared.showcase.section.sceneState",
|
|
204
|
+
qualityBudgets: "gpuShared.showcase.section.qualityBudgets",
|
|
205
|
+
debugTelemetry: "gpuShared.showcase.section.debugTelemetry",
|
|
206
|
+
notes: "gpuShared.showcase.section.notes",
|
|
207
|
+
noteAssetLoading: "gpuShared.showcase.note.assetLoading",
|
|
208
|
+
noteMoonlight: "gpuShared.showcase.note.moonlight",
|
|
209
|
+
noteContinuity: "gpuShared.showcase.note.continuity",
|
|
210
|
+
notePerformance: "gpuShared.showcase.note.performance",
|
|
211
|
+
notePhysicsSnapshots: "gpuShared.showcase.note.physicsSnapshots",
|
|
212
|
+
notePhysicsCollisions: "gpuShared.showcase.note.physicsCollisions",
|
|
213
|
+
notePhysicsLighting: "gpuShared.showcase.note.physicsLighting",
|
|
214
|
+
debugAdapterShowcase: "gpuShared.debug.adapter.showcase",
|
|
215
|
+
debugMainColorBuffer: "gpuShared.debug.allocation.mainColorBuffer",
|
|
216
|
+
debugShadowImpressionAtlas: "gpuShared.debug.allocation.shadowImpressionAtlas"
|
|
217
|
+
});
|
|
218
|
+
gpuSharedTranslations = Object.freeze({
|
|
219
|
+
"en-GB": gpuSharedEnGbTranslations
|
|
220
|
+
});
|
|
56
221
|
}
|
|
57
222
|
});
|
|
58
223
|
|
|
@@ -75,6 +240,8 @@ function decodeDataUri(uri) {
|
|
|
75
240
|
}
|
|
76
241
|
function getComponentArray(componentType, buffer, byteOffset, count) {
|
|
77
242
|
switch (componentType) {
|
|
243
|
+
case 5121:
|
|
244
|
+
return new Uint8Array(buffer, byteOffset, count);
|
|
78
245
|
case 5123:
|
|
79
246
|
return new Uint16Array(buffer, byteOffset, count);
|
|
80
247
|
case 5125:
|
|
@@ -85,6 +252,16 @@ function getComponentArray(componentType, buffer, byteOffset, count) {
|
|
|
85
252
|
throw new Error(`Unsupported glTF componentType: ${componentType}`);
|
|
86
253
|
}
|
|
87
254
|
}
|
|
255
|
+
function getNormalizationScale(componentType) {
|
|
256
|
+
switch (componentType) {
|
|
257
|
+
case 5121:
|
|
258
|
+
return 255;
|
|
259
|
+
case 5123:
|
|
260
|
+
return 65535;
|
|
261
|
+
default:
|
|
262
|
+
return 1;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
88
265
|
function getTypeSize(type) {
|
|
89
266
|
switch (type) {
|
|
90
267
|
case "SCALAR":
|
|
@@ -100,27 +277,59 @@ function getTypeSize(type) {
|
|
|
100
277
|
}
|
|
101
278
|
}
|
|
102
279
|
function readAccessor(document2, accessorIndex, buffers) {
|
|
103
|
-
const accessor = document2.accessors[accessorIndex];
|
|
104
|
-
|
|
280
|
+
const accessor = document2.accessors?.[accessorIndex];
|
|
281
|
+
if (!accessor) {
|
|
282
|
+
throw new Error(`glTF accessor ${accessorIndex} is missing.`);
|
|
283
|
+
}
|
|
284
|
+
const bufferView = document2.bufferViews?.[accessor.bufferView];
|
|
285
|
+
if (!bufferView) {
|
|
286
|
+
throw new Error(`glTF bufferView ${accessor.bufferView} is missing.`);
|
|
287
|
+
}
|
|
105
288
|
const buffer = buffers[bufferView.buffer];
|
|
106
289
|
const componentCount = getTypeSize(accessor.type);
|
|
107
290
|
const byteOffset = (bufferView.byteOffset ?? 0) + (accessor.byteOffset ?? 0);
|
|
108
291
|
const valueCount = accessor.count * componentCount;
|
|
109
|
-
|
|
292
|
+
const values = Array.from(
|
|
293
|
+
getComponentArray(accessor.componentType, buffer, byteOffset, valueCount)
|
|
294
|
+
);
|
|
295
|
+
if (accessor.normalized) {
|
|
296
|
+
const scale = getNormalizationScale(accessor.componentType);
|
|
297
|
+
return values.map((value) => value / scale);
|
|
298
|
+
}
|
|
299
|
+
return values;
|
|
110
300
|
}
|
|
111
|
-
function
|
|
301
|
+
function getMaterialInfo(document2, primitive) {
|
|
112
302
|
const material = document2.materials?.[primitive.material] ?? null;
|
|
113
303
|
const factor = material?.pbrMetallicRoughness?.baseColorFactor ?? [0.56, 0.33, 0.22, 1];
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
304
|
+
const emissive = material?.emissiveFactor ?? [0, 0, 0];
|
|
305
|
+
return Object.freeze({
|
|
306
|
+
name: material?.name ?? "default-material",
|
|
307
|
+
color: Object.freeze({
|
|
308
|
+
r: factor[0],
|
|
309
|
+
g: factor[1],
|
|
310
|
+
b: factor[2],
|
|
311
|
+
a: factor[3] ?? 1
|
|
312
|
+
}),
|
|
313
|
+
roughness: typeof material?.pbrMetallicRoughness?.roughnessFactor === "number" ? material.pbrMetallicRoughness.roughnessFactor : 0.92,
|
|
314
|
+
metallic: typeof material?.pbrMetallicRoughness?.metallicFactor === "number" ? material.pbrMetallicRoughness.metallicFactor : 0.08,
|
|
315
|
+
emissive: Object.freeze({
|
|
316
|
+
r: emissive[0] ?? 0,
|
|
317
|
+
g: emissive[1] ?? 0,
|
|
318
|
+
b: emissive[2] ?? 0
|
|
319
|
+
})
|
|
320
|
+
});
|
|
120
321
|
}
|
|
121
322
|
function computeBounds(positions) {
|
|
122
|
-
const min = [
|
|
123
|
-
|
|
323
|
+
const min = [
|
|
324
|
+
Number.POSITIVE_INFINITY,
|
|
325
|
+
Number.POSITIVE_INFINITY,
|
|
326
|
+
Number.POSITIVE_INFINITY
|
|
327
|
+
];
|
|
328
|
+
const max = [
|
|
329
|
+
Number.NEGATIVE_INFINITY,
|
|
330
|
+
Number.NEGATIVE_INFINITY,
|
|
331
|
+
Number.NEGATIVE_INFINITY
|
|
332
|
+
];
|
|
124
333
|
for (let index = 0; index < positions.length; index += 3) {
|
|
125
334
|
min[0] = Math.min(min[0], positions[index]);
|
|
126
335
|
min[1] = Math.min(min[1], positions[index + 1]);
|
|
@@ -129,7 +338,10 @@ function computeBounds(positions) {
|
|
|
129
338
|
max[1] = Math.max(max[1], positions[index + 1]);
|
|
130
339
|
max[2] = Math.max(max[2], positions[index + 2]);
|
|
131
340
|
}
|
|
132
|
-
return {
|
|
341
|
+
return Object.freeze({
|
|
342
|
+
min: Object.freeze([min[0], min[1], min[2]]),
|
|
343
|
+
max: Object.freeze([max[0], max[1], max[2]])
|
|
344
|
+
});
|
|
133
345
|
}
|
|
134
346
|
function resolveBrowserRequestBaseUrl() {
|
|
135
347
|
if (typeof document !== "undefined" && typeof document.baseURI === "string" && document.baseURI.length > 0) {
|
|
@@ -154,16 +366,173 @@ function resolveFetchBaseUrl(requestUrl, responseUrl) {
|
|
|
154
366
|
if (browserBaseUrl) {
|
|
155
367
|
return new URL(requestUrl, browserBaseUrl);
|
|
156
368
|
}
|
|
157
|
-
throw new Error(
|
|
369
|
+
throw new Error(
|
|
370
|
+
`Unable to resolve a stable base URL for glTF asset loading: ${String(requestUrl)}`
|
|
371
|
+
);
|
|
158
372
|
}
|
|
159
373
|
}
|
|
160
|
-
|
|
374
|
+
function createIdentityMatrix() {
|
|
375
|
+
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
376
|
+
}
|
|
377
|
+
function multiplyMatrices(a, b) {
|
|
378
|
+
const out = new Array(16).fill(0);
|
|
379
|
+
for (let column = 0; column < 4; column += 1) {
|
|
380
|
+
for (let row = 0; row < 4; row += 1) {
|
|
381
|
+
out[column * 4 + row] = a[0 * 4 + row] * b[column * 4 + 0] + a[1 * 4 + row] * b[column * 4 + 1] + a[2 * 4 + row] * b[column * 4 + 2] + a[3 * 4 + row] * b[column * 4 + 3];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return out;
|
|
385
|
+
}
|
|
386
|
+
function composeNodeMatrix(node) {
|
|
387
|
+
if (Array.isArray(node.matrix) && node.matrix.length === 16) {
|
|
388
|
+
return [...node.matrix];
|
|
389
|
+
}
|
|
390
|
+
const translation = Array.isArray(node.translation) ? node.translation : [0, 0, 0];
|
|
391
|
+
const rotation = Array.isArray(node.rotation) ? node.rotation : [0, 0, 0, 1];
|
|
392
|
+
const scale = Array.isArray(node.scale) ? node.scale : [1, 1, 1];
|
|
393
|
+
const [x, y, z, w] = rotation;
|
|
394
|
+
const x2 = x + x;
|
|
395
|
+
const y2 = y + y;
|
|
396
|
+
const z2 = z + z;
|
|
397
|
+
const xx = x * x2;
|
|
398
|
+
const xy = x * y2;
|
|
399
|
+
const xz = x * z2;
|
|
400
|
+
const yy = y * y2;
|
|
401
|
+
const yz = y * z2;
|
|
402
|
+
const zz = z * z2;
|
|
403
|
+
const wx = w * x2;
|
|
404
|
+
const wy = w * y2;
|
|
405
|
+
const wz = w * z2;
|
|
406
|
+
return [
|
|
407
|
+
(1 - (yy + zz)) * scale[0],
|
|
408
|
+
(xy + wz) * scale[0],
|
|
409
|
+
(xz - wy) * scale[0],
|
|
410
|
+
0,
|
|
411
|
+
(xy - wz) * scale[1],
|
|
412
|
+
(1 - (xx + zz)) * scale[1],
|
|
413
|
+
(yz + wx) * scale[1],
|
|
414
|
+
0,
|
|
415
|
+
(xz + wy) * scale[2],
|
|
416
|
+
(yz - wx) * scale[2],
|
|
417
|
+
(1 - (xx + yy)) * scale[2],
|
|
418
|
+
0,
|
|
419
|
+
translation[0],
|
|
420
|
+
translation[1],
|
|
421
|
+
translation[2],
|
|
422
|
+
1
|
|
423
|
+
];
|
|
424
|
+
}
|
|
425
|
+
function transformPosition(position, matrix) {
|
|
426
|
+
return [
|
|
427
|
+
matrix[0] * position[0] + matrix[4] * position[1] + matrix[8] * position[2] + matrix[12],
|
|
428
|
+
matrix[1] * position[0] + matrix[5] * position[1] + matrix[9] * position[2] + matrix[13],
|
|
429
|
+
matrix[2] * position[0] + matrix[6] * position[1] + matrix[10] * position[2] + matrix[14]
|
|
430
|
+
];
|
|
431
|
+
}
|
|
432
|
+
function transformNormal(normal, matrix) {
|
|
433
|
+
const transformed = [
|
|
434
|
+
matrix[0] * normal[0] + matrix[4] * normal[1] + matrix[8] * normal[2],
|
|
435
|
+
matrix[1] * normal[0] + matrix[5] * normal[1] + matrix[9] * normal[2],
|
|
436
|
+
matrix[2] * normal[0] + matrix[6] * normal[1] + matrix[10] * normal[2]
|
|
437
|
+
];
|
|
438
|
+
const length = Math.hypot(transformed[0], transformed[1], transformed[2]) || 1;
|
|
439
|
+
return [transformed[0] / length, transformed[1] / length, transformed[2] / length];
|
|
440
|
+
}
|
|
441
|
+
function collectScenePrimitives(document2, buffers) {
|
|
442
|
+
const scene = document2.scenes?.[document2.scene ?? 0];
|
|
443
|
+
if (!scene || !Array.isArray(scene.nodes) || scene.nodes.length === 0) {
|
|
444
|
+
throw new Error("glTF demo asset must expose a default scene with at least one node.");
|
|
445
|
+
}
|
|
446
|
+
const results = [];
|
|
447
|
+
let modelName = null;
|
|
448
|
+
let physics = null;
|
|
449
|
+
function visit(nodeIndex, parentMatrix) {
|
|
450
|
+
const node = document2.nodes?.[nodeIndex];
|
|
451
|
+
if (!node) {
|
|
452
|
+
throw new Error(`glTF node ${nodeIndex} is missing.`);
|
|
453
|
+
}
|
|
454
|
+
const localMatrix = composeNodeMatrix(node);
|
|
455
|
+
const worldMatrix = multiplyMatrices(parentMatrix, localMatrix);
|
|
456
|
+
if (!modelName && typeof node.name === "string" && node.name.length > 0) {
|
|
457
|
+
modelName = node.name;
|
|
458
|
+
}
|
|
459
|
+
if (!physics && node.extras?.physics && typeof node.extras.physics === "object") {
|
|
460
|
+
physics = Object.freeze({ ...node.extras.physics });
|
|
461
|
+
}
|
|
462
|
+
if (typeof node.mesh === "number") {
|
|
463
|
+
const mesh = document2.meshes?.[node.mesh];
|
|
464
|
+
if (!mesh || !Array.isArray(mesh.primitives)) {
|
|
465
|
+
throw new Error(`glTF mesh ${node.mesh} is missing primitives.`);
|
|
466
|
+
}
|
|
467
|
+
mesh.primitives.forEach((primitive, primitiveIndex) => {
|
|
468
|
+
const positions = readAccessor(document2, primitive.attributes.POSITION, buffers);
|
|
469
|
+
const normals = typeof primitive.attributes.NORMAL === "number" ? readAccessor(document2, primitive.attributes.NORMAL, buffers) : null;
|
|
470
|
+
const colors = typeof primitive.attributes.COLOR_0 === "number" ? readAccessor(document2, primitive.attributes.COLOR_0, buffers) : null;
|
|
471
|
+
const transformedPositions = [];
|
|
472
|
+
const transformedNormals = [];
|
|
473
|
+
for (let index = 0; index < positions.length; index += 3) {
|
|
474
|
+
const point = transformPosition(
|
|
475
|
+
[positions[index], positions[index + 1], positions[index + 2]],
|
|
476
|
+
worldMatrix
|
|
477
|
+
);
|
|
478
|
+
transformedPositions.push(point[0], point[1], point[2]);
|
|
479
|
+
if (normals) {
|
|
480
|
+
const normal = transformNormal(
|
|
481
|
+
[normals[index], normals[index + 1], normals[index + 2]],
|
|
482
|
+
worldMatrix
|
|
483
|
+
);
|
|
484
|
+
transformedNormals.push(normal[0], normal[1], normal[2]);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const indices = typeof primitive.indices === "number" ? readAccessor(document2, primitive.indices, buffers).map((value) => Number(value)) : Array.from({ length: transformedPositions.length / 3 }, (_, index) => index);
|
|
488
|
+
const material = getMaterialInfo(document2, primitive);
|
|
489
|
+
const primitiveName = `${node.name ?? mesh.name ?? "mesh"}-${primitiveIndex}`;
|
|
490
|
+
results.push(
|
|
491
|
+
Object.freeze({
|
|
492
|
+
name: primitiveName,
|
|
493
|
+
positions: Object.freeze(transformedPositions),
|
|
494
|
+
indices: Object.freeze(indices),
|
|
495
|
+
normals: transformedNormals.length > 0 ? Object.freeze(transformedNormals) : null,
|
|
496
|
+
colors: colors ? Object.freeze(colors) : null,
|
|
497
|
+
material,
|
|
498
|
+
bounds: computeBounds(transformedPositions)
|
|
499
|
+
})
|
|
500
|
+
);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
if (Array.isArray(node.children)) {
|
|
504
|
+
for (const childIndex of node.children) {
|
|
505
|
+
visit(childIndex, worldMatrix);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
for (const rootNodeIndex of scene.nodes) {
|
|
510
|
+
visit(rootNodeIndex, createIdentityMatrix());
|
|
511
|
+
}
|
|
512
|
+
if (results.length === 0) {
|
|
513
|
+
throw new Error("glTF demo asset must contain at least one mesh primitive.");
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
name: modelName ?? "gltf-model",
|
|
517
|
+
physics: physics ?? Object.freeze({}),
|
|
518
|
+
primitives: results
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
async function loadGltfDocument(url) {
|
|
161
522
|
const response = await fetch(url);
|
|
162
523
|
if (!response.ok) {
|
|
163
524
|
throw new Error(`Failed to load glTF asset: ${response.status} ${response.statusText}`);
|
|
164
525
|
}
|
|
165
|
-
|
|
166
|
-
|
|
526
|
+
return {
|
|
527
|
+
document: await response.json(),
|
|
528
|
+
baseUrl: resolveFetchBaseUrl(url, response.url)
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
async function loadInlineShowcaseDocument() {
|
|
532
|
+
const module2 = await Promise.resolve().then(() => (init_showcase_inline_assets(), showcase_inline_assets_exports));
|
|
533
|
+
return loadGltfDocument(new URL(module2.INLINE_SHOWCASE_ASSET_URLS.brigantine));
|
|
534
|
+
}
|
|
535
|
+
async function buildGltfModel(document2, baseUrl2) {
|
|
167
536
|
const buffers = await Promise.all(
|
|
168
537
|
(document2.buffers ?? []).map(async (buffer) => {
|
|
169
538
|
if (typeof buffer.uri !== "string") {
|
|
@@ -179,26 +548,46 @@ async function loadGltfModel(url) {
|
|
|
179
548
|
return nested.arrayBuffer();
|
|
180
549
|
})
|
|
181
550
|
);
|
|
182
|
-
const scene = document2
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const
|
|
551
|
+
const scene = collectScenePrimitives(document2, buffers);
|
|
552
|
+
const aggregatePositions = [];
|
|
553
|
+
const aggregateIndices = [];
|
|
554
|
+
for (const primitive of scene.primitives) {
|
|
555
|
+
const vertexOffset = aggregatePositions.length / 3;
|
|
556
|
+
aggregatePositions.push(...primitive.positions);
|
|
557
|
+
aggregateIndices.push(...primitive.indices.map((index) => index + vertexOffset));
|
|
558
|
+
}
|
|
559
|
+
const color = scene.primitives[0]?.material?.color ?? { r: 0.56, g: 0.33, b: 0.22, a: 1 };
|
|
191
560
|
return Object.freeze({
|
|
192
|
-
name:
|
|
193
|
-
positions,
|
|
194
|
-
indices,
|
|
195
|
-
bounds: computeBounds(
|
|
196
|
-
color:
|
|
197
|
-
physics:
|
|
561
|
+
name: scene.name,
|
|
562
|
+
positions: Object.freeze(aggregatePositions),
|
|
563
|
+
indices: Object.freeze(aggregateIndices),
|
|
564
|
+
bounds: computeBounds(aggregatePositions),
|
|
565
|
+
color: Object.freeze({ ...color }),
|
|
566
|
+
physics: scene.physics,
|
|
567
|
+
primitives: Object.freeze(scene.primitives)
|
|
198
568
|
});
|
|
199
569
|
}
|
|
570
|
+
function shouldRetryWithInlineShowcaseFallback(url, error) {
|
|
571
|
+
if (!shouldUseInlineShowcaseFallback(url)) {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
return error instanceof TypeError || /^Failed to load glTF asset:/u.test(error.message);
|
|
575
|
+
}
|
|
576
|
+
async function loadGltfModel(url) {
|
|
577
|
+
try {
|
|
578
|
+
const { document: document2, baseUrl: baseUrl2 } = await loadGltfDocument(url);
|
|
579
|
+
return buildGltfModel(document2, baseUrl2);
|
|
580
|
+
} catch (error) {
|
|
581
|
+
if (!shouldRetryWithInlineShowcaseFallback(url, error)) {
|
|
582
|
+
throw error;
|
|
583
|
+
}
|
|
584
|
+
const { document: document2, baseUrl: baseUrl2 } = await loadInlineShowcaseDocument();
|
|
585
|
+
return buildGltfModel(document2, baseUrl2);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
200
588
|
var init_gltf_loader = __esm({
|
|
201
589
|
"src/gltf-loader.js"() {
|
|
590
|
+
init_asset_url();
|
|
202
591
|
}
|
|
203
592
|
});
|
|
204
593
|
|
|
@@ -2519,7 +2908,7 @@ function getLightingProfile(name = defaultLightingProfile) {
|
|
|
2519
2908
|
}
|
|
2520
2909
|
return profile;
|
|
2521
2910
|
}
|
|
2522
|
-
var import_meta2, __require, baseUrl, techniqueSpecs, lightingTechniques, lightingTechniqueNames, defaultLightingTechnique, profileSpecs, lightingProfiles, lightingProfileNames, defaultLightingProfile, lightingDistanceBands, lightingWorkerQueueClass, lightingDebugOwner, lightingImportanceLevels, lightingBandPolicySpecs, lightingWorkerSpecPresets, lightingWorkerDagSpecs, lightingWorkerManifests, defaultTechnique, lightingPreludeWgslUrl, lightingJobLabels, lightingJobs;
|
|
2911
|
+
var import_meta2, __require, baseUrl, techniqueSpecs, lightingTechniques, lightingTechniqueNames, defaultLightingTechnique, profileSpecs, lightingProfiles, lightingProfileNames, defaultLightingProfile, lightingProfileModeOrder, defaultAdaptiveLightingProfilePolicy, lightingDistanceBands, lightingWorkerQueueClass, lightingDebugOwner, lightingImportanceLevels, lightingBandPolicySpecs, lightingProfileModeEstimatedCostMs, lightingWorkerSpecPresets, lightingWorkerDagSpecs, lightingWorkerManifests, defaultTechnique, lightingPreludeWgslUrl, lightingJobLabels, lightingJobs;
|
|
2523
2912
|
var init_dist3 = __esm({
|
|
2524
2913
|
"node_modules/@plasius/gpu-lighting/dist/index.js"() {
|
|
2525
2914
|
import_meta2 = {};
|
|
@@ -2613,6 +3002,16 @@ var init_dist3 = __esm({
|
|
|
2613
3002
|
);
|
|
2614
3003
|
lightingProfileNames = Object.freeze(Object.keys(lightingProfiles));
|
|
2615
3004
|
defaultLightingProfile = "realtime";
|
|
3005
|
+
lightingProfileModeOrder = Object.freeze([
|
|
3006
|
+
"realtime",
|
|
3007
|
+
"hybrid",
|
|
3008
|
+
"reference"
|
|
3009
|
+
]);
|
|
3010
|
+
defaultAdaptiveLightingProfilePolicy = Object.freeze({
|
|
3011
|
+
preferredProfile: "reference",
|
|
3012
|
+
minimumFrameRate: 30,
|
|
3013
|
+
sampleWindowSize: 4
|
|
3014
|
+
});
|
|
2616
3015
|
lightingDistanceBands = Object.freeze([
|
|
2617
3016
|
"near",
|
|
2618
3017
|
"mid",
|
|
@@ -2668,6 +3067,11 @@ var init_dist3 = __esm({
|
|
|
2668
3067
|
impressionOnly: true
|
|
2669
3068
|
})
|
|
2670
3069
|
});
|
|
3070
|
+
lightingProfileModeEstimatedCostMs = Object.freeze({
|
|
3071
|
+
realtime: 4.5,
|
|
3072
|
+
hybrid: 7.5,
|
|
3073
|
+
reference: 12.5
|
|
3074
|
+
});
|
|
2671
3075
|
lightingWorkerSpecPresets = {
|
|
2672
3076
|
hybrid: {
|
|
2673
3077
|
suggestedAllocationIds: [
|
|
@@ -6339,10 +6743,19 @@ var init_browser = __esm({
|
|
|
6339
6743
|
}
|
|
6340
6744
|
});
|
|
6341
6745
|
|
|
6746
|
+
// src/feature-flags.js
|
|
6747
|
+
var GPU_SHOWCASE_REALISTIC_MODELS_FEATURE;
|
|
6748
|
+
var init_feature_flags = __esm({
|
|
6749
|
+
"src/feature-flags.js"() {
|
|
6750
|
+
GPU_SHOWCASE_REALISTIC_MODELS_FEATURE = "gpu_showcase_realistic_models_v1";
|
|
6751
|
+
}
|
|
6752
|
+
});
|
|
6753
|
+
|
|
6342
6754
|
// src/showcase-runtime.js
|
|
6343
6755
|
var showcase_runtime_exports = {};
|
|
6344
6756
|
__export(showcase_runtime_exports, {
|
|
6345
6757
|
__testOnlyAdvanceShowcaseClothSimulationState: () => advanceShowcaseClothSimulationState,
|
|
6758
|
+
__testOnlyBuildWaterBands: () => buildWaterBands,
|
|
6346
6759
|
__testOnlyBuildWaterMotionEffects: () => buildWaterMotionEffects,
|
|
6347
6760
|
__testOnlyCollectSceneLightSources: () => collectSceneLightSources,
|
|
6348
6761
|
__testOnlyCreateShowcaseClothSimulationState: () => createShowcaseClothSimulationState,
|
|
@@ -6374,6 +6787,11 @@ function injectStyles() {
|
|
|
6374
6787
|
radial-gradient(circle at 82% 18%, rgba(240, 188, 103, 0.08), transparent 18%),
|
|
6375
6788
|
linear-gradient(180deg, #04101d 0%, #0b1930 42%, #081321 100%);
|
|
6376
6789
|
}
|
|
6790
|
+
.${ROOT_CLASS}.${CAPTURE_CLASS} {
|
|
6791
|
+
min-height: 100vh;
|
|
6792
|
+
overflow: hidden;
|
|
6793
|
+
background: #030710;
|
|
6794
|
+
}
|
|
6377
6795
|
.${ROOT_CLASS},
|
|
6378
6796
|
.${ROOT_CLASS} * {
|
|
6379
6797
|
box-sizing: border-box;
|
|
@@ -6453,6 +6871,40 @@ function injectStyles() {
|
|
|
6453
6871
|
border: 1px solid rgba(159, 185, 223, 0.12);
|
|
6454
6872
|
background: linear-gradient(180deg, #071220 0%, #132440 42%, #10344b 42%, #05111d 100%);
|
|
6455
6873
|
}
|
|
6874
|
+
.${CAPTURE_CLASS} .plasius-demo {
|
|
6875
|
+
width: 100vw;
|
|
6876
|
+
height: 100vh;
|
|
6877
|
+
padding: 0;
|
|
6878
|
+
display: block;
|
|
6879
|
+
}
|
|
6880
|
+
.${CAPTURE_CLASS} .plasius-demo__hero,
|
|
6881
|
+
.${CAPTURE_CLASS} .plasius-demo__toolbar,
|
|
6882
|
+
.${CAPTURE_CLASS} .plasius-demo__legend,
|
|
6883
|
+
.${CAPTURE_CLASS} .plasius-demo__sidebar,
|
|
6884
|
+
.${CAPTURE_CLASS} .plasius-demo__footer {
|
|
6885
|
+
display: none;
|
|
6886
|
+
}
|
|
6887
|
+
.${CAPTURE_CLASS} .plasius-demo__layout {
|
|
6888
|
+
display: block;
|
|
6889
|
+
height: 100%;
|
|
6890
|
+
}
|
|
6891
|
+
.${CAPTURE_CLASS} .plasius-demo__canvas-panel {
|
|
6892
|
+
height: 100%;
|
|
6893
|
+
padding: 0;
|
|
6894
|
+
border: 0;
|
|
6895
|
+
border-radius: 0;
|
|
6896
|
+
background: transparent;
|
|
6897
|
+
box-shadow: none;
|
|
6898
|
+
backdrop-filter: none;
|
|
6899
|
+
}
|
|
6900
|
+
.${CAPTURE_CLASS} .plasius-demo__canvas {
|
|
6901
|
+
width: 100%;
|
|
6902
|
+
height: 100%;
|
|
6903
|
+
aspect-ratio: auto;
|
|
6904
|
+
border: 0;
|
|
6905
|
+
border-radius: 0;
|
|
6906
|
+
background: #030710;
|
|
6907
|
+
}
|
|
6456
6908
|
.plasius-demo__toolbar {
|
|
6457
6909
|
position: absolute;
|
|
6458
6910
|
top: 26px;
|
|
@@ -6544,6 +6996,10 @@ function clamp(value, min, max) {
|
|
|
6544
6996
|
function mix(a, b, t) {
|
|
6545
6997
|
return a + (b - a) * t;
|
|
6546
6998
|
}
|
|
6999
|
+
function smoothstep(min, max, value) {
|
|
7000
|
+
const t = clamp((value - min) / Math.max(1e-4, max - min), 0, 1);
|
|
7001
|
+
return t * t * (3 - 2 * t);
|
|
7002
|
+
}
|
|
6547
7003
|
function pseudoRandom(seed) {
|
|
6548
7004
|
const value = Math.sin(seed * 12.9898 + seed * seed * 17e-4) * 43758.5453;
|
|
6549
7005
|
return value - Math.floor(value);
|
|
@@ -6602,6 +7058,11 @@ function transformPoint(point, transform) {
|
|
|
6602
7058
|
const rotated = rotateY(scaled, transform.rotationY);
|
|
6603
7059
|
return addVec3(rotated, transform.position);
|
|
6604
7060
|
}
|
|
7061
|
+
function transformDirection(direction, transform) {
|
|
7062
|
+
const scale = typeof transform.scale === "number" ? { x: transform.scale, y: transform.scale, z: transform.scale } : transform.scale;
|
|
7063
|
+
const scaled = vec3(direction.x * scale.x, direction.y * scale.y, direction.z * scale.z);
|
|
7064
|
+
return normalizeVec3(rotateY(scaled, transform.rotationY));
|
|
7065
|
+
}
|
|
6605
7066
|
function projectPoint(point, camera, viewport) {
|
|
6606
7067
|
const relative = subVec3(point, camera.eye);
|
|
6607
7068
|
const viewX = dotVec3(relative, camera.right);
|
|
@@ -6625,6 +7086,66 @@ function colorToRgba(color, alpha = 1) {
|
|
|
6625
7086
|
const b = Math.round(clamp(color.b, 0, 1) * 255);
|
|
6626
7087
|
return `rgba(${r}, ${g}, ${b}, ${clamp(alpha, 0, 1)})`;
|
|
6627
7088
|
}
|
|
7089
|
+
function mixColor(a, b, t) {
|
|
7090
|
+
return {
|
|
7091
|
+
r: mix(a.r, b.r, t),
|
|
7092
|
+
g: mix(a.g, b.g, t),
|
|
7093
|
+
b: mix(a.b, b.b, t),
|
|
7094
|
+
a: mix(a.a ?? 1, b.a ?? 1, t)
|
|
7095
|
+
};
|
|
7096
|
+
}
|
|
7097
|
+
function multiplyColor(a, b) {
|
|
7098
|
+
return {
|
|
7099
|
+
r: a.r * b.r,
|
|
7100
|
+
g: a.g * b.g,
|
|
7101
|
+
b: a.b * b.b,
|
|
7102
|
+
a: (a.a ?? 1) * (b.a ?? 1)
|
|
7103
|
+
};
|
|
7104
|
+
}
|
|
7105
|
+
function createLegacyMeshPrimitive(mesh) {
|
|
7106
|
+
return Object.freeze({
|
|
7107
|
+
name: mesh.name ?? "legacy-mesh",
|
|
7108
|
+
positions: mesh.positions,
|
|
7109
|
+
indices: mesh.indices,
|
|
7110
|
+
normals: null,
|
|
7111
|
+
colors: null,
|
|
7112
|
+
material: Object.freeze({
|
|
7113
|
+
name: "legacy-material",
|
|
7114
|
+
color: mesh.color ?? { r: 0.56, g: 0.33, b: 0.22, a: 1 },
|
|
7115
|
+
roughness: 0.88,
|
|
7116
|
+
metallic: 0.08,
|
|
7117
|
+
emissive: Object.freeze({ r: 0, g: 0, b: 0 })
|
|
7118
|
+
})
|
|
7119
|
+
});
|
|
7120
|
+
}
|
|
7121
|
+
function isFeatureEnabled(featureFlags, featureName, fallback = true) {
|
|
7122
|
+
const directValue = typeof featureFlags?.[featureName] === "boolean" ? featureFlags[featureName] : featureFlags?.flags?.[featureName];
|
|
7123
|
+
if (typeof directValue === "boolean") {
|
|
7124
|
+
return directValue;
|
|
7125
|
+
}
|
|
7126
|
+
const enabledValue = typeof featureFlags?.enabled?.[featureName] === "boolean" ? featureFlags.enabled[featureName] : void 0;
|
|
7127
|
+
if (typeof enabledValue === "boolean") {
|
|
7128
|
+
return enabledValue;
|
|
7129
|
+
}
|
|
7130
|
+
return fallback;
|
|
7131
|
+
}
|
|
7132
|
+
function getMeshPrimitives(mesh) {
|
|
7133
|
+
return Array.isArray(mesh?.primitives) && mesh.primitives.length > 0 ? mesh.primitives : [createLegacyMeshPrimitive(mesh)];
|
|
7134
|
+
}
|
|
7135
|
+
function tintPrimitiveColor(material, colorOverride) {
|
|
7136
|
+
if (!colorOverride) {
|
|
7137
|
+
return material.color;
|
|
7138
|
+
}
|
|
7139
|
+
const name = String(material.name ?? "").toLowerCase();
|
|
7140
|
+
if (name.includes("sail") || name.includes("glass") || name.includes("roof")) {
|
|
7141
|
+
return material.color;
|
|
7142
|
+
}
|
|
7143
|
+
const tintAmount = name.includes("hull") ? 0.54 : name.includes("trim") ? 0.22 : name.includes("deck") ? 0.12 : 0;
|
|
7144
|
+
if (tintAmount <= 0) {
|
|
7145
|
+
return material.color;
|
|
7146
|
+
}
|
|
7147
|
+
return mixColor(material.color, multiplyColor(material.color, colorOverride), tintAmount);
|
|
7148
|
+
}
|
|
6628
7149
|
function projectShadowPoint(point, lightDir, planeY) {
|
|
6629
7150
|
const shadowDir = scaleVec3(lightDir, -1);
|
|
6630
7151
|
if (Math.abs(shadowDir.y) < 1e-4) {
|
|
@@ -6645,6 +7166,50 @@ function shadeColor(base, normal, lightDir, heightBias = 0, accent = 0) {
|
|
|
6645
7166
|
b: clamp(base.b * (brightness + 0.03), 0, 1)
|
|
6646
7167
|
};
|
|
6647
7168
|
}
|
|
7169
|
+
function getMaterialSeed(materialName) {
|
|
7170
|
+
let seed = 0;
|
|
7171
|
+
for (let index = 0; index < materialName.length; index += 1) {
|
|
7172
|
+
seed += materialName.charCodeAt(index) * (index + 1);
|
|
7173
|
+
}
|
|
7174
|
+
return seed;
|
|
7175
|
+
}
|
|
7176
|
+
function getMaterialDetailStrength(material, surfaceType) {
|
|
7177
|
+
const name = String(material?.name ?? "").toLowerCase();
|
|
7178
|
+
if (surfaceType === "water" || name.includes("glass")) {
|
|
7179
|
+
return 0.018;
|
|
7180
|
+
}
|
|
7181
|
+
if (name.includes("wood") || name.includes("timber") || name.includes("plank")) {
|
|
7182
|
+
return 0.13;
|
|
7183
|
+
}
|
|
7184
|
+
if (name.includes("stone") || name.includes("concrete") || name.includes("plaster")) {
|
|
7185
|
+
return 0.1;
|
|
7186
|
+
}
|
|
7187
|
+
if (name.includes("roof") || name.includes("crate")) {
|
|
7188
|
+
return 0.09;
|
|
7189
|
+
}
|
|
7190
|
+
if (name.includes("paint")) {
|
|
7191
|
+
return 0.045;
|
|
7192
|
+
}
|
|
7193
|
+
if (name.includes("metal")) {
|
|
7194
|
+
return 0.035;
|
|
7195
|
+
}
|
|
7196
|
+
return 0.04;
|
|
7197
|
+
}
|
|
7198
|
+
function applyMaterialDetail(color, material, worldCenter, normal, surfaceType) {
|
|
7199
|
+
const materialName = String(material?.name ?? surfaceType ?? "material");
|
|
7200
|
+
const detailStrength = getMaterialDetailStrength(material, surfaceType);
|
|
7201
|
+
const sample = worldCenter.x * 3.17 + worldCenter.y * 5.29 + worldCenter.z * 7.83 + getMaterialSeed(materialName) * 0.013;
|
|
7202
|
+
const grain = (pseudoRandom(sample) - 0.5) * detailStrength;
|
|
7203
|
+
const lowerSurface = smoothstep(7.5, -0.8, worldCenter.y);
|
|
7204
|
+
const verticalSurface = 1 - clamp(Math.abs(normal.y), 0, 1);
|
|
7205
|
+
const materialLowerWear = /stone|concrete|plaster|paint|wood|timber|plank|crate/.test(materialName.toLowerCase()) ? lowerSurface * verticalSurface * 0.055 : 0;
|
|
7206
|
+
const wetlineWear = surfaceType === "ship" && worldCenter.y < 0.72 ? smoothstep(0.72, -0.1, worldCenter.y) * 0.05 : 0;
|
|
7207
|
+
return {
|
|
7208
|
+
r: clamp(color.r * (1 + grain) - materialLowerWear - wetlineWear, 0, 1),
|
|
7209
|
+
g: clamp(color.g * (1 + grain * 0.82) - materialLowerWear * 0.9 - wetlineWear, 0, 1),
|
|
7210
|
+
b: clamp(color.b * (1 + grain * 0.62) - materialLowerWear * 0.68 - wetlineWear * 0.75, 0, 1)
|
|
7211
|
+
};
|
|
7212
|
+
}
|
|
6648
7213
|
function buildCamera(state, canvas) {
|
|
6649
7214
|
const preset = CAMERA_PRESETS[state.focus] ?? CAMERA_PRESETS.integrated;
|
|
6650
7215
|
const yaw = state.camera.yaw ?? preset.yaw;
|
|
@@ -6669,44 +7234,131 @@ function buildCamera(state, canvas) {
|
|
|
6669
7234
|
aspect: canvas.width / canvas.height
|
|
6670
7235
|
};
|
|
6671
7236
|
}
|
|
6672
|
-
function buildTrianglesFromMesh(mesh, transform,
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
const
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
7237
|
+
function buildTrianglesFromMesh(mesh, transform, colorOverride, camera, viewport, triangles, options = {}) {
|
|
7238
|
+
const primitives = getMeshPrimitives(mesh);
|
|
7239
|
+
for (const primitive of primitives) {
|
|
7240
|
+
const resolvedColor = tintPrimitiveColor(primitive.material, colorOverride);
|
|
7241
|
+
for (let index = 0; index < primitive.indices.length; index += 3) {
|
|
7242
|
+
const aIndex = primitive.indices[index] * 3;
|
|
7243
|
+
const bIndex = primitive.indices[index + 1] * 3;
|
|
7244
|
+
const cIndex = primitive.indices[index + 2] * 3;
|
|
7245
|
+
const a = transformPoint(
|
|
7246
|
+
vec3(
|
|
7247
|
+
primitive.positions[aIndex],
|
|
7248
|
+
primitive.positions[aIndex + 1],
|
|
7249
|
+
primitive.positions[aIndex + 2]
|
|
7250
|
+
),
|
|
7251
|
+
transform
|
|
7252
|
+
);
|
|
7253
|
+
const b = transformPoint(
|
|
7254
|
+
vec3(
|
|
7255
|
+
primitive.positions[bIndex],
|
|
7256
|
+
primitive.positions[bIndex + 1],
|
|
7257
|
+
primitive.positions[bIndex + 2]
|
|
7258
|
+
),
|
|
7259
|
+
transform
|
|
7260
|
+
);
|
|
7261
|
+
const c = transformPoint(
|
|
7262
|
+
vec3(
|
|
7263
|
+
primitive.positions[cIndex],
|
|
7264
|
+
primitive.positions[cIndex + 1],
|
|
7265
|
+
primitive.positions[cIndex + 2]
|
|
7266
|
+
),
|
|
7267
|
+
transform
|
|
7268
|
+
);
|
|
7269
|
+
const ab = subVec3(b, a);
|
|
7270
|
+
const ac = subVec3(c, a);
|
|
7271
|
+
const faceNormal = normalizeVec3(crossVec3(ab, ac));
|
|
7272
|
+
let normal = faceNormal;
|
|
7273
|
+
if (Array.isArray(primitive.normals)) {
|
|
7274
|
+
const aNormal = transformDirection(
|
|
7275
|
+
vec3(
|
|
7276
|
+
primitive.normals[aIndex],
|
|
7277
|
+
primitive.normals[aIndex + 1],
|
|
7278
|
+
primitive.normals[aIndex + 2]
|
|
7279
|
+
),
|
|
7280
|
+
transform
|
|
7281
|
+
);
|
|
7282
|
+
const bNormal = transformDirection(
|
|
7283
|
+
vec3(
|
|
7284
|
+
primitive.normals[bIndex],
|
|
7285
|
+
primitive.normals[bIndex + 1],
|
|
7286
|
+
primitive.normals[bIndex + 2]
|
|
7287
|
+
),
|
|
7288
|
+
transform
|
|
7289
|
+
);
|
|
7290
|
+
const cNormal = transformDirection(
|
|
7291
|
+
vec3(
|
|
7292
|
+
primitive.normals[cIndex],
|
|
7293
|
+
primitive.normals[cIndex + 1],
|
|
7294
|
+
primitive.normals[cIndex + 2]
|
|
7295
|
+
),
|
|
7296
|
+
transform
|
|
7297
|
+
);
|
|
7298
|
+
normal = normalizeVec3(
|
|
7299
|
+
scaleVec3(addVec3(addVec3(aNormal, bNormal), cNormal), 1 / 3)
|
|
7300
|
+
);
|
|
7301
|
+
}
|
|
7302
|
+
const viewDir = normalizeVec3(subVec3(camera.eye, a));
|
|
7303
|
+
if (dotVec3(faceNormal, viewDir) <= 0) {
|
|
7304
|
+
continue;
|
|
7305
|
+
}
|
|
7306
|
+
const projected = [
|
|
7307
|
+
projectPoint(a, camera, viewport),
|
|
7308
|
+
projectPoint(b, camera, viewport),
|
|
7309
|
+
projectPoint(c, camera, viewport)
|
|
7310
|
+
];
|
|
7311
|
+
if (projected.some((value) => value === null)) {
|
|
7312
|
+
continue;
|
|
7313
|
+
}
|
|
7314
|
+
triangles.push({
|
|
7315
|
+
points: projected,
|
|
7316
|
+
depth: (projected[0].depth + projected[1].depth + projected[2].depth) / 3,
|
|
7317
|
+
worldCenter: scaleVec3(addVec3(addVec3(a, b), c), 1 / 3),
|
|
7318
|
+
normal,
|
|
7319
|
+
baseColor: resolvedColor,
|
|
7320
|
+
accent: options.accent ?? 0,
|
|
7321
|
+
material: primitive.material,
|
|
7322
|
+
reflection: options.reflection ?? 0,
|
|
7323
|
+
surfaceType: options.surfaceType ?? "solid"
|
|
7324
|
+
});
|
|
6699
7325
|
}
|
|
6700
|
-
triangles.push({
|
|
6701
|
-
points: projected,
|
|
6702
|
-
depth: (projected[0].depth + projected[1].depth + projected[2].depth) / 3,
|
|
6703
|
-
worldCenter: scaleVec3(addVec3(addVec3(a, b), c), 1 / 3),
|
|
6704
|
-
normal,
|
|
6705
|
-
baseColor,
|
|
6706
|
-
accent
|
|
6707
|
-
});
|
|
6708
7326
|
}
|
|
6709
7327
|
}
|
|
7328
|
+
async function loadShowcaseAssetCatalog() {
|
|
7329
|
+
const [brigantine, cutter, lighthouse, harborDock] = await Promise.all([
|
|
7330
|
+
loadGltfModel(resolveShowcaseAssetUrl("brigantine")),
|
|
7331
|
+
loadGltfModel(resolveShowcaseAssetUrl("cutter")),
|
|
7332
|
+
loadGltfModel(resolveShowcaseAssetUrl("lighthouse")),
|
|
7333
|
+
loadGltfModel(resolveShowcaseAssetUrl("harbor-dock"))
|
|
7334
|
+
]);
|
|
7335
|
+
return Object.freeze({
|
|
7336
|
+
primaryShipKey: "brigantine",
|
|
7337
|
+
ships: Object.freeze({
|
|
7338
|
+
brigantine,
|
|
7339
|
+
cutter
|
|
7340
|
+
}),
|
|
7341
|
+
environment: Object.freeze({
|
|
7342
|
+
lighthouse,
|
|
7343
|
+
"harbor-dock": harborDock
|
|
7344
|
+
})
|
|
7345
|
+
});
|
|
7346
|
+
}
|
|
7347
|
+
function createLegacyShowcaseAssetCatalog() {
|
|
7348
|
+
const brigantine = loadGltfModel(resolveShowcaseAssetUrl("brigantine"));
|
|
7349
|
+
return Promise.resolve(brigantine).then(
|
|
7350
|
+
(primary) => Object.freeze({
|
|
7351
|
+
primaryShipKey: "brigantine",
|
|
7352
|
+
ships: Object.freeze({
|
|
7353
|
+
brigantine: primary
|
|
7354
|
+
}),
|
|
7355
|
+
environment: Object.freeze({})
|
|
7356
|
+
})
|
|
7357
|
+
);
|
|
7358
|
+
}
|
|
7359
|
+
function resolveShipModel(state, ship, fallbackModel = null) {
|
|
7360
|
+
return state.assetCatalog?.ships?.[ship.modelKey ?? state.assetCatalog?.primaryShipKey ?? "brigantine"] ?? fallbackModel ?? state.shipModel;
|
|
7361
|
+
}
|
|
6710
7362
|
function createPerformanceGovernor() {
|
|
6711
7363
|
const fluidDetail = createQualityLadderAdapter({
|
|
6712
7364
|
id: "fluid-detail",
|
|
@@ -6758,6 +7410,7 @@ function createPerformanceGovernor() {
|
|
|
6758
7410
|
return { governor, fluidDetail, clothDetail, lightingDetail };
|
|
6759
7411
|
}
|
|
6760
7412
|
function buildDemoDom(root, options) {
|
|
7413
|
+
const t = options.translate;
|
|
6761
7414
|
root.innerHTML = `
|
|
6762
7415
|
<main class="plasius-demo">
|
|
6763
7416
|
<section class="plasius-demo__hero">
|
|
@@ -6767,56 +7420,52 @@ function buildDemoDom(root, options) {
|
|
|
6767
7420
|
<p class="plasius-demo__lead">${options.subtitle}</p>
|
|
6768
7421
|
</section>
|
|
6769
7422
|
<section class="plasius-panel plasius-demo__status">
|
|
6770
|
-
<p id="demoStatus" class="plasius-demo__status-badge"
|
|
7423
|
+
<p id="demoStatus" class="plasius-demo__status-badge">${t(gpuSharedTranslationKeys.statusBooting)}</p>
|
|
6771
7424
|
<p id="demoDetails" class="plasius-demo__status-text">
|
|
6772
|
-
|
|
7425
|
+
${t(gpuSharedTranslationKeys.detailsBooting)}
|
|
6773
7426
|
</p>
|
|
6774
7427
|
</section>
|
|
6775
7428
|
</section>
|
|
6776
7429
|
<section class="plasius-demo__layout">
|
|
6777
7430
|
<section class="plasius-panel plasius-demo__canvas-panel">
|
|
6778
|
-
<canvas id="demoCanvas" class="plasius-demo__canvas" width="
|
|
7431
|
+
<canvas id="demoCanvas" class="plasius-demo__canvas" width="${DEFAULT_CANVAS_WIDTH}" height="${DEFAULT_CANVAS_HEIGHT}"></canvas>
|
|
6779
7432
|
<div class="plasius-demo__toolbar">
|
|
6780
|
-
<button id="pauseButton" type="button"
|
|
7433
|
+
<button id="pauseButton" type="button">${t(gpuSharedTranslationKeys.pause)}</button>
|
|
6781
7434
|
<label class="plasius-toggle">
|
|
6782
7435
|
<input id="stressToggle" type="checkbox" />
|
|
6783
|
-
|
|
7436
|
+
${t(gpuSharedTranslationKeys.stressMode)}
|
|
6784
7437
|
</label>
|
|
6785
7438
|
<label class="plasius-toggle">
|
|
6786
|
-
|
|
7439
|
+
${t(gpuSharedTranslationKeys.focus)}
|
|
6787
7440
|
<select id="focusMode">
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
<option value="fluid">fluid</option>
|
|
6792
|
-
<option value="physics">physics</option>
|
|
6793
|
-
<option value="performance">performance</option>
|
|
6794
|
-
<option value="debug">debug</option>
|
|
7441
|
+
${showcaseFocusModes.map(
|
|
7442
|
+
(mode) => `<option value="${mode}">${t(FOCUS_MODE_TRANSLATION_KEYS[mode])}</option>`
|
|
7443
|
+
).join("")}
|
|
6795
7444
|
</select>
|
|
6796
7445
|
</label>
|
|
6797
7446
|
</div>
|
|
6798
7447
|
<div class="plasius-demo__legend">
|
|
6799
|
-
<strong
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
7448
|
+
<strong>${t(gpuSharedTranslationKeys.legendTitle)}</strong>
|
|
7449
|
+
${t(gpuSharedTranslationKeys.legendShipMetadata)}<br />
|
|
7450
|
+
${t(gpuSharedTranslationKeys.legendLighting)}<br />
|
|
7451
|
+
${t(gpuSharedTranslationKeys.legendCollisions)}
|
|
6803
7452
|
</div>
|
|
6804
7453
|
</section>
|
|
6805
7454
|
<aside class="plasius-demo__sidebar">
|
|
6806
7455
|
<section class="plasius-panel plasius-demo__card">
|
|
6807
|
-
<h2
|
|
7456
|
+
<h2>${t(gpuSharedTranslationKeys.sceneState)}</h2>
|
|
6808
7457
|
<ul id="sceneMetrics" class="plasius-demo__metrics"></ul>
|
|
6809
7458
|
</section>
|
|
6810
7459
|
<section class="plasius-panel plasius-demo__card">
|
|
6811
|
-
<h2
|
|
7460
|
+
<h2>${t(gpuSharedTranslationKeys.qualityBudgets)}</h2>
|
|
6812
7461
|
<ul id="qualityMetrics" class="plasius-demo__metrics"></ul>
|
|
6813
7462
|
</section>
|
|
6814
7463
|
<section class="plasius-panel plasius-demo__card">
|
|
6815
|
-
<h2
|
|
7464
|
+
<h2>${t(gpuSharedTranslationKeys.debugTelemetry)}</h2>
|
|
6816
7465
|
<ul id="debugMetrics" class="plasius-demo__metrics"></ul>
|
|
6817
7466
|
</section>
|
|
6818
7467
|
<section class="plasius-panel plasius-demo__card">
|
|
6819
|
-
<h2
|
|
7468
|
+
<h2>${t(gpuSharedTranslationKeys.notes)}</h2>
|
|
6820
7469
|
<ul id="sceneNotes" class="plasius-demo__metrics"></ul>
|
|
6821
7470
|
</section>
|
|
6822
7471
|
</aside>
|
|
@@ -6840,6 +7489,11 @@ function buildDemoDom(root, options) {
|
|
|
6840
7489
|
};
|
|
6841
7490
|
}
|
|
6842
7491
|
function buildSceneSnapshot(state, shipModel) {
|
|
7492
|
+
const shipPhysics = Object.freeze(
|
|
7493
|
+
Object.fromEntries(
|
|
7494
|
+
state.ships.map((ship) => [ship.id, resolveShipModel(state, ship, shipModel)?.physics ?? null])
|
|
7495
|
+
)
|
|
7496
|
+
);
|
|
6843
7497
|
return Object.freeze({
|
|
6844
7498
|
focus: state.focus,
|
|
6845
7499
|
frame: state.frame,
|
|
@@ -6861,6 +7515,7 @@ function buildSceneSnapshot(state, shipModel) {
|
|
|
6861
7515
|
state.ships.map(
|
|
6862
7516
|
(ship) => Object.freeze({
|
|
6863
7517
|
id: ship.id,
|
|
7518
|
+
modelKey: ship.modelKey ?? "brigantine",
|
|
6864
7519
|
position: Object.freeze({ ...ship.position }),
|
|
6865
7520
|
velocity: Object.freeze({ ...ship.velocity }),
|
|
6866
7521
|
rotationY: ship.rotationY,
|
|
@@ -6881,12 +7536,13 @@ function buildSceneSnapshot(state, shipModel) {
|
|
|
6881
7536
|
)
|
|
6882
7537
|
),
|
|
6883
7538
|
shipPhysics: shipModel?.physics ?? null,
|
|
7539
|
+
shipModels: shipPhysics,
|
|
6884
7540
|
physics: Object.freeze({
|
|
6885
7541
|
profile: state.physics.profile,
|
|
6886
7542
|
plan: state.physics.plan,
|
|
6887
7543
|
manifest: state.physics.manifest,
|
|
6888
7544
|
snapshot: state.physics.snapshot,
|
|
6889
|
-
shipPhysics
|
|
7545
|
+
shipPhysics
|
|
6890
7546
|
})
|
|
6891
7547
|
});
|
|
6892
7548
|
}
|
|
@@ -6921,6 +7577,61 @@ function normalizeColorOverride(color, fallback) {
|
|
|
6921
7577
|
function readVisualNumber(value, fallback) {
|
|
6922
7578
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
6923
7579
|
}
|
|
7580
|
+
function readPositiveNumber3(value, fallback) {
|
|
7581
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
7582
|
+
}
|
|
7583
|
+
function isTruthyCaptureValue(value) {
|
|
7584
|
+
return value === "1" || value === "true" || value === "scene" || value === "video";
|
|
7585
|
+
}
|
|
7586
|
+
function resolveCaptureSettings(options) {
|
|
7587
|
+
const explicitCaptureMode = typeof options.captureMode === "boolean" ? options.captureMode : void 0;
|
|
7588
|
+
let captureMode = explicitCaptureMode ?? false;
|
|
7589
|
+
let renderScale = readPositiveNumber3(options.renderScale, void 0);
|
|
7590
|
+
try {
|
|
7591
|
+
const params = new URLSearchParams(window.location.search);
|
|
7592
|
+
if (explicitCaptureMode === void 0) {
|
|
7593
|
+
captureMode = isTruthyCaptureValue(params.get("capture")) || params.get("presentation") === "capture";
|
|
7594
|
+
}
|
|
7595
|
+
renderScale = readPositiveNumber3(Number(params.get("renderScale")), renderScale);
|
|
7596
|
+
} catch {
|
|
7597
|
+
}
|
|
7598
|
+
return {
|
|
7599
|
+
captureMode,
|
|
7600
|
+
renderScale
|
|
7601
|
+
};
|
|
7602
|
+
}
|
|
7603
|
+
function getCanvasDisplaySize(canvas) {
|
|
7604
|
+
const rect = typeof canvas.getBoundingClientRect === "function" ? canvas.getBoundingClientRect() : null;
|
|
7605
|
+
const width = Math.round(
|
|
7606
|
+
readPositiveNumber3(rect?.width, readPositiveNumber3(canvas.clientWidth, canvas.width))
|
|
7607
|
+
);
|
|
7608
|
+
const height = Math.round(
|
|
7609
|
+
readPositiveNumber3(rect?.height, readPositiveNumber3(canvas.clientHeight, canvas.height))
|
|
7610
|
+
);
|
|
7611
|
+
return {
|
|
7612
|
+
width: Math.max(1, width || DEFAULT_CANVAS_WIDTH),
|
|
7613
|
+
height: Math.max(1, height || DEFAULT_CANVAS_HEIGHT)
|
|
7614
|
+
};
|
|
7615
|
+
}
|
|
7616
|
+
function resizeCanvasToDisplaySize(canvas, state) {
|
|
7617
|
+
const { width, height } = getCanvasDisplaySize(canvas);
|
|
7618
|
+
const deviceScale = readPositiveNumber3(globalThis.devicePixelRatio, 1);
|
|
7619
|
+
const requestedScale = readPositiveNumber3(state.renderScale, deviceScale);
|
|
7620
|
+
const maxScale = state.captureMode ? 2 : 1.5;
|
|
7621
|
+
let scale = clamp(requestedScale, 1, maxScale);
|
|
7622
|
+
const pixelBudget = state.captureMode ? CAPTURE_CANVAS_PIXEL_BUDGET : DEFAULT_CANVAS_WIDTH * DEFAULT_CANVAS_HEIGHT * 1.5;
|
|
7623
|
+
const projectedPixels = width * height * scale * scale;
|
|
7624
|
+
if (projectedPixels > pixelBudget) {
|
|
7625
|
+
scale = Math.sqrt(pixelBudget / Math.max(1, width * height));
|
|
7626
|
+
}
|
|
7627
|
+
const targetWidth = Math.max(1, Math.round(width * scale));
|
|
7628
|
+
const targetHeight = Math.max(1, Math.round(height * scale));
|
|
7629
|
+
if (canvas.width !== targetWidth || canvas.height !== targetHeight) {
|
|
7630
|
+
canvas.width = targetWidth;
|
|
7631
|
+
canvas.height = targetHeight;
|
|
7632
|
+
}
|
|
7633
|
+
state.renderScale = scale;
|
|
7634
|
+
}
|
|
6924
7635
|
function resolveClothPresentation(state, meshDetail) {
|
|
6925
7636
|
const clothPlan = createClothRepresentationPlan({
|
|
6926
7637
|
garmentId: "shore-flag",
|
|
@@ -7322,6 +8033,12 @@ function sampleWave(state, x, z, time) {
|
|
|
7322
8033
|
const base = Math.sin(along * 0.22 - time * 1.12 * phaseSpeed) * 0.42 + Math.cos(along * 0.11 + cross * 0.07 - time * 0.78 * phaseSpeed) * 0.26 + Math.sin(cross * 0.19 - time * 1.34 * phaseSpeed) * 0.16;
|
|
7323
8034
|
return base * amplitude + sampleShipWake(state, x, z, time) + sampleWaveImpulses(state, x, z, time);
|
|
7324
8035
|
}
|
|
8036
|
+
function resolveFluidBandContinuity(continuity, band) {
|
|
8037
|
+
if (continuity?.bands && continuity.bands[band]) {
|
|
8038
|
+
return continuity.bands[band];
|
|
8039
|
+
}
|
|
8040
|
+
return continuity ?? { amplitudeFloor: 1, frequencyFloor: 1 };
|
|
8041
|
+
}
|
|
7325
8042
|
function buildWaterMotionEffects(state) {
|
|
7326
8043
|
const wakeTrails = [];
|
|
7327
8044
|
const rippleRings = state.waveImpulses.map((impulse) => {
|
|
@@ -7395,6 +8112,7 @@ function buildWaterBands(state, fluidDetail, visuals) {
|
|
|
7395
8112
|
for (const bandSpec of bandExtents) {
|
|
7396
8113
|
const representation = fluidPlan.representations.find((entry) => entry.band === bandSpec.band) ?? fluidPlan.representations[0];
|
|
7397
8114
|
const continuity = createFluidContinuityEnvelope({ fluidBodyId: "harbor" });
|
|
8115
|
+
const bandContinuity = resolveFluidBandContinuity(continuity, bandSpec.band);
|
|
7398
8116
|
const bandResolution = bandSpec.band === "near" ? fluidDetail.nearResolution : bandSpec.band === "mid" ? fluidDetail.midResolution : bandSpec.band === "far" ? 5 : 3;
|
|
7399
8117
|
const cols = Math.max(4, bandResolution * 2);
|
|
7400
8118
|
const rows = Math.max(4, bandResolution + 2);
|
|
@@ -7408,7 +8126,7 @@ function buildWaterBands(state, fluidDetail, visuals) {
|
|
|
7408
8126
|
const v = row / (rows - 1);
|
|
7409
8127
|
const x = originX + bandSpec.width * u;
|
|
7410
8128
|
const z = originZ + bandSpec.depth * v;
|
|
7411
|
-
const y = bandSpec.y + sampleWave(state, x, z, state.time) *
|
|
8129
|
+
const y = bandSpec.y + sampleWave(state, x, z, state.time) * bandContinuity.amplitudeFloor * (bandSpec.band === "near" ? 0.9 : bandSpec.band === "mid" ? 0.55 : 0.3);
|
|
7412
8130
|
positions.push(vec3(x, y, z));
|
|
7413
8131
|
}
|
|
7414
8132
|
}
|
|
@@ -7424,7 +8142,7 @@ function buildWaterBands(state, fluidDetail, visuals) {
|
|
|
7424
8142
|
bandMeshes.push({
|
|
7425
8143
|
band: bandSpec.band,
|
|
7426
8144
|
representation,
|
|
7427
|
-
continuity,
|
|
8145
|
+
continuity: bandContinuity,
|
|
7428
8146
|
rows,
|
|
7429
8147
|
cols,
|
|
7430
8148
|
positions,
|
|
@@ -7443,6 +8161,7 @@ function buildWaterBands(state, fluidDetail, visuals) {
|
|
|
7443
8161
|
return { fluidPlan, bandMeshes };
|
|
7444
8162
|
}
|
|
7445
8163
|
function createSceneState(options) {
|
|
8164
|
+
const translate = options.translate;
|
|
7446
8165
|
const { governor, fluidDetail, clothDetail, lightingDetail } = createPerformanceGovernor();
|
|
7447
8166
|
const physicsProfile = defaultPhysicsWorkerProfile;
|
|
7448
8167
|
const physicsPlan = createPhysicsSimulationPlan(physicsProfile);
|
|
@@ -7450,7 +8169,7 @@ function createSceneState(options) {
|
|
|
7450
8169
|
const debugSession = createGpuDebugSession({
|
|
7451
8170
|
enabled: true,
|
|
7452
8171
|
adapter: {
|
|
7453
|
-
label:
|
|
8172
|
+
label: translate(gpuSharedTranslationKeys.debugAdapterShowcase),
|
|
7454
8173
|
memoryCapacityHintBytes: 6 * 1024 * 1024 * 1024,
|
|
7455
8174
|
coreCountHint: 12
|
|
7456
8175
|
}
|
|
@@ -7460,22 +8179,26 @@ function createSceneState(options) {
|
|
|
7460
8179
|
owner: "renderer",
|
|
7461
8180
|
category: "texture",
|
|
7462
8181
|
sizeBytes: 1280 * 720 * 4,
|
|
7463
|
-
label:
|
|
8182
|
+
label: translate(gpuSharedTranslationKeys.debugMainColorBuffer)
|
|
7464
8183
|
});
|
|
7465
8184
|
debugSession.trackAllocation({
|
|
7466
8185
|
id: "showcase.shadow-impression",
|
|
7467
8186
|
owner: "lighting",
|
|
7468
8187
|
category: "texture",
|
|
7469
8188
|
sizeBytes: 12 * 1024 * 1024,
|
|
7470
|
-
label:
|
|
8189
|
+
label: translate(gpuSharedTranslationKeys.debugShadowImpressionAtlas)
|
|
7471
8190
|
});
|
|
7472
8191
|
return {
|
|
8192
|
+
translate,
|
|
7473
8193
|
focus: options.focus,
|
|
7474
8194
|
governor,
|
|
7475
8195
|
fluidDetail,
|
|
7476
8196
|
clothDetail,
|
|
7477
8197
|
lightingDetail,
|
|
7478
8198
|
debugSession,
|
|
8199
|
+
showcaseRealisticModelsEnabled: options.realisticModelsEnabled !== false,
|
|
8200
|
+
captureMode: options.captureMode === true,
|
|
8201
|
+
renderScale: readPositiveNumber3(options.renderScale, void 0),
|
|
7479
8202
|
packageState: void 0,
|
|
7480
8203
|
demoDescription: null,
|
|
7481
8204
|
demoVisuals: null,
|
|
@@ -7490,6 +8213,7 @@ function createSceneState(options) {
|
|
|
7490
8213
|
ships: [
|
|
7491
8214
|
{
|
|
7492
8215
|
id: "northwind",
|
|
8216
|
+
modelKey: "brigantine",
|
|
7493
8217
|
position: vec3(-5.2, 0, 7.2),
|
|
7494
8218
|
velocity: vec3(2.35, 0, -1.08),
|
|
7495
8219
|
rotationY: 0.58,
|
|
@@ -7500,17 +8224,18 @@ function createSceneState(options) {
|
|
|
7500
8224
|
throttleResponse: 0.46,
|
|
7501
8225
|
rudderResponse: 0.54,
|
|
7502
8226
|
wanderPhase: 0.35,
|
|
7503
|
-
lanterns:
|
|
8227
|
+
lanterns: CUTTER_LANTERNS,
|
|
7504
8228
|
lanternStrength: 1.06,
|
|
7505
8229
|
collisionRadiusScale: 1.04
|
|
7506
8230
|
},
|
|
7507
8231
|
{
|
|
7508
8232
|
id: "tidecaller",
|
|
8233
|
+
modelKey: "cutter",
|
|
7509
8234
|
position: vec3(4.8, 0, 4.4),
|
|
7510
8235
|
velocity: vec3(-2.15, 0, 1.74),
|
|
7511
8236
|
rotationY: -2.48,
|
|
7512
8237
|
angularVelocity: -0.2,
|
|
7513
|
-
tint: { r: 0.
|
|
8238
|
+
tint: { r: 0.58, g: 0.24, b: 0.16 },
|
|
7514
8239
|
massScale: 0.84,
|
|
7515
8240
|
cruiseSpeed: 2.68,
|
|
7516
8241
|
throttleResponse: 0.7,
|
|
@@ -7534,6 +8259,7 @@ function createSceneState(options) {
|
|
|
7534
8259
|
manifest: physicsManifest,
|
|
7535
8260
|
snapshot: null
|
|
7536
8261
|
},
|
|
8262
|
+
assetCatalog: null,
|
|
7537
8263
|
shipModel: null
|
|
7538
8264
|
};
|
|
7539
8265
|
}
|
|
@@ -7609,10 +8335,38 @@ function drawSkyAndShore(ctx, canvas, state, nearLighting, reflectionStrength, s
|
|
|
7609
8335
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
7610
8336
|
}
|
|
7611
8337
|
}
|
|
7612
|
-
function
|
|
8338
|
+
function resolveLocalLightContribution(triangle, lightSources) {
|
|
8339
|
+
const contribution = { r: 0, g: 0, b: 0 };
|
|
8340
|
+
if (!Array.isArray(lightSources) || triangle.surfaceType === "water") {
|
|
8341
|
+
return contribution;
|
|
8342
|
+
}
|
|
8343
|
+
const normal = normalizeVec3(triangle.normal);
|
|
8344
|
+
for (const source of lightSources.slice(0, 8)) {
|
|
8345
|
+
const delta = subVec3(source.point, triangle.worldCenter);
|
|
8346
|
+
const distance = lengthVec3(delta);
|
|
8347
|
+
const attenuation = (source.glowScale ?? 1) / Math.max(1, 0.68 + distance * distance * 0.2);
|
|
8348
|
+
if (attenuation < 0.012) {
|
|
8349
|
+
continue;
|
|
8350
|
+
}
|
|
8351
|
+
const lightDir = normalizeVec3(delta);
|
|
8352
|
+
const facing = clamp(dotVec3(normal, lightDir), 0, 1);
|
|
8353
|
+
const response = attenuation * (0.18 + facing * 0.82);
|
|
8354
|
+
const glowColor = source.glowColor ?? source.coreColor ?? { r: 1, g: 0.72, b: 0.4 };
|
|
8355
|
+
contribution.r += glowColor.r * response * 0.32;
|
|
8356
|
+
contribution.g += glowColor.g * response * 0.26;
|
|
8357
|
+
contribution.b += glowColor.b * response * 0.18;
|
|
8358
|
+
}
|
|
8359
|
+
return contribution;
|
|
8360
|
+
}
|
|
8361
|
+
function drawTriangles(ctx, triangles, lightDir, reflectionStrength, camera, shadowStrength, localLights = []) {
|
|
7613
8362
|
triangles.sort((left, right) => right.depth - left.depth);
|
|
7614
8363
|
for (const triangle of triangles) {
|
|
7615
8364
|
const surfaceNormal = normalizeVec3(triangle.normal);
|
|
8365
|
+
const material = triangle.material ?? {
|
|
8366
|
+
roughness: 0.88,
|
|
8367
|
+
metallic: 0.08,
|
|
8368
|
+
emissive: { r: 0, g: 0, b: 0 }
|
|
8369
|
+
};
|
|
7616
8370
|
const shaded = shadeColor(
|
|
7617
8371
|
triangle.baseColor,
|
|
7618
8372
|
surfaceNormal,
|
|
@@ -7620,19 +8374,41 @@ function drawTriangles(ctx, triangles, lightDir, reflectionStrength, camera, sha
|
|
|
7620
8374
|
clamp((triangle.worldCenter.y + 3) / 10, 0, 1),
|
|
7621
8375
|
triangle.accent
|
|
7622
8376
|
);
|
|
7623
|
-
const reflection =
|
|
8377
|
+
const reflection = reflectionStrength * (triangle.reflection ?? 0);
|
|
7624
8378
|
const viewDir = normalizeVec3(subVec3(camera.eye, triangle.worldCenter));
|
|
7625
8379
|
const reflectedLight = reflectVec3(scaleVec3(lightDir, -1), surfaceNormal);
|
|
7626
|
-
const gloss =
|
|
7627
|
-
const
|
|
7628
|
-
const
|
|
7629
|
-
const
|
|
8380
|
+
const gloss = mix(0.78, 0.14, clamp(material.roughness ?? 0.88, 0, 1)) + (material.metallic ?? 0) * 0.18;
|
|
8381
|
+
const specularPower = mix(26, 7, clamp(material.roughness ?? 0.88, 0, 1));
|
|
8382
|
+
const specular = Math.pow(clamp(dotVec3(reflectedLight, viewDir), 0, 1), specularPower) * gloss;
|
|
8383
|
+
const emissive = material.emissive ?? { r: 0, g: 0, b: 0 };
|
|
8384
|
+
const localLight = resolveLocalLightContribution(triangle, localLights);
|
|
8385
|
+
const occlusion = triangle.surfaceType === "water" ? shadowStrength * 0.018 : shadowStrength * 0.04;
|
|
8386
|
+
const detailed = applyMaterialDetail(
|
|
7630
8387
|
{
|
|
7631
|
-
r: clamp(
|
|
7632
|
-
|
|
7633
|
-
|
|
8388
|
+
r: clamp(
|
|
8389
|
+
shaded.r + reflection * 0.08 + specular * 0.16 + emissive.r * 0.42 + localLight.r - occlusion,
|
|
8390
|
+
0,
|
|
8391
|
+
1
|
|
8392
|
+
),
|
|
8393
|
+
g: clamp(
|
|
8394
|
+
shaded.g + reflection * 0.08 + specular * 0.16 + emissive.g * 0.42 + localLight.g - occlusion,
|
|
8395
|
+
0,
|
|
8396
|
+
1
|
|
8397
|
+
),
|
|
8398
|
+
b: clamp(
|
|
8399
|
+
shaded.b + reflection * 0.16 + specular * 0.22 + emissive.b * 0.46 + localLight.b - occlusion * 0.5,
|
|
8400
|
+
0,
|
|
8401
|
+
1
|
|
8402
|
+
)
|
|
7634
8403
|
},
|
|
7635
|
-
|
|
8404
|
+
material,
|
|
8405
|
+
triangle.worldCenter,
|
|
8406
|
+
surfaceNormal,
|
|
8407
|
+
triangle.surfaceType
|
|
8408
|
+
);
|
|
8409
|
+
const fill = colorToRgba(
|
|
8410
|
+
detailed,
|
|
8411
|
+
triangle.baseColor.a ?? 0.98
|
|
7636
8412
|
);
|
|
7637
8413
|
ctx.fillStyle = fill;
|
|
7638
8414
|
ctx.beginPath();
|
|
@@ -7663,74 +8439,100 @@ function renderProjectedShadow(ctx, worldPoints, camera, viewport, lightDir, opt
|
|
|
7663
8439
|
ctx.fill();
|
|
7664
8440
|
ctx.restore();
|
|
7665
8441
|
}
|
|
7666
|
-
function pushHarborGeometry(camera, viewport, triangles,
|
|
7667
|
-
|
|
7668
|
-
{
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
8442
|
+
function pushHarborGeometry(camera, viewport, triangles, state) {
|
|
8443
|
+
if (!state.showcaseRealisticModelsEnabled) {
|
|
8444
|
+
for (const object of LEGACY_HARBOR_LAYOUT) {
|
|
8445
|
+
buildTrianglesFromMesh(
|
|
8446
|
+
{ positions: [object], indices: [0], normals: null, colors: null, material: createLegacyMeshPrimitive({})?.material, bounds: null, name: "legacy-structure" },
|
|
8447
|
+
{
|
|
8448
|
+
position: object.position,
|
|
8449
|
+
rotationY: object.rotationY,
|
|
8450
|
+
scale: object.scale
|
|
8451
|
+
},
|
|
8452
|
+
object.color,
|
|
8453
|
+
camera,
|
|
8454
|
+
viewport,
|
|
8455
|
+
triangles,
|
|
8456
|
+
{
|
|
8457
|
+
accent: object.accent,
|
|
8458
|
+
reflection: 0,
|
|
8459
|
+
surfaceType: "structure"
|
|
8460
|
+
}
|
|
8461
|
+
);
|
|
8462
|
+
}
|
|
8463
|
+
return;
|
|
8464
|
+
}
|
|
8465
|
+
for (const placement of SHOWCASE_ENVIRONMENT_LAYOUT) {
|
|
8466
|
+
const mesh = state.assetCatalog?.environment?.[placement.assetKey] ?? null;
|
|
8467
|
+
if (!mesh) {
|
|
8468
|
+
continue;
|
|
7688
8469
|
}
|
|
7689
|
-
];
|
|
7690
|
-
for (const object of harborObjects) {
|
|
7691
8470
|
buildTrianglesFromMesh(
|
|
7692
|
-
|
|
8471
|
+
mesh,
|
|
7693
8472
|
{
|
|
7694
|
-
position:
|
|
7695
|
-
rotationY:
|
|
7696
|
-
scale:
|
|
8473
|
+
position: vec3(placement.position.x, placement.position.y, placement.position.z),
|
|
8474
|
+
rotationY: placement.rotationY,
|
|
8475
|
+
scale: placement.scale
|
|
7697
8476
|
},
|
|
7698
|
-
|
|
8477
|
+
null,
|
|
7699
8478
|
camera,
|
|
7700
8479
|
viewport,
|
|
7701
8480
|
triangles,
|
|
7702
|
-
|
|
8481
|
+
{
|
|
8482
|
+
accent: placement.accent,
|
|
8483
|
+
reflection: 0,
|
|
8484
|
+
surfaceType: "structure"
|
|
8485
|
+
}
|
|
7703
8486
|
);
|
|
7704
8487
|
}
|
|
7705
8488
|
}
|
|
7706
8489
|
function renderShipRigging(ctx, ship, camera, viewport) {
|
|
7707
8490
|
const transform = { position: ship.position, rotationY: ship.rotationY, scale: SHIP_SCALE };
|
|
7708
|
-
const
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
8491
|
+
const layout = ship.modelKey === "cutter" ? {
|
|
8492
|
+
lineColor: "rgba(85, 89, 97, 0.92)",
|
|
8493
|
+
sailColor: "rgba(218, 232, 244, 0.28)",
|
|
8494
|
+
points: [
|
|
8495
|
+
vec3(0, 0.88, -0.32),
|
|
8496
|
+
vec3(0, 2.4, -0.28),
|
|
8497
|
+
vec3(0.1, 1.92, -0.3),
|
|
8498
|
+
vec3(1.18, 1.72, -0.18),
|
|
8499
|
+
vec3(1.04, 1.08, -0.12)
|
|
8500
|
+
],
|
|
8501
|
+
mastPairs: [[0, 1], [2, 3]],
|
|
8502
|
+
sailTriangle: [2, 3, 4]
|
|
8503
|
+
} : {
|
|
8504
|
+
lineColor: "rgba(73, 54, 45, 0.94)",
|
|
8505
|
+
sailColor: "rgba(238, 232, 214, 0.88)",
|
|
8506
|
+
points: [
|
|
8507
|
+
vec3(0, 0.38, -0.4),
|
|
8508
|
+
vec3(0, 3.8, -0.2),
|
|
8509
|
+
vec3(-0.25, 0.32, -1.9),
|
|
8510
|
+
vec3(-0.15, 2.7, -1.75),
|
|
8511
|
+
vec3(0.08, 3.2, -0.2),
|
|
8512
|
+
vec3(0.12, 1.2, -0.5),
|
|
8513
|
+
vec3(2.25, 2.25, 0.15)
|
|
8514
|
+
],
|
|
8515
|
+
mastPairs: [[0, 1], [2, 3]],
|
|
8516
|
+
sailTriangle: [4, 5, 6]
|
|
8517
|
+
};
|
|
8518
|
+
const projected = layout.points.map((point) => transformPoint(point, transform)).map((point) => projectPoint(point, camera, viewport));
|
|
7718
8519
|
if (projected.some((value) => value === null)) {
|
|
7719
8520
|
return;
|
|
7720
8521
|
}
|
|
7721
|
-
ctx.strokeStyle =
|
|
7722
|
-
ctx.lineWidth = 3.5;
|
|
8522
|
+
ctx.strokeStyle = layout.lineColor;
|
|
8523
|
+
ctx.lineWidth = ship.modelKey === "cutter" ? 2.2 : 3.5;
|
|
7723
8524
|
ctx.beginPath();
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
8525
|
+
for (const [from, to] of layout.mastPairs) {
|
|
8526
|
+
ctx.moveTo(projected[from].x, projected[from].y);
|
|
8527
|
+
ctx.lineTo(projected[to].x, projected[to].y);
|
|
8528
|
+
}
|
|
7728
8529
|
ctx.stroke();
|
|
7729
|
-
|
|
8530
|
+
const [a, b, c] = layout.sailTriangle;
|
|
8531
|
+
ctx.fillStyle = layout.sailColor;
|
|
7730
8532
|
ctx.beginPath();
|
|
7731
|
-
ctx.moveTo(projected[
|
|
7732
|
-
ctx.lineTo(projected[
|
|
7733
|
-
ctx.lineTo(projected[
|
|
8533
|
+
ctx.moveTo(projected[a].x, projected[a].y);
|
|
8534
|
+
ctx.lineTo(projected[b].x, projected[b].y);
|
|
8535
|
+
ctx.lineTo(projected[c].x, projected[c].y);
|
|
7734
8536
|
ctx.closePath();
|
|
7735
8537
|
ctx.fill();
|
|
7736
8538
|
}
|
|
@@ -7948,10 +8750,10 @@ function resolveBoundaryCollision(ship, state, shipModel) {
|
|
|
7948
8750
|
}
|
|
7949
8751
|
}
|
|
7950
8752
|
}
|
|
7951
|
-
function resolveShipCollision(state, a, b,
|
|
8753
|
+
function resolveShipCollision(state, a, b, shipModelA, shipModelB) {
|
|
7952
8754
|
const delta = subVec3(b.position, a.position);
|
|
7953
|
-
const radiusA = getShipCollisionRadius(a,
|
|
7954
|
-
const radiusB = getShipCollisionRadius(b,
|
|
8755
|
+
const radiusA = getShipCollisionRadius(a, shipModelA);
|
|
8756
|
+
const radiusB = getShipCollisionRadius(b, shipModelB);
|
|
7955
8757
|
const distance = Math.hypot(delta.x, delta.z);
|
|
7956
8758
|
const minDistance = radiusA + radiusB;
|
|
7957
8759
|
if (distance >= minDistance) {
|
|
@@ -7960,15 +8762,15 @@ function resolveShipCollision(state, a, b, shipModel) {
|
|
|
7960
8762
|
const normal = distance > 1e-4 ? normalizeVec3(vec3(delta.x / distance, 0, delta.z / distance)) : normalizeVec3(vec3(Math.cos(state.time * 5.2), 0, Math.sin(state.time * 4.8)));
|
|
7961
8763
|
const tangent = vec3(-normal.z, 0, normal.x);
|
|
7962
8764
|
const penetration = minDistance - distance;
|
|
7963
|
-
const invMassA = getShipInverseMass(a,
|
|
7964
|
-
const invMassB = getShipInverseMass(b,
|
|
8765
|
+
const invMassA = getShipInverseMass(a, shipModelA);
|
|
8766
|
+
const invMassB = getShipInverseMass(b, shipModelB);
|
|
7965
8767
|
const invMassSum = invMassA + invMassB;
|
|
7966
8768
|
const correction = scaleVec3(normal, penetration / Math.max(1e-4, invMassSum) * 0.72);
|
|
7967
8769
|
a.position = subVec3(a.position, scaleVec3(correction, invMassA));
|
|
7968
8770
|
b.position = addVec3(b.position, scaleVec3(correction, invMassB));
|
|
7969
8771
|
const relativeVelocity = subVec3(b.velocity, a.velocity);
|
|
7970
8772
|
const velocityAlongNormal = dotVec3(relativeVelocity, normal);
|
|
7971
|
-
const restitution = readPhysicsNumber(
|
|
8773
|
+
const restitution = (readPhysicsNumber(shipModelA.physics, "restitution", 0.22) + readPhysicsNumber(shipModelB.physics, "restitution", 0.22)) / 2 * 0.88;
|
|
7972
8774
|
if (velocityAlongNormal < 0) {
|
|
7973
8775
|
const impulseMagnitude = -(1 + restitution) * velocityAlongNormal / Math.max(1e-4, invMassSum);
|
|
7974
8776
|
const impulse = scaleVec3(normal, impulseMagnitude);
|
|
@@ -7983,8 +8785,8 @@ function resolveShipCollision(state, a, b, shipModel) {
|
|
|
7983
8785
|
const frictionImpulse = scaleVec3(tangent, frictionMagnitude);
|
|
7984
8786
|
a.velocity = subVec3(a.velocity, scaleVec3(frictionImpulse, invMassA));
|
|
7985
8787
|
b.velocity = addVec3(b.velocity, scaleVec3(frictionImpulse, invMassB));
|
|
7986
|
-
a.angularVelocity -= tangentSpeed * radiusA * getShipInverseInertia(a,
|
|
7987
|
-
b.angularVelocity += tangentSpeed * radiusB * getShipInverseInertia(b,
|
|
8788
|
+
a.angularVelocity -= tangentSpeed * radiusA * getShipInverseInertia(a, shipModelA) * 0.2 + impulseMagnitude * 24e-5;
|
|
8789
|
+
b.angularVelocity += tangentSpeed * radiusB * getShipInverseInertia(b, shipModelB) * 0.2 + impulseMagnitude * 24e-5;
|
|
7988
8790
|
const impactSpeed = Math.abs(velocityAlongNormal);
|
|
7989
8791
|
if (impactSpeed > 0.18 && Math.max(readVisualNumber(a.collisionCooldown, 0), readVisualNumber(b.collisionCooldown, 0)) <= 0) {
|
|
7990
8792
|
const contactPoint = vec3(
|
|
@@ -8016,12 +8818,17 @@ function updateShips(state, dt, shipModel) {
|
|
|
8016
8818
|
let collided = false;
|
|
8017
8819
|
state.contactCount = 0;
|
|
8018
8820
|
for (const ship of state.ships) {
|
|
8019
|
-
|
|
8020
|
-
|
|
8821
|
+
const activeShipModel = resolveShipModel(state, ship, shipModel);
|
|
8822
|
+
updateShipMotion(state, ship, dt, activeShipModel);
|
|
8823
|
+
resolveBoundaryCollision(ship, state, activeShipModel);
|
|
8021
8824
|
}
|
|
8022
8825
|
for (let index = 0; index < state.ships.length; index += 1) {
|
|
8023
8826
|
for (let otherIndex = index + 1; otherIndex < state.ships.length; otherIndex += 1) {
|
|
8024
|
-
|
|
8827
|
+
const shipA = state.ships[index];
|
|
8828
|
+
const shipB = state.ships[otherIndex];
|
|
8829
|
+
const shipModelA = resolveShipModel(state, shipA, shipModel);
|
|
8830
|
+
const shipModelB = resolveShipModel(state, shipB, shipModel);
|
|
8831
|
+
collided = resolveShipCollision(state, shipA, shipB, shipModelA, shipModelB) || collided;
|
|
8025
8832
|
}
|
|
8026
8833
|
}
|
|
8027
8834
|
state.collisionFlash = collided ? Math.max(0.12, state.collisionFlash) : Math.max(0, state.collisionFlash - dt * 1.3);
|
|
@@ -8285,6 +9092,101 @@ function renderWaterLightReflection(ctx, source, state, camera, viewport) {
|
|
|
8285
9092
|
ctx.fill();
|
|
8286
9093
|
ctx.restore();
|
|
8287
9094
|
}
|
|
9095
|
+
function renderLighthouseBeam(ctx, state, camera, viewport, visuals) {
|
|
9096
|
+
const lighthousePlacement = SHOWCASE_ENVIRONMENT_LAYOUT.find(
|
|
9097
|
+
(placement) => placement.assetKey === "lighthouse"
|
|
9098
|
+
);
|
|
9099
|
+
if (!lighthousePlacement || !state.showcaseRealisticModelsEnabled) {
|
|
9100
|
+
return;
|
|
9101
|
+
}
|
|
9102
|
+
const source = transformPoint(
|
|
9103
|
+
vec3(0, 11.34, 0),
|
|
9104
|
+
{
|
|
9105
|
+
position: vec3(
|
|
9106
|
+
lighthousePlacement.position.x,
|
|
9107
|
+
lighthousePlacement.position.y,
|
|
9108
|
+
lighthousePlacement.position.z
|
|
9109
|
+
),
|
|
9110
|
+
rotationY: lighthousePlacement.rotationY,
|
|
9111
|
+
scale: lighthousePlacement.scale
|
|
9112
|
+
}
|
|
9113
|
+
);
|
|
9114
|
+
const sweep = state.time * 0.22 + 0.8;
|
|
9115
|
+
const direction = normalizeVec3(vec3(Math.sin(sweep), -0.07, Math.cos(sweep)));
|
|
9116
|
+
const spread = perpendicularOnWater(direction);
|
|
9117
|
+
const farCenter = addVec3(source, scaleVec3(direction, 34));
|
|
9118
|
+
const left = addVec3(farCenter, scaleVec3(spread, 7.4));
|
|
9119
|
+
const right = addVec3(farCenter, scaleVec3(spread, -7.4));
|
|
9120
|
+
const projectedSource = projectPoint(source, camera, viewport);
|
|
9121
|
+
const projectedLeft = projectPoint(left, camera, viewport);
|
|
9122
|
+
const projectedRight = projectPoint(right, camera, viewport);
|
|
9123
|
+
if (!projectedSource || !projectedLeft || !projectedRight) {
|
|
9124
|
+
return;
|
|
9125
|
+
}
|
|
9126
|
+
const pulse = 0.72 + Math.sin(state.time * 1.7) * 0.08;
|
|
9127
|
+
ctx.save();
|
|
9128
|
+
ctx.globalCompositeOperation = "screen";
|
|
9129
|
+
ctx.fillStyle = colorToRgba(visuals.torchCore, 0.055 * pulse);
|
|
9130
|
+
ctx.beginPath();
|
|
9131
|
+
ctx.moveTo(projectedSource.x, projectedSource.y);
|
|
9132
|
+
ctx.lineTo(projectedLeft.x, projectedLeft.y);
|
|
9133
|
+
ctx.lineTo(projectedRight.x, projectedRight.y);
|
|
9134
|
+
ctx.closePath();
|
|
9135
|
+
ctx.fill();
|
|
9136
|
+
const beamLength = Math.hypot(
|
|
9137
|
+
projectedLeft.x - projectedSource.x,
|
|
9138
|
+
projectedLeft.y - projectedSource.y
|
|
9139
|
+
);
|
|
9140
|
+
const core = ctx.createRadialGradient(
|
|
9141
|
+
projectedSource.x,
|
|
9142
|
+
projectedSource.y,
|
|
9143
|
+
2,
|
|
9144
|
+
projectedSource.x,
|
|
9145
|
+
projectedSource.y,
|
|
9146
|
+
clamp(beamLength * 0.22, 18, 80)
|
|
9147
|
+
);
|
|
9148
|
+
core.addColorStop(0, colorToRgba(visuals.torchCore, 0.58));
|
|
9149
|
+
core.addColorStop(0.5, colorToRgba(visuals.torchGlow, 0.18));
|
|
9150
|
+
core.addColorStop(1, colorToRgba(visuals.torchGlow, 0));
|
|
9151
|
+
ctx.fillStyle = core;
|
|
9152
|
+
ctx.beginPath();
|
|
9153
|
+
ctx.arc(projectedSource.x, projectedSource.y, clamp(beamLength * 0.18, 14, 64), 0, Math.PI * 2);
|
|
9154
|
+
ctx.fill();
|
|
9155
|
+
ctx.restore();
|
|
9156
|
+
}
|
|
9157
|
+
function renderAtmosphericGrade(ctx, canvas, state, visuals) {
|
|
9158
|
+
const vignette = ctx.createRadialGradient(
|
|
9159
|
+
canvas.width * 0.5,
|
|
9160
|
+
canvas.height * 0.48,
|
|
9161
|
+
canvas.width * 0.2,
|
|
9162
|
+
canvas.width * 0.5,
|
|
9163
|
+
canvas.height * 0.5,
|
|
9164
|
+
canvas.width * 0.72
|
|
9165
|
+
);
|
|
9166
|
+
vignette.addColorStop(0, "rgba(0, 0, 0, 0)");
|
|
9167
|
+
vignette.addColorStop(0.68, "rgba(0, 0, 0, 0.08)");
|
|
9168
|
+
vignette.addColorStop(1, "rgba(0, 0, 0, 0.32)");
|
|
9169
|
+
ctx.fillStyle = vignette;
|
|
9170
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
9171
|
+
const seaHaze = ctx.createLinearGradient(0, canvas.height * 0.34, 0, canvas.height);
|
|
9172
|
+
seaHaze.addColorStop(0, "rgba(0, 0, 0, 0)");
|
|
9173
|
+
seaHaze.addColorStop(0.5, visuals.ambientMist);
|
|
9174
|
+
seaHaze.addColorStop(1, "rgba(3, 8, 16, 0.18)");
|
|
9175
|
+
ctx.fillStyle = seaHaze;
|
|
9176
|
+
ctx.fillRect(0, canvas.height * 0.34, canvas.width, canvas.height * 0.66);
|
|
9177
|
+
if (state.captureMode) {
|
|
9178
|
+
ctx.save();
|
|
9179
|
+
ctx.globalCompositeOperation = "screen";
|
|
9180
|
+
for (let index = 0; index < 70; index += 1) {
|
|
9181
|
+
const x = pseudoRandom(index * 19 + 3) * canvas.width;
|
|
9182
|
+
const y = pseudoRandom(index * 23 + 7) * canvas.height;
|
|
9183
|
+
const alpha = 8e-3 + pseudoRandom(index * 31 + 11) * 0.012;
|
|
9184
|
+
ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
|
|
9185
|
+
ctx.fillRect(x, y, 1.1, 1.1);
|
|
9186
|
+
}
|
|
9187
|
+
ctx.restore();
|
|
9188
|
+
}
|
|
9189
|
+
}
|
|
8288
9190
|
function renderWaterMotionEffects(ctx, effects, camera, viewport) {
|
|
8289
9191
|
ctx.save();
|
|
8290
9192
|
ctx.globalCompositeOperation = "screen";
|
|
@@ -8403,13 +9305,22 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8403
9305
|
worldCenter: scaleVec3(addVec3(addVec3(a, b), c), 1 / 3),
|
|
8404
9306
|
normal,
|
|
8405
9307
|
baseColor: bandMesh.color,
|
|
8406
|
-
accent: bandAccent
|
|
9308
|
+
accent: bandAccent,
|
|
9309
|
+
material: {
|
|
9310
|
+
name: "water-surface",
|
|
9311
|
+
color: bandMesh.color,
|
|
9312
|
+
roughness: 0.2,
|
|
9313
|
+
metallic: 0,
|
|
9314
|
+
emissive: { r: 0, g: 0, b: 0 }
|
|
9315
|
+
},
|
|
9316
|
+
reflection: 1,
|
|
9317
|
+
surfaceType: "water"
|
|
8407
9318
|
});
|
|
8408
9319
|
}
|
|
8409
9320
|
}
|
|
8410
9321
|
const waterMotionEffects = buildWaterMotionEffects(state);
|
|
8411
9322
|
const lightSources = collectSceneLightSources(state, visuals);
|
|
8412
|
-
pushHarborGeometry(camera, viewport, sceneTriangles,
|
|
9323
|
+
pushHarborGeometry(camera, viewport, sceneTriangles, state);
|
|
8413
9324
|
const cloth = buildClothSurface(
|
|
8414
9325
|
state,
|
|
8415
9326
|
state,
|
|
@@ -8431,23 +9342,46 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8431
9342
|
worldCenter: scaleVec3(addVec3(addVec3(a, b), c), 1 / 3),
|
|
8432
9343
|
normal,
|
|
8433
9344
|
baseColor: cloth.color,
|
|
8434
|
-
accent: cloth.band === "near" ? 0.1 : 0.04
|
|
9345
|
+
accent: cloth.band === "near" ? 0.1 : 0.04,
|
|
9346
|
+
material: {
|
|
9347
|
+
name: "flag-cloth",
|
|
9348
|
+
color: cloth.color,
|
|
9349
|
+
roughness: 0.94,
|
|
9350
|
+
metallic: 0,
|
|
9351
|
+
emissive: { r: 0, g: 0, b: 0 }
|
|
9352
|
+
},
|
|
9353
|
+
reflection: 0,
|
|
9354
|
+
surfaceType: "cloth"
|
|
8435
9355
|
});
|
|
8436
9356
|
}
|
|
8437
9357
|
for (const ship of state.ships) {
|
|
9358
|
+
const activeShipModel = resolveShipModel(state, ship, shipModel);
|
|
8438
9359
|
buildTrianglesFromMesh(
|
|
8439
|
-
|
|
9360
|
+
activeShipModel,
|
|
8440
9361
|
{ position: ship.position, rotationY: ship.rotationY, scale: SHIP_SCALE },
|
|
8441
9362
|
ship.tint,
|
|
8442
9363
|
camera,
|
|
8443
9364
|
viewport,
|
|
8444
9365
|
sceneTriangles,
|
|
8445
|
-
|
|
9366
|
+
{
|
|
9367
|
+
accent: nearLighting.rtParticipation.directShadows === "premium" ? 0.08 : 0.02,
|
|
9368
|
+
reflection: 0,
|
|
9369
|
+
surfaceType: "ship"
|
|
9370
|
+
}
|
|
8446
9371
|
);
|
|
8447
9372
|
}
|
|
8448
9373
|
drawTriangles(ctx, waterTriangles, lightDir, reflectionStrength, camera, shadowStrength);
|
|
8449
9374
|
for (const ship of state.ships) {
|
|
8450
|
-
renderShipShadow(
|
|
9375
|
+
renderShipShadow(
|
|
9376
|
+
ctx,
|
|
9377
|
+
resolveShipModel(state, ship, shipModel),
|
|
9378
|
+
ship,
|
|
9379
|
+
state,
|
|
9380
|
+
camera,
|
|
9381
|
+
viewport,
|
|
9382
|
+
lightDir,
|
|
9383
|
+
shadowStrength
|
|
9384
|
+
);
|
|
8451
9385
|
}
|
|
8452
9386
|
renderFlagShadow(ctx, cloth, camera, viewport, lightDir, shadowStrength);
|
|
8453
9387
|
for (const source of lightSources.reflectionLights) {
|
|
@@ -8455,9 +9389,18 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8455
9389
|
}
|
|
8456
9390
|
renderWaterMotionEffects(ctx, waterMotionEffects, camera, viewport);
|
|
8457
9391
|
renderWaterHighlights(ctx, water.bandMeshes, camera, viewport);
|
|
8458
|
-
drawTriangles(
|
|
9392
|
+
drawTriangles(
|
|
9393
|
+
ctx,
|
|
9394
|
+
sceneTriangles,
|
|
9395
|
+
lightDir,
|
|
9396
|
+
reflectionStrength,
|
|
9397
|
+
camera,
|
|
9398
|
+
shadowStrength,
|
|
9399
|
+
lightSources.directLights
|
|
9400
|
+
);
|
|
8459
9401
|
renderFlagPole(ctx, camera, viewport);
|
|
8460
9402
|
renderClothAccent(ctx, cloth, camera, viewport);
|
|
9403
|
+
renderLighthouseBeam(ctx, state, camera, viewport, visuals);
|
|
8461
9404
|
for (const source of lightSources.directLights) {
|
|
8462
9405
|
renderDirectLightGlow(ctx, source, camera, viewport);
|
|
8463
9406
|
}
|
|
@@ -8465,6 +9408,7 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8465
9408
|
renderShipRigging(ctx, ship, camera, viewport);
|
|
8466
9409
|
}
|
|
8467
9410
|
renderSprays(ctx, state.sprays, camera, viewport);
|
|
9411
|
+
renderAtmosphericGrade(ctx, canvas, state, visuals);
|
|
8468
9412
|
const debugSnapshot = state.debugSession.getSnapshot();
|
|
8469
9413
|
const quality = {
|
|
8470
9414
|
fluid: state.fluidDetail.getSnapshot(),
|
|
@@ -8473,11 +9417,11 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8473
9417
|
};
|
|
8474
9418
|
const sceneMetrics = [
|
|
8475
9419
|
`focus: ${state.focus}`,
|
|
8476
|
-
`ships: ${state.ships.length} active GLTF hulls`,
|
|
8477
|
-
`moonlight: cold overhead key + ${HARBOR_TORCHES.length + state.ships.
|
|
9420
|
+
`ships: ${state.ships.length} active GLTF hulls across ${new Set(state.ships.map((ship) => ship.modelKey)).size} model families`,
|
|
9421
|
+
`moonlight: cold overhead key + ${HARBOR_TORCHES.length + state.ships.reduce((total, ship) => total + (Array.isArray(ship.lanterns) ? ship.lanterns.length : 0), 0)} warm deck and harbor lights`,
|
|
8478
9422
|
`physics snapshot: ${state.physics.snapshot.stage} (${state.physics.snapshot.stability})`,
|
|
8479
9423
|
`physics contacts: ${state.contactCount}`,
|
|
8480
|
-
`mass split: ${state.ships.map((ship) => `${ship.id} ${(getShipMass(ship, shipModel) / 1e3).toFixed(1)}t`).join(" \xB7 ")}`,
|
|
9424
|
+
`mass split: ${state.ships.map((ship) => `${ship.id} ${(getShipMass(ship, resolveShipModel(state, ship, shipModel)) / 1e3).toFixed(1)}t`).join(" \xB7 ")}`,
|
|
8481
9425
|
`cloth band: ${cloth.band} -> ${cloth.representation.output}`,
|
|
8482
9426
|
`fluid near band: ${water.bandMeshes[0].representation.output}`,
|
|
8483
9427
|
`lighting profile: ${lightingPlan.profile} (${lightingDistanceBands.length} bands)`
|
|
@@ -8498,11 +9442,7 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8498
9442
|
`pipeline samples: ${debugSnapshot.pipeline.sampleCount}`,
|
|
8499
9443
|
`tracked memory: ${(debugSnapshot.memory.totalTrackedBytes / (1024 * 1024)).toFixed(1)} MB`
|
|
8500
9444
|
];
|
|
8501
|
-
const sceneNotes = state.focus === "physics" ?
|
|
8502
|
-
"Stable world snapshots are taken after the authoritative rigid-body commit and before visual follow-up work.",
|
|
8503
|
-
"The ships collide with mass-weighted impulses and positional correction, so the heavier hull keeps more of its line.",
|
|
8504
|
-
"Moonlight keeps the overall read legible while lanterns and torches make collision moments easy to track against the water."
|
|
8505
|
-
] : SCENE_NOTES;
|
|
9445
|
+
const sceneNotes = state.focus === "physics" ? PHYSICS_SCENE_NOTE_KEYS.map((key) => state.translate(key)) : SCENE_NOTE_KEYS.map((key) => state.translate(key));
|
|
8506
9446
|
const custom = state.demoDescription ?? null;
|
|
8507
9447
|
setListContent(
|
|
8508
9448
|
dom.sceneMetrics,
|
|
@@ -8517,8 +9457,16 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
8517
9457
|
Array.isArray(custom?.debugMetrics) ? custom.debugMetrics : debugMetrics
|
|
8518
9458
|
);
|
|
8519
9459
|
setListContent(dom.sceneNotes, Array.isArray(custom?.notes) ? custom.notes : sceneNotes);
|
|
8520
|
-
dom.status.textContent = typeof custom?.status === "string" ? custom.status :
|
|
8521
|
-
|
|
9460
|
+
dom.status.textContent = typeof custom?.status === "string" ? custom.status : state.translate(gpuSharedTranslationKeys.statusLive, {
|
|
9461
|
+
fps: state.lastDecision.metrics.fps.toFixed(1)
|
|
9462
|
+
});
|
|
9463
|
+
dom.details.textContent = typeof custom?.details === "string" ? custom.details : state.focus === "physics" ? state.translate(gpuSharedTranslationKeys.detailsPhysics, {
|
|
9464
|
+
snapshotStageId: state.physics.plan.snapshotStageId
|
|
9465
|
+
}) : state.showcaseRealisticModelsEnabled ? state.translate(gpuSharedTranslationKeys.detailsRealistic, {
|
|
9466
|
+
pressureLevel: state.lastDecision.pressureLevel
|
|
9467
|
+
}) : state.translate(gpuSharedTranslationKeys.detailsLegacy, {
|
|
9468
|
+
pressureLevel: state.lastDecision.pressureLevel
|
|
9469
|
+
});
|
|
8522
9470
|
}
|
|
8523
9471
|
function updateSceneState(state, dt, shipModel) {
|
|
8524
9472
|
updateShips(state, dt, shipModel);
|
|
@@ -8548,15 +9496,18 @@ function syncTextState(state, shipModel) {
|
|
|
8548
9496
|
stress: state.stress,
|
|
8549
9497
|
ships: state.ships.map((ship) => ({
|
|
8550
9498
|
id: ship.id,
|
|
9499
|
+
modelKey: ship.modelKey ?? "brigantine",
|
|
8551
9500
|
x: Number(ship.position.x.toFixed(2)),
|
|
8552
9501
|
y: Number(ship.position.y.toFixed(2)),
|
|
8553
9502
|
z: Number(ship.position.z.toFixed(2)),
|
|
8554
9503
|
vx: Number(ship.velocity.x.toFixed(2)),
|
|
8555
9504
|
vz: Number(ship.velocity.z.toFixed(2)),
|
|
8556
|
-
massKg: Math.round(getShipMass(ship, shipModel)),
|
|
9505
|
+
massKg: Math.round(getShipMass(ship, resolveShipModel(state, ship, shipModel))),
|
|
8557
9506
|
lanterns: Array.isArray(ship.lanterns) ? ship.lanterns.length : 0
|
|
8558
9507
|
})),
|
|
8559
|
-
shipPhysics:
|
|
9508
|
+
shipPhysics: Object.fromEntries(
|
|
9509
|
+
state.ships.map((ship) => [ship.id, resolveShipModel(state, ship, shipModel)?.physics ?? null])
|
|
9510
|
+
),
|
|
8560
9511
|
sprays: state.sprays.length,
|
|
8561
9512
|
waveImpulses: state.waveImpulses.length,
|
|
8562
9513
|
pressure: state.lastDecision?.pressureLevel ?? "stable",
|
|
@@ -8579,22 +9530,36 @@ function syncTextState(state, shipModel) {
|
|
|
8579
9530
|
}
|
|
8580
9531
|
};
|
|
8581
9532
|
}
|
|
8582
|
-
async function mountGpuShowcase(options = {}) {
|
|
9533
|
+
async function mountGpuShowcase(options = {}, featureFlags = null) {
|
|
8583
9534
|
injectStyles();
|
|
8584
9535
|
const root = options.root ?? document.body;
|
|
8585
9536
|
root.classList?.add?.(ROOT_CLASS);
|
|
9537
|
+
const captureSettings = resolveCaptureSettings(options);
|
|
9538
|
+
if (captureSettings.captureMode) {
|
|
9539
|
+
root.classList?.add?.(CAPTURE_CLASS);
|
|
9540
|
+
}
|
|
8586
9541
|
const previousMarkup = root.innerHTML;
|
|
8587
9542
|
const previousRenderGameToText = window.render_game_to_text;
|
|
8588
9543
|
const previousAdvanceTime = window.advanceTime;
|
|
8589
9544
|
const focus = options.focus ?? new URLSearchParams(window.location.search).get("focus") ?? "integrated";
|
|
9545
|
+
const translate = createGpuSharedTranslator(options.translate);
|
|
8590
9546
|
const dom = buildDemoDom(root, {
|
|
8591
9547
|
packageName: options.packageName ?? "@plasius/gpu-demo-viewer",
|
|
8592
|
-
title: options.title ??
|
|
8593
|
-
subtitle: options.subtitle ??
|
|
9548
|
+
title: options.title ?? translate(gpuSharedTranslationKeys.showcaseTitle),
|
|
9549
|
+
subtitle: options.subtitle ?? translate(gpuSharedTranslationKeys.showcaseSubtitle),
|
|
9550
|
+
translate
|
|
8594
9551
|
});
|
|
8595
9552
|
dom.focusMode.value = focus;
|
|
8596
|
-
const state = createSceneState({
|
|
8597
|
-
|
|
9553
|
+
const state = createSceneState({
|
|
9554
|
+
focus,
|
|
9555
|
+
translate,
|
|
9556
|
+
realisticModelsEnabled: isFeatureEnabled(featureFlags, GPU_SHOWCASE_REALISTIC_MODELS_FEATURE, true),
|
|
9557
|
+
captureMode: captureSettings.captureMode,
|
|
9558
|
+
renderScale: captureSettings.renderScale
|
|
9559
|
+
});
|
|
9560
|
+
const assetCatalog = await (state.showcaseRealisticModelsEnabled ? loadShowcaseAssetCatalog() : createLegacyShowcaseAssetCatalog());
|
|
9561
|
+
const shipModel = assetCatalog.ships[assetCatalog.primaryShipKey];
|
|
9562
|
+
state.assetCatalog = assetCatalog;
|
|
8598
9563
|
state.shipModel = shipModel;
|
|
8599
9564
|
state.packageState = typeof options.createState === "function" ? options.createState() : void 0;
|
|
8600
9565
|
updatePhysicsSnapshot(state, shipModel);
|
|
@@ -8605,6 +9570,8 @@ async function mountGpuShowcase(options = {}) {
|
|
|
8605
9570
|
if (!ctx) {
|
|
8606
9571
|
throw new Error("2D canvas context is required for the shared showcase.");
|
|
8607
9572
|
}
|
|
9573
|
+
ctx.imageSmoothingEnabled = true;
|
|
9574
|
+
ctx.imageSmoothingQuality = "high";
|
|
8608
9575
|
let animationFrameId = 0;
|
|
8609
9576
|
let destroyed = false;
|
|
8610
9577
|
const renderFrame = (nowMs) => {
|
|
@@ -8625,13 +9592,14 @@ async function mountGpuShowcase(options = {}) {
|
|
|
8625
9592
|
state.lastDecision = recordTelemetry(state, syntheticFrame);
|
|
8626
9593
|
}
|
|
8627
9594
|
state.demoDescription = resolveSceneDescription(state, options, shipModel).description;
|
|
9595
|
+
resizeCanvasToDisplaySize(dom.canvas, state);
|
|
8628
9596
|
renderScene(ctx, dom.canvas, state, shipModel, dom);
|
|
8629
9597
|
syncTextState(state, shipModel);
|
|
8630
9598
|
animationFrameId = requestAnimationFrame(renderFrame);
|
|
8631
9599
|
};
|
|
8632
9600
|
const handlePauseClick = () => {
|
|
8633
9601
|
state.paused = !state.paused;
|
|
8634
|
-
dom.pauseButton.textContent = state.paused ?
|
|
9602
|
+
dom.pauseButton.textContent = state.paused ? state.translate(gpuSharedTranslationKeys.resume) : state.translate(gpuSharedTranslationKeys.pause);
|
|
8635
9603
|
};
|
|
8636
9604
|
const handleStressChange = () => {
|
|
8637
9605
|
state.stress = dom.stressToggle.checked;
|
|
@@ -8666,6 +9634,7 @@ async function mountGpuShowcase(options = {}) {
|
|
|
8666
9634
|
state.packageState = void 0;
|
|
8667
9635
|
}
|
|
8668
9636
|
root.classList?.remove?.(ROOT_CLASS);
|
|
9637
|
+
root.classList?.remove?.(CAPTURE_CLASS);
|
|
8669
9638
|
root.innerHTML = previousMarkup;
|
|
8670
9639
|
if (typeof previousRenderGameToText === "function") {
|
|
8671
9640
|
window.render_game_to_text = previousRenderGameToText;
|
|
@@ -8686,6 +9655,12 @@ async function mountGpuShowcase(options = {}) {
|
|
|
8686
9655
|
};
|
|
8687
9656
|
}
|
|
8688
9657
|
function updatePhysicsSnapshot(state, shipModel) {
|
|
9658
|
+
const rigidBodyShapes = Object.fromEntries(
|
|
9659
|
+
state.ships.map((ship) => [
|
|
9660
|
+
ship.id,
|
|
9661
|
+
resolveShipModel(state, ship, shipModel)?.physics?.shape ?? "box"
|
|
9662
|
+
])
|
|
9663
|
+
);
|
|
8689
9664
|
state.physics.snapshot = createPhysicsWorldSnapshot({
|
|
8690
9665
|
frameId: `showcase-${state.frame}`,
|
|
8691
9666
|
tick: state.frame,
|
|
@@ -8701,11 +9676,12 @@ function updatePhysicsSnapshot(state, shipModel) {
|
|
|
8701
9676
|
collisionCount: state.collisionCount,
|
|
8702
9677
|
contactCount: state.contactCount,
|
|
8703
9678
|
snapshotStageId: state.physics.plan.snapshotStageId,
|
|
8704
|
-
rigidBodyShape: shipModel.physics.shape ?? "box"
|
|
9679
|
+
rigidBodyShape: shipModel.physics.shape ?? "box",
|
|
9680
|
+
rigidBodyShapes
|
|
8705
9681
|
}
|
|
8706
9682
|
});
|
|
8707
9683
|
}
|
|
8708
|
-
var STYLE_ID, ROOT_CLASS,
|
|
9684
|
+
var STYLE_ID, ROOT_CLASS, CAPTURE_CLASS, DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT, CAPTURE_CANVAS_PIXEL_BUDGET, SHIP_SCALE, HARBOR_BOUNDS, CAMERA_PRESETS, showcaseFocusModes, FOCUS_MODE_TRANSLATION_KEYS, SCENE_NOTE_KEYS, PHYSICS_SCENE_NOTE_KEYS, LEGACY_HARBOR_LAYOUT, SHOWCASE_ENVIRONMENT_LAYOUT, SHIP_LANTERNS, CUTTER_LANTERNS, HARBOR_TORCHES, FLAG_LAYOUT;
|
|
8709
9685
|
var init_showcase_runtime = __esm({
|
|
8710
9686
|
"src/showcase-runtime.js"() {
|
|
8711
9687
|
init_dist();
|
|
@@ -8716,10 +9692,14 @@ var init_showcase_runtime = __esm({
|
|
|
8716
9692
|
init_browser();
|
|
8717
9693
|
init_asset_url();
|
|
8718
9694
|
init_gltf_loader();
|
|
9695
|
+
init_feature_flags();
|
|
9696
|
+
init_i18n();
|
|
8719
9697
|
STYLE_ID = "plasius-shared-3d-showcase-style";
|
|
8720
9698
|
ROOT_CLASS = "plasius-showcase-root";
|
|
8721
|
-
|
|
8722
|
-
|
|
9699
|
+
CAPTURE_CLASS = "plasius-showcase-root--capture";
|
|
9700
|
+
DEFAULT_CANVAS_WIDTH = 1280;
|
|
9701
|
+
DEFAULT_CANVAS_HEIGHT = 720;
|
|
9702
|
+
CAPTURE_CANVAS_PIXEL_BUDGET = 1920 * 1080;
|
|
8723
9703
|
SHIP_SCALE = 1.1;
|
|
8724
9704
|
HARBOR_BOUNDS = Object.freeze({
|
|
8725
9705
|
minX: -11.2,
|
|
@@ -8737,84 +9717,75 @@ var init_showcase_runtime = __esm({
|
|
|
8737
9717
|
debug: Object.freeze({ yaw: -0.7, pitch: 0.32, distance: 24, target: [0, 2.2, 0] })
|
|
8738
9718
|
});
|
|
8739
9719
|
showcaseFocusModes = Object.freeze(Object.keys(CAMERA_PRESETS));
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
-0.5,
|
|
8749
|
-
-0.5,
|
|
8750
|
-
-0.5,
|
|
8751
|
-
0.5,
|
|
8752
|
-
-0.5,
|
|
8753
|
-
-0.5,
|
|
8754
|
-
0.5,
|
|
8755
|
-
0.5,
|
|
8756
|
-
-0.5,
|
|
8757
|
-
-0.5,
|
|
8758
|
-
0.5,
|
|
8759
|
-
-0.5,
|
|
8760
|
-
-0.5,
|
|
8761
|
-
-0.5,
|
|
8762
|
-
0.5,
|
|
8763
|
-
0.5,
|
|
8764
|
-
-0.5,
|
|
8765
|
-
0.5,
|
|
8766
|
-
0.5,
|
|
8767
|
-
0.5,
|
|
8768
|
-
0.5,
|
|
8769
|
-
-0.5,
|
|
8770
|
-
0.5,
|
|
8771
|
-
0.5
|
|
8772
|
-
]),
|
|
8773
|
-
indices: Object.freeze([
|
|
8774
|
-
0,
|
|
8775
|
-
1,
|
|
8776
|
-
2,
|
|
8777
|
-
0,
|
|
8778
|
-
2,
|
|
8779
|
-
3,
|
|
8780
|
-
5,
|
|
8781
|
-
4,
|
|
8782
|
-
7,
|
|
8783
|
-
5,
|
|
8784
|
-
7,
|
|
8785
|
-
6,
|
|
8786
|
-
4,
|
|
8787
|
-
0,
|
|
8788
|
-
3,
|
|
8789
|
-
4,
|
|
8790
|
-
3,
|
|
8791
|
-
7,
|
|
8792
|
-
1,
|
|
8793
|
-
5,
|
|
8794
|
-
6,
|
|
8795
|
-
1,
|
|
8796
|
-
6,
|
|
8797
|
-
2,
|
|
8798
|
-
3,
|
|
8799
|
-
2,
|
|
8800
|
-
6,
|
|
8801
|
-
3,
|
|
8802
|
-
6,
|
|
8803
|
-
7,
|
|
8804
|
-
4,
|
|
8805
|
-
5,
|
|
8806
|
-
1,
|
|
8807
|
-
4,
|
|
8808
|
-
1,
|
|
8809
|
-
0
|
|
8810
|
-
])
|
|
9720
|
+
FOCUS_MODE_TRANSLATION_KEYS = Object.freeze({
|
|
9721
|
+
integrated: gpuSharedTranslationKeys.focusIntegrated,
|
|
9722
|
+
lighting: gpuSharedTranslationKeys.focusLighting,
|
|
9723
|
+
cloth: gpuSharedTranslationKeys.focusCloth,
|
|
9724
|
+
fluid: gpuSharedTranslationKeys.focusFluid,
|
|
9725
|
+
physics: gpuSharedTranslationKeys.focusPhysics,
|
|
9726
|
+
performance: gpuSharedTranslationKeys.focusPerformance,
|
|
9727
|
+
debug: gpuSharedTranslationKeys.focusDebug
|
|
8811
9728
|
});
|
|
9729
|
+
SCENE_NOTE_KEYS = Object.freeze([
|
|
9730
|
+
gpuSharedTranslationKeys.noteAssetLoading,
|
|
9731
|
+
gpuSharedTranslationKeys.noteMoonlight,
|
|
9732
|
+
gpuSharedTranslationKeys.noteContinuity,
|
|
9733
|
+
gpuSharedTranslationKeys.notePerformance
|
|
9734
|
+
]);
|
|
9735
|
+
PHYSICS_SCENE_NOTE_KEYS = Object.freeze([
|
|
9736
|
+
gpuSharedTranslationKeys.notePhysicsSnapshots,
|
|
9737
|
+
gpuSharedTranslationKeys.notePhysicsCollisions,
|
|
9738
|
+
gpuSharedTranslationKeys.notePhysicsLighting
|
|
9739
|
+
]);
|
|
9740
|
+
LEGACY_HARBOR_LAYOUT = Object.freeze([
|
|
9741
|
+
Object.freeze({
|
|
9742
|
+
position: Object.freeze({ x: -8.2, y: 1.1, z: -0.9 }),
|
|
9743
|
+
rotationY: -0.16,
|
|
9744
|
+
scale: 5.4,
|
|
9745
|
+
color: { r: 0.32, g: 0.27, b: 0.23, a: 1 },
|
|
9746
|
+
accent: 0.06
|
|
9747
|
+
}),
|
|
9748
|
+
Object.freeze({
|
|
9749
|
+
position: Object.freeze({ x: -5.7, y: 0.45, z: 1.4 }),
|
|
9750
|
+
rotationY: -0.08,
|
|
9751
|
+
scale: { x: 6.8, y: 0.3, z: 2.1 },
|
|
9752
|
+
color: { r: 0.31, g: 0.31, b: 0.34, a: 1 },
|
|
9753
|
+
accent: 0.04
|
|
9754
|
+
}),
|
|
9755
|
+
Object.freeze({
|
|
9756
|
+
position: Object.freeze({ x: -10.4, y: 0.28, z: 0.8 }),
|
|
9757
|
+
rotationY: 0.22,
|
|
9758
|
+
scale: { x: 1.2, y: 0.9, z: 1.2 },
|
|
9759
|
+
color: { r: 0.31, g: 0.35, b: 0.39, a: 1 },
|
|
9760
|
+
accent: 0.02
|
|
9761
|
+
})
|
|
9762
|
+
]);
|
|
9763
|
+
SHOWCASE_ENVIRONMENT_LAYOUT = Object.freeze([
|
|
9764
|
+
Object.freeze({
|
|
9765
|
+
assetKey: "harbor-dock",
|
|
9766
|
+
position: Object.freeze({ x: -4.6, y: 0.16, z: 0.7 }),
|
|
9767
|
+
rotationY: -0.08,
|
|
9768
|
+
scale: 0.84,
|
|
9769
|
+
accent: 0.04
|
|
9770
|
+
}),
|
|
9771
|
+
Object.freeze({
|
|
9772
|
+
assetKey: "lighthouse",
|
|
9773
|
+
position: Object.freeze({ x: -9.8, y: 0, z: -0.58 }),
|
|
9774
|
+
rotationY: 0.12,
|
|
9775
|
+
scale: 0.56,
|
|
9776
|
+
accent: 0.08
|
|
9777
|
+
})
|
|
9778
|
+
]);
|
|
8812
9779
|
SHIP_LANTERNS = Object.freeze([
|
|
8813
9780
|
Object.freeze({ x: 0.94, y: 1.54, z: 2.52, glow: 1 }),
|
|
8814
9781
|
Object.freeze({ x: -0.9, y: 1.58, z: 2.44, glow: 0.92 }),
|
|
8815
9782
|
Object.freeze({ x: 0.62, y: 1.42, z: -2.18, glow: 0.88 }),
|
|
8816
9783
|
Object.freeze({ x: -0.58, y: 1.46, z: -2.04, glow: 0.84 })
|
|
8817
9784
|
]);
|
|
9785
|
+
CUTTER_LANTERNS = Object.freeze([
|
|
9786
|
+
Object.freeze({ x: 0.42, y: 1.04, z: 1.18, glow: 0.94 }),
|
|
9787
|
+
Object.freeze({ x: -0.42, y: 1.04, z: 1.12, glow: 0.88 })
|
|
9788
|
+
]);
|
|
8818
9789
|
HARBOR_TORCHES = Object.freeze([
|
|
8819
9790
|
Object.freeze({ x: -5.2, y: 1.25, z: 1.36, glow: 1.1 }),
|
|
8820
9791
|
Object.freeze({ x: -8.6, y: 2.48, z: -0.72, glow: 1 }),
|
|
@@ -8832,13 +9803,20 @@ var init_showcase_runtime = __esm({
|
|
|
8832
9803
|
// src/index.js
|
|
8833
9804
|
var index_exports = {};
|
|
8834
9805
|
__export(index_exports, {
|
|
9806
|
+
createGpuSharedTranslator: () => createGpuSharedTranslator,
|
|
9807
|
+
gpuSharedEnGbTranslations: () => gpuSharedEnGbTranslations,
|
|
9808
|
+
gpuSharedTranslationKeys: () => gpuSharedTranslationKeys,
|
|
9809
|
+
gpuSharedTranslations: () => gpuSharedTranslations,
|
|
8835
9810
|
loadGltfModel: () => loadGltfModel2,
|
|
8836
9811
|
mountGpuShowcase: () => mountGpuShowcase2,
|
|
8837
9812
|
resolveShowcaseAssetUrl: () => resolveShowcaseAssetUrl,
|
|
8838
|
-
showcaseFocusModes: () => showcaseFocusModes2
|
|
9813
|
+
showcaseFocusModes: () => showcaseFocusModes2,
|
|
9814
|
+
translateGpuSharedText: () => translateGpuSharedText
|
|
8839
9815
|
});
|
|
8840
9816
|
module.exports = __toCommonJS(index_exports);
|
|
8841
9817
|
init_asset_url();
|
|
9818
|
+
init_i18n();
|
|
9819
|
+
init_en_GB();
|
|
8842
9820
|
var showcaseFocusModes2 = Object.freeze([
|
|
8843
9821
|
"integrated",
|
|
8844
9822
|
"lighting",
|
|
@@ -8860,13 +9838,19 @@ async function mountGpuShowcase2(options = {}) {
|
|
|
8860
9838
|
}
|
|
8861
9839
|
const publicOptions = { ...options };
|
|
8862
9840
|
delete publicOptions.__runtimeLoader;
|
|
8863
|
-
|
|
9841
|
+
delete publicOptions.__featureFlags;
|
|
9842
|
+
return module2.mountGpuShowcase(publicOptions, options.__featureFlags);
|
|
8864
9843
|
}
|
|
8865
9844
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8866
9845
|
0 && (module.exports = {
|
|
9846
|
+
createGpuSharedTranslator,
|
|
9847
|
+
gpuSharedEnGbTranslations,
|
|
9848
|
+
gpuSharedTranslationKeys,
|
|
9849
|
+
gpuSharedTranslations,
|
|
8867
9850
|
loadGltfModel,
|
|
8868
9851
|
mountGpuShowcase,
|
|
8869
9852
|
resolveShowcaseAssetUrl,
|
|
8870
|
-
showcaseFocusModes
|
|
9853
|
+
showcaseFocusModes,
|
|
9854
|
+
translateGpuSharedText
|
|
8871
9855
|
});
|
|
8872
9856
|
//# sourceMappingURL=index.cjs.map
|