three.js click single particle

邮差的信 提交于 2019-12-12 15:03:11

问题


In this example you can see 2 particles which are clickable but they are both affected by the click. Also i want just to detect clicks on particles without filtering them out of the scene. Like here

if (intersects.length>0){
    if(intersects[0].object.type == "Points"){
        intersects[0].object.material.color.setHex( Math.random() * 0xffffff );
    }
}

It is important for me to use particles because they can stay always the same size to the camera and i dont need to use a second orthographic camera. In the end i want to achieve something like the ARK Starmap from Star Citizen. Where the systems stay always the same size and are clickable.

$(function(){
    if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

    var stats;

    var camera, controls, scene, renderer;

    var group;
    var objectControls;
    var particleSystem, raycaster;
    var mouse = new THREE.Vector2();
    var projector = new THREE.Projector();

    function init() {

        var width = window.innerWidth;
        var height = window.innerHeight;

        camera = new THREE.PerspectiveCamera( 50, width / height, 1, 10000000 );
        camera.position.z = 1500;
        camera.position.y = 100;

        scene = new THREE.Scene();

        renderer = new THREE.WebGLRenderer();
        renderer.setClearColor("black");
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.autoClear = false;

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

        controls = new THREE.OrbitControls( camera, renderer.domElement );
        controls.enableZoom = false;
        controls.minDistance  = 50;
        controls.maxDistance  = 500000;

        var loader = new THREE.TextureLoader();
        loader.load( "textures/systempoint.png", function ( texture ) {
               particles = new THREE.Geometry(),
               pMaterial = new THREE.PointsMaterial({map: texture, size: 32, transparent:true, sizeAttenuation:false});

               particle = new THREE.Vector3(400, 300, 300);
               particles.vertices.push(particle);

               particle = new THREE.Vector3(300, 400, 300);
               particles.vertices.push(particle);

               // create the particle system
               particleSystem = new THREE.Points(particles,pMaterial);
               particleSystem.sortParticles = false;
               particleSystem.name = "systems";
               scene.add(particleSystem);
           });

        //////////////////////////////////////////////////////////////////////////
           // Lights
           //////////////////////////////////////////////////////////////////////////

        light = new THREE.AmbientLight( 0x666666 );
        scene.add( light );

           var params = { recursive: true };
        objectControls = new ObjectControls( camera, params );

           stats = new Stats();
           stats.domElement.style.position = 'absolute';
           stats.domElement.style.top = '0px';
           stats.domElement.style.zIndex = 100;
           container.appendChild( stats.domElement );

        window.addEventListener( 'resize', onWindowResize, false );

        console.log(scene);
    }
    function onWindowResize() {
        var width = window.innerWidth;
        var height = window.innerHeight;
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
        renderer.setSize( width, height );
    }
    var lastTimeMsec= null;
    var nowMsec= null;
    function animate() {
        requestAnimationFrame( animate );
        //controls.update(); // required if controls.enableDamping = true, or if controls.autoRotate = true
        stats.update();
        objectControls.update();
        render();

    }
    function render() {
        renderer.render( scene, camera );
    }
    $(document).mousedown(function(e) {
        e.preventDefault();
        var mouseVector = new THREE.Vector3(
            ( e.clientX / window.innerWidth ) * 2 - 1,
          - ( e.clientY / window.innerHeight ) * 2 + 1,
            1 );

        mouseVector.unproject(camera);
        var raycaster = new THREE.Raycaster( camera.position, mouseVector.sub( camera.position ).normalize() );
        raycaster.params.Points.threshold = 15

        var intersects = raycaster.intersectObjects( scene.children );

        if (intersects.length>0){
            if(intersects[0].object.type == "Points"){
                console.log(intersects[0].object.position);
                intersects[0].object.material.color.setHex( Math.random() * 0xffffff );
            }
        }
    });
    init();
    animate();
   });

回答1:


You mistook the change of color of both for both being detected in the click ... you're not coloring the particles, you are coloring the material. And the material is shared between the particles.

I've managed to fix your fiddle, took a lot of effort (but learned a bit in the process).

http://jsfiddle.net/agqq96bq/5/

Some key points:

  • I switched three.js to a non-minified version as that makes it much easier to troubleshoot.
  • The raycaster does support the Points object, and I've made use of this. For best result there's a threshold that needs to be set (how large it is defines how far away you can be for the click to register on a particle).
  • You need to give each particle its own unique color, and set it to use THREE.VertexColors. The code does this now.
  • I tidied the code using the Raycaster.
  • You'll find code in there which also adds Sprites ... initially I thought you'd not be able to match against particles in a Points object, but the three.js source proved me wrong, the problem has been solved there and the sprites aren't need for that anymore. I've left the sprites in anyway, easy to get rid of.
  • I've added code to make use of the userData property (the official place in a three.js object to store your own data), you'll find this invaluable when you actually want to do something with the item that was clicked on.


来源:https://stackoverflow.com/questions/33308105/three-js-click-single-particle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!