【AR开发示例】实现AR管线巡检

写在前面的话

这是一篇旧文档,代码仓库见 https://gitee.com/tanyunxiu/AR-pipe

本文档是基于超图移动端SDK的AR模块开发的示例,仅供参考,SDK在持续迭代中,相关描述可能有变化。

示例介绍

这是一个使用AR查看墙内管线的基础示例程序。

涉及的关键词:SuperMap iMobile for Android、深度遮挡、ARCore、AREngine

数据准备

数据格式

本示例所使用到的管线模型格式为:gltf2.0 、gltf2.0介绍

示例数据

示例数据位于ar_occlusion\sampledata\PipeData.zip中

数据制作

  1. 使用blender制作模型(或在blender中导入模型)

为了防止在模型批量导出的过程中出现错误,请参考下图的场景集合的层级结构。

由于示例程序中采用OBB有向包围盒( 它是包含该对象且相对于坐标轴方向任意的最小的长方体 )的方式用于射线检测。为了在示例程序中能够准确点击模型,请通过将模型拆分成单个实体对象的方式,确保模型的冗余空间尽可能地小。

模型导入

  1. 批量导出模型

在菜单栏->"Scripting"中新建脚本,内容如下:

# exports each selected object into its own file
import bpy
import os

# export to blend file location
basedir = r"E:\3d\top_pipe\\"

if not basedir:
    raise Exception("Blend file is not saved")

view_layer = bpy.context.view_layer

obj_active = view_layer.objects.active
selection = bpy.context.selected_objects

bpy.ops.object.select_all(action='DESELECT')

for obj in selection:

    obj.select_set(True)

    # some exporters only use the active object
    view_layer.objects.active = obj

    name = bpy.path.clean_name(obj.name)
    fn = os.path.join(basedir, name)

    #bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
    bpy.ops.export_scene.gltf(filepath=fn, export_format="GLB", export_lights=False, use_selection=True)

    obj.select_set(False)

    print("written:", fn)

view_layer.objects.active = obj_active

for obj in selection:
    obj.select_set(True)

print("All save completed!")
  1. 选中场景集合中所有模型,执行脚本,导出模型。

批量导出脚本

  1. 查看模型文件夹。

模型组

  1. 至此,数据准备阶段已完成。

在后续构建的AR场景中,通过点击交互就可以查询出模型的名称。(Mesh2、Mesh3、Line…)。

若是需要通过点击交互,查询模型的其他属性信息(诸如规格、连接类型这些信息)。可通过创建一张属性表,建立模型名称与属性字段的一一对应的关系。通过查询模型名称,进而去查询对应的属性值。

属性查询

运行流程

开发环境

  • IDE:Android Studio 2021
  • Android Gradle Plugin Version:4.1.2
  • Gradle Version:6.5

注意事项:

Gradle 7.0版本后,请参考Android官方对于Gradle版本与Gradle插件的配套关系,把Gradle插件版本也升级到7.0及以上。

iMobile SDK

使用SuperMap移动GIS的iMobile for Android 的SDK 下载链接

示例程序涉及SDK中的以下so 和 jar

  • libimb2d_1100.so
  • com.supermap.data_v1100.jar
  • com.supermap.ar_v1100.jar
  • scenefrom-sm-11.0.1.aar

在工程中导入iMboile的AR模块

产品包

模块的build.gradle配置如下

plugins {
    id 'com.android.application'
}

android {
    compileSdk 28

    defaultConfig {
        applicationId "com.supermap.samplecode.occlusiondemo"
        minSdk 24
        targetSdk 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        ndk{
        	//注意使用的产品包是32位还是64位
            abiFilters 'armeabi-v7a'
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

    //SuperMap Data模块
    implementation files('libs/com.supermap.data_v1100.jar')
    //SuperMap AR模块
    implementation files('libs/com.supermap.ar_v1100.jar')

    //渲染框架
    implementation files('libs/sceneform-sm-11.0.1.aar')
    //第三方工具类
    implementation files('libs/eqtool-1.3.0.jar')
}

运行示例

  1. 许可设置

    此示例程序使用的是离线使用许可。

    在src/main/assets/目录下,默认存放一个试用许可"SuperMapiMobileTrial.slm"。在程序初次启动时,会拷贝至手机对应文件夹(…/PipeData/license)下。

    若许可过期或不可用,请先申请许可,然后拷贝至手机对应文件夹(…/PipeData/license)下,或在assets目录进行替换。

    注意:

    许可过期或不可用,会出现如下报错信息:

错误信息

若许可可用,仍出现上述异常信息,请从以下方面进行自查。

  • 使用的so与jar不是同一个产品包的产物
  • 申请的许可与对应产品包的版本不一致
  • 手机未开启存储读写权限
  1. 导入工程

方式一
打开工程

导入工程

指定对应文件夹

导入工程

方式二
在现有工程的settings.gradle中添加配置,实现模块导入

include ':ar_occlusion'
project(':ar_occlusion').projectDir=new File('D:\\OcclusionDemo')
  1. 导入模型数据

将模型数据拷贝至手机目录/SuperMap/PipeData。

具体路径配置,参考PathConfig.java

public static final String SD_CARD = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();

/**
* 数据文件夹根路径
* MI 9 Transparent Edition\内部存储设备\SuperMap\PipeData
*/
public static final String PIPE_DATA_PATH = SD_CARD + "/SuperMap/PipeData";

/**
* 屋顶通风管道模型组文件夹路径
*/
public static String TOP_PIPE_DATA = PIPE_DATA_PATH + "/Model/top_pipe";

/**
* 地下管线模型组
*/
public static String UNDERGROUND_PIPE_DATA = PIPE_DATA_PATH + "/Model/underground_pipe";

/**
* 垂直墙面内的管线数据
*/
public static String VERTICAL_PIPE_DATA = PIPE_DATA_PATH + "/Model/pipe_v";
  1. 运行示例

运行示例程序

run

程序运行成功后,会在手机SuperMap/PipeData生成以下内容

  • ImgData
  • license
  • Log
  • app.cfg

run

app.cfg(default.cfg)、ImgData(包含一张名为“mark.png”的图片)可在工程的assets目录下找到

run

  1. 示例程序使用流程
  • 打印“mark.png”,将其布置在场景中

  • 启动程序,进入主界面

使用流程

  • 点击 “定位”,扫描“mark.png”,加载场景

使用流程

  • 点击 “视口模式”,行走浏览

    可通过手势调节开挖参数,具体操作见程序演示

  • 点击"卷帘模式",行走浏览

    可通过手势调节显示范围,具体操作见程序演示

代码定位

场景加载

实现通过扫码的方式加载场景。

见MarkerConfig,涉及Marker的初始位置、图片资源路径的相关信息。

见ScanLayout,涉及布局设置和图片识别相关的接口(ImageScanner)调用。

/**
* 开启图片扫描功能
* @param arEffectView AR视图
* @param callback 扫描结果回调
*/
public void startImageScan(AREffectView arEffectView,ScanCallback callback){
    //...
}

/**
* 结束图片扫描
* @param arEffectView AR视图
*/
private void stopScan(AREffectView arEffectView) {
        //...
}

见DataManager,涉及数据的加载.

/**
* 添加管线场景
* @param parent 父节点
* @param dataPath 数据路径
* @param enabled 启用点击交互
* @param type 数据类型
*/
public void addPipeScene(AREffectElement parent,String dataPath,boolean enabled,Type type){
	//...
}

/**
* 添加管线场景
* @param parent 父节点
* @param dataPath 数据路径
* @param enabled 启用点击交互
*/
public void addPipeScene(AREffectElement parent,String dataPath,boolean enabled) {
	//...
}

视口模式

实现在视口模式下,对墙内管线模型进行开挖显示。

见ViewportFuncLayout,涉及布局设置。

见ExcavatorManager,涉及开挖参数的计算、坑洞对象渲染和屏幕显示范围构成的点集的更新。

private EffectView.OnUpdateListener onUpdateListener = new OnUpdateListener() {
    @Override
    public void onUpdate() {
        //开挖参数计算->坑洞对象渲染->更新屏幕显示范围构成的点集
    }

卷帘模式

实现类似卷帘的效果。

实现原理上,比视口模式更简单。直接根据分割线计算出屏幕显示范围构成的点集即可。

见RollingFuncLayout,涉及布局设置。

屏幕范围裁剪

见ScreenPointManager,统一管理屏幕显示范围构成的点集,当点集更新时,触发update回调。在回调事件里执行屏幕范围裁剪。

//在PipeActivity中
ScreenPointManager.getInstance().setOnUpdatePointListener(new ScreenPointManager.OnUpdatePointListener() {
    @Override
    public void update(List<ArrayList<int[]>> screenPoint,List<ArrayList<int[]>> bottomScreenPoint) {
    	//...裁剪屏幕显示范围
    }
});

开挖参数调节

在视口模式中,涉及通过手势去修改开挖参数。

在最初的版本中,是通过SeekBar的方式去修改开挖参数。

参数修改

参数修改

当前版本修改为通过手势去修改开挖参数。

参数修改

见CustomGesture,涉及单指、双指手势的定义。
见DigGestureManager,涉及开挖参数修改的手势管理。

见DynamicView,在布局上位于最顶部,用于接收MotionEvent,分发onTouch事件。

@Override
public boolean onTouch(View v, MotionEvent event) {
	//...
}

程序演示

注: 以下内容非最终成果,仅是迭代过程中的录屏。且对应模型数据需要结合对应场景,才可正确地显示。

v1.0

示例程序的录屏

补充说明

实现方式

对每一帧显示的AR内容进行裁剪的方式来实现只显示坑洞范围内的AR内容。

在EffectView#OnUpdateListener的onUpdate事件中,重复执行以下步骤。

  • 构建开挖参数ExcavationParameter
  • Excavator#generateHitPoint 生成碰撞点
  • Excavator#calculate 根据开挖参数进行计算
  • PitObject#updateMesh 更新坑洞对象的网格
  • OcclusionHelper#setUniquePointList 设置屏幕裁剪的范围
  • OcclusionHelper#refresh 刷新

简单示例

//遮挡设置
occlusionHelper = arView.getOcclusionHelper();
occlusionHelper.init(0.36f)
    .setRenderMode(OcclusionHelper.RenderMode.NORMAL);
  
List  roomBounds = Arrays.asList(
    new Point3D(-1, -1, -2),
    new Point3D(-1, 6, -2),
    new Point3D(6, 6, -2),
    new Point3D(6, -1, -2),
    new Point3D(-1, -1, -2)
);

//采用ARGeoPrism,构建“检测墙”
ARGeoPrism geoVerticalRegion = new ARGeoPrism();
geoVerticalRegion.setParentNode(arView);
//仅用作射线检测,渲染状态设置为false
geoVerticalRegion.setRenderable(false);
geoVerticalRegion.addPart(roomBounds,6.0f);

//创建开挖工具,在这之前,需确认AREffectView开启了遮挡设置
//Excavator所有子类使用方法一致
excavatorWall = new WallExcavator(geoVerticalRegion);
//坑洞纹理
Bitmap bitmap=null;
Bitmap bitmap2=null;
try {
    InputStream is = getApplicationContext().getAssets()
        .open("brown_mud_dry2.png");
    bitmap= BitmapFactory.decodeStream(is);
    InputStream is2 = getApplicationContext().getAssets()
        .open("wall_texture.png");
    bitmap2= BitmapFactory.decodeStream(is2);
    is.close();
    is2.close();
} catch (IOException e) {
}

//创建坑洞渲染对象
pitWall = new PitObject(excavatorWall)
    .setTexture(bitmap,bitmap2);
  

//在每一帧刷新时调用(通常使用EffectView.addOnUpdateListener(EffectView.OnUpdateListener)添加帧监听事件)
arView.addOnUpdateListener(()->{
    //开挖计算墙面碰撞点 arView为AREffectView、screenPointX/Y为对应的屏幕坐标
    //以屏幕中心计算碰撞点
    Point3D hitPoint = excavatorWall
                .generateHitPoint(arView, screenPointX, screenPointY);
    if (hitPoint!=null){
        //desc-执行开挖的顶点计算(开挖参数)
        excavatorWall.calculate(ExcavationParameter.builder()
                                .setRadius(radius)
                                .setOffset(offset)
                                .setInnerMargin(0)
                                .setCenterPoint(hitPoint)
                                .build());
    }
    //渲染坑洞结果
    pitWall.updateMesh();
                                  
    if (occlusionHelper.isEnabled()){
        //desc-执行画面裁剪
        ArrayList  screenPoint = null;
        if (excavatorWall !=null){
            //计算屏幕坐标
            screenPoint = excavatorWall.getScreenPoint(null);
            if (screenPoint!=null){
                //根据屏幕坐标刷新裁剪范围
                occlusionHelper.setUniquePointList(screenPoint).refresh();
            }
        }
    }
})

AR开发专栏

原生开发?就用这做AR

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/554388.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

授权协议OAuth 2.0之除了授权码许可还有什么授权流程?

写在前面 源码 。 本文看下OAuth2.0的另外3中授权流程&#xff0c;资源拥有者凭据许可&#xff0c;客户端许可&#xff0c;隐式许可。分别看下具体的使用流程以及该使用场景。 1&#xff1a;资源拥有者凭据许可 资源拥有者凭据许可&#xff0c;这里资源拥有者的凭据是什么呢&…

【C++核心】面向对象的三大特性

面向对象的三大特性 一、封装性1. 封装性的意义1.1 表现事物1.2 权限控制1.3 成员属性设置为私有 2. 封装性的衍生知识2.1 struct和class区别2.2 友元2.2.1 全局函数做友元2.2.2 类做友元2.2.3 成员函数做友元 二、继承性1. 继承的语法2. 继承方式3. 继承中的对象模型3.1 说明3…

17 如何查看Hadoop中wordCount源码

1.进入官网下载源码并进行解压操作&#xff1a; 我们使用的是hadoop-3.1.4版本&#xff0c;直接进入官网进行下载&#xff1a;https://archive.apache.org/dist/hadoop/common/hadoop-3.1.4/ 下载得到的文件如下图所示&#xff1a; 解压后的文件&#xff1a; 2.使用Idea打开此项…

vue3.0项目生成标签条形码(插件:jsbarcode)并打印(插件:Print.js)支持pda扫码枪扫描

文章目录 功能场景生成条形码设置打印功能踩坑 功能场景 功能场景&#xff1a;供应链中对一些货品根据赋码规则进行赋码&#xff0c;赋码之后生成根据赋码结果生成条形码&#xff0c;执行打印功能&#xff0c;贴在货品之上&#xff0c;打印之后可以用pda的手枪进行扫描&#x…

(亲测有效)win7安装nodejs高版本(18.8.0)

现在学习vue3,vite,使用pnpm创建项目都需要高版本的nodejs了&#xff0c;win7最高只能安装13版本&#xff0c;好多已经不支持了。当然此篇只是以安装18.8.0为例&#xff0c;可以替换成更高的18或者20版本&#xff0c;只是太高的话可能出现冲突&#xff0c;够用就好。希望对各位…

如何修改WordPress数据库表前缀以提高安全性

WordPress作为世界上最受欢迎的内容管理系统之一&#xff0c;吸引了数以百万计的用户。然而&#xff0c;正因为其广泛的使用&#xff0c;WordPress网站也成为了黑客攻击的目标之一。其中一个最常见的安全漏洞是使用默认的数据库表前缀wp_&#xff0c;使得黑客能够更轻松地进行大…

分布式调度器

xxl-job介绍 xxl-job 是一个轻量级分布式任务调度框架&#xff0c;支持动态添加、修改、删除定时任务&#xff0c;支持海量任务分片执行&#xff0c;支持任务执行日志在线查看和分页查询&#xff0c;同时支持任务失败告警和重试机制&#xff0c;支持分布式部署和高可用。xxl-j…

亚马逊云科技官方重磅发布GenAI应用开发学习路线(全免费)

今天小李哥给大家分享的是亚马逊云科技&#xff08;AWS&#xff09;最近官方发布的GenAI应用开发最佳学习路线&#xff0c;不仅内容非常全面更主要的是全部免费&#xff01;大家动动小手就能成为GenAI开发大&#x1f42e;&#xff01; 1️⃣这个GenAI开发学习路线包括什么&…

跟着Datawhale重学数据结构与算法(2)———数组知识

数组定义 数组是一种数据结构&#xff0c;用于存储一系列相同类型的元素。在大多数编程语言中&#xff0c;数组中的每个元素都有一个索引&#xff0c;通常从0开始。 数组的特点 固定大小&#xff1a;一旦定义&#xff0c;数组的大小通常是固定的&#xff0c;不能动态增减。相…

虚拟机数据恢复—KVM虚拟机磁盘文件数据恢复案例

虚拟化数据恢复环境&故障&#xff1a; KVM是Kernel-based Virtual Machine的简称&#xff0c;是一个开源的系统虚拟化模块&#xff0c;自Linux2.6.20版本之后集成在Linux的各个主要发行版本中。KVM使用Linux自身的调度器进行管理。 本案例中的服务器操作系统为Linux&#x…

官宣|Apache Paimon 毕业成为顶级项目,数据湖步入实时新篇章!

北京时间 2024 年 4 月 16日&#xff0c;开源软件基金会 Apache Software Foundation&#xff08;以下简称 ASF&#xff09;正式宣布 Apache Paimon 毕业成为 Apache 顶级项目(TLP, Top Level Project)。经过社区的共同努力和持续创新&#xff0c;Apache Paimon 在构建实时数据…

【剪映专业版】10时间线工具:主轨磁吸、自动吸附、联动、预览轴、全局缩放预览

视频课程&#xff1a;B站有知公开课【剪映电脑版教程】 主轨&#xff1a;有封面标志的轨道才是主轨。 主轨磁吸&#xff1a;开启后&#xff0c;在主轨上移动素材&#xff0c;自动向前磁吸&#xff0c;在其他轨道上移动无此效果&#xff1b;关闭后&#xff0c;不自动向前磁吸&…

艾迪比皮具携手工博科技SAP ERP公有云,打造数字化转型新标杆

4月1日&#xff0c;广州市艾迪比皮具有限公司&#xff08;以下简称“艾迪比”&#xff09;SAP S/4HANA Cloud Public Edition&#xff08;以下简称“SAP ERP公有云”&#xff09;项目正式启动。双方项目组领导、成员出席本次项目启动会&#xff0c;为未来项目的顺利实施打下坚实…

Python程序设计 元组和集合

教学案例七 元组和集合 1. 根据年月日计算周几 根据输入的年号、月号、日号&#xff0c;计算是周几(中文、英文) 蔡勒公式 通过蔡勒&#xff08;Zeller&#xff09;公式可计算星期几 w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六 c&…

【hive】lateral view侧视图

文档地址&#xff1a;https://cwiki.apache.org/confluence/display/Hive/LanguageManualLateralView 1.介绍2.语法3.code demo1&#xff09;单重侧视图2&#xff09;多重侧视图3&#xff09;tips&#xff1a;lateral view outer 1.介绍 lateral view也叫侧视图&#xff0c;属…

【electron3】electron将数据写入本地数据库

安装 yarn add sqlite3 --save连接并调用数据库&#xff0c;创建表 createDB.ts文件内容 const sqlite3 require(sqlite3) const NODE_ENV process.env.NODE_ENV const path require(path) const { app } require(electron) let DB_PATH path.join(app.getAppPath(), /…

LDF、DBC、BIN、HEX、S19、BLF、asc、csv、ARXML、slx等(未完待续)

文章目录 如题如题 LDF是LIN报文格式文件,把这个直接拖到软件里面,可以发报文和接收报文 DBC是CAN报文格式文件,把这个直接拖到软件里面,可以发报文和接收报文 BIN文件烧录在BOOT里面(stm32),有人喜欢叫固件,这个固件就是bin文件,bin文件比hex文件体积小 其实BOOT也…

Android apk包使用360加固工具的加固步骤

1&#xff0c;准备好已经签名打包的apk包。 2&#xff0c;在360加固官方网站下载加固exe软件。三六零天御-企业移动应用安全一站式服务平台 3&#xff0c;步骤一&#xff0c;添加加固包&#xff0c;进行加固&#xff0c;并输出加固包&#xff1a; 4&#xff0c;步骤二&#…

预算不足千元SSL证书该怎么选?

随着互联网安全概念日渐深入人心&#xff0c;越来越多的企业或个人为自己的网站加装SSL证书&#xff1b;那对于个人或者小小微企业&#xff0c;预算不足千元的情况下该怎么选择SSL证书呢&#xff1f;可以从以下几个方面进行考量&#xff0c;以确保在有限的预算内获得满足基本安…

Linux编辑器-vim的使用

vim的基本概念 vim的三种模式(其实有好多模式&#xff0c;目前掌握这3种即可),分别是命令模式&#xff08;command mode&#xff09;、插 入模式&#xff08;Insert mode&#xff09;和底行模式&#xff08;last line mode&#xff09;&#xff0c;各模式的功能区分如下&#…