• 作者:老汪软件技巧
  • 发表时间:2024-11-15 11:02
  • 浏览量:

定向包围盒(OBB,Oriented Bounding Box) 是一种三维包围盒,它与物体的旋转方向对齐,而不是像轴对齐包围盒(AABB)那样总是与坐标轴对齐。OBB 的优势在于它能够更紧密地包围物体,从而减少包围盒的空白区域。

OBB 通过 applyMatrix4 方法获取物体的边界信息以使用于包围盒计算

OBB 有三个属性十五个方法

OBB( center : Vector3, halfSize : Vector3, rotation : Matrix3 )
    center — OBB 的中心。(可选)
    halfSize — OBB 沿每个轴的正半宽范围。(可选)
    rotation — OBB 的旋转。(可选)
    创建一个新的 OBB。
    
    
    以下为代码示例
    
    // 创建 WebGL 渲染器,启用抗锯齿
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    // 设置渲染器的大小
    renderer.setSize( width, height );
    // 启用局部裁剪
    renderer.localClippingEnabled = true; 
    // 启用阴影
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 设置阴影类型为软阴影
    // 将渲染器的 DOM 元素添加到页面中
    DOMEl.appendChild( renderer.domElement );
    // 创建场景对象
    const scene = new THREE.Scene();
    // 设置清空背景色为黑色
    renderer.setClearColor(0x000000);
    // 创建透视相机
    const camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );
    // 设置相机位置
    camera.position.set( 0, 80, 0 );
    // 让相机指向场景的中心
    camera.lookAt( 0, 0, 0 );
    // 创建时钟对象用于计算每帧的时间差
    const clock = new THREE.Clock();
    // 存储物体的数组
    const objects  = [];
    // 存储鼠标坐标的向量
    const mouse = new THREE.Vector2();
    // 创建射线投射器
    const raycaster = new THREE.Raycaster();
    // 创建半球光源,模拟环境光
    const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x222222, 4 );
    hemiLight.position.set( 1, 1, 1 );
    // 将半球光源添加到场景中
    scene.add( hemiLight );
    // 创建盒子的尺寸
    const size = new THREE.Vector3( 10, 5, 6 );
    // 创建盒子几何体
    const geometry = new THREE.BoxGeometry( size.x, size.y, size.z );
    // 为几何体添加用户数据,存储 OBB 信息
    geometry.userData.obb = new OBB();
    geometry.userData.obb.halfSize.copy( size ).multiplyScalar( 0.5 );
    // 创建多个物体并添加到场景中
    for ( let i = 0; i < 100; i ++ ) {
        const object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x00ff00 } ) );
        object.matrixAutoUpdate = false;
        object.position.x = Math.random() * 80 - 40;
        object.position.y = Math.random() * 80 - 40;
        object.position.z = Math.random() * 80 - 40;
        object.rotation.x = Math.random() * 2 * Math.PI;
        object.rotation.y = Math.random() * 2 * Math.PI;
        object.rotation.z = Math.random() * 2 * Math.PI;
        object.scale.x = Math.random() + 0.5;
        object.scale.y = Math.random() + 0.5;
        object.scale.z = Math.random() + 0.5;
        scene.add( object );
        // 为物体添加 OBB 信息
        object.userData.obb = new OBB();
        objects.push( object );
    };
    // 创建一个可视化的碰撞框
    const hitbox = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true } ) );
    // 鼠标点击事件的回调函数
    function onClick( event ) {
        event.preventDefault();
        const rect = DOMEl.getBoundingClientRect();
        mouse.x = ((event.clientX - rect.left) / width) * 2 - 1;
        mouse.y = -((event.clientY - rect.top) / height) * 2 + 1;

_边界盒有什么用_边界盒怎么删除

// 根据鼠标坐标生成射线 raycaster.setFromCamera( mouse, camera ); const intersectionPoint = new THREE.Vector3(); const intersections = []; // 遍历所有物体,检测射线是否与物体的 OBB 相交 for ( let i = 0, il = objects.length; i < il; i ++ ) { const object = objects[ i ]; const obb = object.userData.obb; const ray = raycaster.ray; if ( obb.intersectRay( ray, intersectionPoint ) !== null ) { const distance = ray.origin.distanceTo( intersectionPoint ); intersections.push( { distance: distance, object: object } ); } }; console.log(intersections,"intersections") // 如果有相交的物体,将第一个相交物体添加碰撞框 if ( intersections.length > 0 ) { intersections.sort( sortIntersections ); intersections[ 0 ].object.add( hitbox ); } else { // 如果没有相交物体,从场景中移除碰撞框 const parent = hitbox.parent; if ( parent ) parent.remove( hitbox ); } } // 排序函数,按照距离升序排列 function sortIntersections( a, b ) { return a.distance - b.distance; } // 添加点击事件监听器 DOMEl.addEventListener( 'click', onClick ); // 创建 OrbitControls 实例,用于控制相机 const controls = new OrbitControls(camera, renderer.domElement); // 设置控制器的目标点 controls.target.set(0, 0, 0); // 将目标点设置为场景的中心 // 动画函数 function animate() { requestAnimationFrame(animate); controls.update(); // 更新 OrbitControls const delta = clock.getDelta(); // 更新每个物体的旋转 for ( let i = 0, il = objects.length; i < il; i ++ ) { const object = objects[ i ]; object.rotation.x += delta * Math.PI * 0.20; object.rotation.y += delta * Math.PI * 0.1; object.updateMatrix(); object.updateMatrixWorld(); // 更新物体的 OBB 信息 object.userData.obb.copy( object.geometry.userData.obb ); object.userData.obb.applyMatrix4( object.matrixWorld ); object.material.color.setHex( 0x00ff00 ); } // 检查物体之间的碰撞 for ( let i = 0, il = objects.length; i < il; i ++ ) { const object = objects[ i ]; const obb = object.userData.obb; for ( let j = i + 1, jl = objects.length; j < jl; j ++ ) { const objectToTest = objects[ j ]; const obbToTest = objectToTest.userData.obb; // 如果物体之间发生碰撞,改变它们的颜色 if ( obb.intersectsOBB( obbToTest ) === true ) { object.material.color.setHex( 0xff0000 ); objectToTest.material.color.setHex( 0xff0000 ); } } } // 渲染场景 renderer.render(scene, camera); } // 启动动画循环 animate();

属性

方法

总结

OBB(有序包围盒):用于提供物体的边界信息,尤其在物体有旋转、缩放和位置变换时,能够提供更精确的碰撞检测和空间计算。与几何体的关系:OBB 并不直接包含物体的几何体,它依赖物体的几何尺寸和形状来创建一个包围盒(bounding box)。这个包围盒会根据物体的变换(位置、旋转、缩放)进行更新。如何更新边界信息OBB 的作用:OBB 是为物体提供一个精确的边界框,帮助进行碰撞检测、光线交集等空间计算,而不需要直接操作物体的几何体。

关键点:- OBB 使用矩阵更新边界信息,确保包围盒随着物体的变换而更新。- OBB 不需要直接包含几何体,而是通过物体的几何尺寸、位置、旋转等信息来计算包围盒。


上一条查看详情 +【前端学算法】搜索算法详解
下一条 查看详情 +没有了