@needle-tools/engine 4.11.0-next.91b9cf1 → 4.11.0-next.cc37c71
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 +7 -1
- package/README.md +3 -1
- package/components.needle.json +1 -1
- package/dist/{gltf-progressive-B63NpN_i.js → gltf-progressive-BvlZQAkt.js} +4 -4
- package/dist/{gltf-progressive-D4Z_Khp3.min.js → gltf-progressive-CftVUJy3.min.js} +1 -1
- package/dist/{gltf-progressive-CHeORqEv.umd.cjs → gltf-progressive-GwdQV1Qx.umd.cjs} +1 -1
- package/dist/{needle-engine.bundle-D4dsuq2U.js → needle-engine.bundle-BPZ6emFK.js} +7858 -7724
- package/dist/{needle-engine.bundle-DtfAXDjU.umd.cjs → needle-engine.bundle-CTY0RgBZ.umd.cjs} +150 -150
- package/dist/needle-engine.bundle-JV2ghuCa.min.js +1652 -0
- package/dist/needle-engine.d.ts +6 -0
- package/dist/needle-engine.js +4 -4
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-DQ2pynXW.js → postprocessing-CJC0Npcd.js} +2 -2
- package/dist/{postprocessing-BsnRNRRS.umd.cjs → postprocessing-DrM4PWU3.umd.cjs} +1 -1
- package/dist/{postprocessing-BHMVuZQ1.min.js → postprocessing-l7zsdO_Q.min.js} +1 -1
- package/dist/{three-qw28ZtTy.min.js → three-BDW9I486.min.js} +13 -13
- package/dist/{three-CJSAehtG.js → three-MHVqtJYj.js} +1 -0
- package/dist/{three-examples-Doq0rvFU.js → three-examples-C5Ht-QFN.js} +1 -1
- package/dist/{three-examples-Deqc1bNw.umd.cjs → three-examples-CgwGHSgz.umd.cjs} +1 -1
- package/dist/{three-examples-BivkhnvN.min.js → three-examples-fvEPSC8L.min.js} +1 -1
- package/dist/{three-B-jwTHao.umd.cjs → three-iFaDq9U3.umd.cjs} +13 -13
- package/dist/{three-mesh-ui-CktOi6oI.js → three-mesh-ui-BjWTTk1R.js} +1 -1
- package/dist/{three-mesh-ui-CsHwj9cJ.umd.cjs → three-mesh-ui-Bm32sS2a.umd.cjs} +1 -1
- package/dist/{three-mesh-ui-DhYXcXZe.min.js → three-mesh-ui-CLdkp21K.min.js} +1 -1
- package/dist/{vendor-BcsPRUmt.umd.cjs → vendor-CAWj5cBK.umd.cjs} +2 -2
- package/dist/{vendor-CyfN5nor.js → vendor-DJBpoQcM.js} +608 -599
- package/dist/{vendor-DyavoogU.min.js → vendor-DWGd3dEf.min.js} +20 -20
- package/lib/engine/engine_physics.js +25 -2
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/js-extensions/Object3D.d.ts +6 -0
- package/lib/engine/js-extensions/Object3D.js +15 -0
- package/lib/engine/js-extensions/Object3D.js.map +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +2 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +26 -0
- package/lib/engine-components/Collider.js +26 -0
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +11 -2
- package/lib/engine-components/ContactShadows.js +11 -2
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/DropListener.d.ts +3 -0
- package/lib/engine-components/DropListener.js +44 -21
- package/lib/engine-components/DropListener.js.map +1 -1
- package/lib/engine-components/Duplicatable.d.ts +2 -2
- package/lib/engine-components/Duplicatable.js +2 -2
- package/lib/engine-components/EventList.d.ts +18 -1
- package/lib/engine-components/EventList.js +18 -1
- package/lib/engine-components/EventList.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +3 -0
- package/lib/engine-components/GroundProjection.js +3 -0
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/Interactable.d.ts +4 -0
- package/lib/engine-components/Interactable.js +4 -0
- package/lib/engine-components/Interactable.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +4 -2
- package/lib/engine-components/OrbitControls.js +33 -3
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +5 -0
- package/lib/engine-components/RigidBody.js +5 -0
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SeeThrough.js +20 -0
- package/lib/engine-components/SeeThrough.js.map +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +4 -2
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +69 -14
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
- package/lib/engine-components/splines/SplineWalker.d.ts +43 -4
- package/lib/engine-components/splines/SplineWalker.js +88 -12
- package/lib/engine-components/splines/SplineWalker.js.map +1 -1
- package/lib/engine-components/ui/Text.js +6 -1
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/utils/LookAt.d.ts +3 -0
- package/lib/engine-components/utils/LookAt.js +3 -0
- package/lib/engine-components/utils/LookAt.js.map +1 -1
- package/lib/engine-components/utils/OpenURL.d.ts +2 -1
- package/lib/engine-components/utils/OpenURL.js +2 -1
- package/lib/engine-components/utils/OpenURL.js.map +1 -1
- package/lib/engine-components/web/Clickthrough.d.ts +2 -0
- package/lib/engine-components/web/Clickthrough.js +23 -1
- package/lib/engine-components/web/Clickthrough.js.map +1 -1
- package/lib/engine-components/web/ScrollFollow.d.ts +1 -9
- package/lib/engine-components/web/ScrollFollow.js +13 -30
- package/lib/engine-components/web/ScrollFollow.js.map +1 -1
- package/lib/engine-components/web/ViewBox.d.ts +16 -0
- package/lib/engine-components/web/ViewBox.js +35 -3
- package/lib/engine-components/web/ViewBox.js.map +1 -1
- package/lib/engine-components/webxr/WebARCameraBackground.d.ts +2 -0
- package/lib/engine-components/webxr/WebARCameraBackground.js +2 -0
- package/lib/engine-components/webxr/WebARCameraBackground.js.map +1 -1
- package/lib/engine-components/webxr/WebARSessionRoot.d.ts +1 -1
- package/lib/engine-components/webxr/WebARSessionRoot.js +1 -1
- package/lib/engine-components/webxr/WebXR.d.ts +2 -0
- package/lib/engine-components/webxr/WebXR.js +2 -0
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +29 -0
- package/lib/engine-components/webxr/WebXRImageTracking.js +29 -0
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/package.json +2 -2
- package/plugins/common/needle-engine.js +41 -0
- package/plugins/common/worker.js +129 -0
- package/plugins/vite/asap.js +5 -23
- package/plugins/vite/dependencies.js +21 -11
- package/plugins/vite/index.js +7 -0
- package/plugins/vite/needle-app.js +194 -0
- package/src/engine/engine_physics.ts +27 -2
- package/src/engine/js-extensions/Object3D.ts +24 -0
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +3 -1
- package/src/engine-components/Collider.ts +27 -1
- package/src/engine-components/ContactShadows.ts +12 -4
- package/src/engine-components/DropListener.ts +45 -24
- package/src/engine-components/Duplicatable.ts +2 -2
- package/src/engine-components/EventList.ts +18 -1
- package/src/engine-components/GroundProjection.ts +4 -1
- package/src/engine-components/Interactable.ts +4 -1
- package/src/engine-components/OrbitControls.ts +32 -5
- package/src/engine-components/RigidBody.ts +6 -1
- package/src/engine-components/SeeThrough.ts +42 -2
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +117 -17
- package/src/engine-components/splines/SplineWalker.ts +99 -14
- package/src/engine-components/ui/Text.ts +11 -2
- package/src/engine-components/utils/LookAt.ts +3 -0
- package/src/engine-components/utils/OpenURL.ts +3 -2
- package/src/engine-components/web/Clickthrough.ts +28 -1
- package/src/engine-components/web/ScrollFollow.ts +16 -34
- package/src/engine-components/web/ViewBox.ts +35 -5
- package/src/engine-components/webxr/WebARCameraBackground.ts +2 -0
- package/src/engine-components/webxr/WebARSessionRoot.ts +1 -1
- package/src/engine-components/webxr/WebXR.ts +2 -0
- package/src/engine-components/webxr/WebXRImageTracking.ts +30 -3
- package/dist/needle-engine.bundle-B8HfDBoL.min.js +0 -1652
|
@@ -10,6 +10,9 @@ export class UsageMarker extends Behaviour
|
|
|
10
10
|
public usedBy: any = null;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* An empty component that can be used to mark an object as interactable.
|
|
15
|
+
* @group Components
|
|
16
|
+
*/
|
|
14
17
|
/** @deprecated */
|
|
15
18
|
export class Interactable extends Behaviour {}
|
|
@@ -255,7 +255,12 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
255
255
|
* @default 1
|
|
256
256
|
*/
|
|
257
257
|
@serializable()
|
|
258
|
-
targetLerpDuration
|
|
258
|
+
get targetLerpDuration() { return this._lookTargetLerpDuration; }
|
|
259
|
+
set targetLerpDuration(v) { this._lookTargetLerpDuration = v; }
|
|
260
|
+
private _lookTargetLerpDuration: number = 1;
|
|
261
|
+
|
|
262
|
+
@serializable(Object3D)
|
|
263
|
+
targetBounds: Object3D | null = null;
|
|
259
264
|
|
|
260
265
|
/**
|
|
261
266
|
* Rotate the camera left (or right) by the specified angle in radians.
|
|
@@ -326,7 +331,6 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
326
331
|
private _lookTargetStartPosition: Vector3 = new Vector3();
|
|
327
332
|
private _lookTargetEndPosition: Vector3 = new Vector3();
|
|
328
333
|
private _lookTargetLerp01: number = 0;
|
|
329
|
-
private _lookTargetLerpDuration: number = 0;
|
|
330
334
|
|
|
331
335
|
private _cameraLerpActive: boolean = false;
|
|
332
336
|
private _cameraStartPosition: Vector3 = new Vector3();
|
|
@@ -685,10 +689,32 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
685
689
|
}
|
|
686
690
|
}
|
|
687
691
|
|
|
692
|
+
if (this.targetBounds) {
|
|
693
|
+
// #region target bounds
|
|
694
|
+
const targetVector = this._controls.target;
|
|
695
|
+
const boundsCenter = this.targetBounds.worldPosition;
|
|
696
|
+
const boundsHalfSize = getTempVector(this.targetBounds.worldScale).multiplyScalar(0.5);
|
|
697
|
+
const min = getTempVector(boundsCenter).sub(boundsHalfSize);
|
|
698
|
+
const max = getTempVector(boundsCenter).add(boundsHalfSize);
|
|
699
|
+
const newTarget = getTempVector(this._controls.target).clamp(min, max);
|
|
700
|
+
const duration = .1;
|
|
701
|
+
if (duration <= 0) targetVector.copy(newTarget);
|
|
702
|
+
else targetVector.lerp(newTarget, this.context.time.deltaTime / duration);
|
|
703
|
+
if (this._lookTargetLerpActive) {
|
|
704
|
+
if (duration <= 0) this._lookTargetEndPosition.copy(newTarget);
|
|
705
|
+
else this._lookTargetEndPosition.lerp(newTarget, this.context.time.deltaTime / (duration * 5));
|
|
706
|
+
}
|
|
707
|
+
if (debug) {
|
|
708
|
+
Gizmos.DrawWireBox(boundsCenter, boundsHalfSize.multiplyScalar(2), 0xffaa00);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
688
712
|
|
|
689
713
|
if (this._controls) {
|
|
690
|
-
if (this.debugLog)
|
|
691
|
-
|
|
714
|
+
if (this.debugLog) this._controls.domElement = this.context.renderer.domElement;
|
|
715
|
+
|
|
716
|
+
const viewZoomFactor = 1 / (this.context.focusRectSettings?.zoom || 1);
|
|
717
|
+
|
|
692
718
|
this._controls.enabled = !this._shouldDisable && this._camera === this.context.mainCameraComponent && !this.context.isInXR && !this._activePointerEvents.some(e => e.used);
|
|
693
719
|
this._controls.keys = this.enableKeys ? defaultKeys : disabledKeys;
|
|
694
720
|
this._controls.autoRotate = this.autoRotate;
|
|
@@ -699,6 +725,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
699
725
|
this._controls.enableDamping = this.enableDamping;
|
|
700
726
|
this._controls.dampingFactor = this.dampingFactor;
|
|
701
727
|
this._controls.enablePan = this.enablePan;
|
|
728
|
+
this._controls.panSpeed = viewZoomFactor;
|
|
702
729
|
this._controls.enableRotate = this.enableRotate;
|
|
703
730
|
this._controls.minAzimuthAngle = this.minAzimuthAngle;
|
|
704
731
|
this._controls.maxAzimuthAngle = this.maxAzimuthAngle;
|
|
@@ -1000,7 +1027,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1000
1027
|
*/
|
|
1001
1028
|
fitCamera(options?: OrbitFitCameraOptions);
|
|
1002
1029
|
/** @deprecated Use fitCamera(options) */
|
|
1003
|
-
fitCamera(objects?: Object3D | Array<Object3D>, options?: Omit<OrbitFitCameraOptions, "objects">);
|
|
1030
|
+
fitCamera(objects?: Object3D | Array<Object3D>, options?: Omit<OrbitFitCameraOptions, "objects">);
|
|
1004
1031
|
fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | OrbitFitCameraOptions, options?: OrbitFitCameraOptions): void {
|
|
1005
1032
|
|
|
1006
1033
|
|
|
@@ -134,7 +134,12 @@ class TransformWatch {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
* A Rigidbody is used together with a Collider to create physical interactions between objects in the scene.
|
|
137
|
+
* A Rigidbody is used together with a Collider to create physical interactions between objects in the scene.
|
|
138
|
+
*
|
|
139
|
+
* - Example: https://samples.needle.tools/physics-basic
|
|
140
|
+
* - Example: https://samples.needle.tools/physics-playground
|
|
141
|
+
* - Example: https://samples.needle.tools/physics-&-animation
|
|
142
|
+
*
|
|
138
143
|
* @category Physics
|
|
139
144
|
* @group Components
|
|
140
145
|
*/
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { Material, Object3D, Vector3 } from "three";
|
|
1
|
+
import { Material, Object3D, Object3DEventMap, Vector3 } from "three";
|
|
2
2
|
|
|
3
3
|
import { Gizmos } from "../engine/engine_gizmos.js";
|
|
4
4
|
import { Mathf } from "../engine/engine_math.js";
|
|
5
5
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
6
6
|
import { getTempVector } from "../engine/engine_three_utils.js";
|
|
7
7
|
import { getParam } from "../engine/engine_utils.js";
|
|
8
|
+
import { USDObject, USDZExporterContext } from "./api.js";
|
|
8
9
|
import { Behaviour } from "./Component.js";
|
|
10
|
+
import { IUSDExporterExtension } from "./export/usdz/Extension.js";
|
|
11
|
+
import { USDZExporter } from "./export/usdz/USDZExporter.js";
|
|
9
12
|
import { Renderer } from "./Renderer.js";
|
|
10
13
|
|
|
11
14
|
const debugSeeThrough = getParam("debugseethrough");
|
|
@@ -102,6 +105,7 @@ export class SeeThrough extends Behaviour {
|
|
|
102
105
|
onEnable() {
|
|
103
106
|
this._needsUpdate = true;
|
|
104
107
|
this._renderer = null;
|
|
108
|
+
SeeThroughUsdzExporterPlugin.components.push(this);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
/** @internal */
|
|
@@ -118,6 +122,9 @@ export class SeeThrough extends Behaviour {
|
|
|
118
122
|
this.rendererMaterials.delete(r);
|
|
119
123
|
this.rendererMaterialsOriginal.delete(r);
|
|
120
124
|
});
|
|
125
|
+
|
|
126
|
+
const index = SeeThroughUsdzExporterPlugin.components.indexOf(this);
|
|
127
|
+
if (index !== -1) SeeThroughUsdzExporterPlugin.components.splice(index, 1);
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
/**
|
|
@@ -253,4 +260,37 @@ export class SeeThrough extends Behaviour {
|
|
|
253
260
|
});
|
|
254
261
|
}
|
|
255
262
|
|
|
256
|
-
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
;
|
|
267
|
+
class SeeThroughUsdzExporterPlugin implements IUSDExporterExtension {
|
|
268
|
+
|
|
269
|
+
static readonly components: SeeThrough[] = [];
|
|
270
|
+
|
|
271
|
+
get extensionName() {
|
|
272
|
+
return "SeeThrough";
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// onExportObject(object: Object3D<Object3DEventMap>, model: USDObject, context: USDZExporterContext) {
|
|
276
|
+
// const component = SeeThroughUsdzExporterPlugin.components.find(c => c.gameObject === object);
|
|
277
|
+
// if(!component) return;
|
|
278
|
+
// console.log("OH MY GOD SEE THROUGH USDZ EXPORTER", component, model);
|
|
279
|
+
|
|
280
|
+
// model.materialName = "AlphaHashMaterialInstance"; // we could make this unique per object if needed
|
|
281
|
+
|
|
282
|
+
// model.addEventListener("serialize", (writer, context) => {
|
|
283
|
+
// writer.appendLine(`# SeeThrough component on ${object.name}`);
|
|
284
|
+
// });
|
|
285
|
+
// }
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const seeThroughUsdzExporterPlugin = new SeeThroughUsdzExporterPlugin();
|
|
290
|
+
|
|
291
|
+
USDZExporter.beforeExport.addEventListener(args => {
|
|
292
|
+
if (SeeThroughUsdzExporterPlugin.components.length === 0) return;
|
|
293
|
+
if (args.exporter.extensions.includes(seeThroughUsdzExporterPlugin) === false) {
|
|
294
|
+
args.exporter.extensions.push(seeThroughUsdzExporterPlugin);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
@@ -112,6 +112,10 @@ const PositionIdentity = new Vector3();
|
|
|
112
112
|
const QuaternionIdentity = new Quaternion();
|
|
113
113
|
const ScaleIdentity = new Vector3(1,1,1);
|
|
114
114
|
|
|
115
|
+
// #region USDObject
|
|
116
|
+
|
|
117
|
+
type USDObjectEventType = "serialize" & ({} & string);
|
|
118
|
+
|
|
115
119
|
class USDObject {
|
|
116
120
|
|
|
117
121
|
static USDObject_export_id = 0;
|
|
@@ -153,12 +157,13 @@ class USDObject {
|
|
|
153
157
|
private set isDynamic( value ) { this._isDynamic = value; }
|
|
154
158
|
geometry: BufferGeometry | null;
|
|
155
159
|
material: MeshStandardMaterial | MeshBasicMaterial | Material | MeshPhysicalNodeMaterial | null;
|
|
160
|
+
// usdMaterial?: USDMaterial;
|
|
156
161
|
camera: PerspectiveCamera | OrthographicCamera | null;
|
|
157
162
|
parent: USDObject | null;
|
|
158
163
|
skinnedMesh: SkinnedMesh | null;
|
|
159
164
|
children: Array<USDObject | null> = [];
|
|
160
165
|
animations: AnimationClip[] | null;
|
|
161
|
-
_eventListeners:
|
|
166
|
+
_eventListeners: Record<USDObjectEventType, Function[]>;
|
|
162
167
|
|
|
163
168
|
// these are for tracking which xformops are needed
|
|
164
169
|
needsTranslate: boolean = false;
|
|
@@ -201,7 +206,7 @@ class USDObject {
|
|
|
201
206
|
this.camera = camera;
|
|
202
207
|
this.parent = null;
|
|
203
208
|
this.children = [];
|
|
204
|
-
this._eventListeners = {}
|
|
209
|
+
this._eventListeners = {} as Record<USDObjectEventType, Function[]>;
|
|
205
210
|
this._isDynamic = false;
|
|
206
211
|
this.skinnedMesh = skinnedMesh;
|
|
207
212
|
this.animations = animations;
|
|
@@ -287,7 +292,7 @@ class USDObject {
|
|
|
287
292
|
|
|
288
293
|
}
|
|
289
294
|
|
|
290
|
-
addEventListener( evt, listener: ( writer: USDWriter, context: USDZExporterContext ) => void ) {
|
|
295
|
+
addEventListener( evt : USDObjectEventType, listener: ( writer: USDWriter, context: USDZExporterContext ) => void ) {
|
|
291
296
|
|
|
292
297
|
if ( ! this._eventListeners[ evt ] ) this._eventListeners[ evt ] = [];
|
|
293
298
|
this._eventListeners[ evt ].push( listener );
|
|
@@ -316,6 +321,67 @@ class USDObject {
|
|
|
316
321
|
}
|
|
317
322
|
|
|
318
323
|
|
|
324
|
+
// #region USDMaterial
|
|
325
|
+
|
|
326
|
+
// class MaterialInput {
|
|
327
|
+
// name: string;
|
|
328
|
+
// }
|
|
329
|
+
|
|
330
|
+
class USDMaterial {
|
|
331
|
+
|
|
332
|
+
static USDMaterial_id = 0;
|
|
333
|
+
|
|
334
|
+
readonly material: Material;
|
|
335
|
+
readonly id: number;
|
|
336
|
+
|
|
337
|
+
name: string;
|
|
338
|
+
|
|
339
|
+
isOverride: boolean = false;
|
|
340
|
+
isInstanceable: boolean = false;
|
|
341
|
+
|
|
342
|
+
constructor( material: Material ) {
|
|
343
|
+
this.material = material;
|
|
344
|
+
this.id = USDMaterial.USDMaterial_id ++;
|
|
345
|
+
this.name = makeNameSafe( material.name || 'Material_' + this.id );
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
readonly inputs: Record<string, string | number | boolean | number[] | undefined> = {};
|
|
349
|
+
|
|
350
|
+
// addInput( name: string, value: "" ) {
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
// }
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
serialize( writer: USDWriter, _context: USDZExporterContext ) {
|
|
358
|
+
|
|
359
|
+
const name = this.name;
|
|
360
|
+
|
|
361
|
+
writer.appendLine( `def Material "${this.name}" ${name ?`( displayName = "${makeDisplayNameSafe(name)}" )` : ''}` );
|
|
362
|
+
writer.beginBlock();
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
writer.closeBlock();
|
|
366
|
+
|
|
367
|
+
// def Material "${materialName}" ${material.name ?`(
|
|
368
|
+
// displayName = "${material.name}"
|
|
369
|
+
// )` : ''}
|
|
370
|
+
// {
|
|
371
|
+
// token outputs:mtlx:surface.connect = ${materialRoot}/${materialName}/Occlusion.outputs:out>
|
|
372
|
+
|
|
373
|
+
// def Shader "Occlusion"
|
|
374
|
+
// {
|
|
375
|
+
// uniform token info:id = "${mode}"
|
|
376
|
+
// token outputs:out
|
|
377
|
+
// }
|
|
378
|
+
// }`;
|
|
379
|
+
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// #region USDDocument
|
|
384
|
+
|
|
319
385
|
class USDDocument extends USDObject {
|
|
320
386
|
|
|
321
387
|
stageLength: number;
|
|
@@ -448,6 +514,7 @@ ${comments}
|
|
|
448
514
|
|
|
449
515
|
}
|
|
450
516
|
|
|
517
|
+
|
|
451
518
|
const newLine = '\n';
|
|
452
519
|
const materialRoot = '</StageRoot/Materials';
|
|
453
520
|
|
|
@@ -540,6 +607,8 @@ class USDWriter {
|
|
|
540
607
|
|
|
541
608
|
declare type TextureMap = {[name: string]: {texture: Texture, scale?: Vector4}};
|
|
542
609
|
|
|
610
|
+
// #region USDZExporterContext
|
|
611
|
+
|
|
543
612
|
class USDZExporterContext {
|
|
544
613
|
root?: Object3D;
|
|
545
614
|
exporter: USDZExporter;
|
|
@@ -576,6 +645,10 @@ class USDZExporterContext {
|
|
|
576
645
|
|
|
577
646
|
}
|
|
578
647
|
|
|
648
|
+
makeNameSafe( str ) {
|
|
649
|
+
return makeNameSafe( str );
|
|
650
|
+
}
|
|
651
|
+
|
|
579
652
|
}
|
|
580
653
|
|
|
581
654
|
/**[documentation](https://developer.apple.com/documentation/arkit/usdz_schemas_for_ar/preliminary_anchoringapi/preliminary_anchoring_type) */
|
|
@@ -597,6 +670,8 @@ class USDZExporterOptions {
|
|
|
597
670
|
exportInvisible: boolean = false;
|
|
598
671
|
}
|
|
599
672
|
|
|
673
|
+
// #region USDZExporter
|
|
674
|
+
|
|
600
675
|
class USDZExporter {
|
|
601
676
|
debug: boolean;
|
|
602
677
|
pruneUnusedNodes: boolean;
|
|
@@ -698,13 +773,7 @@ class USDZExporter {
|
|
|
698
773
|
}
|
|
699
774
|
|
|
700
775
|
Progress.report('export-usdz', { message: "Parsing document", autoStep: 10 });
|
|
701
|
-
await parseDocument( context,
|
|
702
|
-
// injected after stageRoot.
|
|
703
|
-
// TODO property use context/writer instead of string concat
|
|
704
|
-
Progress.report('export-usdz', "Building materials");
|
|
705
|
-
const result = buildMaterials( materials, textures, options.quickLookCompatible );
|
|
706
|
-
return result;
|
|
707
|
-
} );
|
|
776
|
+
await parseDocument( context, options );
|
|
708
777
|
|
|
709
778
|
Progress.report("export-usdz", "Invoking onAfterSerialize");
|
|
710
779
|
await invokeAll( context, 'onAfterSerialize' );
|
|
@@ -726,7 +795,7 @@ class USDZExporter {
|
|
|
726
795
|
const final = header + '\n' + context.output;
|
|
727
796
|
|
|
728
797
|
// full output file
|
|
729
|
-
if ( this.debug ) console.
|
|
798
|
+
if ( this.debug ) console.debug( final );
|
|
730
799
|
|
|
731
800
|
files[ modelFileName ] = fflate.strToU8( final );
|
|
732
801
|
context.output = '';
|
|
@@ -822,6 +891,9 @@ class USDZExporter {
|
|
|
822
891
|
|
|
823
892
|
}
|
|
824
893
|
|
|
894
|
+
// #endregion
|
|
895
|
+
|
|
896
|
+
// #region traverse
|
|
825
897
|
function traverse( object: Object3D, parentModel: USDObject, context: USDZExporterContext, keepObject?: (object: Object3D) => boolean ) {
|
|
826
898
|
|
|
827
899
|
if (!context.exportInvisible && !object.visible) return;
|
|
@@ -919,6 +991,8 @@ function traverse( object: Object3D, parentModel: USDObject, context: USDZExport
|
|
|
919
991
|
|
|
920
992
|
}
|
|
921
993
|
|
|
994
|
+
// #endregion
|
|
995
|
+
|
|
922
996
|
function logUsdHierarchy( object: USDObject, prefix: string, ...extraLogObjects: any[] ) {
|
|
923
997
|
|
|
924
998
|
const item = {};
|
|
@@ -1020,7 +1094,8 @@ function prune ( object: USDObject, options : {
|
|
|
1020
1094
|
return canBePruned;
|
|
1021
1095
|
}
|
|
1022
1096
|
|
|
1023
|
-
|
|
1097
|
+
// #region parseDocument
|
|
1098
|
+
async function parseDocument( context: USDZExporterContext, options: USDZExporterOptions ) {
|
|
1024
1099
|
|
|
1025
1100
|
Progress.start("export-usdz-resources", "export-usdz");
|
|
1026
1101
|
const resources: Array<() => void> = [];
|
|
@@ -1086,14 +1161,21 @@ async function parseDocument( context: USDZExporterContext, afterStageRoot: () =
|
|
|
1086
1161
|
|
|
1087
1162
|
writer.closeBlock();
|
|
1088
1163
|
writer.closeBlock();
|
|
1089
|
-
|
|
1164
|
+
|
|
1165
|
+
// TODO property use context/writer instead of string concat
|
|
1166
|
+
Progress.report('export-usdz', "Building materials");
|
|
1167
|
+
const result = buildMaterials( context.materials, context.textures, options.quickLookCompatible );
|
|
1168
|
+
writer.appendLine(result);
|
|
1169
|
+
|
|
1090
1170
|
writer.closeBlock();
|
|
1091
1171
|
|
|
1092
1172
|
Progress.report("export-usdz", "write to string")
|
|
1093
1173
|
context.output += writer.toString();
|
|
1094
1174
|
|
|
1095
1175
|
}
|
|
1176
|
+
// #endregion
|
|
1096
1177
|
|
|
1178
|
+
// #region addResources
|
|
1097
1179
|
function addResources( object: USDObject | null, context: USDZExporterContext, resources: Array<() => void>) {
|
|
1098
1180
|
|
|
1099
1181
|
if ( !object ) return;
|
|
@@ -1132,7 +1214,7 @@ function addResources( object: USDObject | null, context: USDZExporterContext, r
|
|
|
1132
1214
|
|
|
1133
1215
|
if ( material ) {
|
|
1134
1216
|
|
|
1135
|
-
if (
|
|
1217
|
+
if ( context.materials.get( material.uuid ) === undefined ) {
|
|
1136
1218
|
|
|
1137
1219
|
context.materials[ material.uuid ] = material;
|
|
1138
1220
|
|
|
@@ -1169,6 +1251,10 @@ async function invokeAll( context: USDZExporterContext, name: string, writer: US
|
|
|
1169
1251
|
}
|
|
1170
1252
|
|
|
1171
1253
|
}
|
|
1254
|
+
|
|
1255
|
+
// #endregion
|
|
1256
|
+
|
|
1257
|
+
// #region GPU utils
|
|
1172
1258
|
let _renderer: WebGLRenderer | null = null;
|
|
1173
1259
|
let renderTarget: WebGLRenderTarget | null = null;
|
|
1174
1260
|
let fullscreenQuadGeometry: PlaneGeometry | null;
|
|
@@ -1431,7 +1517,9 @@ function getPathToSkeleton(bone: Object3D, assumedRoot: Object3D) {
|
|
|
1431
1517
|
return path;
|
|
1432
1518
|
}
|
|
1433
1519
|
|
|
1434
|
-
//
|
|
1520
|
+
// #endregion
|
|
1521
|
+
|
|
1522
|
+
// #region XForm
|
|
1435
1523
|
|
|
1436
1524
|
export function buildXform( model: USDObject | null, writer: USDWriter, context: USDZExporterContext ) {
|
|
1437
1525
|
|
|
@@ -1635,7 +1723,7 @@ function buildMatrixRow( array, offset ) {
|
|
|
1635
1723
|
|
|
1636
1724
|
}
|
|
1637
1725
|
|
|
1638
|
-
// Mesh
|
|
1726
|
+
// #region Mesh
|
|
1639
1727
|
|
|
1640
1728
|
function buildMeshObject( geometry: BufferGeometry, bonesArray: Bone[] = [], quickLookCompatible: boolean = true) {
|
|
1641
1729
|
|
|
@@ -1948,7 +2036,9 @@ function buildVector2Array( attribute: BufferAttribute | InterleavedBufferAttrib
|
|
|
1948
2036
|
|
|
1949
2037
|
}
|
|
1950
2038
|
|
|
1951
|
-
//
|
|
2039
|
+
// #endregion
|
|
2040
|
+
|
|
2041
|
+
// #region Materials
|
|
1952
2042
|
|
|
1953
2043
|
function buildMaterials( materials: Map<string, Material>, textures: TextureMap, quickLookCompatible = false ) {
|
|
1954
2044
|
|
|
@@ -2103,10 +2193,14 @@ function buildTexture( texture: Texture, mapType: MapType, quickLookCompatible:
|
|
|
2103
2193
|
}`;
|
|
2104
2194
|
}
|
|
2105
2195
|
|
|
2196
|
+
|
|
2106
2197
|
function buildMaterial( material: MeshBasicMaterial, textures: TextureMap, quickLookCompatible = false ) {
|
|
2107
2198
|
|
|
2108
2199
|
const materialName = getMaterialName(material);
|
|
2109
2200
|
|
|
2201
|
+
// TODO: refactor to USDMaterial class
|
|
2202
|
+
// const usdMaterial = new USDMaterial(material);
|
|
2203
|
+
|
|
2110
2204
|
// Special case: occluder material
|
|
2111
2205
|
// Supported on iOS 18+ and visionOS 1+
|
|
2112
2206
|
const isShadowCatcherMaterial =
|
|
@@ -2330,6 +2424,7 @@ function buildMaterial( material: MeshBasicMaterial, textures: TextureMap, quick
|
|
|
2330
2424
|
}
|
|
2331
2425
|
}
|
|
2332
2426
|
|
|
2427
|
+
|
|
2333
2428
|
return `
|
|
2334
2429
|
|
|
2335
2430
|
def Material "${materialName}" ${material.name ?`(
|
|
@@ -2368,6 +2463,8 @@ ${samplers.join( '\n' )}` : ''}
|
|
|
2368
2463
|
}`;
|
|
2369
2464
|
}
|
|
2370
2465
|
|
|
2466
|
+
// #endregion
|
|
2467
|
+
|
|
2371
2468
|
function buildColor( color ) {
|
|
2372
2469
|
|
|
2373
2470
|
return `(${color.r}, ${color.g}, ${color.b})`;
|
|
@@ -2407,6 +2504,9 @@ const formatsWithAlphaChannel = [
|
|
|
2407
2504
|
36492, // RGBA_BPTC_Format
|
|
2408
2505
|
];
|
|
2409
2506
|
|
|
2507
|
+
|
|
2508
|
+
// #region exports
|
|
2509
|
+
|
|
2410
2510
|
export {
|
|
2411
2511
|
buildMatrix,
|
|
2412
2512
|
decompressGpuTexture,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { Object3D } from "three"
|
|
2
|
+
import { Object3D, Vector3 } from "three"
|
|
3
3
|
|
|
4
4
|
import { Mathf } from "../../engine/engine_math.js";
|
|
5
5
|
import { serializeable } from "../../engine/engine_serialization_decorator.js";
|
|
@@ -7,7 +7,10 @@ import { Behaviour } from "../Component.js";
|
|
|
7
7
|
import { SplineContainer } from "./Spline.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Moves an object along a spline.
|
|
10
|
+
* Moves an object along a spline.
|
|
11
|
+
* Use this with a SplineContainer component.
|
|
12
|
+
*
|
|
13
|
+
* - Example http://samples.needle.tools/splines
|
|
11
14
|
*/
|
|
12
15
|
export class SplineWalker extends Behaviour {
|
|
13
16
|
|
|
@@ -17,18 +20,35 @@ export class SplineWalker extends Behaviour {
|
|
|
17
20
|
@serializeable(SplineContainer)
|
|
18
21
|
spline: SplineContainer | null = null;
|
|
19
22
|
|
|
20
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* The object to move along the spline.
|
|
25
|
+
* If object is undefined then the spline walker will use it's own object (gameObject).
|
|
26
|
+
* If object is null the spline walker will not move any object.
|
|
21
27
|
* @default undefined
|
|
22
28
|
*/
|
|
23
29
|
@serializeable(Object3D)
|
|
24
30
|
object?: Object3D | null = undefined;
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* If true the object will rotate to look in the direction of the spline while moving along it.
|
|
36
|
+
* @default true
|
|
37
|
+
*/
|
|
38
|
+
@serializeable()
|
|
39
|
+
useLookAt = true;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The object to look at while moving along the spline.
|
|
43
|
+
* If null the object will look in the direction of the spline.
|
|
44
|
+
* This can be disabled by setting useLookAt to false.
|
|
27
45
|
* @default null
|
|
28
46
|
*/
|
|
29
47
|
@serializeable(Object3D)
|
|
30
48
|
lookAt: Object3D | null = null;
|
|
31
|
-
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
32
52
|
/**
|
|
33
53
|
* When clamp is set to true, the position01 value will be clamped between 0 and 1 and the object will not loop the spline.
|
|
34
54
|
* @default false
|
|
@@ -36,7 +56,10 @@ export class SplineWalker extends Behaviour {
|
|
|
36
56
|
@serializeable()
|
|
37
57
|
clamp: boolean = false;
|
|
38
58
|
|
|
39
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* The current position on the spline. The value ranges from 0 (start of the spline curve) to 1 (end of the spline curve)
|
|
61
|
+
*
|
|
62
|
+
* When setting this value, the position will be updated in the next frame.
|
|
40
63
|
* @default 0
|
|
41
64
|
*/
|
|
42
65
|
// @type float
|
|
@@ -46,7 +69,7 @@ export class SplineWalker extends Behaviour {
|
|
|
46
69
|
}
|
|
47
70
|
set position01(v: number) {
|
|
48
71
|
this._position01 = v;
|
|
49
|
-
this.
|
|
72
|
+
this._needsUpdate = true;
|
|
50
73
|
}
|
|
51
74
|
|
|
52
75
|
/** Resets the position to 0 */
|
|
@@ -68,25 +91,60 @@ export class SplineWalker extends Behaviour {
|
|
|
68
91
|
@serializeable()
|
|
69
92
|
duration: number = 10;
|
|
70
93
|
|
|
94
|
+
/**
|
|
95
|
+
* The strength with which the object is pulled to the spline.
|
|
96
|
+
* This can be used to create a "rubber band" effect when the object is moved away from the spline by other forces.
|
|
97
|
+
* A value of 0 means no pull, a value of 1 means the object is always on the spline.
|
|
98
|
+
* @default 1
|
|
99
|
+
*/
|
|
100
|
+
pullStrength: number = 1;
|
|
101
|
+
|
|
71
102
|
|
|
72
103
|
// #region internal
|
|
73
104
|
|
|
74
105
|
private _position01: number = 0;
|
|
106
|
+
private _needsUpdate = false;
|
|
75
107
|
|
|
76
108
|
/** @internal */
|
|
77
109
|
start() {
|
|
78
|
-
if(this.object === undefined) this.object = this.gameObject;
|
|
110
|
+
if (this.object === undefined) this.object = this.gameObject;
|
|
79
111
|
this.updateFromPosition();
|
|
80
112
|
}
|
|
81
113
|
|
|
114
|
+
/** @internal */
|
|
115
|
+
onEnable(): void {
|
|
116
|
+
window.addEventListener("pointerdown", this.onUserInput, { passive: true });
|
|
117
|
+
window.addEventListener("wheel", this.onUserInput, { passive: true });
|
|
118
|
+
}
|
|
119
|
+
/** @internal */
|
|
120
|
+
onDisable(): void {
|
|
121
|
+
window.removeEventListener("pointerdown", this.onUserInput);
|
|
122
|
+
window.removeEventListener("wheel", this.onUserInput);
|
|
123
|
+
}
|
|
124
|
+
private onUserInput = () => {
|
|
125
|
+
if (this.object?.contains(this.context.mainCamera)) {
|
|
126
|
+
this._needsUpdate = false;
|
|
127
|
+
this._performedUpdates += 999;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** @internal */
|
|
82
132
|
update() {
|
|
83
133
|
if (this.autoRun) {
|
|
134
|
+
this._needsUpdate = true;
|
|
84
135
|
this._position01 += this.context.time.deltaTime / this.duration;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (this._needsUpdate) {
|
|
139
|
+
this._needsUpdate = false;
|
|
85
140
|
this.updateFromPosition();
|
|
86
141
|
}
|
|
87
142
|
}
|
|
88
143
|
|
|
89
|
-
|
|
144
|
+
/**
|
|
145
|
+
* Updates the position of the object based on the current position01 value.
|
|
146
|
+
* @internal
|
|
147
|
+
*/
|
|
90
148
|
private updateFromPosition() {
|
|
91
149
|
if (!this.spline || !this.spline.curve) return;
|
|
92
150
|
if (!this.object) return;
|
|
@@ -96,11 +154,38 @@ export class SplineWalker extends Behaviour {
|
|
|
96
154
|
|
|
97
155
|
const t = this._position01 >= 1 ? 1 : this._position01 % 1;
|
|
98
156
|
const pt = this.spline.getPointAt(t);
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
157
|
+
|
|
158
|
+
if (this.pullStrength >= 1) {
|
|
159
|
+
this.object.worldPosition = pt;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
if (this._position01 !== this._lastPosition01) {
|
|
163
|
+
this._performedUpdates = 0;
|
|
164
|
+
}
|
|
165
|
+
this._requiredUpdates = Math.round(100 / this.pullStrength);
|
|
166
|
+
if (this._performedUpdates < this._requiredUpdates) {
|
|
167
|
+
const wp = this.object.worldPosition;
|
|
168
|
+
this._performedUpdates++;
|
|
169
|
+
const pull = Mathf.clamp01(this.pullStrength);
|
|
170
|
+
const newPosition = this.object.worldPosition = wp.lerp(pt, pull * (this.context.time.deltaTime / .3));
|
|
171
|
+
this._lastPositionVector.copy(newPosition);
|
|
172
|
+
this._needsUpdate = true;
|
|
173
|
+
}
|
|
103
174
|
}
|
|
104
|
-
|
|
175
|
+
|
|
176
|
+
if (this.useLookAt) {
|
|
177
|
+
if (!this.lookAt) {
|
|
178
|
+
const tan = this.spline.getTangentAt(t);
|
|
179
|
+
this.object.lookAt(pt.add(tan));
|
|
180
|
+
}
|
|
181
|
+
else this.object.lookAt(this.lookAt.worldPosition);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
this._lastPosition01 = this._position01;
|
|
105
185
|
}
|
|
186
|
+
|
|
187
|
+
private _lastPosition01 = 0;
|
|
188
|
+
private _requiredUpdates: number = 0;
|
|
189
|
+
private _performedUpdates: number = 0;
|
|
190
|
+
private _lastPositionVector = new Vector3();
|
|
106
191
|
}
|