34using SubdivisionScheme = OpenSubdiv::Sdc::SchemeType;
39template <
typename MeshType>
42 using VertexType =
typename MeshType::VertexType;
43 OSDVertex() =
default;
44 OSDVertex(OSDVertex
const& src) { m_position = src.m_position; }
47 void Clear(
void* = 0) { m_position.setZero(); }
48 void AddWithWeight(OSDVertex
const& src,
float weight)
50 m_position += (weight * src.m_position);
54 void SetPosition(
const VertexType& pos) { m_position = pos; }
55 const VertexType& GetPosition()
const {
return m_position; }
58 VertexType m_position;
62template <
typename MeshType>
65 using UVType =
typename MeshType::UVType;
67 OSDUV(OSDUV
const& src) { m_position = src.m_position; }
70 void Clear(
void* = 0) { m_position.setZero(); }
71 void AddWithWeight(OSDUV
const& src,
float weight) { m_position += (weight * src.m_position); }
74 void SetPosition(
const UVType& pos) { m_position = pos; }
75 const UVType& GetPosition()
const {
return m_position; }
87template <
typename input_meshType,
typename output_meshType>
88std::unique_ptr<output_meshType> subdivide_mesh(
89 const input_meshType& input_mesh,
90 SubdivisionScheme scheme_type,
92 OpenSubdiv::Sdc::Options::VtxBoundaryInterpolation vertexInterp =
93 OpenSubdiv::Sdc::Options::VTX_BOUNDARY_EDGE_ONLY,
94 OpenSubdiv::Sdc::Options::FVarLinearInterpolation primvarInterp =
95 OpenSubdiv::Sdc::Options::FVAR_LINEAR_ALL)
97 static_assert(MeshTrait<input_meshType>::is_mesh(),
"Input type is not Mesh");
99 std::is_same<typename input_meshType::Index, typename output_meshType::Index>::value,
100 "Meshes must have same Index type");
102 using namespace OpenSubdiv;
103 using Descriptor = Far::TopologyDescriptor;
104 using namespace internal;
105 using OSDIndex = Vtr::Index;
107 if (scheme_type == SubdivisionScheme::SCHEME_LOOP) {
109 input_mesh.get_vertex_per_facet() == 3,
110 "Loop Subdivision only supports triangle meshes");
114 Sdc::Options options;
115 options.SetVtxBoundaryInterpolation(vertexInterp);
116 options.SetFVarLinearInterpolation(primvarInterp);
119 const auto num_vertices = input_mesh.get_num_vertices();
120 const auto num_facets = input_mesh.get_num_facets();
121 const auto input_vertex_per_facet = input_mesh.get_vertex_per_facet();
122 const auto output_vertex_per_facet =
123 output_meshType::FacetArray::ColsAtCompileTime == Eigen::Dynamic
124 ? input_vertex_per_facet
125 : output_meshType::FacetArray::ColsAtCompileTime;
127 if (input_vertex_per_facet == 3 && output_vertex_per_facet == 4) {
130 "Only non-zero-level subdivision is supported when the input is triangle and the "
131 "output is quadrangle.");
136 desc.numVertices = num_vertices;
137 desc.numFaces = num_facets;
139 std::vector<int> verts_per_face(num_facets, input_vertex_per_facet);
140 desc.numVertsPerFace = verts_per_face.data();
142 const auto& facets = input_mesh.get_facets();
143 std::vector<OSDIndex> vert_indices;
144 vert_indices.resize(num_facets * input_vertex_per_facet);
145 for (
auto i :
range(desc.numFaces)) {
146 for (
auto j :
range(input_vertex_per_facet)) {
150 desc.vertIndicesPerFace = vert_indices.data();
154 const bool hasUvs = input_mesh.is_uv_initialized();
155 std::vector<OSDIndex> uv_indices;
156 const int channelUV = 0;
157 const int numChannels = 1;
158 Descriptor::FVarChannel channels[numChannels];
160 channels[channelUV].numValues = (int)input_mesh.get_uv().rows();
161 const auto& inputUVIndices = input_mesh.get_uv_indices();
162 uv_indices.resize(inputUVIndices.size());
163 for (
auto i :
range(desc.numFaces)) {
164 for (
auto j :
range(input_vertex_per_facet)) {
165 uv_indices[i * input_vertex_per_facet + j] =
169 channels[channelUV].valueIndices = uv_indices.data();
172 desc.numFVarChannels = numChannels;
173 desc.fvarChannels = channels;
177 std::unique_ptr<Far::TopologyRefiner> refiner(
178 Far::TopologyRefinerFactory<Descriptor>::Create(
180 Far::TopologyRefinerFactory<Descriptor>::Options(scheme_type, options)));
185 Far::TopologyRefiner::UniformOptions refineOptions(maxlevel);
186 refineOptions.fullTopologyInLastLevel =
true;
187 refiner->RefineUniform(refineOptions);
192 std::vector<OSDVertex<output_meshType>> vbuffer(refiner->GetNumVerticesTotal());
193 OSDVertex<output_meshType>* outputVerts = &vbuffer[0];
195 int nInputVerts = input_mesh.get_num_vertices();
196 for (
int i = 0; i < nInputVerts; ++i)
197 outputVerts[i].SetPosition(
200 OSDUV<output_meshType>* outputUvs =
nullptr;
201 std::vector<OSDUV<output_meshType>> fvBufferUV;
204 fvBufferUV.resize(refiner->GetNumFVarValuesTotal(channelUV));
205 outputUvs = &fvBufferUV[0];
207 for (
int i = 0; i < input_mesh.get_uv().rows(); ++i) {
208 outputUvs[i].SetPosition(
214 Far::PrimvarRefiner primvarRefiner(*refiner);
215 OSDVertex<output_meshType>* srcVert = outputVerts;
216 OSDUV<output_meshType>* srcFVarUV = outputUvs;
218 for (
int level = 1; level <= maxlevel; ++level) {
219 OSDVertex<output_meshType>* dstVert =
220 srcVert + refiner->GetLevel(level - 1).GetNumVertices();
221 OSDUV<output_meshType>* dstFVarUV = outputUvs;
223 dstFVarUV = srcFVarUV + refiner->GetLevel(level - 1).GetNumFVarValues(channelUV);
225 primvarRefiner.Interpolate(level, srcVert, dstVert);
227 if (hasUvs) primvarRefiner.InterpolateFaceVarying(level, srcFVarUV, dstFVarUV, channelUV);
229 if (hasUvs) srcFVarUV = dstFVarUV;
235 Far::TopologyLevel
const& refLastLevel = refiner->GetLevel(maxlevel);
236 int nOutputVerts = refLastLevel.GetNumVertices();
237 int nOutputFaces = refLastLevel.GetNumFaces();
238 bool triangulate =
false;
239 if (scheme_type == SubdivisionScheme::SCHEME_LOOP) {
241 assert(output_vertex_per_facet == 3);
244 assert(output_vertex_per_facet == 3 || output_vertex_per_facet == 4);
245 if (output_vertex_per_facet == 3) {
247 if (maxlevel > 0 || input_vertex_per_facet > 3) {
255 int firstOfLastVerts = refiner->GetNumVerticesTotal() - nOutputVerts;
256 typename output_meshType::VertexArray V;
257 V.resize(nOutputVerts, 3);
258 for (
int iVert = 0; iVert < nOutputVerts; ++iVert) {
259 typename output_meshType::VertexType pos =
260 outputVerts[firstOfLastVerts + iVert].GetPosition();
265 typename output_meshType::FacetArray F;
266 F.resize(nOutputFaces, F.cols());
267 for (
int iFace = 0; iFace < refLastLevel.GetNumFaces(); ++iFace) {
268 Far::ConstIndexArray facetIndices = refLastLevel.GetFaceVertices(iFace);
270 F(iFace * 2, 0) = facetIndices[0];
271 F(iFace * 2, 1) = facetIndices[1];
272 F(iFace * 2, 2) = facetIndices[2];
273 F(iFace * 2 + 1, 0) = facetIndices[0];
274 F(iFace * 2 + 1, 1) = facetIndices[2];
275 F(iFace * 2 + 1, 2) = facetIndices[3];
277 for (
int i = 0; i < facetIndices.size(); ++i) {
278 F(iFace, i) = facetIndices[i];
283 std::unique_ptr<output_meshType> output_mesh =
create_mesh(std::move(V), std::move(F));
287 int nOutputUvs = refLastLevel.GetNumFVarValues(channelUV);
288 int firstOfLastUvs = refiner->GetNumFVarValuesTotal(channelUV) - nOutputUvs;
289 typename output_meshType::UVArray
UV;
290 typename output_meshType::FacetArray UVF;
291 UV.resize(nOutputUvs, 2);
292 UVF.resize(nOutputFaces, output_vertex_per_facet);
293 for (
int iFVVert = 0; iFVVert < nOutputUvs; ++iFVVert) {
294 typename output_meshType::UVType uv = outputUvs[firstOfLastUvs + iFVVert].GetPosition();
295 UV.row(iFVVert) = uv;
297 for (
int iFace = 0; iFace < refLastLevel.GetNumFaces(); ++iFace) {
298 Far::ConstIndexArray uvIndices = refLastLevel.GetFaceFVarValues(iFace, channelUV);
300 UVF(iFace * 2, 0) = uvIndices[0];
301 UVF(iFace * 2, 1) = uvIndices[1];
302 UVF(iFace * 2, 2) = uvIndices[2];
303 UVF(iFace * 2 + 1, 0) = uvIndices[0];
304 UVF(iFace * 2 + 1, 1) = uvIndices[2];
305 UVF(iFace * 2 + 1, 2) = uvIndices[3];
307 for (
int i = 0; i < uvIndices.size(); ++i) {
308 UVF(iFace, i) = uvIndices[i];
312 output_mesh->initialize_uv(
UV, UVF);