Reputation: 141
I am working on 3D AABB collisions detection for box and sphere.
If box is directly added to scene then collision is detected but if its added in a group (THREE.Group) and rotated, then collision is not detected.
This is the code to add box
function addPlatforms() {
var coreGroup = new THREE.Group(); // this is the group
scene.add(coreGroup);
var box = [];
cube_box1 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
box.push(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid));
box[0].position.set(-1.83, -0.22, 1.11);
box[0].rotation.x += Math.PI / 2;
box[0].rotation.z -= 0.78;
box[0].receiveShadow = true;
cube_box2 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
box.push(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid));
box[1].position.set(-2.15, -0.22, 0.51);
box[1].rotation.x += Math.PI / 2;
box[1].receiveShadow = true;
var platGroup = new THREE.Group();
platGroup.add(box[0]);
platGroup.add(box[1]);
platGroup.rotation.y -= 2;
platGroup.position.y = 1;
coreGroup.add(platGroup);
cube_box1.setFromObject(box[0]);
platformArr.push(cube_box1);
cube_box2.setFromObject(box[1]);
platformArr.push(cube_box2);
}
Code to get Collision between box and sphere.
THREE.Sphere.__closest = new THREE.Vector3();
THREE.Sphere.prototype.intersectsBox = function(box) {
// get box closest point to sphere center by clamping
THREE.Sphere.__closest.set(this.center.x, this.center.y, this.center.z);
THREE.Sphere.__closest.clamp(box.min, box.max);
var distance = this.center.distanceToSquared(THREE.Sphere.__closest);
return distance < (this.radius * this.radius);
};
function isCollision() {
for (var i = 0; i < platformArr.length; i++) {
_cubeBox = platformArr[i];
return sphereBox.intersectsBox(_cubeBox);
}
}
This is how sphere is added
function addBall(){
sphere = new THREE.Mesh(
new THREE.SphereGeometry(0.19, 20, 20), materials.solid);
sphere.position.set(0, 1, -2);
sphere.geometry.computeBoundingSphere();
scene.add(sphere);
sphereBox = new THREE.Sphere(sphere.position, sphere.geometry.boundingSphere.radius);
sphereBox.radius = sphere.geometry.boundingSphere.radius;
cy = sphere.position.y;
}
Logic to render
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
if (collision) { // ball is on surface
vy = -vy;
collision = false;
}
cy -= vy * dt;
sphere.position.y = cy;
if (vy <= mvy)
vy += gravity;
collision = isCollision();
}
If a box is added to scene and collision is detected with sphere then its working. Ex - Create a simple box and change some properties like rotation and position
var _box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid);
_box.position.set(-1.83, -0.22, 1.11);
_box.rotation.x += Math.PI / 2;
_box.rotation.z -= 0.78;
_box.receiveShadow = true;
Then find the collision in animate update
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
if (collision) { // ball is on surface
vy = -vy;
collision = false;
}
cy -= vy * dt;
sphere.position.y = cy;
if (vy <= mvy)
vy += gravity;
collision = sphereBox.intersectsBox(_box);
}
Upvotes: 0
Views: 1149
Reputation: 2237
By default, the object's world matrix will be updated every frame. You are instantiating these boxes, transforming, and adding them to the group. Then you instantly call cube_box1.setFromObject(box[0]);
, which uses matrixWorld
internally. But the world matrices of the boxes are not set yet. You can wait a frame to let the matrices to be computed automatically, or you have to trigger matrix updates manually:
//... your code ...
coreGroup.add(platGroup);
coreGroup.updateMatrixWorld( true );
cube_box1.setFromObject(box[0]);
platformArr.push(cube_box1);
//... your code ...
Three.js Docs Matrix Transformations
When either the parent or the child object's transformation changes, you can request that the child object's
matrixWorld
be updated by callingupdateMatrixWorld()
.
.matrixAutoUpdate : Boolean
When this is set, it calculates the matrix of position, (rotation or quaternion) and scale every frame and also recalculates the matrixWorld property. Default is
Object3D.DefaultMatrixAutoUpdate
(true).
Upvotes: 1