三.js 鼠标拾取对象 [英] Three.js mouse picking object

查看:42
本文介绍了三.js 鼠标拾取对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我找到了很多关于如何在 Threejs 本身可用的默认对象上使用鼠标拾取的教程,但是是否可以在导入的模型(如 .obj 文件)上使用鼠标拾取并在精确位置显示一个球体用户点击模型?如果是这样,有人可以给我一个教程或至少一个带有源代码的示例,以便我可以使用它.我更喜欢教程,因为那是更好的学习方式.;)

So i found a lot of tutorials on how to use mouse picking on default objects available in Threejs itself, but is it possible to use mouse picking on imported models like a .obj file and displaying a sphere at the exact position where the user clicks the model? If so, can someone give me a tutorial or at least an example with source code so i can use it. I prefer a tutorial, because thats a better way to learn it. ;)

所以我让鼠标选择为模型工作!但是现在我想在用户单击模型的位置显示一个小点.我试着按照这个演示的方式来做:http://mrdoob.github.io/three.js/examples/#canvas_interactive_cubes 但不能让它工作,有人知道为什么吗?看下面的代码

So i got mouse picking working for the model! But now i want to show a little dot at the location where the user clicks the model. I tried to do it the way this demo works: http://mrdoob.github.io/three.js/examples/#canvas_interactive_cubes but can't get it to work, someone who knows why? See code below

// once everything is loaded, we run our Three.js stuff.
var clock = new THREE.Clock();
var stats = initStats();
var particleMaterial;

// create a scene, that will hold all our elements such as objects, cameras and lights.
var PI2 = Math.PI * 2;
particleMaterial = new THREE.SpriteCanvasMaterial( {
    color: 0x000000,
    program: function ( context ) {
        context.beginPath();
        context.arc( 0, 0, 0.5, 0, PI2, true );
        context.fill();
    }
});
var projector = new THREE.Projector();
var scene = new THREE.Scene();

// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);


// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEFEFEF, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 40;
camera.lookAt(new THREE.Vector3(0, 0, 0));


var trackballControls = new THREE.TrackballControls(camera);

trackballControls.rotateSpeed = 3.0;
trackballControls.zoomSpeed = 3.0;
trackballControls.panSpeed = 0.4;
trackballControls.staticMoving = false;

var ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
hemiLight = new THREE.HemisphereLight( 0xFFFFFF, 0xFFFFFF, 0.9 ); 
scene.add(hemiLight);
// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(300, 300, 300);
spotLight.intensity = 1;
scene.add(spotLight);

// add the output of the renderer to the html element
$("#WebGL-output").append(webGLRenderer.domElement);

// call the render function
var step = 0;


// setup the control gui
//var controls = new function () {
    // we need the first child, since it's a multimaterial


//}

//var gui = new dat.GUI();
var mesh;
var objects = [];

var loader = new THREE.OBJMTLLoader();
loader.addEventListener('load', function (event) {
    var object = event.content;
    object.traverse( function ( child ) {
        if ( child instanceof THREE.Mesh ) {
            //The child is the bit needed for the raycaster.intersectObject() method
        }
    } );
    object.scale.set(4, 4, 4);
    object.position.set(0, -10, 0);
    object.name = "test";
    scene.add(object);
    objects.push(object);
});

loader.load('models/dancer07.obj', 'models/dancer07.mtl', {side: THREE.DoubleSide});

var plane = new THREE.Mesh(new THREE.PlaneGeometry(400, 400, 50, 50), new THREE.MeshBasicMaterial({ color: 0x808080, wireframe: true }));
plane.rotation.x = -Math.PI / 2;
plane.name = 'Ground';
plane.position.set(0, -10, 0);
scene.add(plane);
objects.push(plane);

render();

function render() {
    stats.update();
    var delta = clock.getDelta();

    if (mesh) {
        //   mesh.rotation.y+=0.006;
    }


    trackballControls.update(delta);

    //webGLRenderer.clear();
    // render using requestAnimationFrame
    requestAnimationFrame(render);
    webGLRenderer.render(scene, camera)
}

function initStats() {

    var stats = new Stats();
    stats.setMode(0); // 0: fps, 1: ms

    // Align top-left
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.left = '0px';
    stats.domElement.style.top = '0px';

    $("#Stats-output").append(stats.domElement);

    return stats;
}
document.addEventListener('mousedown', onDocumentMouseDown, false);
window.addEventListener( 'resize', onWindowResize, false ); 

function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );

    }

function onDocumentMouseDown( event ){
    event.preventDefault();
    var mouseX = (event.clientX / window.innerWidth)*2-1;
    var mouseY = -(event.clientY /window.innerHeight)*2+1;
    var vector = new THREE.Vector3( mouseX, mouseY, 0.5 );
    projector.unprojectVector( vector, camera );
    var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
    var intersects = raycaster.intersectObjects( objects, true );
    if (intersects.length > 0) {
        alert("intersect!");
        var particle = new THREE.Sprite( particleMaterial );
        particle.position.copy( intersects[0].point );
        particle.scale.x = particle.scale.y = 300;
        scene.add(particle);    
    }

}

$('#reset').click(function() {
    trackballControls.reset();
});

$('#female').click(function() {
    scene.remove(scene.getObjectByName("test"));
    loader.load('models/dancer07.obj', 'models/dancer07.mtl', {side: THREE.DoubleSide});
});

$('#male').click(function() {
    scene.remove(scene.getObjectByName("test"));
    loader.load('models/doorman.obj', 'models/doorman.mtl', {side: THREE.DoubleSide});
});

推荐答案

它是导入的模型还是默认对象并不重要.Three.JS 示例中的鼠标拾取代码适用于任何类型的网格.

It doesn't matter if its an imported model or a default object. The mouse picking code in the Three.JS examples works with any sort of mesh.

http://threejs.org/examples/#webgl_interactive_buffergeometry

var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
projector.unprojectVector( vector, camera );

raycaster.set(camera.position, vector.sub(camera.position).normalize());

var intersects = raycaster.intersectObject(mesh); 

raycaster.intersectObject 函数中使用加载器创建的网格.在您的情况下,您可以使用以下加载代码获取构成对象的所有网格.

Use the meshes created by the loader in the raycaster.intersectObject function. In your case you could get all of the meshes that compose an object with the below loading code.

var loader = new THREE.OBJLoader( manager );
loader.load( 'example.obj', function ( object ) {
    object.traverse( function ( child ) {
        if ( child instanceof THREE.Mesh ) {
            //The child is the bit needed for the raycaster.intersectObject() method
        }
    } );
    object.position.y = - 80;
    scene.add( object );
} );

这篇关于三.js 鼠标拾取对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆