源码分析学习记录(12)——自动UV展开

本文介绍了UV展开的概念,强调其在三维曲面到二维平面映射中的作用。内容涉及创建割缝的必要性,割缝的理想特性,以及UV展开后的扭曲情况分析。最后提到了UvUnwrap过程,包括自动找纹理割缝、UV展开、再分割和纹理坐标打包等步骤。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

UV 展开

参数曲面的参数域变量一般用UV字母来表达,比如参数曲面F(u,v)。所以一般叫的三维曲面本质上是二维的,它所嵌入的空间是三维的。凡是能通过F(u,v)来表达的曲面都是参数曲面,比如NURBS曲面。对于三角网格,如果能把它与参数平面建立一一映射,那么它也就被参数化了,这个映射就是UV展开。如下图所示,左图是右边网格在参数平面上的展开,这样每个顶点都有了一个uv参数值,这也被称为纹理坐标。
在这里插入图片描述

创建割缝

网格UV展开到平面的时候,如果没有割缝产生,那么每个顶点在其相邻三角形内的纹理坐标都是一样的,故可简称为顶点的纹理坐标。如果有割缝产生,割缝处的顶点在不同三角形内的纹理坐标是不一样的。这时,顶点和纹理坐标是一对多的关系。对于任意拓扑结构的网格,需要给它添加割缝,把它分割成一片一片的圆盘结构,再做展开。
在这里插入图片描述
UV展开的应用里,经常需要创建一些网格割缝。好的割缝,一般有这些性质:

  • 长度很短
  • 割线光滑
  • 沿特征边
  • 分布在视觉不明显的地方
  • 在全自动UV展开应用里,割缝首先要能把网格割成一片一片的圆盘结构

UV展开的扭曲情况

网格展开到平面区域,除了可展曲面,其它曲面在展开后都会产生一些扭曲。一般有两种扭曲。一种是曲面本身的几何所决定的,比如球面展开到平面,一定会产生扭曲。想要减少展开的扭曲程度,可以在扭曲程度大的地方增加曲面割线。另一种是展开算法中的约束产生的扭曲,比如固定边界的UV展开。一种直观的观察展开扭曲程度的方式是,把一张棋盘格图片贴到网格上,棋盘格越均匀,UV展开扭曲越小。

UvUnwrap

任意拓扑网格全自动UV展开大概有以下步骤:自动找纹理割缝,自动UV展开,如果展开扭曲大,会自动进行再分割展开,最后自动纹理坐标打包。

//任意拓扑网格全自动UV展开类
class UvUnwrapper
{
   
public:
    void setMesh(const Mesh &mesh);
    void setTexelSize(float texelSize);
    void unwrap();
    const std::vector<FaceTextureCoords> &getFaceUvs() const;
    const std::vector<Rect> &getChartRects() const;
    const std::vector<int> &getChartSourcePartitions() const;
    float getTextureSize() const;

private:
    void partition();
    void splitPartitionToIslands(const std::vector<size_t> &group, std::vector<std::vector<size_t>> &islands);
    void unwrapSingleIsland(const std::vector<size_t> &group, int sourcePartition, bool skipCheckHoles=false);
    void parametrizeSingleGroup(const std::vector<Vertex> &verticies,
        const std::vector<Face> &faces,
        std::map<size_t, size_t> &localToGlobalFacesMap,
        size_t faceNumToChart,
        int sourcePartition);
    bool fixHolesExceptTheLongestRing(const std::vector<Vertex> &verticies, std::vector<Face> &faces, size_t *remainingHoleNum=nullptr);
    void makeSeamAndCut(const std::vector<Vertex> &verticies,
        const std::vector<Face> &faces,
        std::map<size_t, size_t> &localToGlobalFacesMap,
        std::vector<size_t> &firstGroup, std::vector<size_t> &secondGroup);
    void calculateSizeAndRemoveInvalidCharts()
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值