@@ -47,6 +47,8 @@ export class TreeNode<T> {
4747 /** 0: leaf, -1: free node */
4848 height : number = - 1 ;
4949
50+ moved : boolean = false ;
51+
5052 constructor ( id ?: number ) {
5153 this . id = id ;
5254 }
@@ -110,6 +112,18 @@ export class DynamicTree<T> {
110112 return node . userData ;
111113 }
112114
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+
113127 /**
114128 * Get the fat AABB for a node id.
115129 *
@@ -152,6 +166,7 @@ export class DynamicTree<T> {
152166
153167 node . userData = userData ;
154168 node . height = 0 ;
169+ node . moved = true ;
155170
156171 this . insertLeaf ( node ) ;
157172
@@ -176,48 +191,65 @@ export class DynamicTree<T> {
176191 * fattened AABB, then the proxy is removed from the tree and re-inserted.
177192 * Otherwise the function returns immediately.
178193 *
179- * @param d Displacement
194+ * @param displacement Displacement
180195 *
181196 * @return true if the proxy was re-inserted.
182197 */
183- moveProxy ( id : number , aabb : AABB , d : Vec2Value ) : boolean {
198+ moveProxy ( id : number , aabb : AABB , displacement : Vec2Value ) : boolean {
184199 _ASSERT && console . assert ( AABB . isValid ( aabb ) ) ;
185- _ASSERT && console . assert ( ! d || Vec2 . isValid ( d ) ) ;
200+ _ASSERT && console . assert ( ! displacement || Vec2 . isValid ( displacement ) ) ;
186201
187202 const node = this . m_nodes [ id ] ;
188203
189204 _ASSERT && console . assert ( ! ! node ) ;
190205 _ASSERT && console . assert ( node . isLeaf ( ) ) ;
191206
192- if ( node . aabb . contains ( aabb ) ) {
193- return false ;
194- }
195-
196- this . removeLeaf ( node ) ;
197-
198- node . aabb . set ( aabb ) ;
199-
200207 // 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 ) ;
203211
204- // Predict AABB displacement.
212+ // Predict AABB movement
205213 // const d = Vec2.mul(Settings.aabbMultiplier, displacement);
206214
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 ;
209217 } else {
210- aabb . upperBound . x += d . x * Settings . aabbMultiplier ;
218+ fatAABB . upperBound . x += displacement . x * Settings . aabbMultiplier ;
211219 }
212220
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 ;
215223 } 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
217243 }
218244
245+ this . removeLeaf ( node ) ;
246+
247+ node . aabb = fatAABB ;
248+
219249 this . insertLeaf ( node ) ;
220250
251+ node . moved = true ;
252+
221253 return true ;
222254 }
223255
@@ -285,6 +317,7 @@ export class DynamicTree<T> {
285317 newParent . userData = null ;
286318 newParent . aabb . combine ( leafAABB , sibling . aabb ) ;
287319 newParent . height = sibling . height + 1 ;
320+ newParent . moved = false ;
288321
289322 if ( oldParent != null ) {
290323 // The sibling was not the root.
@@ -693,6 +726,7 @@ export class DynamicTree<T> {
693726 parent . height = 1 + Math . max ( child1 . height , child2 . height ) ;
694727 parent . aabb . combine ( child1 . aabb , child2 . aabb ) ;
695728 parent . parent = null ;
729+ parent . moved = false ;
696730
697731 child1 . parent = parent ;
698732 child2 . parent = parent ;
0 commit comments