Three.js鼠标采摘对象 [英] Three.js mouse picking object

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

问题描述

所以,我发现了很多关于如何使用鼠标采摘的Threejs本身提供默认对象的教程,但有可能使用鼠标采摘进口车型,如一个obj文件,并在准确的位置显示一个球体,其中用户点击模式? 如果是这样,有人可以给我一个教程,或者至少一个例子与源$ C ​​$ C这样我就可以使用它。 我preFER的教程,因为那一个更好的方式来学习它。 ;)

编辑:所以我就鼠标采摘工作的典范!但现在我想展示一个小圆点,在那里用户点击模型中的位置。我试图做这个演示的工作方式: http://mrdoob.github.io /three.js/examples/#canvas_interactive_cubes 的,但不能让它的工作,别人谁知道为什么?请参阅下面

code

  //一旦一切都被加载,我们运行Three.js的东西。
VAR时钟=新THREE.Clock();
VAR统计= initStats();
VAR particleMaterial;

//创建一个场景,那将持有我们所有的元素,例如物体,摄影机和灯光。
变种PI2 = Math.PI * 2;
particleMaterial =新THREE.SpriteCanvasMaterial({
    颜色:0x000000处,
    程序:函数(上下文){
        context.beginPath();
        context.arc(0,0,0.5%,0,PI2,真);
        context.fill();
    }
});
VAR投影机=新THREE.Projector();
VAR场景=新THREE.Scene();

//创建一个摄像头,它定义了我们正在寻找。
VAR摄像头=新THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000);


//创建一个渲染和设置大小
VAR webGLRenderer =新THREE.WebGLRenderer();
webGLRenderer.setClearColor(新THREE.Color(0xEFEFEF,1.0));
webGLRenderer.setSize(window.innerWidth,window.innerHeight);
webGLRenderer.shadowMapEnabled = TRUE;

//位置,将相机指向到场景的中心
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 40;
camera.lookAt(新THREE.Vector3(0,0,0));


VAR trackballControls =新THREE.TrackballControls(摄像头);

trackballControls.rotateSpeed​​ = 3.0;
trackballControls.zoomSpeed​​ = 3.0;
trackballControls.panSpeed​​ = 0.4;
trackballControls.staticMoving = FALSE;

VAR ambientLight =新THREE.AmbientLight(0XFFFFFF);
scene.add(ambientLight);
hemiLight =新THREE.HemisphereLight(0XFFFFFF,0XFFFFFF,0.9);
scene.add(hemiLight);
//增加聚光灯阴影
VAR聚光灯=新THREE.SpotLight(0XFFFFFF);
spotLight.position.set(300,300,300);
spotLight.intensity = 1;
scene.add(聚光灯);

//渲染器的输出添加到html元素
$(#WebGL的输出)追加(webGLRenderer.domElement);

//调用渲染功能
变种步骤= 0;


//设置控制GUI
//无功控制=新功能(){
    //我们需要的第一个孩子,因为它是一个多材料


//}

// VAR GUI =新dat.GUI();
VAR网格;
变种对象= [];

VAR装载机=新THREE.OBJMTLLoader();
loader.addEventListener('负荷',函数(事件){
    VAR对象= event.content;
    object.traverse(函数(子){
        如果(孩子的instanceof THREE.Mesh){
            //这个孩子所需raycaster.intersectObject位()方法
        }
    });
    object.scale.set(4,4,4);
    object.position.set(0,-10,0);
    object.name =测试;
    scene.add(对象);
    objects.push(对象);
});

loader.load(模型/ dancer07.obj,模型/ dancer07.mtl',{方:THREE.DoubleSide});

VAR飞机=新THREE.Mesh(新THREE.PlaneGeometry(400,400,50,50),新THREE.MeshBasicMaterial({颜色:0x808080,线框:真}));
plane.rotation.x = -Math.PI / 2;
plane.name =勤;
plane.position.set(0,-10,0);
scene.add(平面);
objects.push(平面);

渲染();

功能渲染(){
    stats.update();
    变种,δ= clock.getDelta();

    如果(目){
        // mesh.rotation.y + = 0.006;
    }


    trackballControls.update(增量);

    //webGLRenderer.clear();
    //渲染使用requestAnimationFrame
    requestAnimationFrame(渲染);
    webGLRenderer.render(场景,摄像机)
}

功能initStats(){

    VAR统计=新的统计();
    stats.setMode(0); // 0:FPS,1:MS

    //对齐左上角
    stats.domElement.style.position ='绝对';
    stats.domElement.style.left =0px​​;
    stats.domElement.style.top =0px​​;

    $(#统计输出)追加(stats.domElement);

    返回统计信息;
}
document.addEventListener(鼠标按下,onDocumentMouseDown,假);
window.addEventListener('调整',onWindowResize,假);

功能onWindowResize(){

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

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

    }

功能onDocumentMouseDown(事件){
    。事件preventDefault();
    VAR mouseX =(event.clientX / window.innerWidth)* 2-1;
    VAR mouseY的=  - (event.clientY /window.innerHeight)*2+1;
    VAR向量=新THREE.Vector3(mouseX,mouseY的,0.5);
    projector.unprojectVector(矢量,摄像头);
    VAR raycaster =新THREE.Raycaster(camera.position,vector.sub(camera.position).normalize());
    VAR相交= raycaster.intersectObjects(对象,真正的);
    如果(intersects.length大于0){
        警报(相交!);
        VAR颗粒=新THREE.Sprite(particleMaterial);
        particle.position.copy(相交[0] .point);
        particle.scale.x = particle.scale.y = 300;
        scene.add(粒);
    }

}

$('#复位)。点击(函数(){
    trackballControls.reset();
});

$('#女)。点击(函数(){
    scene.remove(scene.getObjectByName(测试));
    loader.load(模型/ dancer07.obj,模型/ dancer07.mtl',{方:THREE.DoubleSide});
});

$('#男)。点击(函数(){
    scene.remove(scene.getObjectByName(测试));
    loader.load(模型/ doorman.obj,模型/ doorman.mtl',{方:THREE.DoubleSide});
});
 

解决方案

没关系,如果导入的模型或默认对象。鼠标采摘code在Three.JS例子适用于任何类型的网格。

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

  VAR向量=新THREE.Vector3(mouse.x,mouse.y,1);
projector.unprojectVector(矢量,摄像头);

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

变种相交= raycaster.intersectObject(目);
 

使用由 raycaster.intersectObject 函数加载程序创建的网格。你的情况,你可以得到所有的组成物体的下面装code中的网格。

  VAR装载机=新THREE.OBJLoader(经理);
loader.load('example.obj',函数(对象){
    object.traverse(函数(子){
        如果(孩子的instanceof THREE.Mesh){
            //这个孩子所需raycaster.intersectObject位()方法
        }
    });
    object.position.y =  -  80;
    scene.add(对象);
});
 

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. ;)

EDIT: 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});
});

解决方案

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); 

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 );
} );

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

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