- C 91%
- Shell 8.3%
- Makefile 0.7%
| scripts | ||
| src | ||
| vendor | ||
| .gitignore | ||
| Makefile | ||
| README.md | ||
SpaceMouse support for Siemens NX under Wine
This directory is a self-contained installer for making a 3Dconnexion SpaceMouse drive Siemens NX's 3D viewport (rotate/pan/zoom) when NX is run under Wine on Linux.
It replaces the vendor's low-level siappdll.dll device-API DLL (the one
the official 3DxNX.dll NX plugin loads) with a custom shim that:
- reads the SpaceMouse directly via Wine's RawInput/HID support, and
- drives NX's viewport directly through the NX Open C API,
bypassing the internal 3DxWare event-processing pipeline entirely, because (after extensive reverse-engineering) that pipeline was found to be non-functional for this NX/3DxWare version combination under Wine.
Result / current status
Real hardware SpaceMouse input drives 6DOF (rotate, pan, zoom) in NX, correctly axis-mapped, with no visible helper windows and no manual reconnect step beyond one initial "open a part and wiggle the knob" per NX session. This is considered production-usable. Two minor known cosmetic issues remain (see "Known limitations" below) but do not block normal use.
Architecture
SpaceMouse hardware (USB HID, VID 0x256F)
|
v
Wine RawInput (WM_INPUT), read directly by our shim's own background
thread -- NOT via 3DxNX.dll's internal pipeline
|
v
custom siappdll.dll (this project)
- satisfies 3DxNX.dll's expected siappdll device-API surface just
enough for it to initialize and hand control to us
- separately: its own RawInput listener thread parses SpaceMouse HID
reports (translation + rotation) directly
- marshals resulting 6DOF deltas onto NX's main UI thread (required --
calling NX Open C "set" APIs from a background thread crashes NX)
- applies them directly via NX Open C calls:
UF_VIEW_ask_rotation / UF_VIEW_set_rotation (rotate)
UF_VIEW_ask_center / UF_VIEW_set_center (pan)
UF_VIEW_set_scale (zoom)
UF_VIEW_ask_visible_objects + UF_MODL_ask_bounding_box
+ UF_VIEW_set_center
(one-time auto-recenter)
|
v
Siemens NX 2506 (via NXOpen C / libufun.dll, already loaded in-process)
The official 3DxNX.dll plugin is still present and still loaded by NX (we
deliberately keep using it rather than reimplementing NX plugin discovery),
but its own internal motion-delivery pipeline is not what actually moves
the viewport -- our shim's RawInput + NX Open C path does that instead.
Why a real device-API DLL replacement, and not just an NX plugin?
3DxNX.dll expects to load a vendor-provided siappdll.dll implementing the
classic 3DxWare "SpaceWare Input Library" C ABI (SiInitialize, SiOpen,
SiGetEvent, ...) plus a newer GetFactory/COM-ish object surface. Our
shim implements just enough of that surface for 3DxNX.dll to complete its
own initialization handshake (which is a real prerequisite -- NX/3DxNX
won't get far enough to even construct a device object without it), then
takes over motion delivery itself instead of relying on 3DxNX's own event
processing (which was proven dead for this configuration).
Why the magellan-window-helper.exe companion process?
3DxNX.dll performs a FindWindow check for a window of class
MAGELLAN_3D_CONTROLLER as part of its own driver-availability detection.
magellan-window-helper.exe is a small helper that registers a single
hidden (SW_HIDE) window of that class and otherwise does nothing. It
must be running (in the same Wine prefix) before NX starts. It has no
visible UI.
The "wiggle the knob" step
3DxWare's own device-connect handshake needs one real HID report to fully recognize the device each NX session. In practice: open any part, then gently move the SpaceMouse once. After that it stays connected for the rest of the session. This is the only manual step; NX does not need to be restarted, and there is no dialog to click through.
Known limitations
- Rotation pivot is auto-recentered once, automatically, to the model's bounding-box center on first SpaceMouse motion each session (no more manual "Fit" needed -- this used to be a manual step, now fixed).
- Zoom occasionally choppy specifically when combined with simultaneous
rotate/pan in the same motion (zoom alone, and rotate+pan alone, are
both smooth). Root cause not fully identified; two throttling strategies
were tried and did not help. A promising-looking undocumented API pair
(
UF_VIEW_ask_frustum/UF_VIEW_set_frustum) was investigated as a possible fix or alternative zoom mechanism:ask_frustumis safe and gives believable read data, butset_frustumcorrupts the view on even a single call (its exact semantics don't match the naive eye-point/direction/extent model reverse-engineered from disassembly) -- do not useUF_VIEW_set_frustumwithout a real documented signature. Zoom is implemented via the ordinaryUF_VIEW_set_scaleinstead. - Zoom can "jump" if you mix 2D-mouse zoom and SpaceMouse zoom in the
same session. Cause: there is no
UF_VIEW_ask_scaleexport, so the shim tracks its own relative scale value internally, which can desync from NX's true current scale if you zoom by other means. Workaround: stick to one zoom input method per session, or hit "Fit" to resync.
Prerequisites
Before running this installer, in the target Wine prefix you must already have:
- Siemens NX installed (e.g. under
<prefix>/drive_c/Program Files/Siemens/NX<version>/NXBIN/ugraf.exe). - The official 3Dconnexion 3DxWare driver package with the NX plugin
installed (provides
3DxNX.dllunder<prefix>/drive_c/Program Files/3Dconnexion/3DxWare/3DxNX/ugii_dir/v<version>/startup/, and the genuine vendorsiappdll.dllin NX'sNXBINdirectory). This project intentionally does not install or redistribute that driver -- only replaces the one low-level DLL it loads. - On the Linux side: the SpaceMouse must be usable as a raw USB HID device visible to Wine (no special Linux driver/daemon is required by this shim itself -- it reads the device directly via Wine's RawInput/HID support, which talks to the kernel HID device node).
- A build toolchain:
x86_64-w64-mingw32-gcc(MinGW cross compiler).
Install
cd installer
make CC=x86_64-w64-mingw32-gcc
WINEPREFIX=/path/to/your/wineprefix make install
(make install just runs scripts/install.sh; you can also invoke that
script directly with the prefix as an argument instead of the environment
variable.)
This will:
- Locate NX's
NXBINdirectory and confirm3DxNX.dllis present. - Back up the genuine vendor
siappdll.dlltosiappdll_vendor.dllin the same directory (only on first install -- safe to re-run). - Copy the freshly-built shim into
NXBIN/siappdll.dll. - Install
magellan-window-helper.exeunder<prefix>/drive_c/spacemouse-nx/. - Generate
build/start-nx.sh, a ready-to-use launcher for this prefix.
Running NX
./build/start-nx.sh
This kills any stray NX/helper processes in the prefix, starts the hidden helper, then starts NX. Wait roughly 90 seconds for NX to fully start, open any part, and gently wiggle the SpaceMouse once to connect it.
Uninstall
WINEPREFIX=/path/to/your/wineprefix make uninstall
Restores the genuine vendor siappdll.dll and removes the helper
directory. NX itself is untouched.
Directory layout
installer/
Makefile top-level build (siappdll.dll + helper .exe)
README.md this file
src/
siappdll.c the shim source (RawInput + NX Open C driver)
siappdll.def its DLL export table (SpaceWare ABI + factory)
magellan_window_helper.c the hidden helper window process
scripts/
install.sh installs into a target Wine prefix
uninstall.sh reverts an install
start-nx.sh.in template used to generate build/start-nx.sh
build/ (generated) compiled .dll/.exe + start-nx.sh
Rebuilding after source changes
make CC=x86_64-w64-mingw32-gcc clean all
WINEPREFIX=/path/to/your/wineprefix make install
./build/start-nx.sh
Always verify the deployed DLL's checksum matches the freshly built one
(install.sh prints an md5sum of both for this purpose) before testing,
to avoid testing a stale build.