23# include <opensubdiv/far/patchMap.h>
24# include <opensubdiv/far/patchTableFactory.h>
25# include <opensubdiv/far/primvarRefiner.h>
26# include <opensubdiv/far/topologyRefinerFactory.h>
31namespace OPENSUBDIV_VERSION {
34bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner &refiner,
35 ccl::Mesh
const &mesh)
37 setNumBaseVertices(refiner, mesh.get_verts().size());
38 setNumBaseFaces(refiner, mesh.get_num_subd_faces());
40 for (
int i = 0; i < mesh.get_num_subd_faces(); i++) {
41 setNumBaseFaceVertices(refiner, i, mesh.get_subd_num_corners()[i]);
48bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner &refiner,
49 ccl::Mesh
const &mesh)
51 const ccl::array<int> &subd_face_corners = mesh.get_subd_face_corners();
52 const ccl::array<int> &subd_start_corner = mesh.get_subd_start_corner();
53 const ccl::array<int> &subd_num_corners = mesh.get_subd_num_corners();
55 for (
int i = 0; i < mesh.get_num_subd_faces(); i++) {
56 IndexArray face_verts = getBaseFaceVertices(refiner, i);
58 int start_corner = subd_start_corner[i];
59 int *corner = &subd_face_corners[start_corner];
61 for (
int j = 0; j < subd_num_corners[i]; j++, corner++) {
62 face_verts[j] = *corner;
70bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner,
71 ccl::Mesh
const &mesh)
74 static constexpr float CREASE_SCALE = 10.0f;
76 size_t num_creases = mesh.get_subd_creases_weight().size();
77 size_t num_vertex_creases = mesh.get_subd_vert_creases().size();
80 if (num_creases == 0 && num_vertex_creases == 0) {
84 for (
int i = 0; i < num_creases; i++) {
86 Index edge = findBaseEdge(refiner, crease.
v[0], crease.
v[1]);
89 setBaseEdgeSharpness(refiner, edge, crease.
crease * CREASE_SCALE);
93 std::map<int, float> vertex_creases;
95 for (
size_t i = 0; i < num_vertex_creases; ++i) {
96 const int vertex_idx = mesh.get_subd_vert_creases()[i];
97 const float weight = mesh.get_subd_vert_creases_weight()[i];
99 vertex_creases[vertex_idx] = weight * CREASE_SCALE;
102 for (
int i = 0; i < mesh.get_verts().
size(); i++) {
103 float sharpness = 0.0f;
104 std::map<int, float>::const_iterator iter = vertex_creases.find(i);
106 if (iter != vertex_creases.end()) {
107 sharpness = iter->second;
110 ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
112 if (vert_edges.size() == 2) {
113 const float sharpness0 = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
114 const float sharpness1 = refiner.getLevel(0).getEdgeSharpness(vert_edges[1]);
116 sharpness += ccl::min(sharpness0, sharpness1);
117 sharpness = ccl::min(sharpness, CREASE_SCALE);
120 if (sharpness != 0.0f) {
121 setBaseVertexSharpness(refiner, i, sharpness);
129bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner & ,
136void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError ,
151template<
typename T>
struct OsdValue {
156 void Clear(
void * = 0)
158 memset(&value, 0,
sizeof(T));
161 void AddWithWeight(OsdValue<T>
const &src,
float weight)
163 value += src.value * weight;
167template<>
void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4>
const &src,
float weight)
169 for (
int i = 0; i < 4; i++) {
170 value[i] += (
uchar)(src.value[i] * weight);
179 Far::TopologyRefiner *refiner;
180 Far::PatchTable *patch_table;
181 Far::PatchMap *patch_map;
184 OsdData() : mesh(
NULL), refiner(
NULL), patch_table(
NULL), patch_map(
NULL) {}
193 void build_from_mesh(
Mesh *mesh_)
198 Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
201 options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
204 refiner = Far::TopologyRefinerFactory<Mesh>::Create(
205 *mesh, Far::TopologyRefinerFactory<Mesh>::Options(type,
options));
208 int max_isolation = calculate_max_isolation();
209 refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
212 Far::PatchTableFactory::Options patch_options;
213 patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
215 patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
218 int num_refiner_verts = refiner->GetNumVerticesTotal();
219 int num_local_points = patch_table->GetNumLocalPoints();
221 verts.resize(num_refiner_verts + num_local_points);
222 for (
int i = 0; i < mesh->get_verts().
size(); i++) {
223 verts[i].value = mesh->get_verts()[i];
226 OsdValue<float3> *src =
verts.data();
227 for (
int i = 0; i < refiner->GetMaxLevel(); i++) {
228 OsdValue<float3> *dest = src + refiner->GetLevel(i).GetNumVertices();
229 Far::PrimvarRefiner(*refiner).Interpolate(i + 1, src, dest);
233 if (num_local_points) {
234 patch_table->ComputeLocalPointValues(&
verts[0], &
verts[num_refiner_verts]);
238 patch_map =
new Far::PatchMap(*patch_table);
241 void subdivide_attribute(
Attribute &attr)
243 Far::PrimvarRefiner primvar_refiner(*refiner);
246 int num_refiner_verts = refiner->GetNumVerticesTotal();
247 int num_local_points = patch_table->GetNumLocalPoints();
249 attr.
resize(num_refiner_verts + num_local_points);
252 char *src = attr.
buffer.data();
254 for (
int i = 0; i < refiner->GetMaxLevel(); i++) {
255 char *dest = src + refiner->GetLevel(i).GetNumVertices() * attr.
data_sizeof();
258 primvar_refiner.Interpolate(i + 1, (OsdValue<float> *)src, (OsdValue<float> *&)dest);
261 primvar_refiner.Interpolate(i + 1, (OsdValue<float2> *)src, (OsdValue<float2> *&)dest);
266 primvar_refiner.Interpolate(i + 1, (OsdValue<float4> *)src, (OsdValue<float4> *&)dest);
269 primvar_refiner.Interpolate(i + 1, (OsdValue<float3> *)src, (OsdValue<float3> *&)dest);
275 if (num_local_points) {
277 patch_table->ComputeLocalPointValues(
278 (OsdValue<float> *)&attr.
buffer[0],
282 patch_table->ComputeLocalPointValues(
283 (OsdValue<float2> *)&attr.
buffer[0],
289 patch_table->ComputeLocalPointValues(
290 (OsdValue<float4> *)&attr.
buffer[0],
296 patch_table->ComputeLocalPointValues(
297 (OsdValue<float3> *)&attr.
buffer[0],
307 int calculate_max_isolation()
310 const Far::TopologyLevel &level = refiner->GetLevel(0);
311 const SubdParams *subd_params = mesh->get_subd_params();
315 float longest_edge = 0.0f;
317 for (
size_t i = 0; i < level.GetNumEdges(); i++) {
318 Far::ConstIndexArray
verts = level.GetEdgeVertices(i);
332 edge_len =
len(a -
b);
335 longest_edge =
max(longest_edge, edge_len);
339 int isolation = (
int)(log2f(
max(longest_edge / subd_params->
dicing_rate, 1.0f)) + 1.0f);
341 return min(isolation, 10);
344 friend struct OsdPatch;
350struct OsdPatch :
Patch {
354 OsdPatch(OsdData *data) : osd_data(data) {}
358 const Far::PatchTable::PatchHandle *handle = osd_data->patch_map->FindPatch(
359 patch_index, (
double)u, (
double)
v);
362 float p_weights[20], du_weights[20], dv_weights[20];
363 osd_data->patch_table->EvaluateBasis(*handle, u,
v, p_weights, du_weights, dv_weights);
365 Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
373 for (
int i = 0; i < cv.size(); i++) {
374 float3 p = osd_data->verts[cv[i]].value;
377 *
P += p * p_weights[i];
378 du += p * du_weights[i];
379 dv += p * dv_weights[i];
403#ifdef WITH_OPENSUBDIV
405 bool need_packed_patch_table =
false;
409 osd_data.build_from_mesh(
this);
422 attr.
flags &= ~ATTR_SUBDIVIDED;
433 for (
int f = 0; f < num_faces; f++) {
436 if (face.is_quad()) {
440 num_patches += face.num_corners;
445#ifdef WITH_OPENSUBDIV
448 OsdPatch *patch = osd_patches.data();
450 for (
int f = 0; f < num_faces; f++) {
453 if (face.is_quad()) {
454 patch->patch_index = face.ptex_offset;
455 patch->from_ngon =
false;
456 patch->shader = face.shader;
460 for (
int corner = 0; corner < face.num_corners; corner++) {
461 patch->patch_index = face.ptex_offset + corner;
462 patch->from_ngon =
true;
463 patch->shader = face.shader;
470 split->split_patches(osd_patches.data(),
sizeof(OsdPatch));
478 for (
int f = 0; f < num_faces; f++) {
481 if (face.is_quad()) {
488 for (
int i = 0; i < 4; i++) {
489 hull[i] =
verts[subd_face_corners[face.start_corner + i]];
493 for (
int i = 0; i < 4; i++) {
494 normals[i] = vN[subd_face_corners[face.start_corner + i]];
499 for (
int i = 0; i < 4; i++) {
504 swap(hull[2], hull[3]);
505 swap(normals[2], normals[3]);
507 patch->
shader = face.shader;
515 float inv_num_corners = 1.0f /
float(face.num_corners);
516 for (
int corner = 0; corner < face.num_corners; corner++) {
517 center_vert +=
verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
518 center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
521 for (
int corner = 0; corner < face.num_corners; corner++) {
528 patch->
shader = face.shader;
531 verts[subd_face_corners[face.start_corner +
mod(corner + 0, face.num_corners)]];
533 verts[subd_face_corners[face.start_corner +
mod(corner + 1, face.num_corners)]];
535 verts[subd_face_corners[face.start_corner +
mod(corner - 1, face.num_corners)]];
536 hull[3] = center_vert;
538 hull[1] = (hull[1] + hull[0]) * 0.5;
539 hull[2] = (hull[2] + hull[0]) * 0.5;
543 vN[subd_face_corners[face.start_corner +
mod(corner + 0, face.num_corners)]];
545 vN[subd_face_corners[face.start_corner +
mod(corner + 1, face.num_corners)]];
547 vN[subd_face_corners[face.start_corner +
mod(corner - 1, face.num_corners)]];
548 normals[3] = center_normal;
550 normals[1] = (normals[1] + normals[0]) * 0.5;
551 normals[2] = (normals[2] + normals[0]) * 0.5;
555 for (
int i = 0; i < 4; i++) {
571#ifdef WITH_OPENSUBDIV
575 attr.
flags &= ~ATTR_SUBDIVIDED;
578 osd_data.subdivide_attribute(attr);
580 need_packed_patch_table =
true;
586 char *data = attr.
data();
592 for (
int f = 0; f < num_faces; f++) {
595 if (!face.is_quad()) {
596 char *center = data + (
verts.size() - num_subd_verts + ngons) * stride;
599 float inv_num_corners = 1.0f /
float(face.num_corners);
601 for (
int corner = 0; corner < face.num_corners; corner++) {
603 data + subd_face_corners[face.start_corner + corner] * stride,
617 for (
int f = 0; f < num_faces; f++) {
620 if (!face.is_quad()) {
621 char *center = data + (subd_face_corners.size() + ngons) * stride;
624 float inv_num_corners = 1.0f /
float(face.num_corners);
626 for (
int corner = 0; corner < face.num_corners; corner++) {
628 center, data + (face.start_corner + corner) * stride, inv_num_corners);
637 for (
int f = 0; f < num_faces; f++) {
640 if (!face.is_quad()) {
641 uchar *center = (
uchar *)data + (subd_face_corners.size() + ngons) * stride;
643 float inv_num_corners = 1.0f /
float(face.num_corners);
646 for (
int corner = 0; corner < face.num_corners; corner++) {
647 for (
int i = 0; i < 4; i++) {
648 val[i] +=
float(*(data + (face.start_corner + corner) * stride + i)) *
653 for (
int i = 0; i < 4; i++) {
667#ifdef WITH_OPENSUBDIV
669 if (need_packed_patch_table) {
672 patch_table->
pack(osd_data.patch_table);
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
list< Attribute > attributes
Attribute * find(ustring name) const
static bool same_storage(TypeDesc a, TypeDesc b)
void add_with_weight(void *dst, void *src, float weight)
void resize(Geometry *geom, AttributePrimitive prim, bool reserve_only)
void zero_data(void *dst)
size_t data_sizeof() const
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)=0
local_group_size(16, 16) .push_constant(Type b
CCL_NAMESPACE_BEGIN struct Options options
#define CCL_NAMESPACE_END
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
@ ATTR_ELEMENT_CORNER_BYTE
@ ATTR_ELEMENT_VERTEX_MOTION
ccl_device_inline float cross(const float2 a, const float2 b)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
CCL_NAMESPACE_BEGIN static OIIO_NAMESPACE_USING constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)
float world_to_raster_size(float3 P)
void tessellate(DiagSplit *split)
size_t get_num_subd_faces() const
AttributeSet subd_attributes
@ SUBDIVISION_CATMULL_CLARK
SubdFace get_subd_face(size_t index) const
void pack(Far::PatchTable *patch_table, int offset=0)
ccl_device_inline int mod(int x, int m)