获取地形的高度(y)坐标为Three.js

时间:2015-02-17 18:33:12

标签: javascript 3d three.js terrain

我有一个Collada模型的地形。我需要在我的地形上添加其他模型。为此,我想我需要通过x和z坐标获得地形的高度坐标(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] http://i.stack.imgur.com/bZqE4.jpg

1 个答案:

答案 0 :(得分:0)

获得高度图图像数据后,需要像这样读取像素:

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个像素,读取高度图颜色值。假设像素值在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。从THREE.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.z替换v.y.

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

完成之后,你需要巩固这些变化:

geometry.verticesNeedUpdate = true;