Three.js How to make a camera follow a terrain hei

2019-07-13 18:47发布

问题:

I have a terrain mountain range with a camera fly view positioned close to the heightmap. The camera is controlled using standard keyboard controls that doesn't allow movement in y axis; it stays on it's set y-axis. Since the terrain is not an even level and randomly renders. How can I get the camera to follow the terrain heightmap? Here is an example. Below is an attempt to add raycaster to scale over the terrain. All code is in the animate function in project. I noticed that when the camera attempts to scale up the terrain. If too steep, it will go straight through. Also, it doesn't follow the terrain as it drops. The camera remains at the highest position.

var raycaster = new THREE.Raycaster(camera.position.clone(), new THREE.Vector3(0, -1, 0));
raycaster.ray.origin.copy(camera.position);

var intersections = raycaster.intersectObjects( terrain );

if (intersections.length > 0){

    var distance = intersections[0].distance;
    if(distance > 0 && distance < 10){
        camera.position.y= intersections[0].point.y + 20;
    }

}

回答1:

In this snippet:

if(distance > 0 && distance < 10){
    camera.position.y= intersections[0].point.y + 20;
}

...intersections with distance > 10 are ignored, but then the camera moves to +20 above the terrain. I suspect that's why it can't follow terrain as it drops. I'm less sure about the "too steep" issue, but that could be similar... try keeping the raycaster at a height that's above the maximum terrain altitude, rather than at the camera's location.

If the issues persist, you may want to include a live demo or an export of your terrain.



回答2:

Copy the camera.position to a vector and raising vector position.y and setting the raycaster to the vectors.

  var castFrom = new THREE.Vector3();
      var castDirection = new THREE.Vector3(0,-1,0);
      var raycaster = new THREE.Raycaster(camera.position.clone(), new THREE.Vector3(0, -1, 0));
        castFrom.copy(camera.position);
        castFrom.y += 1000;
        raycaster.set(castFrom,castDirection);
    var intersections = raycaster.intersectObjects( terrain );
     if (intersections.length > 0){
       camera.position.y = intersections[0].point.y+20;
       }