Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

225
Views
How to get world coordinates from clicking screen in Three.js using displacement maps?

I'm trying to get world coordinates from clicking the screen, but using displacement maps. This makes it more complex as the floor is variable heights (hills). My approach so far is to calculate the point on the floor (assuming the floor was all flat at z=0), then ray trace from the camera to that point, and at each iteration see where the height of the ray becomes <= the real height of the floor at that point. Once its smaller or equal to, we know it hit the floor and have the (x,y,z). Points outside the map have z=0 too.

This is the code:

// https://stackoverflow.com/questions/13055214/mouse-canvas-x-y-to-three-js-world-x-y-z
public static Get3DPoints(camera:THREE.PerspectiveCamera, click_position:THREE.Vector2, targetZ:number) {
    var vec = new THREE.Vector3(); // create once and reuse
    var pos = new THREE.Vector3(); // create once and reuse
    vec.set(
        ( click_position.x / window.innerWidth ) * 2 - 1,
        - ( click_position.y / window.innerHeight ) * 2 + 1,
        0.5 );
    vec.unproject( camera );
    vec.sub( camera.position ).normalize();
    var distance = ( targetZ - camera.position.z ) / vec.z;
    pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );
    return pos;
}

public static async Get3DCoordinatesFromClick(GAME_CONTEXT:Game_Context, camera:THREE.PerspectiveCamera, click_position:THREE.Vector2):Promise<THREE.Vector3> {
    return new Promise((resolve, reject) => {
        var start = camera.position.clone();
        var collision_point:THREE.Vector3;
        var point3d = this.Get3DPoints(camera, click_position, 0);
        //console.log(click_position, " fp --->", point3d);
        new TWEEN.Tween(start).to({
            x:point3d.x,
            y:point3d.y,
            z:point3d.z
        }, 60).onUpdate(vector => {
            if (vector.x < 0 || vector.y < 0 || vector.x > GAME_CONTEXT.width || vector.y > GAME_CONTEXT.height) {
                var z = 0;
            } else {
                var z = GAME_CONTEXT.heights_map.GetValue(vector.x/GAME_CONTEXT.width, vector.y/GAME_CONTEXT.width);
            }
            if (!collision_point && vector.z <= z) {
                collision_point = vector.clone();
            }
        }).onComplete(vector => {
            //console.log(click_position, "--->", collision_point || vector);
            resolve(collision_point || vector);
        }).start();
    });
}

This generally works and gives me fairly accurate measurements, perhaps off by 1-4 real world units. And maybe I could improve it by finding the point of the ray right when its z equals the floor height.

But the main problem is I'm getting inconsistent values each time I click. I'm clicking in the exact same spot on the screen but the (x,y,z) coordinate changes by a little each time. It's not giving me the same value.

I'm suspecting this has to do with Tweening and putting a fixed 60millisecond duration for the ray travel.

Anyone know how to fix this?

about 4 years ago · Juan Pablo Isaza
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!