Vous ne pouvez pas utiliser Physijs pour la détection de collision seule. Il vient tout juste équipé de la simulation physique en temps réel, basée sur la bibliothèque ammo.js. Lorsque vous définissez la masse des mailles sur 0
, cela les rend statiques. Ils étaient alors insensibles aux forces externes, telles que les réponses de collision (c'est-à-dire le changement de vitesse appliqué sur le maillage après la détection de la collision) ou la gravité. De même, deux maillages statiques qui se chevauchent l'un l'autre ne déclenchent pas un événement de collision.
Solution A: Utilisation de directement
Ported de Bullet Physics, la bibliothèque fournit les outils nécessaires pour générer des simulations de physique ou de détecter simplement des collisions entre des formes définies (qui Physijs ne veut pas voir). Voici un extrait de détection de collision entre 2 sphères rigides:
var bt_collision_configuration;
var bt_dispatcher;
var bt_broadphase;
var bt_collision_world;
var scene_size = 500;
var max_objects = 10; // Tweak this as needed
bt_collision_configuration = new Ammo.btDefaultCollisionConfiguration();
bt_dispatcher = new Ammo.btCollisionDispatcher(bt_collision_configuration);
var wmin = new Ammo.btVector3(-scene_size, -scene_size, -scene_size);
var wmax = new Ammo.btVector3(scene_size, scene_size, scene_size);
// This is one type of broadphase, Ammo.js has others that might be faster
bt_broadphase = new Ammo.bt32BitAxisSweep3(
wmin, wmax, max_objects, 0, true /* disable raycast accelerator */);
bt_collision_world = new Ammo.btCollisionWorld(bt_dispatcher, bt_broadphase, bt_collision_configuration);
// Create two collision objects
var sphere_A = new Ammo.btCollisionObject();
var sphere_B = new Ammo.btCollisionObject();
// Move each to a specific location
sphere_A.getWorldTransform().setOrigin(new Ammo.btVector3(2, 1.5, 0));
sphere_B.getWorldTransform().setOrigin(new Ammo.btVector3(2, 0, 0));
// Create the sphere shape with a radius of 1
var sphere_shape = new Ammo.btSphereShape(1);
// Set the shape of each collision object
sphere_A.setCollisionShape(sphere_shape);
sphere_B.setCollisionShape(sphere_shape);
// Add the collision objects to our collision world
bt_collision_world.addCollisionObject(sphere_A);
bt_collision_world.addCollisionObject(sphere_B);
// Perform collision detection
bt_collision_world.performDiscreteCollisionDetection();
var numManifolds = bt_collision_world.getDispatcher().getNumManifolds();
// For each contact manifold
for(var i = 0; i < numManifolds; i++){
var contactManifold = bt_collision_world.getDispatcher().getManifoldByIndexInternal(i);
var obA = contactManifold.getBody0();
var obB = contactManifold.getBody1();
contactManifold.refreshContactPoints(obA.getWorldTransform(), obB.getWorldTransform());
var numContacts = contactManifold.getNumContacts();
// For each contact point in that manifold
for(var j = 0; j < numContacts; j++){
// Get the contact information
var pt = contactManifold.getContactPoint(j);
var ptA = pt.getPositionWorldOnA();
var ptB = pt.getPositionWorldOnB();
var ptdist = pt.getDistance();
// Do whatever else you need with the information...
}
}
// Oh yeah! Ammo.js wants us to deallocate
// the objects with 'Ammo.destroy(obj)'
I transformé this C++ code en son équivalent JS. Il se peut qu'il y ait eu une syntaxe manquante, donc vous pouvez vérifier le Ammo.js API binding changes pour tout ce qui ne fonctionne pas.
Solution B: Utilisez le lanceur de sorts de rayons de TROIS
Le lanceur de rayons est moins précis, mais peut être plus précis avec l'ajout de nombre de vertex supplémentaire dans vos formes. Voici un code pour détecter une collision entre 2 boîtes:
// General box mesh data
var boxGeometry = new THREE.CubeGeometry(100, 100, 20, 1, 1, 1);
var boxMaterial = new THREE.MeshBasicMaterial({color: 0x8888ff, wireframe: true});
// Create box that detects collision
var dcube = new THREE.Mesh(boxGeometry, boxMaterial);
// Create box to check collision with
var ocube = new THREE.Mesh(boxGeometry, boxMaterial);
// Create ray caster
var rcaster = new THREE.Raycaster(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 1, 0));
// Cast a ray through every vertex or extremity
for(var vi = 0, l = dcube.geometry.vertices.length; vi < l; vi++){
var glovert = dcube.geometry.vertices[vi].clone().applyMatrix4(dcube.matrix);
var dirv = glovert.sub(dcube.position);
// Setup ray caster
rcaster.set(dcubeOrigin, dirv.clone().normalize());
// Get collision result
var hitResult = rcaster.intersectObject(ocube);
// Check if collision is within range of other cube
if(hitResult.length && hitResult[0].distance < dirv.length()){
// There was a hit detected between dcube and ocube
}
}
Découvrez ces liens pour plus d'informations (et peut-être leur code source):
quelle excellente réponse! j'aime avec la solution de munitions. Je vais essayer sur un maillage concave et voir comment il fonctionne. – lpic
la solution de munitions fonctionne très bien pour les maillages concaves ... merci encore – lpic
@ XavCo7, s'il vous plaît jeter un oeil à https: // stackoverflow.com/questions/46423290/glisser-un-maillage sur un autre-et-limiter-il-dans-les-côtés-trois-js, j'ai expliqué l'exigence. Je dois faire glisser une fenêtre sur le mur dans les limites du mur. J'ai créé l'ensemble de l'application dans trois.js. Will Physijs travaillera pour la tâche? – Deeps