Skip to content

Concurrent input and constraints

A camera can move through mouse input or application constraints while Rotatrix is navigating. If Rotatrix continues from an outdated pose, its next update can undo that movement. NavigationSession uses camera observations and write readback to keep Rotatrix aligned with the application’s actual state.

The demos demonstrate this with simultaneous mouse and Rotatrix input. The same mechanism applies to object edits.

With no object edit active, start a Rotatrix gesture and use middle/right-drag to orbit, Shift-drag to pan, or the wheel to zoom. Release the gesture while moving. Try perspective and orthographic views with D enabled. Movement should remain continuous, including the final pose after release.

During an object edit, mouse input changes the object instead. Its adapter uses the same observation/correction mechanism.

An observation callback reads the application’s current pose. A change notification tells NavigationSession when to read it, so native input can be incorporated even before the next server update. The integration registers these notifications at startup; the application emits them after its own input changes a pose.

Adapter writes already report their result directly and do not emit a second native-input notification.

After creating session, MyOpenAxisIntegration.start() assigns its notification methods to the application’s event hooks. The application invokes these hooks after native input changes a pose:

app.on_camera_changed = session.native_camera_changed
app.on_object_changed = session.native_object_changed

The observation=adapter.read callback reads the latest camera pose when NavigationSession handles a change notification.

The NavigationSession schedules an observation on the application thread. If the actual pose changed independently, it sends a correction and waits for acknowledgement before applying further output that depends on that correction.

An application may constrain a requested pose, for example by limiting camera height. The adapter returns the resulting pose so NavigationSession can correct Rotatrix’s state and continue from the constrained position.

The NavigationSession calls MyNavigationAdapter on the application thread to apply a pose. The complete adapter shows how it captures the application and reads its camera.

context is the captured MyApplication; desired is an SDK CameraPose. MyCamera is the application’s camera value type from application.py. self.read(context) uses the adapter’s existing read method to return an SDK pose:

def apply_camera(self, context, desired, navigation, pivot):
context.set_camera(MyCamera(desired.t, desired.r, desired.fov, desired.ortho_extent))
return WriteResult(True, self.read(context))
Application resultPythonC#TypeScript
Write succeeded; resulting pose knownWriteResult(True, actual)new NavigationWriteResult(true, actual){ success: true, realizedPose: actual }
Write succeeded; readback temporarily unavailableWriteResult(True)new NavigationWriteResult(true){ success: true }
Write failedWriteResult(False)new NavigationWriteResult(false){ success: false }

Unknown readback is retried on later observation while navigation continues optimistically. The examples normally return immediate readback; SDK tests cover unknown-readback recovery and failures.

Repeated conversions can introduce rounding differences without moving the visible camera. Comparison tolerances prevent these differences from generating continuous corrections while preserving meaningful motion. Their values depend on the application’s measured precision and camera representation.

Panda3D stores float32 transforms. The integration accounts for their precision with comparison and object_comparison callbacks.

These callables specialize the SDK’s compare and compare_object functions using functools.partial. MyOpenAxisIntegration.start() passes them to the NavigationSession; the SDK invokes them when comparing observed and requested poses:

compare_camera_pose = partial(compare, absolute=1e-6, relative=2e-7, angular=1e-6)
compare_object_pose = partial(compare_object, absolute=1e-6, relative=2e-7, angular=1e-6)

See write and observation contracts.

Manually verify simultaneous native and Rotatrix input, gesture release, reset, projection changes, object editing and operation invalidation. Application-specific constraints need their own tests. The SDK owns reconciliation and timeouts.

For automated commands and coverage, use the demo READMEs: Python, C#, TypeScript, and C++.