pmndrs / pmndrs/three-stdlib

OrbitControls touch crashes on Expo mobile app

Open
#426 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
JavaScript
Stars
858
Forks
144
PR merge metrics
No merged PRs in 30d

Description

  • three version: ^0.166.1
  • @types/three version: 0.183.1
  • three-stdlib version: ^2.35.6
Problem description:

As previously reported by @damistheanswer in the issue https://github.com/mrdoob/three.js/issues/32116, OrbitControls does crash a mobile app on touch devices, such tablets and iPads, when using multi-touches to zoom in/zoom out an object.
I got the same message such as:

TypeError: Cannot read properties of undefined (reading 'x')

Reproduction steps
  1. Download the sample project or the apk file
  2. Start a two-finger pinch gesture (pinch-to-zoom)
  3. Lift one finger mid-gesture while the other finger remains touching
  4. The error occurs sporadically when the second pointer position becomes undefined
Relevant code:

Same as the issue #32116

In OrbitControls.js, the _getSecondPointerPosition() method returns undefined when a pointer is no longer tracked:

// Line ~1407-1411
_getSecondPointerPosition( event ) {
    const pointerId = ( event.pointerId === this._pointers[ 0 ] ) ? this._pointers[ 1 ] : this._pointers[ 0 ];
    return this._pointerPositions[ pointerId ]; // Can return undefined!
}

This undefined value is then used without null checking in multiple places:

// Line ~1234-1238 (handleTouchMoveDolly)
const position = this._getSecondPointerPosition( event );
const dx = event.pageX - position.x; // ❌ Crash: position is undefined
const dy = event.pageY - position.y;

Similar crashes occur at:

  • Line 1202-1204 (handleTouchStartRotate)
  • Line 1221-1223 (handleTouchStartPan)
  • Line 1269-1271 (handleTouchMoveRotate)
  • Line 1298-1300 (handleTouchMovePan)
  • Line 1317-1320 (handleTouchMoveDolly)
Live example

Same as the issue #32116:

  1. User starts two-finger gesture → both pointers tracked in _pointers array
  2. User lifts one finger → pointer is removed from _pointers
  3. Move event fires for remaining finger → tries to get second pointer position
  4. _pointerPositions[pointerId] returns undefined because pointer was removed
  5. Code attempts position.x → crash
Screenshots

Attached error on expo app:

Image

Please check this video for demonstration of the bug:

Device

Mobile

OS

Android

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in OrbitControls.js at _getSecondPointerPosition() and the listed touch handlers, then reproduce the two-finger pinch and finger-lift sequence with the linked Expo sample project. Done means the gesture no longer crashes when the second pointer position is undefined, including the listed rotate, pan, and dolly paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, three.js
Domain
frontend, mobile-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.