0

What i'm trying to achieve is making a laser beam connect 2 points in space.

I was thinking that maybe by rendering a lineGeometry and appending 6 planes rotated on x axis will do the trick, but it seems like it's more complicated.

This is how I generate the laser beam, so far so good

window.lazor = new THREE.Object3D();
        var material    = new THREE.MeshBasicMaterial({
            blending    : THREE.AdditiveBlending,
            color       : 0x4444aa,
            side        : THREE.DoubleSide,
            depthWrite  : false,
            transparent : true
        })
        var geometry    = new THREE.PlaneBufferGeometry(100, 0.1)
        var nPlanes = 3;
        for(var i = 0; i < nPlanes; i++){
            var mesh    = new THREE.Mesh(geometry, material)
            mesh.rotation.x = i/nPlanes * Math.PI
            lazor.add(mesh);
        }

        window.lazor.rotation.y = Math.PI / 2

What i'm looking into is to render both ends of the object3D to 2 points(Vec3).

Line geometry seems to do the trick (length will always be equal to the distance between the 2 points), by updating the second vertice to the Vector3 it needs to connect with every frame, but i'm not confident on what approach should I take using the `Object3D (I'm not sure how to find out where each end of the Object3D is located)

1 Answer 1

1

You want to create a plane that spans two 3D points.

The solution is to create a PlaneBufferGeometry and transform the geometry so that one end lies at the origin, and the geometry is aligned with the positive z-axis.

So, in your case, to create your laser, you would do something like this:

// material
var material    = new THREE.MeshBasicMaterial( {

    blending    : THREE.AdditiveBlending,
    color       : 0x4444aa,
    side        : THREE.DoubleSide,
    depthWrite  : false,
    transparent : true

} );

// geometry
var geometry = new THREE.PlaneBufferGeometry( 1, 100 );
geometry.rotateX( - Math.PI / 2 ); // so it aligns with the z-axis
geometry.translate( 0, 0, 50 ); // so one end is at the origin

// laser
laser = new THREE.Object3D();
laser.position.set( 10, 10, 10 );
scene.add( laser );

var nPlanes = 3;

for( var i = 0; i < nPlanes; i++ ){

    var mesh = new THREE.Mesh( geometry, material );

    mesh.rotation.z = i / nPlanes * Math.PI; // rotate around z-axis

    laser.add( mesh );

}

// laser target
target = new THREE.Object3D(); // or some character in the scene
target.position.set( 200, 200, 200 ); // or wherever it happens to be

Then in the render loop

laser.lookAt( target.position );

The only thing that may be an issue, is the laser must be a child of the scene directly, because lookAt() is limited in that sense.

If you want to dynamically change the length of the laser, the easiest thing to do is to do this:

laser.scale.z = 2;

three.js r.84

Sign up to request clarification or add additional context in comments.

3 Comments

Indeed, target child is part of a Group which unfortunately cannot be removed since it's supposed to move around depending on player's target position, this is meant to fix floating point errors on huge coordinates
Think about my answer for more than 5 minutes before you reject it. The target is the object that laser points at. Also, three.js r85dev has mitigated the large-coordinate problem.
I've been implementing the code, and managed to aim the beam straight where I needed to by getting matrixworld of the target. Didn't knew about the floating point fix coming up in r85(which is awesome). However everything works just fine and smooth.. was thinking that Vec3.lookAt(x,y,z) might be an expensive operation to use, but so far it works like a charm

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.