diff --git a/spectromotion/index.html b/spectromotion/index.html
index 90be3c9..1f9b1cb 100644
--- a/spectromotion/index.html
+++ b/spectromotion/index.html
@@ -114,7 +114,7 @@
Abstract
Results and comparisons
Here we display side-by-side videos comparing our method to top-performing baselines across different captured scenes.
- Select a scene and a baseline method below:
+ Select a scene, baseline method, and view below:
@@ -123,11 +123,21 @@
Results and comparisons
+
+
Interactive visualization. Hover or tap to move the split.
-
@@ -138,130 +148,95 @@ Results and comparisons
const methods = ['NeRF-DS', 'Deformable 3DGS', '4DGS', 'GaussianShader', 'GS-IR', 'HyperNeRF'];
const views = ['RGB', 'Depth', 'Normal'];
- function createSceneTabs() {
- const sceneTabsContainer = document.getElementById('scene-tabs');
- scenes.forEach((scene, index) => {
+ // State object to store selections for each scene
+ const state = {};
+ scenes.forEach(scene => {
+ state[scene] = {
+ method: methods[0],
+ view: views[0]
+ };
+ });
+
+ let currentScene = scenes[0];
+
+ function createTabs(containerId, items, clickHandler) {
+ const container = document.getElementById(containerId);
+ items.forEach((item, index) => {
const li = document.createElement('li');
- li.className = index === 0 ? 'is-active' : '';
const a = document.createElement('a');
- a.textContent = scene;
- a.onclick = () => switchScene(scene);
+ a.textContent = item;
+ a.onclick = () => clickHandler(item);
li.appendChild(a);
- sceneTabsContainer.appendChild(li);
+ container.appendChild(li);
});
}
- function createSceneContent() {
- const sceneContentContainer = document.getElementById('scene-content');
- scenes.forEach((scene, index) => {
- const sceneDiv = document.createElement('div');
- sceneDiv.style.display = index === 0 ? 'block' : 'none';
- sceneDiv.id = `scene-${scene}`;
-
- const methodTabs = document.createElement('div');
- methodTabs.className = 'tabs is-centered is-toggle is-toggle-rounded is-small';
- const methodUl = document.createElement('ul');
- methodUl.className = 'is-marginless';
-
- methods.forEach((method, methodIndex) => {
- const li = document.createElement('li');
- li.className = methodIndex === 0 ? 'is-active' : '';
- const a = document.createElement('a');
- a.textContent = method;
- a.onclick = () => switchMethod(scene, method);
- li.appendChild(a);
- methodUl.appendChild(li);
- });
-
- methodTabs.appendChild(methodUl);
- sceneDiv.appendChild(methodTabs);
-
- const methodContent = document.createElement('div');
- methodContent.className = 'tabs-content';
- methods.forEach((method, methodIndex) => {
- const methodDiv = document.createElement('div');
- methodDiv.style.display = methodIndex === 0 ? 'block' : 'none';
- methodDiv.id = `${scene}-${method}`;
-
- const viewTabs = document.createElement('div');
- viewTabs.className = 'tabs is-centered is-toggle is-toggle-rounded is-small';
- const viewUl = document.createElement('ul');
- viewUl.className = 'is-marginless';
-
- views.forEach((view, viewIndex) => {
- const li = document.createElement('li');
- li.className = viewIndex === 0 ? 'is-active' : '';
- const a = document.createElement('a');
- a.textContent = view;
- a.onclick = () => switchView(scene, method, view);
- li.appendChild(a);
- viewUl.appendChild(li);
- });
-
- viewTabs.appendChild(viewUl);
- methodDiv.appendChild(viewTabs);
+ function updateActiveTab(containerId, activeItem) {
+ const tabs = document.querySelectorAll(`#${containerId} li`);
+ tabs.forEach(tab => {
+ tab.className = tab.textContent === activeItem ? 'is-active' : '';
+ });
+ }
- views.forEach((view, viewIndex) => {
- const videoComparison = document.createElement('div');
- videoComparison.className = 'video-comparison';
- videoComparison.setAttribute('data-label', method);
- videoComparison.setAttribute('data-label2', 'Ours');
- videoComparison.style.display = viewIndex === 0 ? 'block' : 'none';
+ function createVideoComparison() {
+ const container = document.getElementById('video-container');
+ container.innerHTML = ''; // Clear existing content
- const video = document.createElement('video');
- video.className = 'video';
- video.width = '100%';
- video.loop = true;
- video.playsinline = true;
- video.muted = true;
- video.src = `./static/videos/${method.toLowerCase()}_${scene}_ours_${scene}_${view.toLowerCase()}_30fps.mp4`;
+ const currentMethod = state[currentScene].method;
+ const currentView = state[currentScene].view;
- const canvas = document.createElement('canvas');
+ const videoComparison = document.createElement('div');
+ videoComparison.className = 'video-comparison';
+ videoComparison.setAttribute('data-label', currentMethod);
+ videoComparison.setAttribute('data-label2', 'Ours');
- videoComparison.appendChild(video);
- videoComparison.appendChild(canvas);
- methodDiv.appendChild(videoComparison);
- });
+ const video = document.createElement('video');
+ video.className = 'video';
+ video.width = '100%';
+ video.loop = true;
+ video.playsinline = true;
+ video.muted = true;
+ video.src = `./static/videos/${currentMethod.toLowerCase()}_${currentScene}_ours_${currentScene}_${currentView.toLowerCase()}_30fps.mp4`;
- methodContent.appendChild(methodDiv);
- });
+ const canvas = document.createElement('canvas');
- sceneDiv.appendChild(methodContent);
- sceneContentContainer.appendChild(sceneDiv);
- });
+ videoComparison.appendChild(video);
+ videoComparison.appendChild(canvas);
+ container.appendChild(videoComparison);
}
function switchScene(scene) {
- scenes.forEach(s => {
- document.getElementById(`scene-${s}`).style.display = s === scene ? 'block' : 'none';
- });
- document.querySelectorAll('#scene-tabs li').forEach(li => {
- li.className = li.textContent === scene ? 'is-active' : '';
- });
+ currentScene = scene;
+ updateActiveTab('scene-tabs', scene);
+ updateActiveTab('method-tabs', state[scene].method);
+ updateActiveTab('view-tabs', state[scene].view);
+ createVideoComparison();
}
- function switchMethod(scene, method) {
- methods.forEach(m => {
- document.getElementById(`${scene}-${m}`).style.display = m === method ? 'block' : 'none';
- });
- document.querySelectorAll(`#scene-${scene} .tabs.is-toggle li`).forEach(li => {
- li.className = li.textContent === method ? 'is-active' : '';
- });
+ function switchMethod(method) {
+ state[currentScene].method = method;
+ updateActiveTab('method-tabs', method);
+ createVideoComparison();
}
- function switchView(scene, method, view) {
- const methodDiv = document.getElementById(`${scene}-${method}`);
- methodDiv.querySelectorAll('.video-comparison').forEach((div, index) => {
- div.style.display = views[index] === view ? 'block' : 'none';
- });
- methodDiv.querySelectorAll('.tabs.is-toggle li').forEach(li => {
- li.className = li.textContent === view ? 'is-active' : '';
- });
+ function switchView(view) {
+ state[currentScene].view = view;
+ updateActiveTab('view-tabs', view);
+ createVideoComparison();
}
// Initialize the tabs and content
- createSceneTabs();
- createSceneContent();
+ createTabs('scene-tabs', scenes, switchScene);
+ createTabs('method-tabs', methods, switchMethod);
+ createTabs('view-tabs', views, switchView);
+
+ // Set initial active tabs
+ updateActiveTab('scene-tabs', currentScene);
+ updateActiveTab('method-tabs', state[currentScene].method);
+ updateActiveTab('view-tabs', state[currentScene].view);
+
+ // Create initial video comparison
+ createVideoComparison();