21bool TopologyRefinerFactory<OsdMesh>::resizeComponentTopology(TopologyRefiner &refiner,
22 OsdMesh
const &osd_mesh)
24 const Mesh &mesh = osd_mesh.mesh;
28 const int *subd_num_corners = mesh.get_subd_num_corners().data();
30 setNumBaseVertices(refiner, num_base_verts);
31 setNumBaseFaces(refiner, num_base_faces);
33 for (
int i = 0;
i < num_base_faces;
i++) {
34 setNumBaseFaceVertices(refiner,
i, subd_num_corners[
i]);
41bool TopologyRefinerFactory<OsdMesh>::assignComponentTopology(TopologyRefiner &refiner,
42 OsdMesh
const &osd_mesh)
44 const Mesh &mesh = osd_mesh.mesh;
48 const int *subd_face_corners = mesh.get_subd_face_corners().data();
49 const int *subd_start_corner = mesh.get_subd_start_corner().data();
50 const int *subd_num_corners = mesh.get_subd_num_corners().data();
52 for (
int i = 0;
i < num_base_faces;
i++) {
53 IndexArray face_verts = getBaseFaceVertices(refiner,
i);
55 const int start_corner = subd_start_corner[
i];
56 const int *corner = &subd_face_corners[start_corner];
58 for (
int j = 0; j < subd_num_corners[
i]; j++, corner++) {
59 face_verts[j] = *corner;
67bool TopologyRefinerFactory<OsdMesh>::assignComponentTags(TopologyRefiner &refiner,
68 OsdMesh
const &osd_mesh)
70 const Mesh &mesh = osd_mesh.mesh;
73 static constexpr float CREASE_SCALE = 10.0f;
75 const size_t num_creases = mesh.get_subd_creases_weight().size();
76 const size_t num_vertex_creases = mesh.get_subd_vert_creases().size();
79 if (num_creases == 0 && num_vertex_creases == 0) {
83 for (
int i = 0;
i < num_creases;
i++) {
85 const Index edge = findBaseEdge(refiner, crease.
v[0], crease.
v[1]);
88 setBaseEdgeSharpness(refiner, edge, crease.
crease * CREASE_SCALE);
92 std::map<int, float> vertex_creases;
94 for (
size_t i = 0;
i < num_vertex_creases; ++
i) {
95 const int vertex_idx = mesh.get_subd_vert_creases()[
i];
96 const float weight = mesh.get_subd_vert_creases_weight()[
i];
98 vertex_creases[vertex_idx] = weight * CREASE_SCALE;
103 for (
int i = 0;
i < num_base_verts;
i++) {
104 float sharpness = 0.0f;
105 const std::map<int, float>::const_iterator iter = vertex_creases.find(
i);
107 if (iter != vertex_creases.end()) {
108 sharpness = iter->second;
111 const ConstIndexArray vert_edges = getBaseVertexEdges(refiner,
i);
113 if (vert_edges.size() == 2) {
114 const float sharpness0 = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
115 const float sharpness1 = refiner.getLevel(0).getEdgeSharpness(vert_edges[1]);
117 sharpness +=
min(sharpness0, sharpness1);
118 sharpness =
min(sharpness, CREASE_SCALE);
121 if (sharpness != 0.0f) {
122 setBaseVertexSharpness(refiner,
i, sharpness);
130static void merge_smooth_fvar(
const Mesh &mesh,
131 const Attribute &subd_attr,
132 OsdMesh::MergedFVar &merged_fvar,
133 vector<int> &merged_next,
134 vector<int> &merged_face_corners)
138 const int *subd_face_corners = mesh.get_subd_face_corners().data();
140 const T *values =
reinterpret_cast<const T *
>(subd_attr.
data());
142 merged_fvar.values.resize(num_base_verts *
sizeof(
T));
147 const int state_uninitialized = 0;
148 const int state_end = -1;
149 merged_next.resize(num_base_verts, state_uninitialized);
151 for (
int f = 0,
i = 0; f < num_base_faces; f++) {
154 for (
int corner = 0; corner < face.
num_corners; corner++) {
156 const T value = values[
i++];
158 if (merged_next[
v] == state_uninitialized) {
160 reinterpret_cast<T *
>(merged_fvar.values.data())[
v] = value;
161 merged_next[
v] = state_end;
162 merged_face_corners.push_back(
v);
167 for (;
v != state_end; v_prev =
v,
v = merged_next[
v]) {
168 if (
reinterpret_cast<T *
>(merged_fvar.values.data())[
v] == value) {
170 merged_face_corners.push_back(
v);
175 if (
v == state_end) {
177 const int next = merged_next.size();
178 merged_fvar.values.resize((
next + 1) *
sizeof(
T));
179 reinterpret_cast<T *
>(merged_fvar.values.data())[
next] = value;
180 merged_next.push_back(state_end);
181 merged_next[v_prev] =
next;
182 merged_face_corners.push_back(
next);
190bool TopologyRefinerFactory<OsdMesh>::assignFaceVaryingTopology(TopologyRefiner &refiner,
191 OsdMesh
const &osd_mesh)
193 const Mesh &mesh = osd_mesh.mesh;
194 auto &merged_fvars =
const_cast<OsdMesh &
>(osd_mesh).merged_fvars;
197 if (!osd_mesh.use_smooth_fvar(subd_attr)) {
202 OsdMesh::MergedFVar merged_fvar{subd_attr};
204 vector<int> merged_next;
205 vector<int> merged_face_corners;
208 merge_smooth_fvar<uchar4>(mesh, subd_attr, merged_fvar, merged_next, merged_face_corners);
211 merge_smooth_fvar<float>(mesh, subd_attr, merged_fvar, merged_next, merged_face_corners);
214 merge_smooth_fvar<float2>(mesh, subd_attr, merged_fvar, merged_next, merged_face_corners);
217 merge_smooth_fvar<float3>(mesh, subd_attr, merged_fvar, merged_next, merged_face_corners);
220 merge_smooth_fvar<float4>(mesh, subd_attr, merged_fvar, merged_next, merged_face_corners);
224 merged_fvar.channel = createBaseFVarChannel(refiner, merged_next.size());
227 for (
int f = 0,
i = 0; f < num_base_faces; f++) {
228 Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner, f, merged_fvar.channel);
229 const int num_corners = dst_face_uvs.size();
230 for (
int corner = 0; corner < num_corners; corner++) {
231 dst_face_uvs[corner] = merged_face_corners[
i++];
235 merged_fvars.push_back(std::move(merged_fvar));
242void TopologyRefinerFactory<OsdMesh>::reportInvalidTopology(TopologyError ,
244 OsdMesh
const &osd_mesh)
246 const Mesh &mesh = osd_mesh.mesh;
247 LOG_WARNING <<
"Invalid subdivision topology for '" << mesh.
name.c_str() <<
"': " << msg;
255Sdc::Options OsdMesh::sdc_options()
258 switch (mesh.get_subdivision_fvar_interpolation()) {
260 options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_NONE);
263 options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_CORNERS_ONLY);
266 options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_CORNERS_PLUS1);
269 options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_CORNERS_PLUS2);
272 options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_BOUNDARIES);
275 options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_ALL);
278 switch (mesh.get_subdivision_boundary_interpolation()) {
280 options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_NONE);
283 options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
286 options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_AND_CORNER);
292bool OsdMesh::use_smooth_fvar(
const Attribute &attr)
const
299bool OsdMesh::use_smooth_fvar()
const
302 if (use_smooth_fvar(attr)) {
312void OsdData::build(OsdMesh &osd_mesh)
315 refiner.reset(Far::TopologyRefinerFactory<OsdMesh>::Create(
317 Far::TopologyRefinerFactory<OsdMesh>::Options(Sdc::SCHEME_CATMARK, osd_mesh.sdc_options())));
320 const bool has_fvar = osd_mesh.use_smooth_fvar();
321 const int max_isolation = 3;
323 Far::TopologyRefiner::AdaptiveOptions adaptive_options(max_isolation);
324 adaptive_options.considerFVarChannels = has_fvar;
325 adaptive_options.useInfSharpPatch =
true;
326 refiner->RefineAdaptive(adaptive_options);
329 Far::PatchTableFactory::Options patch_options;
330 patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
331 patch_options.generateFVarTables = has_fvar;
332 patch_options.generateFVarLegacyLinearPatches =
false;
333 patch_options.useInfSharpPatch =
true;
335 patch_table.reset(Far::PatchTableFactory::Create(*refiner, patch_options));
338 const int num_refiner_verts = refiner->GetNumVerticesTotal();
339 const int num_local_points = patch_table->GetNumLocalPoints();
340 const int num_base_verts = osd_mesh.mesh.get_num_subd_base_verts();
341 const float3 *verts_data = osd_mesh.mesh.get_verts().data();
343 refined_verts.resize(num_refiner_verts + num_local_points);
344 for (
int i = 0;
i < num_base_verts;
i++) {
345 refined_verts[
i].value = verts_data[
i];
348 OsdValue<float3> *src = refined_verts.data();
349 for (
int i = 0;
i < refiner->GetMaxLevel();
i++) {
350 OsdValue<float3> *dest = src + refiner->GetLevel(
i).GetNumVertices();
351 Far::PrimvarRefiner(*refiner).Interpolate(
i + 1, src, dest);
355 if (num_local_points) {
356 patch_table->ComputeLocalPointValues(refined_verts.data(), &refined_verts[num_refiner_verts]);
360 patch_map = make_unique<Far::PatchMap>(*patch_table);
368 const Far::PatchTable::PatchHandle &handle = *osd_data.patch_map->FindPatch(
369 patch_index, (
double)u, (
double)
v);
371 float p_weights[20], du_weights[20], dv_weights[20];
372 osd_data.patch_table->EvaluateBasis(handle, u,
v, p_weights, du_weights, dv_weights);
374 const Far::ConstIndexArray cv = osd_data.patch_table->GetPatchVertices(handle);
382 for (
int i = 0;
i < cv.size();
i++) {
383 const float3 p = osd_data.refined_verts[cv[
i]].value;
386 *
P += p * p_weights[
i];
388 du += p * du_weights[
i];
389 dv += p * dv_weights[
i];
ATTR_WARN_UNUSED_RESULT const BMVert * v
list< Attribute > attributes
CCL_NAMESPACE_BEGIN struct Options options
#define CCL_NAMESPACE_END
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
@ ATTR_SUBDIVIDE_SMOOTH_FVAR
@ ATTR_ELEMENT_CORNER_BYTE
ccl_device_inline float3 safe_normalize_fallback(const float3 a, const float3 fallback)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
static bool same_storage(const TypeDesc a, const TypeDesc b)
size_t get_num_subd_faces() const
size_t get_num_subd_base_verts() const
AttributeSet subd_attributes
@ SUBDIVISION_FVAR_LINEAR_NONE
@ SUBDIVISION_FVAR_LINEAR_CORNERS_PLUS2
@ SUBDIVISION_FVAR_LINEAR_CORNERS_ONLY
@ SUBDIVISION_FVAR_LINEAR_ALL
@ SUBDIVISION_FVAR_LINEAR_BOUNDARIES
@ SUBDIVISION_FVAR_LINEAR_CORNERS_PLUS1
SubdFace get_subd_face(const size_t index) const
SubdEdgeCrease get_subd_crease(const size_t i) const
@ SUBDIVISION_BOUNDARY_EDGE_ONLY
@ SUBDIVISION_BOUNDARY_EDGE_AND_CORNER
@ SUBDIVISION_BOUNDARY_NONE