After spending some time debugging, I was able to discover the root of the issue. The story behind it is quite intriguing, so brace yourself...
When looking into the Sphere
constructor (r152 source code), I found that it expects a Vector3
for the center position and a Number
for the radius of the sphere being defined. The interesting part is that the center Vector3
is not duplicated into the Sphere.center
, but rather simply assigned to the property. This means that Sphere.center
will now refer back to the original Vector3
passed to it.
But hold on, there's more to it!
In the world of three.js
, making changes to Mesh.position
will not immediately update the matrixWorld
unless you explicitly do so with Object3D.updatematrixWorld()
or a call to render
. Hence, until this update occurs, ball.matrixWorld
will retain the matrix from the previous update.
Unraveling the chain of events...
- You set
ball.position
(which technically also updates ballbb.center
!)
- You render the scene (which automatically triggers
Object3D.updateMatrixWorld()
)
- You modify
ball.position
(no automatic update to ball.matrixWorld
)
- You copy the geometry's bsphere (identity position) into
ballbb
- You apply
ball.matrixWorld
to ballbb
(this involves multiplying it against ballbb.center
)
- Go back to step 1 and repeat
Evaluating the situation
Step 4 is where things start going awry. When you copy the identity bounding sphere into ballbb
, you essentially undo the update made in Step 1, not only for ballbb
but also for
ball</code! By copying the identity, you reset <code>ballbb.center
(and consequently,
ball.position
) to
(0, 0, 0)
. Subsequently applying the
ball.MatrixWorld
results in applying the transformation from the previous frame since there hasn't been a
render
or an
updateMatrixWorld
since
Step 2, hence the ball appears motionless.
How can this be resolved?
You could potentially rearrange your logic to ensure that updating ball.position
or ballbb.center
is both applied and propagated correctly. However, I managed to resolve it by making a single adjustment:
var ballbb = new THREE.Sphere(ball.position.clone(), 70)
Take note of the call to Vector3.clone()
. This ensures that the Vector3
provided to the Sphere
is a duplicate of
ball.position</code, ensuring that updates to one will not affect the other.</p>
<h3>A more effective solution...</h3>
<p>Ultimately, the ideal approach would be to simplify your code and refrain from performing any unnecessary calculations. When creating your <code>Sphere
, do provide it with
ball.position
, and then leave it at that. As you update
ball.position
, it will also update
ballbb.center
. Given that a
Sphere
lacks a
matrixWorld
, all computations are based on the
center
and
radius
values, resulting in the sphere "automatically" following
ball
.