Skip to content

Commit 1b7c4eb

Browse files
committed
Add option to directly view .ply files on demo page
1 parent f9f28bf commit 1b7c4eb

File tree

1 file changed

+104
-73
lines changed

1 file changed

+104
-73
lines changed

demo/index.html

Lines changed: 104 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
margin-right: 8px;
122122
}
123123

124-
.ply-loader {
124+
.loading-icon {
125125
width: 35px;
126126
padding: 15px;
127127
background: #324d70;
@@ -198,10 +198,9 @@
198198
<script type="module">
199199
import * as GaussianSplats3D from 'gaussian-splats-3d';
200200

201-
function convertPLY(plyBuffer, compressionLevel, alphaRemovalThreshold) {
201+
function convertPLYToSplatBuffer(plyBuffer, compressionLevel, alphaRemovalThreshold) {
202202
const plyParser = new GaussianSplats3D.PlyParser(plyBuffer);
203-
const splatBuffer = plyParser.parseToSplatBuffer(compressionLevel, alphaRemovalThreshold);
204-
new GaussianSplats3D.SplatLoader(splatBuffer).downloadFile('converted_file.splat');
203+
return plyParser.parseToSplatBuffer(compressionLevel, alphaRemovalThreshold);
205204
}
206205

207206
window.onFileChange = function(arg, fileNameLabelID) {
@@ -256,7 +255,8 @@
256255
setConversionCheckIconVisibility(false);
257256
window.setTimeout(() => {
258257
try {
259-
convertPLY(fileReader.result, compressionLevel, alphaRemovalThreshold);
258+
const splatBuffer = convertPLYToSplatBuffer(fileReader.result, compressionLevel, alphaRemovalThreshold);
259+
new GaussianSplats3D.SplatLoader(splatBuffer).downloadFile('converted_file.splat');
260260
conversionDone();
261261
} catch (e) {
262262
conversionDone(e);
@@ -285,7 +285,7 @@
285285
}
286286

287287
function setConversionLoadingIconVisibility(visible) {
288-
document.getElementById('loading-icon').style.display = visible ? 'block' : 'none';
288+
document.getElementById('conversion-loading-icon').style.display = visible ? 'block' : 'none';
289289
}
290290

291291
function setConversionCheckIconVisibility(visible) {
@@ -308,7 +308,7 @@
308308
if (!viewFile.files[0]) {
309309
setViewError("Please choose a file to view.");
310310
return;
311-
} else if (isNaN(alphaRemovalThreshold) || alphaRemovalThreshold <0 || alphaRemovalThreshold > 255) {
311+
} else if (isNaN(alphaRemovalThreshold) || alphaRemovalThreshold < 0 || alphaRemovalThreshold > 255) {
312312
setViewError("Invalid alpha remval threshold.");
313313
return;
314314
}
@@ -328,6 +328,9 @@
328328
return;
329329
}
330330

331+
const viewFileName = viewFile.files[0].name;
332+
const isPly = viewFileName.toLowerCase().trim().endsWith('.ply');
333+
331334
for (let i = 0; i < 3; i++) {
332335
cameraUpArray[i] = parseFloat(cameraUpArray[i]);
333336
cameraPositionArray[i] = parseFloat(cameraPositionArray[i]);
@@ -356,12 +359,13 @@
356359
try {
357360
const fileReader = new FileReader();
358361
fileReader.onload = function(){
359-
document.getElementById("table-of-contents-container").style.display = 'none';
360-
document.body.style.backgroundColor = "#000000";
361-
history.pushState("ViewSplat", null);
362-
runViewer(fileReader.result, alphaRemovalThreshold, cameraUpArray, cameraPositionArray, cameraLookAtArray);
362+
try {
363+
runViewer(fileReader.result, isPly, alphaRemovalThreshold, cameraUpArray, cameraPositionArray, cameraLookAtArray);
364+
} catch (e) {
365+
setViewError("Could not view .SPLAT file");
366+
}
363367
}
364-
setViewStatus("Loading .SPLAT...");
368+
setViewStatus("Loading scene...");
365369
fileReader.readAsArrayBuffer(viewFile.files[0]);
366370
} catch (e) {
367371
console.error(e);
@@ -370,15 +374,21 @@
370374
}
371375

372376
function setViewError(msg) {
377+
setViewLoadingIconVisibility(false);
373378
document.getElementById("viewStatus").innerHTML = "";
374379
document.getElementById("viewError").innerHTML = msg;
375380
}
376381

377382
function setViewStatus(msg) {
383+
setViewLoadingIconVisibility(true);
378384
document.getElementById("viewError").innerHTML = "";
379385
document.getElementById("viewStatus").innerHTML = msg;
380386
}
381387

388+
function setViewLoadingIconVisibility(visible) {
389+
document.getElementById('view-loading-icon').style.display = visible ? 'block' : 'none';
390+
}
391+
382392
window.addEventListener("popstate", (event) => {
383393
if (currentAlphaRemovalThreshold !== undefined) {
384394
window.location = 'index.html?art=' + currentAlphaRemovalThreshold + '&cu=' + currentCameraUpArray + "&cp=" + currentCameraPositionArray + "&cla=" + currentCameraLookAtArray;
@@ -387,17 +397,28 @@
387397
}
388398
});
389399

390-
function runViewer(splatBufferData, alphaRemovalThreshold, cameraUpArray, cameraPositionArray, cameraLookAtArray) {
391-
const splatBuffer = new GaussianSplats3D.SplatBuffer(splatBufferData);
392-
const viewer = new GaussianSplats3D.Viewer({
400+
function runViewer(splatBufferData, isPly, alphaRemovalThreshold, cameraUpArray, cameraPositionArray, cameraLookAtArray) {
401+
const viewerOptions = {
393402
'cameraUp': cameraUpArray,
394403
'initialCameraPosition': cameraPositionArray,
395404
'initialCameraLookAt': cameraLookAtArray
396-
});
397-
viewer.loadSplatBuffer(splatBuffer, {
405+
};
406+
const sceneOptions = {
398407
'halfPrecisionCovariancesOnGPU': true,
399408
'splatAlphaRemovalThreshold': alphaRemovalThreshold
400-
})
409+
};
410+
let splatBuffer;
411+
if (isPly) {
412+
splatBuffer = convertPLYToSplatBuffer(splatBufferData, 0, alphaRemovalThreshold);
413+
} else {
414+
splatBuffer = new GaussianSplats3D.SplatBuffer(splatBufferData);
415+
}
416+
417+
document.getElementById("table-of-contents-container").style.display = 'none';
418+
document.body.style.backgroundColor = "#000000";
419+
history.pushState("ViewSplat", null);
420+
const viewer = new GaussianSplats3D.Viewer(viewerOptions);
421+
viewer.loadSplatBuffer(splatBuffer, sceneOptions)
401422
.then(() => {
402423
viewer.start();
403424
});
@@ -418,7 +439,7 @@
418439
<div id="table-of-contents-container" class="table-of-contents-container">
419440
<div class="table-of-contents-inner-container">
420441
<br>
421-
<span class="title">View demo scene</span>
442+
<span class="title">Demo scenes</span>
422443
<br>
423444
<div class="table-of-contents-row">
424445
<div class="table-of-contents-entry" onclick="openDemo('garden')">
@@ -437,124 +458,134 @@
437458
<br>
438459
<br>
439460
<div class="table-of-contents-row">
440-
<div id ="conversion-panel" class="splat-panel">
461+
462+
<div id ="view-panel" class="splat-panel" style="height:300px;">
441463
<br>
442-
<span style="font-weight: bold">Convert your own .PLY to .SPLAT</span>
464+
<span style="font-weight: bold">View a .PLY or .SPLAT file</span>
443465
<br>
444466
<br>
445467
<table style="text-align: left;">
446468
<tr>
447469
<td colspan="2">
448-
<label for="conversionFile">
470+
<label for="viewFile">
449471
<span class="glyphicon glyphicon-folder-open" aria-hidden="true"><span class="button">Choose file</span></span>
450-
<input type="file" id="conversionFile" style="display:none" onchange="window.onFileChange(this, 'conversionFileName')">
472+
<input type="file" id="viewFile" style="display:none" onchange="window.onFileChange(this, 'viewFileName')">
451473
</label>
452-
<span id="conversionFileName" style="padding-left:15px; color: #333333">(No file chosen)</span>
474+
<span id="viewFileName" style="padding-left:15px; color: #333333">(No file chosen)</span>
453475
</td>
454476
</tr>
455477
<tr>
456478
<td colspan="2" style="height: 10px;"></td>
457479
</tr>
458480
<tr>
459481
<td>
460-
Compression level:
482+
Minimum alpha:&nbsp;
461483
</td>
462484
<td>
463-
<input id="compressionLevel" type="text" class="text-input" style="width: 50px" value="1"></input>
485+
<input id="alphaRemovalThresholdView" type="text" class="text-input" style="width: 50px" value="1"></input>
486+
<span style="color:#888888">(1 - 255)</span>
464487
</td>
465488
</tr>
466489
<tr>
467490
<td>
468-
Alpha removal threshold:&nbsp;
491+
Camera up:&nbsp;
469492
</td>
470493
<td>
471-
<input id="alphaRemovalThreshold" type="text" class="text-input" style="width: 50px" value="1"></input>
494+
<input id="cameraUp" type="text" class="text-input" style="width: 90px" value="0, 1, 0"></input>
495+
</td>
496+
</tr>
497+
<tr>
498+
<td>
499+
Camera position:&nbsp;
500+
</td>
501+
<td>
502+
<input id="cameraPosition" type="text" class="text-input" style="width: 90px" value="0, 1, 0"></input>
503+
</td>
504+
</tr>
505+
<tr>
506+
<td>
507+
Camera look-at:&nbsp;
508+
</td>
509+
<td>
510+
<input id="cameraLookAt" type="text" class="text-input" style="width: 90px" value="1, 0, 0"></input>
472511
</td>
473512
</tr>
474513
</table>
475514
<br>
476-
<span id="convertButton" class="button" onclick="window.convertPlyFile()">Convert</span>
515+
<span class="button" onclick="window.viewSplat()">View</span>
516+
&nbsp;&nbsp;
517+
<span class="button" onclick="reset()">Reset</span>
477518
<br>
478519
<br>
479-
<div style="text-align: center;">
480520
<div style="display: flex; flex-direction: row; width: 230px; margin: auto;">
481521
<div style="width: 50px;">
482-
<div id="loading-icon" class="ply-loader" style="display: none;">
483-
</div>
484-
<div id="check-icon" class="check" style="display: none;">
485-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="35px" width="35px" version="1.1" id="Capa_1" viewBox="0 0 17.837 17.837" xml:space="preserve" style="background:#ffffff00;">
486-
<g>
487-
<path style="fill:#00790a;" d="M16.145,2.571c-0.272-0.273-0.718-0.273-0.99,0L6.92,10.804l-4.241-4.27 c-0.272-0.274-0.715-0.274-0.989,0L0.204,8.019c-0.272,0.271-0.272,0.717,0,0.99l6.217,6.258c0.272,0.271,0.715,0.271,0.99,0 L17.63,5.047c0.276-0.273,0.276-0.72,0-0.994L16.145,2.571z"/>
488-
</g>
489-
</svg>
490-
</div>
522+
<div id="view-loading-icon" class="loading-icon" style="display: none;">
523+
</div>
491524
</div>
492-
<div id="conversionStatus" style="text-align: left; color: #333333; margin-top: 7px; margin-left: 15px; width: 175px"></div>
493-
</div>
525+
<div id="viewStatus" style="text-align: left; color: #333333; margin-top: 7px; margin-left: 15px; width: 175px"></div>
494526
</div>
495-
<span id="conversionError" style="color: #ff0000"></span>
527+
<span id="viewError" style="color: #ff0000"></span>
496528
<br>
497529
</div>
498-
499-
<div id ="view-panel" class="splat-panel">
530+
531+
<div id ="conversion-panel" class="splat-panel">
500532
<br>
501-
<span style="font-weight: bold">View a .SPLAT file</span>
533+
<span style="font-weight: bold">Convert your own .PLY to .SPLAT</span>
502534
<br>
503535
<br>
504536
<table style="text-align: left;">
505537
<tr>
506538
<td colspan="2">
507-
<label for="viewFile">
539+
<label for="conversionFile">
508540
<span class="glyphicon glyphicon-folder-open" aria-hidden="true"><span class="button">Choose file</span></span>
509-
<input type="file" id="viewFile" style="display:none" onchange="window.onFileChange(this, 'viewFileName')">
541+
<input type="file" id="conversionFile" style="display:none" onchange="window.onFileChange(this, 'conversionFileName')">
510542
</label>
511-
<span id="viewFileName" style="padding-left:15px; color: #333333">(No file chosen)</span>
543+
<span id="conversionFileName" style="padding-left:15px; color: #333333">(No file chosen)</span>
512544
</td>
513545
</tr>
514546
<tr>
515547
<td colspan="2" style="height: 10px;"></td>
516548
</tr>
517549
<tr>
518550
<td>
519-
Alpha removal threshold:&nbsp;
520-
</td>
521-
<td>
522-
<input id="alphaRemovalThresholdView" type="text" class="text-input" style="width: 50px" value="1"></input>
523-
</td>
524-
</tr>
525-
<tr>
526-
<td>
527-
Camera up:&nbsp;
528-
</td>
529-
<td>
530-
<input id="cameraUp" type="text" class="text-input" style="width: 90px" value="0, 1, 0"></input>
531-
</td>
532-
</tr>
533-
<tr>
534-
<td>
535-
Camera position:&nbsp;
551+
Compression level:
536552
</td>
537553
<td>
538-
<input id="cameraPosition" type="text" class="text-input" style="width: 90px" value="0, 1, 0"></input>
554+
<input id="compressionLevel" type="text" class="text-input" style="width: 50px" value="1"></input>
555+
<span style="color:#888888">(0 or 1)</span>
539556
</td>
540557
</tr>
541558
<tr>
542559
<td>
543-
Camera look-at:&nbsp;
560+
Minimum alpha:&nbsp;
544561
</td>
545562
<td>
546-
<input id="cameraLookAt" type="text" class="text-input" style="width: 90px" value="1, 0, 0"></input>
563+
<input id="alphaRemovalThreshold" type="text" class="text-input" style="width: 50px" value="1"></input>
564+
<span style="color:#888888">(1 - 255)</span>
547565
</td>
548566
</tr>
549567
</table>
550568
<br>
551-
<span class="button" onclick="window.viewSplat()">View</span>
552-
&nbsp;&nbsp;
553-
<span class="button" onclick="reset()">Reset</span>
569+
<span id="convertButton" class="button" onclick="window.convertPlyFile()">Convert</span>
554570
<br>
555571
<br>
556-
<span id="viewStatus" style="color: #333333"></span>
557-
<span id="viewError" style="color: #ff0000"></span>
572+
<div style="text-align: center;">
573+
<div style="display: flex; flex-direction: row; width: 230px; margin: auto;">
574+
<div style="width: 50px;">
575+
<div id="conversion-loading-icon" class="loading-icon" style="display: none;">
576+
</div>
577+
<div id="check-icon" class="check" style="display: none;">
578+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="35px" width="35px" version="1.1" id="Capa_1" viewBox="0 0 17.837 17.837" xml:space="preserve" style="background:#ffffff00;">
579+
<g>
580+
<path style="fill:#00790a;" d="M16.145,2.571c-0.272-0.273-0.718-0.273-0.99,0L6.92,10.804l-4.241-4.27 c-0.272-0.274-0.715-0.274-0.989,0L0.204,8.019c-0.272,0.271-0.272,0.717,0,0.99l6.217,6.258c0.272,0.271,0.715,0.271,0.99,0 L17.63,5.047c0.276-0.273,0.276-0.72,0-0.994L16.145,2.571z"/>
581+
</g>
582+
</svg>
583+
</div>
584+
</div>
585+
<div id="conversionStatus" style="text-align: left; color: #333333; margin-top: 7px; margin-left: 15px; width: 175px"></div>
586+
</div>
587+
</div>
588+
<span id="conversionError" style="color: #ff0000"></span>
558589
<br>
559590
</div>
560591

0 commit comments

Comments
 (0)