Three.js无法获得正确的鼠标位置

时间:2019-01-30 05:15:20

标签: javascript html three.js

所以我的问题是我正在尝试从2d鼠标坐标中获取3d向量,并且我想使用3d位置使3d对象移至目前为止,我已经使对象沿您所拥有的最后一个方向移动移动了鼠标,但是它不会移到鼠标当前所在的实际位置,甚至不会最后移到仅将方向定位的位置

var scene;
var camera;
var renderer;
var geometry;
var material;
var sphere;
var cube;
var SphereColors = ["rgb(0, 255, 0)", "rgb(255, 255, 0)", "rgb(255, 0, 102)", "rgb(0, 0, 255)", "rgb(255, 51, 0)", "rgb(0, 255, 255)"];
var mouse =  new THREE.Vector2();
var pos = new THREE.Vector3();

scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0, 2, 5);
camera.rotation.set(-0.1, 0, 0);

renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

geometry = new THREE.SphereGeometry( 1, 32, 32 );
material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
sphere = new THREE.Mesh( geometry, material );
sphere.scale.set(0.8, 0.8, 0.8);

geometry = new THREE.BoxGeometry( 1, 1, 1 );
material = new THREE.MeshBasicMaterial( {color: "rgb(0, 102, 0)"} );
cube = new THREE.Mesh(geometry, material);
cube.scale.set(50, 1, 50);

scene.add( cube );
scene.add( sphere );

var controls = new THREE.OrbitControls( camera );

controls.target = sphere.position;
controls.maxPolarAngle = 1.2
controls.minPolarAngle = 0.2

controls.update();

var animate = function () {
    requestAnimationFrame( animate );
    controls.update();
    renderer.render( scene, camera );

    sphere.rotation.x += 0.01;
    sphere.rotation.y += 0.01;
    //camera.position.set(sphere.position.x + 1.5, sphere.position.y + 1, sphere.position.z + 1.5);
    //camera.lookAt(sphere.position);
    TWEEN.update();
};

animate();
function PickRandomColor() {
    sphere.material.color = new THREE.Color(SphereColors[Math.floor(Math.random() * SphereColors.length)]);
}

setInterval(UpdatePosition, 100)
var speed = 0.4
function UpdatePosition() {
    var tween = new TWEEN.Tween(sphere.position).to({ x: pos.x, y: 0, z: pos.z }, (sphere.position.distanceTo(pos) / speed) * 1000).start();
}

var raycaster = new THREE.Raycaster(); 

document.addEventListener( 'mousemove', UpdateMouse, false );

function UpdateMouse(e) {

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

    var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
    vector.unproject( camera );
    var dir = vector.sub( camera.position ).normalize();
    var distance = - camera.position.z / dir.z;
    //pos = camera.position.clone().add( dir.multiplyScalar( distance ) );
    raycaster.setFromCamera( mouse, camera );
    var inter = raycaster.intersectObjects(scene.children, true);
    pos = inter[0].point
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>

1 个答案:

答案 0 :(得分:0)

您的代码中有2个问题:

  1. THREE.Raycaster可能无法命中任何对象,在这种情况下,.intersectObjects返回的对象列表为空。
    在设置新的目标位置之前,请检查列表的长度。
  var inter = raycaster.intersectObjects(scene.children, true);
  if ( inter.length )
      pos = inter[0].point
  1. 您做两件事互相矛盾:

一方面,您想将球体移动到从相机位置通过光标(鼠标)位置的光线照射到曲面(立方体)的位置:

var tween = new TWEEN.Tween(sphere.position).to({ x: pos.x, y: 0, z: pos.z }, (sphere.position.distanceTo(pos) / speed) * 1000).start();

这导致球体稍微“跟随”鼠标。

另一方面,THREE.OrbitControls应将球体保持在视口的中心:

var controls = new THREE.OrbitControls( camera );
controls.target = sphere.position;

请注意,当您执行controls.target = sphere.position;时,controls.targetsphere.position将共享同一个THREE.Vector3对象。
这导致球体似乎停留在原处。球体跟随鼠标,但是场景视图弥补了这一点,因为它跟随球体。
最终,球体更改了位置,但仍位于视图的中心。

.clone在启动时THREE.OrbitControls的目标位置的球体位置,但不要永久性地指向同一位置:

controls.target = sphere.position;

controls.target = sphere.position.clone();

请参见示例,其中我将建议的更改应用于原始代码:

var scene;
var camera;
var renderer;
var geometry;
var material;
var sphere;
var cube;
var SphereColors = ["rgb(0, 255, 0)", "rgb(255, 255, 0)", "rgb(255, 0, 102)", "rgb(0, 0, 255)", "rgb(255, 51, 0)", "rgb(0, 255, 255)"];
var mouse =  new THREE.Vector2();
var pos = new THREE.Vector3();

scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0, 5, 5);
camera.rotation.set(-0.1, 0, 0);

renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

geometry = new THREE.SphereGeometry( 1, 32, 32 );
material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
sphere = new THREE.Mesh( geometry, material );
sphere.scale.set(0.8, 0.8, 0.8);

geometry = new THREE.BoxGeometry( 1, 1, 1 );
material = new THREE.MeshBasicMaterial( {color: "rgb(0, 102, 0)"} );
cube = new THREE.Mesh(geometry, material);
cube.scale.set(50, 1, 50);

scene.add( cube );
scene.add( sphere );

var controls = new THREE.OrbitControls( camera );

controls.target = sphere.position.clone();
controls.maxPolarAngle = 1.2
controls.minPolarAngle = 0.2

controls.update();

var animate = function () {

    sphere.rotation.x += 0.01;
    sphere.rotation.y += 0.01;
    TWEEN.update();

    requestAnimationFrame( animate );
    controls.update();
    renderer.render( scene, camera );
};

animate();
function PickRandomColor() {
    sphere.material.color = new THREE.Color(SphereColors[Math.floor(Math.random() * SphereColors.length)]);
}

setInterval(UpdatePosition, 100)
var speed = 2.0
function UpdatePosition() {
    var tween = new TWEEN.Tween(sphere.position).to({ x: pos.x, y: 0, z: pos.z }, (sphere.position.distanceTo(pos) / speed) * 1000).start();
}

var raycaster = new THREE.Raycaster(); 

document.addEventListener( 'mousemove', UpdateMouse, false );

function UpdateMouse(e) {

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

    //var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
    //vector.unproject( camera );
    //var dir = vector.sub( camera.position ).normalize();
    //var distance = - camera.position.z / dir.z;
    //pos = camera.position.clone().add( dir.multiplyScalar( distance ) );
    raycaster.setFromCamera( mouse, camera );
    var inter = raycaster.intersectObjects(scene.children, true);
    if ( inter.length )
        pos = inter[0].point
}

window.onresize = function() { 
    var aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = aspect;
    camera.updateProjectionMatrix();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>