Skip to content

Commit b259516

Browse files
committed
add traj
1 parent f970ef2 commit b259516

File tree

3 files changed

+103
-29
lines changed

3 files changed

+103
-29
lines changed

css/index.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ body {
248248
position: absolute;
249249
right: 90px;
250250
}
251+
#btn-pause {
252+
position: absolute;
253+
right: 210px;
254+
}
251255

252256
/* Font Awesome icon inside */
253257
.rotate-button i {

index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ <h1 class="title is-2 publication-title">
233233
<button id="btn-traj" class="rotate-button">
234234
Trajectory: Off
235235
</button>
236+
<button id="btn-pause" class="rotate-button">
237+
Pause
238+
</button>
236239
</div>
237240
</div>
238241
</section>

js/pcd-viewer.js

Lines changed: 96 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -650,32 +650,39 @@ function clearAllViewers() {
650650
clearTimeout(playTimeoutId);
651651

652652
allStates.forEach((st) => {
653+
// Guard: skip any state object that doesn’t have a scene
654+
if (!st || !st.scene) return; // ← UPDATED: avoid calling traverse on undefined
655+
653656
if (st.isSampled) {
654657
// Remove any interpolated meshes (if still present)
655-
st.scene.traverse((obj) => {
656-
if (obj.name && obj.name.startsWith(`interp_${st.currentSampleId}_`)) {
657-
if (obj.geometry) obj.geometry.dispose();
658-
if (obj.material) obj.material.dispose();
659-
st.scene.remove(obj);
660-
}
661-
});
658+
// st.scene.traverse((obj) => {
659+
// if (obj.name && obj.name.startsWith(`interp_${st.currentSampleId}_`)) {
660+
// if (obj.geometry) obj.geometry.dispose();
661+
// if (obj.material) obj.material.dispose();
662+
// st.scene.remove(obj);
663+
// }
664+
// });
662665

663666
// Remove each frame’s InstancedMesh
664-
st.frameMeshes.forEach((m) => {
665-
if (m) {
666-
st.scene.remove(m);
667-
m.geometry.dispose();
668-
m.material.dispose();
669-
}
670-
});
667+
if (Array.isArray(st.frameMeshes)) {
668+
st.frameMeshes.forEach((m) => {
669+
if (m) {
670+
st.scene.remove(m);
671+
if (m.geometry) m.geometry.dispose();
672+
if (m.material) m.material.dispose();
673+
}
674+
});
675+
}
671676

672677
// Remove any trajectory spheres
673-
st.trajectorySpheres.forEach((sphere) => {
674-
if (sphere.geometry) sphere.geometry.dispose();
675-
if (sphere.material) sphere.material.dispose();
676-
st.scene.remove(sphere);
677-
});
678-
st.trajectorySpheres.length = 0;
678+
if (Array.isArray(st.trajectorySpheres)) {
679+
st.trajectorySpheres.forEach((sphere) => {
680+
if (sphere.geometry) sphere.geometry.dispose();
681+
if (sphere.material) sphere.material.dispose();
682+
st.scene.remove(sphere);
683+
});
684+
st.trajectorySpheres.length = 0;
685+
}
679686
} else {
680687
if (st.mesh) {
681688
st.scene.remove(st.mesh);
@@ -690,7 +697,12 @@ function clearAllViewers() {
690697
}
691698
});
692699

693-
document.querySelector('.viewers-container').innerHTML = '';
700+
// Also clear out the containers in the DOM
701+
const containerEl = document.querySelector('.viewers-container');
702+
if (containerEl) {
703+
containerEl.innerHTML = '';
704+
}
705+
694706
inputState = null;
695707
sampledStates = [];
696708
allStates = [];
@@ -1075,6 +1087,29 @@ function selectObject(objName) {
10751087
sampledStates = [state1, state2];
10761088
allStates = [inputState, state1, state2];
10771089

1090+
// ← NEW: Whenever we switch objects, force‐resume playback + rotation + disable trajectories
1091+
isPaused = false; // ensure we’re playing
1092+
const pauseBtn = document.getElementById('btn-pause');
1093+
if (pauseBtn) {
1094+
pauseBtn.innerText = 'Pause';
1095+
}
1096+
1097+
const rotateBtn = document.getElementById('btn-rotate');
1098+
if (rotateBtn) {
1099+
// Restore rotation to “On”
1100+
rotateBtn.innerText = 'Rotate: On';
1101+
}
1102+
// Actually enable autoRotate on every viewer’s OrbitControls
1103+
allStates.forEach((st) => {
1104+
if (st.controls) st.controls.autoRotate = true;
1105+
});
1106+
1107+
showTrajectories = false; // disable any lingering trajectories
1108+
const trajBtn = document.getElementById('btn-traj');
1109+
if (trajBtn) {
1110+
trajBtn.innerText = 'Trajectories: Off';
1111+
}
1112+
10781113
// Reset frame index & begin animation/resampling loop
10791114
currentFrameIdx = 0;
10801115
advanceAllFrames(currentSession);
@@ -1092,27 +1127,29 @@ window.addEventListener('DOMContentLoaded', () => {
10921127
// “Rotate” button toggles autoRotate:
10931128
const rotateBtn = document.getElementById('btn-rotate');
10941129
rotateBtn.addEventListener('click', () => {
1095-
const anyAuto = allStates.some((st) => st.controls.autoRotate);
1130+
const anyAuto = allStates.some((st) => st.controls?.autoRotate);
10961131
if (anyAuto) {
10971132
allStates.forEach((st) => {
1098-
st.controls.autoRotate = false;
1133+
if (st.controls) st.controls.autoRotate = false;
10991134
});
11001135
} else {
11011136
allStates.forEach((st) => {
1102-
st.controls.autoRotate = true;
1137+
if (st.controls) st.controls.autoRotate = true;
11031138
});
11041139
}
1140+
// Enable the button again (in case it was disabled during drag)
11051141
rotateBtn.disabled = false;
1106-
const anyAuto2 = allStates.some((st) => st.controls.autoRotate);
1107-
rotateBtn.innerHTML = anyAuto2
1108-
? 'Rotate: On '
1142+
1143+
const anyAuto2 = allStates.some((st) => st.controls?.autoRotate);
1144+
rotateBtn.innerText = anyAuto2
1145+
? 'Rotate: On'
11091146
: 'Rotate: Off';
11101147
});
11111148

11121149
// “Show Trajectories” button (toggle):
11131150
const trajBtn = document.getElementById('btn-traj');
11141151
trajBtn.innerText = 'Trajectories: Off'; // initially off
1115-
trajBtn.addEventListener('click', () => { // ← TRAJ
1152+
trajBtn.addEventListener('click', () => {
11161153
showTrajectories = !showTrajectories;
11171154
if (showTrajectories) {
11181155
trajBtn.innerText = 'Trajectories: On';
@@ -1132,9 +1169,39 @@ window.addEventListener('DOMContentLoaded', () => {
11321169
}
11331170
});
11341171

1172+
// ← UPDATED: “Play/Pause” button wiring (now also stops/starts autoRotate)
1173+
const pauseBtn = document.getElementById('btn-pause');
1174+
if (pauseBtn) {
1175+
pauseBtn.innerText = 'Pause'; // default: playing
1176+
pauseBtn.addEventListener('click', () => {
1177+
isPaused = !isPaused;
1178+
1179+
if (isPaused) {
1180+
// 1) Switch button label
1181+
pauseBtn.innerText = 'Play';
1182+
// 2) Stop the frame‐advance loop
1183+
clearTimeout(playTimeoutId);
1184+
// 3) Force all viewers to stop rotating
1185+
allStates.forEach((st) => {
1186+
if (st.controls) st.controls.autoRotate = false;
1187+
});
1188+
} else {
1189+
// 1) Switch button label
1190+
pauseBtn.innerText = 'Pause';
1191+
// 2) Restore autoRotate only if "Rotate" is currently set to On:
1192+
const rotateIsOn = rotateBtn.innerText.includes('On');
1193+
allStates.forEach((st) => {
1194+
if (st.controls) st.controls.autoRotate = rotateIsOn;
1195+
});
1196+
// 3) Re‐start frame‐advance from the current frame
1197+
advanceAllFrames(currentSession);
1198+
}
1199+
});
1200+
}
1201+
11351202
// Show the first object by default
11361203
selectObject('partnet_652');
11371204

11381205
// Start the render loop
11391206
animateAll();
1140-
});
1207+
});

0 commit comments

Comments
 (0)