@@ -47,6 +47,8 @@ export class TreeNode<T> {
47
47
/** 0: leaf, -1: free node */
48
48
height : number = - 1 ;
49
49
50
+ moved : boolean = false ;
51
+
50
52
constructor ( id ?: number ) {
51
53
this . id = id ;
52
54
}
@@ -110,6 +112,18 @@ export class DynamicTree<T> {
110
112
return node . userData ;
111
113
}
112
114
115
+ wasMoved ( proxyId : number ) : boolean {
116
+ const node = this . m_nodes [ proxyId ] ;
117
+ _ASSERT && console . assert ( ! ! node ) ;
118
+ return node . moved ;
119
+ }
120
+
121
+ clearMoved ( proxyId : number ) : void {
122
+ const node = this . m_nodes [ proxyId ] ;
123
+ _ASSERT && console . assert ( ! ! node ) ;
124
+ node . moved = false ;
125
+ }
126
+
113
127
/**
114
128
* Get the fat AABB for a node id.
115
129
*
@@ -152,6 +166,7 @@ export class DynamicTree<T> {
152
166
153
167
node . userData = userData ;
154
168
node . height = 0 ;
169
+ node . moved = true ;
155
170
156
171
this . insertLeaf ( node ) ;
157
172
@@ -176,48 +191,65 @@ export class DynamicTree<T> {
176
191
* fattened AABB, then the proxy is removed from the tree and re-inserted.
177
192
* Otherwise the function returns immediately.
178
193
*
179
- * @param d Displacement
194
+ * @param displacement Displacement
180
195
*
181
196
* @return true if the proxy was re-inserted.
182
197
*/
183
- moveProxy ( id : number , aabb : AABB , d : Vec2Value ) : boolean {
198
+ moveProxy ( id : number , aabb : AABB , displacement : Vec2Value ) : boolean {
184
199
_ASSERT && console . assert ( AABB . isValid ( aabb ) ) ;
185
- _ASSERT && console . assert ( ! d || Vec2 . isValid ( d ) ) ;
200
+ _ASSERT && console . assert ( ! displacement || Vec2 . isValid ( displacement ) ) ;
186
201
187
202
const node = this . m_nodes [ id ] ;
188
203
189
204
_ASSERT && console . assert ( ! ! node ) ;
190
205
_ASSERT && console . assert ( node . isLeaf ( ) ) ;
191
206
192
- if ( node . aabb . contains ( aabb ) ) {
193
- return false ;
194
- }
195
-
196
- this . removeLeaf ( node ) ;
197
-
198
- node . aabb . set ( aabb ) ;
199
-
200
207
// Extend AABB.
201
- aabb = node . aabb ;
202
- AABB . extend ( aabb , Settings . aabbExtension ) ;
208
+ const fatAABB = new AABB ( )
209
+ fatAABB . set ( aabb ) ;
210
+ AABB . extend ( fatAABB , Settings . aabbExtension ) ;
203
211
204
- // Predict AABB displacement.
212
+ // Predict AABB movement
205
213
// const d = Vec2.mul(Settings.aabbMultiplier, displacement);
206
214
207
- if ( d . x < 0.0 ) {
208
- aabb . lowerBound . x += d . x * Settings . aabbMultiplier ;
215
+ if ( displacement . x < 0.0 ) {
216
+ fatAABB . lowerBound . x += displacement . x * Settings . aabbMultiplier ;
209
217
} else {
210
- aabb . upperBound . x += d . x * Settings . aabbMultiplier ;
218
+ fatAABB . upperBound . x += displacement . x * Settings . aabbMultiplier ;
211
219
}
212
220
213
- if ( d . y < 0.0 ) {
214
- aabb . lowerBound . y += d . y * Settings . aabbMultiplier ;
221
+ if ( displacement . y < 0.0 ) {
222
+ fatAABB . lowerBound . y += displacement . y * Settings . aabbMultiplier ;
215
223
} else {
216
- aabb . upperBound . y += d . y * Settings . aabbMultiplier ;
224
+ fatAABB . upperBound . y += displacement . y * Settings . aabbMultiplier ;
225
+ }
226
+
227
+ const treeAABB = node . aabb ;
228
+ if ( treeAABB . contains ( aabb ) ) {
229
+ // The tree AABB still contains the object, but it might be too large.
230
+ // Perhaps the object was moving fast but has since gone to sleep.
231
+ // The huge AABB is larger than the new fat AABB.
232
+ const hugeAABB = new AABB ( ) ;
233
+ hugeAABB . set ( fatAABB ) ;
234
+ AABB . extend ( hugeAABB , 4.0 * Settings . aabbExtension ) ;
235
+
236
+ if ( hugeAABB . contains ( treeAABB ) ) {
237
+ // The tree AABB contains the object AABB and the tree AABB is
238
+ // not too large. No tree update needed.
239
+ return false ;
240
+ }
241
+
242
+ // Otherwise the tree AABB is huge and needs to be shrunk
217
243
}
218
244
245
+ this . removeLeaf ( node ) ;
246
+
247
+ node . aabb = fatAABB ;
248
+
219
249
this . insertLeaf ( node ) ;
220
250
251
+ node . moved = true ;
252
+
221
253
return true ;
222
254
}
223
255
@@ -285,6 +317,7 @@ export class DynamicTree<T> {
285
317
newParent . userData = null ;
286
318
newParent . aabb . combine ( leafAABB , sibling . aabb ) ;
287
319
newParent . height = sibling . height + 1 ;
320
+ newParent . moved = false ;
288
321
289
322
if ( oldParent != null ) {
290
323
// The sibling was not the root.
@@ -693,6 +726,7 @@ export class DynamicTree<T> {
693
726
parent . height = 1 + Math . max ( child1 . height , child2 . height ) ;
694
727
parent . aabb . combine ( child1 . aabb , child2 . aabb ) ;
695
728
parent . parent = null ;
729
+ parent . moved = false ;
696
730
697
731
child1 . parent = parent ;
698
732
child2 . parent = parent ;
0 commit comments