之前用ammojs写了一点点动画:微信小程序体验3D物理引擎-ammo.js,把碰撞检测的代码写一下,Mark下,记个笔记:
碰撞检测
function updatePhysics(deltaTime) {
physicsWorld.stepSimulation(deltaTime);
//physicsWorld.performDiscreteCollisionDetection();
var numManifolds=dispatcher.getNumManifolds();
for(var i=0; i<numManifolds; i++){
var contactManifold=dispatcher.getManifoldByIndexInternal(i);
var objA=contactManifold.getBody0();
var objB=contactManifold.getBody1();
var numContacts = contactManifold.getNumContacts();
//console.log(numContacts,objA,objB);
for(var j=0; j<numContacts; j++)
{
var pt = contactManifold.getContactPoint(j);
if(pt.getDistance()<=0.0){
var posA = pt.getPositionWorldOnA();
var posB = pt.getPositionWorldOnB();
console.log("A:",i, posA.x(), posA.y(), posA.z()); // 碰撞点
console.log("B:",i, posB.x(), posB.y(), posB.z());
}
}
}
// 更新物体位置
for (var i = 0, iL = rigidBodies.length; i <iL; i++ ){
var objThree = rigidBodies[i];
var objPhys = objThree.userData.physicsBody;
var ms = objPhys.getMotionState();
if (ms) {
ms.getWorldTransform(transformAux1);
var p = transformAux1.getOrigin();
var q = transformAux1.getRotation();
objThree.position.set(p.x(), p.y(), p.z());
objThree.quaternion.set(q.x(), q.y(), q.z(), q.w());
}
}
}
创建TriangleMesh的Shape:
function createTriangleShapeByGeometry(geometry) {
var mesh = new Ammo.btTriangleMesh(true, true);
var vertices = geometry.vertices;
for (var i = 0; i < geometry.faces.length; i++) {
var face = geometry.faces[i];
if (face instanceof THREE.Face3) {
mesh.addTriangle(
new Ammo.btVector3(vertices[face.a].x, vertices[face.a].y, vertices[face.a].z),
new Ammo.btVector3(vertices[face.b].x, vertices[face.b].y, vertices[face.b].z),
new Ammo.btVector3(vertices[face.c].x, vertices[face.c].y, vertices[face.c].z),
false
);
} else if (face instanceof THREE.Face4) {
mesh.addTriangle(
new Ammo.btVector3(vertices[face.a].x, vertices[face.a].y, vertices[face.a].z),
new Ammo.btVector3(vertices[face.b].x, vertices[face.b].y, vertices[face.b].z),
new Ammo.btVector3(vertices[face.d].x, vertices[face.d].y, vertices[face.d].z),
false
);
mesh.addTriangle(
new Ammo.btVector3(vertices[face.b].x, vertices[face.b].y, vertices[face.b].z),
new Ammo.btVector3(vertices[face.c].x, vertices[face.c].y, vertices[face.c].z),
new Ammo.btVector3(vertices[face.d].x, vertices[face.d].y, vertices[face.d].z),
false
);
}
}
var shape = new Ammo.btBvhTriangleMeshShape(mesh, true, true);
return shape;
}
例如创建一条管道的Shape:
var ballMass = 35;
var ballRadius = 0.4;
var path = new CustomSinCurve( 1.0 );
var geometry = new THREE.TubeGeometry( path, 20, 0.2, 8, false );
//var geometry=new THREE.SphereGeometry( ballRadius, 14, 10 );
var ball = new THREE.Mesh( geometry, ballMaterial );
ball.castShadow = true;
ball.receiveShadow = true;
var ballShape = createTriangleShapeByGeometry(geometry);//new Ammo.btSphereShape( ballRadius );
ballShape.setMargin( margin );
var pos = new THREE.Vector3();
var quat = new THREE.Quaternion();
pos.copy( raycaster.ray.direction );
pos.add( raycaster.ray.origin );
quat.set( 0, 0, 0, 1 );
var ballBody = createRigidBody( ball, ballShape, ballMass, pos, quat );
pos.copy( raycaster.ray.direction );
pos.multiplyScalar( 24 );
ballBody.setLinearVelocity( new Ammo.btVector3( pos.x, pos.y, pos.z ) );
管道Factory代码:
function CustomSinCurve( scale ) {
THREE.Curve.call( this );
this.scale = ( scale === undefined ) ? 1 : scale;
}
CustomSinCurve.prototype = Object.create( THREE.Curve.prototype );
CustomSinCurve.prototype.constructor = CustomSinCurve;
CustomSinCurve.prototype.getPoint = function ( t ) {
var tx = t * 3 - 1.5;
var ty = Math.sin( 2 * Math.PI * t );
var tz = 0;
return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
};
Demo:
点击体验3D物理引擎bullet的javascript版本。源码参考了:https://github.com/THISISAGOODNAME/learn-ammojs,感谢原作者!
(正文完!)