Raycast объект для включения события щелчка мыши с Three.js - PullRequest
1 голос
/ 27 сентября 2019

Я добавляю объекты в сцену для каждой записи в базе данных.У меня был куб, появляющийся в сцене для входа, но когда я попытался добавить raycast для щелчка по объектам, он не работает, объекты не появляются, и консоль читает «Выражение недоступно». Я получил части кода из трех.JS сайт Raycasting, так что не уверен, что я делаю не так.

Вот код JS:

var renderer, scene, container, camera;
var geometry, material;
var controls, group;

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();


init()

function onMouseMove( event ) {

    // calculate mouse position in normalized device coordinates
    // (-1 to +1) for both components

    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

}

function init() {
    // init renderer
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    // document.body.appendChild( renderer.domElement );

    container = document.getElementById('container');
    container.appendChild( renderer.domElement );

    // init scene
    scene = new THREE.Scene();
    scene.background = new THREE.Color( 0xffffff );

    group = new THREE.Group();
    scene.add( group )

    //fetch data from database and add object for each entry
    getData()
    async function getData() {
        var response = await fetch('/api/indexvr');
        var data = await response.json();
        console.log(data) 

        for (var i=0; i<data.length; i++) {
            cube = new THREE.Mesh( geometry, material );
            cube.position.x = i;
            scene.add(cube);
            //group.add(data)
        }
    }

    // init camera
    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.set( 15, 15, 15 ); //camera.position.set( 5, 0, 10 );
    camera.lookAt( scene.position );
    // controls = new OrbitControls( camera, renderer.domElement );
    // controls.enableRotate = true;
}

function render() {

    // update the picking ray with the camera and mouse position
    raycaster.setFromCamera( mouse, camera );

    // calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects( scene.children );

    for ( var i = 0; i < intersects.length; i++ ) {

        intersects[ i ].object.material.color.set( 0xff0000 );

    }

    renderer.render( scene, camera );

}

window.addEventListener( 'mousemove', onMouseMove, false );

window.requestAnimationFrame(render);

В HTML есть только div, называемый «контейнер», и этот тег:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.js"></script>

Он не производит никакихошибка, это говорит только о том, что в консоли: enter image description here

Таким образом, он выбирает данные, но не может отобразить сцену

var renderer, scene, container, camera;
var geometry, material;
var controls, group;

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();


init()

function onMouseMove(event) {

  // calculate mouse position in normalized device coordinates
  // (-1 to +1) for both components

  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

}

function init() {
  // init renderer
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  // document.body.appendChild( renderer.domElement );

  container = document.getElementById('container');
  container.appendChild(renderer.domElement);

  // init scene
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xffffff);


  group = new THREE.Group();
  scene.add(group)

  //fetch data from database and add object for each entry
  getData()
  async function getData() {
    /**
     * @author TheJim01
     * Replacing DB call with fake data to make it work here.
     * Nancy: Please feel free to add appropriate data.
     */
    // var response = await fetch('/api/indexvr');
    // var data = await response.json();
    var data = [{}, {}, {}, {}, {}]
    console.log(data)

    for (var i = 0; i < data.length; i++) {
      cube = new THREE.Mesh(geometry, material);
      cube.position.x = i;
      scene.add(cube);
      //group.add(data)
    }
  }

  // init camera
  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
  camera.position.set(15, 15, 15); //camera.position.set( 5, 0, 10 );
  camera.lookAt(scene.position);
  // controls = new OrbitControls( camera, renderer.domElement );
  // controls.enableRotate = true;
}

function render() {

  // update the picking ray with the camera and mouse position
  raycaster.setFromCamera(mouse, camera);

  // calculate objects intersecting the picking ray
  var intersects = raycaster.intersectObjects(scene.children);

  for (var i = 0; i < intersects.length; i++) {

    intersects[i].object.material.color.set(0xff0000);

  }

  renderer.render(scene, camera);

}

window.addEventListener('mousemove', onMouseMove, false);

window.requestAnimationFrame(render);
<script src="//threejs.org/build/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.js"></script>
<script src="https://unpkg.com/spritejs/dist/spritejs.min.js"></script>

<div id="container"></div>

Ответы [ 2 ]

1 голос
/ 28 сентября 2019

Я вижу несколько неправильных вещей.Я не могу сказать, является ли это тем, что вы пропустили разделы своего кода.

Во-первых, предоставленный вами код не определяет ни геометрию, ни материал.Вы подразумевали, что рисуете куб для каждого результата БД, поэтому я сделаю предположение и использую BoxBufferGeometry.У вас также не определены источники света, поэтому я просто буду использовать MeshBasicMaterial, который не нуждается в источниках света.

С этими исключениями кажется, что вы на полпути к настройкеЦикл рендеринга с использованием window.requestAnimationFrame, но вы все равно вызываете render только один раз, даже если выборка БД асинхронна.Другими словами, рендеринг может произойти еще до того, как вы получите ответ от вашей БД, поэтому вы ничего не увидите.Я добавил некоторый шаблонный код для настройки цикла рендеринга, аналогично тому, как Three.js делает в своих примерах.

Интересно, что это было все, что потребовалось.Raycaster начал работать, и я смог утешить результаты.Я получил несколько ложных срабатываний, когда сцена впервые начала рендеринг, но это потому, что еще не было никакого ввода мышью, поэтому это было лучевое вещание с середины экрана (там, где существует первый куб).

Обычно, вы не хотели бы получать raycast для каждого кадра, но я понимаю, что ситуация с виртуальной реальностью может быть разной (чертовски суетливые люди).

Наконец, одно из последних изменений, которое я сделал, - дать каждому кубу свой материал.(ну клоны оригинала).Это было необходимо для того, чтобы вы могли передавать лучи против каждого отдельно.

// Need to create geometry and material
var geometry = new THREE.BoxBufferGeometry(0.5, 0.5, 0.5);
var material = new THREE.MeshBasicMaterial({
  color: "green"
});

var renderer, scene, container, camera;
var controls, group;

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

init()

function onMouseMove(event) {

  // calculate mouse position in normalized device coordinates
  // (-1 to +1) for both components

  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

}

function init() {
  // init renderer
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  // document.body.appendChild( renderer.domElement );

  container = document.getElementById('container');
  container.appendChild(renderer.domElement);

  // init scene
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xffffff);


  group = new THREE.Group();
  scene.add(group)

  //fetch data from database and add object for each entry
  getData()
  async function getData() {
    /**
     * @author TheJim01
     * Replacing DB call with fake data to make it work here.
     * Nancy: Please feel free to add appropriate data.
     */
    // var response = await fetch('/api/indexvr');
    // var data = await response.json();
    var data = [{}, {}, {}, {}, {}]
    //console.log(data)

    for (var i = 0; i < data.length; i++) {
      cube = new THREE.Mesh(geometry, material.clone());
      cube.position.x = i;
      scene.add(cube);
      //group.add(data)
    }
  }

  // init camera
  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
  camera.position.set(15, 15, 15); //camera.position.set( 5, 0, 10 );
  camera.lookAt(scene.position);
  // controls = new OrbitControls( camera, renderer.domElement );
  // controls.enableRotate = true;
}

function render() {

  // update the picking ray with the camera and mouse position
  raycaster.setFromCamera(mouse, camera);

  // calculate objects intersecting the picking ray
  var intersects = raycaster.intersectObjects(scene.children);
  if (intersects.length > 0) {
    console.log(intersects);
  }

  for (var i = 0; i < intersects.length; i++) {

  intersects[i].object.material.color.set(0xff0000);
  

  }

  renderer.render(scene, camera);

}

window.addEventListener('mousemove', onMouseMove, false);

// Here's the bbasic render loop implementation
function animate() {
  requestAnimationFrame(animate);
  render();
}
animate();
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.min.js"></script>

<div id="container"></div>
1 голос
/ 27 сентября 2019

Я думаю, вы никогда не добавите модуль трехорбитального контроля.В соответствии с документацией three.js нам необходимо отдельно добавить элементы управления орбитой в файл.

https://threejs.org/docs/#examples/en/controls/OrbitControls

https://www.npmjs.com/package/three-orbitcontrols

У вас есть файл OrbitControls.js вваш проект?

...