Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Lazy Picking for POINTERMOVE #13044

Merged
merged 29 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bf65e33
Lazy Pick on Move
PolygonalSun Sep 8, 2022
07785a7
Change to account for undefined
PolygonalSun Sep 8, 2022
757a531
cameras using DSM
PolygonalSun Sep 8, 2022
5c4cd98
Check for reasons to pick before picking
PolygonalSun Sep 8, 2022
ec05176
Addressed some feedback (missing meshUnderPointer)
PolygonalSun Sep 15, 2022
2fbd9db
Modified get meshUnderPointer
PolygonalSun Sep 16, 2022
166a60c
Add frame awareness picking for move
PolygonalSun Sep 17, 2022
a81875c
Merge branch 'master' into input-perf-test
PolygonalSun Sep 20, 2022
fa70f57
Caching Test
PolygonalSun Sep 27, 2022
d7d0986
Merge branch 'master' into input-perf-test
PolygonalSun Sep 27, 2022
b4db311
format
PolygonalSun Sep 27, 2022
0502afa
Merge branch 'input-perf-test' of https://github.com/PolygonalSun/Bab…
PolygonalSun Sep 27, 2022
fdf4934
Merge branch 'master' into input-perf-test
PolygonalSun Sep 28, 2022
568d43a
import fix
PolygonalSun Sep 28, 2022
5dd409d
Removed test code
PolygonalSun Sep 28, 2022
85c814f
PR Feedback
PolygonalSun Oct 6, 2022
0ccc7a2
fixed import
PolygonalSun Oct 6, 2022
a0ffe9c
removed gesture recognizer and reverted inputs
PolygonalSun Oct 7, 2022
51ee8cd
Revert videoDome because it uses picking info
PolygonalSun Oct 7, 2022
a9801ee
formatting
PolygonalSun Oct 7, 2022
3aab516
Changed to just MOVE Lazy Picking
PolygonalSun Oct 12, 2022
ee240e5
Format
PolygonalSun Oct 12, 2022
a3e5370
Removed comment
PolygonalSun Oct 12, 2022
f032d99
PR Feedback
PolygonalSun Oct 14, 2022
4a29d5a
Re-added meshunderpointer code back
PolygonalSun Oct 14, 2022
7b42a02
More feedback
PolygonalSun Oct 14, 2022
4d5dc2c
Comment
PolygonalSun Oct 14, 2022
eba0051
PR Feedback part 1
PolygonalSun Oct 17, 2022
dc3c171
comment
PolygonalSun Oct 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Addressed some feedback (missing meshUnderPointer)
  • Loading branch information
PolygonalSun committed Sep 15, 2022
commit ec05176925a4a6ea8d1dc14d1939f7b76b277589
4 changes: 2 additions & 2 deletions packages/dev/core/src/Actions/actionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export class ActionManager extends AbstractActionManager {
}

this.actions.push(action);
this.getScene()._registeredActionManagers++;
this.getScene()._registeredActions++;

if (ActionManager.Triggers[action.trigger]) {
ActionManager.Triggers[action.trigger]++;
Expand Down Expand Up @@ -302,7 +302,7 @@ export class ActionManager extends AbstractActionManager {
delete ActionManager.Triggers[action.trigger];
}
action._actionManager = null;
this.getScene()._registeredActionManagers--;
this.getScene()._registeredActions--;
return true;
}
return false;
Expand Down
33 changes: 15 additions & 18 deletions packages/dev/core/src/Events/pointerEvents.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { Nullable } from "../types";
import { Vector2 } from "../Maths/math.vector";
import type { PickingInfo } from "../Collisions/pickingInfo";
import type { IMouseEvent } from "./deviceInputEvents";
import type { IMouseEvent, IPointerEvent } from "./deviceInputEvents";
import type { InputManager } from "../Inputs/scene.inputManager";

declare type Ray = import("../Culling/ray").Ray;

Expand Down Expand Up @@ -104,35 +105,31 @@ export class PointerInfoPre extends PointerInfoBase {
* The event member is an instance of PointerEvent for all types except PointerWheel and is of type MouseWheelEvent when type equals PointerWheel. The different event types can be found in the PointerEventTypes class.
*/
export class PointerInfo extends PointerInfoBase {
private _getPickInfo: () => Nullable<PickingInfo>;
private _pickInfo: Nullable<PickingInfo>;
private _inputManager: Nullable<InputManager>;

/**
* Defines the picking info associated to the info (if any)
*/
public get pickInfo(): Nullable<PickingInfo> {
return this._getPickInfo();
if (this._inputManager) {
this._pickInfo = this._inputManager._pickMove((this.event as IPointerEvent).pointerId);
this._inputManager = null;
}

return this._pickInfo;
}
/**
* Instantiates a PointerInfo to store pointer related info to the onPointerObservable event.
* @param type Defines the type of event (PointerEventTypes)
* @param event Defines the related dom event
* @param pickInfo Defines the picking info associated to the info (if any)\
* @param pickInfo Defines the picking info associated to the info (if any)
* @param inputManager Defines the InputManager to use if there is no pickInfo
*/
constructor(type: number, event: IMouseEvent, pickInfo: Nullable<PickingInfo> | (() => Nullable<PickingInfo>)) {
constructor(type: number, event: IMouseEvent, pickInfo: Nullable<PickingInfo>, inputManager: Nullable<InputManager> = null) {
super(type, event);

if (typeof pickInfo === "function") {
let info: Nullable<PickingInfo> = null;
this._getPickInfo = () => {
if (!info) {
info = pickInfo();
}

return info;
};
} else {
this._getPickInfo = () => pickInfo;
}
this._pickInfo = pickInfo;
this._inputManager = inputManager;
}
}

Expand Down
141 changes: 74 additions & 67 deletions packages/dev/core/src/Inputs/scene.inputManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ import type { IKeyboardEvent, IMouseEvent, IPointerEvent } from "../Events/devic
import { DeviceSourceManager } from "../DeviceInput/InputDevices/deviceSourceManager";
import { EngineStore } from "../Engines/engineStore";

declare module "../scene" {
interface Scene {
/** @hidden */
_registeredActions: number;
}
}

declare type Scene = import("../scene").Scene;

/** @hidden */
Expand Down Expand Up @@ -63,6 +70,12 @@ export class InputManager {
/** If you need to check double click without raising a single click at first click, enable this flag */
public static ExclusiveDoubleClickMode = false;

/**
* @hidden
* This property keeps track of how many actions have been registered.
*/
public _numActions: number = 0;

/** This is a defensive check to not allow control attachment prior to an already active one. If already attached, previous control is unattached before attaching the new one. */
private _alreadyAttached = false;
private _alreadyAttachedTo: Nullable<HTMLElement>;
Expand Down Expand Up @@ -122,6 +135,8 @@ export class InputManager {
if (!this._scene) {
return;
}

this._scene._registeredActions = 0;
}

/**
Expand Down Expand Up @@ -187,7 +202,7 @@ export class InputManager {
this._unTranslatedPointerY = this._pointerY;
}

private _processPointerMove(pickResult: Nullable<PickingInfo> | (() => Nullable<PickingInfo>), evt: IPointerEvent) {
private _processPointerMove(pickResult: Nullable<PickingInfo>, evt: IPointerEvent) {
const scene = this._scene;
const engine = scene.getEngine();
const canvas = engine.getInputElement();
Expand All @@ -201,52 +216,32 @@ export class InputManager {
}
}

if (scene._registeredActionManagers > 0) {
pickResult = typeof pickResult === "function" ? pickResult() : pickResult;
}

if (typeof pickResult !== "function") {
const isMeshPicked = pickResult && pickResult.hit && pickResult.pickedMesh ? true : false;
if (isMeshPicked) {
scene.setPointerOverMesh(pickResult!.pickedMesh, evt.pointerId, pickResult);

if (!scene.doNotHandleCursors && canvas && this._pointerOverMesh) {
const actionManager = this._pointerOverMesh._getActionManagerForTrigger();
if (actionManager && actionManager.hasPointerTriggers) {
canvas.style.cursor = actionManager.hoverCursor || scene.hoverCursor;
}
}
} else {
scene.setPointerOverMesh(null, evt.pointerId, pickResult);
}
}
this._setCursorAndPointerOverMesh(pickResult, evt.pointerId, scene);

for (const step of scene._pointerMoveStage) {
const pr = typeof pickResult !== "function" ? pickResult : pickResult();
const isMeshPicked = pr && pr.hit && pr.pickedMesh ? true : false;
pickResult = step.action(this._unTranslatedPointerX, this._unTranslatedPointerY, pr, isMeshPicked, canvas);
const isMeshPicked = pickResult && pickResult.hit && pickResult.pickedMesh ? true : false;
pickResult = step.action(this._unTranslatedPointerX, this._unTranslatedPointerY, pickResult, isMeshPicked, canvas);
}

if (pickResult) {
const type = evt.type === "wheel" || evt.type === "mousewheel" || evt.type === "DOMMouseScroll" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;

if (scene.onPointerMove) {
const pr = typeof pickResult !== "function" ? pickResult : pickResult();
scene.onPointerMove(evt, pr!, type);
scene.onPointerMove(evt, pickResult, type);
}

if (scene.onPointerObservable.hasObservers()) {
const pi = new PointerInfo(type, evt, pickResult);
this._setRayOnPointerInfo(pi, typeof pickResult);
this._setRayOnPointerInfo(pi);
scene.onPointerObservable.notifyObservers(pi, type);
}
}
}

// Pointers handling
private _setRayOnPointerInfo(pointerInfo: PointerInfo, pickInfoType: string) {
private _setRayOnPointerInfo(pointerInfo: PointerInfo) {
const scene = this._scene;
if (pickInfoType === "object" && pointerInfo.pickInfo && scene._pickingAvailable) {
if (pointerInfo.pickInfo && scene._pickingAvailable) {
if (!pointerInfo.pickInfo.ray) {
pointerInfo.pickInfo.ray = scene.createPickingRay(pointerInfo.event.offsetX, pointerInfo.event.offsetY, Matrix.Identity(), scene.activeCamera);
}
Expand All @@ -271,6 +266,47 @@ export class InputManager {
}
}

/**
* @param pointerId Pointer Id to use as reference
* @param setMesh TODO
* @hidden
*/
public _pickMove(pointerId: number, setMesh: boolean = true): Nullable<PickingInfo> {
const scene = this._scene;
const pickResult = scene.pick(
this._unTranslatedPointerX,
this._unTranslatedPointerY,
scene.pointerMovePredicate,
false,
scene.cameraToUseForPointers,
scene.pointerMoveTrianglePredicate
);

if (setMesh) {
this._setCursorAndPointerOverMesh(pickResult, pointerId, scene);
}

return pickResult;
}

private _setCursorAndPointerOverMesh(pickResult: Nullable<PickingInfo>, pointerId: number, scene: Scene) {
const engine = scene.getEngine();
const canvas = engine.getInputElement();

if (pickResult && pickResult.hit && pickResult.pickedMesh) {
this.setPointerOverMesh(pickResult.pickedMesh, pointerId, pickResult);

if (!scene.doNotHandleCursors && canvas && this._pointerOverMesh) {
const actionManager = this._pointerOverMesh._getActionManagerForTrigger();
if (actionManager && actionManager.hasPointerTriggers) {
canvas.style.cursor = actionManager.hoverCursor || scene.hoverCursor;
}
}
} else {
this.setPointerOverMesh(null, pointerId, pickResult);
}
}

/**
* Use this method to simulate a pointer move on a mesh
* The pickResult parameter can be obtained from a scene.pick or scene.pickWithRay
Expand Down Expand Up @@ -367,7 +403,7 @@ export class InputManager {

if (scene.onPointerObservable.hasObservers()) {
const pi = new PointerInfo(type, evt, pickResult);
this._setRayOnPointerInfo(pi, typeof pickResult);
this._setRayOnPointerInfo(pi);
scene.onPointerObservable.notifyObservers(pi, type);
}
}
Expand Down Expand Up @@ -420,7 +456,7 @@ export class InputManager {
if (clickInfo.singleClick && !clickInfo.ignore && scene.onPointerObservable.hasObservers()) {
const type = PointerEventTypes.POINTERPICK;
const pi = new PointerInfo(type, evt, pickResult);
this._setRayOnPointerInfo(pi, typeof pickResult);
this._setRayOnPointerInfo(pi);
scene.onPointerObservable.notifyObservers(pi, type);
}
}
Expand Down Expand Up @@ -462,15 +498,15 @@ export class InputManager {
}
if (type) {
const pi = new PointerInfo(type, evt, pickResult);
this._setRayOnPointerInfo(pi, typeof pickResult);
this._setRayOnPointerInfo(pi);
scene.onPointerObservable.notifyObservers(pi, type);
}
}

if (!clickInfo.ignore) {
type = PointerEventTypes.POINTERUP;
const pi = new PointerInfo(type, evt, pickResult);
this._setRayOnPointerInfo(pi, typeof pickResult);
this._setRayOnPointerInfo(pi);
scene.onPointerObservable.notifyObservers(pi, type);
}
}
Expand Down Expand Up @@ -516,9 +552,10 @@ export class InputManager {
// Because this is only called from _initClickEvent, which is called in _onPointerUp, we'll use the pointerUpPredicate for the pick call
this._initActionManager = (act: Nullable<AbstractActionManager>): Nullable<AbstractActionManager> => {
if (!this._meshPickProceed) {
const pickResult = scene.skipPointerUpPicking || (scene._registeredActionManagers === 0 && !scene.onPointerObservable.hasObservers())
? null
: scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerUpPredicate, false, scene.cameraToUseForPointers);
const pickResult =
scene.skipPointerUpPicking || (scene._registeredActions === 0 && !scene.onPointerObservable.hasObservers())
? null
: scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerUpPredicate, false, scene.cameraToUseForPointers);
this._currentPickResult = pickResult;
if (pickResult) {
act = pickResult.hit && pickResult.pickedMesh ? pickResult.pickedMesh._getActionManagerForTrigger() : null;
Expand Down Expand Up @@ -694,37 +731,7 @@ export class InputManager {
(!scene.cameraToUseForPointers || (scene.cameraToUseForPointers.layerMask & mesh.layerMask) !== 0);
}

// Meshes
const pickResult = () => {
const scene = this._scene;
const engine = scene.getEngine();
const canvas = engine.getInputElement();
const pr = scene.pick(
this._unTranslatedPointerX,
this._unTranslatedPointerY,
scene.pointerMovePredicate,
false,
scene.cameraToUseForPointers,
scene.pointerMoveTrianglePredicate
);

const isMeshPicked = pr && pr.hit && pr.pickedMesh ? true : false;
if (isMeshPicked && typeof pickResult !== "function") {
scene.setPointerOverMesh(pr!.pickedMesh, (evt as IPointerEvent).pointerId, pickResult);

if (!scene.doNotHandleCursors && canvas && this._pointerOverMesh) {
const actionManager = this._pointerOverMesh._getActionManagerForTrigger();
if (actionManager && actionManager.hasPointerTriggers) {
canvas.style.cursor = actionManager.hoverCursor || scene.hoverCursor;
}
}
} else {
scene.setPointerOverMesh(null, (evt as IPointerEvent).pointerId, pr);
}

return pr;
};

const pickResult = scene._registeredActions > 0 ? this._pickMove((evt as IPointerEvent).pointerId) : null;
this._processPointerMove(pickResult, evt as IPointerEvent);
};

Expand Down Expand Up @@ -775,7 +782,7 @@ export class InputManager {
// Meshes
this._pickedDownMesh = null;
let pickResult;
if (scene.skipPointerDownPicking || (scene._registeredActionManagers === 0 && !scene.onPointerObservable.hasObservers())) {
if (scene.skipPointerDownPicking || (scene._registeredActions === 0 && !scene.onPointerObservable.hasObservers())) {
pickResult = new PickingInfo();
} else {
pickResult = scene.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, scene.pointerDownPredicate, false, scene.cameraToUseForPointers);
Expand Down
3 changes: 0 additions & 3 deletions packages/dev/core/src/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4884,9 +4884,6 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
return false;
}

/** @hidden */
public _registeredActionManagers: number = 0;

/** Launch a ray to try to pick a mesh in the scene
* @param x position on screen
* @param y position on screen
Expand Down