@@ -21,6 +21,21 @@ class EjectableSceneObject extends SceneObject {
21
21
private _deltaTransformation ?: THREE . Matrix4
22
22
private _ejectVelocity ?: number
23
23
24
+ // Animation state
25
+ private _animationStartTime = 0
26
+ private _animationDuration = EjectableSceneObject . _defaultAnimationDuration
27
+ private _startTranslation ?: THREE . Vector3
28
+ private _startRotation ?: THREE . Quaternion
29
+
30
+ private static _defaultAnimationDuration = 0.5
31
+
32
+ public static setAnimationDuration ( duration : number ) {
33
+ EjectableSceneObject . _defaultAnimationDuration = duration
34
+ }
35
+ public static getAnimationDuration ( ) {
36
+ return EjectableSceneObject . _defaultAnimationDuration
37
+ }
38
+
24
39
public get gamePieceBodyId ( ) {
25
40
return this . _gamePieceBodyId
26
41
}
@@ -49,15 +64,24 @@ class EjectableSceneObject extends SceneObject {
49
64
)
50
65
this . _ejectVelocity = this . _parentAssembly . ejectorPreferences . ejectorVelocity
51
66
67
+ // Record start transform at the game piece center of mass
68
+ const gpBody = World . physicsSystem . getBody ( this . _gamePieceBodyId )
69
+ this . _startTranslation = new THREE . Vector3 ( 0 , 0 , 0 )
70
+ this . _startRotation = new THREE . Quaternion ( 0 , 0 , 0 , 1 )
71
+ convertJoltMat44ToThreeMatrix4 ( gpBody . GetCenterOfMassTransform ( ) ) . decompose (
72
+ this . _startTranslation ,
73
+ this . _startRotation ,
74
+ new THREE . Vector3 ( 1 , 1 , 1 )
75
+ )
76
+
77
+ this . _animationDuration = EjectableSceneObject . _defaultAnimationDuration
78
+ this . _animationStartTime = performance . now ( )
79
+
52
80
World . physicsSystem . disablePhysicsForBody ( this . _gamePieceBodyId )
53
81
54
- // Checks if the gamepiece comes from a zone for persistent point score updates
55
- // because gamepieces removed by intake are not detected in the collision listener
82
+ // Remove from any scoring zones
56
83
const zones = [ ...World . sceneRenderer . sceneObjects . entries ( ) ]
57
- . filter ( x => {
58
- const y = x [ 1 ] instanceof ScoringZoneSceneObject
59
- return y
60
- } )
84
+ . filter ( x => x [ 1 ] instanceof ScoringZoneSceneObject )
61
85
. map ( x => x [ 1 ] ) as ScoringZoneSceneObject [ ]
62
86
63
87
zones . forEach ( x => {
@@ -69,26 +93,51 @@ class EjectableSceneObject extends SceneObject {
69
93
}
70
94
71
95
public update ( ) : void {
96
+ const now = performance . now ( )
97
+ const elapsed = ( now - this . _animationStartTime ) / 1000
98
+ const tRaw = elapsed / this . _animationDuration
99
+ const t = Math . min ( tRaw , 1 )
100
+
101
+ // ease-in curve for gradual acceleration
102
+ const easedT = t * t
103
+
72
104
if ( this . _parentBodyId && this . _deltaTransformation && this . _gamePieceBodyId ) {
73
105
if ( ! World . physicsSystem . isBodyAdded ( this . _gamePieceBodyId ) ) {
74
106
this . _gamePieceBodyId = undefined
75
107
return
76
108
}
77
109
78
- // I had a think and free wrote this matrix math on a whim. It worked first try and I honestly can't quite remember how it works... -Hunter
79
110
const gpBody = World . physicsSystem . getBody ( this . _gamePieceBodyId )
80
111
const posToCOM = convertJoltMat44ToThreeMatrix4 ( gpBody . GetCenterOfMassTransform ( ) ) . premultiply (
81
112
convertJoltMat44ToThreeMatrix4 ( gpBody . GetWorldTransform ( ) ) . invert ( )
82
113
)
83
114
84
115
const body = World . physicsSystem . getBody ( this . _parentBodyId )
85
- const bodyTransform = posToCOM
86
- . invert ( )
87
- . premultiply (
88
- this . _deltaTransformation
89
- . clone ( )
90
- . premultiply ( convertJoltMat44ToThreeMatrix4 ( body . GetWorldTransform ( ) ) )
91
- )
116
+ let desiredPosition = new THREE . Vector3 ( 0 , 0 , 0 )
117
+ let desiredRotation = new THREE . Quaternion ( 0 , 0 , 0 , 1 )
118
+
119
+ // Compute target world transform
120
+ const desiredTransform = this . _deltaTransformation
121
+ . clone ( )
122
+ . premultiply ( convertJoltMat44ToThreeMatrix4 ( body . GetWorldTransform ( ) ) )
123
+
124
+ desiredTransform . decompose ( desiredPosition , desiredRotation , new THREE . Vector3 ( 1 , 1 , 1 ) )
125
+
126
+ if ( t < 1 && this . _startTranslation && this . _startRotation ) {
127
+ // gradual acceleration via easedT
128
+ desiredPosition = new THREE . Vector3 ( ) . lerpVectors ( this . _startTranslation , desiredPosition , easedT )
129
+ desiredRotation = new THREE . Quaternion ( ) . copy ( this . _startRotation ) . slerp ( desiredRotation , easedT )
130
+ }
131
+ // } else if (t >= 1) {
132
+ // // snap instantly and re-enable physics
133
+ // World.physicsSystem.enablePhysicsForBody(this._gamePieceBodyId)
134
+ // }
135
+
136
+ // apply the transform
137
+ desiredTransform . identity ( ) . compose ( desiredPosition , desiredRotation , new THREE . Vector3 ( 1 , 1 , 1 ) )
138
+
139
+ const bodyTransform = posToCOM . clone ( ) . invert ( ) . premultiply ( desiredTransform )
140
+
92
141
const position = new THREE . Vector3 ( 0 , 0 , 0 )
93
142
const rotation = new THREE . Quaternion ( 0 , 0 , 0 , 1 )
94
143
bodyTransform . decompose ( position , rotation , new THREE . Vector3 ( 1 , 1 , 1 ) )
0 commit comments