Android增强现实(三)-3D模型展示器
1.Android增强现实(一)-AR的三种方式(展示篇)
2.Android增强现实(二)-支持拖拽控制进度和伸缩的VrGifView
3.Android增强现实(三)-3D模型展示器
前言
前段时间研究了一下增强现实在Android端的实现,目前大体分为两种,全景立体图(GIF和全景图)和3D模型图。这篇博客主要讲一下关于3D模型的展示方式吧。
使用方式
1.Add it in your root build.gradle at the end of repositories:
allprojects {repositories {...maven { url 'https://jitpack.io' }}
}
Step 2. Add the dependency
dependencies {compile 'com.github.sdfdzx:VRShow:v1.0.2'
}
XML and Java
<com.study.xuan.stlshow.widget.STLViewandroid:id="@+id/stl"android:layout_width="match_parent"android:layout_height="match_parent"/>
java
//读取STL文件类STLViewBuilder.init(STLView stlView).Reader(ISTLReader reader).Byte(byte[] bytes).File(File file).Assets(Context context, String fileName).InputStream(InputStream inputStream).build();
//基础使用方法STLViewBuilder.init(mStl).Assets(this, "bai.stl").build();mStl.setTouch(true);//是否可以触摸mStl.setScale(true);//是否可以缩放mStl.setRotate(true);//是否可以拖拽mStl.setSensor(true);//是否支持陀螺仪//stl文件读取过程中的回调mStl.setOnReadCallBack(new OnReadCallBack() {@Overridepublic void onStart() {}@Overridepublic void onReading(int cur, int total) {}@Overridepublic void onFinish() {}});
技术分析
对于3D模型的渲染其实对于平常的应用平台其实涉及的还是比较少的,在游戏平台应用广泛,我无意中在京东看到过这样的功能
起先我平常对于这种效果接触的比较少,还不太清楚怎么实现,后来才了解到关于OpenGL的相关知识才了解到这种实现方式其实是利用OpenGL和GLSurfaceView进行实现。
大概了解了实现可行性,我们来看一下需求:
1.支持渲染3D模型
2.支持单指拖拽
3.支持双指缩放
4.支持陀螺仪
5.支持读取时的异步回调
对于这个的实现方式首先要了解这几个知识点:
1.3D模型,STL文件格式
2.OpenGL相关知识
3.GLSurfaceView的使用
3D模型,STL文件格式
其实对于3D模型的渲染,这里其实要明白的就是我们要做的就是两步:
1.3D模型数据文件->模型数据(异步读取文件过程)
2.模型数据->模型展示(渲染展示过程)
这里只涉及STL文件格式的3D模型数据,不同的文件格式,读取文件的格式也不一样,我目前就实现了STL文件格式的,那么问题来了,何为STL文件,为什么要了解STL文件?
我们其实没必要了解那么深入,这里引入百度百科的介绍其实已经够我们进行了解;
STL是用三角网格来表现3D CAD模型的一种文件格式。
可能这样我们理解还是比较困难,那么再加一张图
上图可以看到是一个由STL文件描述的猫,就是由一个个小的三角形构成的,所以说STL描述的就是构成这个3D模型所用的所有的三角形的相关数据。
那么我们就需要了解一下STL文件是怎么描述三角形数据的。
STL文件分为两种格式,一种是ASCII明码格式,另一种是二进制格式。
ASCII明码格式:(以下引自百度百科)
ASCII码格式的STL文件逐行给出三角面片的几何信息,每一行以1个或2个关键字开头。
在STL文件中的三角面片的信息单元 facet 是一个带矢量方向的三角面片,STL三维模型就是由一系列这样的三角面片构成。
整个STL文件的首行给出了文件路径及文件名。
在一个 STL文件中,每一个facet由7 行数据组成,
facet normal 是三角面片指向实体外部的法矢量坐标,
outer loop 说明随后的3行数据分别是三角面片的3个顶点坐标,3顶点沿指向实体外部的法矢量方向逆时针排列。
明码://字符段意义
solidfilenamestl//文件路径及文件名
facetnormalxyz//三角面片法向量的3个分量值
outerloop
vertexxyz//三角面片第一个顶点坐标
vertexxyz//三角面片第二个顶点坐标
vertexxyz//三角面片第三个顶点坐标
endloop
endfacet//完成一个三角面片定义......//其他facetendsolidfilenamestl//整个STL文件定义结束
看到上面的介绍,其实不难发现,其实对于ASCII码格式的STL文件我们需要怎么读取哪?其实很简单,有固定的字段表示文件的开始和结束,有固定的字段表示一个三角的开始和结束,固定每个三角形由7行数据构成,固定每一行表示的含义,这所有的都是固定的,一个for循环,按照文件的格式读取即可。
二进制格式:(以下引自百度百科)
二进制STL文件用固定的字节数来给出三角面片的几何信息。
文件起始的80个字节是文件头,用于存贮文件名;
紧接着用 4 个字节的整数来描述模型的三角面片个数,
后面逐个给出每个三角面片的几何信息。每个三角面片占用固定的50个字节,依次是:
3个4字节浮点数(角面片的法矢量)
3个4字节浮点数(1个顶点的坐标)
3个4字节浮点数(2个顶点的坐标)
3个4字节浮点数(3个顶点的坐标)个
三角面片的最后2个字节用来描述三角面片的属性信息。
一个完整二进制STL文件的大小为三角形面片数乘以 50再加上84个字节。
UINT8//Header//文件头
UINT32//Numberoftriangles//三角面片数量
//foreachtriangle(每个三角面片中)
REAL32[3]//Normalvector//法线矢量
REAL32[3]//Vertex1//顶点1坐标
REAL32[3]//Vertex2//顶点2坐标
REAL32[3]//Vertex3//顶点3坐标
UINT16//Attributebytecountend//文件属性统计
其实读取方法和上面的相似,只不过上面的是操作文件的行,这里就是操作字节数了,可以看到每个三角面占用的字节数固定,固定的字节数内数据依次占用固定的字节数,所以还是一个for循环,按照字节的格式读取即可。
OpenGL相关知识
OpenGL的相关知识怎么说哪,很多渲染过程中的相关api我也没搞懂,这里只说几个我们实现过程中需要了解的吧(具体网上资料很多,这方面我反正是个小白,就不充胖子了)。
1.glTranslatef(x,y,z)
2.glRotatef(angle,x,y,z)
3.glScalef(x,y,z)
看到字面意思就很好理解吧,平移,旋转,缩放,有api就好说了,剩下的就是我们将我们触摸得到的量转化成这里面的数值就行。
GLSurfaceView的使用
GLSurfaceView是Android一个专门处理3D模型的的View,他的基本用法和平常的View没什么差异,唯一需要注意的就是需要调用setRenderer()
传入一个Renderer
对象。理解起来也比较容易,GLSurfaceView其实就是一个View,也就是一个展示的视图,而控制展示的也就是Renderer
对象了。Renderer其实是一个接口,对应有三个方法需要我们实现,onSurfaceCreated对应视图创建时调用,onSurfaceChanged对应视图改变时调用,onDrawFrame对应视图绘制时调用。
public interface Renderer {void onSurfaceCreated(GL10 gl, EGLConfig config);void onSurfaceChanged(GL10 gl, int width, int height);void onDrawFrame(GL10 gl);}
对应配合上面OpenGL的相关知识,其实大概的实现过程已经有个雏形了。
关键代码
1.读取STL文件(这里以ASCII格式为例)
这里我是定义了一个读取的接口ISTLReader
public interface ISTLReader {public STLModel parserBinStl(byte[] bytes);public STLModel parserAsciiStl(byte[] bytes);public void setCallBack(OnReadListener listener);
}
可以通过STLViewBuilder.Reader(ISTLReader reader)方法自己实现。
我默认实现的STLReader这里只放上对于ASCII格式文件读取的伪代码吧。
public STLModel parserAsciiStl(byte[] bytes) {...String stlText = new String(bytes);String[] stlLines = stlText.split("\n");vertext_size = (stlLines.length - 2) / 7;...for (int i = 0; i < stlLines.length; i++) {String string = stlLines[i].trim();if (string.startsWith("facet normal ")) {string = string.replaceFirst("facet normal ", "");String[] normalValue = string.split(" ");for (int n = 0; n < 3; n++) {...}}if (string.startsWith("vertex ")) {string = string.replaceFirst("vertex ", "");String[] vertexValue = string.split(" ");...}...}...}
这里可以看到我是将byte[]转为了String,接着就通过固定的格式来进行读取,伪代码在上面,便于理解读取过程,可以看到,基本的就是通过对行数,startsWith,split等对字符串处理的函数进行读取的,读取规则其实可以仿照上面对于STL文件格式的介绍。
2.自定义Renderer渲染
自定义Renderer其实主要是对于OPenGL函数的调用,由于我对于这块也不是特别了解,我是在别人的基础上进行了一定的修改,里面参数的修改影响的就是渲染效果。而对于我们要实现的关于旋转缩放的函数其实就比较基础了,这里我还加入了关于缩放范围的控制。
gl.glRotatef(angleX, 0, 1, 0);gl.glRotatef(angleY, 1, 0, 0);gl.glPopMatrix();scale_rember = scale_now * scale;if (scaleRange) {if (scale_rember > SCALE_MAX) {scale_rember = SCALE_MAX;}if (scale_rember < SCALE_MIN) {scale_rember = SCALE_MIN;}}gl.glScalef(scale_rember, scale_rember, scale_rember);
3.手势监听
其实对于缩放和旋转的处理和前一篇Android增强现实(二)-支持拖拽控制进度和伸缩的VrGifView的处理大同小异,具体大家可以看前一篇博客,而对于陀螺仪的处理其实也比较简单,只不过用的比较少所以比较陌生,步骤也不比较固定。
private void initSensor() {sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);sensorEventListener = new SensorEventListener() {@Overridepublic void onSensorChanged(SensorEvent sensorEvent) {if (sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE) {if (timestamp != 0) {final float dT = (sensorEvent.timestamp - timestamp) * NS2S;stlRenderer.angleX += sensorEvent.values[0] * dT * 180.0f % 360.0f;stlRenderer.angleY += sensorEvent.values[1] * dT * 180.0f % 360.0f;stlRenderer.requestRedraw();requestRender();}timestamp = sensorEvent.timestamp;}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}};sensorManager.registerListener(sensorEventListener, gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);}
总结
其实相较于前一篇的对于GIF图的处理,这里技术上的考虑不是特别多,主要是对于3D文件STL格式的学习,OpenGL基础知识的学习,还有陀螺仪传感器使用的学习。
这里对于STL文件的读取还有Renderer中OpenGL的使用参考学习了以下资料,大家感兴趣的可以去查看学习:
1.一个不错的STL解析器,支持贴纹理,坐标系等
2.Android OpenGL入门系列,一个不错的系列入门文章
3.Android OpenGL入门系列
Android增强现实(三)-3D模型展示器相关推荐
- three.js实现3D模型展示
开头说明下 文章是转载我同事一个 哥们的.怕自己 以后会用 拿过来 方便以后使用 three.js实现3D模型展示 由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 ...
- html3d模型渲染,【SVG】纯clip-path打造的3D模型渲染器
几天之前, 一个species-in-pieces的网站把我震到了(如下图), 出于一个优秀前端的敏锐嗅觉和原始本能, 我立刻祭出了看家法宝--Chrome开发者工具开始偷窥这个网站. 简单推敲之后, ...
- 嵌入式系统大作业——基于QT的3D模型展示
嵌入式系统大作业--基于QT的3D模型展示 写在前面 实验设备 实现内容 实现过程 在win10上利用SolidWorks软件对模型进行预处理: 编写代码实现功能: 效果演示 参考资料 写在前面 该大 ...
- 3D模型展示 | 手机秒变3D扫描仪,给鞋子拍摄建模
鞋子3D模型展示,鞋子模型是由手机拍摄生成,用的是易模器物模式(三圈),仅仅花费了十几分钟就拿到了高精度逼真的模型,可用于线上电商3D展示.线下智慧门店展厅.3D打印等. 此款鞋子的鞋面是麂皮材质,模 ...
- Unity 3D模型展示框架篇之ILRuntime快速入门
系列文章目录 Unity 3D模型展示框架篇之项目整理 Unity 3D模型展示框架篇之框架运用 Unity 3D模型展示框架篇之自由观察(Cinemachine) Unity 3D模型展示框架篇之资 ...
- Unity 3D模型展示框架篇之项目整理
本项目将整合之前Unity程序基础小框架专栏在Unity 3D模型展示项目基础上进行整合,并记录了集成过程中对原脚本的调整过程.增加了Asset Bundle+ILRuntime热更新技术流程. 1. ...
- js jquery 3D模型展示
本人主要用于商城商品的3D模型展示: 效果如下: 可旋转可放大的3D模型展示 用法介绍 (1)如果你想直接使用简单的展示功能那么已经有封装好的js在此 下载引用即可 https://downlo ...
- Unity 3D模型展示框架篇之自由观察(Cinemachine)
本项目将整合之前Unity程序基础小框架专栏在Unity 3D模型展示项目基础上进行整合,并记录了集成过程中对原脚本的调整过程.增加了Asset Bundle+ILRuntime热更新技术流程. 在U ...
- Unity 3D模型展示之webGL平台展现
在之前的项目基础上我们已经打包后在PC端进行展示了.这篇文章主要介绍在切换到webGL上时效果展示不出来需要进行调整,特此记录一下. 1.平台切换 选择WebGL平台切换,没有的可以进行安装,安装之后 ...
最新文章
- C语言中的scanf()函数介绍
- java调用cd传输_Java调用Linux命令(cd的处理)
- 程序人生系列之新闻发布系统 在网站部署经验分享
- Android Studio检测内存泄露和性能
- ubutnu16.04搭建LAMP环境(搭建wordpress博客)
- Jquery在线引用地址:
- Redis 常用操作命令
- Google 最新的 Fuchsia OS【科技讯息摘要】
- HTTPS学习笔记一----HTTPS的基础理论知识
- Windows7下安装配置PostgreSQL10
- MyBatis中![CDATA[ ]]的使用
- Android 设置 横屏 竖屏 (转)
- PyTorch学习—19.模型的加载与保存(序列化与反序列化)
- 【算法基础一】字符编码分类
- 题目:js实现求100以内的质数
- ssh 所选的用户密钥未在远程主机上注册
- CHD6.3.1部署文档
- 快速截屏并保存图像 - 快速保存剪切板截图到图像-
- Nosql初探(voldemort)
- OC的单例模式的实现
热门文章
- 让POW的共识机制不再成为公链系统吞吐率的瓶颈 | Conflux CTO伍鸣
- 【产业互联网周报】微盟称数据已全面找回,公布商家赔付计划;疫情影响全球展会:Facebook取消年度F8开发者大会...
- java mybatis的作用,【java框架】MyBatis-Plus(1)--MyBatis-Plus快速上手开发及核心功能体验-博客...
- Python实现迷宫游戏
- 设计模式之 Vistor 访问者模式:Swift 实现
- javascript高级程序设计阅读收获(1.1)——javascript简短的历史回顾
- 题8:二叉树的下一个结点
- 网络信息安全领域中常见的几个概念
- Mindjet MindManager2022完整版思维导图v22.1.234版本
- excel php 数字科学计数_PHP导出excel时数字变为科学计数的解决方法