Skip to content

Add support for 3DConnexion's SpaceMouse devices.#45

Open
amishne wants to merge 2 commits into
CNCKitchen:mainfrom
amishne:spacemouse
Open

Add support for 3DConnexion's SpaceMouse devices.#45
amishne wants to merge 2 commits into
CNCKitchen:mainfrom
amishne:spacemouse

Conversation

@amishne

@amishne amishne commented Apr 12, 2026

Copy link
Copy Markdown

This was vibe-coded as well :-)

Unfortunately browser support for these devices seems to be poll-based and so the function has to run on every iteration, so the function has been optimized to cache as much as possible. Performance on my machine was good.

Tested with my SpaceMouse.

@EllaFoxo EllaFoxo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some code quality improvements for your clanker :)

Comment thread js/viewer.js
function applySpaceMouse() {
if (!controls.enabled) return;

const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Break out gamepad selection into a separate reusable function

Comment thread js/viewer.js
}
}

if (!sm) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't silently fail if no space mouse is found. Report back a bool or int return result so that the function's caller is notified of the presence (or not) of a space mouse.

Comment thread js/viewer.js
// Smooth deadzone mapping.
// Instead of a step discontinuity (a < threshold ? 0 : a) that causes sudden camera
// jumps when crossing the threshold, we scale smoothly from 0.0 to 1.0 after the deadzone.
const deadzone = 0.08;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deadzone should be configurable, not hardcoded.

Comment thread js/viewer.js
const tz = ax1;
const ty = -ax2;

if (tx !== 0 || ty !== 0 || tz !== 0) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like some in-line comment documentation here to explain the math behind what is going on. Looks to be calculating the axis positional change delta, and applying that directly to the camera controls. Perhaps this could be broken up into separate functions, one that handles the math, one that does camera transforms.

Comment thread js/viewer.js
transSpeed = (orthoCamera.top / orthoCamera.zoom) * 0.04;
}

_tmpV1.set(0, 0, 1).applyQuaternion(camera.quaternion).normalize();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_tmpV1, _tmpV2 etc are all meaningless variables. Give them a suitable name. Doesn't matter if they're temporary allocations; code needs to be readable.

Comment thread js/viewer.js
_needsRender = true;
}

const pitch = ax3;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would have been nice to have pitch/roll/yaw comments on the original axis declaration, so we're able to determine which axis does what movement. Can then continue setting a constant later.

Comment thread js/viewer.js
const yaw = -ax5;

if (pitch !== 0 || roll !== 0 || yaw !== 0) {
const rotSpeed = 0.02;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another place we don't want to hardcode.

Comment thread js/viewer.js
function applySpaceMouse() {
if (!controls.enabled) return;

const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gamepad API should be the fallback - WebHID is preferential if support in the browser is there (currently only Edge, Chrome and Opera). Direct HID input is going to yield more control if you can get it.

https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API

https://developer.mozilla.org/en-US/docs/Web/API/HIDInputReportEvent

Comment thread js/viewer.js
let transSpeed = 2.0;
if (_isPerspective) {
const dist = camera.position.distanceTo(pivot);
transSpeed = dist * 0.02;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic values for 2.0, 0.02, 0.04. Same for the dollyDelta and camera.zoom later. What are they? What are they doing to the speed and zoom? Document them, and/or make them constant. Where appropriate, provide them as a field in the function header.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants