【WebGL】OpenCTM 格式详解

作者: 0bac0812186e | 来源:发表于2017-03-28 16:21 被阅读507次

    命题为『OpenCTM 格式详解』实在有些大言不惭,羞羞。

    这篇文章是对 OpenCTM 官方《Developers Manual》(以下简称手册)中我觉得比较重要的可以帮助深入理解 OpenCTM 部分的摘取。在上一篇文章中我介绍了如何在 Three.js 中引入 OpenCTM,传送门《Three.js载入OpenCTM模型

    官方提供了 C 和 C++ 版本的 OpenCTM API,用于读写 OpenCTM 格式。完整 api 文档可以看《OpenCTM API Reference》,推荐先阅读完本文或者《Developers Manual》(以下简称手册,第二次)获得一个较全面认知后,再查看 API 文档方能快速消化。

    手册里的代码示例都是 C 语言的,如果你不是 C 语言的开发者也请留步!OpenCTM 可以支持在各个平台,流行语言基本都有自己版本的开源库支持 OpenCTM 文件的读取。不同语言的库的原理还是想通的,所以就算你是 java 或者 js 的开发者,阅读本文也会对你有所帮助。

    前言

    本文首先介绍 OpenCTM 文件内容格式,再解说最重要的 OpenCTM 格式可采用的压缩种类,最后会简单介绍一下 C 版本 API 的类。

    OpenCTM 文件格式

    OpenCTM 文件格式非常简单,它被设计成了非常适合用于现代 3d 图形渲染管线程式(台湾腔)(如 OpenGL)的格式。以后有机会可以讲一下 3d 渲染管线,现在你可以将渲染管线理解成我们在计算机屏幕上绘图的『画笔』工具,且它对接收到的指令有一定的格式要求。

    The triangle mesh, in OpenCTM terms, is managed in a format that is well suited for a modern 3D rendering pipeline, such as OpenGL.

    OpenCTM 格式到底有多简单呢?我们都知道,一个 3d 模型有顶点面片、顶点颜色、顶点uv等信息。其中,要描述一个3d模型,最少所需的信息是模型的『顶点坐标』和『坐标点组成的面片』这两个信息(因为只有知道坐标点,并且知道那几个点是一个面你才能造出 3d 物体呀)。OpenCTM 十分直观包含了这两个必备信息,且支持增加另外一些可选信息(如顶点颜色、顶点uv,这些都是根据使用场景添加的)。

    一个 OpenCTM 文件仅包含一个 Mesh,所以本文提及的模型都是一个 Mesh。一个文件主要分成两部分:

    1. Mesh 的顶点信息

    不同模型的顶点信息可能有所差别。有的模型提供了顶点法相,顶点颜色等,有的模型则没有。

    最基本的顶点信息是 Vertex 数组,即顶点坐标位置数组。一个顶点的位置由 (x,y,z) 三轴坐标确定,x,y,z 皆为浮点数类型。一个模型的坐标信息是一个很大的数组,每个元素都是一个表示某点某一坐标轴位置的浮点数,从第一个元素开始没三个元素标识一个顶点。如果一个模型有 n 个顶点,那么 Vertex 数组的长度为 3n。

    附加信息如 Normal 数组,表示每个点的法相,每个点的法相都是3元的浮点数数组,跟 Vertex 数组相近。还有 UVCoord 数组,表示每个点的 UV 坐标,UV表示模型上点在贴图的哪个位置获取颜色(如果有贴图),每个顶点的 uv 是一个2元的整数数组。另外有 Attribute 数组,用来记录定制信息,每个点的 Attribute 是一个4元浮点叔叔组;Attribute 可以用来记录顶点颜色、顶点权重等信息。

    文件中顶点信息的就是这样放置的:全部的 Vertex,全部的 Normal,全部的 UV,全部的 Attribute...其中 Vertex 是必须提供的。顶点的下标(0,1,2,...N)在暗中保证数据的对应关系(没有理解的看下图)。

    需要注意的是,一个文件中的每个顶点所拥有的信息都是相同的(就是说不可以有些顶点有 uv 坐标,但有些顶点没有,要么都没有要么都有)。

    模型顶点信息

    2. Mesh 的面片信息

    每个模型面片信息格式相同,OpenCTM 只支持三角面,每个面由三个顶点组成,而模型的顶点是以下标标识的,所以一个面可以表示成三个顶点下标的数组(顶点的顺序非常重要,[v1, v2, v3] 组成的三角面和 [v1, v3, v2] 组成的三角面位置相同但是面的超像相反,我们称它们具有相反的面法相)。模型的面存在一个很长的数组里,数组元素是自然数(包括0),从第一个数开始每三个数标识一个面。一个顶点可能参与多个面的组成。

    模型面片信息

    OpenCTM 的压缩方式

    OpenCTM 官方提供了三种压缩思路,raw、mg1 和 mg2。raw 就是没有压缩的方式(lol),数据结构被压缩算法没有改变,方便开发和测试,生成速度最快。

    mg1 压缩

    是一种无损压缩,官方 OpenCTM 库默认使用 mg1 格式生成 .ctm 文件。生成速度比 raw 格式慢(增加了压缩的计算量),但是读取速度没有受到很大影响。

    mg1 压缩先把文件重新编码成可压缩的格式再用 lzma 算法做无损压缩,保留了所有的浮点数信息。

    跟 raw 格式相比,mg1 平均能把顶点信息压缩到 raw 格式的3/4,面片信息可以压缩到 raw 的 17%。

    mg2 压缩

    mg2 可以是有损压缩,且压缩比更高。mg2 文件的生成速度和 mg1 相差无几。

    mg2 在压缩面片信息的处理上和 mg1 相同,但在顶点信息的压缩上更胜一筹。它首先将顶点分割成更小的空间,并在小空间中做了一些有效降低顶点熵值的处理(算法这块求高手指点),这样一来 lzma 的压缩效率能大大提高。

    In short, the MG2 method divides the mesh into small sub-spaces, sorts the data geometrically, and applies delta-prediction to the data, which effectively lowers the data entropy. The re-coded vertex data is then compressed with LZMA.

    官方为 mg2 压缩提供了一个压缩精度参数,从0~9,0表示精度最低但是速度最快的压缩,9表示精度最高但是比较慢的压缩。此外,官方 API 还提供了比这更加细粒度的精度控制函数,可以控制到不同的顶点信息,比如我想要顶点坐标的精度为0.01,而法相坐标精度为0.1。精度控制在实际生产中很有意义,如果你要用模型做 3d 打印,你的模型单位是 1cm,你的打印机精度为 0.01mm,那么模型的精度如果超过了 0.01 就没有意义了(反正没法被打印)。

    大家可以根据自己的需求选择对应的压缩格式。

    官方 API

    官方提供了三个类:ctm_error,CTMexporter 和 CTMimporter。CTMexporter 用于创建 OpenCTM 文件导出的上下文,在这个上下文中有许多处理函数。相应的,CTMimporter 提供了 OpenCTM 文件导入的上下文。ctm_error 是一个错误处理类,在 C++ 版本的 API 中被 try catch 机制替代。具体请看《OpenCTM API Reference

    结束语

    OpenCTM 格式非常简单,raw 压缩格式的文件更是适合开发者上手,比较难懂(对我个人而言)的内容是 mg2 压缩格式所用到的优化算法以及 lzma 算法的使用(mg1 所用到的算法 mg2 也都用到了),也是在开发环节中比较容易出错又很难 debug 的部分。

    3d 的世界真的很有意思,浏览器为前端开发开启了一个探索图形编程的豁口——WebGL,前端能做的不再只是界面动画、表单验证,而是可以更多的接触底层算法和底层接口(WebGL 接口),不用活在程序猿鄙视链的低端啦~(开玩笑 :-)

    不免俗的,帮公司打波招聘广告:

    酷家乐春招开始啦,小伙伴们快把简历砸过来吧~~~~

    邮箱:neitui_qunhe@qq.com

    链接:http://wanzi319.legendh5.com/h5/kujiale.html?isappinstalled=0&from=timeline

    相关文章

      网友评论

        本文标题:【WebGL】OpenCTM 格式详解

        本文链接:https://www.haomeiwen.com/subject/tnyjottx.html