Skip to content

Commit 67d797b

Browse files
committed
restructure app code for modularizing and organization
1 parent 5f8d930 commit 67d797b

5 files changed

Lines changed: 650 additions & 174 deletions

File tree

VR/client/app.js

Lines changed: 3 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,4 @@
1-
import * as THREE from "three";
2-
import { VRButton } from "three/addons/webxr/VRButton.js";
3-
import { CHARACTER_MODES_REGISTRY } from "./modes/modes_registry.js";
1+
import { createApp } from "./app/create_app.js";
42

5-
const statusEl = document.getElementById("status");
6-
const startButton = document.getElementById("start-btn");
7-
const joinPanel = document.getElementById("join-panel");
8-
const joinButton = document.getElementById("join-btn");
9-
const characterModeSelect = document.getElementById("character-mode");
10-
let selectedCharacterMode = "demo-spline";
11-
12-
const searchParams = new URLSearchParams(window.location.search);
13-
const defaultWsScheme = window.location.protocol === "https:" ? "wss" : "ws";
14-
const defaultWsHost = window.location.hostname || "127.0.0.1";
15-
const defaultWsPort = searchParams.get("ws_port") ?? "8765";
16-
const serverHost =
17-
searchParams.get("ws") ??
18-
`${defaultWsScheme}://${defaultWsHost}:${defaultWsPort}`;
19-
20-
const calibrationOffset = new THREE.Vector3(
21-
Number(searchParams.get("ox") ?? 0.0),
22-
Number(searchParams.get("oy") ?? 0.0),
23-
Number(searchParams.get("oz") ?? 0.0)
24-
);
25-
26-
let socket = null;
27-
let userId = null;
28-
let sessionRole = "vr_client";
29-
let sessionMode = "vr_client";
30-
31-
const scene = new THREE.Scene();
32-
scene.background = new THREE.Color(0x1a1f2b);
33-
const worldRoot = new THREE.Group();
34-
worldRoot.position.copy(calibrationOffset);
35-
scene.add(worldRoot);
36-
37-
const camera = new THREE.PerspectiveCamera(
38-
70,
39-
window.innerWidth / window.innerHeight,
40-
0.01,
41-
50
42-
);
43-
camera.position.set(0, 1.4, 2.0);
44-
45-
const renderer = new THREE.WebGLRenderer({ antialias: true });
46-
renderer.setSize(window.innerWidth, window.innerHeight);
47-
renderer.xr.enabled = true;
48-
document.body.appendChild(renderer.domElement);
49-
50-
const hemi = new THREE.HemisphereLight(0xffffff, 0x223344, 1.2);
51-
scene.add(hemi);
52-
53-
const grid = new THREE.GridHelper(8, 16, 0x6c757d, 0x495057);
54-
grid.position.y = 0;
55-
worldRoot.add(grid);
56-
const worldAxes = new THREE.AxesHelper(0.3);
57-
worldRoot.add(worldAxes);
58-
59-
function setStatus(text) {
60-
statusEl.textContent = text;
61-
}
62-
63-
function applyCharacterMode(modeKey) {
64-
// TODO: Implement character mode selection
65-
}
66-
67-
function connect(joinConfig) {
68-
socket = new WebSocket(serverHost);
69-
sessionRole = joinConfig.serverRole ?? joinConfig.role;
70-
sessionMode = joinConfig.role;
71-
72-
socket.onopen = () => {
73-
setStatus(`connected: ${serverHost}`);
74-
socket.send(
75-
JSON.stringify({
76-
version: 1,
77-
type: "hello",
78-
payload: {
79-
client: "sparc-webxr",
80-
role: sessionRole,
81-
},
82-
})
83-
);
84-
};
85-
86-
socket.onclose = (event) => {
87-
setStatus(`disconnected: ${serverHost} (code=${event.code})`);
88-
};
89-
socket.onerror = () => {
90-
setStatus(`error: failed to connect ${serverHost}`);
91-
};
92-
93-
socket.onmessage = (event) => {
94-
// TODO: Implement message handling
95-
96-
const message = JSON.parse(event.data);
97-
98-
if (message.type === "error") {
99-
setStatus(`server error: ${message.payload?.reason ?? "unknown"}`);
100-
}
101-
102-
};
103-
}
104-
105-
function sendXRInput(frame) {
106-
// TODO: Implement XR input sending
107-
}
108-
109-
function animate() {
110-
// TODO: Implement animation loop
111-
let lastTime = performance.now() / 1000;
112-
renderer.setAnimationLoop((_, frame) => {
113-
const now = performance.now() / 1000;
114-
const dt = Math.min(0.05, now - lastTime);
115-
lastTime = now;
116-
117-
if (frame) sendXRInput(frame);
118-
119-
renderer.render(scene, camera);
120-
});
121-
}
122-
123-
startButton.addEventListener("click", () => {
124-
document.body.appendChild(VRButton.createButton(renderer));
125-
startButton.remove();
126-
});
127-
128-
window.addEventListener("resize", () => {
129-
camera.aspect = window.innerWidth / window.innerHeight;
130-
camera.updateProjectionMatrix();
131-
renderer.setSize(window.innerWidth, window.innerHeight);
132-
});
133-
134-
/* TODO: Implement key handling for desktop mode */
135-
window.addEventListener("keydown", (event) => {
136-
const key = event.key.toLowerCase();
137-
// TODO: Implement key handling
138-
});
139-
140-
window.addEventListener("keyup", (event) => {
141-
const key = event.key.toLowerCase();
142-
// TODO: Implement key handling
143-
});
144-
/* TODO */
145-
146-
renderer.domElement.addEventListener("click", () => {
147-
if (!renderer.xr.isPresenting && document.pointerLockElement !== renderer.domElement) {
148-
renderer.domElement.requestPointerLock();
149-
}
150-
});
151-
152-
document.addEventListener("mousemove", (event) => {
153-
if (document.pointerLockElement !== renderer.domElement) return;
154-
if (renderer.xr.isPresenting) return;
155-
156-
// TODO: Implement desktop mode mouse movement handling
157-
});
158-
159-
function setupJoinPanel() {
160-
// TODO: Implement join panel setup
161-
}
162-
163-
function populateCharacterModeSelect() {
164-
characterModeSelect.replaceChildren();
165-
for (const { id, label } of CHARACTER_MODES_REGISTRY) {
166-
const opt = document.createElement("option");
167-
opt.value = id;
168-
opt.textContent = label;
169-
characterModeSelect.appendChild(opt);
170-
}
171-
}
172-
173-
populateCharacterModeSelect();
174-
setupJoinPanel();
175-
animate();
3+
const app = createApp({ document, window });
4+
app.start();

VR/client/app/config.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import * as THREE from "three";
2+
3+
4+
export function createWindowConfig({ window }) {
5+
const searchParams = new URLSearchParams(window.location.search);
6+
const defaultWsScheme = window.location.protocol === "https:" ? "wss" : "ws";
7+
const defaultWsHost = window.location.hostname || "127.0.0.1";
8+
const defaultWsPort = searchParams.get("ws_port") ?? "8765";
9+
const serverHost =
10+
searchParams.get("ws") ??
11+
`${defaultWsScheme}://${defaultWsHost}:${defaultWsPort}`;
12+
13+
return {
14+
searchParams,
15+
serverHost,
16+
};
17+
}
18+
19+
export function createRunConfig({ windowConfig }) {
20+
const calibrationOffset = new THREE.Vector3(
21+
Number(windowConfig.searchParams.get("ox") ?? 0.0),
22+
Number(windowConfig.searchParams.get("oy") ?? 0.0),
23+
Number(windowConfig.searchParams.get("oz") ?? 0.0)
24+
);
25+
26+
const demoArmIds = [
27+
"left_arm",
28+
"right_arm"
29+
];
30+
31+
const armConfig = {
32+
left_arm: {
33+
color: "#ff6b6b",
34+
base: new THREE.Vector3(-0.25, 0.95, -0.35),
35+
hand: "left",
36+
},
37+
right_arm: {
38+
color: "#74c0fc",
39+
base: new THREE.Vector3(0.25, 0.95, -0.35),
40+
hand: "right",
41+
}
42+
};
43+
44+
const characterModes = {
45+
"demo-spline": {
46+
allowsBaseControl: true,
47+
leftBase: new THREE.Vector3(-0.25, 0.95, -0.35),
48+
rightBase: new THREE.Vector3(0.25, 0.95, -0.35),
49+
},
50+
"two-cr": {
51+
allowsBaseControl: false,
52+
leftBase: new THREE.Vector3(-0.15, 1.0, -0.15),
53+
rightBase: new THREE.Vector3(0.15, 1.0, -0.15),
54+
}
55+
};
56+
57+
// Initial director for controller forward direction
58+
const initialControllerForward = new THREE.Vector3(0.0, -1.0, 0.0);
59+
60+
return {
61+
calibrationOffset,
62+
initialControllerForward,
63+
demoArmIds,
64+
armIds: demoArmIds,
65+
armConfig,
66+
characterModes,
67+
curveSamples: 21,
68+
tipDefaultRadius: 0.045,
69+
maxContactPoints: 6000,
70+
71+
// Zoom configuration
72+
zoomConfig: {
73+
scale: 1.0,
74+
min: 0.35,
75+
max: 3.0,
76+
step: 0.06,
77+
},
78+
baseControl: {
79+
deadband: 0.12,
80+
step: 0.012,
81+
minX: -1.5,
82+
maxX: 1.5,
83+
minZ: -2.0,
84+
maxZ: 1.5,
85+
minY: 0.1,
86+
maxY: 2.0,
87+
heightStep: 0.02,
88+
},
89+
inputSendHz: Math.max(1.0, Number(windowConfig.searchParams.get("input_hz") ?? 30.0)),
90+
defaultDemoArmColors: Object.fromEntries(
91+
Object.entries(armConfig).map(([armId, arm]) => [armId, arm.color])
92+
),
93+
};
94+
}

0 commit comments

Comments
 (0)