개발/three.js / / 2022. 10. 11. 14:44

three.js Raycaster로 물체 감지하기

반응형
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

...

// Controls
const controls = new OrbitControls(camera, renderer.domElement);

// Mesh
const lineMeterial = new THREE.LineBasicMaterial({ color: 'yellow' });
const points = [];
points.push(new THREE.Vector3(0, 0, 100));
points.push(new THREE.Vector3(0, 0, -100));
const lineGeometry = new THREE.BufferGeometry().setFromPoints(points); 
const guide = new THREE.Line(lineGeometry, lineMaterial);
scene.add(guide);

const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const boxMaterial = new THREE.MeshStandardMaterial({ color: 'plum' });
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
boxMesh.name = 'box';

const torusGeometry = new THREE.TorusGeometry(2, 0.5, 16, 100);
const torusMaterial = new THREE.MeshStandardMaterial({ color: 'lime' });
const torusMesh	= new THREE.Mesh(torusGeometry, torusMaterial);
torusMesh.name = 'torus';

scene.add(boxMesh, torusMesh);

points 배열에 있는 point들의 위치를 기반으로 buffer geometry가 생성된다. 위 코드에서는 point 두 개를 배열에 넣어 geometry를 그렸으므로 선이 그려진다.

그려진 선과 line material을 통해 guide line을 그린다.

 

각종 mesh를 통해 선이 도형을 뚫고 나가는 것을 볼 수 있다.

 

이제 raycaster를 넣어보자

const meshes = [boxMesh, torusMesh];
const raycaster = new THREE.Raycaster();

function draw() {
    const delta = clock.getDelta();

    const origin = new THREE.Vector3(0, 0, 100);
    const direction = new THREE.Vector3(0, 0, -1);
    raycaster.set(origin, direction);

    console.log(raycaster.intersectObjects(meshes));

    renderer.render(scene, camera);
    renderer.setAnimationLoop(draw);
}

raycaster의 origin과 direction을 설정하여 raycaster를 세팅한다. 이때 raycaster는 같은 도형이더라도 감지되는 면 하나하나를 체크한다.

direction에서 주의할 점은 vector 값을 normalize된 값을 사용해야하므로, 1보다 절댓값이 큰 수를 사용하면 동작하지 않는다. 그러한 경우 normalize함수로 vector를 normalize한 다음 사용한다.

 

function draw() {
    // const delta = clock.getDelta();
    const time = clock.getElapsedTime();

    boxMesh.position.y = Math.sin(time) * 2;
    torusMesh.position.y = Math.sin(time) * 2;
    boxMesh.material.color.set('plum');
    torusMesh.material.color.set('orange');

    const origin = new THREE.Vector3(0, 0, 100);
    const direction = new THREE.Vector3(0,  0, -1).normalize();
    raycaster.set(origin, direction);

    const intersects = raycaster.intersectObjects(meshes);
    intersects.forEach(item => {
        console.log(item.object.name);
        item.object.material.color.set('red');
    });

    renderer.render(scene, camera);
    renderer.setAnimationLoop(draw);
}

boxMesh와 torusMesh를 움직여 raycast에 닿는 경우에 색이 변하도록 할 수 있다.

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유