如视 Five SDK
    Preparing search index...

    Raycast (射线检测)

    • Summary: Five 提供了增强版的射线检测机制,内置 BVH 加速,并扩展了 Three.js Raycaster 以支持更灵活的过滤和性能优化。
    • Schema: 参见下方 Three.js Raycaster Extensions
    • Concepts: BVH, IntersectRaycaster, Raycaster Extensions。
    • Examples: 提供基础检测与性能优化示例。

    Definition: Raycaster

    Five 对 Three.js 的 Raycaster 进行了扩展,在 declare module 'three' 中增加了以下属性:

    // defined in five/declare.d.ts
    declare module 'three' {
    export interface Raycaster {
    /**
    * 只捕获第一个焦点 (性能优化)
    * - true: 找到第一个交点后立即停止检测,返回结果。
    * - false (默认): 检测所有可能的交点。
    */
    firstHitOnly?: boolean;

    /**
    * 自定义交点过滤器
    * - 回调函数,返回 boolean。
    * - true: 保留该交点。
    * - false: 丢弃该交点。
    */
    hitFilter?: (intersect: THREE.Intersection) => boolean;

    /**
    * 是否由近及远排序
    * - true (默认): 返回的结果数组按距离摄像机从近到远排序。
    * - false: 结果顺序不确定(通常按遍历顺序)。
    */
    sortByDistance?: boolean;

    /**
    * 作用楼层 (Five 特有逻辑)
    * - 用于多楼层场景过滤。
    */
    floorIndex?: number;
    }

    export interface Intersection {
    /** 命中的具体 Tile 对象 (仅 3DTiles) */
    tile?: Tile;
    /** 命中的 ViewLayer 对象 */
    viewLayer?: ViewLayer;
    /** 命中的 Model 对象 */
    model?: Model;
    }
    }

    Five 内置了一套高效的 BVH 实现,用于优化 MeshPoints 的射线检测。

    • 作用: 在进行射线检测时,不直接遍历所有三角形或点,而是先与构建好的 BVH 树(包围盒层次结构)进行相交测试。只有当射线穿过包围盒时,才进一步检测内部的几何体。
    • 优势: 极大提升了复杂模型(如数十万面的 Mesh 或百万级 Points)的碰撞检测性能。
    • 透明性: 开发者通常无需手动操作 BVH,Five 在加载模型时会自动构建,并在调用 intersectRaycaster 时自动应用。

    Five 提供了 model.intersectRaycaster 方法,与 Three.js 原生的 raycaster.intersectObject 有显著区别:

    特性 five.model.intersectRaycaster raycaster.intersectObject (Three.js 原生)
    检测范围 聚合检测 five.model.shownModels 中所有可见模型。 仅检测指定的单个 Object3D 及其子节点。
    结果排序 自动合并所有模型的检测结果,并根据 raycaster.sortByDistance 排序。 仅对当前 Object 及其子节点的结果排序。
    扩展支持 支持 firstHitOnly, hitFilter, sortByDistance 等扩展属性。 不支持 Five 的扩展属性(需手动实现)。
    内部优化 自动调用模型内部的优化逻辑(如 BVH, Tile3D 的空间索引)。 仅进行标准的场景图遍历检测。
    使用场景 推荐。适用于全局点击、地板检测、物体拾取等业务场景。 仅在需要检测特定原生 Object3D 时使用。

    最常见的场景是将鼠标点击的屏幕坐标转换为 3D 空间中的点。

    import * as THREE from 'three';
    import { Five } from '@realsee/five';

    const five = new Five();
    // ... 初始化 ...

    const raycaster = new THREE.Raycaster();
    const vector = new THREE.Vector2();

    // 假设 onTap 是点击事件处理函数
    function onTap(event: { x: number, y: number }) {
    // 1. 将屏幕坐标转换为归一化设备坐标 (NDC)
    // 注意:five.getElement() 获取 canvas 容器
    const element = five.getElement();
    if (!element) return;

    const rect = element.getBoundingClientRect();
    vector.x = ((event.x - rect.left) / rect.width) * 2 - 1;
    vector.y = -((event.y - rect.top) / rect.height) * 2 + 1;

    // 2. 设置射线
    raycaster.setFromCamera(vector, five.camera);

    // 3. 调用 Five 的检测方法
    const intersects = five.model.intersectRaycaster(raycaster);

    if (intersects.length > 0) {
    const firstHit = intersects[0];
    console.log('点击到了模型:', firstHit.object);
    console.log('交点坐标 (世界坐标):', firstHit.point);
    }
    }

    在进行如“地面检测”或“视线遮挡检测”时,通常只需要知道最近的交点。此时开启 firstHitOnly 可以显著提升性能。

    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouseVector, five.camera);

    // 开启性能优化:找到最近的一个交点后立即停止
    raycaster.firstHitOnly = true;

    // 结果数组长度最多为 1
    const intersects = five.model.intersectRaycaster(raycaster);

    if (intersects.length > 0) {
    // 处理最近的交点
    }

    如果你只想检测特定类型的物体(例如只检测地板,忽略天花板),可以使用 hitFilter

    raycaster.hitFilter = (intersect) => {
    // 示例:假设地板的法线是向上的 (0, 1, 0)
    // 只保留法线朝上的交点(地板)
    if (intersect.face && intersect.face.normal.y > 0.5) {
    return true; // 保留
    }
    return false; // 丢弃
    };

    const intersects = five.model.intersectRaycaster(raycaster);
    • 验证交点: 在开发阶段,可以在交点处添加一个临时的红色小球 THREE.Mesh,直观地确认检测位置是否正确。
    • 检查模型可见性: intersectRaycaster 只会检测 visible = true 的模型。如果检测不到,请检查模型的可见性状态。
    • Performance: 如果射线检测导致掉帧,检查是否频繁调用了全场景检测。尝试使用 firstHitOnly 或减小检测频率(如节流)。
    1. 混淆 API: 错误地使用 raycaster.intersectObject(five.scene)。虽然这也能工作,但会失去 Five 的 BVH 优化和多模型聚合能力,导致性能下降或漏检。请始终优先使用 five.model.intersectRaycaster(raycaster)
    2. 忽略坐标系: raycaster.setFromCamera 需要 NDC 坐标(-1 到 1),而不是像素坐标。务必进行正确的坐标转换。
    3. Tile3D 模型的特殊性: 对于大型 Tile3D 场景,射线检测可能涉及动态加载的瓦片。Five 内部已处理这些逻辑,外部调用方式不变,但返回的 object 可能是某个具体的 Tile 节点。
    • Parameter: 了解模型参数配置。
    • Screen Project: 屏幕坐标与空间坐标转换(标签、拾取的前置步骤)。
    • Event: 手势事件系统,获取点击坐标的来源。
    • Coordinate System: 坐标系定义,理解 NDC 与世界坐标。

    tags: [点击, 拾取, 碰撞检测, 物体选择, raycast, bvh, interaction, performance, picking, hit-test, click, floor-detection]