Arcgis js+Three.js

Arcgis js+Three.js

一、基本结构

 require([
      'esri/Map',
      'esri/views/SceneView',
      'esri/views/3d/externalRenderers'
    ], function (
      Map,
      SceneView,
      externalRenderers,
      webMercatorUtils,
    ) {
    //场景地图
      var map = new Map({
        basemap: "satellite",
      });

	//场景相机参数
      const view = new SceneView({
        container: 'arcgisContainer',
        map: map,
        camera: {
          position: [116, 40, 250],//相机初始位置
          tilt: 0,
        },
      });

	//引入threejs
      const myRenderer = {
        view: view,
        renderer: null, // three.js 渲染器
        camera: null, // three.js 相机
        scene: null, // three.js 中的场景
        controls: null,

        setup: function (context) {
          this.renderer = new THREE.WebGLRenderer({
            context: context.gl, // 可用于将渲染器附加到已有的渲染环境(RenderingContext)中
            premultipliedAlpha: false, // renderer是否假设颜色有 premultiplied alpha. 默认为true
          });
          this.renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比。通常用于避免HiDPI设备上绘图模糊
          this.renderer.setViewport(0, 0, view.width, view.height); // 视口大小设置

          // 防止Three.js清除ArcGIS JS API提供的缓冲区。
          this.renderer.autoClearDepth = false; // 定义renderer是否清除深度缓存
          this.renderer.autoClearStencil = false; // 定义renderer是否清除模板缓存
          this.renderer.autoClearColor = false; // 定义renderer是否清除颜色缓存

          // ArcGIS JS API渲染自定义离屏缓冲区,而不是默认的帧缓冲区。
          // 我们必须将这段代码注入到three.js运行时中,以便绑定这些缓冲区而不是默认的缓冲区。
          const originalSetRenderTarget = this.renderer.setRenderTarget.bind(
            this.renderer
          );
          this.renderer.setRenderTarget = function (target) {
            originalSetRenderTarget(target);
            if (target == null) {
              // 绑定外部渲染器应该渲染到的颜色和深度缓冲区
              context.bindRenderTarget();
            }
          };

          this.scene = new THREE.Scene(); // 场景
          this.camera = new THREE.PerspectiveCamera(); // 相机

          var scene = this.scene;
          scene.background = new THREE.Color(0xf0f0f0);
          scene.Helpers = new THREE.AxesHelper(0);
          scene.add(scene.Helpers);

          //OrbitControls
          this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement)
          this.controls.enablePan = true
          this.controls.zoomSpeed = 0.6
          this.controls.rotateSpeed = 0.2

          //light
          let props = new THREE.Vector3(100, 300, 200);
          let directionalLight = new THREE.DirectionalLight(0xffffff, 1);

          directionalLight.position.copy(props);
          directionalLight.name = "directionalLight";
          this.scene.add(directionalLight);
          let ambientLight = new THREE.AmbientLight(0x343434);
          ambientLight.name = "ambientLight";
          this.scene.add(ambientLight);

          // 添加坐标轴辅助工具
          const axesHelper = new THREE.AxesHelper(10000000);
          this.scene.Helpers = axesHelper;
          this.scene.add(axesHelper);
          
          context.resetWebGLState();
        },


        render: function (context) {

          // 更新相机参数
          const cam = context.camera;
          this.camera.position.set(cam.eye[0], cam.eye[1], cam.eye[2]);
          this.camera.up.set(cam.up[0], cam.up[1], cam.up[2]);
          this.camera.lookAt(
            new THREE.Vector3(cam.center[0], cam.center[1], cam.center[2])
          );

          // 投影矩阵可以直接复制
          this.camera.projectionMatrix.fromArray(cam.projectionMatrix);

          this.renderer.state.reset();

          this.renderer.render(this.scene, this.camera);

          // 请求重绘视图。
          externalRenderers.requestRender(view);

          // cleanup
          context.resetWebGLState();
        },
      };

      // 注册renderer
      externalRenderers.add(view, myRenderer);

    });

二、添加模型或mesh

 // =====================模型投放=================================
          var gltfLoader = new THREE.GLTFLoader();//obj加载器

          gltfLoader.load('./models/rocket.gltf', function (object) {

            object.scene.scale.set(10, 10, 10);

            object.scene.rotateX(Math.PI * 0.20);//绕x轴旋转
            object.scene.rotateY(Math.PI * 1.1);
            object.scene.rotateZ(-Math.PI * 0.12);
            scene.add(object.scene);

            // 将经纬度坐标转换为xy值\ 模型位置
            let pointXY = lngLatToXY(view, [116, 40, 20]);

            object.scene.position.set(pointXY.vector3List.x, pointXY.vector3List.y, pointXY.vector3List.z);

          })

          // =====================mesh加载=================================

          var geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
          var material = new THREE.MeshLambertMaterial({
            color: 0x0000ff
          }); //材质对象Material
          var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh

          scene.add(mesh); //网格模型添加到场景中

           // 将经纬度坐标转换为xy值\ 模型位置
           let pointXY = lngLatToXY(view, [116.001, 40, 20]);

          mesh.scale.set(0.1, 0.1, 0.1);
          mesh.position.set(pointXY.vector3List.x, pointXY.vector3List.y, pointXY.vector3List.z);
          
          //======================================================

          //经纬度坐标转成三维空间坐标
          function lngLatToXY(view, points) {

            let vector3List; // 顶点数组

            let pointXYs;

            require([
              'esri/views/3d/externalRenderers',
              'esri/geometry/support/webMercatorUtils',
            ], function (
              externalRenderers,
              webMercatorUtils
            ) {

              // 计算顶点
              let transform = new THREE.Matrix4(); // 变换矩阵
              let transformation = new Array(16);

              // 将经纬度坐标转换为xy值\
              let pointXY = webMercatorUtils.lngLatToXY(points[0], points[1]);

              // 先转换高度为0的点
              transform.fromArray(
                externalRenderers.renderCoordinateTransformAt(
                  view,
                  [pointXY[0], pointXY[1], points[2]], // 坐标在地面上的点[x值, y值, 高度值]
                  view.spatialReference,
                  transformation
                )
              );

              pointXYs = pointXY;

              vector3List =
                new THREE.Vector3(
                  transform.elements[12],
                  transform.elements[13],
                  transform.elements[14]
                )
            });

            return {
              vector3List: vector3List,
              pointXYs: pointXYs
            };
          }

效果图

在这里插入图片描述
地址:https://gitee.com/imyang1998/Webgl-learning-experience

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

imyang_123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值