수색…


피킹 / 레이 캐스팅

Raycasting은 화면상의 마우스 위치에서부터 광선을 광선에 던지는 것을 의미하며, 구현 한 경우 어떤 객체를 클릭할지 결정합니다. Threejs는 사용하여 해당 정보를 얻을 수 옥트리를 ,하지만 여전히 생산에 각 프레임에서 또는에서 결과를 계산하고 싶지 않을 수도 mousemove 이벤트, 오히려에 click 이 낮은 요구 사항에 더 접근 응용 프로그램을위한 이벤트입니다.

var raycaster, mouse = { x : 0, y : 0 };

init();

function init () {

    //Usual setup code here.

    raycaster = new THREE.Raycaster();
    renderer.domElement.addEventListener( 'click', raycast, false );

    //Next setup code there.

}

function raycast ( e ) {

    //1. sets the mouse position with a coordinate system where the center
    //   of the screen is the origin
    mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1;

    //2. set the picking ray from the camera position and mouse coordinates
    raycaster.setFromCamera( mouse, camera );    

    //3. compute intersections
    var intersects = raycaster.intersectObjects( scene.children );

    for ( var i = 0; i < intersects.length; i++ ) {
        console.log( intersects[ i ] ); 
        /*
            An intersection has the following properties :
                - object : intersected object (THREE.Mesh)
                - distance : distance from camera to intersection (number)
                - face : intersected face (THREE.Face3)
                - faceIndex : intersected face index (number)
                - point : intersection point (THREE.Vector3)
                - uv : intersection point in the object's UV coordinates (THREE.Vector2)
        */
    }

}

주의! 다음 부분을 읽지 않으면 빈 화면을 바라 보는 시간을 잃을 수 있습니다.

가벼운 도우미를 탐지하려면 raycaster.intersectObjects( scene.children ); 의 두 번째 매개 변수를 설정하십시오 raycaster.intersectObjects( scene.children ); 사실로.

그것은 raycaster.intersectObjects( scene.children , true); 의미 raycaster.intersectObjects( scene.children , true);

레이 캐스트 코드는 가벼운 도우미 만 탐지합니다.

가벼운 도우미뿐만 아니라 일반 물체도 탐지하려면 위의 레이 캐스트 기능을 다시 복사해야합니다. 이 질문을 참조하십시오.

전체 레이 캐스트 코드는 다음과 같습니다.

function raycast ( e ) {
// Step 1: Detect light helper
    //1. sets the mouse position with a coordinate system where the center
    //   of the screen is the origin
    mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1;

    //2. set the picking ray from the camera position and mouse coordinates
    raycaster.setFromCamera( mouse, camera );    

    //3. compute intersections (note the 2nd parameter)
    var intersects = raycaster.intersectObjects( scene.children, true );

    for ( var i = 0; i < intersects.length; i++ ) {
        console.log( intersects[ i ] ); 
        /*
            An intersection has the following properties :
                - object : intersected object (THREE.Mesh)
                - distance : distance from camera to intersection (number)
                - face : intersected face (THREE.Face3)
                - faceIndex : intersected face index (number)
                - point : intersection point (THREE.Vector3)
                - uv : intersection point in the object's UV coordinates (THREE.Vector2)
        */
    }
// Step 2: Detect normal objects
    //1. sets the mouse position with a coordinate system where the center
    //   of the screen is the origin
    mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1;

    //2. set the picking ray from the camera position and mouse coordinates
    raycaster.setFromCamera( mouse, camera );    

    //3. compute intersections (no 2nd parameter true anymore)
    var intersects = raycaster.intersectObjects( scene.children );

    for ( var i = 0; i < intersects.length; i++ ) {
        console.log( intersects[ i ] ); 
        /*
            An intersection has the following properties :
                - object : intersected object (THREE.Mesh)
                - distance : distance from camera to intersection (number)
                - face : intersected face (THREE.Face3)
                - faceIndex : intersected face index (number)
                - point : intersection point (THREE.Vector3)
                - uv : intersection point in the object's UV coordinates (THREE.Vector2)
        */
    }

}

객체 피킹 / GPU

Raycasting을 사용한 객체 선택은 설정에 따라 (예 : 설정과 같은 8 진수가없는 경우) 장면에있는 객체의 수에 따라 CPU에 과중한 작업 일 수 있습니다.

마우스 커서 아래에 세계 좌표가 필요하지 않지만 그 아래에있는 객체를 식별하는 경우에만 GPU 따기를 사용할 수 있습니다.

짧은 설명, GPU는 계산을위한 강력한 도구가 될 수 있지만 결과를 다시 얻는 방법을 알아야합니다. 아이디어는 ID를 나타내는 색상으로 객체를 렌더링하면 커서 아래에있는 픽셀의 색상을 읽고 가져온 객체의 ID를 찾을 수 있다는 것입니다. RGB는 16 진수 값이므로 id (정수)와 color (16 진수) 사이에 변환이 있음을 기억하십시오.

  1. 객체에 대한 새 장면 및 새 렌더링 대상 만들기
var pickingScene = new THREE.Scene();
var pickingTexture = new THREE.WebGLRenderTarget(renderer.domElement.clientWidth, renderer.domElement.clientHeight);
    pickingTexture.texture.minFilter = THREE.LinearFilter;
  1. 객체 선택을위한 새로운 쉐이더 재질을 생성하십시오.
var vs3D = `
attribute vec3 idcolor;
varying vec3 vidcolor;
void main(){
vidcolor = idcolor;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0);
}`;

var fs3D = `
varying vec3 vidcolor;
void main(void) {
gl_FragColor = vec4(vidcolor,1.0);
}`;

var pickingMaterial = new THREE.ShaderMaterial(
    {
        vertexShader: vs3D,
        fragmentShader: fs3D,
        transparent: false,
        side: THREE.DoubleSide
    });
  1. 메쉬 / 선 형상에 RGB에서 ID를 나타내는 새로운 속성을 추가하고, 동일한 지오메트리를 사용하여 pickingObject를 생성하고이를 피킹 씬에 추가하고 실제 메쉬를 id-> 객체 사전에 추가하십시오
var selectionObjects = [];

for(var i=0; i<myMeshes.length; i++){
    var mesh = myMeshes[i];
    var positions = mesh.geometry.attributes["position"].array;
    var idColor = new Float32Array(positions.length);

    var color = new THREE.Color();
    color.setHex(mesh.id);

    for (var j=0; j< positions.length; j+=3){
        idColor[j] = color.r;
        idColor[j+1] = color.g;
        idColor[j+2] = color.b;
    }

    mesh.geometry.addAttribute('idcolor', new THREE.BufferAttribute(idColor, 3));

    var pickingObject = new THREE.Mesh(mesh.geometry, pickingMaterial);
    
    pickingScene.add(pickingObject);
    selectionObjects[mesh.id] = mesh;
}
  1. 마지막으로 마우스 클릭 핸들러에서
renderer.render(pickingScene, camera, pickingTexture);
var pixelBuffer = new Uint8Array(4);
renderer.readRenderTargetPixels(pickingTexture, event.pageX, pickingTexture.height - event.pageY, 1, 1, pixelBuffer);
var id = (pixelBuffer[0] << 16) | (pixelBuffer[1] << 8) | (pixelBuffer[2]);

if (id>0){
    //this is the id of the picked object
}else{
    //it's 0. clicked on an empty space
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow