Three.js学习笔记(三):使用SelectionBox选中instanceMesh遇到的问题记录

公司之前有个绘制大量点和矢量的编辑平台是一个外包开发的,外包写的很粗糙,导致点线数据一朵卡顿频繁,fps骤降至3,因此决定用InstanceMesh改造一番。外包写的逻辑密密麻麻,可读性有些略差,在用InstanceMesh渲染物体时遇到了一个框选问题。记录一番。

以下是一个简单的SelectionBox实现案例

import * as THREE from 'three';
import { SelectionBox } from 'three/examples/jsm/interactive/SelectionBox.js';
import { SelectionHelper } from 'three/examples/jsm/interactive/SelectionHelper.js';

// 创建场景、相机、渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 添加多个立方体作为可选对象
const objects = [];
for (let i = 0; i < 10; i++) {
    const geometry = new THREE.BoxGeometry();
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    cube.position.set(Math.random() * 5, Math.random() * 5, Math.random() * 5);
    scene.add(cube);
    objects.push(cube);
}

// 创建 SelectionBox 和 SelectionHelper
const selectionBox = new SelectionBox(camera, scene);
const selectionHelper = new SelectionHelper(selectionBox, renderer, 'selectBox');

// 监听鼠标事件
document.addEventListener('pointerdown', (event) => {
    selectionBox.startPoint.set(
        (event.clientX / window.innerWidth) * 2 - 1,
        -(event.clientY / window.innerHeight) * 2 + 1,
        0.5
    );
}, false);

document.addEventListener('pointermove', (event) => {
    if (selectionHelper.isDown) {
        selectionBox.endPoint.set(
            (event.clientX / window.innerWidth) * 2 - 1,
            -(event.clientY / window.innerHeight) * 2 + 1,
            0.5
        );
        const allSelected = selectionBox.select();
        for (const obj of allSelected) {
            if (obj.material) obj.material.color.set(0xff0000); // 改变选中对象的颜色
        }
    }
});

document.addEventListener('pointerup', (event) => {
    if (selectionHelper.isDown) {
        selectionBox.endPoint.set(
            (event.clientX / window.innerWidth) * 2 - 1,
            -(event.clientY / window.innerHeight) * 2 + 1,
            0.5
        );
        const allSelected = selectionBox.select();
        for (const obj of objects) {
            if (obj.material) obj.material.color.set(0x00ff00); // 重置所有对象颜色
        }
        for (const obj of allSelected) {
            if (obj.material) obj.material.color.set(0xff0000); // 改变选中对象的颜色
        }
    }
    selectionHelper.isDown = false;
});

// 渲染循环
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}

animate();

在使用上面的方法去框选时会存在一个问题,执行select后选不中instanceMesh这是为什么呢?直接看源码。

在执行select的时候主要关注searchChildInFrustum,可以发现哈select方法返回的事collection而我们需要的instanceMesh在instances,这时候你可以将instances返回就可以拿到想要的instanceId了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值