Platform
Android
Module
sceneview (3D only)
SceneView version
4.12.0
Device / OS
Galaxy s21 ultra - Android 15
What happened?
When updating a Node's quaternion continuously inside an onFrame loop (e.g., for a 120Hz gesture-driven object rotation), the node's visual mesh slowly warps and skews over time, drifting away from its true mathematical center and shape.
The root cause is in Node.kt. The setter for quaternion relies on reading the position and scale properties to compose a new Transform:
open var quaternion: Quaternion
get() = transform.quaternion
set(value) {
transform = Transform(position, value, scale)
}
Because position and scale fetch their values by decomposing the underlying Filament 4x4 Matrix (transformManager.getTransform()), floating-point imprecision accumulates. Reading and rewriting the decomposed scale 120 times a second causes it to decay (e.g., from 1.0 to 0.99999...), physically skewing the rendered node over time.
What did you expect?
Updating node.quaternion should strictly update the rotation without causing floating-point decay in scale and position. Node.kt should ideally cache local position, quaternion, and scale as pristine backing fields in memory, and compose the Transform from those fields rather than decomposing the Filament 4x4 matrix every time a single property is updated.
Steps to reproduce
1. Create a Node (e.g., attach a 3D sphere or mesh to it).
2. Inside an onFrame callback, continuously update node.quaternion (e.g., spinning it rapidly or driving it via continuous touch gestures).
3. Observe the 3D model over a short period of continuous rotation; it will visually distort and stretch on its axes (most noticeable when precision is needed).
4. Proof of issue: The distortion can be completely stopped setting the transform directly with clean values:
// This decays and skews the mesh because the setter internally reads the dirty position/scale:
node.quaternion = newQuaternion
// This completely fixes it and keeps the mesh pristine, while also saving JNI calls:
node.transform = Transform(
position = Position(0f),
quaternion = newQuaternion,
scale = Scale(1f)
)
Logs / stack trace
This is the specific block in Node.kt causing the precision loss loop:
open var quaternion: Quaternion
get() = transform.quaternion
set(value) {
// Calling `position` and `scale` here triggers matrix decomposition
// from the C++ engine, pulling floating-point inaccuracies into the new Transform.
transform = Transform(position, value, scale)
}
Screenshots / screen recordings
No response
Platform
Android
Module
sceneview (3D only)
SceneView version
4.12.0
Device / OS
Galaxy s21 ultra - Android 15
What happened?
When updating a Node's quaternion continuously inside an onFrame loop (e.g., for a 120Hz gesture-driven object rotation), the node's visual mesh slowly warps and skews over time, drifting away from its true mathematical center and shape.
The root cause is in Node.kt. The setter for quaternion relies on reading the position and scale properties to compose a new Transform:
Because position and scale fetch their values by decomposing the underlying Filament 4x4 Matrix (transformManager.getTransform()), floating-point imprecision accumulates. Reading and rewriting the decomposed scale 120 times a second causes it to decay (e.g., from 1.0 to 0.99999...), physically skewing the rendered node over time.
What did you expect?
Updating node.quaternion should strictly update the rotation without causing floating-point decay in scale and position. Node.kt should ideally cache local position, quaternion, and scale as pristine backing fields in memory, and compose the Transform from those fields rather than decomposing the Filament 4x4 matrix every time a single property is updated.
Steps to reproduce
Logs / stack trace
Screenshots / screen recordings
No response