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) {
121 if (is_render_color) {
136 src[tri[0]][0], src[tri[0]][1], src[tri[0]][2], src[tri[0]][3]);
138 src[tri[1]][0], src[tri[1]][1], src[tri[1]][2], src[tri[1]][3]);
140 src[tri[2]][0], src[tri[2]][1], src[tri[2]][2], src[tri[2]][3]);
163 using BlenderT = decltype(dummy);
164 using Converter = typename ccl::AttributeConverter<BlenderT>;
165 using CyclesT = typename Converter::CyclesT;
166 if constexpr (!std::is_void_v<CyclesT>) {
167 Attribute *attr = attributes.add(name, Converter::type_desc, element);
168 if (is_render_color) {
169 attr->std = ATTR_STD_VERTEX_COLOR;
172 CyclesT *data = reinterpret_cast<CyclesT *>(attr->data());
174 const blender::VArraySpan src = b_attr.varray.typed<BlenderT>();
175 switch (b_attr.domain) {
176 case blender::bke::AttrDomain::Corner: {
178 for (const int i : src.index_range()) {
179 data[i] = Converter::convert(src[i]);
183 for (const int i : corner_tris.index_range()) {
184 const blender::int3 &tri = corner_tris[i];
185 data[i * 3 + 0] = Converter::convert(src[tri[0]]);
186 data[i * 3 + 1] = Converter::convert(src[tri[1]]);
187 data[i * 3 + 2] = Converter::convert(src[tri[2]]);
192 case blender::bke::AttrDomain::Point: {
193 for (const int i : src.index_range()) {
194 data[i] = Converter::convert(src[i]);
198 case blender::bke::AttrDomain::Face: {
200 for (const int i : src.index_range()) {
201 data[i] = Converter::convert(src[i]);
205 for (const int i : corner_tris.index_range()) {
206 data[i] = Converter::convert(src[tri_faces[i]]);
223 set<ustring> uv_names;
229 uv_names.emplace(std::string_view(iter.
name));
239 const ::Mesh &b_mesh,
240 const set<ustring> &blender_uv_names)
245 if (blender_uv_names.empty()) {
249 for (
const ustring &uv_name : blender_uv_names) {
250 const bool active_render = uv_name == render_name;
272 fdata[
i * 3 + 0] =
make_float2(b_uv_map[tri[0]][0], b_uv_map[tri[0]][1]);
273 fdata[
i * 3 + 1] =
make_float2(b_uv_map[tri[1]][0], b_uv_map[tri[1]][1]);
274 fdata[
i * 3 + 2] =
make_float2(b_uv_map[tri[2]][0], b_uv_map[tri[2]][1]);
282 const ::Mesh &b_mesh,
283 const set<ustring> &blender_uv_names)
286 if (
faces.is_empty()) {
290 if (blender_uv_names.empty()) {
296 for (
const ustring &uv_name : blender_uv_names) {
297 const bool active_render = uv_name == render_name;
321 for (
const int i :
faces.index_range()) {
323 for (
const int corner : face) {
324 *(fdata++) =
make_float2(b_uv_map[corner][0], b_uv_map[corner][1]);
338 bool operator()(
const int &vert_idx_a,
const int &vert_idx_b)
342 if (vert_a == vert_b) {
344 return vert_idx_a > vert_idx_b;
346 const float x1 = vert_a.
x + vert_a.
y + vert_a.
z;
347 const float x2 = vert_b.
x + vert_b.
y + vert_b.
z;
361 const int num_verts = positions.
size();
370 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
371 sorted_vert_indeices[vert_index] = vert_index;
374 sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
379 for (
int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) {
380 const int vert_index = sorted_vert_indeices[sorted_vert_index];
381 const float3 &vert_co = mesh->get_verts()[vert_index];
383 for (
int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts;
384 ++other_sorted_vert_index)
386 const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index];
387 const float3 &other_vert_co = mesh->get_verts()[other_vert_index];
389 if ((other_vert_co.
x + other_vert_co.
y + other_vert_co.
z) -
390 (vert_co.
x + vert_co.
y + vert_co.
z) >
396 if (
len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
398 vert_orig_index[vert_index] = other_vert_index;
403 vert_orig_index[vert_index] = vert_index;
407 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
408 int orig_index = vert_orig_index[vert_index];
409 while (orig_index != vert_orig_index[orig_index]) {
410 orig_index = vert_orig_index[orig_index];
412 vert_orig_index[vert_index] = orig_index;
420 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
421 const float *b_vert_normal = b_vert_normals[vert_index];
422 const int orig_index = vert_orig_index[vert_index];
423 vert_normal[orig_index] +=
make_float3(b_vert_normal[0], b_vert_normal[1], b_vert_normal[2]);
428 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
429 const int orig_index = vert_orig_index[vert_index];
430 vert_normal[vert_index] =
normalize(vert_normal[orig_index]);
437 memset(counter.data(), 0,
sizeof(
int) * counter.size());
441 const int v0 = vert_orig_index[b_edge[0]];
442 const int v1 = vert_orig_index[b_edge[1]];
443 if (visited_edges.
exists(v0, v1)) {
446 visited_edges.
insert(v0, v1);
447 const float3 co0 =
make_float3(positions[v0][0], positions[v0][1], positions[v0][2]);
448 const float3 co1 =
make_float3(positions[v1][0], positions[v1][1], positions[v1][2]);
450 edge_accum[v0] += edge;
451 edge_accum[v1] += -edge;
455 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
456 const int orig_index = vert_orig_index[vert_index];
457 if (orig_index != vert_index) {
461 if (counter[vert_index] > 0) {
462 const float3 normal = vert_normal[vert_index];
463 const float angle =
safe_acosf(
dot(normal, edge_accum[vert_index] / counter[vert_index]));
467 raw_data[vert_index] = 0.0f;
474 memcpy(
data, raw_data.data(),
sizeof(
float) * raw_data.size());
475 memset(counter.data(), 0,
sizeof(
int) * counter.size());
476 visited_edges.
clear();
479 const int v0 = vert_orig_index[b_edge[0]];
480 const int v1 = vert_orig_index[b_edge[1]];
481 if (visited_edges.
exists(v0, v1)) {
484 visited_edges.
insert(v0, v1);
485 data[v0] += raw_data[v1];
486 data[v1] += raw_data[v0];
490 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
491 data[vert_index] /= counter[vert_index] + 1;
494 for (
int vert_index = 0; vert_index < num_verts; ++vert_index) {
495 const int orig_index = vert_orig_index[vert_index];
496 data[vert_index] =
data[orig_index];
512 const ::Mesh &b_mesh,
519 if (b_mesh.verts_num == 0) {
529 vertices_sets.
join(edges[
i][0], edges[
i][1]);
540 const int vert = corner_verts[corner_tris[
i][0]];
547 if (!
faces.is_empty()) {
548 for (
const int i :
faces.index_range()) {
549 const int vert = corner_verts[
faces[
i].start()];
560 const ::Mesh &b_mesh,
562 const bool need_motion,
563 const float motion_scale,
564 const bool subdivision =
false)
571 const int numfaces = (!subdivision) ? b_mesh.corner_tris().size() :
faces.size();
574 (mesh->get_subdivision_type() !=
578 if (
faces.is_empty()) {
587 if (use_corner_normals) {
588 corner_normals = b_mesh.corner_normals();
610 if (subdivision || !(use_corner_normals && !corner_normals.is_empty())) {
613 N[
i] =
make_float3(vert_normals[
i][0], vert_normals[
i][1], vert_normals[
i][2]);
620 const bool need_default_tangent = (subdivision ==
false) && (blender_uv_names.empty()) &&
623 const float (*orco)[3] =
static_cast<const float (*)[3]
>(
631 float texspace_location[3];
632 float texspace_size[3];
645 value = positions[
i];
651 auto clamp_material_index = [&](
const int material_index) ->
int {
652 return clamp(material_index, 0, used_shaders.
size() - 1);
657 int *triangles = mesh->get_triangles().data();
658 bool *smooth = mesh->get_smooth().data();
659 int *shader = mesh->get_shader().data();
664 triangles[
i * 3 + 0] = corner_verts[tri[0]];
665 triangles[
i * 3 + 1] = corner_verts[tri[1]];
666 triangles[
i * 3 + 2] = corner_verts[tri[2]];
672 shader[
i] = clamp_material_index(material_indices[tri_faces[
i]]);
676 std::fill(shader, shader + numtris, 0);
679 if (!sharp_faces.is_empty() && !(use_corner_normals && !corner_normals.is_empty())) {
682 smooth[
i] = !sharp_faces[tri_faces[
i]];
690 if (use_corner_normals && !corner_normals.is_empty()) {
693 for (
int i = 0;
i < 3;
i++) {
694 const int corner = tri[
i];
695 const int vert = corner_verts[corner];
696 const float *normal = corner_normals[corner];
702 mesh->tag_triangles_modified();
703 mesh->tag_shader_modified();
704 mesh->tag_smooth_modified();
707 int *subd_start_corner = mesh->get_subd_start_corner().data();
708 int *subd_num_corners = mesh->get_subd_num_corners().data();
709 int *subd_shader = mesh->get_subd_shader().data();
710 bool *subd_smooth = mesh->get_subd_smooth().data();
711 int *subd_ptex_offset = mesh->get_subd_ptex_offset().data();
712 int *subd_face_corners = mesh->get_subd_face_corners().data();
714 if (!sharp_faces.is_empty() && !use_corner_normals) {
715 for (
int i = 0;
i < numfaces;
i++) {
716 subd_smooth[
i] = !sharp_faces[
i];
720 std::fill(subd_smooth, subd_smooth + numfaces,
true);
724 for (
int i = 0;
i < numfaces;
i++) {
725 subd_shader[
i] = clamp_material_index(material_indices[
i]);
729 std::fill(subd_shader, subd_shader + numfaces, 0);
732 std::copy(corner_verts.
data(), corner_verts.
data() + corner_verts.
size(), subd_face_corners);
736 for (
const int i :
faces.index_range()) {
739 subd_start_corner[
i] = face.
start();
740 subd_num_corners[
i] = face.
size();
741 subd_ptex_offset[
i] = ptex_offset;
742 const int num_ptex = (face.
size() == 4) ? 1 : face.
size();
743 ptex_offset += num_ptex;
746 mesh->tag_subd_face_corners_modified();
747 mesh->tag_subd_start_corner_modified();
748 mesh->tag_subd_num_corners_modified();
749 mesh->tag_subd_shader_modified();
750 mesh->tag_subd_smooth_modified();
751 mesh->tag_subd_ptex_offset_modified();
788 const ::Mesh &b_mesh,
790 const bool need_motion,
791 const float motion_scale,
792 const float dicing_rate,
793 const int max_subdivisions)
797 BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
798 const bool use_creases = subsurf_mod.use_creases();
800 create_mesh(scene, mesh, b_mesh, used_shaders, need_motion, motion_scale,
true);
806 size_t num_creases = 0;
808 if (creases[
i] != 0.0f) {
817 const float crease = creases[
i];
818 if (crease != 0.0f) {
829 if (vert_creases[
i] != 0.0f) {
838 switch (subsurf_mod.adaptive_space()) {
839 case BL::SubsurfModifier::adaptive_space_OBJECT:
842 case BL::SubsurfModifier::adaptive_space_PIXEL:
847 max(0.1f, subsurf_mod.adaptive_pixel_size() * dicing_rate) :
848 subsurf_mod.adaptive_object_edge_length() * dicing_rate;
850 mesh->set_subd_adaptive_space(space);
851 mesh->set_subd_dicing_rate(subd_dicing_rate);
852 mesh->set_subd_max_level(max_subdivisions);
853 mesh->set_subd_objecttoworld(
get_transform(b_ob.matrix_world()));
862 array<Node *> used_shaders = mesh->get_used_shaders();
865 new_mesh.set_used_shaders(used_shaders);
867 if (view_layer.use_surfaces) {
874 const float motion_scale = (need_motion) ?
875 scene->motion_shutter_time() /
876 (b_scene.render().fps() / b_scene.render().fps_base()) :
884 *
static_cast<const ::
Mesh *
>(b_mesh.ptr.data),
885 new_mesh.get_used_shaders(),
894 *
static_cast<const ::
Mesh *
>(b_mesh.ptr.data),
895 new_mesh.get_used_shaders(),
909 for (
const SocketType &socket : new_mesh.
type->
inputs) {
911 if (socket.
name ==
"use_motion_blur" || socket.
name ==
"used_shaders") {
914 mesh->
set_value(socket, new_mesh, socket);
923 const bool rebuild = (mesh->triangles_is_modified()) || (mesh->subd_num_corners_is_modified()) ||
924 (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) ||
925 (mesh->subd_ptex_offset_is_modified()) ||
926 (mesh->subd_start_corner_is_modified()) ||
927 (mesh->subd_face_corners_is_modified());
932void BlenderSync::sync_mesh_motion(
BObjectInfo &b_ob_info,
Mesh *mesh,
const int motion_step)
935 const size_t numverts = mesh->get_verts().size();
943 if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
948 const std::string ob_name = b_ob_info.
real_object.name();
952 const ::Mesh &b_mesh = *
static_cast<const ::
Mesh *
>(b_mesh_rna.ptr.data);
953 const int b_verts_num = b_mesh.
verts_num;
954 const blender::Span<blender::float3> positions = b_mesh.vert_positions();
969 bool new_attribute =
false;
977 new_attribute =
true;
981 float3 *mN = (attr_mN) ? attr_mN->
data_float3() + motion_step * numverts :
nullptr;
987 mP[
i] =
make_float3(positions[
i][0], positions[
i][1], positions[
i][2]);
990 const blender::Span<blender::float3> b_vert_normals = b_mesh.vert_normals();
992 mN[
i] =
make_float3(b_vert_normals[
i][0], b_vert_normals[
i][1], b_vert_normals[
i][2]);
997 if (b_verts_num != numverts ||
998 memcmp(mP, mesh->get_verts().data(),
sizeof(
float3) * numverts) == 0)
1001 if (b_verts_num != numverts) {
1002 LOG_WARNING <<
"Topology differs, disabling motion blur for object " << ob_name;
1005 LOG_TRACE <<
"No actual deformation motion for object " << ob_name;
1012 else if (motion_step > 0) {
1013 LOG_TRACE <<
"Filling deformation motion for object " << ob_name;
1016 const float3 *
P = mesh->get_verts().data();
1027 if (b_verts_num != numverts) {
1028 LOG_WARNING <<
"Topology differs, discarding motion blur for object " << ob_name
1029 <<
" at time " << motion_step;
1030 const float3 *
P = mesh->get_verts().data();
1032 std::copy_n(
P, numverts, mP);
1033 if (mN !=
nullptr) {
1034 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
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
#define assert(assertion)
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
constexpr T clamp(T, U, U) RET
VecBase< float, 3 > float3
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_device_inline float2 safe_normalize(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)
const PointerRNA PointerRNA_NULL
Transform * data_transform()
size_t get_num_subd_faces() const
@ SUBDIVISION_ADAPTIVE_SPACE_OBJECT
@ SUBDIVISION_ADAPTIVE_SPACE_PIXEL
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)