@plasius/gpu-shared 0.1.6 → 0.1.9
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 +54 -0
- package/README.md +6 -0
- package/dist/index.cjs +517 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{showcase-runtime-JZIYGQAU.js → showcase-runtime-55OVDYWT.js} +517 -126
- package/dist/showcase-runtime-55OVDYWT.js.map +1 -0
- package/package.json +2 -2
- package/src/showcase-runtime.js +569 -151
- package/dist/showcase-runtime-JZIYGQAU.js.map +0 -1
|
@@ -2022,9 +2022,12 @@ var __require2 = /* @__PURE__ */ ((x) => typeof __require !== "undefined" ? __re
|
|
|
2022
2022
|
if (typeof __require !== "undefined") return __require.apply(this, arguments);
|
|
2023
2023
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
2024
2024
|
});
|
|
2025
|
+
function createModuleBaseUrl(metaUrl) {
|
|
2026
|
+
return Reflect.construct(URL, [String(metaUrl)]);
|
|
2027
|
+
}
|
|
2025
2028
|
var baseUrl = (() => {
|
|
2026
2029
|
if (typeof import.meta.url !== "undefined") {
|
|
2027
|
-
return
|
|
2030
|
+
return createModuleBaseUrl(import.meta.url);
|
|
2028
2031
|
}
|
|
2029
2032
|
if (typeof __filename !== "undefined" && typeof __require2 !== "undefined") {
|
|
2030
2033
|
const { pathToFileURL } = __require2("url");
|
|
@@ -6209,6 +6212,12 @@ var HARBOR_TORCHES = Object.freeze([
|
|
|
6209
6212
|
Object.freeze({ x: -8.6, y: 2.48, z: -0.72, glow: 1 }),
|
|
6210
6213
|
Object.freeze({ x: -10.4, y: 1.28, z: 0.82, glow: 0.92 })
|
|
6211
6214
|
]);
|
|
6215
|
+
var FLAG_LAYOUT = Object.freeze({
|
|
6216
|
+
origin: Object.freeze({ x: -3.5, y: 5.9, z: 2.4 }),
|
|
6217
|
+
width: 4.8,
|
|
6218
|
+
height: 2.7,
|
|
6219
|
+
mastOffsetX: 1.8
|
|
6220
|
+
});
|
|
6212
6221
|
function injectStyles() {
|
|
6213
6222
|
if (document.getElementById(STYLE_ID)) {
|
|
6214
6223
|
return;
|
|
@@ -6781,6 +6790,250 @@ function normalizeColorOverride(color, fallback) {
|
|
|
6781
6790
|
function readVisualNumber(value, fallback) {
|
|
6782
6791
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
6783
6792
|
}
|
|
6793
|
+
function resolveClothPresentation(state, meshDetail) {
|
|
6794
|
+
const clothPlan = createClothRepresentationPlan({
|
|
6795
|
+
garmentId: "shore-flag",
|
|
6796
|
+
kind: state.focus === "cloth" ? "flag" : clothGarmentKinds[0],
|
|
6797
|
+
profile: state.focus === "cloth" ? "cinematic" : clothProfileNames[0],
|
|
6798
|
+
supportsRayTracing: true,
|
|
6799
|
+
nearFieldMaxMeters: 18,
|
|
6800
|
+
midFieldMaxMeters: 55,
|
|
6801
|
+
farFieldMaxMeters: 180
|
|
6802
|
+
});
|
|
6803
|
+
const preset = CAMERA_PRESETS[state.focus] ?? CAMERA_PRESETS.integrated;
|
|
6804
|
+
const fallbackEye = state.camera.eye ? state.camera.eye : addVec3(
|
|
6805
|
+
state.camera.target,
|
|
6806
|
+
vec3(
|
|
6807
|
+
Math.sin(state.camera.yaw ?? preset.yaw) * Math.cos(state.camera.pitch ?? preset.pitch) * (state.camera.distance ?? preset.distance),
|
|
6808
|
+
Math.sin(state.camera.pitch ?? preset.pitch) * (state.camera.distance ?? preset.distance),
|
|
6809
|
+
Math.cos(state.camera.yaw ?? preset.yaw) * Math.cos(state.camera.pitch ?? preset.pitch) * (state.camera.distance ?? preset.distance)
|
|
6810
|
+
)
|
|
6811
|
+
);
|
|
6812
|
+
const cameraDistance = lengthVec3(subVec3(state.camera.target, fallbackEye));
|
|
6813
|
+
const band = selectClothRepresentationBand(cameraDistance, clothPlan.thresholds);
|
|
6814
|
+
const representation = clothPlan.representations.find((entry) => entry.band === band) ?? clothPlan.representations[0];
|
|
6815
|
+
return {
|
|
6816
|
+
clothPlan,
|
|
6817
|
+
band,
|
|
6818
|
+
continuity: representation.continuity,
|
|
6819
|
+
representation
|
|
6820
|
+
};
|
|
6821
|
+
}
|
|
6822
|
+
function getFlagRestPosition(rows, cols, row, column) {
|
|
6823
|
+
const u = cols <= 1 ? 0 : column / (cols - 1);
|
|
6824
|
+
const v = rows <= 1 ? 0 : row / (rows - 1);
|
|
6825
|
+
return vec3(
|
|
6826
|
+
FLAG_LAYOUT.origin.x + u * FLAG_LAYOUT.mastOffsetX,
|
|
6827
|
+
FLAG_LAYOUT.origin.y - FLAG_LAYOUT.height * v - u * u * 0.08,
|
|
6828
|
+
FLAG_LAYOUT.origin.z + FLAG_LAYOUT.width * u
|
|
6829
|
+
);
|
|
6830
|
+
}
|
|
6831
|
+
function buildClothConstraints(rows, cols, restPositions) {
|
|
6832
|
+
const constraints = [];
|
|
6833
|
+
const indexFor = (row, column) => row * cols + column;
|
|
6834
|
+
const pushConstraint = (a, b, stiffness) => {
|
|
6835
|
+
constraints.push(
|
|
6836
|
+
Object.freeze({
|
|
6837
|
+
a,
|
|
6838
|
+
b,
|
|
6839
|
+
restLength: lengthVec3(subVec3(restPositions[a], restPositions[b])),
|
|
6840
|
+
stiffness
|
|
6841
|
+
})
|
|
6842
|
+
);
|
|
6843
|
+
};
|
|
6844
|
+
for (let row = 0; row < rows; row += 1) {
|
|
6845
|
+
for (let column = 0; column < cols; column += 1) {
|
|
6846
|
+
const index = indexFor(row, column);
|
|
6847
|
+
if (column + 1 < cols) {
|
|
6848
|
+
pushConstraint(index, indexFor(row, column + 1), 0.92);
|
|
6849
|
+
}
|
|
6850
|
+
if (row + 1 < rows) {
|
|
6851
|
+
pushConstraint(index, indexFor(row + 1, column), 0.9);
|
|
6852
|
+
}
|
|
6853
|
+
if (column + 1 < cols && row + 1 < rows) {
|
|
6854
|
+
pushConstraint(index, indexFor(row + 1, column + 1), 0.66);
|
|
6855
|
+
}
|
|
6856
|
+
if (column - 1 >= 0 && row + 1 < rows) {
|
|
6857
|
+
pushConstraint(index, indexFor(row + 1, column - 1), 0.66);
|
|
6858
|
+
}
|
|
6859
|
+
if (column + 2 < cols) {
|
|
6860
|
+
pushConstraint(index, indexFor(row, column + 2), 0.22);
|
|
6861
|
+
}
|
|
6862
|
+
if (row + 2 < rows) {
|
|
6863
|
+
pushConstraint(index, indexFor(row + 2, column), 0.18);
|
|
6864
|
+
}
|
|
6865
|
+
}
|
|
6866
|
+
}
|
|
6867
|
+
return Object.freeze(constraints);
|
|
6868
|
+
}
|
|
6869
|
+
function createShowcaseClothSimulationState(options = {}) {
|
|
6870
|
+
const rows = Math.max(4, options.rows ?? 11);
|
|
6871
|
+
const cols = Math.max(4, options.cols ?? 16);
|
|
6872
|
+
const continuity = options.continuity ?? {
|
|
6873
|
+
broadMotionFloor: 0.72,
|
|
6874
|
+
wrinkleFloor: 0.56
|
|
6875
|
+
};
|
|
6876
|
+
const representation = options.representation ?? {
|
|
6877
|
+
mesh: {
|
|
6878
|
+
solverIterations: 6,
|
|
6879
|
+
wrinkleLayers: 2
|
|
6880
|
+
}
|
|
6881
|
+
};
|
|
6882
|
+
const restPositions = [];
|
|
6883
|
+
const positions = [];
|
|
6884
|
+
const previousPositions = [];
|
|
6885
|
+
const uvs = [];
|
|
6886
|
+
const phaseOffsets = [];
|
|
6887
|
+
const pinned = [];
|
|
6888
|
+
for (let row = 0; row < rows; row += 1) {
|
|
6889
|
+
for (let column = 0; column < cols; column += 1) {
|
|
6890
|
+
const index = row * cols + column;
|
|
6891
|
+
const u = cols <= 1 ? 0 : column / (cols - 1);
|
|
6892
|
+
const v = rows <= 1 ? 0 : row / (rows - 1);
|
|
6893
|
+
const rest = getFlagRestPosition(rows, cols, row, column);
|
|
6894
|
+
const preload = vec3(
|
|
6895
|
+
u * 0.04,
|
|
6896
|
+
Math.sin(v * Math.PI) * 0.02 * continuity.wrinkleFloor,
|
|
6897
|
+
-u * 0.12
|
|
6898
|
+
);
|
|
6899
|
+
const pinnedPoint = column === 0;
|
|
6900
|
+
restPositions.push(rest);
|
|
6901
|
+
positions.push(pinnedPoint ? vec3(rest.x, rest.y, rest.z) : addVec3(rest, preload));
|
|
6902
|
+
previousPositions.push(
|
|
6903
|
+
pinnedPoint ? vec3(rest.x, rest.y, rest.z) : addVec3(rest, scaleVec3(preload, 0.35))
|
|
6904
|
+
);
|
|
6905
|
+
uvs.push(Object.freeze({ u, v }));
|
|
6906
|
+
phaseOffsets.push(pseudoRandom(index + 17) * Math.PI * 2);
|
|
6907
|
+
pinned.push(pinnedPoint);
|
|
6908
|
+
}
|
|
6909
|
+
}
|
|
6910
|
+
return {
|
|
6911
|
+
rows,
|
|
6912
|
+
cols,
|
|
6913
|
+
continuity,
|
|
6914
|
+
representation,
|
|
6915
|
+
restPositions,
|
|
6916
|
+
positions,
|
|
6917
|
+
previousPositions,
|
|
6918
|
+
constraints: buildClothConstraints(rows, cols, restPositions),
|
|
6919
|
+
indices: Object.freeze(
|
|
6920
|
+
Array.from({ length: (rows - 1) * (cols - 1) * 6 }, (_, listIndex) => listIndex).map((_, listIndex, source) => {
|
|
6921
|
+
if (listIndex >= source.length) {
|
|
6922
|
+
return 0;
|
|
6923
|
+
}
|
|
6924
|
+
const quadIndex = Math.floor(listIndex / 6);
|
|
6925
|
+
const quadColumn = quadIndex % (cols - 1);
|
|
6926
|
+
const quadRow = Math.floor(quadIndex / (cols - 1));
|
|
6927
|
+
const base = quadRow * cols + quadColumn;
|
|
6928
|
+
return [base, base + 1, base + cols + 1, base, base + cols + 1, base + cols][listIndex % 6];
|
|
6929
|
+
})
|
|
6930
|
+
),
|
|
6931
|
+
uvs,
|
|
6932
|
+
phaseOffsets,
|
|
6933
|
+
pinned
|
|
6934
|
+
};
|
|
6935
|
+
}
|
|
6936
|
+
function resetPinnedClothPoints(clothState) {
|
|
6937
|
+
for (let index = 0; index < clothState.positions.length; index += 1) {
|
|
6938
|
+
if (!clothState.pinned[index]) {
|
|
6939
|
+
continue;
|
|
6940
|
+
}
|
|
6941
|
+
const anchor = clothState.restPositions[index];
|
|
6942
|
+
clothState.positions[index] = vec3(anchor.x, anchor.y, anchor.z);
|
|
6943
|
+
clothState.previousPositions[index] = vec3(anchor.x, anchor.y, anchor.z);
|
|
6944
|
+
}
|
|
6945
|
+
}
|
|
6946
|
+
function satisfyClothConstraint(clothState, constraint) {
|
|
6947
|
+
const a = clothState.positions[constraint.a];
|
|
6948
|
+
const b = clothState.positions[constraint.b];
|
|
6949
|
+
const delta = subVec3(b, a);
|
|
6950
|
+
const distance = lengthVec3(delta);
|
|
6951
|
+
if (distance <= 1e-4) {
|
|
6952
|
+
return;
|
|
6953
|
+
}
|
|
6954
|
+
const correctionScale = (distance - constraint.restLength) / distance * 0.5 * constraint.stiffness;
|
|
6955
|
+
const correction = scaleVec3(delta, correctionScale);
|
|
6956
|
+
if (!clothState.pinned[constraint.a]) {
|
|
6957
|
+
clothState.positions[constraint.a] = addVec3(a, correction);
|
|
6958
|
+
}
|
|
6959
|
+
if (!clothState.pinned[constraint.b]) {
|
|
6960
|
+
clothState.positions[constraint.b] = subVec3(b, correction);
|
|
6961
|
+
}
|
|
6962
|
+
}
|
|
6963
|
+
function advanceShowcaseClothSimulationState(clothState, options = {}) {
|
|
6964
|
+
const dt = clamp(options.dt ?? 1 / 60, 1 / 240, 1 / 18);
|
|
6965
|
+
const time = readVisualNumber(options.time, 0);
|
|
6966
|
+
const flagMotion = readVisualNumber(options.flagMotion, 0.92);
|
|
6967
|
+
const waveInfluence = readVisualNumber(options.waveInfluence, 0);
|
|
6968
|
+
const wrinkleLayers = Math.max(1, clothState.representation.mesh?.wrinkleLayers ?? 2);
|
|
6969
|
+
const solverIterations = clamp(
|
|
6970
|
+
Math.round(clothState.representation.mesh?.solverIterations ?? 6),
|
|
6971
|
+
2,
|
|
6972
|
+
10
|
|
6973
|
+
);
|
|
6974
|
+
for (let index = 0; index < clothState.positions.length; index += 1) {
|
|
6975
|
+
if (clothState.pinned[index]) {
|
|
6976
|
+
continue;
|
|
6977
|
+
}
|
|
6978
|
+
const current = clothState.positions[index];
|
|
6979
|
+
const previous = clothState.previousPositions[index];
|
|
6980
|
+
const { u, v } = clothState.uvs[index];
|
|
6981
|
+
const phase = clothState.phaseOffsets[index];
|
|
6982
|
+
const broadMotion = clothState.continuity.broadMotionFloor;
|
|
6983
|
+
const wrinkleMotion = clothState.continuity.wrinkleFloor;
|
|
6984
|
+
const gustPhase = time * 2.1 + phase + u * 4.4 + v * 2.3;
|
|
6985
|
+
const wrinklePhase = time * 5.3 + phase * 0.72 + u * 9.6 + v * 7.1;
|
|
6986
|
+
const windDirection = normalizeVec3(
|
|
6987
|
+
vec3(
|
|
6988
|
+
0.18 + Math.sin(gustPhase) * (0.12 + broadMotion * 0.09),
|
|
6989
|
+
Math.cos(time * 1.4 + phase + v * 4.8) * 0.06 * wrinkleMotion,
|
|
6990
|
+
1 + Math.sin(gustPhase * 0.74) * 0.18
|
|
6991
|
+
)
|
|
6992
|
+
);
|
|
6993
|
+
const windStrength = (1.6 + broadMotion * 1.25 + wrinkleLayers * 0.12) * flagMotion * (0.44 + u * 1.14);
|
|
6994
|
+
const wrinkleForce = vec3(
|
|
6995
|
+
Math.sin(wrinklePhase) * 0.22 * wrinkleMotion * flagMotion,
|
|
6996
|
+
Math.cos(wrinklePhase * 0.7) * 0.08 * wrinkleMotion,
|
|
6997
|
+
Math.cos(wrinklePhase) * 0.14 * broadMotion * flagMotion
|
|
6998
|
+
);
|
|
6999
|
+
const acceleration = addVec3(
|
|
7000
|
+
vec3(0, -0.48 - u * 0.08, 0),
|
|
7001
|
+
addVec3(
|
|
7002
|
+
scaleVec3(windDirection, windStrength),
|
|
7003
|
+
addVec3(
|
|
7004
|
+
wrinkleForce,
|
|
7005
|
+
vec3(waveInfluence * (0.04 + u * 0.08), 0, waveInfluence * 0.16)
|
|
7006
|
+
)
|
|
7007
|
+
)
|
|
7008
|
+
);
|
|
7009
|
+
const inertia = scaleVec3(subVec3(current, previous), 0.987);
|
|
7010
|
+
const next = addVec3(addVec3(current, inertia), scaleVec3(acceleration, dt * dt));
|
|
7011
|
+
clothState.previousPositions[index] = vec3(current.x, current.y, current.z);
|
|
7012
|
+
clothState.positions[index] = next;
|
|
7013
|
+
}
|
|
7014
|
+
resetPinnedClothPoints(clothState);
|
|
7015
|
+
for (let iteration = 0; iteration < solverIterations; iteration += 1) {
|
|
7016
|
+
for (const constraint of clothState.constraints) {
|
|
7017
|
+
satisfyClothConstraint(clothState, constraint);
|
|
7018
|
+
}
|
|
7019
|
+
resetPinnedClothPoints(clothState);
|
|
7020
|
+
}
|
|
7021
|
+
return clothState;
|
|
7022
|
+
}
|
|
7023
|
+
function ensureShowcaseClothState(state, meshDetail, clothPresentation) {
|
|
7024
|
+
if (!state.clothState || state.clothState.rows !== meshDetail.rows || state.clothState.cols !== meshDetail.cols) {
|
|
7025
|
+
state.clothState = createShowcaseClothSimulationState({
|
|
7026
|
+
rows: meshDetail.rows,
|
|
7027
|
+
cols: meshDetail.cols,
|
|
7028
|
+
continuity: clothPresentation.continuity,
|
|
7029
|
+
representation: clothPresentation.representation
|
|
7030
|
+
});
|
|
7031
|
+
} else {
|
|
7032
|
+
state.clothState.continuity = clothPresentation.continuity;
|
|
7033
|
+
state.clothState.representation = clothPresentation.representation;
|
|
7034
|
+
}
|
|
7035
|
+
return state.clothState;
|
|
7036
|
+
}
|
|
6784
7037
|
function resolveVisualConfig(nearLighting, lightingSnapshot, customVisuals = {}) {
|
|
6785
7038
|
const premiumShadows = nearLighting.primaryShadowSource === "ray-traced-primary";
|
|
6786
7039
|
const defaults = {
|
|
@@ -6864,58 +7117,17 @@ function resolveVisualConfig(nearLighting, lightingSnapshot, customVisuals = {})
|
|
|
6864
7117
|
};
|
|
6865
7118
|
}
|
|
6866
7119
|
function buildClothSurface(model, state, meshDetail, visuals) {
|
|
6867
|
-
const
|
|
6868
|
-
|
|
6869
|
-
kind: state.focus === "cloth" ? "flag" : clothGarmentKinds[0],
|
|
6870
|
-
profile: state.focus === "cloth" ? "cinematic" : clothProfileNames[0],
|
|
6871
|
-
supportsRayTracing: true,
|
|
6872
|
-
nearFieldMaxMeters: 18,
|
|
6873
|
-
midFieldMaxMeters: 55,
|
|
6874
|
-
farFieldMaxMeters: 180
|
|
6875
|
-
});
|
|
6876
|
-
const cameraDistance = lengthVec3(subVec3(state.camera.target, state.camera.eye ?? vec3(...CAMERA_PRESETS[state.focus].target)));
|
|
6877
|
-
const band = selectClothRepresentationBand(cameraDistance, clothPlan.thresholds);
|
|
6878
|
-
const representation = clothPlan.representations.find((entry) => entry.band === band) ?? clothPlan.representations[0];
|
|
6879
|
-
const continuity = createClothContinuityEnvelope({ garmentId: "shore-flag" });
|
|
6880
|
-
const cols = meshDetail.cols;
|
|
6881
|
-
const rows = meshDetail.rows;
|
|
6882
|
-
const origin = vec3(-3.5, 5.9, 2.4);
|
|
6883
|
-
const width = 4.8;
|
|
6884
|
-
const height = 2.7;
|
|
6885
|
-
const positions = [];
|
|
6886
|
-
const indices = [];
|
|
6887
|
-
const time = state.time;
|
|
6888
|
-
for (let row = 0; row < rows; row += 1) {
|
|
6889
|
-
for (let column = 0; column < cols; column += 1) {
|
|
6890
|
-
const u = column / (cols - 1);
|
|
6891
|
-
const v = row / (rows - 1);
|
|
6892
|
-
const gust = Math.sin(time * 1.9 + v * 3.2 + u * 2.1) * continuity.broadMotionFloor * visuals.flagMotion;
|
|
6893
|
-
const wrinkle = Math.sin(time * 4.4 + u * 9.2 + v * 5.6) * continuity.wrinkleFloor * 0.22 * Math.max(0.55, visuals.flagMotion);
|
|
6894
|
-
const x = origin.x + u * 1.8 + gust * 0.55 * (u * 0.9);
|
|
6895
|
-
const y = origin.y - height * v + wrinkle * 0.2;
|
|
6896
|
-
const z = origin.z + width * u + gust * 0.72 * (u * 0.85);
|
|
6897
|
-
const flap = Math.cos(time * 2.7 + u * 7.4 + v * 3.8) * continuity.broadMotionFloor * 0.28 * visuals.flagMotion;
|
|
6898
|
-
positions.push(vec3(x + flap, y, z));
|
|
6899
|
-
}
|
|
6900
|
-
}
|
|
6901
|
-
for (let row = 0; row < rows - 1; row += 1) {
|
|
6902
|
-
for (let column = 0; column < cols - 1; column += 1) {
|
|
6903
|
-
const a = row * cols + column;
|
|
6904
|
-
const b = a + 1;
|
|
6905
|
-
const c = a + cols + 1;
|
|
6906
|
-
const d = a + cols;
|
|
6907
|
-
indices.push(a, b, c, a, c, d);
|
|
6908
|
-
}
|
|
6909
|
-
}
|
|
7120
|
+
const clothPresentation = resolveClothPresentation(state, meshDetail);
|
|
7121
|
+
const clothState = ensureShowcaseClothState(state, meshDetail, clothPresentation);
|
|
6910
7122
|
return {
|
|
6911
|
-
clothPlan,
|
|
6912
|
-
band,
|
|
6913
|
-
representation,
|
|
6914
|
-
continuity,
|
|
7123
|
+
clothPlan: clothPresentation.clothPlan,
|
|
7124
|
+
band: clothPresentation.band,
|
|
7125
|
+
representation: clothPresentation.representation,
|
|
7126
|
+
continuity: clothPresentation.continuity,
|
|
6915
7127
|
color: visuals.flagColor,
|
|
6916
|
-
positions,
|
|
6917
|
-
indices,
|
|
6918
|
-
grid: { rows, cols }
|
|
7128
|
+
positions: clothState.positions.map((point) => vec3(point.x, point.y, point.z)),
|
|
7129
|
+
indices: clothState.indices,
|
|
7130
|
+
grid: { rows: clothState.rows, cols: clothState.cols }
|
|
6919
7131
|
};
|
|
6920
7132
|
}
|
|
6921
7133
|
function resolveWaveDirection(state) {
|
|
@@ -6979,6 +7191,59 @@ function sampleWave(state, x, z, time) {
|
|
|
6979
7191
|
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;
|
|
6980
7192
|
return base * amplitude + sampleShipWake(state, x, z, time) + sampleWaveImpulses(state, x, z, time);
|
|
6981
7193
|
}
|
|
7194
|
+
function buildWaterMotionEffects(state) {
|
|
7195
|
+
const wakeTrails = [];
|
|
7196
|
+
const rippleRings = state.waveImpulses.map((impulse) => {
|
|
7197
|
+
const radius = impulse.radius + (1 - impulse.life) * 4.8;
|
|
7198
|
+
return Object.freeze({
|
|
7199
|
+
center: vec3(
|
|
7200
|
+
impulse.x,
|
|
7201
|
+
sampleWave(state, impulse.x, impulse.z, state.time) * 0.24 + 0.06,
|
|
7202
|
+
impulse.z
|
|
7203
|
+
),
|
|
7204
|
+
radius,
|
|
7205
|
+
opacity: clamp(impulse.life * 0.28, 0.08, 0.3)
|
|
7206
|
+
});
|
|
7207
|
+
});
|
|
7208
|
+
for (const ship of state.ships) {
|
|
7209
|
+
const speed = Math.hypot(ship.velocity.x, ship.velocity.z);
|
|
7210
|
+
if (speed <= 0.18) {
|
|
7211
|
+
continue;
|
|
7212
|
+
}
|
|
7213
|
+
const direction = normalizeVec3(vec3(ship.velocity.x, 0, ship.velocity.z));
|
|
7214
|
+
const behind = scaleVec3(direction, -1);
|
|
7215
|
+
const lateral = vec3(-direction.z, 0, direction.x);
|
|
7216
|
+
const points = [];
|
|
7217
|
+
for (let sampleIndex = 0; sampleIndex < 6; sampleIndex += 1) {
|
|
7218
|
+
const along = 1 + sampleIndex * 1.45;
|
|
7219
|
+
const lateralOffset = Math.sin(state.time * 1.2 + sampleIndex * 0.8 + readVisualNumber(ship.wanderPhase, 0)) * 0.12;
|
|
7220
|
+
const worldPoint = addVec3(
|
|
7221
|
+
ship.position,
|
|
7222
|
+
addVec3(scaleVec3(behind, along), scaleVec3(lateral, lateralOffset))
|
|
7223
|
+
);
|
|
7224
|
+
points.push(
|
|
7225
|
+
Object.freeze({
|
|
7226
|
+
center: vec3(
|
|
7227
|
+
worldPoint.x,
|
|
7228
|
+
sampleWave(state, worldPoint.x, worldPoint.z, state.time) * 0.24 + 0.04,
|
|
7229
|
+
worldPoint.z
|
|
7230
|
+
),
|
|
7231
|
+
width: 0.34 + sampleIndex * 0.13
|
|
7232
|
+
})
|
|
7233
|
+
);
|
|
7234
|
+
}
|
|
7235
|
+
wakeTrails.push(
|
|
7236
|
+
Object.freeze({
|
|
7237
|
+
opacity: clamp(0.18 + speed * 0.09, 0.22, 0.46),
|
|
7238
|
+
points: Object.freeze(points)
|
|
7239
|
+
})
|
|
7240
|
+
);
|
|
7241
|
+
}
|
|
7242
|
+
return Object.freeze({
|
|
7243
|
+
wakeTrails: Object.freeze(wakeTrails),
|
|
7244
|
+
rippleRings: Object.freeze(rippleRings)
|
|
7245
|
+
});
|
|
7246
|
+
}
|
|
6982
7247
|
function buildWaterBands(state, fluidDetail, visuals) {
|
|
6983
7248
|
const fluidPlan = createFluidRepresentationPlan({
|
|
6984
7249
|
fluidBodyId: "harbor",
|
|
@@ -7131,6 +7396,7 @@ function createSceneState(options) {
|
|
|
7131
7396
|
contactCount: 0,
|
|
7132
7397
|
collisionCount: 0,
|
|
7133
7398
|
collisionFlash: 0,
|
|
7399
|
+
clothState: null,
|
|
7134
7400
|
physics: {
|
|
7135
7401
|
profile: physicsProfile,
|
|
7136
7402
|
plan: physicsPlan,
|
|
@@ -7766,16 +8032,73 @@ function renderFlagShadow(ctx, cloth, camera, viewport, lightDir, shadowStrength
|
|
|
7766
8032
|
blur: 12 + shadowStrength * 20
|
|
7767
8033
|
});
|
|
7768
8034
|
}
|
|
7769
|
-
function
|
|
7770
|
-
const
|
|
8035
|
+
function collectSceneLightSources(state, visuals) {
|
|
8036
|
+
const directLights = [];
|
|
8037
|
+
const reflectionLights = [];
|
|
8038
|
+
const pushLight = (point, glowScale, reflectionStrength, coreColor, glowColor) => {
|
|
8039
|
+
directLights.push(
|
|
8040
|
+
Object.freeze({
|
|
8041
|
+
pass: "direct-glow",
|
|
8042
|
+
point,
|
|
8043
|
+
coreColor,
|
|
8044
|
+
glowColor,
|
|
8045
|
+
glowScale
|
|
8046
|
+
})
|
|
8047
|
+
);
|
|
8048
|
+
if (reflectionStrength > 0) {
|
|
8049
|
+
reflectionLights.push(
|
|
8050
|
+
Object.freeze({
|
|
8051
|
+
pass: "water-reflection",
|
|
8052
|
+
point,
|
|
8053
|
+
coreColor,
|
|
8054
|
+
glowColor,
|
|
8055
|
+
glowScale,
|
|
8056
|
+
reflectionStrength
|
|
8057
|
+
})
|
|
8058
|
+
);
|
|
8059
|
+
}
|
|
8060
|
+
};
|
|
8061
|
+
for (const torch of HARBOR_TORCHES) {
|
|
8062
|
+
pushLight(
|
|
8063
|
+
vec3(torch.x, torch.y, torch.z),
|
|
8064
|
+
torch.glow,
|
|
8065
|
+
visuals.lanternReflectionStrength * 0.55,
|
|
8066
|
+
visuals.torchCore,
|
|
8067
|
+
visuals.torchGlow
|
|
8068
|
+
);
|
|
8069
|
+
}
|
|
8070
|
+
for (const ship of state.ships) {
|
|
8071
|
+
const lanterns = Array.isArray(ship.lanterns) ? ship.lanterns : SHIP_LANTERNS;
|
|
8072
|
+
const strength = readVisualNumber(ship.lanternStrength, 1);
|
|
8073
|
+
for (const lantern of lanterns) {
|
|
8074
|
+
const point = transformPoint(
|
|
8075
|
+
vec3(lantern.x, lantern.y, lantern.z),
|
|
8076
|
+
{ position: ship.position, rotationY: ship.rotationY, scale: SHIP_SCALE }
|
|
8077
|
+
);
|
|
8078
|
+
pushLight(
|
|
8079
|
+
point,
|
|
8080
|
+
lantern.glow * strength,
|
|
8081
|
+
visuals.lanternReflectionStrength,
|
|
8082
|
+
visuals.lanternCore,
|
|
8083
|
+
visuals.lanternGlow
|
|
8084
|
+
);
|
|
8085
|
+
}
|
|
8086
|
+
}
|
|
8087
|
+
return Object.freeze({
|
|
8088
|
+
directLights: Object.freeze(directLights),
|
|
8089
|
+
reflectionLights: Object.freeze(reflectionLights)
|
|
8090
|
+
});
|
|
8091
|
+
}
|
|
8092
|
+
function renderDirectLightGlow(ctx, source, camera, viewport) {
|
|
8093
|
+
const projected = projectPoint(source.point, camera, viewport);
|
|
7771
8094
|
if (!projected) {
|
|
7772
8095
|
return;
|
|
7773
8096
|
}
|
|
7774
|
-
const radius = clamp(1 / projected.depth * 420 * glowScale, 4, 34);
|
|
8097
|
+
const radius = clamp(1 / projected.depth * 420 * source.glowScale, 4, 34);
|
|
7775
8098
|
const halo = ctx.createRadialGradient(projected.x, projected.y, radius * 0.12, projected.x, projected.y, radius);
|
|
7776
|
-
halo.addColorStop(0, colorToRgba(coreColor, 0.98));
|
|
7777
|
-
halo.addColorStop(0.5, colorToRgba(glowColor, 0.42));
|
|
7778
|
-
halo.addColorStop(1, colorToRgba(glowColor, 0));
|
|
8099
|
+
halo.addColorStop(0, colorToRgba(source.coreColor, 0.98));
|
|
8100
|
+
halo.addColorStop(0.5, colorToRgba(source.glowColor, 0.42));
|
|
8101
|
+
halo.addColorStop(1, colorToRgba(source.glowColor, 0));
|
|
7779
8102
|
ctx.save();
|
|
7780
8103
|
ctx.globalCompositeOperation = "screen";
|
|
7781
8104
|
ctx.fillStyle = halo;
|
|
@@ -7783,79 +8106,119 @@ function renderGlowLight(ctx, point, camera, viewport, coreColor, glowColor, glo
|
|
|
7783
8106
|
ctx.arc(projected.x, projected.y, radius, 0, Math.PI * 2);
|
|
7784
8107
|
ctx.fill();
|
|
7785
8108
|
ctx.restore();
|
|
7786
|
-
ctx.fillStyle = colorToRgba(coreColor, 0.98);
|
|
8109
|
+
ctx.fillStyle = colorToRgba(source.coreColor, 0.98);
|
|
7787
8110
|
ctx.beginPath();
|
|
7788
8111
|
ctx.arc(projected.x, projected.y, Math.max(1.2, radius * 0.16), 0, Math.PI * 2);
|
|
7789
8112
|
ctx.fill();
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
8113
|
+
}
|
|
8114
|
+
function renderWaterLightReflection(ctx, source, state, camera, viewport) {
|
|
8115
|
+
const projected = projectPoint(source.point, camera, viewport);
|
|
8116
|
+
if (!projected) {
|
|
8117
|
+
return;
|
|
8118
|
+
}
|
|
8119
|
+
const radius = clamp(1 / projected.depth * 420 * source.glowScale, 4, 34);
|
|
8120
|
+
const waterline = sampleWave(state, source.point.x, source.point.z, state.time) * 0.22;
|
|
8121
|
+
const reflectedPoint = vec3(
|
|
8122
|
+
source.point.x,
|
|
8123
|
+
waterline - (source.point.y - waterline) * 0.58,
|
|
8124
|
+
source.point.z + 0.08
|
|
8125
|
+
);
|
|
8126
|
+
const reflected = projectPoint(reflectedPoint, camera, viewport);
|
|
8127
|
+
if (!reflected) {
|
|
8128
|
+
return;
|
|
8129
|
+
}
|
|
8130
|
+
const reflectionRadius = radius * 0.72;
|
|
8131
|
+
const glow = ctx.createRadialGradient(
|
|
8132
|
+
reflected.x,
|
|
8133
|
+
reflected.y,
|
|
8134
|
+
reflectionRadius * 0.1,
|
|
8135
|
+
reflected.x,
|
|
8136
|
+
reflected.y,
|
|
8137
|
+
reflectionRadius
|
|
8138
|
+
);
|
|
8139
|
+
glow.addColorStop(0, colorToRgba(source.coreColor, source.reflectionStrength * 0.34));
|
|
8140
|
+
glow.addColorStop(1, colorToRgba(source.glowColor, 0));
|
|
8141
|
+
ctx.save();
|
|
8142
|
+
ctx.globalCompositeOperation = "screen";
|
|
8143
|
+
ctx.fillStyle = glow;
|
|
8144
|
+
ctx.beginPath();
|
|
8145
|
+
ctx.ellipse(
|
|
8146
|
+
reflected.x,
|
|
8147
|
+
reflected.y,
|
|
8148
|
+
reflectionRadius * 0.34,
|
|
8149
|
+
reflectionRadius,
|
|
8150
|
+
0,
|
|
8151
|
+
0,
|
|
8152
|
+
Math.PI * 2
|
|
8153
|
+
);
|
|
8154
|
+
ctx.fill();
|
|
8155
|
+
ctx.restore();
|
|
8156
|
+
}
|
|
8157
|
+
function renderWaterMotionEffects(ctx, effects, camera, viewport) {
|
|
8158
|
+
ctx.save();
|
|
8159
|
+
ctx.globalCompositeOperation = "screen";
|
|
8160
|
+
for (const wake of effects.wakeTrails) {
|
|
8161
|
+
const projected = wake.points.map((point) => ({
|
|
8162
|
+
projected: projectPoint(point.center, camera, viewport),
|
|
8163
|
+
width: point.width
|
|
8164
|
+
})).filter((entry) => entry.projected);
|
|
8165
|
+
if (projected.length < 2) {
|
|
8166
|
+
continue;
|
|
8167
|
+
}
|
|
8168
|
+
const averageDepth = projected.reduce((total, entry) => total + entry.projected.depth, 0) / projected.length;
|
|
8169
|
+
const averageWidth = projected.reduce((total, entry) => total + entry.width, 0) / projected.length;
|
|
8170
|
+
const baseWidth = clamp(averageWidth / Math.max(0.25, averageDepth) * 180, 1.6, 5.4);
|
|
8171
|
+
ctx.strokeStyle = `rgba(146, 194, 236, ${wake.opacity * 0.52})`;
|
|
8172
|
+
ctx.lineWidth = baseWidth * 1.9;
|
|
8173
|
+
ctx.lineCap = "round";
|
|
8174
|
+
ctx.lineJoin = "round";
|
|
8175
|
+
ctx.beginPath();
|
|
8176
|
+
ctx.moveTo(projected[0].projected.x, projected[0].projected.y);
|
|
8177
|
+
for (let index = 1; index < projected.length; index += 1) {
|
|
8178
|
+
ctx.lineTo(projected[index].projected.x, projected[index].projected.y);
|
|
8179
|
+
}
|
|
8180
|
+
ctx.stroke();
|
|
8181
|
+
ctx.strokeStyle = `rgba(234, 247, 255, ${wake.opacity})`;
|
|
8182
|
+
ctx.lineWidth = baseWidth;
|
|
8183
|
+
ctx.lineCap = "round";
|
|
8184
|
+
ctx.lineJoin = "round";
|
|
8185
|
+
ctx.beginPath();
|
|
8186
|
+
ctx.moveTo(projected[0].projected.x, projected[0].projected.y);
|
|
8187
|
+
for (let index = 1; index < projected.length; index += 1) {
|
|
8188
|
+
ctx.lineTo(projected[index].projected.x, projected[index].projected.y);
|
|
8189
|
+
}
|
|
8190
|
+
ctx.stroke();
|
|
8191
|
+
for (const entry of projected.slice(1, 5)) {
|
|
8192
|
+
ctx.fillStyle = `rgba(239, 248, 255, ${wake.opacity * 0.76})`;
|
|
7809
8193
|
ctx.beginPath();
|
|
7810
8194
|
ctx.ellipse(
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
8195
|
+
entry.projected.x,
|
|
8196
|
+
entry.projected.y,
|
|
8197
|
+
baseWidth * 0.72,
|
|
8198
|
+
baseWidth * 0.44,
|
|
7815
8199
|
0,
|
|
7816
8200
|
0,
|
|
7817
8201
|
Math.PI * 2
|
|
7818
8202
|
);
|
|
7819
8203
|
ctx.fill();
|
|
7820
|
-
ctx.restore();
|
|
7821
8204
|
}
|
|
7822
8205
|
}
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
);
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
visuals.lanternCore,
|
|
7838
|
-
visuals.lanternGlow,
|
|
7839
|
-
lantern.glow * strength,
|
|
7840
|
-
visuals.lanternReflectionStrength,
|
|
7841
|
-
state
|
|
7842
|
-
);
|
|
7843
|
-
}
|
|
7844
|
-
}
|
|
7845
|
-
function renderHarborTorches(ctx, state, camera, viewport, visuals) {
|
|
7846
|
-
for (const torch of HARBOR_TORCHES) {
|
|
7847
|
-
renderGlowLight(
|
|
7848
|
-
ctx,
|
|
7849
|
-
vec3(torch.x, torch.y, torch.z),
|
|
7850
|
-
camera,
|
|
7851
|
-
viewport,
|
|
7852
|
-
visuals.torchCore,
|
|
7853
|
-
visuals.torchGlow,
|
|
7854
|
-
torch.glow,
|
|
7855
|
-
visuals.lanternReflectionStrength * 0.55,
|
|
7856
|
-
state
|
|
7857
|
-
);
|
|
8206
|
+
for (const ring of effects.rippleRings) {
|
|
8207
|
+
const center = projectPoint(ring.center, camera, viewport);
|
|
8208
|
+
const xAxis = projectPoint(addVec3(ring.center, vec3(ring.radius, 0, 0)), camera, viewport);
|
|
8209
|
+
const zAxis = projectPoint(addVec3(ring.center, vec3(0, 0, ring.radius)), camera, viewport);
|
|
8210
|
+
if (!center || !xAxis || !zAxis) {
|
|
8211
|
+
continue;
|
|
8212
|
+
}
|
|
8213
|
+
const radiusX = Math.hypot(xAxis.x - center.x, xAxis.y - center.y);
|
|
8214
|
+
const radiusY = Math.hypot(zAxis.x - center.x, zAxis.y - center.y);
|
|
8215
|
+
ctx.strokeStyle = `rgba(216, 235, 255, ${ring.opacity})`;
|
|
8216
|
+
ctx.lineWidth = clamp((radiusX + radiusY) * 0.02, 1, 3.1);
|
|
8217
|
+
ctx.beginPath();
|
|
8218
|
+
ctx.ellipse(center.x, center.y, radiusX, radiusY, 0, 0, Math.PI * 2);
|
|
8219
|
+
ctx.stroke();
|
|
7858
8220
|
}
|
|
8221
|
+
ctx.restore();
|
|
7859
8222
|
}
|
|
7860
8223
|
function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
7861
8224
|
const viewport = { width: canvas.width, height: canvas.height };
|
|
@@ -7885,8 +8248,8 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
7885
8248
|
shadowStrength,
|
|
7886
8249
|
visuals
|
|
7887
8250
|
);
|
|
7888
|
-
const
|
|
7889
|
-
|
|
8251
|
+
const waterTriangles = [];
|
|
8252
|
+
const sceneTriangles = [];
|
|
7890
8253
|
const water = buildWaterBands(
|
|
7891
8254
|
state,
|
|
7892
8255
|
state.fluidDetail.getSnapshot().currentLevel.config,
|
|
@@ -7903,7 +8266,7 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
7903
8266
|
if (projected.some((value) => value === null)) {
|
|
7904
8267
|
continue;
|
|
7905
8268
|
}
|
|
7906
|
-
|
|
8269
|
+
waterTriangles.push({
|
|
7907
8270
|
points: projected,
|
|
7908
8271
|
depth: (projected[0].depth + projected[1].depth + projected[2].depth) / 3,
|
|
7909
8272
|
worldCenter: scaleVec3(addVec3(addVec3(a, b), c), 1 / 3),
|
|
@@ -7913,6 +8276,9 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
7913
8276
|
});
|
|
7914
8277
|
}
|
|
7915
8278
|
}
|
|
8279
|
+
const waterMotionEffects = buildWaterMotionEffects(state);
|
|
8280
|
+
const lightSources = collectSceneLightSources(state, visuals);
|
|
8281
|
+
pushHarborGeometry(camera, viewport, sceneTriangles, visuals);
|
|
7916
8282
|
const cloth = buildClothSurface(
|
|
7917
8283
|
state,
|
|
7918
8284
|
state,
|
|
@@ -7928,7 +8294,7 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
7928
8294
|
if (projected.some((value) => value === null)) {
|
|
7929
8295
|
continue;
|
|
7930
8296
|
}
|
|
7931
|
-
|
|
8297
|
+
sceneTriangles.push({
|
|
7932
8298
|
points: projected,
|
|
7933
8299
|
depth: (projected[0].depth + projected[1].depth + projected[2].depth) / 3,
|
|
7934
8300
|
worldCenter: scaleVec3(addVec3(addVec3(a, b), c), 1 / 3),
|
|
@@ -7944,22 +8310,28 @@ function renderScene(ctx, canvas, state, shipModel, dom) {
|
|
|
7944
8310
|
ship.tint,
|
|
7945
8311
|
camera,
|
|
7946
8312
|
viewport,
|
|
7947
|
-
|
|
8313
|
+
sceneTriangles,
|
|
7948
8314
|
nearLighting.rtParticipation.directShadows === "premium" ? 0.08 : 0.02
|
|
7949
8315
|
);
|
|
7950
8316
|
}
|
|
8317
|
+
drawTriangles(ctx, waterTriangles, lightDir, reflectionStrength, camera, shadowStrength);
|
|
7951
8318
|
for (const ship of state.ships) {
|
|
7952
8319
|
renderShipShadow(ctx, shipModel, ship, state, camera, viewport, lightDir, shadowStrength);
|
|
7953
8320
|
}
|
|
7954
8321
|
renderFlagShadow(ctx, cloth, camera, viewport, lightDir, shadowStrength);
|
|
7955
|
-
|
|
8322
|
+
for (const source of lightSources.reflectionLights) {
|
|
8323
|
+
renderWaterLightReflection(ctx, source, state, camera, viewport);
|
|
8324
|
+
}
|
|
8325
|
+
renderWaterMotionEffects(ctx, waterMotionEffects, camera, viewport);
|
|
7956
8326
|
renderWaterHighlights(ctx, water.bandMeshes, camera, viewport);
|
|
7957
|
-
|
|
8327
|
+
drawTriangles(ctx, sceneTriangles, lightDir, reflectionStrength, camera, shadowStrength);
|
|
7958
8328
|
renderFlagPole(ctx, camera, viewport);
|
|
7959
8329
|
renderClothAccent(ctx, cloth, camera, viewport);
|
|
8330
|
+
for (const source of lightSources.directLights) {
|
|
8331
|
+
renderDirectLightGlow(ctx, source, camera, viewport);
|
|
8332
|
+
}
|
|
7960
8333
|
for (const ship of state.ships) {
|
|
7961
8334
|
renderShipRigging(ctx, ship, camera, viewport);
|
|
7962
|
-
renderShipLanterns(ctx, ship, state, camera, viewport, visuals);
|
|
7963
8335
|
}
|
|
7964
8336
|
renderSprays(ctx, state.sprays, camera, viewport);
|
|
7965
8337
|
const debugSnapshot = state.debugSession.getSnapshot();
|
|
@@ -8021,6 +8393,21 @@ function updateSceneState(state, dt, shipModel) {
|
|
|
8021
8393
|
updateShips(state, dt, shipModel);
|
|
8022
8394
|
updateWaveImpulses(state, dt);
|
|
8023
8395
|
updateSpray(state, dt);
|
|
8396
|
+
const clothPresentation = resolveClothPresentation(
|
|
8397
|
+
state,
|
|
8398
|
+
state.clothDetail.getSnapshot().currentLevel.config
|
|
8399
|
+
);
|
|
8400
|
+
const clothState = ensureShowcaseClothState(
|
|
8401
|
+
state,
|
|
8402
|
+
state.clothDetail.getSnapshot().currentLevel.config,
|
|
8403
|
+
clothPresentation
|
|
8404
|
+
);
|
|
8405
|
+
advanceShowcaseClothSimulationState(clothState, {
|
|
8406
|
+
dt,
|
|
8407
|
+
time: state.time,
|
|
8408
|
+
flagMotion: readVisualNumber(state.demoVisuals?.flagMotion, 0.92),
|
|
8409
|
+
waveInfluence: sampleWave(state, FLAG_LAYOUT.origin.x + FLAG_LAYOUT.width * 0.55, FLAG_LAYOUT.origin.z + FLAG_LAYOUT.width * 0.48, state.time)
|
|
8410
|
+
});
|
|
8024
8411
|
updatePhysicsSnapshot(state, shipModel);
|
|
8025
8412
|
}
|
|
8026
8413
|
function syncTextState(state, shipModel) {
|
|
@@ -8188,7 +8575,11 @@ function updatePhysicsSnapshot(state, shipModel) {
|
|
|
8188
8575
|
});
|
|
8189
8576
|
}
|
|
8190
8577
|
export {
|
|
8578
|
+
advanceShowcaseClothSimulationState as __testOnlyAdvanceShowcaseClothSimulationState,
|
|
8579
|
+
buildWaterMotionEffects as __testOnlyBuildWaterMotionEffects,
|
|
8580
|
+
collectSceneLightSources as __testOnlyCollectSceneLightSources,
|
|
8581
|
+
createShowcaseClothSimulationState as __testOnlyCreateShowcaseClothSimulationState,
|
|
8191
8582
|
mountGpuShowcase,
|
|
8192
8583
|
showcaseFocusModes
|
|
8193
8584
|
};
|
|
8194
|
-
//# sourceMappingURL=showcase-runtime-
|
|
8585
|
+
//# sourceMappingURL=showcase-runtime-55OVDYWT.js.map
|