37 const float motion_scale)
39 const int numverts = mesh->get_verts().size();
42 mesh->set_motion_steps(3);
49 float3 *
P = mesh->get_verts().data();
57 const float motion_times[2] = {-1.0f, 1.0f};
59 const float relative_time = motion_times[
step] * 0.5f * motion_scale;
62 for (
int i = 0;
i < numverts;
i++) {
63 mP[
i] =
P[
i] +
make_float3(b_attr[
i][0], b_attr[
i][1], b_attr[
i][2]) * relative_time;
71 const bool subdivision,
72 const bool need_motion,
73 const float motion_scale)
78 corner_tris = b_mesh.corner_tris();
79 tri_faces = b_mesh.corner_tri_faces();
83 static const ustring u_velocity(
"velocity");
84 const ustring default_color_name{
88 const ustring name{std::string_view(iter.
name)};
89 const bool is_render_color = name == default_color_name;
91 if (need_motion && name == u_velocity) {
102 if (attributes.
find(name)) {
120 if (is_render_color) {
135 src[tri[0]][0], src[tri[0]][1], src[tri[0]][2], src[tri[0]][3]);
137 src[tri[1]][0], src[tri[1]][1], src[tri[1]][2], src[tri[1]][3]);
139 src[tri[2]][0], src[tri[2]][1], src[tri[2]][2], src[tri[2]][3]);
162 using BlenderT = decltype(dummy);
163 using Converter = typename ccl::AttributeConverter<BlenderT>;
164 using CyclesT = typename Converter::CyclesT;
165 if constexpr (!std::is_void_v<CyclesT>) {
166 Attribute *attr = attributes.add(name, Converter::type_desc, element);
167 if (is_render_color) {
168 attr->std = ATTR_STD_VERTEX_COLOR;
171 CyclesT *data = reinterpret_cast<CyclesT *>(attr->data());
173 const blender::VArraySpan src = b_attr.varray.typed<BlenderT>();
174 switch (b_attr.domain) {
175 case blender::bke::AttrDomain::Corner: {
177 for (const int i : src.index_range()) {
178 data[i] = Converter::convert(src[i]);
182 for (const int i : corner_tris.index_range()) {
183 const blender::int3 &tri = corner_tris[i];
184 data[i * 3 + 0] = Converter::convert(src[tri[0]]);
185 data[i * 3 + 1] = Converter::convert(src[tri[1]]);
186 data[i * 3 + 2] = Converter::convert(src[tri[2]]);
191 case blender::bke::AttrDomain::Point: {
192 for (const int i : src.index_range()) {
193 data[i] = Converter::convert(src[i]);
197 case blender::bke::AttrDomain::Face: {
199 for (const int i : src.index_range()) {
200 data[i] = Converter::convert(src[i]);
204 for (const int i : corner_tris.index_range()) {
205 data[i] = Converter::convert(src[tri_faces[i]]);
222 set<ustring> uv_names;
226 uv_names.emplace(std::string_view(iter.
name));
236 const ::Mesh &b_mesh,
237 const set<ustring> &blender_uv_names)
242 if (blender_uv_names.empty()) {
246 for (
const ustring &uv_name : blender_uv_names) {
247 const bool active_render = uv_name == render_name;
250 const ustring tangent_name = ustring((
string(uv_name) +
".tangent").c_str());
256 const bool need_tangent = mesh->
need_attribute(scene, tangent_name) ||
261 if (need_uv || need_tangent) {
274 fdata[
i * 3 + 0] =
make_float2(b_uv_map[tri[0]][0], b_uv_map[tri[0]][1]);
275 fdata[
i * 3 + 1] =
make_float2(b_uv_map[tri[1]][0], b_uv_map[tri[1]][1]);
276 fdata[
i * 3 + 2] =
make_float2(b_uv_map[tri[2]][0], b_uv_map[tri[2]][1]);
284 const ::Mesh &b_mesh,
285 const set<ustring> &blender_uv_names)
288 if (
faces.is_empty()) {
292 if (blender_uv_names.empty()) {
298 for (
const ustring &uv_name : blender_uv_names) {
299 const bool active_render = uv_name == render_name;
302 const ustring tangent_name = ustring((
string(uv_name) +
".tangent").c_str());
308 const bool need_tangent = mesh->
need_attribute(scene, tangent_name) ||
314 if (need_uv || need_tangent) {
328 for (
const int i :
faces.index_range()) {
330 for (
const int corner : face) {
331 *(fdata++) =
make_float2(b_uv_map[corner][0], b_uv_map[corner][1]);
345 bool operator()(
const int &vert_idx_a,
const int &vert_idx_b)
349 if (vert_a == vert_b) {
351 return vert_idx_a > vert_idx_b;
353 const float x1 = vert_a.
x + vert_a.
y + vert_a.
z;
354 const float x2 = vert_b.
x + vert_b.
y + vert_b.
z;
368 const int num_verts = positions.
size();
377 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
378 sorted_vert_indeices[vert_index] = vert_index;
381 sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
386 for (
int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) {
387 const int vert_index = sorted_vert_indeices[sorted_vert_index];
388 const float3 &vert_co = mesh->get_verts()[vert_index];
390 for (
int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts;
391 ++other_sorted_vert_index)
393 const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index];
394 const float3 &other_vert_co = mesh->get_verts()[other_vert_index];
396 if ((other_vert_co.
x + other_vert_co.
y + other_vert_co.
z) -
397 (vert_co.
x + vert_co.
y + vert_co.
z) >
403 if (
len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
405 vert_orig_index[vert_index] = other_vert_index;
410 vert_orig_index[vert_index] = vert_index;
414 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
415 int orig_index = vert_orig_index[vert_index];
416 while (orig_index != vert_orig_index[orig_index]) {
417 orig_index = vert_orig_index[orig_index];
419 vert_orig_index[vert_index] = orig_index;
427 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
428 const float *b_vert_normal = b_vert_normals[vert_index];
429 const int orig_index = vert_orig_index[vert_index];
430 vert_normal[orig_index] +=
make_float3(b_vert_normal[0], b_vert_normal[1], b_vert_normal[2]);
435 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
436 const int orig_index = vert_orig_index[vert_index];
437 vert_normal[vert_index] =
normalize(vert_normal[orig_index]);
444 memset(counter.data(), 0,
sizeof(
int) * counter.size());
448 const int v0 = vert_orig_index[b_edge[0]];
449 const int v1 = vert_orig_index[b_edge[1]];
450 if (visited_edges.
exists(v0, v1)) {
453 visited_edges.
insert(v0, v1);
454 const float3 co0 =
make_float3(positions[v0][0], positions[v0][1], positions[v0][2]);
455 const float3 co1 =
make_float3(positions[v1][0], positions[v1][1], positions[v1][2]);
457 edge_accum[v0] += edge;
458 edge_accum[v1] += -edge;
462 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
463 const int orig_index = vert_orig_index[vert_index];
464 if (orig_index != vert_index) {
468 if (counter[vert_index] > 0) {
469 const float3 normal = vert_normal[vert_index];
470 const float angle =
safe_acosf(
dot(normal, edge_accum[vert_index] / counter[vert_index]));
474 raw_data[vert_index] = 0.0f;
481 memcpy(
data, raw_data.data(),
sizeof(
float) * raw_data.size());
482 memset(counter.data(), 0,
sizeof(
int) * counter.size());
483 visited_edges.
clear();
486 const int v0 = vert_orig_index[b_edge[0]];
487 const int v1 = vert_orig_index[b_edge[1]];
488 if (visited_edges.
exists(v0, v1)) {
491 visited_edges.
insert(v0, v1);
492 data[v0] += raw_data[v1];
493 data[v1] += raw_data[v0];
497 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
498 data[vert_index] /= counter[vert_index] + 1;
501 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
502 const int orig_index = vert_orig_index[vert_index];
503 data[vert_index] =
data[orig_index];
519 const ::Mesh &b_mesh,
526 if (b_mesh.verts_num == 0) {
536 vertices_sets.
join(edges[
i][0], edges[
i][1]);
547 const int vert = corner_verts[corner_tris[
i][0]];
554 if (!
faces.is_empty()) {
555 for (
const int i :
faces.index_range()) {
556 const int vert = corner_verts[
faces[
i].start()];
567 const ::Mesh &b_mesh,
569 const bool need_motion,
570 const float motion_scale,
571 const bool subdivision =
false)
578 const int numfaces = (!subdivision) ? b_mesh.corner_tris().size() :
faces.size();
581 (mesh->get_subdivision_type() !=
585 if (
faces.is_empty()) {
594 if (use_corner_normals) {
595 corner_normals = b_mesh.corner_normals();
617 if (subdivision || !(use_corner_normals && !corner_normals.is_empty())) {
620 N[
i] =
make_float3(vert_normals[
i][0], vert_normals[
i][1], vert_normals[
i][2]);
627 const bool need_default_tangent = (subdivision ==
false) && (blender_uv_names.empty()) &&
630 const float(*orco)[3] =
static_cast<const float(*)[3]
>(
638 float texspace_location[3];
639 float texspace_size[3];
652 value = positions[
i];
658 auto clamp_material_index = [&](
const int material_index) ->
int {
659 return clamp(material_index, 0, used_shaders.
size() - 1);
664 int *triangles = mesh->get_triangles().data();
665 bool *smooth = mesh->get_smooth().data();
666 int *shader = mesh->get_shader().data();
671 triangles[
i * 3 + 0] = corner_verts[tri[0]];
672 triangles[
i * 3 + 1] = corner_verts[tri[1]];
673 triangles[
i * 3 + 2] = corner_verts[tri[2]];
679 shader[
i] = clamp_material_index(material_indices[tri_faces[
i]]);
683 std::fill(shader, shader + numtris, 0);
686 if (!sharp_faces.is_empty() && !(use_corner_normals && !corner_normals.is_empty())) {
689 smooth[
i] = !sharp_faces[tri_faces[
i]];
697 if (use_corner_normals && !corner_normals.is_empty()) {
700 for (
int i = 0;
i < 3;
i++) {
701 const int corner = tri[
i];
702 const int vert = corner_verts[corner];
703 const float *normal = corner_normals[corner];
709 mesh->tag_triangles_modified();
710 mesh->tag_shader_modified();
711 mesh->tag_smooth_modified();
714 int *subd_start_corner = mesh->get_subd_start_corner().data();
715 int *subd_num_corners = mesh->get_subd_num_corners().data();
716 int *subd_shader = mesh->get_subd_shader().data();
717 bool *subd_smooth = mesh->get_subd_smooth().data();
718 int *subd_ptex_offset = mesh->get_subd_ptex_offset().data();
719 int *subd_face_corners = mesh->get_subd_face_corners().data();
721 if (!sharp_faces.is_empty() && !use_corner_normals) {
722 for (
int i = 0;
i < numfaces;
i++) {
723 subd_smooth[
i] = !sharp_faces[
i];
727 std::fill(subd_smooth, subd_smooth + numfaces,
true);
731 for (
int i = 0;
i < numfaces;
i++) {
732 subd_shader[
i] = clamp_material_index(material_indices[
i]);
736 std::fill(subd_shader, subd_shader + numfaces, 0);
739 std::copy(corner_verts.
data(), corner_verts.
data() + corner_verts.
size(), subd_face_corners);
743 for (
const int i :
faces.index_range()) {
746 subd_start_corner[
i] = face.
start();
747 subd_num_corners[
i] = face.
size();
748 subd_ptex_offset[
i] = ptex_offset;
749 const int num_ptex = (face.
size() == 4) ? 1 : face.
size();
750 ptex_offset += num_ptex;
753 mesh->tag_subd_face_corners_modified();
754 mesh->tag_subd_start_corner_modified();
755 mesh->tag_subd_num_corners_modified();
756 mesh->tag_subd_shader_modified();
757 mesh->tag_subd_smooth_modified();
758 mesh->tag_subd_ptex_offset_modified();
795 const ::Mesh &b_mesh,
797 const bool need_motion,
798 const float motion_scale,
799 const float dicing_rate,
800 const int max_subdivisions)
804 BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
805 const bool use_creases = subsurf_mod.use_creases();
807 create_mesh(scene, mesh, b_mesh, used_shaders, need_motion, motion_scale,
true);
813 size_t num_creases = 0;
815 if (creases[
i] != 0.0f) {
824 const float crease = creases[
i];
825 if (crease != 0.0f) {
836 if (vert_creases[
i] != 0.0f) {
845 const float subd_dicing_rate =
max(0.1f,
RNA_float_get(&cobj,
"dicing_rate") * dicing_rate);
847 mesh->set_subd_dicing_rate(subd_dicing_rate);
848 mesh->set_subd_max_level(max_subdivisions);
849 mesh->set_subd_objecttoworld(
get_transform(b_ob.matrix_world()));
858 array<Node *> used_shaders = mesh->get_used_shaders();
861 new_mesh.set_used_shaders(used_shaders);
863 if (view_layer.use_surfaces) {
870 const float motion_scale = (need_motion) ?
871 scene->motion_shutter_time() /
872 (b_scene.render().fps() / b_scene.render().fps_base()) :
880 *
static_cast<const ::
Mesh *
>(b_mesh.ptr.data),
881 new_mesh.get_used_shaders(),
890 *
static_cast<const ::
Mesh *
>(b_mesh.ptr.data),
891 new_mesh.get_used_shaders(),
905 for (
const SocketType &socket : new_mesh.
type->
inputs) {
907 if (socket.
name ==
"use_motion_blur" || socket.
name ==
"used_shaders") {
910 mesh->
set_value(socket, new_mesh, socket);
919 const bool rebuild = (mesh->triangles_is_modified()) || (mesh->subd_num_corners_is_modified()) ||
920 (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) ||
921 (mesh->subd_ptex_offset_is_modified()) ||
922 (mesh->subd_start_corner_is_modified()) ||
923 (mesh->subd_face_corners_is_modified());
928void BlenderSync::sync_mesh_motion(
BObjectInfo &b_ob_info,
Mesh *mesh,
const int motion_step)
931 const size_t numverts = mesh->get_verts().size();
939 if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
944 const std::string ob_name = b_ob_info.
real_object.name();
948 const ::Mesh &b_mesh = *
static_cast<const ::
Mesh *
>(b_mesh_rna.ptr.data);
949 const int b_verts_num = b_mesh.
verts_num;
950 const blender::Span<blender::float3> positions = b_mesh.vert_positions();
965 bool new_attribute =
false;
973 new_attribute =
true;
977 float3 *mN = (attr_mN) ? attr_mN->
data_float3() + motion_step * numverts :
nullptr;
983 mP[
i] =
make_float3(positions[
i][0], positions[
i][1], positions[
i][2]);
986 const blender::Span<blender::float3> b_vert_normals = b_mesh.vert_normals();
988 mN[
i] =
make_float3(b_vert_normals[
i][0], b_vert_normals[
i][1], b_vert_normals[
i][2]);
993 if (b_verts_num != numverts ||
994 memcmp(mP, mesh->get_verts().data(),
sizeof(
float3) * numverts) == 0)
997 if (b_verts_num != numverts) {
998 VLOG_WARNING <<
"Topology differs, disabling motion blur for object " << ob_name;
1001 VLOG_DEBUG <<
"No actual deformation motion for object " << ob_name;
1008 else if (motion_step > 0) {
1009 VLOG_DEBUG <<
"Filling deformation motion for object " << ob_name;
1012 const float3 *
P = mesh->get_verts().data();
1023 if (b_verts_num != numverts) {
1024 VLOG_WARNING <<
"Topology differs, discarding motion blur for object " << ob_name
1025 <<
" at time " << motion_step;
1026 const float3 *
P = mesh->get_verts().data();
1028 std::copy_n(
P, numverts, mP);
1029 if (mN !=
nullptr) {
1030 std::copy_n(
N, numverts, mN);
std::optional< blender::StringRef > BKE_id_attributes_default_color_name(const struct ID *id)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
const char * CustomData_get_render_layer_name(const CustomData *data, eCustomDataType type)
void BKE_mesh_texspace_get(Mesh *mesh, float r_texspace_location[3], float r_texspace_size[3])
MINLINE float safe_acosf(float a)
MINLINE void madd_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3])
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
static void attr_create_generic(Scene *scene, Mesh *mesh, const ::Mesh &b_mesh, const bool subdivision, const bool need_motion, const float motion_scale)
static void attr_create_random_per_island(Scene *scene, Mesh *mesh, const ::Mesh &b_mesh, bool subdivision)
static void create_mesh(Scene *scene, Mesh *mesh, const ::Mesh &b_mesh, const array< Node * > &used_shaders, const bool need_motion, const float motion_scale, const bool subdivision=false)
static void create_subd_mesh(Scene *scene, Mesh *mesh, BObjectInfo &b_ob_info, const ::Mesh &b_mesh, const array< Node * > &used_shaders, const bool need_motion, const float motion_scale, const float dicing_rate, const int max_subdivisions)
static void attr_create_pointiness(Mesh *mesh, const blender::Span< blender::float3 > positions, const blender::Span< blender::float3 > b_vert_normals, const blender::Span< blender::int2 > edges, bool subdivision)
static void attr_create_uv_map(Scene *scene, Mesh *mesh, const ::Mesh &b_mesh, const set< ustring > &blender_uv_names)
static set< ustring > get_blender_uv_names(const ::Mesh &b_mesh)
static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, const ::Mesh &b_mesh, const set< ustring > &blender_uv_names)
static CCL_NAMESPACE_BEGIN void attr_create_motion_from_velocity(Mesh *mesh, const blender::Span< blender::float3 > b_attr, const float motion_scale)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const void * element
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static DBVT_INLINE btDbvtNode * sort(btDbvtNode *n, btDbvtNode *&r)
void update(AttributeSet &&new_attributes)
Attribute * find(ustring name) const
Attribute * add(ustring name, const TypeDesc type, AttributeElement element)
void remove(ustring name)
void join(const size_t x, const size_t y)
void insert(int v0, int v1)
bool exists(int v0, int v1)
void tag_update(Scene *scene, bool rebuild)
bool need_attribute(Scene *scene, AttributeStandard std)
VertexAverageComparator(const array< float3 > &verts)
bool operator()(const int &vert_idx_a, const int &vert_idx_b)
const array< float3 > & verts_
const CPPType & type() const
VArray< T > typed() const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr const T * data() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
GAttributeReader lookup(const StringRef attribute_id) const
eCustomDataType data_type
GAttributeReader get() const
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
static BL::Mesh object_to_mesh(BObjectInfo &b_ob_info)
static void mesh_texture_space(const ::Mesh &b_mesh, float3 &loc, float3 &size)
static void free_object_to_mesh(BObjectInfo &b_ob_info, BL::Mesh &mesh)
static bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
static void object_subdivision_to_mesh(BL::Object &b_ob, Mesh &mesh, const bool preview, const bool use_adaptive_subdivision)
static Transform get_transform(const BL::Array< float, 16 > &array)
#define CCL_NAMESPACE_END
VecBase< float, D > normalize(VecOp< float, D >) RET
#define assert(assertion)
VecBase< float, 3 > float3
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
constexpr T clamp(T, U, U) RET
ccl_device_inline float hash_uint_to_float(const uint kx)
@ ATTR_STD_GENERATED_TRANSFORM
@ ATTR_STD_MOTION_VERTEX_NORMAL
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_STD_RANDOM_PER_ISLAND
@ ATTR_SUBDIVIDE_SMOOTH_FVAR
@ ATTR_ELEMENT_CORNER_BYTE
ccl_device_inline float len_squared(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
bool attribute_name_is_anonymous(const StringRef name)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
const PointerRNA PointerRNA_NULL
float RNA_float_get(PointerRNA *ptr, const char *name)
Transform * data_transform()
size_t get_num_subd_faces() const
void reserve_subd_creases(const size_t num_creases)
AttributeSet subd_attributes
void copy_center_to_motion_step(const int motion_step)
void set_num_subd_faces(const size_t num_subd_faces_)
void add_vertex_crease(const int v, const float weight)
@ SUBDIVISION_CATMULL_CLARK
void resize_subd_faces(const int numfaces, const int numcorners)
void resize_mesh(const int numverts, const int numtris)
void add_edge_crease(const int v0, const int v1, const float weight)
vector< SocketType, std::allocator< SocketType > > inputs
void set_value(const SocketType &socket, const Node &other, const SocketType &other_socket)