three.js
Выбор объекта
Поиск…
Сбор объектов / Raycasting
Raycasting означает выброс луча из положения мыши на экране в сцену, так как трижды определяет, на какой объект вы хотите щелкнуть, если вы его внедрили. Трижды получает эту информацию с помощью октета , но все же в процессе производства вы не можете рассчитывать результат в каждом кадре или в событии 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 , true);
Код raycast обнаруживает только светлый помощник.
Если вы хотите, чтобы он обнаруживал обычные объекты, а также помощник света, вам нужно снова скопировать вышеупомянутую функцию raycast. См. Этот вопрос .
Полный код raycast
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 может быть тяжелой задачей для вашего процессора в зависимости от вашей установки (например, если у вас нет такой настройки, как octree) и количества объектов в сцене.
Если вам не нужны координаты мира под курсором мыши, но только для идентификации объекта под ним вы можете использовать сбор GPU.
Краткое объяснение, GPU может быть мощным инструментом для вычисления, но вам нужно знать, как вернуть результаты. Идея состоит в том, что если вы визуализируете объекты с цветом, который представляет их идентификатор, вы можете прочитать цвет пикселя под курсором и найти идентификатор выбранного объекта. Помните, что RGB - это просто шестнадцатеричное значение, поэтому существует преобразование между id (integer) и цветом (hex).
- Создайте новую сцену и новую цель рендеринга для своего объекта
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, создайте объект pickingObject с использованием той же геометрии и добавьте его в сцену выбора и добавьте реальную сетку в словарь id-> object
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
}