three.js
개체 따기
수색…
피킹 / 레이 캐스팅
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 진수) 사이에 변환이 있음을 기억하십시오.
- 객체에 대한 새 장면 및 새 렌더링 대상 만들기
var pickingScene = new THREE.Scene();
var pickingTexture = new THREE.WebGLRenderTarget(renderer.domElement.clientWidth, renderer.domElement.clientHeight);
pickingTexture.texture.minFilter = THREE.LinearFilter;
- 객체 선택을위한 새로운 쉐이더 재질을 생성하십시오.
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
});
- 메쉬 / 선 형상에 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;
}
- 마지막으로 마우스 클릭 핸들러에서
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
}