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模型展示器相关推荐

  1. three.js实现3D模型展示

    开头说明下  文章是转载我同事一个 哥们的.怕自己 以后会用 拿过来  方便以后使用 three.js实现3D模型展示 由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 ...

  2. html3d模型渲染,【SVG】纯clip-path打造的3D模型渲染器

    几天之前, 一个species-in-pieces的网站把我震到了(如下图), 出于一个优秀前端的敏锐嗅觉和原始本能, 我立刻祭出了看家法宝--Chrome开发者工具开始偷窥这个网站. 简单推敲之后, ...

  3. 嵌入式系统大作业——基于QT的3D模型展示

    嵌入式系统大作业--基于QT的3D模型展示 写在前面 实验设备 实现内容 实现过程 在win10上利用SolidWorks软件对模型进行预处理: 编写代码实现功能: 效果演示 参考资料 写在前面 该大 ...

  4. 3D模型展示 | 手机秒变3D扫描仪,给鞋子拍摄建模

    鞋子3D模型展示,鞋子模型是由手机拍摄生成,用的是易模器物模式(三圈),仅仅花费了十几分钟就拿到了高精度逼真的模型,可用于线上电商3D展示.线下智慧门店展厅.3D打印等. 此款鞋子的鞋面是麂皮材质,模 ...

  5. Unity 3D模型展示框架篇之ILRuntime快速入门

    系列文章目录 Unity 3D模型展示框架篇之项目整理 Unity 3D模型展示框架篇之框架运用 Unity 3D模型展示框架篇之自由观察(Cinemachine) Unity 3D模型展示框架篇之资 ...

  6. Unity 3D模型展示框架篇之项目整理

    本项目将整合之前Unity程序基础小框架专栏在Unity 3D模型展示项目基础上进行整合,并记录了集成过程中对原脚本的调整过程.增加了Asset Bundle+ILRuntime热更新技术流程. 1. ...

  7. js jquery 3D模型展示

    本人主要用于商城商品的3D模型展示: 效果如下:    可旋转可放大的3D模型展示 用法介绍 (1)如果你想直接使用简单的展示功能那么已经有封装好的js在此 下载引用即可 https://downlo ...

  8. Unity 3D模型展示框架篇之自由观察(Cinemachine)

    本项目将整合之前Unity程序基础小框架专栏在Unity 3D模型展示项目基础上进行整合,并记录了集成过程中对原脚本的调整过程.增加了Asset Bundle+ILRuntime热更新技术流程. 在U ...

  9. Unity 3D模型展示之webGL平台展现

    在之前的项目基础上我们已经打包后在PC端进行展示了.这篇文章主要介绍在切换到webGL上时效果展示不出来需要进行调整,特此记录一下. 1.平台切换 选择WebGL平台切换,没有的可以进行安装,安装之后 ...

最新文章

  1. C语言中的scanf()函数介绍
  2. java调用cd传输_Java调用Linux命令(cd的处理)
  3. 程序人生系列之新闻发布系统 在网站部署经验分享
  4. Android Studio检测内存泄露和性能
  5. ubutnu16.04搭建LAMP环境(搭建wordpress博客)
  6. Jquery在线引用地址:
  7. Redis 常用操作命令
  8. Google 最新的 Fuchsia OS【科技讯息摘要】
  9. HTTPS学习笔记一----HTTPS的基础理论知识
  10. Windows7下安装配置PostgreSQL10
  11. MyBatis中![CDATA[ ]]的使用
  12. Android 设置 横屏 竖屏 (转)
  13. PyTorch学习—19.模型的加载与保存(序列化与反序列化)
  14. 【算法基础一】字符编码分类
  15. 题目:js实现求100以内的质数
  16. ssh 所选的用户密钥未在远程主机上注册
  17. CHD6.3.1部署文档
  18. 快速截屏并保存图像 - 快速保存剪切板截图到图像-
  19. Nosql初探(voldemort)
  20. OC的单例模式的实现

热门文章

  1. 让POW的共识机制不再成为公链系统吞吐率的瓶颈 | Conflux CTO伍鸣
  2. 【产业互联网周报】微盟称数据已全面找回,公布商家赔付计划;疫情影响全球展会:Facebook取消年度F8开发者大会...
  3. java mybatis的作用,【java框架】MyBatis-Plus(1)--MyBatis-Plus快速上手开发及核心功能体验-博客...
  4. Python实现迷宫游戏
  5. 设计模式之 Vistor 访问者模式:Swift 实现
  6. javascript高级程序设计阅读收获(1.1)——javascript简短的历史回顾
  7. 题8:二叉树的下一个结点
  8. 网络信息安全领域中常见的几个概念
  9. Mindjet MindManager2022完整版思维导图v22.1.234版本
  10. excel php 数字科学计数_PHP导出excel时数字变为科学计数的解决方法