首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >三维网格表示

三维网格表示

作者头像
NT4.4
修改于 2019-10-29 02:31:02
修改于 2019-10-29 02:31:02
74900
代码可运行
举报
文章被收录于专栏:图形视觉图形视觉
运行总次数:0
代码可运行

原文链接

网格有哪些数据结构

网格的数据结构其实就是一个图结构:点,边,面。可以是有向图,比如半边结构,也可以是无向图。在不同的软件或者开发包里,网格数据结构的实现都是有差异的。这种差异主要体现在网格连接关系的记录结构上,比如顶点是否记录邻域点,边,面信息,边是否记录邻域面信息等。记录的信息越多,查询的时候越方便,但是冗余的信息也越多,如果网格连接关系有变动,维护的信息也越多。另外,这些关系的建立也是需要开销的。所以,没有最好的数据结构,只有最适合当前算法的数据结构。

下面是一个例子:ITriMesh用于表达网格数据结构。网格算法都是基于ITriMesh接口来调用的,具体如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    class ITriMesh
    {
    public:
        ITriMesh(){}

        virtual Int GetVertexCount(void) const = 0;
        virtual Int GetTriangleCount(void) const = 0;

        virtual Vector3 GetVertexCoord(Int vid) const = 0;
        virtual void SetVertexCoord(Int vid, const Vector3& coord) = 0;
        virtual Vector3 GetVertexNormal(Int vid) const = 0;
        virtual void SetVertexNormal(Int vid, const Vector3& normal) = 0;

        virtual void GetTriangleVertexIds(Int fid, Int vertexIds[3]) const = 0;
        virtual void SetTriangleVertexIds(Int fid, Int vertexId0, Int vertexId1, Int vertexId2) = 0;
        virtual Vector3 GetTriangleNormal(Int fid) const = 0;
        virtual void SetTriangleNormal(Int fid, const Vector3& normal) = 0;
        virtual Int InsertTriangle(Int vertexId0, Int vertexId1, Int vertexId2) = 0;
        virtual Int InsertVertex(const Vector3& coord) = 0;
        
        virtual void SwapVertex(Int vertexId0, Int vertexId1) = 0; 
        virtual void PopbackVertices(Int popCount) = 0;
        virtual void SwapTriangles(Int fid0, Int fid1) =0;
        virtual void PopbackTriangles(Int popCount) = 0;

        virtual void UpdateNormal(void) = 0;
        virtual void Clear(void) = 0;

        virtual ~ITriMesh(){};
    };

ITriMesh是一个抽象类,不能直接使用。用户可以继承这个接口类,实现其成员函数。这样设计的一个好处是,用户无需改变自己已有的数据结构,只要实现了这个接口类,就可以调用所有关于网格的算法了。真正体现了即插即用的特点。比如用户已经有了一个三角网格类MyTriMeshData,则我们可以定义一个类MyTriMesh,并用它来调用各种网格算法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    class MyTriMesh : public ITriMesh
    {
        MyTriMeshData* mData;
        MyTriMesh(MyTriMeshData* data) : mData(data) 
        {}
        virtual Int GetVertecCount() const 
        { 
            return mData->GetVertecCount(); 
        }
        virtual Vector3 GetVertexCoord(Int vid) const 
        { 
            return mData->GetVertexCoord(); 
        }
        virtual void SetVertexCoord(Int vid, const Vector3& coord) 
        { 
            mData->SetVertexCoord(vid, coord[0], coord[1], coord[2]); 
        }
        virtual Int InsertVertex(const Vector3& coord) 
        { 
            mData->InsertVertex(coord); 
            return insertVertexId; 
        }
        // 其它成员函数类似
    };

    MyTriMesh triMesh(myTriMeshData); // 用自己的三角网格数据初始化MyTriMesh
    ErrorCode res = ConsolidateMesh::LaplaceSmooth(triMesh, 0.2, 5, true); // 调用网格算法API来修改自己的网格数据
    res = ConsolidateMesh::MakeTriMeshManifold(triMesh);

半边结构好用吗

半边结构是网格数据结构的一种表达方式,它是一个有向图,把一条边表达为两个有向半边,如下图所示。它的优点在于网格信息的拾取非常方便,缺点是网格连接关系变动后,需要维护的信息也比较多。另外,半边结构表达的网格需要是流形结构,半边结构的构造也需要一定的时间开销。所以,一般场合我们都使用ITriMesh这类简单的网格表达方式。


网格有哪些属性

三角网格可以看作是一个图结构,由顶点,边和面(三角片)三个元素组成。网格的常见属性也由这三个元素的属性来表达。


网格顶点属性

顶点的几何属性通常可以表示为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    struct VertexInfo
    {
        Vector3 mCoord;
        Vector3 mNormal;
    };

除此之外,它还有一些其它的属性:

  • 邻域:邻顶点,邻边,邻面
  • 流形:如果顶点的邻域是一个单连同区域,则这点为流形结构
  • colorId:对于一个彩色顶点网格,每个顶点有一个颜色值。如果这个网格是多个角度的数据拼接而成,则每个角度的网格片往往存在色差。colorId用于记录这个色差信息:同一个colorId的顶点,可以认为是颜色相容的,没有色差。colorId属性用于去除顶点色差的功能里。

网格边属性

边的几何属性一般由对应端点的几何属性来表达,所以它通常由拓扑属性来表达:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    struct EdgeInfo
    {
        int mVertexId[2];
        std::vector< int > mFaceIds;
    };

除此之外,它还有一些其它的属性:

  • 边界边:如果它的邻接面为1,则为边界上的边
  • 非流形边:如果它的邻接面个数 > 2,则为非流形边

网格面属性

面的常见表达方式为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    struct TriangleInfo
    {
        Int mIndex[3];
        Vector3 mNormal;
    };

其中mIndex为三角片的顶点索引,mNormal为三角片的法线。三角片的属性其实用的并不多,它常见的属性是面点属性。所谓面点,即三角片的三个顶点。需要注意的是,面点和顶点的概念是不同的。下面是一些常见的面点属性:

  • 面点法线:它和顶点法线是不一样的概念。比如特征尖锐的区域,可以设置面点法线为面法线;在光滑区域,设置面点法线为顶点法线。
  • 纹理坐标:纹理坐标是一个典型的面点属性。严格来讲,顶点并没有纹理坐标的概念,只有三角形有纹理坐标的概念。网格UV展开到平面的时候,如果没有割缝产生,那么每个顶点在其相邻三角形内的纹理坐标都是一样的,故可简称为顶点的纹理坐标。如果有割缝产生,割缝处的顶点在不同三角形内的纹理坐标是不一样的。这时,顶点和纹理坐标是一对多的关系。其实,UV展开在UV域生成了一个二维网格,UV域的网格的顶点和原始网格的面点是一一对应的。所以,从这个角度来看SimplifyWithTextureCoords,它其实是对UV域的网格做了保持边界的QuadricSimplify操作。
  • 点像对应:点像对应信息用于纹理贴图,它的含义是三角片的面点在图像中的对应。它的概念和纹理坐标是类似的,都是网格到二维区域的一个映射。点像对应信息在图像域也映射出了一个二维网格。和UV展开的区别在于,UV展开的二维域是唯一的,而点像对应的二维域(图像),有可能有多个(多张图片)。这导致某些三角片的面点可能对应于不同的图像域。对于这类三角片的纹理贴图,一般采用面点颜色插值。
  • 注意:虽然点像对应是一个面点属性,Magic3D里的点像对应采用的却是顶点属性的表达方式,其主要原因是,网格的点像对应信息是从点云的点像对应映射过来的,所以可以认为每个顶点对应于一个像素。

网格法线计算

网格的法线可以分为三类:面法线,顶点法线,面点法线。

  • 面法线:可以通过面的两条边做外积叉乘得到面法线
  • 顶点法线:可以加权平均顶点的面邻域法线
  • 面点法线:它代表了面里的顶点,而不是网格顶点,它与网格顶点是多对一的关系。比如正方体的一个角点,它有三个垂直的相邻面,面点法线可以取对应的面法线,而顶点法线则明显区别于这类面点法线。面点法线不是很常用。

看似简单的法线计算,要得到稳定的计算结果,需要考虑一些退化的情况。比如网格内有面退化的时候,该如何处理呢?

有兴趣的读者,欢迎参考视频:三维网格表示 网格半边结构

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Metal入门教程(二)三维变换
上一篇的教程介绍了如何绘制一张图片,这次的目标是把图片显示到3D物体上,并进行三维变换。
落影
2018/07/01
1.7K3
Metal入门教程(二)三维变换
WebGL,真正进入三维的世界
一、在此之前 在之前的文章中,我想大家已经对WebGL有了一个大体的了解,不过为了凑字数,我在这篇文章的开头再稍微回顾一下,如果我们需要使用WebGL来绘制图像需要走完以下这五步: 1、从canvas
周明礼
2017/05/17
9K2
WebGL,真正进入三维的世界
Unity Mesh基础系列(一)生成网格(程序生成)
本教程假设你已经熟悉Unity Scripting的基本知识了。如果不清楚的可以看 时钟 的章节学习Unity的基础知识。而 构建分形 的章节里也提供了协程的基本介绍。
放牛的星星
2020/08/21
11.1K0
Unity Mesh基础系列(一)生成网格(程序生成)
Unity3D学习笔记2——绘制一个带纹理的面
上一篇文章《Unity3D学习笔记1——绘制一个三角形》中介绍了Unity3D的HelloWorld——绘制一个简单的三角形。不过这个三角形太简单了,连材质都没有。那么这里就将三角形扩展为一个矩形的面,并且为这个面贴上纹理。
charlee44
2021/07/13
1.2K0
OpenCV+OpenGL 双目立体视觉三维重建
这篇文章主要为了研究双目立体视觉的最终目标——三维重建,系统的介绍了三维重建的整体步骤。双目立体视觉的整体流程包括:图像获取,摄像机标定,特征提取(稠密匹配中这一步可以省略),立体匹配,三维重建。我在做双目立体视觉问题时,主要关注的点是立体匹配,本文主要关注最后一个步骤三维重建中的:三角剖分和纹理贴图以及对应的OpenCV+OpenGL代码实现。
流川疯
2019/01/18
5.8K0
进阶渲染系列(一)——平坦和线框着色(导数和几何体)
本教程介绍如何添加对平面着色的支持以及如何显示网格的线框。它使用了高级渲染技术,并假定您熟悉“渲染”系列中介绍的材质。
放牛的星星
2020/07/10
2.8K0
进阶渲染系列(一)——平坦和线框着色(导数和几何体)
Shader经验分享
流水线 1.应用阶段:(CPU)输出渲染图元,粗粒度剔除等 比如完全不在相机范围内的需要剔除,文件系统的粒子系统实现就用到粗粒度剔除。 2.几何阶段:(GPU)把顶点坐标转换到屏幕空间,包含了模型空间 到世界空间 到观察空间(相机视角view) 到齐次裁剪空间(投影project2维空间,四维矩阵,通过-w<x<w判断是否在裁剪空间) 到归一化设备坐标NDC(四维矩阵通过齐次除法,齐次坐标的w除以xyz实现归一化) 到屏幕空间(通过屏幕宽高和归一化坐标计算)。 a.顶点着色器:坐标变换和逐顶点光照,将顶点空间转换到齐次裁剪空间。 b.曲面细分着色器:可选 c.几何着色器:可选 d.裁剪:通过齐次裁剪坐标的-w<x<w判断不在视野范围内的部分或者全部裁剪,归一化。 e.屏幕映射:把NDC坐标转换为屏幕坐标 3.光栅化阶段:(GPU)把几何阶段传来的数据来产生屏幕上的像素,计算每个图元覆盖了哪些像素,计算他们的颜色、 a.三角形设置:计算网格的三角形表达式 b.三角形遍历:检查每个像素是否被网格覆盖,被覆盖就生成一个片元。 c.片元着色器:对片元进行渲染操作 d.逐片元操作:模板测试,深度测试 混合等 e.屏幕图像 ------------------------------------------------------- 矩阵: M*A=A*M的转置(M是矩阵,A是向量,该公式不适合矩阵与矩阵) 坐标转换: o.pos = mul(UNITY_MATRIX_MVP, v.vertex);顶点位置模型空间到齐次空间 o.worldNormal = mul((float3x3)_Object2World,v.normal);//游戏中正常的法向量转换,转换后法向量可能不与原切线垂直,但是不影响游戏显示,而且大部分显示也是差不多的。一般用这个就行了。 o.worldNormal = mul(v.normal, (float3x3)_World2Object);顶点法向量从模型空间转换到世界空间的精确算法,公式是用_Object2World该矩阵的逆转置矩阵去转换法线。然后通过换算得到该行。 ------------------------------------------------------- API: UNITY_MATRIX_MVP 将顶点方向矢量从模型空间变换到裁剪空间 UNITY_MATRIX_MV 将顶点方向矢量从模型空间变换到观察空间 UNITY_MATRIX_V 将顶点方向矢量从世界空间变换到观察空间 UNITY_MATRIX_P 将顶点方向矢量从观察空间变换到裁剪空间 UNITY_MATRIX_VP 将顶点方向矢量从世界空间变换到裁剪空间 UNITY_MATRIX_T_MV UNITY_MATRIX_MV的转置矩阵 UNITY_MATRIX_IT_MV UNITY_MATRIX_MV的逆转置矩阵,用于将法线从模型空间转换到观察空间 _Object2World将顶点方向矢量从模型空间变换到世界空间,矩阵。 _World2Object将顶点方向矢量从世界空间变换到模型空间,矩阵。 模型空间到世界空间的矩阵简称M矩阵,世界空间到View空间的矩阵简称V矩阵,View到Project空间的矩阵简称P矩阵。 --------------------------------------------- _WorldSpaceCameraPos该摄像机在世界空间中的坐标 _ProjectionParams _ScreenParams _ZBufferParams unity_OrthoParams unity_Cameraprojection unity_CameraInvProjection unity_CameraWorldClipPlanes[6]摄像机在世界坐标下的6个裁剪面,分别是左右上下近远、 ---------------------------- 1.表面着色器 void surf (Input IN, inout SurfaceOutput o) {}表面着色器,unity特殊封装的着色器 Input IN:可以引用外部定义输入参数 inout SurfaceOutput o:输出参数 struct SurfaceOutput//普通光照 { half3 Albedo;//纹理,反射率,是漫反射的颜色值 half3 Normal;//法线坐标 half3 Emission;//自发光颜色 half Specular;//高光,镜面反射系数 half Gloss;//光泽度 half Alpha;//alpha通道 } 基于物理的光照模型:金属工作流Surfa
bering
2019/12/03
2.3K0
Direct3D学习(六):动画基础(3)网格模型基础
ID3DXMesh继承自ID3DXBaseMesh接口 ID3DXBaseMesh包含一个顶点缓存和一个索引缓存 一个mesh是由一组子集(subset)组成的 子集是具有相同属性的一组三角形 这里的属性指材质,纹理,渲染状态 属性ID存在mesh的属性缓存中,DWORD类型 子集i与材质和纹理数组的第i项对应 Mesh的顶点和索引缓存可以被重组以便更快地渲染,如根据属性把三角形重新排一下序 优化有时要用到邻接数组 Mesh可以被拷贝,拷贝的同时可以改变顶点格式 Mesh不包括顶点法线数据时,可以
逍遥剑客
2018/05/23
5350
【笔记】《计算机图形学》(11)——纹理映射
这系列的笔记来自著名的图形学虎书《Fundamentals of Computer Graphics》,这里我为了保证与最新的技术接轨看的是英文第五版,而没有选择第二版的中文翻译版本。不过在记笔记时多少也会参考一下中文版本
ZifengHuang
2020/12/08
4.8K0
3D 小姐姐模型是怎么“捏”成的? 初识 Mesh 知识点!
今天菜鸟和大家一起来讨论一下3D入门的基础性知识:「Mesh」它是3D模型能正常展现的重要因素。(文末有奖问卷调查,感谢各位老铁支持!)
张晓衡
2023/02/23
1.3K0
3D 小姐姐模型是怎么“捏”成的? 初识 Mesh 知识点!
NDK OpenGL ES 3.0 开发(二十一):3D 模型加载和渲染
上一节简单介绍了常用的 3D 模型文件 Obj 的数据结构和模型加载库 Assimp 的编译,本节主要介绍如何使用 Assimp 加载 3D 模型文件和渲染 3D 模型。
字节流动
2020/06/02
1K0
【笔记】《计算机图形学》(12)——图形学的数据结构
之前我的笔记都是在OneNote上记录的,苦于OneNote羸弱的跨平台性,我决定抛弃OneNote,今后的笔记都用Markdown记录,方便迁移也方便调整格式。文章一开始编辑后会保存在我的Github仓库中(https://github.com/ZFhuang/Study-Notes),整理完后会发到公众号上,并延时同步到我的腾讯云。
ZifengHuang
2021/02/04
6.4K0
学习PCL库:PCL库中的geometry模块介绍
PCL库中的geometry模块主要提供了点云几何计算的工具,geometry模块提供了点云和三维网格(mesh)处理的一些基本算法和数据结构。
点云PCL博主
2023/08/21
1.1K0
学习PCL库:PCL库中的geometry模块介绍
通过Mesh投影来实现贴花系统
在做FPS之类的游戏中,如果枪打到了墙角,并不能简单放置一来弹孔面片了事。而是要像一张贴纸一样,完全与墙角贴合。这时就需要去实现一个贴花系统来达到这种效果。
重归混沌
2020/04/26
1.1K0
3D 可视化入门:渲染管线原理与实践
玩 3D 游戏的时候,有没有想过这些 3D 物体是怎么渲染出来的?其中的动画是怎么做的?为什么会出现穿模、阴影不对、镜子照不出主角的情况?要想解答这些问题,就要了解实时渲染。其中最基础的,就是渲染管线。
Tecvan
2021/12/09
7.3K1
3D 可视化入门:渲染管线原理与实践
用Three.js建模
在Three.js中,一个可见的物体是由几何体和材料构成的。在这个教程中,我们将学习如何从头开始创建新的网格几何体,研究Three.js为处理几何对象和材质所提供的相关支持。
用户5687508
2021/07/17
8K0
OBJ 3D模型格式介绍
OBJ 是一种几何定义文件格式,Wavefront Technologies 公司在可视化加强动画包中第一次使用了这个格式,文件格式是公开的,并具有及其优质的兼容性和跨平台、跨行业的通用性,在所有 3D 应用软件中被支持。
为为为什么
2024/07/13
5700
网格UV展开
参数曲面的参数域变量一般用UV字母来表达,比如参数曲面F(u,v)。所以一般叫的三维曲面本质上是二维的,它所嵌入的空间是三维的。凡是能通过F(u,v)来表达的曲面都是参数曲面,比如NURBS曲面。对于三角网格,如果能把它与参数平面建立一一映射,那么它也就被参数化了,这个映射就是UV展开。如下图所示,左图是右边网格在参数平面上的展开,这样每个顶点都有了一个uv参数值,这也被称为纹理坐标。
NT4.4
2019/10/18
3.3K0
网格UV展开
【笔记】《计算机图形学》(17)——使用图形硬件
这一章介绍了计算机与图形硬件和实际编程相关的内容, 其中主要利用OpenGL简单介绍了实际的图形编程部分, 但是如果想要真正开始OpenGL编程, 查阅其它资料是必不可少的. 注意这一章最新的英文版和中文版由于时代不同所以内容差别非常大, 建议还是阅读英文版本.
ZifengHuang
2021/07/23
1.7K0
【笔记】《计算机图形学》(17)——使用图形硬件
面试官:纹理贴图必须要输入顶点坐标或纹理坐标吗
这个就引出了文本提到的全屏三角形,它不需要顶点缓冲区,而是利用顶点着色器直接生成所需的顶点坐标和纹理坐标。
字节流动
2024/06/18
3231
面试官:纹理贴图必须要输入顶点坐标或纹理坐标吗
推荐阅读
相关推荐
Metal入门教程(二)三维变换
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验