OpenSubdiv.OPENSUBDIV_VERSION.Bfr
OpenSubdiv.OPENSUBDIV_VERSION.Far
OpenSubdiv.OPENSUBDIV_VERSION.Osd
OpenSubdiv.OPENSUBDIV_VERSION.Sdc
OpenSubdiv.OPENSUBDIV_VERSION.Vtr

OpenSubdiv.OPENSUBDIV_VERSION.Bfr.Parameterization

概述

OpenSubdiv是一种用于细分曲面的开源C ++库。 Bfr.Parameterization是其中一种函数,用于对曲面进行参数化以便于细分。

函数签名

template<class T> void Bfr::Parameterization(T const & mesh, 
                                             T::PrimVar const & uvs, 
                                             T * ptex, 
                                             int nchannels, 
                                             int facevarying, 
                                             bool requireUV, 
                                             float * fvarData=nullptr)

参数说明

参数 说明
mesh 要参数化的网格
uvs 该网格已存在的纹理坐标
ptex 一个可选的参数化坐标;调用函数后,这个参数将包含从纹理坐标转换的参数化坐标
nchannels 网格中的通道数
facevarying 是否进行面间参数化
requireUV 是否需要使用纹理坐标
fvarData 一个可选的数据块,它包含网格上的fvar数据,如果存在的话

使用方法

  • 定义一个类派生自OpenSubdiv::Osd::MeshInterface(称为FooMesh);
  • 实现FooMesh的几个虚函数,以支持它在Bfr.Parameterization中使用;
  • 为FooMesh创建一个实例,并设置其顶点,拓扑和纹理坐标等等;
  • 调用Bfr::Parameterization方法进行参数化。

示例

// 定义一个类派生自Osd::MeshInterface
class FooMesh : public OpenSubdiv::Osd::MeshInterface {
public:
    // 实现几个虚函数,以支持它在Bfr.Parameterization中使用

    // 实现GetNumVertices方法
    int GetNumVertices() const override {
        return numvertices_;
    }

    // 实现GetNumFaces方法
    int GetNumFaces() const override {
        return numfaces_;
    }

    // 实现GetNumVertsPerFace方法
    int GetNumVertsPerFace(int faceid) const override {
        return numvertsperface_[faceid];
    }

    // 实现GetVertVertexIndices
    void GetVertVertexIndices(int vertid, int * outbuffer) const override {
        outbuffer[0] = vertexindices_[vertid];
    }

    // 实现GetFaceVertexIndices
    void GetFaceVertexIndices(int faceid, int * outbuffer) const override {
        memcpy(outbuffer, &vertexfaceindices_[facevtxoffsets_[faceid]],
               sizeof(int) * numvertsperface_[faceid]);
    }

    // 实现GetVertexAttribData
    void GetVertexAttribData(int index, int * numcompspervertex,
                             int * attribsize, void const ** attribdata) const override {
        switch (index) {
            case 0:  // 第一个属性
                *numcompspervertex = 2;
                *attribsize = sizeof(float) * 2;
                *attribdata = uvcoords_;
                break;
            default:
                // 其他属性默认为空
                *numcompspervertex = 0;
                *attribsize = 0;
                *attribdata = nullptr;
        }
    }

    // 设置顶点,拓扑和纹理坐标等
    void SetupMesh(int numvertices, int numfaces, int const * numvertsperface,
                   int const * vertsperface, int const * vertexindices,
                   float const * uvcoords) {
        numvertices_= numvertices;
        numfaces_= numfaces;
        numvertsperface_ = numvertsperface;
        vertexfaceindices_.resize(numfaces * 4);
        facevtxoffsets_.resize(numfaces + 1, 0);
        vertexindices_ = vertexindices;
        uvcoords_ = uvcoords;

        for (int i = 0; i < numfaces; ++i) {
            int const num = numvertsperface[i];
            facevtxoffsets_[i + 1] = facevtxoffsets_[i] + num;
            memcpy(&vertexfaceindices_[facevtxoffsets_[i]],
                   &vertsperface[facevtxoffsets_[i]],
                   num * sizeof(int));
        }
    }

private:
    int numvertices_ = 0;
    int numfaces_ = 0;
    std::vector<int> numvertsperface_;
    std::vector<int> vertexfaceindices_;
    std::vector<int> facevtxoffsets_;
    int const * vertexindices_ = nullptr;
    float const * uvcoords_ = nullptr;
};

// 创建FooMesh实例,设置其顶点,拓扑和纹理坐标等
FooMesh foo;
int const verts[4] = {0, 1, 2, 3};  // 一个四边形
float const uvcoords[8] = {0, 0, 0, 1, 1, 1, 1, 0};  // 对应的纹理坐标
int const numvertsperface[1] = {4};  // 一个四边形
foo.SetupMesh(4, 1, numvertsperface, verts, verts, uvcoords);

// 使用Bfr::Parameterization方法进行参数化
// 参数uvcoords是FooMesh实例foo的纹理坐标
// 参数ptex是一个可选的参数化坐标,调用函数后,它将包含从纹理坐标转换的参数化坐标
Bfr::Parameterization(foo, 1, &ptex, 2, 0, true, nullptr);

注意事项

  • 在调用Bfr::Parameterization之前,必须先定义一个类派生自Osd::MeshInterface,并实现几个虚函数。
  • FooMesh实例的拓扑信息必须为Quads或Triangles。