Three.js鼠标拣选对象

时间:2014-09-04 13:57:55

标签: javascript 3d three.js .obj

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

编辑:所以我为模型选择了鼠标!但现在我想在用户点击模型的位置显示一个小点。我尝试按照这个演示的方式进行操作:http://mrdoob.github.io/three.js/examples/#canvas_interactive_cubes但是无法让它工作,有人知道为什么吗?见下面的代码

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

1 个答案:

答案 0 :(得分:1)

无论是导入的模型还是默认对象都无关紧要。 Three.JS示例中的鼠标选取代码适用于任何类型的网格。

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函数中加载程序创建的网格。在您的情况下,您可以使用以下加载代码获取构成对象的所有网格。

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