Spaces:
Running
Running
Update viewer.js
Browse files
viewer.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
| 1 |
-
// viewer.js
|
| 2 |
|
| 3 |
-
let pc; // PlayCanvas
|
| 4 |
export let app = null;
|
| 5 |
let cameraEntity = null;
|
| 6 |
let modelEntity = null;
|
| 7 |
let viewerInitialized = false;
|
| 8 |
let resizeObserver = null;
|
| 9 |
-
let loadTimeout = null; //
|
| 10 |
|
| 11 |
let chosenCameraX, chosenCameraY, chosenCameraZ;
|
| 12 |
let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, minY;
|
| 13 |
let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
|
| 14 |
let plyUrl, glbUrl;
|
| 15 |
|
| 16 |
-
// iOS detection
|
| 17 |
function isIOS() {
|
| 18 |
return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
| 19 |
}
|
|
@@ -25,7 +24,7 @@ function logAndAlert(msg) {
|
|
| 25 |
export async function initializeViewer(config, instanceId) {
|
| 26 |
if (viewerInitialized) return;
|
| 27 |
|
| 28 |
-
//
|
| 29 |
plyUrl = config.ply_url;
|
| 30 |
glbUrl = config.glb_url;
|
| 31 |
minZoom = parseFloat(config.minZoom || "1");
|
|
@@ -57,7 +56,7 @@ export async function initializeViewer(config, instanceId) {
|
|
| 57 |
chosenCameraY = mobile ? cameraYPhone : cameraY;
|
| 58 |
chosenCameraZ = mobile ? cameraZPhone : cameraZ;
|
| 59 |
|
| 60 |
-
// DOM
|
| 61 |
const canvasId = 'canvas-' + instanceId;
|
| 62 |
const progressDialog = document.getElementById('progress-dialog-' + instanceId);
|
| 63 |
const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
|
|
@@ -87,7 +86,6 @@ export async function initializeViewer(config, instanceId) {
|
|
| 87 |
|
| 88 |
progressDialog.style.display = 'block';
|
| 89 |
|
| 90 |
-
// PlayCanvas
|
| 91 |
if (!pc) {
|
| 92 |
pc = await import("https://esm.run/playcanvas");
|
| 93 |
window.pc = pc;
|
|
@@ -96,6 +94,7 @@ export async function initializeViewer(config, instanceId) {
|
|
| 96 |
|
| 97 |
try {
|
| 98 |
logAndAlert('[viewer.js] Creating graphics device...');
|
|
|
|
| 99 |
const device = await pc.createGraphicsDevice(canvas, {
|
| 100 |
deviceTypes: ["webgl2"],
|
| 101 |
glslangUrl: "https://playcanvas.vercel.app/static/lib/glslang/glslang.js",
|
|
@@ -104,7 +103,6 @@ export async function initializeViewer(config, instanceId) {
|
|
| 104 |
preserveDrawingBuffer: isIOS() ? true : false,
|
| 105 |
alpha: false
|
| 106 |
});
|
| 107 |
-
logAndAlert('[viewer.js] Graphics device created!');
|
| 108 |
device.maxPixelRatio = Math.min(window.devicePixelRatio, 2);
|
| 109 |
|
| 110 |
const opts = new pc.AppOptions();
|
|
@@ -127,12 +125,17 @@ export async function initializeViewer(config, instanceId) {
|
|
| 127 |
pc.GSplatHandler
|
| 128 |
];
|
| 129 |
|
| 130 |
-
|
|
|
|
|
|
|
| 131 |
app.setCanvasFillMode(pc.FILLMODE_NONE);
|
| 132 |
app.setCanvasResolution(pc.RESOLUTION_AUTO);
|
|
|
|
|
|
|
| 133 |
|
| 134 |
logAndAlert('[viewer.js] PlayCanvas application created!');
|
| 135 |
|
|
|
|
| 136 |
resizeObserver = new ResizeObserver(entries => {
|
| 137 |
for (const entry of entries) {
|
| 138 |
const { width, height } = entry.contentRect;
|
|
@@ -142,7 +145,6 @@ export async function initializeViewer(config, instanceId) {
|
|
| 142 |
}
|
| 143 |
});
|
| 144 |
resizeObserver.observe(viewerContainer);
|
| 145 |
-
|
| 146 |
window.addEventListener('resize', () => {
|
| 147 |
if (app) app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
|
| 148 |
});
|
|
@@ -163,9 +165,8 @@ export async function initializeViewer(config, instanceId) {
|
|
| 163 |
const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
|
| 164 |
let lastProg = 0;
|
| 165 |
|
| 166 |
-
// iOS
|
| 167 |
if (isIOS()) {
|
| 168 |
-
// 90MB is a big PLY!
|
| 169 |
loadTimeout = setTimeout(() => {
|
| 170 |
alert("⚠️ 3D model loading is taking unusually long on your device. Large PLY files (>40MB) may exceed memory limits on iOS Safari and cannot be shown. Try a smaller model, or use a desktop browser for best results.");
|
| 171 |
progressDialog.innerHTML = `<p style="color:red">Loading failed or too slow. Try a smaller model, or use a desktop browser.</p>`;
|
|
|
|
| 1 |
+
// viewer.js -- Drop-in for mikafil-viewer-gs with robust iOS/GLB/PLY support
|
| 2 |
|
| 3 |
+
let pc; // PlayCanvas global ref
|
| 4 |
export let app = null;
|
| 5 |
let cameraEntity = null;
|
| 6 |
let modelEntity = null;
|
| 7 |
let viewerInitialized = false;
|
| 8 |
let resizeObserver = null;
|
| 9 |
+
let loadTimeout = null; // iOS load fallback
|
| 10 |
|
| 11 |
let chosenCameraX, chosenCameraY, chosenCameraZ;
|
| 12 |
let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, minY;
|
| 13 |
let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
|
| 14 |
let plyUrl, glbUrl;
|
| 15 |
|
|
|
|
| 16 |
function isIOS() {
|
| 17 |
return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
| 18 |
}
|
|
|
|
| 24 |
export async function initializeViewer(config, instanceId) {
|
| 25 |
if (viewerInitialized) return;
|
| 26 |
|
| 27 |
+
// Parse config
|
| 28 |
plyUrl = config.ply_url;
|
| 29 |
glbUrl = config.glb_url;
|
| 30 |
minZoom = parseFloat(config.minZoom || "1");
|
|
|
|
| 56 |
chosenCameraY = mobile ? cameraYPhone : cameraY;
|
| 57 |
chosenCameraZ = mobile ? cameraZPhone : cameraZ;
|
| 58 |
|
| 59 |
+
// DOM references
|
| 60 |
const canvasId = 'canvas-' + instanceId;
|
| 61 |
const progressDialog = document.getElementById('progress-dialog-' + instanceId);
|
| 62 |
const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
|
|
|
|
| 86 |
|
| 87 |
progressDialog.style.display = 'block';
|
| 88 |
|
|
|
|
| 89 |
if (!pc) {
|
| 90 |
pc = await import("https://esm.run/playcanvas");
|
| 91 |
window.pc = pc;
|
|
|
|
| 94 |
|
| 95 |
try {
|
| 96 |
logAndAlert('[viewer.js] Creating graphics device...');
|
| 97 |
+
// Use the old-school AppBase+init pattern for max compatibility
|
| 98 |
const device = await pc.createGraphicsDevice(canvas, {
|
| 99 |
deviceTypes: ["webgl2"],
|
| 100 |
glslangUrl: "https://playcanvas.vercel.app/static/lib/glslang/glslang.js",
|
|
|
|
| 103 |
preserveDrawingBuffer: isIOS() ? true : false,
|
| 104 |
alpha: false
|
| 105 |
});
|
|
|
|
| 106 |
device.maxPixelRatio = Math.min(window.devicePixelRatio, 2);
|
| 107 |
|
| 108 |
const opts = new pc.AppOptions();
|
|
|
|
| 125 |
pc.GSplatHandler
|
| 126 |
];
|
| 127 |
|
| 128 |
+
// THIS is the robust way: AppBase + .init()
|
| 129 |
+
app = new pc.AppBase(canvas);
|
| 130 |
+
app.init(opts);
|
| 131 |
app.setCanvasFillMode(pc.FILLMODE_NONE);
|
| 132 |
app.setCanvasResolution(pc.RESOLUTION_AUTO);
|
| 133 |
+
app.scene.exposure = 0.5;
|
| 134 |
+
app.scene.toneMapping = pc.TONEMAP_ACES;
|
| 135 |
|
| 136 |
logAndAlert('[viewer.js] PlayCanvas application created!');
|
| 137 |
|
| 138 |
+
// Resize
|
| 139 |
resizeObserver = new ResizeObserver(entries => {
|
| 140 |
for (const entry of entries) {
|
| 141 |
const { width, height } = entry.contentRect;
|
|
|
|
| 145 |
}
|
| 146 |
});
|
| 147 |
resizeObserver.observe(viewerContainer);
|
|
|
|
| 148 |
window.addEventListener('resize', () => {
|
| 149 |
if (app) app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
|
| 150 |
});
|
|
|
|
| 165 |
const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
|
| 166 |
let lastProg = 0;
|
| 167 |
|
| 168 |
+
// iOS: fallback timeout
|
| 169 |
if (isIOS()) {
|
|
|
|
| 170 |
loadTimeout = setTimeout(() => {
|
| 171 |
alert("⚠️ 3D model loading is taking unusually long on your device. Large PLY files (>40MB) may exceed memory limits on iOS Safari and cannot be shown. Try a smaller model, or use a desktop browser for best results.");
|
| 172 |
progressDialog.innerHTML = `<p style="color:red">Loading failed or too slow. Try a smaller model, or use a desktop browser.</p>`;
|