@needle-tools/engine 2.35.4-pre → 2.36.0-pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/needle-engine.d.ts +213 -144
- package/dist/needle-engine.js +414 -358
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +99 -43
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/api.d.ts +3 -0
- package/lib/engine/api.js +3 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.d.ts +3 -0
- package/lib/engine/debug/debug.js +8 -0
- package/lib/engine/debug/debug.js.map +1 -0
- package/lib/engine/debug/debug_overlay.d.ts +7 -0
- package/lib/engine/debug/debug_overlay.js +213 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -0
- package/lib/engine/engine.js +1 -1
- package/lib/engine/engine.js.map +1 -1
- package/lib/engine/engine_element_loading.js +1 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +1 -0
- package/lib/engine/engine_gameobject.js +13 -1
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +4 -0
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.d.ts +1 -1
- package/lib/engine/engine_mainloop_utils.js +7 -3
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +29 -28
- package/lib/engine/engine_physics.js +85 -86
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +43 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +1 -1
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_time.d.ts +1 -0
- package/lib/engine/engine_time.js +1 -0
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_types.d.ts +6 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_typestore.d.ts +1 -0
- package/lib/engine/engine_typestore.js +1 -0
- package/lib/engine/engine_typestore.js.map +1 -1
- package/lib/engine/engine_utils.js +1 -1
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_render_objects.d.ts +2 -2
- package/lib/engine/extensions/NEEDLE_render_objects.js +2 -2
- package/lib/engine/extensions/NEEDLE_render_objects.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +5 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +5 -1
- package/lib/engine-components/Animation.js +21 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +1 -0
- package/lib/engine-components/AnimatorController.js +14 -7
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -1
- package/lib/engine-components/AudioSource.js +2 -2
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.d.ts +2 -2
- package/lib/engine-components/BoxHelperComponent.js +27 -9
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Component.d.ts +2 -1
- package/lib/engine-components/Component.js +11 -5
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +2 -0
- package/lib/engine-components/GroundProjection.js +18 -6
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +22 -0
- package/lib/engine-components/ReflectionProbe.js +134 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -0
- package/lib/engine-components/Renderer.d.ts +16 -4
- package/lib/engine-components/Renderer.js +96 -45
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +7 -7
- package/lib/engine-components/WebARSessionRoot.js +7 -7
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +9 -8
- package/lib/engine-components/WebXR.js +40 -24
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.d.ts +4 -5
- package/lib/engine-components/WebXRAvatar.js +9 -8
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.d.ts +21 -21
- package/lib/engine-components/WebXRController.js +83 -63
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRGrabRendering.d.ts +3 -3
- package/lib/engine-components/WebXRGrabRendering.js +2 -2
- package/lib/engine-components/WebXRGrabRendering.js.map +1 -1
- package/lib/engine-components/WebXRSync.d.ts +8 -8
- package/lib/engine-components/WebXRSync.js +15 -15
- package/lib/engine-components/WebXRSync.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/js-extensions/ExtensionUtils.js +1 -1
- package/lib/engine-components/js-extensions/ExtensionUtils.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +1 -0
- package/lib/engine-components/ui/EventSystem.js +21 -1
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/api.ts +3 -0
- package/src/engine/codegen/register_types.js +293 -0
- package/src/engine/debug/debug.ts +9 -0
- package/src/engine/debug/debug_overlay.ts +224 -0
- package/src/engine/engine.ts +1 -1
- package/src/engine/engine_element_loading.ts +1 -1
- package/src/engine/engine_gameobject.ts +17 -4
- package/src/engine/engine_gltf_builtin_components.ts +5 -1
- package/src/engine/engine_mainloop_utils.ts +7 -3
- package/src/engine/engine_physics.ts +130 -130
- package/src/engine/engine_serialization_core.ts +41 -0
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_time.ts +2 -0
- package/src/engine/engine_types.ts +7 -1
- package/src/engine/engine_typestore.ts +2 -0
- package/src/engine/engine_utils.ts +3 -2
- package/src/engine/extensions/EXT_texture_exr.js +1 -1
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +2 -1
- package/src/engine/extensions/NEEDLE_render_objects.ts +4 -4
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +7 -0
- package/src/engine-components/Animation.ts +16 -1
- package/src/engine-components/AnimatorController.ts +19 -9
- package/src/engine-components/AudioSource.ts +3 -3
- package/src/engine-components/BoxHelperComponent.ts +29 -9
- package/src/engine-components/Component.ts +11 -5
- package/src/engine-components/GroundProjection.ts +22 -7
- package/src/engine-components/ReflectionProbe.ts +141 -0
- package/src/engine-components/Renderer.ts +116 -54
- package/src/engine-components/WebARSessionRoot.ts +16 -16
- package/src/engine-components/WebXR.ts +53 -48
- package/src/engine-components/WebXRAvatar.ts +16 -16
- package/src/engine-components/WebXRController.ts +133 -107
- package/src/engine-components/WebXRGrabRendering.ts +6 -6
- package/src/engine-components/WebXRSync.ts +20 -20
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/js-extensions/ExtensionUtils.ts +1 -1
- package/src/engine-components/ui/EventSystem.ts +26 -3
- package/lib/engine/debug/error_overlay.d.ts +0 -1
- package/lib/engine/debug/error_overlay.js +0 -114
- package/lib/engine/debug/error_overlay.js.map +0 -1
- package/src/engine/debug/error_overlay.ts +0 -126
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
|
2
2
|
import { WebXR } from "./WebXR";
|
|
3
|
-
import
|
|
3
|
+
import { Quaternion, Vector3 } from "three";
|
|
4
4
|
import { AvatarLoader } from "./AvatarLoader";
|
|
5
5
|
import { XRFlag, XRStateFlag } from "./XRFlag";
|
|
6
6
|
import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt";
|
|
@@ -45,7 +45,7 @@ export class AvatarMarker extends Behaviour {
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
public connectionId!: string;
|
|
48
|
-
public avatar?: WebXRAvatar |
|
|
48
|
+
public avatar?: WebXRAvatar | Object3D;
|
|
49
49
|
|
|
50
50
|
awake() {
|
|
51
51
|
AvatarMarker.instances.push(this);
|
|
@@ -94,16 +94,16 @@ export class WebXRAvatar {
|
|
|
94
94
|
/** the user id */
|
|
95
95
|
public guid: string;
|
|
96
96
|
|
|
97
|
-
private root:
|
|
98
|
-
public head:
|
|
99
|
-
public handLeft:
|
|
100
|
-
public handRight:
|
|
97
|
+
private root: Object3D | null = null;
|
|
98
|
+
public head: Object3D | null = null;
|
|
99
|
+
public handLeft: Object3D | null = null;
|
|
100
|
+
public handRight: Object3D | null = null;
|
|
101
101
|
public lastUpdate: number = -1;
|
|
102
102
|
public isLocalAvatar: boolean = false;
|
|
103
103
|
public flags: XRFlag[] | null = null;
|
|
104
|
-
private headScale:
|
|
105
|
-
private handLeftScale:
|
|
106
|
-
private handRightScale:
|
|
104
|
+
private headScale: Vector3 = new Vector3(1, 1, 1);
|
|
105
|
+
private handLeftScale: Vector3 = new Vector3(1, 1, 1);
|
|
106
|
+
private handRightScale: Vector3 = new Vector3(1, 1, 1);
|
|
107
107
|
|
|
108
108
|
private readonly webxr: WebXR;
|
|
109
109
|
|
|
@@ -142,12 +142,12 @@ export class WebXRAvatar {
|
|
|
142
142
|
return null;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
private _headTarget:
|
|
146
|
-
private _handLeftTarget:
|
|
147
|
-
private _handRightTarget:
|
|
145
|
+
private _headTarget: Object3D = new Object3D();
|
|
146
|
+
private _handLeftTarget: Object3D = new Object3D();
|
|
147
|
+
private _handRightTarget: Object3D = new Object3D();
|
|
148
148
|
private _canInterpolate: boolean = false;
|
|
149
149
|
|
|
150
|
-
private static invertRotation:
|
|
150
|
+
private static invertRotation: Quaternion = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI);
|
|
151
151
|
|
|
152
152
|
public tryUpdate(state: VRUserState, _timeDiff: number) {
|
|
153
153
|
if (state.guid === this.guid) {
|
|
@@ -247,7 +247,7 @@ export class WebXRAvatar {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
private async setupCustomAvatar(avatarId: string |
|
|
250
|
+
private async setupCustomAvatar(avatarId: string | Object3D | AssetReference): Promise<boolean> {
|
|
251
251
|
if (debug)
|
|
252
252
|
console.log("LOAD", avatarId, this);
|
|
253
253
|
|
|
@@ -263,14 +263,14 @@ export class WebXRAvatar {
|
|
|
263
263
|
await reference.loadAssetAsync();
|
|
264
264
|
const prefab = reference.asset as Object3D;
|
|
265
265
|
GameObject.setActive(prefab, false);
|
|
266
|
-
avatarId = GameObject.instantiate(prefab as Object3D) as
|
|
266
|
+
avatarId = GameObject.instantiate(prefab as Object3D) as Object3D;
|
|
267
267
|
GameObject.setActive(avatarId, true);
|
|
268
268
|
// console.log("Avatar", avatarId);
|
|
269
269
|
}
|
|
270
270
|
if (debug)
|
|
271
271
|
console.log(avatarId);
|
|
272
272
|
|
|
273
|
-
const model = await WebXRAvatar.loader.getOrCreateNewAvatarInstance(this.context, avatarId as (
|
|
273
|
+
const model = await WebXRAvatar.loader.getOrCreateNewAvatarInstance(this.context, avatarId as (Object3D | string));
|
|
274
274
|
if (debug)
|
|
275
275
|
console.log(model, model?.isValid, this.lastAvatarId, avatarId);
|
|
276
276
|
// if (this.lastAvatarId !== avatarId) {
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { WebXR } from "./WebXR";
|
|
3
|
-
import * as THREE from "three";
|
|
4
|
-
import { SyncedTransform } from "./SyncedTransform";
|
|
5
|
-
import { Physics, RaycastOptions } from "../engine/engine_physics";
|
|
6
|
-
import { XRControllerModel, XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js';
|
|
1
|
+
import { BoxHelper, BufferGeometry, Color, Euler, Group, Intersection, Layers, Line, LineBasicMaterial, Material, Mesh, MeshBasicMaterial, Object3D, PerspectiveCamera, Quaternion, Ray, SphereGeometry, Vector2, Vector3, XRInputSource, XRSession } from "three";
|
|
7
2
|
import { OculusHandModel } from 'three/examples/jsm/webxr/OculusHandModel.js';
|
|
8
3
|
import { OculusHandPointerModel } from 'three/examples/jsm/webxr/OculusHandPointerModel.js';
|
|
9
|
-
import {
|
|
10
|
-
|
|
4
|
+
import { XRControllerModel, XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js';
|
|
5
|
+
|
|
6
|
+
import { InstancingUtil } from "../engine/engine_instancing";
|
|
11
7
|
import { Mathf } from "../engine/engine_math";
|
|
12
|
-
import
|
|
8
|
+
import { RaycastOptions } from "../engine/engine_physics";
|
|
9
|
+
import { getWorldPosition, getWorldQuaternion, setWorldPosition, setWorldQuaternion } from "../engine/engine_three_utils";
|
|
10
|
+
import { getParam, getPath } from "../engine/engine_utils";
|
|
11
|
+
|
|
12
|
+
import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt";
|
|
13
|
+
import { Behaviour, GameObject } from "./Component";
|
|
13
14
|
import { Interactable, UsageMarker } from "./Interactable";
|
|
14
|
-
import { InstancingUtil } from "../engine/engine_instancing";
|
|
15
15
|
import { Rigidbody } from "./RigidBody";
|
|
16
|
-
import {
|
|
16
|
+
import { SyncedTransform } from "./SyncedTransform";
|
|
17
17
|
import { UIRaycastUtils } from "./ui/RaycastUtils";
|
|
18
|
-
import {
|
|
18
|
+
import { WebXR } from "./WebXR";
|
|
19
19
|
|
|
20
20
|
const debug = getParam("debugwebxrcontroller");
|
|
21
21
|
|
|
@@ -38,28 +38,28 @@ export class WebXRController extends Behaviour {
|
|
|
38
38
|
|
|
39
39
|
public static Factory: XRControllerModelFactory = new XRControllerModelFactory();
|
|
40
40
|
|
|
41
|
-
private static raycastColor:
|
|
42
|
-
private static raycastNoHitColor:
|
|
43
|
-
private static geometry = new
|
|
41
|
+
private static raycastColor: Color = new Color(.9, .3, .3);
|
|
42
|
+
private static raycastNoHitColor: Color = new Color(.6, .6, .6);
|
|
43
|
+
private static geometry = new BufferGeometry().setFromPoints([new Vector3(0, 0, 0), new Vector3(0, 0, -1)]);
|
|
44
44
|
private static handModels: { [index: number]: OculusHandPointerModel } = {};
|
|
45
45
|
|
|
46
|
-
private static CreateRaycastLine():
|
|
47
|
-
const line = new
|
|
48
|
-
const mat = line.material as
|
|
46
|
+
private static CreateRaycastLine(): Line {
|
|
47
|
+
const line = new Line(this.geometry);
|
|
48
|
+
const mat = line.material as LineBasicMaterial;
|
|
49
49
|
mat.color = this.raycastColor;
|
|
50
50
|
// mat.linewidth = 10;
|
|
51
|
-
line.layers.set(
|
|
51
|
+
line.layers.set(2);
|
|
52
52
|
line.name = 'line';
|
|
53
53
|
line.scale.z = 1;
|
|
54
54
|
return line;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
private static CreateRaycastHitPoint():
|
|
58
|
-
const geometry = new
|
|
59
|
-
const material = new
|
|
60
|
-
const sphere = new
|
|
57
|
+
private static CreateRaycastHitPoint(): Mesh {
|
|
58
|
+
const geometry = new SphereGeometry(.5, 22, 22);
|
|
59
|
+
const material = new MeshBasicMaterial({ color: this.raycastColor });
|
|
60
|
+
const sphere = new Mesh(geometry, material);
|
|
61
61
|
sphere.visible = false;
|
|
62
|
-
sphere.layers.set(
|
|
62
|
+
sphere.layers.set(2);
|
|
63
63
|
return sphere;
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -71,7 +71,7 @@ export class WebXRController extends Behaviour {
|
|
|
71
71
|
ctrl.type = type;
|
|
72
72
|
|
|
73
73
|
const context = owner.context;
|
|
74
|
-
// from https://github.com/mrdoob/
|
|
74
|
+
// from https://github.com/mrdoob/js/blob/master/examples/webxr_vr_dragging.html
|
|
75
75
|
// controllers
|
|
76
76
|
ctrl.controller = context.renderer.xr.getController(index);
|
|
77
77
|
ctrl.controllerGrip = context.renderer.xr.getControllerGrip(index);
|
|
@@ -79,23 +79,29 @@ export class WebXRController extends Behaviour {
|
|
|
79
79
|
ctrl.controllerGrip.add(ctrl.controllerModel);
|
|
80
80
|
|
|
81
81
|
ctrl.hand = context.renderer.xr.getHand(index);
|
|
82
|
-
|
|
82
|
+
const hand = new OculusHandModel(ctrl.hand);
|
|
83
|
+
if (ctrl.webXR.handModelPath && ctrl.webXR.handModelPath !== "")
|
|
84
|
+
hand["path"] = "/" + getPath(owner.sourceId, ctrl.webXR.handModelPath);
|
|
85
|
+
ctrl.hand.add(hand);
|
|
83
86
|
ctrl.hand.traverse(x => x.layers.set(2));
|
|
84
87
|
|
|
85
88
|
ctrl.handPointerModel = new OculusHandPointerModel(ctrl.hand, ctrl.controller);
|
|
86
89
|
|
|
87
90
|
|
|
88
|
-
// TODO remove all these once https://github.com/mrdoob/
|
|
91
|
+
// TODO remove all these once https://github.com/mrdoob/js/pull/23279 lands
|
|
89
92
|
ctrl.controller.addEventListener('connected', (_) => {
|
|
90
93
|
ctrl.setControllerLayers(ctrl.controllerModel, 2);
|
|
91
94
|
ctrl.setControllerLayers(ctrl.controllerGrip, 2);
|
|
95
|
+
ctrl.setControllerLayers(ctrl.hand, 2);
|
|
92
96
|
setTimeout(() => {
|
|
97
|
+
ctrl.setControllerLayers(ctrl.controllerModel, 2);
|
|
93
98
|
ctrl.setControllerLayers(ctrl.controllerGrip, 2);
|
|
99
|
+
ctrl.setControllerLayers(ctrl.hand, 2);
|
|
94
100
|
}, 1000);
|
|
95
101
|
});
|
|
96
102
|
|
|
97
103
|
// TODO: unsubscribe! this should be moved into onenable and ondisable!
|
|
98
|
-
// TODO remove all these once https://github.com/mrdoob/
|
|
104
|
+
// TODO remove all these once https://github.com/mrdoob/js/pull/23279 lands
|
|
99
105
|
ctrl.hand.addEventListener('connected', (event) => {
|
|
100
106
|
const xrInputSource = event.data;
|
|
101
107
|
if (xrInputSource.hand) {
|
|
@@ -142,12 +148,12 @@ export class WebXRController extends Behaviour {
|
|
|
142
148
|
public webXR!: WebXR;
|
|
143
149
|
public index: number = -1;
|
|
144
150
|
public controllerModel!: XRControllerModel;
|
|
145
|
-
public controller!:
|
|
146
|
-
public controllerGrip!:
|
|
147
|
-
public hand!:
|
|
151
|
+
public controller!: Group;
|
|
152
|
+
public controllerGrip!: Group;
|
|
153
|
+
public hand!: Group;
|
|
148
154
|
public handPointerModel!: OculusHandPointerModel;
|
|
149
155
|
public grabbed: AttachedObject | null = null;
|
|
150
|
-
public input:
|
|
156
|
+
public input: XRInputSource | null = null;
|
|
151
157
|
public type: ControllerType = ControllerType.PhysicalDevice;
|
|
152
158
|
|
|
153
159
|
get isUsingHands(): boolean {
|
|
@@ -155,35 +161,35 @@ export class WebXRController extends Behaviour {
|
|
|
155
161
|
return r !== null && r !== undefined;
|
|
156
162
|
}
|
|
157
163
|
|
|
158
|
-
get wrist():
|
|
164
|
+
get wrist(): Object3D | null {
|
|
159
165
|
if (!this.hand) return null;
|
|
160
166
|
const jnts = this.hand["joints"];
|
|
161
167
|
if (!jnts) return null;
|
|
162
168
|
return jnts["wrist"];
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
private _wristQuaternion:
|
|
166
|
-
getWristQuaternion():
|
|
171
|
+
private _wristQuaternion: Quaternion | null = null;
|
|
172
|
+
getWristQuaternion(): Quaternion | null {
|
|
167
173
|
const wrist = this.wrist;
|
|
168
174
|
if (!wrist) return null;
|
|
169
|
-
if (!this._wristQuaternion) this._wristQuaternion = new
|
|
170
|
-
const wr =
|
|
175
|
+
if (!this._wristQuaternion) this._wristQuaternion = new Quaternion();
|
|
176
|
+
const wr = getWorldQuaternion(wrist).multiply(this._wristQuaternion.setFromEuler(new Euler(-Math.PI / 4, 0, 0)));
|
|
171
177
|
return wr;
|
|
172
178
|
}
|
|
173
179
|
|
|
174
|
-
private movementVector:
|
|
175
|
-
private worldRot:
|
|
176
|
-
private joystick:
|
|
180
|
+
private movementVector: Vector3 = new Vector3();
|
|
181
|
+
private worldRot: Quaternion = new Quaternion();
|
|
182
|
+
private joystick: Vector2 = new Vector2();
|
|
177
183
|
private didRotate: boolean = false;
|
|
178
184
|
private didTeleport: boolean = false;
|
|
179
185
|
private didChangeScale: boolean = false;
|
|
180
186
|
private static PreviousCameraFarDistance: number | undefined = undefined;
|
|
181
187
|
private static MovementSpeedFactor: number = 1;
|
|
182
188
|
|
|
183
|
-
private lastHit:
|
|
189
|
+
private lastHit: Intersection | null = null;
|
|
184
190
|
|
|
185
|
-
private raycastLine:
|
|
186
|
-
private _raycastHitPoint:
|
|
191
|
+
private raycastLine: Line | null = null;
|
|
192
|
+
private _raycastHitPoint: Object3D | null = null;
|
|
187
193
|
private _connnectedCallback: any | null = null;
|
|
188
194
|
private _disconnectedCallback: any | null = null;
|
|
189
195
|
private _selectStartEvt: any | null = null;
|
|
@@ -193,7 +199,7 @@ export class WebXRController extends Behaviour {
|
|
|
193
199
|
public get selectionUp(): boolean { return !this._selectionPressed && this._selectionPressedLastFrame; }
|
|
194
200
|
public get selectionPressed(): boolean { return this._selectionPressed; }
|
|
195
201
|
public get selectionClick(): boolean { return this._selectionEndTime - this._selectionStartTime < 0.3; }
|
|
196
|
-
public get raycastHitPoint():
|
|
202
|
+
public get raycastHitPoint(): Object3D | null { return this._raycastHitPoint; }
|
|
197
203
|
|
|
198
204
|
private _selectionPressed: boolean = false;
|
|
199
205
|
private _selectionPressedLastFrame: boolean = false;
|
|
@@ -334,7 +340,7 @@ export class WebXRController extends Behaviour {
|
|
|
334
340
|
}
|
|
335
341
|
}
|
|
336
342
|
|
|
337
|
-
rayRotation:
|
|
343
|
+
rayRotation: Quaternion = new Quaternion();
|
|
338
344
|
|
|
339
345
|
update(): void {
|
|
340
346
|
|
|
@@ -355,8 +361,13 @@ export class WebXRController extends Behaviour {
|
|
|
355
361
|
let t = 1;
|
|
356
362
|
if (this.type === ControllerType.PhysicalDevice) t = this.context.time.deltaTime / .1;
|
|
357
363
|
else if (this.isUsingHands && this.handPointerModel.pinched) t = this.context.time.deltaTime / .3;
|
|
358
|
-
this.rayRotation.slerp(
|
|
359
|
-
const wp =
|
|
364
|
+
this.rayRotation.slerp(getWorldQuaternion(this.controller), this.useSmoothing ? t : 1.0);
|
|
365
|
+
const wp = getWorldPosition(this.controller);
|
|
366
|
+
|
|
367
|
+
// hide hand pointer model, it's giant and doesn't really help
|
|
368
|
+
if (this.isUsingHands && this.handPointerModel.cursorObject) {
|
|
369
|
+
this.handPointerModel.cursorObject.visible = false;
|
|
370
|
+
}
|
|
360
371
|
|
|
361
372
|
if (this.raycastLine) {
|
|
362
373
|
if (this.type === ControllerType.Touch) {
|
|
@@ -364,7 +375,7 @@ export class WebXRController extends Behaviour {
|
|
|
364
375
|
}
|
|
365
376
|
else if (this.isUsingHands) {
|
|
366
377
|
this.raycastLine.visible = !this.grabbed;
|
|
367
|
-
|
|
378
|
+
setWorldPosition(this.raycastLine, wp);
|
|
368
379
|
const jnts = this.hand!['joints'];
|
|
369
380
|
if (jnts) {
|
|
370
381
|
const wrist = jnts['wrist'];
|
|
@@ -375,12 +386,12 @@ export class WebXRController extends Behaviour {
|
|
|
375
386
|
// this.rayRotation.slerp(wr, this.useSmoothing ? t * 2 : 1);
|
|
376
387
|
}
|
|
377
388
|
}
|
|
378
|
-
|
|
389
|
+
setWorldQuaternion(this.raycastLine, this.rayRotation);
|
|
379
390
|
}
|
|
380
391
|
else {
|
|
381
392
|
this.raycastLine.visible = true;
|
|
382
|
-
|
|
383
|
-
|
|
393
|
+
setWorldQuaternion(this.raycastLine, this.rayRotation);
|
|
394
|
+
setWorldPosition(this.raycastLine, wp);
|
|
384
395
|
}
|
|
385
396
|
}
|
|
386
397
|
|
|
@@ -478,8 +489,8 @@ export class WebXRController extends Behaviour {
|
|
|
478
489
|
if (pinched && this._pinchStartTime && this.context.time.time - this._pinchStartTime > .8) {
|
|
479
490
|
// hacky approach for basic hand teleportation -
|
|
480
491
|
// we teleport if we pinch and the back of the hand points down (open hand gesture)
|
|
481
|
-
// const v1 = new
|
|
482
|
-
// const worldQuaternion = new
|
|
492
|
+
// const v1 = new Vector3();
|
|
493
|
+
// const worldQuaternion = new Quaternion();
|
|
483
494
|
// this.controller.getWorldQuaternion(worldQuaternion);
|
|
484
495
|
// v1.copy(this.controller.up).applyQuaternion(worldQuaternion);
|
|
485
496
|
// const dotPr = -v1.dot(this.controller.up);
|
|
@@ -508,7 +519,7 @@ export class WebXRController extends Behaviour {
|
|
|
508
519
|
doTeleport = true;
|
|
509
520
|
newRigScale = .1;
|
|
510
521
|
WebXRController.MovementSpeedFactor = newRigScale * 2;
|
|
511
|
-
const cam = this.context.mainCamera as
|
|
522
|
+
const cam = this.context.mainCamera as PerspectiveCamera;
|
|
512
523
|
WebXRController.PreviousCameraFarDistance = cam.far;
|
|
513
524
|
cam.far /= newRigScale;
|
|
514
525
|
}
|
|
@@ -517,7 +528,7 @@ export class WebXRController extends Behaviour {
|
|
|
517
528
|
rig.scale.set(1, 1, 1);
|
|
518
529
|
newRigScale = 1;
|
|
519
530
|
WebXRController.MovementSpeedFactor = 1;
|
|
520
|
-
const cam = this.context.mainCamera as
|
|
531
|
+
const cam = this.context.mainCamera as PerspectiveCamera;
|
|
521
532
|
if (WebXRController.PreviousCameraFarDistance)
|
|
522
533
|
cam.far = WebXRController.PreviousCameraFarDistance;
|
|
523
534
|
}
|
|
@@ -537,7 +548,7 @@ export class WebXRController extends Behaviour {
|
|
|
537
548
|
const hit = rc[0];
|
|
538
549
|
if (isInMiniatureMode || this.isValidTeleportTarget(hit.object)) {
|
|
539
550
|
const point = hit.point;
|
|
540
|
-
|
|
551
|
+
setWorldPosition(rig, point);
|
|
541
552
|
}
|
|
542
553
|
}
|
|
543
554
|
}
|
|
@@ -552,17 +563,17 @@ export class WebXRController extends Behaviour {
|
|
|
552
563
|
}
|
|
553
564
|
}
|
|
554
565
|
|
|
555
|
-
private isValidTeleportTarget(obj:
|
|
566
|
+
private isValidTeleportTarget(obj: Object3D): boolean {
|
|
556
567
|
return GameObject.getComponentInParent(obj, TeleportTarget) != null;
|
|
557
568
|
}
|
|
558
569
|
|
|
559
|
-
private updateStick(inputSource:
|
|
570
|
+
private updateStick(inputSource: XRInputSource) {
|
|
560
571
|
if (!inputSource || !inputSource.gamepad || inputSource.gamepad.axes?.length < 4) return;
|
|
561
572
|
this.joystick.x = inputSource.gamepad.axes[2];
|
|
562
573
|
this.joystick.y = inputSource.gamepad.axes[3];
|
|
563
574
|
}
|
|
564
575
|
|
|
565
|
-
private updateLastHit():
|
|
576
|
+
private updateLastHit(): Intersection | null {
|
|
566
577
|
const rc = this.raycast();
|
|
567
578
|
const hit = rc ? rc[0] : null;
|
|
568
579
|
this.lastHit = hit;
|
|
@@ -574,7 +585,7 @@ export class WebXRController extends Behaviour {
|
|
|
574
585
|
|
|
575
586
|
if (this.raycastLine) {
|
|
576
587
|
this.raycastLine.scale.z = factor * (this.lastHit?.distance ?? 9999);
|
|
577
|
-
const mat = this.raycastLine.material as
|
|
588
|
+
const mat = this.raycastLine.material as LineBasicMaterial;
|
|
578
589
|
if (hit != null) mat.color = WebXRController.raycastColor;
|
|
579
590
|
else mat.color = WebXRController.raycastNoHitColor;
|
|
580
591
|
}
|
|
@@ -601,7 +612,7 @@ export class WebXRController extends Behaviour {
|
|
|
601
612
|
}
|
|
602
613
|
|
|
603
614
|
private selectStartCallback: Function | null = null;
|
|
604
|
-
private lastSelectStartObject:
|
|
615
|
+
private lastSelectStartObject: Object3D | null = null;;
|
|
605
616
|
|
|
606
617
|
private onHandleSelectStart() {
|
|
607
618
|
this.selectStartCallback = null;
|
|
@@ -611,7 +622,7 @@ export class WebXRController extends Behaviour {
|
|
|
611
622
|
// console.log("DOWN", this.index, WebXRController.eventSubs);
|
|
612
623
|
|
|
613
624
|
// let maxDistance = this.isUsingHands ? .1 : undefined;
|
|
614
|
-
let intersections:
|
|
625
|
+
let intersections: Intersection[] | null = null;
|
|
615
626
|
let closeGrab: boolean = false;
|
|
616
627
|
if (this.isUsingHands) {
|
|
617
628
|
intersections = this.overlap();
|
|
@@ -625,14 +636,12 @@ export class WebXRController extends Behaviour {
|
|
|
625
636
|
}
|
|
626
637
|
else intersections = this.raycast();
|
|
627
638
|
|
|
639
|
+
if (debug)
|
|
640
|
+
console.log("onHandleSelectStart", "close grab? " + closeGrab, "intersections", intersections);
|
|
641
|
+
|
|
628
642
|
if (intersections && intersections.length > 0) {
|
|
629
643
|
for (const intersection of intersections) {
|
|
630
644
|
const object = intersection.object;
|
|
631
|
-
// if (!this.testIsVisible(object)) {
|
|
632
|
-
// if (debug)
|
|
633
|
-
// console.log("not visible");
|
|
634
|
-
// continue;
|
|
635
|
-
// }
|
|
636
645
|
this.lastSelectStartObject = object;
|
|
637
646
|
const args = { selected: object, grab: object };
|
|
638
647
|
const subs = WebXRController.eventSubs[ControllerEvents.SelectStart];
|
|
@@ -689,7 +698,7 @@ export class WebXRController extends Behaviour {
|
|
|
689
698
|
}
|
|
690
699
|
}
|
|
691
700
|
|
|
692
|
-
private testIsVisible(obj:
|
|
701
|
+
private testIsVisible(obj: Object3D | null): boolean {
|
|
693
702
|
if (!obj) return false;
|
|
694
703
|
if (GameObject.isActiveInHierarchy(obj) === false) return false;
|
|
695
704
|
if (UIRaycastUtils.isInteractable(obj) === false) {
|
|
@@ -700,7 +709,7 @@ export class WebXRController extends Behaviour {
|
|
|
700
709
|
// return this.testIsVisible(obj.parent);
|
|
701
710
|
}
|
|
702
711
|
|
|
703
|
-
private setControllerLayers(obj:
|
|
712
|
+
private setControllerLayers(obj: Object3D, layer: number) {
|
|
704
713
|
if (!obj) return;
|
|
705
714
|
obj.layers.set(layer);
|
|
706
715
|
if (obj.children) {
|
|
@@ -713,28 +722,43 @@ export class WebXRController extends Behaviour {
|
|
|
713
722
|
}
|
|
714
723
|
}
|
|
715
724
|
|
|
716
|
-
public getRay():
|
|
717
|
-
const ray = new
|
|
725
|
+
public getRay(): Ray {
|
|
726
|
+
const ray = new Ray();
|
|
718
727
|
// this.tempMatrix.identity().extractRotation(this.controller.matrixWorld);
|
|
719
728
|
// ray.origin.setFromMatrixPosition(this.controller.matrixWorld);
|
|
720
|
-
ray.origin.copy(
|
|
729
|
+
ray.origin.copy(getWorldPosition(this.controller));
|
|
721
730
|
ray.direction.set(0, 0, -1).applyQuaternion(this.rayRotation);
|
|
722
731
|
return ray;
|
|
723
732
|
}
|
|
724
733
|
|
|
725
|
-
|
|
734
|
+
private closeGrabBoundingBoxHelper?: BoxHelper;
|
|
735
|
+
|
|
736
|
+
public overlap(): Intersection[] {
|
|
726
737
|
const overlapCenter = (this.isUsingHands && this.handPointerModel) ? this.handPointerModel.pointerObject : this.controllerGrip;
|
|
738
|
+
|
|
739
|
+
if (debug) {
|
|
740
|
+
if (!this.closeGrabBoundingBoxHelper && overlapCenter) {
|
|
741
|
+
this.closeGrabBoundingBoxHelper = new BoxHelper( overlapCenter, 0xffff00 );
|
|
742
|
+
this.scene.add(this.closeGrabBoundingBoxHelper);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (this.closeGrabBoundingBoxHelper && overlapCenter) {
|
|
746
|
+
this.closeGrabBoundingBoxHelper.setFromObject(overlapCenter);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
727
750
|
if (!overlapCenter)
|
|
728
|
-
return new Array<
|
|
751
|
+
return new Array<Intersection>();
|
|
729
752
|
|
|
730
|
-
const wp =
|
|
753
|
+
const wp = getWorldPosition(overlapCenter).clone();
|
|
731
754
|
return this.context.physics.sphereOverlap(wp, .02);
|
|
732
755
|
}
|
|
733
756
|
|
|
734
|
-
public raycast():
|
|
757
|
+
public raycast(): Intersection[] {
|
|
735
758
|
const opts = new RaycastOptions();
|
|
736
|
-
opts.layerMask = new
|
|
759
|
+
opts.layerMask = new Layers();
|
|
737
760
|
opts.layerMask.set(0);
|
|
761
|
+
opts.layerMask.disable(2);
|
|
738
762
|
opts.ray = this.getRay();
|
|
739
763
|
const hits = this.context.physics.raycast(opts);
|
|
740
764
|
for (let i = 0; i < hits.length; i++) {
|
|
@@ -793,13 +817,15 @@ export class AttachedObject {
|
|
|
793
817
|
}
|
|
794
818
|
}
|
|
795
819
|
|
|
796
|
-
public static TryTake(controller: WebXRController, candidate:
|
|
820
|
+
public static TryTake(controller: WebXRController, candidate: Object3D, intersection: Intersection, closeGrab: boolean): AttachedObject | null {
|
|
797
821
|
const interactable = GameObject.getComponentInParent(candidate, Interactable);
|
|
798
822
|
if (!interactable) {
|
|
799
823
|
if (debug)
|
|
800
824
|
console.warn("Prevented taking object that is not interactable", candidate);
|
|
801
825
|
return null;
|
|
802
826
|
}
|
|
827
|
+
else candidate = interactable.gameObject;
|
|
828
|
+
|
|
803
829
|
|
|
804
830
|
let objectToAttach = candidate;
|
|
805
831
|
const sync = GameObject.getComponentInParent(candidate, SyncedTransform);
|
|
@@ -824,24 +850,24 @@ export class AttachedObject {
|
|
|
824
850
|
|
|
825
851
|
|
|
826
852
|
public sync: SyncedTransform | null = null;
|
|
827
|
-
public selected:
|
|
828
|
-
public selectedParent:
|
|
829
|
-
public selectedMesh:
|
|
853
|
+
public selected: Object3D | null = null;
|
|
854
|
+
public selectedParent: Object3D | null = null;
|
|
855
|
+
public selectedMesh: Mesh | null = null;
|
|
830
856
|
public controller: WebXRController | null = null;
|
|
831
857
|
public grabTime: number = 0;
|
|
832
858
|
public grabUUID: string = "";
|
|
833
859
|
public isCloseGrab: boolean = false; // when taken via sphere cast with hands
|
|
834
860
|
|
|
835
|
-
private originalMaterial:
|
|
861
|
+
private originalMaterial: Material | Material[] | null = null;
|
|
836
862
|
private usageMarker: UsageMarker | null = null;
|
|
837
863
|
private rigidbodies: Rigidbody[] | null = null;
|
|
838
864
|
private didReparent: boolean = false;
|
|
839
865
|
private grabDistance: number = 0;
|
|
840
866
|
private interactable: Interactable | null = null;
|
|
841
|
-
private positionSource:
|
|
867
|
+
private positionSource: Object3D | null = null;
|
|
842
868
|
|
|
843
|
-
private Take(controller: WebXRController, take:
|
|
844
|
-
intersection:
|
|
869
|
+
private Take(controller: WebXRController, take: Object3D, hit: Object3D, sync: SyncedTransform | null, _interactable: Interactable,
|
|
870
|
+
intersection: Intersection, closeGrab: boolean)
|
|
845
871
|
: AttachedObject {
|
|
846
872
|
console.assert(take !== null, "Expected object to be taken but was", take);
|
|
847
873
|
|
|
@@ -860,11 +886,11 @@ export class AttachedObject {
|
|
|
860
886
|
AttachedObject.Events.WillTake?.forEach(x => x(this, args));
|
|
861
887
|
|
|
862
888
|
|
|
863
|
-
const mesh = hit as
|
|
889
|
+
const mesh = hit as Mesh;
|
|
864
890
|
if (mesh?.material) {
|
|
865
891
|
this.originalMaterial = mesh.material;
|
|
866
892
|
if (!Array.isArray(mesh.material)) {
|
|
867
|
-
mesh.material = (mesh.material as
|
|
893
|
+
mesh.material = (mesh.material as Material).clone();
|
|
868
894
|
if (mesh.material && mesh.material["emissive"])
|
|
869
895
|
mesh.material["emissive"].b = .2;
|
|
870
896
|
}
|
|
@@ -891,7 +917,7 @@ export class AttachedObject {
|
|
|
891
917
|
this.grabUUID = Date.now().toString();
|
|
892
918
|
this.usageMarker = GameObject.addNewComponent(this.selected, UsageMarker);
|
|
893
919
|
this.rigidbodies = GameObject.getComponentsInChildren(this.selected, Rigidbody);
|
|
894
|
-
|
|
920
|
+
getWorldPosition(this.positionSource, this.lastControllerWorldPos);
|
|
895
921
|
const getGrabPoint = () => closeGrab ? this.lastControllerWorldPos.clone() : intersection.point.clone();
|
|
896
922
|
this.grabDistance = getGrabPoint().distanceTo(this.lastControllerWorldPos);
|
|
897
923
|
this.totalChangeAlongDirection = 0.0;
|
|
@@ -900,11 +926,11 @@ export class AttachedObject {
|
|
|
900
926
|
// we're storing rotation relative to the ray
|
|
901
927
|
this.localPositionOffsetToGrab = this.selected.worldToLocal(getGrabPoint());
|
|
902
928
|
const rot = controller.isUsingHands && closeGrab ? this.controller.getWristQuaternion()!.clone() : controller.rayRotation.clone();
|
|
903
|
-
|
|
929
|
+
getWorldQuaternion(this.selected, this.localQuaternionToGrab).premultiply(rot.invert());
|
|
904
930
|
|
|
905
931
|
const rig = this.controller.webXR.Rig;
|
|
906
932
|
if (rig)
|
|
907
|
-
this.rigPositionLastFrame.copy(
|
|
933
|
+
this.rigPositionLastFrame.copy(getWorldPosition(rig))
|
|
908
934
|
|
|
909
935
|
Avatar_POI.Add(controller.context, this.selected);
|
|
910
936
|
AttachedObject.Register(this);
|
|
@@ -971,20 +997,20 @@ export class AttachedObject {
|
|
|
971
997
|
AttachedObject.Events.DidFree?.forEach(x => x(this, args));
|
|
972
998
|
}
|
|
973
999
|
|
|
974
|
-
public grabPoint:
|
|
1000
|
+
public grabPoint: Vector3 = new Vector3();
|
|
975
1001
|
|
|
976
|
-
private localPositionOffsetToGrab:
|
|
977
|
-
private localPositionOffsetToGrab_worldSpace:
|
|
978
|
-
private localQuaternionToGrab:
|
|
979
|
-
private targetDir:
|
|
980
|
-
private quaternionLerp:
|
|
1002
|
+
private localPositionOffsetToGrab: Vector3 | null = null;
|
|
1003
|
+
private localPositionOffsetToGrab_worldSpace: Vector3 = new Vector3();
|
|
1004
|
+
private localQuaternionToGrab: Quaternion = new Quaternion(0, 0, 0, 1);
|
|
1005
|
+
private targetDir: Vector3 | null = null;
|
|
1006
|
+
private quaternionLerp: Quaternion | null = null;
|
|
981
1007
|
|
|
982
|
-
private controllerDir = new
|
|
983
|
-
private controllerWorldPos = new
|
|
984
|
-
private lastControllerWorldPos = new
|
|
985
|
-
private controllerPosDelta = new
|
|
1008
|
+
private controllerDir = new Vector3();
|
|
1009
|
+
private controllerWorldPos = new Vector3();
|
|
1010
|
+
private lastControllerWorldPos = new Vector3();
|
|
1011
|
+
private controllerPosDelta = new Vector3();
|
|
986
1012
|
private totalChangeAlongDirection = 0.0;
|
|
987
|
-
private rigPositionLastFrame = new
|
|
1013
|
+
private rigPositionLastFrame = new Vector3();
|
|
988
1014
|
|
|
989
1015
|
private controllerMovementSinceLastFrame() {
|
|
990
1016
|
if (!this.positionSource || !this.controller) return 0.0;
|
|
@@ -994,13 +1020,13 @@ export class AttachedObject {
|
|
|
994
1020
|
this.controllerDir.applyQuaternion(this.controller.rayRotation);
|
|
995
1021
|
|
|
996
1022
|
// controller delta
|
|
997
|
-
|
|
1023
|
+
getWorldPosition(this.positionSource, this.controllerWorldPos);
|
|
998
1024
|
this.controllerPosDelta.copy(this.controllerWorldPos);
|
|
999
1025
|
this.controllerPosDelta.sub(this.lastControllerWorldPos);
|
|
1000
1026
|
this.lastControllerWorldPos.copy(this.controllerWorldPos);
|
|
1001
1027
|
const rig = this.controller.webXR.Rig;
|
|
1002
1028
|
if (rig) {
|
|
1003
|
-
const rigPos =
|
|
1029
|
+
const rigPos = getWorldPosition(rig);
|
|
1004
1030
|
const rigDelta = this.rigPositionLastFrame.sub(rigPos);
|
|
1005
1031
|
this.controllerPosDelta.add(rigDelta);
|
|
1006
1032
|
this.rigPositionLastFrame.copy(rigPos);
|
|
@@ -1048,7 +1074,7 @@ export class AttachedObject {
|
|
|
1048
1074
|
if (this.grabDistance / rigScale < 0.8) currentDist = 1.0; // don't accelerate if this is a close grab, want full control
|
|
1049
1075
|
|
|
1050
1076
|
if (!this.targetDir) {
|
|
1051
|
-
this.targetDir = new
|
|
1077
|
+
this.targetDir = new Vector3();
|
|
1052
1078
|
}
|
|
1053
1079
|
this.targetDir.set(0, 0, -this.grabDistance * currentDist);
|
|
1054
1080
|
const target = this.targetDir.applyQuaternion(this.controller.rayRotation).add(this.controllerWorldPos);
|
|
@@ -1059,7 +1085,7 @@ export class AttachedObject {
|
|
|
1059
1085
|
this.quaternionLerp = targetQuat.clone();
|
|
1060
1086
|
}
|
|
1061
1087
|
this.quaternionLerp.slerp(targetQuat, this.controller.useSmoothing ? this.controller.context.time.deltaTime / .03 : 1.0);
|
|
1062
|
-
|
|
1088
|
+
setWorldQuaternion(this.selected, this.quaternionLerp);
|
|
1063
1089
|
this.selected.updateWorldMatrix(false, false); // necessary so that rotation is correct for the following position update
|
|
1064
1090
|
|
|
1065
1091
|
// apply position
|
|
@@ -1067,10 +1093,10 @@ export class AttachedObject {
|
|
|
1067
1093
|
// apply local grab offset
|
|
1068
1094
|
if (this.localPositionOffsetToGrab) {
|
|
1069
1095
|
this.localPositionOffsetToGrab_worldSpace.copy(this.localPositionOffsetToGrab);
|
|
1070
|
-
this.selected.localToWorld(this.localPositionOffsetToGrab_worldSpace).sub(
|
|
1096
|
+
this.selected.localToWorld(this.localPositionOffsetToGrab_worldSpace).sub(getWorldPosition(this.selected));
|
|
1071
1097
|
target.sub(this.localPositionOffsetToGrab_worldSpace);
|
|
1072
1098
|
}
|
|
1073
|
-
|
|
1099
|
+
setWorldPosition(this.selected, target);
|
|
1074
1100
|
}
|
|
1075
1101
|
|
|
1076
1102
|
|