有偿,针对 threejs的raycaster进行获取当前 mesh 选中

发布于 2024-08-16 18:08:31

image.png
以上为当前 scene 渲染模型
针对红点想选中/通过鼠标来移动到制定位置
但是在编写过程中,这边使用raycaster来进行模型选中,但并不好使,恳请有经验的大佬得以指点一二


 // 创建一个小球体作为点[多个点]
let raycasterObjects = [];

let point = new THREE.Vector3(-20.79461170700156, -31.34449501478036, 10.72384259079748);
            const geometry = new THREE.SphereGeometry(1, 16, 16);
            const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
            const sphere = new THREE.Mesh(geometry, material);
            sphere.name = "sphere";

            // 设置小球的位置为交点的位置
            sphere.position.copy(point);
            scene.add(sphere)
            raycasterObjects.push(sphere);
//以下是创建鼠标按键事件
let pointer = new THREE.Vector2();
let raycaster = new THREE.Raycaster();

onPointerDown(event) {
    const _this = this;
    pointer.x = (event.clientX / window.innerWidth) * 2 - 1
    pointer.y = -(event.clientY / window.innerHeight) * 2 + 1

    // 使用Raycaster检测是否点击到了可拖拽的点
    raycaster.setFromCamera(pointer, camera);
    const intersects = raycaster.intersectObjects(raycasterObjects, false);
    console.log(`output->intersects`, intersects)

    if (intersects.length > 0) {
        let selectedObject = intersects[0].object; // 选择的对象
        console.log(`output->selectedObject`, selectedObject)
    }
}

具体实现思路
1.通过鼠标按下得到当前选中模型
2.通过鼠标抬起事件,获取当前鼠标的相对坐标[x,y,z] 来进行坐标给当前模型
3.移动模型

备注:也可以承接出去,最好自带报价,感谢感谢

查看更多

关注者
0
被浏览
658
1 个回答
weilaijiezou
weilaijiezou 2024-08-16
这家伙很懒,什么也没写!

因为是片段代码,所以我只能说问题的原因,需要把click点击事件和mousemove分开写,处理逻辑写在click事件中。

示例代码:

<script setup>
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { onMounted, ref } from 'vue'

/**
   * scene
  */
const scene = new THREE.Scene()

/**
 * camera
*/
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    100
)
camera.position.z = 3

/**
 * object
*/
const object1 = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 16, 16),
    new THREE.MeshBasicMaterial({ color: '#ff0000' })
)
object1.position.x = - 2

const object2 = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 16, 16),
    new THREE.MeshBasicMaterial({ color: '#ff0000' })
)

const object3 = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 16, 16),
    new THREE.MeshBasicMaterial({ color: '#ff0000' })
)
object3.position.x = 2

scene.add(object1, object2, object3)


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

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix

    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})

/**
 * axesHelper
*/
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)

/**
 * control
*/
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

/**
* raycaster
*/
const raycaster = new THREE.Raycaster()

/**
 * mouse
*/
const mouse = new THREE.Vector2(1, 1)

window.addEventListener('mousemove', (event) => {
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    mouse.y = - (event.clientY / window.innerHeight) * 2 + 1
})

/**
 * render
*/
const clock = new THREE.Clock()

let currentIntersect = null
const tick = () => {
    const elapsedTime = clock.getElapsedTime()
    const objectsToTest = [object1, object2, object3]
    const intersects = raycaster.intersectObjects(objectsToTest)
    raycaster.setFromCamera(mouse, camera)  // 根据camera的位置设置方向

    if (intersects.length > 0) {
        // console.log('enter');
        currentIntersect = intersects[0]
    } else {
        // console.log('leave');
        currentIntersect = null
    }
    for (const object of objectsToTest) {
        object.material.color.set(0xff0000)
    }
    for (const intersect of intersects) {
        intersect.object.material.color.set('#0000ff')
    }

    // update
    controls.update()
    requestAnimationFrame(tick)
    renderer.render(scene, camera)
}

document.addEventListener('click', () => {
    if (currentIntersect) {
        switch (currentIntersect.object) {
            case object1:
                console.log('click obj1');
                break
            case object2:
                console.log('click obj2');
                break
            case object3:
                console.log('click obj3');
                break
        }
    }
})

onMounted(() => {
    tick()
})

</script>

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览