获取地形's高度(y)坐标Three.js

Getting terrain's height (y) coordinate Three.js

本文关键字:坐标 js Three 高度 获取      更新时间:2023-12-13

我有一个地形作为Collada模型。我需要在我的地形上添加其他模型。为此,我想我需要通过x和z坐标获得地形的高度coord(y)。请告诉我该怎么做?

var scene, camera, renderer;
        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
        var directionVector = new THREE.Vector3();
        var projector = new THREE.Projector();
        var map =
                {
                    'name': 'map1.dae',
                    'x': -42.1,
                    'y': 54,
                    'z': 0
                }
                ;
        var mapModel;
        var mapLoader = new THREE.ColladaLoader();
        mapLoader.options.convertUpAxis = true;
        mapLoader.load( map.name, function ( collada ) {
            mapModel = collada.scene;
            mapModel.position.set(map.x,map.z,map.y);//x,z,y- if you think in blender dimensions ;)
            mapModel.rotation.y = 0.002;
            init();
            animate();
        });
        function init() {
            scene = new THREE.Scene();
            var WIDTH = window.innerWidth,
                    HEIGHT = window.innerHeight;
            renderer = new THREE.WebGLRenderer({antialias:true});
            renderer.setSize(WIDTH, HEIGHT);
            renderer.setClearColor( 0xeeeeee, 1.0 );
            document.body.appendChild(renderer.domElement);
            camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
            camera.position.set(150,450,300);
            scene.add(camera);
            window.addEventListener('resize', function() {
                var WIDTH = window.innerWidth,
                        HEIGHT = window.innerHeight;
                renderer.setSize(WIDTH, HEIGHT);
                camera.aspect = WIDTH / HEIGHT;
                camera.updateProjectionMatrix();
            });
            window.addEventListener('click',onMouseClick);
            window.addEventListener('mouseMove',onMouseMove);
            var axes = new THREE.AxisHelper( 1580 );
            scene.add(axes);
            var gridXZ = new THREE.GridHelper(1000, 10);
            gridXZ.setColors( new THREE.Color(0xff0000), new THREE.Color(0xff0000) );
            gridXZ.position.set(0,0,0 );
            //red axe 0.00001565217 - CONST в 1 метре, градусов     blue axe 0.000009
            scene.add(gridXZ);
            scene.add(mapModel);
            var light = new THREE.PointLight(0xfffff3, 0.8);
            light.position.set(-300,600,300);
            scene.add(light);
            var sphereSize = 1;
            var pointLightHelper = new THREE.PointLightHelper( light, sphereSize );
            scene.add( pointLightHelper );
            var light2 = new THREE.PointLight(0xd7f0ff, 0.2);
            light2.position.set(600,600,200);
            scene.add(light2);
            var sphereSize = 1;
            var pointLightHelper2 = new THREE.PointLightHelper( light2, sphereSize );
            scene.add( pointLightHelper2 );
            var light3 = new THREE.PointLight(0xFFFFFF, 0.5);
            light3.position.set(300,400,-200);
            scene.add(light3);
            var sphereSize = 1;
            var pointLightHelper3 = new THREE.PointLightHelper( light3, sphereSize );
            scene.add( pointLightHelper3 );

[图像][1]https://i.stack.imgur.com/bZqE4.jpg

一旦你有了高度图图像数据,你需要像这样读取像素:

http://www.w3schools.com/tags/canvas_getimagedata.asp

这种方法将把你的图像转移到画布上,在那里你可以进行imageData查找,看看每个像素的RGBA值是多少

var imgData = context.getImageData(0,0,canvas.width,canvas.height);
function lookUpPixelColor( imageData, ux, uy ){
  var px = Math.floor( ux * imageWidth );
  var py = Math.floor( uy * imageHeight );
  var index = (uy * imageWidth + ux) * 4;
  if( index < 0 || index >= imageData.data.length ){
    return 0;
  }
  return {
    r: imageData.data[ index ] ,
    g: imageData.data[ index + 1 ],
    b: imageData.data[ index + 2 ]
  };
}

该函数现在将用于查找0到1之间的任何像素。

然后,对于每个像素或第n个像素,读取heightmap颜色值。假设灰度图像的像素值在0-255之间,则可以有那么多"级别"的高程,因此255将是最高的峰值,0将是尽可能低的值。

既然你已经完成了,你就可以在平面中的每个顶点上循环,并求解查找:

geometry.vertices.forEach( function( v ){
  var ux = v.x / planeWidth;
  var uy = v.y / planeHeight;
  var rgb = lookUpPixelColor( imageData, ux, uv );
  var height = rgb[ 0 ] / 255;
  var z = height * maxHeight;
  v.z = z;
});

这假设平面几何体的第一个顶点为0,0,并转到planeWidth/planeHeight。从THRE.js生成的PlaneGeometry可能不是这样,因为它可能是从-width/2到width/2

所以它看起来像:

geometry.vertices.forEach( function( v ){
  var ux = (v.x + planeWidth * 0.5) / planeWidth;
  var uy = (v.y + planeHeight * 0.5) / planeHeight;
  var rgb = lookUpPixelColor( imageData, ux, uv );
  var height = rgb[ 0 ] / 255;
  var z = height * maxHeight;
  v.z = z;
});

另一个奇怪的地方是,平面可能是沿着XZ而不是XY生成的,所以如果是这种情况,那么在查找过程中只需将v.y替换为v.z。

或者,可以使用faceVertexUVs中的UV进行查找,其中值可以很好地设置为从0到1

完成后,你需要巩固这样的变化:

geometry.verticesNeedUpdate = true;