Mesh: Lines index buffer creation improvement #120720

Merged
Hans Goudey merged 66 commits from HooglyBoogly/blender:mesh-extract-lines-fix into main 2024-04-30 15:55:01 +02:00
23 changed files with 274 additions and 389 deletions
Showing only changes of commit cb6bc31bbf - Show all commits

View File

@ -1949,7 +1949,7 @@ if html_theme == "furo":
"sidebar/scroll-start.html",
"sidebar/navigation.html",
"sidebar/scroll-end.html",
# "sidebar/variant-selector.html",
"sidebar/variant-selector.html",
]
}
""")

View File

@ -324,13 +324,6 @@ ccl_device_inline bool volume_equiangular_valid_ray_segment(KernelGlobals kg,
ccl_private float2 *t_range,
const ccl_private LightSample *ls)
{
# ifdef __LIGHT_TREE__
/* Do not compute ray segment until #119389 is landed. */
if (kernel_data.integrator.use_light_tree) {
return true;
}
# endif
if (ls->type == LIGHT_SPOT) {
ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
return spot_light_valid_ray_segment(klight, ray_P, ray_D, t_range);
@ -708,7 +701,8 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
ccl_private const Ray *ccl_restrict ray,
ccl_private const ShaderData *ccl_restrict sd,
ccl_private const RNGState *ccl_restrict rng_state,
ccl_private EquiangularCoefficients *ccl_restrict equiangular_coeffs)
ccl_private EquiangularCoefficients *ccl_restrict equiangular_coeffs,
ccl_private LightSample &ccl_restrict ls)
{
/* Test if there is a light or BSDF that needs direct light. */
if (!kernel_data.integrator.use_direct_light) {
@ -720,7 +714,6 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
LightSample ls ccl_optional_struct_init;
if (!light_sample_from_volume_segment(kg,
rand_light,
sd->time,
@ -761,41 +754,26 @@ ccl_device_forceinline void integrate_volume_direct_light(
# ifdef __PATH_GUIDING__
ccl_private const Spectrum unlit_throughput,
# endif
ccl_private const Spectrum throughput)
ccl_private const Spectrum throughput,
ccl_private LightSample &ccl_restrict ls)
{
PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_DIRECT_LIGHT);
if (!kernel_data.integrator.use_direct_light) {
if (!kernel_data.integrator.use_direct_light || ls.emitter_id == EMITTER_NONE) {
return;
}
/* Sample position on the same light again, now from the shading point where we scattered.
*
* Note that this means we sample the light tree twice when equiangular sampling is used.
* We could consider sampling the light tree just once and use the same light position again.
*
* This would make the PDFs for MIS weights more complicated due to having to account for
* both distance/equiangular and direct/indirect light sampling, but could be more accurate.
* Additionally we could end up behind the light or outside a spot light cone, which might
* waste a sample. Though on the other hand it would be possible to prevent that with
* equiangular sampling restricted to a smaller sub-segment where the light has influence. */
LightSample ls ccl_optional_struct_init;
/* Sample position on the same light again, now from the shading point where we scattered. */
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
const float3 N = zero_float3();
const int object_receiver = light_link_receiver_nee(kg, sd);
const int shader_flags = SD_BSDF_HAS_TRANSMISSION;
if (!light_sample_from_position(kg,
rng_state,
rand_light,
sd->time,
P,
zero_float3(),
light_link_receiver_nee(kg, sd),
SD_BSDF_HAS_TRANSMISSION,
bounce,
path_flag,
&ls))
if (!light_sample<false>(
kg, rand_light, sd->time, P, N, object_receiver, shader_flags, bounce, path_flag, &ls))
{
return;
}
@ -913,6 +891,7 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
KernelGlobals kg,
IntegratorState state,
ccl_private ShaderData *sd,
ccl_private const Ray *ray,
ccl_private const RNGState *rng_state,
ccl_private const ShaderVolumePhases *phases)
{
@ -965,6 +944,7 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
INTEGRATOR_STATE_WRITE(state, ray, P) = sd->P;
INTEGRATOR_STATE_WRITE(state, ray, D) = normalize(phase_wo);
INTEGRATOR_STATE_WRITE(state, ray, tmin) = 0.0f;
INTEGRATOR_STATE_WRITE(state, ray, previous_dt) = ray->tmax - ray->tmin;
INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX;
# ifdef __RAY_DIFFERENTIALS__
INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP);
@ -993,7 +973,8 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
/* Update path state */
INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = phase_pdf;
INTEGRATOR_STATE_WRITE(state, path, mis_origin_n) = zero_float3();
const float3 previous_P = ray->P + ray->D * ray->tmin;
INTEGRATOR_STATE_WRITE(state, path, mis_origin_n) = sd->P - previous_P;
INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = fminf(
unguided_phase_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
@ -1025,13 +1006,15 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
/* Sample light ahead of volume stepping, for equiangular sampling. */
/* TODO: distant lights are ignored now, but could instead use even distribution. */
LightSample ls ccl_optional_struct_init;
ls.emitter_id = EMITTER_NONE;
const bool need_light_sample = !(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_TERMINATE);
EquiangularCoefficients equiangular_coeffs = {zero_float3(), make_float2(ray->tmin, ray->tmax)};
const bool have_equiangular_sample = need_light_sample &&
integrate_volume_equiangular_sample_light(
kg, state, ray, &sd, &rng_state, &equiangular_coeffs);
const bool have_equiangular_sample =
need_light_sample && integrate_volume_equiangular_sample_light(
kg, state, ray, &sd, &rng_state, &equiangular_coeffs, ls);
VolumeSampleMethod direct_sample_method = (have_equiangular_sample) ?
volume_stack_sample_method(kg, state) :
@ -1129,7 +1112,8 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
# ifdef __PATH_GUIDING__
unlit_throughput,
# endif
result.direct_throughput);
result.direct_throughput,
ls);
}
/* Indirect light.
@ -1168,7 +1152,7 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
# endif
# endif
if (integrate_volume_phase_scatter(kg, state, &sd, &rng_state, &result.indirect_phases)) {
if (integrate_volume_phase_scatter(kg, state, &sd, ray, &rng_state, &result.indirect_phases)) {
return VOLUME_PATH_SCATTERED;
}
else {

View File

@ -75,6 +75,9 @@ KERNEL_STRUCT_MEMBER(ray, float, tmax, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_MEMBER(ray, float, time, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_MEMBER(ray, float, dP, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_MEMBER(ray, float, dD, KERNEL_FEATURE_PATH_TRACING)
#ifdef __LIGHT_TREE__
KERNEL_STRUCT_MEMBER(ray, float, previous_dt, KERNEL_FEATURE_PATH_TRACING)
#endif
KERNEL_STRUCT_END(ray)
/*************************** Intersection result ******************************/

View File

@ -518,9 +518,8 @@ ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLi
const bool shape_above_surface = dot(N, centroid - P) + fabsf(dot(N, extentu)) +
fabsf(dot(N, extentv)) >
0;
const bool in_volume = is_zero(N);
return (front_facing && shape_above_surface) || in_volume;
return front_facing && shape_above_surface;
}
CCL_NAMESPACE_END

View File

@ -12,9 +12,9 @@ CCL_NAMESPACE_BEGIN
typedef struct LightSample {
float3 P; /* position on light, or direction for distant light */
float3 Ng; /* normal on light */
float3 D; /* direction from shading point to light */
packed_float3 Ng; /* normal on light */
float t; /* distance to light (FLT_MAX for distant light) */
float3 D; /* direction from shading point to light */
float u, v; /* parametric coordinate on primitive */
float pdf; /* pdf for selecting light and point on light */
float pdf_selection; /* pdf for selecting light */
@ -25,6 +25,7 @@ typedef struct LightSample {
int lamp; /* lamp id */
int group; /* lightgroup */
LightType type; /* type of light */
int emitter_id; /* index in the emitter array */
} LightSample;
/* Utilities */

View File

@ -41,36 +41,14 @@ ccl_device int light_distribution_sample(KernelGlobals kg, const float rand)
return index;
}
template<bool in_volume_segment>
ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
const float3 rand,
const float time,
const float3 P,
const float3 N,
const int object_receiver,
const int shader_flags,
const int bounce,
const uint32_t path_flag,
const float rand,
ccl_private LightSample *ls)
{
/* Sample light index from distribution. */
/* The first two dimensions of the Sobol sequence have better stratification. */
const int index = light_distribution_sample(kg, rand.z);
const float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
const float2 rand_uv = float3_to_float2(rand);
return light_sample<in_volume_segment>(kg,
rand_uv,
time,
P,
N,
object_receiver,
shader_flags,
bounce,
path_flag,
index,
0,
pdf_selection,
ls);
ls->emitter_id = light_distribution_sample(kg, rand);
ls->pdf_selection = kernel_data.integrator.distribution_pdf_lights;
return true;
}
ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg)

View File

@ -177,7 +177,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
template<bool in_volume_segment>
ccl_device_noinline bool light_sample(KernelGlobals kg,
const float2 rand,
const float3 rand_light,
const float time,
const float3 P,
const float3 N,
@ -185,33 +185,31 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
const int shader_flags,
const int bounce,
const uint32_t path_flag,
const int emitter_index,
const int object_id,
const float pdf_selection,
ccl_private LightSample *ls)
{
/* The first two dimensions of the Sobol sequence have better stratification, use them to sample
* position on the light. */
const float2 rand = float3_to_float2(rand_light);
int prim;
MeshLight mesh_light;
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
emitter_index);
ls->emitter_id);
prim = kemitter->light.id;
mesh_light.shader_flag = kemitter->mesh_light.shader_flag;
mesh_light.object_id = object_id;
mesh_light.object_id = ls->object;
}
else
#endif
{
ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(
light_distribution, emitter_index);
light_distribution, ls->emitter_id);
prim = kdistribution->prim;
mesh_light = kdistribution->mesh_light;
}
/* A different value would be assigned in `triangle_light_sample()` if `!use_light_tree`. */
ls->pdf_selection = pdf_selection;
if (prim >= 0) {
/* Mesh light. */
const int object = mesh_light.object_id;

View File

@ -329,17 +329,25 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
const int shader_flags = SD_BSDF_HAS_TRANSMISSION;
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<true>(
kg, rand, time, P, D, t, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
if (!light_tree_sample<true>(kg, rand.z, P, D, t, object_receiver, shader_flags, ls)) {
return false;
}
}
else
#endif
{
return light_distribution_sample<true>(
kg, rand, time, P, D, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
if (!light_distribution_sample(kg, rand.z, ls)) {
return false;
}
}
/* Sample position on the selected light. */
return light_sample<true>(
kg, rand, time, P, D, object_receiver, shader_flags, bounce, path_flag, ls);
}
ccl_device bool light_sample_from_position(KernelGlobals kg,
@ -354,17 +362,24 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
/* Randomly select a light. */
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<false>(
kg, rand, time, P, N, 0.0f, object_receiver, shader_flags, bounce, path_flag, ls);
if (!light_tree_sample<false>(kg, rand.z, P, N, 0.0f, object_receiver, shader_flags, ls)) {
return false;
}
}
else
#endif
{
return light_distribution_sample<false>(
kg, rand, time, P, N, object_receiver, shader_flags, bounce, path_flag, ls);
if (!light_distribution_sample(kg, rand.z, ls)) {
return false;
}
}
/* Sample position on the selected light. */
return light_sample<false>(
kg, rand, time, P, N, object_receiver, shader_flags, bounce, path_flag, ls);
}
/* Update light sample with new shading point position for MNEE. The position on the light is fixed
@ -415,13 +430,15 @@ ccl_device_inline float light_sample_mis_weight_forward_surface(KernelGlobals kg
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
float3 ray_P = INTEGRATOR_STATE(state, ray, P);
const float dt = INTEGRATOR_STATE(state, ray, previous_dt);
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
uint lookup_offset = kernel_data_fetch(object_lookup_offset, sd->object);
uint prim_offset = kernel_data_fetch(object_prim_offset, sd->object);
uint triangle = kernel_data_fetch(triangle_to_tree, sd->prim - prim_offset + lookup_offset);
pdf *= light_tree_pdf(
kg, ray_P, N, path_flag, sd->object, triangle, light_link_receiver_forward(kg, state));
kg, ray_P, N, dt, path_flag, sd->object, triangle, light_link_receiver_forward(kg, state));
}
else
#endif
@ -445,9 +462,11 @@ ccl_device_inline float light_sample_mis_weight_forward_lamp(KernelGlobals kg,
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
const float dt = INTEGRATOR_STATE(state, ray, previous_dt);
pdf *= light_tree_pdf(kg,
P,
N,
dt,
path_flag,
0,
kernel_data_fetch(light_to_tree, ls->lamp),
@ -485,9 +504,10 @@ ccl_device_inline float light_sample_mis_weight_forward_background(KernelGlobals
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
const float dt = INTEGRATOR_STATE(state, ray, previous_dt);
uint light = kernel_data_fetch(light_to_tree, kernel_data.background.light_index);
pdf *= light_tree_pdf(
kg, ray_P, N, path_flag, 0, light, light_link_receiver_forward(kg, state));
kg, ray_P, N, dt, path_flag, 0, light, light_link_receiver_forward(kg, state));
}
else
#endif

View File

@ -148,10 +148,7 @@ ccl_device void light_tree_importance(const float3 N_or_D,
float cos_min_incidence_angle = 1.0f;
float cos_max_incidence_angle = 1.0f;
/* When sampling the light tree for the second time in `shade_volume.h` and when query the pdf in
* `sample.h`. */
const bool in_volume = is_zero(N_or_D);
if (!in_volume_segment && !in_volume) {
if (!in_volume_segment) {
const float3 N = N_or_D;
const float cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
dot(point_to_centroid, N);
@ -221,9 +218,9 @@ ccl_device void light_tree_importance(const float3 N_or_D,
max_importance = fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle /
(in_volume_segment ? min_distance : sqr(min_distance)));
/* TODO: also min importance for volume? */
/* TODO: compute proper min importance for volume. */
if (in_volume_segment) {
min_importance = max_importance;
min_importance = 0.0f;
return;
}
@ -270,10 +267,10 @@ ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg,
/* Arbitrary centroid and direction. */
centroid = make_float3(0.0f, 0.0f, 1.0f);
dir = make_float3(0.0f, 0.0f, -1.0f);
return !in_volume_segment;
break;
case LIGHT_DISTANT:
dir = centroid;
return !in_volume_segment;
break;
default:
return false;
}
@ -323,12 +320,13 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
float cos_theta_u;
float distance;
if (knode->type == LIGHT_TREE_DISTANT) {
if (in_volume_segment) {
return;
}
point_to_centroid = -bcone.axis;
cos_theta_u = fast_cosf(bcone.theta_o + bcone.theta_e);
distance = 1.0f;
if (t == FLT_MAX) {
/* In world volume, distant light has no contribution. */
return;
}
}
else {
const float3 centroid = 0.5f * (bbox.min + bbox.max);
@ -339,6 +337,9 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
/* Minimal distance of the ray to the cluster. */
distance = len(centroid - closest_point);
point_to_centroid = -compute_v(centroid, P, D, bcone.axis, t);
/* FIXME(weizhen): it is not clear from which point the `cos_theta_u` should be computed in
* volume segment. We could use `closest_point` as a conservative measure, but then
* `point_to_centroid` should also use `closest_point`. */
cos_theta_u = light_tree_cos_bounding_box_angle(bbox, closest_point, point_to_centroid);
}
else {
@ -697,17 +698,16 @@ ccl_device int light_tree_root_node_index(KernelGlobals kg, const int object_rec
return 0;
}
/* Pick a random light from the light tree from a given shading point P, write to the picked light
* index and the probability of picking the light. */
template<bool in_volume_segment>
ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
const float3 rand,
const float time,
const float rand,
const float3 P,
float3 N_or_D,
float t,
const int object_receiver,
const int shader_flags,
const int bounce,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
if (!kernel_data.integrator.use_direct_light) {
@ -718,10 +718,8 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float pdf_leaf = 1.0f;
float pdf_selection = 1.0f;
int selected_emitter = -1;
int object_emitter = 0;
int node_index = light_tree_root_node_index(kg, object_receiver);
/* The first two dimensions of the Sobol sequence have better stratification. */
float rand_selection = rand.z;
float rand_selection = rand;
float3 local_P = P;
@ -743,7 +741,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
}
/* Continue with the picked mesh light. */
object_emitter = kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
ls->object = kernel_data_fetch(light_tree_emitters, selected_emitter).mesh.object_id;
continue;
}
@ -766,27 +764,18 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
}
pdf_selection *= pdf_leaf;
ls->emitter_id = selected_emitter;
ls->pdf_selection = pdf_selection * pdf_leaf;
return light_sample<in_volume_segment>(kg,
float3_to_float2(rand),
time,
P,
N_or_D,
object_receiver,
shader_flags,
bounce,
path_flag,
selected_emitter,
object_emitter,
pdf_selection,
ls);
return true;
}
/* We need to be able to find the probability of selecting a given light for MIS. */
template<bool in_volume_segment>
ccl_device float light_tree_pdf(KernelGlobals kg,
float3 P,
float3 N,
const float dt,
const int path_flag,
const int object_emitter,
const uint index_emitter,
@ -837,8 +826,8 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
for (int i = 0; i < knode->num_emitters; i++) {
const int emitter = knode->leaf.first_emitter + i;
float max_importance, min_importance;
light_tree_emitter_importance<false>(
kg, P, N, 0, has_transmission, emitter, max_importance, min_importance);
light_tree_emitter_importance<in_volume_segment>(
kg, P, N, dt, has_transmission, emitter, max_importance, min_importance);
num_has_importance += (max_importance > 0);
if (emitter == target_emitter) {
target_max_importance = max_importance;
@ -860,7 +849,7 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
if (subtree_root_index != -1) {
/* Arrived at the mesh light. Continue with the subtree. */
float unused;
light_tree_to_local_space<false>(kg, object_emitter, P, N, unused);
light_tree_to_local_space<in_volume_segment>(kg, object_emitter, P, N, unused);
node_index = subtree_root_index;
subtree_root_index = -1;
@ -878,8 +867,8 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
const int right_index = knode->inner.right_child;
float left_prob;
if (!get_left_probability<false>(
kg, P, N, 0, has_transmission, left_index, right_index, left_prob))
if (!get_left_probability<in_volume_segment>(
kg, P, N, dt, has_transmission, left_index, right_index, left_prob))
{
return 0.0f;
}
@ -897,4 +886,27 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
}
}
/* If the function is called in volume, retrieve the previous point in volume segment, and compute
* pdf from there. Otherwise compute from the current shading point. */
ccl_device_inline float light_tree_pdf(KernelGlobals kg,
float3 P,
float3 N,
const float dt,
const int path_flag,
const int emitter_object,
const uint emitter_id,
const int object_receiver)
{
if (path_flag & PATH_RAY_VOLUME_SCATTER) {
const float3 D_times_t = N;
const float3 D = normalize(D_times_t);
P = P - D_times_t;
return light_tree_pdf<true>(
kg, P, D, dt, path_flag, emitter_object, emitter_id, object_receiver);
}
return light_tree_pdf<false>(
kg, P, N, 0.0f, path_flag, emitter_object, emitter_id, object_receiver);
}
CCL_NAMESPACE_END

View File

@ -285,7 +285,8 @@ ccl_device_inline bool triangle_light_valid_ray_segment(KernelGlobals kg,
/* Only one side is sampled, intersect the ray and the triangle light plane to find the visible
* ray segment. Flip normal if Emission Sampling is set to back. */
return ray_plane_intersect((shader_flag & SD_MIS_BACK) ? -ls->Ng : ls->Ng, P, D, t_range);
const float3 N = ls->Ng;
return ray_plane_intersect((shader_flag & SD_MIS_BACK) ? -N : N, P, D, t_range);
}
template<bool in_volume_segment>
@ -326,9 +327,8 @@ ccl_device_forceinline bool triangle_light_tree_parameters(
}
const bool front_facing = bcone.theta_o != 0.0f || dot(bcone.axis, point_to_centroid) < 0;
const bool in_volume = is_zero(N);
return (front_facing && shape_above_surface) || in_volume;
return front_facing && shape_above_surface;
}
CCL_NAMESPACE_END

View File

@ -45,6 +45,7 @@ CCL_NAMESPACE_BEGIN
#define OBJECT_NONE (~0)
#define PRIM_NONE (~0)
#define LAMP_NONE (~0)
#define EMITTER_NONE (~0)
#define ID_NONE (0.0f)
#define PASS_UNUSED (~0)
#define LIGHTGROUP_NONE (~0)

View File

@ -253,54 +253,6 @@ static AttributeIDRef attribute_id_from_custom_data_layer(const CustomDataLayer
return layer.name;
}
static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data,
const eCustomDataType data_type,
const int domain_num,
const AttributeInit &initializer)
{
switch (initializer.type) {
case AttributeInit::Type::Construct: {
void *data = CustomData_add_layer(&custom_data, data_type, CD_CONSTRUCT, domain_num);
return data != nullptr;
}
case AttributeInit::Type::DefaultValue: {
void *data = CustomData_add_layer(&custom_data, data_type, CD_SET_DEFAULT, domain_num);
return data != nullptr;
}
case AttributeInit::Type::VArray: {
void *data = CustomData_add_layer(&custom_data, data_type, CD_CONSTRUCT, domain_num);
if (data == nullptr) {
return false;
}
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray.materialize_to_uninitialized(varray.index_range(), data);
return true;
}
case AttributeInit::Type::MoveArray: {
void *src_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
const void *stored_data = CustomData_add_layer_with_data(
&custom_data, data_type, src_data, domain_num, nullptr);
if (stored_data == nullptr) {
return false;
}
if (stored_data != src_data) {
MEM_freeN(src_data);
return true;
}
return true;
}
case AttributeInit::Type::Shared: {
const AttributeInitShared &init = static_cast<const AttributeInitShared &>(initializer);
const void *stored_data = CustomData_add_layer_with_data(
&custom_data, data_type, const_cast<void *>(init.data), domain_num, init.sharing_info);
return stored_data != nullptr;
}
}
BLI_assert_unreachable();
return false;
}
static void *add_generic_custom_data_layer(CustomData &custom_data,
const eCustomDataType data_type,
const eCDAllocType alloctype,
@ -393,10 +345,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
bool BuiltinCustomDataLayerProvider::layer_exists(const CustomData &custom_data) const
{
if (stored_as_named_attribute_) {
return CustomData_get_named_layer_index(&custom_data, stored_type_, name_) != -1;
}
return CustomData_has_layer(&custom_data, stored_type_);
return CustomData_get_named_layer_index(&custom_data, data_type_, name_) != -1;
}
GAttributeReader BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) const
@ -416,13 +365,7 @@ GAttributeReader BuiltinCustomDataLayerProvider::try_get_for_read(const void *ow
return {};
}
int index;
if (stored_as_named_attribute_) {
index = CustomData_get_named_layer_index(custom_data, stored_type_, name_);
}
else {
index = CustomData_get_layer_index(custom_data, stored_type_);
}
const int index = CustomData_get_named_layer_index(custom_data, data_type_, name_);
if (index == -1) {
return {};
}
@ -452,13 +395,7 @@ GAttributeWriter BuiltinCustomDataLayerProvider::try_get_for_write(void *owner)
return {};
}
void *data = nullptr;
if (stored_as_named_attribute_) {
data = CustomData_get_layer_named_for_write(custom_data, stored_type_, name_, element_num);
}
else {
data = CustomData_get_layer_for_write(custom_data, stored_type_, element_num);
}
void *data = CustomData_get_layer_named_for_write(custom_data, data_type_, name_, element_num);
if (data == nullptr) {
return {};
}
@ -475,27 +412,13 @@ bool BuiltinCustomDataLayerProvider::try_delete(void *owner) const
return {};
}
auto update = [&]() {
const int element_num = custom_data_access_.get_element_num(owner);
if (CustomData_free_layer_named(custom_data, name_, element_num)) {
if (update_on_change_ != nullptr) {
update_on_change_(owner);
}
};
const int element_num = custom_data_access_.get_element_num(owner);
if (stored_as_named_attribute_) {
if (CustomData_free_layer_named(custom_data, name_, element_num)) {
update();
return true;
}
return false;
}
const int layer_index = CustomData_get_layer_index(custom_data, stored_type_);
if (CustomData_free_layer(custom_data, stored_type_, element_num, layer_index)) {
update();
return true;
}
return false;
}
@ -511,21 +434,19 @@ bool BuiltinCustomDataLayerProvider::try_create(void *owner,
}
const int element_num = custom_data_access_.get_element_num(owner);
if (stored_as_named_attribute_) {
if (CustomData_has_layer_named(custom_data, data_type_, name_)) {
/* Exists already. */
return false;
}
return add_custom_data_layer_from_attribute_init(
name_, *custom_data, stored_type_, element_num, initializer);
}
if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
if (CustomData_has_layer_named(custom_data, data_type_, name_)) {
/* Exists already. */
return false;
}
return add_builtin_type_custom_data_layer_from_init(
*custom_data, stored_type_, element_num, initializer);
if (add_custom_data_layer_from_attribute_init(
name_, *custom_data, data_type_, element_num, initializer))
{
if (update_on_change_ != nullptr) {
update_on_change_(owner);
}
return true;
}
return false;
}
bool BuiltinCustomDataLayerProvider::exists(const void *owner) const
@ -534,10 +455,7 @@ bool BuiltinCustomDataLayerProvider::exists(const void *owner) const
if (custom_data == nullptr) {
return false;
}
if (stored_as_named_attribute_) {
return CustomData_has_layer_named(custom_data, stored_type_, name_);
}
return CustomData_get_layer(custom_data, stored_type_) != nullptr;
return CustomData_has_layer_named(custom_data, data_type_, name_);
}
GAttributeReader CustomDataAttributeProvider::try_get_for_read(

View File

@ -174,27 +174,22 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
*/
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
using UpdateOnChange = void (*)(void *owner);
const eCustomDataType stored_type_;
const CustomDataAccessInfo custom_data_access_;
const UpdateOnChange update_on_change_;
bool stored_as_named_attribute_;
public:
BuiltinCustomDataLayerProvider(std::string attribute_name,
const AttrDomain domain,
const eCustomDataType attribute_type,
const eCustomDataType stored_type,
const eCustomDataType data_type,
const CreatableEnum creatable,
const DeletableEnum deletable,
const CustomDataAccessInfo custom_data_access,
const UpdateOnChange update_on_write,
const UpdateOnChange update_on_change,
const AttributeValidator validator = {})
: BuiltinAttributeProvider(
std::move(attribute_name), domain, attribute_type, creatable, deletable, validator),
stored_type_(stored_type),
std::move(attribute_name), domain, data_type, creatable, deletable, validator),
custom_data_access_(custom_data_access),
update_on_change_(update_on_write),
stored_as_named_attribute_(data_type_ == stored_type_)
update_on_change_(update_on_change)
{
}

View File

@ -58,6 +58,8 @@ CurvesGeometry::CurvesGeometry() : CurvesGeometry(0, 0) {}
CurvesGeometry::CurvesGeometry(const int point_num, const int curve_num)
{
this->runtime = MEM_new<CurvesGeometryRuntime>(__func__);
this->point_num = point_num;
this->curve_num = curve_num;
CustomData_reset(&this->point_data);
@ -67,8 +69,6 @@ CurvesGeometry::CurvesGeometry(const int point_num, const int curve_num)
this->attributes_for_write().add<float3>(
"position", AttrDomain::Point, AttributeInitConstruct());
this->runtime = MEM_new<CurvesGeometryRuntime>(__func__);
if (curve_num > 0) {
this->curve_offsets = static_cast<int *>(
MEM_malloc_arrayN(this->curve_num + 1, sizeof(int), __func__));

View File

@ -476,7 +476,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider position("position",
AttrDomain::Point,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
point_access,
@ -485,7 +484,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider radius("radius",
AttrDomain::Point,
CD_PROP_FLOAT,
CD_PROP_FLOAT,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -494,7 +492,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider id("id",
AttrDomain::Point,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -503,7 +500,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider tilt("tilt",
AttrDomain::Point,
CD_PROP_FLOAT,
CD_PROP_FLOAT,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -512,7 +508,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider handle_right("handle_right",
AttrDomain::Point,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -521,7 +516,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider handle_left("handle_left",
AttrDomain::Point,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -536,7 +530,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right",
AttrDomain::Point,
CD_PROP_INT8,
CD_PROP_INT8,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -546,7 +539,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider handle_type_left("handle_type_left",
AttrDomain::Point,
CD_PROP_INT8,
CD_PROP_INT8,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -556,7 +548,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider nurbs_weight("nurbs_weight",
AttrDomain::Point,
CD_PROP_FLOAT,
CD_PROP_FLOAT,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -569,7 +560,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order",
AttrDomain::Curve,
CD_PROP_INT8,
CD_PROP_INT8,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
curve_access,
@ -585,7 +575,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider normal_mode("normal_mode",
AttrDomain::Curve,
CD_PROP_INT8,
CD_PROP_INT8,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
curve_access,
@ -595,7 +584,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider custom_normal("custom_normal",
AttrDomain::Point,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -610,7 +598,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode",
AttrDomain::Curve,
CD_PROP_INT8,
CD_PROP_INT8,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
curve_access,
@ -626,7 +613,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider curve_type("curve_type",
AttrDomain::Curve,
CD_PROP_INT8,
CD_PROP_INT8,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
curve_access,
@ -640,7 +626,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider resolution("resolution",
AttrDomain::Curve,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
curve_access,
@ -650,7 +635,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BuiltinCustomDataLayerProvider cyclic("cyclic",
AttrDomain::Curve,
CD_PROP_BOOL,
CD_PROP_BOOL,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
curve_access,

View File

@ -133,7 +133,6 @@ static ComponentAttributeProviders create_attribute_providers_for_instances()
static BuiltinCustomDataLayerProvider id("id",
AttrDomain::Instance,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
instance_custom_data_access,
@ -142,7 +141,6 @@ static ComponentAttributeProviders create_attribute_providers_for_instances()
static BuiltinCustomDataLayerProvider instance_transform("instance_transform",
AttrDomain::Instance,
CD_PROP_FLOAT4X4,
CD_PROP_FLOAT4X4,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
instance_custom_data_access,
@ -152,7 +150,6 @@ static ComponentAttributeProviders create_attribute_providers_for_instances()
static BuiltinCustomDataLayerProvider reference_index(".reference_index",
AttrDomain::Instance,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
instance_custom_data_access,

View File

@ -1010,7 +1010,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider position("position",
AttrDomain::Point,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
point_access,
@ -1019,7 +1018,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider id("id",
AttrDomain::Point,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -1035,7 +1033,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider material_index("material_index",
AttrDomain::Face,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
face_access,
@ -1049,7 +1046,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider edge_verts(".edge_verts",
AttrDomain::Edge,
CD_PROP_INT32_2D,
CD_PROP_INT32_2D,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
edge_access,
@ -1065,7 +1061,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider corner_vert(".corner_vert",
AttrDomain::Corner,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
corner_access,
@ -1074,7 +1069,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider corner_edge(".corner_edge",
AttrDomain::Corner,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
corner_access,
@ -1084,7 +1078,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider sharp_face("sharp_face",
AttrDomain::Face,
CD_PROP_BOOL,
CD_PROP_BOOL,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
face_access,
@ -1093,7 +1086,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static BuiltinCustomDataLayerProvider sharp_edge("sharp_edge",
AttrDomain::Edge,
CD_PROP_BOOL,
CD_PROP_BOOL,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
edge_access,

View File

@ -147,7 +147,6 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
static BuiltinCustomDataLayerProvider position("position",
AttrDomain::Point,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
point_access,
@ -155,7 +154,6 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
static BuiltinCustomDataLayerProvider radius("radius",
AttrDomain::Point,
CD_PROP_FLOAT,
CD_PROP_FLOAT,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,
@ -163,7 +161,6 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
static BuiltinCustomDataLayerProvider id("id",
AttrDomain::Point,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Deletable,
point_access,

View File

@ -62,11 +62,11 @@ static void pointcloud_init_data(ID *id)
MEMCPY_STRUCT_AFTER(pointcloud, DNA_struct_default_get(PointCloud), id);
pointcloud->runtime = new blender::bke::PointCloudRuntime();
CustomData_reset(&pointcloud->pdata);
pointcloud->attributes_for_write().add<float3>(
"position", blender::bke::AttrDomain::Point, blender::bke::AttributeInitConstruct());
pointcloud->runtime = new blender::bke::PointCloudRuntime();
}
static void pointcloud_copy_data(Main * /*bmain*/,

View File

@ -7,6 +7,8 @@
#include "COM_ConstantOperation.h"
#include "COM_MultiThreadedOperation.h"
#include <mutex>
namespace blender::compositor {
class TranslateOperation : public MultiThreadedOperation {
@ -21,6 +23,8 @@ class TranslateOperation : public MultiThreadedOperation {
bool is_delta_set_;
bool is_relative_;
std::mutex mutex_;
protected:
MemoryBufferExtend x_extend_mode_;
MemoryBufferExtend y_extend_mode_;
@ -50,6 +54,11 @@ class TranslateOperation : public MultiThreadedOperation {
inline void ensure_delta()
{
if (!is_delta_set_) {
std::unique_lock lock(mutex_);
if (is_delta_set_) {
return;
}
delta_x_ = get_input_operation(X_INPUT_INDEX)->get_constant_value_default(0.0f);
delta_y_ = get_input_operation(Y_INPUT_INDEX)->get_constant_value_default(0.0f);
if (get_is_relative()) {

View File

@ -3674,138 +3674,136 @@ size_t ANIM_animdata_filter(bAnimContext *ac,
void *data,
eAnimCont_Types datatype)
{
if (!data || !anim_data) {
return 0;
}
size_t items = 0;
switch (datatype) {
/* Action-Editing Modes */
case ANIMCONT_ACTION: /* 'Action Editor' */
{
Object *obact = ac->obact;
SpaceAction *saction = (SpaceAction *)ac->sl;
bDopeSheet *ads = (saction) ? &saction->ads : nullptr;
/* only filter data if there's somewhere to put it */
if (data && anim_data) {
/* firstly filter the data */
switch (datatype) {
/* Action-Editing Modes */
case ANIMCONT_ACTION: /* 'Action Editor' */
{
Object *obact = ac->obact;
SpaceAction *saction = (SpaceAction *)ac->sl;
bDopeSheet *ads = (saction) ? &saction->ads : nullptr;
/* specially check for AnimData filter, see #36687. */
if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
/* all channels here are within the same AnimData block, hence this special case */
if (LIKELY(obact->adt)) {
ANIMCHANNEL_NEW_CHANNEL(obact->adt, ANIMTYPE_ANIMDATA, (ID *)obact, nullptr);
}
/* specially check for AnimData filter, see #36687. */
if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
/* all channels here are within the same AnimData block, hence this special case */
if (LIKELY(obact->adt)) {
ANIMCHANNEL_NEW_CHANNEL(obact->adt, ANIMTYPE_ANIMDATA, (ID *)obact, nullptr);
}
else {
/* The check for the DopeSheet summary is included here
* since the summary works here too. */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items += animfilter_action(
ac, anim_data, ads, static_cast<bAction *>(data), filter_mode, (ID *)obact);
}
}
break;
}
case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
{
Key *key = (Key *)data;
/* specially check for AnimData filter, see #36687. */
if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
/* all channels here are within the same AnimData block, hence this special case */
if (LIKELY(key->adt)) {
ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, (ID *)key, nullptr);
}
}
else {
/* The check for the DopeSheet summary is included here
* since the summary works here too. */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items = animdata_filter_shapekey(ac, anim_data, key, filter_mode);
}
}
break;
}
/* Modes for Specialty Data Types (i.e. not keyframes) */
case ANIMCONT_GPENCIL: {
else {
/* The check for the DopeSheet summary is included here
* since the summary works here too. */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
if (U.experimental.use_grease_pencil_version3) {
items = animdata_filter_grease_pencil(ac, anim_data, filter_mode);
}
else {
items = animdata_filter_gpencil_legacy(ac, anim_data, data, filter_mode);
}
items += animfilter_action(
ac, anim_data, ads, static_cast<bAction *>(data), filter_mode, (ID *)obact);
}
break;
}
case ANIMCONT_MASK: {
break;
}
case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
{
Key *key = (Key *)data;
/* specially check for AnimData filter, see #36687. */
if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
/* all channels here are within the same AnimData block, hence this special case */
if (LIKELY(key->adt)) {
ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, (ID *)key, nullptr);
}
}
else {
/* The check for the DopeSheet summary is included here
* since the summary works here too. */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items = animdata_filter_mask(ac->bmain, anim_data, data, filter_mode);
items = animdata_filter_shapekey(ac, anim_data, key, filter_mode);
}
break;
}
/* DopeSheet Based Modes */
case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
{
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items += animdata_filter_dopesheet(
ac, anim_data, static_cast<bDopeSheet *>(data), filter_mode);
}
break;
}
case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */
case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
case ANIMCONT_NLA: /* NLA Editor */
{
/* all of these editors use the basic DopeSheet data for filtering options,
* but don't have all the same features */
items = animdata_filter_dopesheet(
ac, anim_data, static_cast<bDopeSheet *>(data), filter_mode);
break;
}
/* Timeline Mode - Basically the same as dopesheet,
* except we only have the summary for now */
case ANIMCONT_TIMELINE: {
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items += animdata_filter_dopesheet(
ac, anim_data, static_cast<bDopeSheet *>(data), filter_mode);
}
break;
}
/* Special/Internal Use */
case ANIMCONT_CHANNEL: /* animation channel */
{
bDopeSheet *ads = ac->ads;
/* based on the channel type, filter relevant data for this */
items = animdata_filter_animchan(
ac, anim_data, ads, static_cast<bAnimListElem *>(data), filter_mode);
break;
}
/* unhandled */
default: {
printf("ANIM_animdata_filter() - Invalid datatype argument %i\n", datatype);
break;
}
break;
}
/* remove any 'weedy' entries */
items = animdata_filter_remove_invalid(anim_data);
/* Modes for Specialty Data Types (i.e. not keyframes) */
case ANIMCONT_GPENCIL: {
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
if (U.experimental.use_grease_pencil_version3) {
items = animdata_filter_grease_pencil(ac, anim_data, filter_mode);
}
else {
items = animdata_filter_gpencil_legacy(ac, anim_data, data, filter_mode);
}
}
break;
}
case ANIMCONT_MASK: {
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items = animdata_filter_mask(ac->bmain, anim_data, data, filter_mode);
}
break;
}
/* remove duplicates (if required) */
if (filter_mode & ANIMFILTER_NODUPLIS) {
items = animdata_filter_remove_duplis(anim_data);
/* DopeSheet Based Modes */
case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
{
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items += animdata_filter_dopesheet(
ac, anim_data, static_cast<bDopeSheet *>(data), filter_mode);
}
break;
}
case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */
case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
case ANIMCONT_NLA: /* NLA Editor */
{
/* all of these editors use the basic DopeSheet data for filtering options,
* but don't have all the same features */
items = animdata_filter_dopesheet(
ac, anim_data, static_cast<bDopeSheet *>(data), filter_mode);
break;
}
/* Timeline Mode - Basically the same as dopesheet,
* except we only have the summary for now */
case ANIMCONT_TIMELINE: {
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
items += animdata_filter_dopesheet(
ac, anim_data, static_cast<bDopeSheet *>(data), filter_mode);
}
break;
}
/* Special/Internal Use */
case ANIMCONT_CHANNEL: /* animation channel */
{
bDopeSheet *ads = ac->ads;
/* based on the channel type, filter relevant data for this */
items = animdata_filter_animchan(
ac, anim_data, ads, static_cast<bAnimListElem *>(data), filter_mode);
break;
}
/* unhandled */
default: {
printf("ANIM_animdata_filter() - Invalid datatype argument %i\n", datatype);
break;
}
}
/* return the number of items in the list */
/* remove any 'weedy' entries */
items = animdata_filter_remove_invalid(anim_data);
/* remove duplicates (if required) */
if (filter_mode & ANIMFILTER_NODUPLIS) {
items = animdata_filter_remove_duplis(anim_data);
}
return items;
}

View File

@ -1613,7 +1613,6 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
const float angle = RNA_float_get(op->ptr, "angle");
bke::mesh_sharp_edges_set_from_angle(mesh, angle, keep_sharp_edges);
}
mesh.tag_sharpness_changed();
BKE_mesh_batch_cache_dirty_tag(static_cast<Mesh *>(ob->data), BKE_MESH_BATCH_DIRTY_ALL);
changed = true;
}

@ -1 +1 @@
Subproject commit 00af9c65712b6aa78ce6eb0c62c5aafb7a867f18
Subproject commit bf5c70830540b215a3b1df21f28e0e80ead230f7