weijielyu commited on
Commit
25d0eb4
·
1 Parent(s): 3916713

Update demo

Browse files
Files changed (2) hide show
  1. VIEWER_DEBUG.md +94 -0
  2. app.py +88 -13
VIEWER_DEBUG.md ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Viewer Debugging Guide
2
+
3
+ The viewer now has extensive console logging to help diagnose issues.
4
+
5
+ ## How to Debug
6
+
7
+ 1. **Run the app:**
8
+ ```bash
9
+ python app.py
10
+ ```
11
+
12
+ 2. **Open the browser console:**
13
+ - Chrome/Edge: Press `F12` or `Ctrl+Shift+J` (Windows) / `Cmd+Option+J` (Mac)
14
+ - Firefox: Press `F12` or `Ctrl+Shift+K` (Windows) / `Cmd+Option+K` (Mac)
15
+ - Safari: Enable Developer menu in Preferences, then press `Cmd+Option+C`
16
+
17
+ 3. **Check the Console tab** and look for these key messages:
18
+
19
+ ## Expected Console Messages
20
+
21
+ ### On Page Load:
22
+ ```
23
+ DOM already loaded, initializing viewer in 100ms
24
+ initViewer called, isInitialized: false
25
+ Container found: <div...>
26
+ Canvas created and added
27
+ WebGL2 context created
28
+ Worker created
29
+ Starting render loop
30
+ ✓ Viewer initialized successfully
31
+ Rendering black screen, waiting for data... (repeats every 60 frames)
32
+ ```
33
+
34
+ ### After Generating a Model:
35
+ ```
36
+ === Starting PLY load ===
37
+ URL: /gradio_api/file=outputs/splats/xxxxx/xxxxx.ply?v=xxxxx
38
+ Initialized? true
39
+ Worker? true
40
+ Fetching: /gradio_api/file=...
41
+ Response status: 200
42
+ ArrayBuffer size: XXXXX bytes
43
+ Magic bytes: Uint8Array(4) [112, 108, 121, 10] (this is correct for PLY files)
44
+ PLY file sent to worker
45
+
46
+ [Worker] Message received: {ply: ArrayBuffer}
47
+ [Worker] Processing PLY buffer...
48
+ [Worker] Buffer processed, vertex count: XXXXX
49
+ [Worker] Generating texture...
50
+ [Worker] Texture generated and sent
51
+
52
+ Worker message received: {texdata: Uint32Array, ...}
53
+ Texture data: {texwidth: 2048, texheight: XXX, vertexCount: XXXXX}
54
+ ✓ Successfully loaded XXXXX gaussians
55
+
56
+ First render with XXXXX vertices
57
+ ```
58
+
59
+ ## Common Issues and Solutions
60
+
61
+ ### Issue 1: "Container #splat-container not found"
62
+ **Problem:** The viewer container isn't in the DOM yet
63
+ **Solution:** This should auto-retry, but if it persists, check that the Gradio interface loaded correctly
64
+
65
+ ### Issue 2: "Failed to load: 404"
66
+ **Problem:** The PLY file URL is incorrect or the file doesn't exist
67
+ **Solution:** Check that the generation completed successfully and the file was saved
68
+
69
+ ### Issue 3: Worker doesn't receive message
70
+ **Problem:** The fetch failed or the ArrayBuffer is empty
71
+ **Solution:** Check the ArrayBuffer size in the console - it should be > 0
72
+
73
+ ### Issue 4: Worker error during processing
74
+ **Problem:** The PLY file format might be incompatible
75
+ **Solution:** Check the magic bytes - should be [112, 108, 121, 10] which is "ply\n"
76
+
77
+ ### Issue 5: Black screen but no errors
78
+ **Problem:** vertexCount might be 0 or rendering issue
79
+ **Solution:** Check that "Successfully loaded X gaussians" appears with X > 0
80
+
81
+ ## Quick Test
82
+
83
+ Run this in the browser console after the page loads:
84
+
85
+ ```javascript
86
+ console.log('Testing viewer state:');
87
+ console.log('Window function:', typeof window.__load_splat__); // should be "function"
88
+ console.log('Container exists:', !!document.getElementById('splat-container')); // should be true
89
+ ```
90
+
91
+ ## Next Steps
92
+
93
+ Copy the console output and we can diagnose the exact issue!
94
+
app.py CHANGED
@@ -527,10 +527,20 @@ void main () {
527
  self.postMessage({ texdata, texwidth, texheight, vertexCount }, [texdata.buffer]);
528
  }
529
  self.onmessage = (e) => {
 
530
  if (e.data.ply) {
531
- buffer = processPlyBuffer(e.data.ply);
532
- vertexCount = Math.floor(buffer.byteLength / rowLength);
533
- generateTexture();
 
 
 
 
 
 
 
 
 
534
  }
535
  };
536
  \`;
@@ -561,17 +571,32 @@ void main () {
561
  };
562
 
563
  function initViewer() {
564
- if (isInitialized) return;
 
 
 
 
 
565
  const container = document.getElementById('splat-container');
566
- if (!container) { console.error('Container not found'); setTimeout(initViewer, 100); return; }
 
 
 
 
567
 
 
568
  canvas = document.createElement('canvas');
569
  canvas.id = 'gs-canvas';
570
  container.innerHTML = '';
571
  container.appendChild(canvas);
 
572
 
573
  gl = canvas.getContext('webgl2', { antialias: false });
574
- if (!gl) { console.error('WebGL2 not supported'); return; }
 
 
 
 
575
 
576
  const vShader = gl.createShader(gl.VERTEX_SHADER);
577
  gl.shaderSource(vShader, vertexShaderSource);
@@ -658,61 +683,111 @@ void main () {
658
  viewMatrix = invert4(inv);
659
  }, { passive: false });
660
 
 
661
  function render() {
662
  if (vertexCount > 0) {
 
663
  gl.uniformMatrix4fv(u_view, false, viewMatrix);
664
  gl.clear(gl.COLOR_BUFFER_BIT);
665
  gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, vertexCount);
 
666
  } else {
 
667
  gl.clearColor(0, 0, 0, 1);
668
  gl.clear(gl.COLOR_BUFFER_BIT);
 
669
  }
670
  requestAnimationFrame(render);
671
  }
 
672
  render();
673
 
674
  worker = createWorker();
 
 
675
  worker.onmessage = (e) => {
 
676
  if (e.data.texdata) {
677
  const { texdata, texwidth, texheight, vertexCount: vc } = e.data;
 
678
  vertexCount = vc;
 
679
  gl.bindTexture(gl.TEXTURE_2D, texture);
680
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
681
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
682
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
683
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
684
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, texwidth, texheight, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, texdata);
 
685
  const depthIndex = new Uint32Array(vc);
686
  for (let i = 0; i < vc; i++) depthIndex[i] = i;
687
  gl.bindBuffer(gl.ARRAY_BUFFER, indexBuffer);
688
  gl.bufferData(gl.ARRAY_BUFFER, depthIndex, gl.STATIC_DRAW);
689
- console.log('Loaded', vc, 'gaussians');
 
690
  }
691
  };
692
 
 
 
 
 
693
  isInitialized = true;
694
- console.log('Viewer initialized');
695
  }
696
 
697
  async function loadPlyFile(url) {
698
  try {
699
- console.log('Loading PLY from:', url);
700
- if (!isInitialized) initViewer();
701
- if (!worker) { console.error('Worker not initialized'); return; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  const response = await fetch(url);
 
 
 
703
  if (!response.ok) throw new Error('Failed to load: ' + response.status);
 
704
  const arrayBuffer = await response.arrayBuffer();
 
 
 
 
 
 
705
  worker.postMessage({ ply: arrayBuffer }, [arrayBuffer]);
706
  console.log('PLY file sent to worker');
707
  } catch (error) {
708
- console.error('Error loading PLY:', error);
 
 
709
  }
710
  }
711
 
712
  window.__load_splat__ = loadPlyFile;
 
 
713
  if (document.readyState === 'loading') {
714
- document.addEventListener('DOMContentLoaded', () => setTimeout(initViewer, 100));
 
 
 
715
  } else {
 
716
  setTimeout(initViewer, 100);
717
  }
718
  })();
 
527
  self.postMessage({ texdata, texwidth, texheight, vertexCount }, [texdata.buffer]);
528
  }
529
  self.onmessage = (e) => {
530
+ console.log('[Worker] Message received:', e.data);
531
  if (e.data.ply) {
532
+ try {
533
+ console.log('[Worker] Processing PLY buffer...');
534
+ buffer = processPlyBuffer(e.data.ply);
535
+ vertexCount = Math.floor(buffer.byteLength / rowLength);
536
+ console.log('[Worker] Buffer processed, vertex count:', vertexCount);
537
+ console.log('[Worker] Generating texture...');
538
+ generateTexture();
539
+ console.log('[Worker] Texture generated and sent');
540
+ } catch (error) {
541
+ console.error('[Worker] Error:', error);
542
+ console.error('[Worker] Stack:', error.stack);
543
+ }
544
  }
545
  };
546
  \`;
 
571
  };
572
 
573
  function initViewer() {
574
+ console.log('initViewer called, isInitialized:', isInitialized);
575
+ if (isInitialized) {
576
+ console.log('Already initialized, skipping');
577
+ return;
578
+ }
579
+
580
  const container = document.getElementById('splat-container');
581
+ if (!container) {
582
+ console.error('Container #splat-container not found, retrying in 100ms');
583
+ setTimeout(initViewer, 100);
584
+ return;
585
+ }
586
 
587
+ console.log('Container found:', container);
588
  canvas = document.createElement('canvas');
589
  canvas.id = 'gs-canvas';
590
  container.innerHTML = '';
591
  container.appendChild(canvas);
592
+ console.log('Canvas created and added');
593
 
594
  gl = canvas.getContext('webgl2', { antialias: false });
595
+ if (!gl) {
596
+ console.error('WebGL2 not supported');
597
+ return;
598
+ }
599
+ console.log('WebGL2 context created');
600
 
601
  const vShader = gl.createShader(gl.VERTEX_SHADER);
602
  gl.shaderSource(vShader, vertexShaderSource);
 
683
  viewMatrix = invert4(inv);
684
  }, { passive: false });
685
 
686
+ let renderCount = 0;
687
  function render() {
688
  if (vertexCount > 0) {
689
+ if (renderCount === 0) console.log('First render with', vertexCount, 'vertices');
690
  gl.uniformMatrix4fv(u_view, false, viewMatrix);
691
  gl.clear(gl.COLOR_BUFFER_BIT);
692
  gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, vertexCount);
693
+ renderCount++;
694
  } else {
695
+ if (renderCount % 60 === 0) console.log('Rendering black screen, waiting for data...');
696
  gl.clearColor(0, 0, 0, 1);
697
  gl.clear(gl.COLOR_BUFFER_BIT);
698
+ renderCount++;
699
  }
700
  requestAnimationFrame(render);
701
  }
702
+ console.log('Starting render loop');
703
  render();
704
 
705
  worker = createWorker();
706
+ console.log('Worker created');
707
+
708
  worker.onmessage = (e) => {
709
+ console.log('Worker message received:', e.data);
710
  if (e.data.texdata) {
711
  const { texdata, texwidth, texheight, vertexCount: vc } = e.data;
712
+ console.log('Texture data:', {texwidth, texheight, vertexCount: vc, textureSize: texdata.byteLength});
713
  vertexCount = vc;
714
+
715
  gl.bindTexture(gl.TEXTURE_2D, texture);
716
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
717
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
718
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
719
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
720
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32UI, texwidth, texheight, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT, texdata);
721
+
722
  const depthIndex = new Uint32Array(vc);
723
  for (let i = 0; i < vc; i++) depthIndex[i] = i;
724
  gl.bindBuffer(gl.ARRAY_BUFFER, indexBuffer);
725
  gl.bufferData(gl.ARRAY_BUFFER, depthIndex, gl.STATIC_DRAW);
726
+
727
+ console.log('✓ Successfully loaded', vc, 'gaussians');
728
  }
729
  };
730
 
731
+ worker.onerror = (error) => {
732
+ console.error('Worker error:', error);
733
+ };
734
+
735
  isInitialized = true;
736
+ console.log('Viewer initialized successfully');
737
  }
738
 
739
  async function loadPlyFile(url) {
740
  try {
741
+ console.log('=== Starting PLY load ===');
742
+ console.log('URL:', url);
743
+ console.log('Initialized?', isInitialized);
744
+ console.log('Worker?', !!worker);
745
+
746
+ if (!isInitialized) {
747
+ console.log('Initializing viewer...');
748
+ initViewer();
749
+ // Wait for initialization
750
+ await new Promise(resolve => setTimeout(resolve, 500));
751
+ }
752
+
753
+ if (!worker) {
754
+ console.error('Worker not initialized after init attempt');
755
+ return;
756
+ }
757
+
758
+ console.log('Fetching:', url);
759
  const response = await fetch(url);
760
+ console.log('Response status:', response.status);
761
+ console.log('Response headers:', [...response.headers.entries()]);
762
+
763
  if (!response.ok) throw new Error('Failed to load: ' + response.status);
764
+
765
  const arrayBuffer = await response.arrayBuffer();
766
+ console.log('ArrayBuffer size:', arrayBuffer.byteLength, 'bytes');
767
+
768
+ // Check PLY magic bytes
769
+ const magic = new Uint8Array(arrayBuffer.slice(0, 4));
770
+ console.log('Magic bytes:', magic, 'Expected: [112, 108, 121, 10] for "ply\\n"');
771
+
772
  worker.postMessage({ ply: arrayBuffer }, [arrayBuffer]);
773
  console.log('PLY file sent to worker');
774
  } catch (error) {
775
+ console.error('=== Error loading PLY ===');
776
+ console.error('Error:', error);
777
+ console.error('Stack:', error.stack);
778
  }
779
  }
780
 
781
  window.__load_splat__ = loadPlyFile;
782
+
783
+ // Initialize on load
784
  if (document.readyState === 'loading') {
785
+ document.addEventListener('DOMContentLoaded', () => {
786
+ console.log('DOM loaded, initializing viewer in 100ms');
787
+ setTimeout(initViewer, 100);
788
+ });
789
  } else {
790
+ console.log('DOM already loaded, initializing viewer in 100ms');
791
  setTimeout(initViewer, 100);
792
  }
793
  })();