@needle-tools/engine 3.4.0-alpha → 3.5.0-alpha
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 +9 -0
- package/dist/needle-engine.js +59357 -59090
- package/dist/needle-engine.min.js +368 -345
- package/dist/needle-engine.umd.cjs +386 -363
- package/lib/engine/api.d.ts +1 -0
- package/lib/engine/api.js +1 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/engine_context.d.ts +1 -1
- package/lib/engine/engine_context.js +21 -15
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_registry.d.ts +5 -3
- package/lib/engine/engine_context_registry.js +10 -2
- package/lib/engine/engine_context_registry.js.map +1 -1
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.js +2 -3
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_input.d.ts +2 -2
- package/lib/engine/engine_physics.d.ts +20 -93
- package/lib/engine/engine_physics.js +20 -892
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics.types.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +103 -0
- package/lib/engine/engine_physics_rapier.js +1003 -0
- package/lib/engine/engine_physics_rapier.js.map +1 -0
- package/lib/engine/engine_types.d.ts +50 -1
- package/lib/engine/engine_types.js +8 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine-components/Collider.js +6 -6
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Joints.js +2 -2
- package/lib/engine-components/Joints.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +0 -1
- package/lib/engine-components/RigidBody.js +24 -30
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +55 -27
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +8 -2
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +44 -7
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
- package/lib/engine-components/ui/RectTransform.js +3 -1
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/plugins/vite/config.js +2 -1
- package/plugins/vite/defines.js +30 -0
- package/plugins/vite/dependency-watcher.js +173 -0
- package/plugins/vite/editor-connection.js +37 -39
- package/plugins/vite/index.js +5 -1
- package/plugins/vite/reload.js +3 -1
- package/src/engine/api.ts +1 -0
- package/src/engine/codegen/register_types.js +2 -2
- package/src/engine/engine_context.ts +32 -23
- package/src/engine/engine_context_registry.ts +13 -6
- package/src/engine/engine_element.ts +2 -1
- package/src/engine/engine_element_loading.ts +2 -3
- package/src/engine/engine_input.ts +2 -2
- package/src/engine/engine_physics.ts +25 -1020
- package/src/engine/engine_physics.types.ts +1 -3
- package/src/engine/engine_physics_rapier.ts +1127 -0
- package/src/engine/engine_types.ts +66 -4
- package/src/engine-components/Collider.ts +6 -6
- package/src/engine-components/Joints.ts +2 -2
- package/src/engine-components/RigidBody.ts +24 -31
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +62 -30
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +51 -9
- package/src/engine-components/ui/RectTransform.ts +3 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RenderTexture } from "./engine_texture";
|
|
2
|
-
import { Camera, Color, Material, Object3D, Vector3, Quaternion, Ray, Scene, Renderer, WebGLRenderer } from "three";
|
|
2
|
+
import { Camera, Color, Material, Object3D, Vector3, Quaternion, Ray, Scene, Renderer, WebGLRenderer, Mesh } from "three";
|
|
3
3
|
import { RGBAColor } from "../engine-components/js-extensions/RGBAColor";
|
|
4
4
|
import { CollisionDetectionMode, PhysicsMaterial, RigidbodyConstraints } from "./engine_physics.types";
|
|
5
5
|
import { CircularBuffer } from "./engine_utils";
|
|
@@ -20,7 +20,6 @@ export interface UIDProvider {
|
|
|
20
20
|
generateUUID(): string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
export declare type CoroutineData = {
|
|
25
24
|
comp: IComponent,
|
|
26
25
|
main: Generator,
|
|
@@ -31,9 +30,17 @@ export interface ITime {
|
|
|
31
30
|
get time(): number;
|
|
32
31
|
}
|
|
33
32
|
|
|
33
|
+
export interface IInput {
|
|
34
|
+
convertScreenspaceToRaycastSpace(vec: Vec2): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface IPhysics {
|
|
38
|
+
engine?: IPhysicsEngine;
|
|
39
|
+
}
|
|
40
|
+
|
|
34
41
|
export interface IContext {
|
|
35
42
|
alias?: string | null;
|
|
36
|
-
hash?:string;
|
|
43
|
+
hash?: string;
|
|
37
44
|
|
|
38
45
|
scene: Scene;
|
|
39
46
|
renderer: WebGLRenderer;
|
|
@@ -42,6 +49,8 @@ export interface IContext {
|
|
|
42
49
|
domElement: HTMLElement;
|
|
43
50
|
|
|
44
51
|
time: ITime;
|
|
52
|
+
input: IInput;
|
|
53
|
+
physics: IPhysics;
|
|
45
54
|
|
|
46
55
|
scripts: IComponent[];
|
|
47
56
|
scripts_pausedChanged: IComponent[];
|
|
@@ -343,4 +352,57 @@ export class Collision {
|
|
|
343
352
|
// }
|
|
344
353
|
// return this._point;
|
|
345
354
|
// }
|
|
346
|
-
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export type RaycastResult = null | { point: Vector3, collider: ICollider, normal?: Vector3 };
|
|
358
|
+
|
|
359
|
+
export class SphereOverlapResult {
|
|
360
|
+
object: Object3D;
|
|
361
|
+
collider: ICollider;
|
|
362
|
+
constructor(object: Object3D, collider: ICollider) {
|
|
363
|
+
this.object = object;
|
|
364
|
+
this.collider = collider;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
export interface IPhysicsEngine {
|
|
370
|
+
initialize(ctx: IContext): Promise<boolean>;
|
|
371
|
+
step(dt: number): void;
|
|
372
|
+
postStep();
|
|
373
|
+
get isUpdating(): boolean;
|
|
374
|
+
/** clear all possibly cached data (e.g. mesh data when creating scaled mesh colliders) */
|
|
375
|
+
clearCaches();
|
|
376
|
+
|
|
377
|
+
// raycasting
|
|
378
|
+
/** fast raycast without getting the normal vector */
|
|
379
|
+
raycast(origin: Vec2 | Vec3, direction: Vec3 | undefined, maxDistance: number, solid: boolean): RaycastResult;
|
|
380
|
+
/** raycast that also gets the normal vector. If you don't need it use raycast() */
|
|
381
|
+
raycastAndGetNormal(origin: Vec2 | Vec3, direction: Vec3 | undefined, maxDistance: number, solid: boolean) : RaycastResult;
|
|
382
|
+
sphereOverlap(point: Vector3, radius: number): Array<SphereOverlapResult>;
|
|
383
|
+
|
|
384
|
+
// Collider methods
|
|
385
|
+
addSphereCollider(collider: ICollider, center: Vector3, radius: number);
|
|
386
|
+
addBoxCollider(collider: ICollider, center: Vector3, size: Vector3);
|
|
387
|
+
addCapsuleCollider(collider: ICollider, center: Vector3, radius: number, height: number);
|
|
388
|
+
addMeshCollider(collider: ICollider, mesh: Mesh, convex: boolean, scale: Vector3);
|
|
389
|
+
|
|
390
|
+
// Rigidbody methods
|
|
391
|
+
wakeup(rb: IRigidbody);
|
|
392
|
+
updateProperties(rb: IRigidbody);
|
|
393
|
+
resetForces(rb: IRigidbody, wakeup: boolean);
|
|
394
|
+
resetTorques(rb: IRigidbody, wakeup: boolean);
|
|
395
|
+
addForce(rb: IRigidbody, vec: Vec3, wakeup: boolean);
|
|
396
|
+
applyImpulse(rb: IRigidbody, vec: Vec3, wakeup: boolean);
|
|
397
|
+
getLinearVelocity(rb: IRigidbody): Vec3 | null;
|
|
398
|
+
getAngularVelocity(rb: IRigidbody): Vec3 | null;
|
|
399
|
+
setAngularVelocity(rb: IRigidbody, vec: Vec3, wakeup: boolean);
|
|
400
|
+
setLinearVelocity(rb: IRigidbody, vec: Vec3, wakeup: boolean);
|
|
401
|
+
|
|
402
|
+
updateBody(comp: ICollider | IRigidbody, translation: boolean, rotation: boolean);
|
|
403
|
+
removeBody(body: IComponent);
|
|
404
|
+
|
|
405
|
+
// Joints
|
|
406
|
+
addFixedJoint(body1: IRigidbody, body2: IRigidbody)
|
|
407
|
+
addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3)
|
|
408
|
+
}
|
|
@@ -40,7 +40,7 @@ export class Collider extends Behaviour implements ICollider {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
onDisable() {
|
|
43
|
-
this.context.physics.removeBody(this);
|
|
43
|
+
this.context.physics.engine?.removeBody(this);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
}
|
|
@@ -55,7 +55,7 @@ export class SphereCollider extends Collider {
|
|
|
55
55
|
|
|
56
56
|
onEnable() {
|
|
57
57
|
super.onEnable();
|
|
58
|
-
this.context.physics.addSphereCollider(this, this.center, this.radius);
|
|
58
|
+
this.context.physics.engine?.addSphereCollider(this, this.center, this.radius);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -68,7 +68,7 @@ export class BoxCollider extends Collider {
|
|
|
68
68
|
|
|
69
69
|
onEnable() {
|
|
70
70
|
super.onEnable();
|
|
71
|
-
this.context.physics.addBoxCollider(this, this.center, this.size);
|
|
71
|
+
this.context.physics.engine?.addBoxCollider(this, this.center, this.size);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -90,7 +90,7 @@ export class MeshCollider extends Collider {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
if (this.sharedMesh?.isMesh) {
|
|
93
|
-
this.context.physics.addMeshCollider(this, this.sharedMesh, this.convex, getWorldScale(this.gameObject));
|
|
93
|
+
this.context.physics.engine?.addMeshCollider(this, this.sharedMesh, this.convex, getWorldScale(this.gameObject));
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
96
96
|
const group = this.sharedMesh as any as Group;
|
|
@@ -99,7 +99,7 @@ export class MeshCollider extends Collider {
|
|
|
99
99
|
for (const ch in group.children) {
|
|
100
100
|
const child = group.children[ch] as Mesh;
|
|
101
101
|
if (child.isMesh) {
|
|
102
|
-
this.context.physics.addMeshCollider(this, child, this.convex, getWorldScale(this.gameObject));
|
|
102
|
+
this.context.physics.engine?.addMeshCollider(this, child, this.convex, getWorldScale(this.gameObject));
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -119,7 +119,7 @@ export class CapsuleCollider extends Collider {
|
|
|
119
119
|
|
|
120
120
|
onEnable() {
|
|
121
121
|
super.onEnable();
|
|
122
|
-
this.context.physics.addCapsuleCollider(this, this.center, this.height, this.radius);
|
|
122
|
+
this.context.physics.engine?.addCapsuleCollider(this, this.center, this.height, this.radius);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
}
|
|
@@ -32,7 +32,7 @@ export abstract class Joint extends Behaviour {
|
|
|
32
32
|
export class FixedJoint extends Joint {
|
|
33
33
|
|
|
34
34
|
protected createJoint(self: Rigidbody, other: Rigidbody) {
|
|
35
|
-
this.context.physics.addFixedJoint(self, other);
|
|
35
|
+
this.context.physics.engine?.addFixedJoint(self, other);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -46,7 +46,7 @@ export class HingeJoint extends Joint {
|
|
|
46
46
|
|
|
47
47
|
protected createJoint(self: Rigidbody, other: Rigidbody) {
|
|
48
48
|
if (this.axis && this.anchor)
|
|
49
|
-
this.context.physics.addHingeJoint(self, other, this.anchor, this.axis);
|
|
49
|
+
this.context.physics.engine?.addHingeJoint(self, other, this.anchor, this.axis);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
}
|
|
@@ -89,7 +89,7 @@ class TransformWatch {
|
|
|
89
89
|
this.position = {};
|
|
90
90
|
// this.position = this.obj.position.clone();
|
|
91
91
|
this._positionWatch.subscribeWrite((val, prop) => {
|
|
92
|
-
if (this.context.physics.isUpdating || this.mute) return;
|
|
92
|
+
if (this.context.physics.engine?.isUpdating || this.mute) return;
|
|
93
93
|
const prev = this.position![prop];
|
|
94
94
|
if (Math.abs(prev - val) < .00001) return;
|
|
95
95
|
this.position![prop] = val;
|
|
@@ -103,7 +103,7 @@ class TransformWatch {
|
|
|
103
103
|
this.quaternion = {};
|
|
104
104
|
// this.quaternion = this.obj.quaternion.clone();
|
|
105
105
|
this._rotationWatch.subscribeWrite((val, prop) => {
|
|
106
|
-
if (this.context.physics.isUpdating || this.mute) return;
|
|
106
|
+
if (this.context.physics.engine?.isUpdating || this.mute) return;
|
|
107
107
|
const prev = this.quaternion![prop];
|
|
108
108
|
if (Math.abs(prev - val) < .00001) return;
|
|
109
109
|
this.quaternion![prop] = val;
|
|
@@ -245,11 +245,11 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
245
245
|
|
|
246
246
|
onDisable() {
|
|
247
247
|
this._watch?.stop();
|
|
248
|
-
this.context.physics.removeBody(this);
|
|
248
|
+
this.context.physics.engine?.removeBody(this);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
onDestroy(): void {
|
|
252
|
-
this.context.physics.removeBody(this);
|
|
252
|
+
this.context.physics.engine?.removeBody(this);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
onValidate() {
|
|
@@ -261,12 +261,12 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
261
261
|
while (true) {
|
|
262
262
|
if (this._propertiesChanged) {
|
|
263
263
|
this._propertiesChanged = false;
|
|
264
|
-
this.context.physics.updateProperties(this);
|
|
264
|
+
this.context.physics.engine?.updateProperties(this);
|
|
265
265
|
}
|
|
266
266
|
if (this._watch?.isDirty) {
|
|
267
267
|
this._watch.mute = true;
|
|
268
268
|
this._watch.applyValues();
|
|
269
|
-
this.context.physics.updateBody(this, this._watch.positionChanged, this._watch.rotationChanged);
|
|
269
|
+
this.context.physics.engine?.updateBody(this, this._watch.positionChanged, this._watch.rotationChanged);
|
|
270
270
|
this._watch.reset();
|
|
271
271
|
}
|
|
272
272
|
else this._watch?.syncValues();
|
|
@@ -275,10 +275,6 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
private get body() {
|
|
279
|
-
return this.context.physics.internal_getRigidbody(this);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
278
|
public teleport(pt: { x: number, y: number, z: number }, localspace: boolean = true) {
|
|
283
279
|
this._watch?.reset(true);
|
|
284
280
|
if (localspace) this.gameObject.position.set(pt.x, pt.y, pt.z);
|
|
@@ -288,11 +284,11 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
288
284
|
}
|
|
289
285
|
|
|
290
286
|
public resetForces() {
|
|
291
|
-
this.
|
|
287
|
+
this.context.physics.engine?.resetForces(this, true);
|
|
292
288
|
}
|
|
293
289
|
|
|
294
290
|
public resetTorques() {
|
|
295
|
-
this.
|
|
291
|
+
this.context.physics.engine?.resetTorques(this, true);
|
|
296
292
|
}
|
|
297
293
|
|
|
298
294
|
public resetVelocities() {
|
|
@@ -306,24 +302,24 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
306
302
|
}
|
|
307
303
|
|
|
308
304
|
public wakeUp() {
|
|
309
|
-
this.
|
|
305
|
+
this.context.physics.engine?.wakeup(this);
|
|
310
306
|
}
|
|
311
307
|
|
|
312
308
|
public applyForce(vec: Vector3, _rel?: THREE.Vector3) {
|
|
313
|
-
this.
|
|
309
|
+
this.context.physics.engine?.addForce(this, vec, true);
|
|
314
310
|
}
|
|
315
311
|
|
|
316
312
|
public applyImpulse(vec: Vector3) {
|
|
317
|
-
this.
|
|
313
|
+
this.context.physics.engine?.applyImpulse(this, vec, true);
|
|
318
314
|
}
|
|
319
315
|
|
|
320
316
|
public setForce(x: number, y: number, z: number) {
|
|
321
|
-
this.
|
|
322
|
-
this.
|
|
317
|
+
this.context.physics.engine?.resetForces(this, true);
|
|
318
|
+
this.context.physics.engine?.addForce(this, { x, y, z }, true);
|
|
323
319
|
}
|
|
324
320
|
|
|
325
321
|
public getVelocity(): Vector3 {
|
|
326
|
-
const vel = this.
|
|
322
|
+
const vel = this.context.physics.engine?.getLinearVelocity(this);
|
|
327
323
|
if (!vel) return this._currentVelocity.set(0, 0, 0);
|
|
328
324
|
this._currentVelocity.x = vel.x;
|
|
329
325
|
this._currentVelocity.y = vel.y;
|
|
@@ -334,25 +330,25 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
334
330
|
public setVelocity(x: number | Vector3, y?: number, z?: number) {
|
|
335
331
|
if (x instanceof Vector3) {
|
|
336
332
|
const vec = x;
|
|
337
|
-
this.
|
|
333
|
+
this.context.physics.engine?.setLinearVelocity(this,vec, true);
|
|
338
334
|
return;
|
|
339
335
|
}
|
|
340
336
|
if (y === undefined || z === undefined) return;
|
|
341
|
-
this.
|
|
337
|
+
this.context.physics.engine?.setLinearVelocity(this, { x: x, y: y, z: z }, true);
|
|
342
338
|
}
|
|
343
339
|
|
|
344
340
|
public setAngularVelocity(x: number | Vector3, y?: number, z?: number) {
|
|
345
341
|
if (x instanceof Vector3) {
|
|
346
342
|
const vec = x;
|
|
347
|
-
this.
|
|
343
|
+
this.context.physics.engine?.setAngularVelocity(this, vec, true);
|
|
348
344
|
return;
|
|
349
345
|
}
|
|
350
346
|
if (y === undefined || z === undefined) return;
|
|
351
|
-
this.
|
|
347
|
+
this.context.physics.engine?.setAngularVelocity(this, { x: x, y: y, z: z }, true);
|
|
352
348
|
}
|
|
353
349
|
|
|
354
350
|
public getAngularVelocity(): Vector3 {
|
|
355
|
-
const vel = this.
|
|
351
|
+
const vel = this.context.physics.engine?.getAngularVelocity(this);
|
|
356
352
|
if (!vel) return this._currentVelocity.set(0, 0, 0);
|
|
357
353
|
this._currentVelocity.x = vel.x;
|
|
358
354
|
this._currentVelocity.y = vel.y;
|
|
@@ -381,13 +377,10 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
381
377
|
|
|
382
378
|
|
|
383
379
|
private captureVelocity() {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
this._smoothedVelocity.lerp(vel, this.context.time.deltaTime / .1);
|
|
390
|
-
// this._smoothedVelocity.set(0, 1 / this.context.time.deltaTime, 0);
|
|
391
|
-
}
|
|
380
|
+
const wp = getWorldPosition(this.gameObject);
|
|
381
|
+
Rigidbody.tempPosition.copy(wp);
|
|
382
|
+
const vel = wp.sub(this._lastPosition);
|
|
383
|
+
this._lastPosition.copy(Rigidbody.tempPosition);
|
|
384
|
+
this._smoothedVelocity.lerp(vel, this.context.time.deltaTime / .1);
|
|
392
385
|
}
|
|
393
386
|
}
|
|
@@ -17,6 +17,9 @@ import {
|
|
|
17
17
|
Camera,
|
|
18
18
|
Color,
|
|
19
19
|
MeshStandardMaterial,
|
|
20
|
+
LinearEncoding,
|
|
21
|
+
sRGBEncoding,
|
|
22
|
+
MeshPhysicalMaterial,
|
|
20
23
|
} from 'three';
|
|
21
24
|
import * as fflate from 'three/examples/jsm/libs/fflate.module.js';
|
|
22
25
|
|
|
@@ -400,13 +403,7 @@ class USDZExporter {
|
|
|
400
403
|
|
|
401
404
|
async parse( scene, options: USDZExporterOptions = new USDZExporterOptions() ) {
|
|
402
405
|
|
|
403
|
-
options = Object.assign(
|
|
404
|
-
ar: {
|
|
405
|
-
anchoring: { type: 'plane' },
|
|
406
|
-
planeAnchoring: { alignment: 'horizontal' }
|
|
407
|
-
},
|
|
408
|
-
extensions: []
|
|
409
|
-
}, options );
|
|
406
|
+
options = Object.assign( new USDZExporterOptions(), options );
|
|
410
407
|
|
|
411
408
|
this.sceneAnchoringOptions = options;
|
|
412
409
|
// @ts-ignore
|
|
@@ -598,7 +595,7 @@ function parseDocument( context: USDZExporterContext ) {
|
|
|
598
595
|
|
|
599
596
|
writer.appendLine( `token preliminary:anchoring:type = "${context.exporter.sceneAnchoringOptions.ar.anchoring.type}"` );
|
|
600
597
|
if (context.exporter.sceneAnchoringOptions.ar.anchoring.type === 'plane')
|
|
601
|
-
writer.appendLine( `token preliminary:planeAnchoring:alignment = "${context.exporter.sceneAnchoringOptions.
|
|
598
|
+
writer.appendLine( `token preliminary:planeAnchoring:alignment = "${context.exporter.sceneAnchoringOptions.planeAnchoring.alignment}"` );
|
|
602
599
|
// bit hacky as we don't have a callback here yet. Relies on the fact that the image is named identical in the ImageTracking extension.
|
|
603
600
|
if (context.exporter.sceneAnchoringOptions.ar.anchoring.type === 'image')
|
|
604
601
|
writer.appendLine( `rel preliminary:imageAnchoring:referenceImage = </${context.document.name}/Scenes/Scene/AnchoringReferenceImage>` );
|
|
@@ -679,21 +676,38 @@ function copyTexture( texture ) {
|
|
|
679
676
|
|
|
680
677
|
const geometry = new PlaneGeometry( 2, 2, 1, 1 );
|
|
681
678
|
const material = new ShaderMaterial( {
|
|
682
|
-
uniforms: {
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
679
|
+
uniforms: {
|
|
680
|
+
blitTexture: new Uniform( texture ),
|
|
681
|
+
},
|
|
682
|
+
defines: {
|
|
683
|
+
IS_SRGB: texture.encoding == sRGBEncoding,
|
|
684
|
+
},
|
|
685
|
+
vertexShader: `
|
|
686
|
+
varying vec2 vUv;
|
|
687
|
+
void main(){
|
|
688
|
+
vUv = uv;
|
|
689
|
+
vUv.y = 1. - vUv.y;
|
|
690
|
+
gl_Position = vec4(position.xy * 1.0,0.,.999999);
|
|
691
|
+
}`,
|
|
692
|
+
fragmentShader: `
|
|
693
|
+
uniform sampler2D blitTexture;
|
|
694
|
+
varying vec2 vUv;
|
|
695
|
+
|
|
696
|
+
// took from threejs 05fc79cd52b79e8c3e8dec1e7dca72c5c39983a4
|
|
697
|
+
vec4 conv_LinearTosRGB( in vec4 value ) {
|
|
698
|
+
return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
void main(){
|
|
702
|
+
gl_FragColor = vec4(vUv.xy, 0, 1);
|
|
703
|
+
|
|
704
|
+
#ifdef IS_SRGB
|
|
705
|
+
gl_FragColor = conv_LinearTosRGB( texture2D( blitTexture, vUv) );
|
|
706
|
+
#else
|
|
707
|
+
gl_FragColor = texture2D( blitTexture, vUv);
|
|
708
|
+
#endif
|
|
709
|
+
}`
|
|
710
|
+
} );
|
|
697
711
|
|
|
698
712
|
const mesh = new Mesh( geometry, material );
|
|
699
713
|
mesh.frustumCulled = false;
|
|
@@ -705,7 +719,9 @@ function copyTexture( texture ) {
|
|
|
705
719
|
renderer.clear();
|
|
706
720
|
renderer.render( scene, cam );
|
|
707
721
|
|
|
708
|
-
|
|
722
|
+
const tex = new Texture( renderer.domElement );
|
|
723
|
+
tex.encoding = texture.encoding;
|
|
724
|
+
return tex;
|
|
709
725
|
|
|
710
726
|
}
|
|
711
727
|
|
|
@@ -825,7 +841,10 @@ export function buildXform( model, writer, context ) {
|
|
|
825
841
|
}
|
|
826
842
|
|
|
827
843
|
if ( geometry )
|
|
828
|
-
writer.beginBlock( `def Xform "${name}" (
|
|
844
|
+
writer.beginBlock( `def Xform "${name}" (
|
|
845
|
+
prepend references = @./geometries/Geometry_${geometry.id}.usd@</Geometry>
|
|
846
|
+
prepend apiSchemas = ["MaterialBindingAPI"]
|
|
847
|
+
)` );
|
|
829
848
|
else if ( camera )
|
|
830
849
|
writer.beginBlock( `def Camera "${name}"` );
|
|
831
850
|
else
|
|
@@ -929,11 +948,11 @@ function buildMesh( geometry ) {
|
|
|
929
948
|
)
|
|
930
949
|
point3f[] points = [${buildVector3Array( attributes.position, count )}]
|
|
931
950
|
${attributes.uv ?
|
|
932
|
-
`
|
|
951
|
+
`texCoord2f[] primvars:st = [${buildVector2Array( attributes.uv, count )}] (
|
|
933
952
|
interpolation = "vertex"
|
|
934
953
|
)` : '' }
|
|
935
954
|
${attributes.uv2 ?
|
|
936
|
-
`
|
|
955
|
+
`texCoord2f[] primvars:st2 = [${buildVector2Array( attributes.uv2, count )}] (
|
|
937
956
|
interpolation = "vertex"
|
|
938
957
|
)` : '' }
|
|
939
958
|
uniform token subdivisionScheme = "none"
|
|
@@ -1051,7 +1070,7 @@ ${array.join( '' )}
|
|
|
1051
1070
|
|
|
1052
1071
|
}
|
|
1053
1072
|
|
|
1054
|
-
function buildMaterial( material, textures ) {
|
|
1073
|
+
function buildMaterial( material: MeshStandardMaterial, textures ) {
|
|
1055
1074
|
|
|
1056
1075
|
// https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html
|
|
1057
1076
|
|
|
@@ -1090,6 +1109,13 @@ function buildMaterial( material, textures ) {
|
|
|
1090
1109
|
const textureTransformInput = `</Materials/Material_${material.id}/${uvReader}.outputs:result>`;
|
|
1091
1110
|
const textureTransformOutput = `</Materials/Material_${material.id}/Transform2d_${mapType}.outputs:result>`;
|
|
1092
1111
|
|
|
1112
|
+
const rawTextureExtra = `(
|
|
1113
|
+
colorSpace = "Raw"
|
|
1114
|
+
)`;
|
|
1115
|
+
const needsTextureScale = mapType !== 'normal' && (color && (color.r !== 1 || color.g !== 1 || color.b !== 1 || opacity !== 1)) || false;
|
|
1116
|
+
const needsNormalScaleAndBias = mapType === 'normal';
|
|
1117
|
+
const normalScaleValueString = (material.normalScale ? material.normalScale.x * 2 : 2).toFixed( PRECISION );
|
|
1118
|
+
|
|
1093
1119
|
return `
|
|
1094
1120
|
${needsTextureTransform ? `def Shader "Transform2d_${mapType}" (
|
|
1095
1121
|
sdrMetadata = {
|
|
@@ -1107,9 +1133,15 @@ function buildMaterial( material, textures ) {
|
|
|
1107
1133
|
def Shader "Texture_${texture.id}_${mapType}"
|
|
1108
1134
|
{
|
|
1109
1135
|
uniform token info:id = "UsdUVTexture"
|
|
1110
|
-
asset inputs:file = @textures/Texture_${id}.${isRGBA ? 'png' : 'jpg'}@
|
|
1136
|
+
asset inputs:file = @textures/Texture_${id}.${isRGBA ? 'png' : 'jpg'}@ ${mapType === 'normal' ? rawTextureExtra : ''}
|
|
1111
1137
|
float2 inputs:st.connect = ${needsTextureTransform ? textureTransformOutput : textureTransformInput}
|
|
1138
|
+
${needsTextureScale ? `
|
|
1112
1139
|
float4 inputs:scale = (${color ? color.r + ', ' + color.g + ', ' + color.b : '1, 1, 1'}, ${opacity ? opacity : '1'})
|
|
1140
|
+
` : `` }
|
|
1141
|
+
${needsNormalScaleAndBias ? `
|
|
1142
|
+
float4 inputs:scale = (${normalScaleValueString}, ${normalScaleValueString}, ${normalScaleValueString}, 1)
|
|
1143
|
+
float4 inputs:bias = (-1, -1, -1, 0)
|
|
1144
|
+
` : `` }
|
|
1113
1145
|
token inputs:wrapS = "${wrapS}"
|
|
1114
1146
|
token inputs:wrapT = "${wrapT}"
|
|
1115
1147
|
float outputs:r
|
|
@@ -1221,7 +1253,7 @@ function buildMaterial( material, textures ) {
|
|
|
1221
1253
|
|
|
1222
1254
|
}
|
|
1223
1255
|
|
|
1224
|
-
if ( material
|
|
1256
|
+
if ( material instanceof MeshPhysicalMaterial ) {
|
|
1225
1257
|
|
|
1226
1258
|
inputs.push( `${pad}float inputs:clearcoat = ${material.clearcoat}` );
|
|
1227
1259
|
inputs.push( `${pad}float inputs:clearcoatRoughness = ${material.clearcoatRoughness}` );
|
|
@@ -6,11 +6,11 @@ import { IPointerClickHandler } from "../../../../ui/PointerEvents";
|
|
|
6
6
|
import { RegisteredAnimationInfo, UsdzAnimation } from "../Animation";
|
|
7
7
|
import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../../../../../engine/engine_three_utils";
|
|
8
8
|
|
|
9
|
-
import { Object3D, Material, Vector3, Quaternion } from "three";
|
|
9
|
+
import { Object3D, Material, Vector3, Quaternion, AnimationAction } from "three";
|
|
10
10
|
import { USDObject } from "../../ThreeUSDZExporter";
|
|
11
11
|
|
|
12
12
|
import { BehaviorExtension, UsdzBehaviour } from "./Behaviour";
|
|
13
|
-
import { ActionBuilder, ActionModel, BehaviorModel, MotionType, Space, TriggerBuilder } from "./BehavioursBuilder";
|
|
13
|
+
import { ActionBuilder, ActionModel, BehaviorModel, IBehaviorElement, MotionType, Space, TriggerBuilder } from "./BehavioursBuilder";
|
|
14
14
|
|
|
15
15
|
export class ChangeTransformOnClick extends Behaviour implements IPointerClickHandler, UsdzBehaviour {
|
|
16
16
|
|
|
@@ -417,6 +417,12 @@ export class PlayAnimationOnClick extends Behaviour implements IPointerClickHand
|
|
|
417
417
|
|
|
418
418
|
@serializable()
|
|
419
419
|
stateName?: string;
|
|
420
|
+
|
|
421
|
+
@serializable()
|
|
422
|
+
stateNameAfterPlaying?: string;
|
|
423
|
+
|
|
424
|
+
@serializable()
|
|
425
|
+
loopAfterPlaying: boolean = false;
|
|
420
426
|
|
|
421
427
|
onPointerClick() {
|
|
422
428
|
if (!this.target) return;
|
|
@@ -425,22 +431,53 @@ export class PlayAnimationOnClick extends Behaviour implements IPointerClickHand
|
|
|
425
431
|
}
|
|
426
432
|
|
|
427
433
|
private selfModel: any;
|
|
428
|
-
|
|
429
|
-
private
|
|
434
|
+
|
|
435
|
+
private stateAnimationModel: any;
|
|
436
|
+
private stateAnimation?: RegisteredAnimationInfo;
|
|
437
|
+
|
|
438
|
+
private stateAfterPlayingAnimationModel: any;
|
|
439
|
+
private stateAfterPlayingAnimation?: RegisteredAnimationInfo;
|
|
430
440
|
|
|
431
441
|
createBehaviours(_ext, model, _context) {
|
|
432
442
|
if (model.uuid === this.gameObject.uuid)
|
|
433
443
|
this.selfModel = model;
|
|
434
444
|
}
|
|
435
445
|
|
|
446
|
+
private static animationActions: ActionModel[] = [];
|
|
447
|
+
|
|
448
|
+
onAfterHierarchy() {
|
|
449
|
+
PlayAnimationOnClick.animationActions = [];
|
|
450
|
+
}
|
|
451
|
+
|
|
436
452
|
afterCreateDocument(ext, context) {
|
|
437
|
-
if (!this.
|
|
453
|
+
if (!this.stateAnimation || !this.stateAnimationModel) return;
|
|
438
454
|
const document = context.document;
|
|
439
455
|
document.traverse(model => {
|
|
440
|
-
if
|
|
456
|
+
// TODO we should probably check if a startAnimationAction already exists, and not have duplicates of identical ones;
|
|
457
|
+
// looks like otherwise we're getting some animation overlap that doesn't look good.
|
|
458
|
+
if (model.uuid === this.target?.uuid && this.stateAnimation) {
|
|
459
|
+
const sequence: IBehaviorElement[] = [];
|
|
460
|
+
let startAction = PlayAnimationOnClick.animationActions.find(a => a.affectedObjects == model && a.start == this.stateAnimation!.start && a.duration == this.stateAnimation!.duration);
|
|
461
|
+
if (!startAction) {
|
|
462
|
+
startAction = ActionBuilder.startAnimationAction(model, this.stateAnimation.start, this.stateAnimation.duration) as ActionModel;
|
|
463
|
+
PlayAnimationOnClick.animationActions.push(startAction);
|
|
464
|
+
}
|
|
465
|
+
sequence.push(startAction);
|
|
466
|
+
|
|
467
|
+
if (this.stateAfterPlayingAnimation && this.stateAfterPlayingAnimationModel) {
|
|
468
|
+
let endAction = PlayAnimationOnClick.animationActions.find(a => a.affectedObjects == model && a.start == this.stateAfterPlayingAnimation!.start && a.duration == this.stateAfterPlayingAnimation!.duration);
|
|
469
|
+
if (!endAction) {
|
|
470
|
+
endAction = ActionBuilder.startAnimationAction(model, this.stateAfterPlayingAnimation.start, this.stateAfterPlayingAnimation.duration) as ActionModel;
|
|
471
|
+
PlayAnimationOnClick.animationActions.push(endAction);
|
|
472
|
+
}
|
|
473
|
+
const idleAnim = ActionBuilder.sequence(endAction);
|
|
474
|
+
if (this.loopAfterPlaying)
|
|
475
|
+
idleAnim.makeLooping();
|
|
476
|
+
sequence.push(idleAnim);
|
|
477
|
+
}
|
|
441
478
|
const playAnimationOnTap = new BehaviorModel("tap " + this.name + " for " + this.stateName + " on " + this.target?.name,
|
|
442
479
|
TriggerBuilder.tapTrigger(this.selfModel),
|
|
443
|
-
ActionBuilder.
|
|
480
|
+
ActionBuilder.sequence(...sequence)
|
|
444
481
|
);
|
|
445
482
|
ext.addBehavior(playAnimationOnTap);
|
|
446
483
|
}
|
|
@@ -449,9 +486,14 @@ export class PlayAnimationOnClick extends Behaviour implements IPointerClickHand
|
|
|
449
486
|
|
|
450
487
|
createAnimation(ext, model, _context) {
|
|
451
488
|
if (this.target && this.animator) {
|
|
489
|
+
|
|
452
490
|
const state = this.animator?.runtimeAnimatorController?.findState(this.stateName);
|
|
453
|
-
this.
|
|
454
|
-
this.
|
|
491
|
+
this.stateAnimationModel = model;
|
|
492
|
+
this.stateAnimation = ext.registerAnimation(this.target, state?.motion.clip);
|
|
493
|
+
|
|
494
|
+
const stateAfter = this.animator?.runtimeAnimatorController?.findState(this.stateNameAfterPlaying);
|
|
495
|
+
this.stateAfterPlayingAnimationModel = model;
|
|
496
|
+
this.stateAfterPlayingAnimation = ext.registerAnimation(this.target, stateAfter?.motion.clip);
|
|
455
497
|
}
|
|
456
498
|
}
|
|
457
499
|
|
|
@@ -191,7 +191,8 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
191
191
|
|
|
192
192
|
const uiobject = this.shadowComponent;
|
|
193
193
|
if (!uiobject) return;
|
|
194
|
-
|
|
194
|
+
if (!this.gameObject.parent) return;
|
|
195
|
+
this._parentRectTransform = GameObject.getComponentInParent(this.gameObject.parent, RectTransform) as RectTransform;
|
|
195
196
|
|
|
196
197
|
this._transformNeedsUpdate = false;
|
|
197
198
|
this.lastMatrix.copy(this.gameObject.matrix);
|
|
@@ -228,7 +229,7 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
|
|
|
228
229
|
else {
|
|
229
230
|
// We have to rotate the canvas when it's in worldspace
|
|
230
231
|
const canvas = this.Root as any as ICanvas;
|
|
231
|
-
if (!canvas.screenspace) uiobject.rotation.y = Math.PI;
|
|
232
|
+
if (canvas && !canvas.screenspace) uiobject.rotation.y = Math.PI;
|
|
232
233
|
}
|
|
233
234
|
|
|
234
235
|
// iterate other components on this object that might need to know about the transform change
|