AR室内导航-Three.js

这篇具有很好参考价值的文章主要介绍了AR室内导航-Three.js。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

如有不明白的可以加QQ:2354528292;wx: aichitudousien
更多教学视频请访问:https://space.bilibili.com/236087412
源码获取:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.3c3a645ebB8H6o&ft=t&id=714574529746

这一次的AR室内导航是使用蜂鸟云地图加上three.js做的,具备室内楼层切换,2D/3D模型切换,指北针控件,AR开启/关闭。模拟室内导航的功能,先来看看视频效果

AR室内导航

初始化室内地图

初始化蜂鸟云室内地图很简单,使用的也是蜂鸟云自带的地图数据
vue文件中调用mapCreate创建地图

this.$nextTick(() => {
        this.mapCreate();
});

地图配置参数,需要自己去创建key值

options: {
          appName: '蜂鸟研发SDK_2_0',
          key: '',
          mapID: '1321274646113083394',
          // 缩放级别
          mapZoom: 20,
          // 显示楼层
          visibleLevels: [1, 2, 3, 4, 5],
          // 默认显示几楼
          level: 3
        }

window.map = new fengmap.FMMap(this.options);

此时地图创建显示成功
AR室内导航-Three.js

创建楼层控件

地图创建完成后生成楼层控件,指北针,导航控件

//监听地图加载完成
        map.on('loaded', () => {
          //创建导航对象
          this.creatNavigation();
          //创建楼层控件
          this.creatFloorControl();
          //创建指北针控件
          this.creatCompassControl();
        });

楼层控件

creatFloorControl() {
        let toolbar = new fengmap.FMToolbar({
          //默认在右上角
          position: fengmap.FMControlPosition.RIGHT_TOP,
          //初始是否是多层显示,默认单层显示
          allLayer: false,
          //是否显示多层/单层切换按钮
          needAllLayerBtn: true,
          //控件位置x,y的偏移量
          offset: {
            x: -10,
            y: 320
          }
        });
        toolbar.addTo(map);
      },

指北针

let compass = new fengmap.FMCompass({
          position: fengmap.FMControlPosition.LEFT_TOP,
          width: 40,
          height: 40,
          offset: {
            x: 12,
            y: 460
          }
        });
        compass.addTo(map);
        compass.on('click', function() {
          map.setRotation({
            rotation: 0,
            animate: true,
            duration: 0.3
          });
        });

导航控件

// FMNaviAnalyser 是可分析最短路径、最快路径并返回分析结果的路径类。可独立于地图工作,支持Web Worker 和 Node
        let analyser = new fengmap.FMNaviAnalyser(
          this.options,
          function() {
            // FMNavigation 是导航相关的功能类, 可用于模拟导航和真实导航使用
            window.navi = new fengmap.FMNavigation({
              map: map,
              analyser: analyser,
              locationMarkerUrl: './img/导航.png',
              locationMarkerSize: 32
            });
          },
          (error) => {
            console.log(error);
          }
        );

AR室内导航-Three.js
此时就可以切换楼层显示和控制2D/3D转换

导航

一个输入开始地址和结束地点的UI,随便写写就ok
AR室内导航-Three.js
然后需在地图点击时输入起始点和终点,需要在地图上绑定点击事件
isNavBoxShow 为组件显示状态,startPointSelect 为起始点状态,endPointSelect 为结束点状态

// //路径规划
        map.on('click', (event) => {
          if (this.$store.state.isNavBoxShow === true) {
            if (this.$store.state.startPointSelect === true) {
              window.routeOpiton.start = {
                x: event.coords.x,
                y: event.coords.y,
                level: event.targets[0].level,
                url: './img/start.png',
                height: 3
              };
              navi.setStartPoint(window.routeOpiton.start);
              if (event.targets[0].name) {
                document.getElementById('startInput').value = event.targets[0].name;
              } else {
                document.getElementById('startInput').value = '当前起点位置';
              }
              this.$store.commit('startPointSelectFalse');
            } else if (this.$store.state.endPointSelect === true) {
              window.routeOpiton.end = {
                x: event.coords.x,
                y: event.coords.y,
                level: event.targets[0].level,
                url: './img/end.png',
                height: 3
              }
              navi.setDestPoint(window.routeOpiton.end);

              if (event.targets[0].name) {
                document.getElementById('endInput').value = event.targets[0].name;
              } else {
                document.getElementById('endInput').value = '当前终点位置';
              }
              this.$store.commit('endPointSelectFalse');
            }
          }
        });

此时我们点击地图模块就可以输入起始点和结束点了
AR室内导航-Three.js
点击确定后调用路径计算函数
window.routeOpiton 为起始点和结束点对象

navi.route(window.routeOpiton, function(result) {
          let line = navi.drawNaviLine();
          let coordinates = [];
          result.subs.forEach(item => {
            item.waypoint.points.forEach(point => {
              coordinates.push(point)
            })
          });
 })

AR室内导航-Three.js

使用Three.js 生成AR模块原理

说明一下生成步骤,第一步同样是先验证是否能打开摄像头,然后初始化Three.js,然后将摄像头的视频流使用video贴图map到three.js的背景中,这样就可以呈现了,然后怎么在场景中显示路径呢,也不难,蜂鸟云的api会返回一条最短路径的数组,通过这个最短路径的数据我们就可以计算,首先判断每一个点之间的距离是否大于1,如何计算两点之间的距离呢,通过两点的的平方开根就好了,计算出后大于1的就是存在有转角的,这时我们就要计算角度了,角度通过反正切来计算,这里需要注意的是轴的旋转方向,最后在监听陀螺仪来改变生成的点和线的角度就可以了,整体来说思路ok了接下来就是变成代码就行了,实现代码不难,主要是思路~

初始化Three

//初始参数
    canvas = document.getElementById('webGL3d')
    arWidth = canvas.offsetWidth
    arHeight = canvas.offsetHeight
    scene = new THREE.Scene()
    camera = new THREE.PerspectiveCamera(60, arWidth / arHeight, 0.0001, 7000)
    camera.position.set(0, -7, 5)
    // //renderer参数
    let renderParam = {
      antialias: true, // true/false表示是否开启反锯齿
      // alpha: true, // true/false 表示是否可以设置背景色透明
      precision: 'highp', // highp/mediump/lowp 表示着色精度选择
      premultipliedAlpha: false, 
      maxLights: 3, 
      canvas: canvas 
    }
    renderer = new THREE.WebGLRenderer(renderParam)
    renderer.setSize(arWidth, arHeight)
    orbitControls = new OrbitControls(camera, renderer.domElement)

判断是否支持摄像头并返回视频流,这里有一个小细节,判断是否是手机还是PC,手机强制使用后置摄像头

let video = document.createElement('video');
  // navigator.mediaDevices.getUserMedia 提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。

  const stream = await navigator.mediaDevices.getUserMedia({
    // 关闭音频
    audio: false,
    video: {
      // 在移动设备上面,表示优先使用前置摄像头
      // facingMode: 'user',
      facingMode: isMobile() ? { exact: "environment" } : 'user',
      width: width,
      height: height
    }
  });

  video.srcObject = stream;
  video.play();
  video.width = width;
  video.height = height;

  return new Promise((resolve) => {
    // 在视频的元数据加载后执行 JavaScript
    video.onloadedmetadata = () => {
      resolve(video);
    };
  });
function isMobile() {
  const isAndroid = /Android/i.test(navigator.userAgent);
  const isiOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
  return isAndroid || isiOS;
}

获取到视频流后将视频贴到three.js的背景中

let video = await openCamera(arWidth, arHeight);
    console.log(video);
    videoTexture = new THREE.Texture(video);
    videoTexture.minFilter = THREE.LinearFilter;
    scene.background = videoTexture;

这里我们就可以在看到视频了
接着我们创建一个起始点标记

let plane = new THREE.PlaneGeometry(1, 1)
    let map = new THREE.TextureLoader().load(require('@/assets/img/WechatIMG1129.png'))
    let material = new THREE.MeshBasicMaterial({
      map: map,
      alphaTest: 0.1,
      color: 0xffffff,
      side: THREE.DoubleSide,
    })
    nowPosPic = new THREE.Mesh(plane, material)
    nowPosPic.position.set(0, offsetY, 0)
    scene.add(nowPosPic)
    //添加坐标轴
    let axes = new THREE.AxesHelper(500)
    scene.add(axes)

AR室内导航-Three.js
绘制导航线

if (coordinates.length !== 0) {
      group = new THREE.Group()
      let starPoint = {
        x: 0,
        y: 0
      }
      for (let i = 1; i < coordinates.length; i++) {
        let x = coordinates[i].x - coordinates[0].x
        let y = coordinates[i].y - coordinates[0].y
        // 计算两点的距离
        let distance = Math.sqrt(Math.pow(x - starPoint.x, 2) + Math.pow(y - starPoint.y, 2))
        if (distance >= 1) {
        // 计算弧度
          let angle = calAngleX(x - starPoint.x, y - starPoint.y)
          // 生成线
          createLine(starPoint, distance, angle)
          starPoint.x = x
          starPoint.y = y
        }
      }
      scene.add(group)
      group.position.y = offsetY
      group.rotation.z = -alpha * Math.PI / 180
    }

计算弧度代码

//计算偏转角度(X逆时针)
  function calAngleX(x, y) {
    let angle = Math.atan(Math.abs(y) / Math.abs(x))
    if (x >= 0 && y >= 0) {

    } else if (x <= 0 && y >= 0) {
      angle = Math.PI - angle
    } else if (x <= 0 && y <= 0) {
      angle = Math.PI + angle
    } else {
      angle = Math.PI * 2 - angle
    }
    return angle
  }

生成线

let plane = new THREE.PlaneGeometry(1, 1)
    let map = new THREE.TextureLoader().load(require('@/assets/img/WechatIMG1123.png'))
    let material = new THREE.MeshBasicMaterial({
      map: map,
      alphaTest: 0.1,
      color: 0xffffff,
      side: THREE.DoubleSide,
    })
    for (let i = 0.6; i <= length; i++) {
      let mesh = new THREE.Mesh(plane, material)
      let x = starPoint.x + i * Math.cos(angle)
      let y = starPoint.y + i * Math.sin(angle)
      mesh.position.set(x, y, 0)
      let obj = {
        x: x + coordinates[0].x,
        y: y + coordinates[0].y
      }
      lingMeshArray.push(obj)
      mesh.rotation.z = angle - Math.PI / 2
      group.add(mesh)
    }

到这里就可以看到生成的线了
AR室内导航-Three.js
监听陀螺仪window.DeviceOrientationEvent
window.DeviceOrientationEvent说明
DeviceOrientationEvent.absolute 只读
用来说明设备是提供的旋转数据是否是绝对定位的布尔值。
DeviceOrientationEvent.alpha 只读
一个表示设备绕z轴旋转的角度(范围在0-360之间)的数字
DeviceOrientationEvent.beta 只读
一个表示设备绕x轴旋转(范围在-180到180之间)的数字,从前到后的方向为正方向。
DeviceOrientationEvent.gamma 只读
一个表示设备绕y轴旋转(范围在-90到90之间)的数字,从左向右为正方向。
throttle只是节流函数

if (window.DeviceOrientationEvent) {
      window.addEventListener('deviceorientation', throttle(setMeshCamera, 100), false)
    } else {
      console.log('你的浏览器不支持陀螺仪')
    }

最后根据陀螺仪计算起始点和线的旋转角度就可以了文章来源地址https://www.toymoban.com/news/detail-400003.html

到了这里,关于AR室内导航-Three.js的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于视觉重定位的室内AR导航APP的大创项目思路(1):最初的项目思路(SLAM)

    前情提要: 是第一次做项目的小白,文章内的资料介绍如有错误,请多包含! 由于我们在日常生活中,大多会在手机端上使用到地图导航这一功能,所以在大创项目的开始, 我将手机确定为应用设备,传感器确定为相机 。 但是因为知识储备较为稀少,对SLAM不够了解,在头

    2024年02月09日
    浏览(38)
  • 基于视觉重定位的室内AR导航项目思路(2):改进的建图和定位分离的项目思路

    前情提要: 是第一次做项目的小白,文章内的资料介绍如有错误,请多包含! 不知道在线建图是否有其他方法,但是我只尝试过使用ORB-SLAM3进行在线建图,这或许是一个可以再进行思考的要点。 可以采用以下两种想法进行建图: 1、在 电脑端 运行ORB-SLAM3实时调用手机摄像头

    2024年02月09日
    浏览(44)
  • three.js实现3D室内全景看房

    首先我们先搭建一个项目,我选择使用vite来进行项目的搭建,执行命令如下: 这样一个基本的项目就搭建成功了,目录如下所示 然后,下载一下three.js工具,执行如下命令 页面中引入 先搭建一个立体图形,并画出辅助线,如下所示  实现代码如下: 接着,给我们的立体图

    2024年02月12日
    浏览(49)
  • 基于视觉重定位的室内AR导航APP的大创项目思路(3)手机相机内参数据获取和相机标定

    前情提要: 是第一次做项目的小白,文章内的资料介绍如有错误,请多包含! 相机内参是本身的物理数据,包括焦距f和缩放c,一般以矩阵K的形式存放和使用 1.相机的内参数据在建图的时候就需要使用,SLAM中需要根据相机内参数据结合传入的图像数据等进行建图,不然无法

    2024年02月09日
    浏览(54)
  • web 3d场景构建+three.js+室内围墙,仓库,楼梯,货架模型等,第一人称进入场景案例

      翻到了之前的一个案例,基于three.js做的仓库布局模拟,地图元素除了大模型外,其他都是通过JSON数据解析动态生成的,例如墙体,柱子门口,地标等,集成了第一人称的插件可以第一人称进入场景有需要的可以下载看看,对想入门的朋友应该有一些参考价值。 /**    *创

    2024年02月10日
    浏览(57)
  • 微信小程序3D,使用Three.js在微信小程序中展示gltf模型,使用VisionKit展示AR能力

    本仓库只开源gltf模型展示技术,技术好的朋友有这些代码就能帮助你解决很多问题了 如需要完整项目(基于若依框架开发的后端,AR能力前端)需另外付费赞助, 联系方式:QQ 790002517 微信公众号:时不待我 https://github.com/zzy-life/Wechat3D Three.js Three.js is a JavaScript 3D library. thr

    2024年02月09日
    浏览(47)
  • 网站登录界面制作(three.js 3D特效背景)+ boostrap导航栏实现 + jQuery移动窗口【附加源代码】

    学过Web前端的许多小伙伴都会面对门户网站制作的大作业报告,这里给大家分享一下我的前端大作业。后续还会继续更新,喜欢的小伙伴可以点个赞。 注意上述为动态界面: 下面的是表单的JS源代码: 下面是3D动态例子的源代码: 注意中间的窗口是移动的; 下面是移动窗口

    2024年02月07日
    浏览(54)
  • 除了three.js,还有许多其他前端开发语言和库可以用于创建3D可视化大屏

    hello老铁们...本人熟悉html5,vue对bootsrap,uniapp,layui,element,vite,antd,echarts,jq响应式尤其擅长,ui设计等技能,如果ui前端工作中有遇到烦恼可私信关注评论我们共同交流进步!谢谢       随着前端技术的飞速发展,3D可视化已经成为许多应用场景中不可或缺的一部分。在

    2024年03月15日
    浏览(72)
  • 揭秘蓝牙定位技术,实现精准室内导航

    提及定位,我们首先想到的是GPS定位系统。然而,GPS主要适用于室外环境,在室内定位方面存在局限性,这主要归结于两个原因:首先,GPS信号功率极低,接收要求相当高,只有在天线对空无遮挡物的情况下才能接收到卫星信号并实现定位;其次,由于现代建筑材料的特性,

    2024年02月07日
    浏览(51)
  • AI:130-基于深度学习的室内导航与定位

    🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲

    2024年02月20日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包