63 if (
mesh.get_num_subd_faces() == 0) {
67 for (
const Attribute &subd_attr :
mesh.subd_attributes.attributes) {
133 const int motion_step)
137 const typename T::Type *subd_data =
reinterpret_cast<const typename T::Type *
>(
139 motion_step *
mesh.get_num_subd_base_verts();
140 typename T::Type *mesh_data =
reinterpret_cast<typename T::Type *
>(mesh_attr.
data()) +
141 motion_step *
mesh.get_verts().size();
143 assert(mesh_data !=
nullptr);
145 attr.
interp = [
this, subd_data, mesh_data](
const int ,
146 const int face_index,
148 const int *vert_index,
150 const int vert_num) {
152 const int *subd_face_corners =
mesh.get_subd_face_corners().data();
158 const typename T::AccumType value0 = T::read(
160 const typename T::AccumType value1 = T::read(
162 const typename T::AccumType value2 = T::read(
164 const typename T::AccumType value3 = T::read(
167 for (
int i = 0;
i < vert_num;
i++) {
169 const typename T::AccumType value =
interp(
171 mesh_data[vert_index[
i]] = T::output(value);
178 typename T::AccumType value_center = T::read(
181 value_center += T::read(subd_data[subd_face_corners[face.
start_corner + j]]);
186 const typename T::AccumType value_corner = T::read(
187 subd_data[subd_face_corners[face.
start_corner + corner]]);
188 const typename T::AccumType value_prev =
189 0.5f * (value_corner +
192 const typename T::AccumType value_next =
193 0.5f * (value_corner +
197 for (
int i = 0;
i < vert_num;
i++) {
201 const typename T::AccumType value =
interp(
202 interp(value_corner, value_next, uv.
x),
interp(value_prev, value_center, uv.
x), uv.
y);
204 mesh_data[vert_index[
i]] = T::output(value);
212#ifdef WITH_OPENSUBDIV
214void SubdAttributeInterpolation::setup_attribute_vertex_smooth(
const Attribute &subd_attr,
216 const int motion_step)
222 const int num_refiner_verts = osd_data.refiner->GetNumVerticesTotal();
223 const int num_local_points = osd_data.patch_table->GetNumLocalPoints();
227 attr.
refined_data.resize((num_refiner_verts + num_local_points) *
sizeof(
typename T::AccumType));
228 typename T::AccumType *subd_data =
reinterpret_cast<typename T::AccumType *
>(
231 const typename T::Type *base_src =
reinterpret_cast<const typename T::Type *
>(subd_attr.
data()) +
232 num_base_verts * motion_step;
233 typename T::AccumType *base_dst = subd_data;
234 for (
int i = 0;
i < num_base_verts;
i++) {
235 base_dst[
i] = T::read(base_src[
i]);
238 Far::PrimvarRefiner primvar_refiner(*osd_data.refiner);
239 typename T::AccumType *src = subd_data;
240 for (
int i = 0;
i < osd_data.refiner->GetMaxLevel();
i++) {
241 typename T::AccumType *dest = src + osd_data.refiner->GetLevel(
i).GetNumVertices();
242 primvar_refiner.Interpolate(
243 i + 1, (OsdValue<typename T::AccumType> *)src, (OsdValue<typename T::AccumType> *&)dest);
247 if (num_local_points) {
248 osd_data.patch_table->ComputeLocalPointValues(
249 (OsdValue<typename T::AccumType> *)subd_data,
250 (OsdValue<typename T::AccumType> *)(subd_data + num_refiner_verts));
254 typename T::Type *mesh_data =
reinterpret_cast<typename T::Type *
>(mesh_attr.
data()) +
255 mesh.get_verts().size() * motion_step;
257 assert(mesh_data !=
nullptr);
260 float3 *mesh_normal_data =
nullptr;
261 if constexpr (std::is_same_v<typename T::Type, float3>) {
264 mesh_normal_data = attr_normal->
data_float3() +
mesh.get_verts().size() * motion_step;
268 attr.
interp = [
this, subd_data, mesh_data, mesh_normal_data](
const int patch_index,
271 const int *vert_index,
273 const int vert_num) {
274 for (
int i = 0;
i < vert_num;
i++) {
278 const Far::PatchTable::PatchHandle &handle = *osd_data.patch_map->FindPatch(
279 patch_index, (
double)uv.
x, (
double)uv.
y);
281 float p_weights[20], du_weights[20], dv_weights[20];
282 osd_data.patch_table->EvaluateBasis(handle, uv.
x, uv.
y, p_weights, du_weights, dv_weights);
283 Far::ConstIndexArray cv = osd_data.patch_table->GetPatchVertices(handle);
286 typename T::AccumType value = subd_data[cv[0]] * p_weights[0];
287 for (
int k = 1; k < cv.size(); k++) {
288 value += subd_data[cv[k]] * p_weights[k];
290 mesh_data[vert_index[
i]] = T::output(value);
293 if (mesh_normal_data) {
294 if constexpr (std::is_same_v<typename T::Type, float3>) {
297 for (
int k = 0; k < cv.size(); k++) {
298 const float3 p = subd_data[cv[k]];
299 du += p * du_weights[k];
300 dv += p * dv_weights[k];
321 const typename T::Type *subd_data =
reinterpret_cast<const typename T::Type *
>(subd_attr.
data());
322 typename T::Type *mesh_data =
reinterpret_cast<typename T::Type *
>(mesh_attr.
data());
324 assert(mesh_data !=
nullptr);
326 attr.
interp = [
this, subd_data, mesh_data](
const int ,
327 const int face_index,
329 const int *triangle_index,
330 const float2 *triangle_uv,
331 const int triangle_num) {
336 const typename T::AccumType value0 = T::read(subd_data[face.
start_corner + 0]);
337 const typename T::AccumType value1 = T::read(subd_data[face.
start_corner + 1]);
338 const typename T::AccumType value2 = T::read(subd_data[face.
start_corner + 2]);
339 const typename T::AccumType value3 = T::read(subd_data[face.
start_corner + 3]);
341 for (
size_t i = 0;
i < triangle_num;
i++) {
342 for (
int j = 0; j < 3; j++) {
343 const float2 uv = triangle_uv[(
i * 3) + j];
344 const typename T::AccumType value =
interp(
346 mesh_data[triangle_index[
i] * 3 + j] = T::output(value);
354 typename T::AccumType value_center = T::read(subd_data[face.
start_corner]);
356 value_center += T::read(subd_data[face.
start_corner + j]);
361 const typename T::AccumType value_corner = T::read(subd_data[face.
start_corner + corner]);
362 const typename T::AccumType value_prev =
363 0.5f * (value_corner +
365 const typename T::AccumType value_next =
366 0.5f * (value_corner +
369 for (
size_t i = 0;
i < triangle_num;
i++) {
370 for (
int j = 0; j < 3; j++) {
371 const float2 uv = triangle_uv[(
i * 3) + j];
374 const typename T::AccumType value =
interp(
interp(value_corner, value_next, uv.
x),
375 interp(value_prev, value_center, uv.
x),
378 mesh_data[triangle_index[
i] * 3 + j] = T::output(value);
387#ifdef WITH_OPENSUBDIV
389void SubdAttributeInterpolation::setup_attribute_corner_smooth(
Attribute &mesh_attr,
396 const int num_refiner_fvars = osd_data.refiner->GetNumFVarValuesTotal(channel);
397 const int num_local_points = osd_data.patch_table->GetNumLocalPointsFaceVarying(channel);
398 const int num_base_fvars = osd_data.refiner->GetLevel(0).GetNumFVarValues(channel);
401 attr.
refined_data.resize((num_refiner_fvars + num_local_points) *
sizeof(
typename T::AccumType));
402 typename T::AccumType *refined_data =
reinterpret_cast<typename T::AccumType *
>(
405 const typename T::Type *base_src =
reinterpret_cast<const typename T::Type *
>(
406 merged_values.data());
407 typename T::AccumType *base_dst = refined_data;
408 for (
int i = 0;
i < num_base_fvars;
i++) {
409 base_dst[
i] = T::read(base_src[
i]);
412 Far::PrimvarRefiner primvar_refiner(*osd_data.refiner);
413 typename T::AccumType *src = refined_data;
414 for (
int i = 0;
i < osd_data.refiner->GetMaxLevel();
i++) {
415 typename T::AccumType *dest = src + osd_data.refiner->GetLevel(
i).GetNumFVarValues(channel);
416 primvar_refiner.InterpolateFaceVarying(
i + 1,
417 (OsdValue<typename T::AccumType> *)src,
418 (OsdValue<typename T::AccumType> *&)dest,
423 if (num_local_points) {
424 osd_data.patch_table->ComputeLocalPointValuesFaceVarying(
425 (OsdValue<typename T::AccumType> *)refined_data,
426 (OsdValue<typename T::AccumType> *)(refined_data + num_refiner_fvars),
431 const typename T::AccumType *subd_data = refined_data;
432 typename T::Type *mesh_data =
reinterpret_cast<typename T::Type *
>(mesh_attr.
data());
434 assert(mesh_data !=
nullptr);
436 attr.
interp = [
this, subd_data, mesh_data, channel](
const int patch_index,
439 const int *triangle_index,
440 const float2 *triangle_uv,
441 const int triangle_num) {
442 for (
size_t i = 0;
i < triangle_num;
i++) {
443 for (
int j = 0; j < 3; j++) {
445 const float2 uv = triangle_uv[(
i * 3) + j];
446 const Far::PatchTable::PatchHandle &handle = *osd_data.patch_map->FindPatch(
447 patch_index, (
double)uv.
x, (
double)uv.
y);
449 float p_weights[20], du_weights[20], dv_weights[20];
450 osd_data.patch_table->EvaluateBasisFaceVarying(handle,
460 Far::ConstIndexArray cv = osd_data.patch_table->GetPatchFVarValues(handle, channel);
463 typename T::AccumType value = subd_data[cv[0]] * p_weights[0];
464 for (
int k = 1; k < cv.size(); k++) {
465 value += subd_data[cv[k]] * p_weights[k];
467 mesh_data[triangle_index[
i] * 3 + j] = T::output(value);
482 const typename T::Type *subd_data =
reinterpret_cast<const typename T::Type *
>(subd_attr.
data());
483 typename T::Type *mesh_data =
reinterpret_cast<typename T::Type *
>(mesh_attr.
data());
485 assert(mesh_data !=
nullptr);
487 attr.
interp = [subd_data, mesh_data](
const int ,
488 const int face_index,
490 const int *triangle_index,
492 const int triangle_num) {
493 for (
int i = 0;
i < triangle_num;
i++) {
494 mesh_data[triangle_index[
i]] = subd_data[face_index];
507#ifdef WITH_OPENSUBDIV
510 switch (subd_attr.
std) {
514 setup_attribute_vertex_smooth<T>(subd_attr, mesh_attr);
530#ifdef WITH_OPENSUBDIV
531 if (osd_mesh.use_smooth_fvar(subd_attr)) {
532 for (
const auto &merged_fvar : osd_mesh.merged_fvars) {
533 if (&merged_fvar.attr == &subd_attr) {
534 if constexpr (std::is_same_v<typename T::Type, float2>) {
535 setup_attribute_corner_smooth<T>(mesh_attr, merged_fvar.channel, merged_fvar.values);
548#ifdef WITH_OPENSUBDIV
550 setup_attribute_vertex_smooth<T>(subd_attr, mesh_attr,
step);
void setup_attribute_face(const Attribute &subd_attr, Attribute &mesh_attr)
SubdAttributeInterpolation(Mesh &mesh)
void setup_attribute_type(const Attribute &subd_attr, Attribute &mesh_attr)
void setup_attribute(const Attribute &subd_attr, Attribute &mesh_attr)
vector< SubdAttribute > triangle_attributes
bool support_interp_attribute(const Attribute &attr) const
void setup_attribute_vertex_linear(const Attribute &subd_attr, Attribute &mesh_attr, const int motion_step=0)
vector< SubdAttribute > vertex_attributes
void setup_attribute_corner_linear(const Attribute &subd_attr, Attribute &mesh_attr)
ccl_device_inline float4 color_uchar4_to_float4(const uchar4 c)
ccl_device uchar4 color_float4_to_uchar4(const float4 c)
#define CCL_NAMESPACE_END
#define assert(assertion)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
VecBase< float, 2 > float2
VecBase< float, 3 > float3
@ ATTR_STD_MOTION_VERTEX_NORMAL
@ ATTR_STD_POSITION_UNDISPLACED
@ ATTR_STD_POSITION_UNDEFORMED
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_ELEMENT_CORNER_BYTE
@ ATTR_ELEMENT_VERTEX_MOTION
ccl_device_inline float interp(const float a, const float b, const float t)
ccl_device_inline float3 safe_normalize_fallback(const float3 a, const float3 fallback)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
static bool same_storage(const TypeDesc a, const TypeDesc b)
size_t get_num_subd_base_verts() const
@ SUBDIVISION_CATMULL_CLARK
std::function< void(const int, const int, const int, const int *, const float2 *, const int)> interp
vector< char > refined_data
static AccumType read(const Type &value)
static Type output(const AccumType &value)
static Type read(const Type &value)
static Type output(const Type &value)