如何在Three.js中结合DragControls实现物体碰撞检测与阻挡
Three.js 拖拽碰撞检测问题
描述
我正在尝试实现两个物体的碰撞效果,通过计算它们的Box3(包围盒),再使用.intersectsBox()方法返回布尔值,以此判断物体是否接触/相交。
由于使用了DragControls,物理引擎无法正常工作(DragControls不会更新刚体位置),期望实现拖拽物体时,遇到另一个物体无法穿透,停在碰撞前的安全位置。
示例代码
以下代码中,obj1和obj2均为BoxGeometry网格,当两者相交时,.intersectsBox()会返回布尔值true。
const obj1 = new THREE.Mesh(new THREE.BoxGeometry(1,1,1), new THREE.MeshBasicMaterial()); const obj2 = new THREE.Mesh(new THREE.BoxGeometry(2,5,2), new THREE.MeshBasicMaterial()); const obj1Box = new THREE.Box3().setFromObject(obj1); const obj2Box = new THREE.Box3().setFromObject(obj2); box1.intersectsBox(obj2);
已尝试方案
尝试保存obj1的上一位置,当检测到相交时将其位置重置为未碰撞的上一位置,但该逻辑未能正常运行。
需求
提供相关的Codesandbox示例,若能给出React Three的实现方案更佳,原生Three.js方案也可接受。
当前代码
import * as THREE from "three"; import { DragControls } from "three/addons/controls/DragControls.js"; import { OrbitControls } from "three/addons/controls/OrbitControls.js"; let renderer, scene, camera, dragcontrols, controls; let objects, boxMesh1, boxMesh2; function init() { const bgColor = 0x263238; renderer = new THREE.WebGLRenderer({ antialias: false }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(bgColor, 1); renderer.outputColorSpace = THREE.SRGBColorSpace; document.body.appendChild(renderer.domElement); scene = new THREE.Scene(); scene.fog = new THREE.Fog(0x263238, 20, 60); camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.far = 100; camera.updateProjectionMatrix(); camera.position.set(1, 1, -5); controls = new OrbitControls(camera, renderer.domElement); boxMesh1 = new THREE.Mesh( new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0x00ff00 }) ); scene.add(boxMesh1); boxMesh2 = new THREE.Mesh( new THREE.BoxGeometry(2, 5, 2), new THREE.MeshBasicMaterial({ color: 0xff0000 }) ); boxMesh2.position.set(2,2,0); scene.add(boxMesh2); dragcontrols = new DragControls([boxMesh1], camera, renderer.domElement); let lastSafePosition = boxMesh1.position.clone(); dragcontrols.addEventListener("dragstart", (event) => { controls.enabled = false; lastSafePosition.copy(event.object.position); }); dragcontrols.addEventListener("dragend", () => { controls.enabled = true; console.log(controls.enabled); }); dragcontrols.addEventListener('drag', () => { boxMesh1.position.y = 0; const box1Mesh = event.object; // The mesh being dragged const box1BoundingBox = new THREE.Box3().setFromObject(box1Mesh); const box2BoundingBox = new THREE.Box3().setFromObject(boxMesh2); if (box1BoundingBox.intersectsBox(box2BoundingBox)) { box1Mesh.position.copy(lastSafePosition); } else { lastSafePosition.copy(box1Mesh.position); } }) const metreSize = 10.0; const metreDivisions = 40.0; const decimetreSize = 10.0; const decimetreDivisions = 400.0; const gridHelper = new THREE.GridHelper( metreSize, metreDivisions, 0x8fc8df, 0x8fc8df ); scene.add(gridHelper); const gridHelper2 = new THREE.GridHelper( decimetreSize, decimetreDivisions, 0xd7eef5, 0xd7eef5 ); scene.add(gridHelper2); gridHelper.position.set(0,-0.5,0) gridHelper2.position.set(0,-0.5,0) } function render() { requestAnimationFrame(render); controls.update(); renderer.render(scene, camera); } init(); render();
内容的提问来源于stack exchange,提问作者AshhadDevLab
相关产品推荐
相关产品推荐

