2

I've been working with three.js examples of boids/flocks for some time, but both the canvas one and the webgl/shaders one have a flaw: the mouseOver event (which "disturbs" birds and triggers a repulsion) only works when camera.position = {x: 0, y: 0,: whatever}.

I've tried to improve that in the canvas example (easier to my eyes) by editing this part:

function onDocumentMouseMove( event ) {
    var vector = new THREE.Vector3( event.clientX - SCREEN_WIDTH_HALF, - event.clientY + SCREEN_HEIGHT_HALF, 0 );
    for ( var i = 0, il = boids.length; i < il; i++ ) {
        boid = boids[ i ];
        vector.z = boid.position.z;
        boid.repulse( vector );
    }
}

And trying something like:

function onDocumentMouseMove( event ) {
    var vector = new THREE.Vector3();
    vector.x = event.clientX;
    vector.y = - event.clientY;
    vector.unproject(camera);
    for ( var i = 0, il = boids.length; i < il; i++ ) {
        boid = boids[ i ];
        vector.z = boid.position.z;
        boid.repulse( vector );
    }
}

But this can't work, the unprojected vector could only be used with a raycaster to find objects intersecting its path. In our case, the repulsion effect must work at 150 distance, according to boid.repulse:

this.repulse = function ( target ) {
    var distance = this.position.distanceTo( target );
    if ( distance < 150 ) {
        var steer = new THREE.Vector3();
        steer.subVectors( this.position, target );
        steer.multiplyScalar( 0.5 / distance );
        _acceleration.add( steer );
    }
}

So I'm stuck. Should I find a way to widen the raycaster so it's like a 150-wide cylinder for mouse picking? Or is there a way to unproject the vector then re-project it on the plane nearest to the bird, so to calculate the distance? (but what about performance with 200+ birds? )

If the solution can only come from shaders, feel free to tell me to create another topic.

Included: jsfiddle of the canvas example with a slightly moved camera.

4

0 回答 0