23# include <opensubdiv/far/patchMap.h>
24# include <opensubdiv/far/patchTableFactory.h>
25# include <opensubdiv/far/primvarRefiner.h>
26# include <opensubdiv/far/topologyRefinerFactory.h>
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++) {
85 ccl::Mesh::SubdEdgeCrease crease = mesh.get_subd_crease(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);
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);
433 for (
int f = 0; f < num_faces; f++) {
445#ifdef WITH_OPENSUBDIV
448 OsdPatch *patch = osd_patches.data();
450 for (
int f = 0; f < num_faces; f++) {
455 patch->from_ngon =
false;
456 patch->shader = face.
shader;
460 for (
int corner = 0; corner < face.
num_corners; 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++) {
488 for (
int i = 0; i < 4; i++) {
493 for (
int i = 0; i < 4; i++) {
499 for (
int i = 0; i < 4; i++) {
504 swap(hull[2], hull[3]);
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++) {
536 hull[3] = center_vert;
538 hull[1] = (hull[1] + hull[0]) * 0.5;
539 hull[2] = (hull[2] + hull[0]) * 0.5;
555 for (
int i = 0; i < 4; i++) {
571#ifdef WITH_OPENSUBDIV
578 osd_data.subdivide_attribute(attr);
580 need_packed_patch_table =
true;
592 for (
int f = 0; f < num_faces; f++) {
596 char *center =
data + (
verts.size() - num_subd_verts + ngons) * stride;
601 for (
int corner = 0; corner < face.
num_corners; corner++) {
617 for (
int f = 0; f < num_faces; f++) {
621 char *center =
data + (subd_face_corners.size() + ngons) * stride;
626 for (
int corner = 0; corner < face.
num_corners; corner++) {
637 for (
int f = 0; f < num_faces; f++) {
641 uchar *center = (
uchar *)
data + (subd_face_corners.size() + ngons) * stride;
646 for (
int corner = 0; corner < face.
num_corners; corner++) {
647 for (
int i = 0; i < 4; 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);
static void split(const char *text, const char *seps, char ***str, int *count)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Attribute
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
VecBase< float, 3 > float3
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
static float normals[][3]
@ 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)
float3 normal(const Mesh *mesh) const
void tessellate(DiagSplit *split)
SubdParams * get_subd_params()
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)
VecBase< float, 4 > float4
ccl_device_inline int mod(int x, int m)