WIP: Brush assets project #106303
|
@ -347,10 +347,7 @@ void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
|
|||
|
||||
/* Write debug render pass to validate it matches combined pass. */
|
||||
pgl_vec3f pgl_final_color = kg->opgl_path_segment_storage->CalculatePixelEstimate(false);
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset;
|
||||
ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer);
|
||||
float3 final_color = make_float3(pgl_final_color.x, pgl_final_color.y, pgl_final_color.z);
|
||||
if (kernel_data.film.pass_guiding_color != PASS_UNUSED) {
|
||||
film_write_pass_float3(buffer + kernel_data.film.pass_guiding_color, final_color);
|
||||
|
|
|
@ -60,10 +60,7 @@ ccl_device_inline float bsdf_get_roughness_pass_squared(ccl_private const Shader
|
|||
/* An additional term to smooth illumination on grazing angles when using bump mapping.
|
||||
* Based on "Taming the Shadow Terminator" by Matt Jen-Yuan Chiang,
|
||||
* Yining Karl Li and Brent Burley. */
|
||||
ccl_device_inline float bump_shadowing_term(ccl_private const ShaderData &sd,
|
||||
float3 Ng,
|
||||
float3 N,
|
||||
float3 I)
|
||||
ccl_device_inline float bump_shadowing_term(int shader_flag, float3 Ng, float3 N, float3 I)
|
||||
{
|
||||
const float cosNI = dot(N, I);
|
||||
if (cosNI < 0.0f) {
|
||||
|
@ -82,7 +79,7 @@ ccl_device_inline float bump_shadowing_term(ccl_private const ShaderData &sd,
|
|||
}
|
||||
|
||||
/* When bump map correction is not used do skip the smoothing. */
|
||||
if ((sd.flag & SD_USE_BUMP_MAP_CORRECTION) == 0) {
|
||||
if ((shader_flag & SD_USE_BUMP_MAP_CORRECTION) == 0) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
@ -244,7 +241,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
|||
}
|
||||
if (label & LABEL_DIFFUSE) {
|
||||
if (!isequal(sc->N, sd->N)) {
|
||||
*eval *= bump_shadowing_term(*sd, sd->N, sc->N, *wo);
|
||||
*eval *= bump_shadowing_term(sd->flag, sd->N, sc->N, *wo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -540,7 +537,7 @@ ccl_device_inline
|
|||
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
||||
if (!isequal(sc->N, sd->N)) {
|
||||
eval *= bump_shadowing_term(*sd, sd->N, sc->N, wo);
|
||||
eval *= bump_shadowing_term(sd->flag, sd->N, sc->N, wo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ ccl_device int bsdf_hair_chiang_setup(ccl_private ShaderData *sd, ccl_private Ch
|
|||
|
||||
bsdf->N = Y;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG | SD_BSDF_HAS_TRANSMISSION;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
|
||||
}
|
||||
|
||||
#endif /* __HAIR__ */
|
||||
|
|
|
@ -101,7 +101,7 @@ ccl_device_forceinline float curve_ribbon_v(
|
|||
curve[3] = kernel_data_fetch(curve_keys, kb);
|
||||
}
|
||||
else {
|
||||
motion_curve_keys(kg, object, prim, time, ka, k0, k1, kb, curve);
|
||||
motion_curve_keys(kg, object, time, ka, k0, k1, kb, curve);
|
||||
}
|
||||
|
||||
float3 ray_P = ray->P;
|
||||
|
|
|
@ -18,10 +18,7 @@ ccl_device_forceinline bool film_need_sample_pixel(KernelGlobals kg,
|
|||
return true;
|
||||
}
|
||||
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset;
|
||||
ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer);
|
||||
|
||||
const uint aux_w_offset = kernel_data.film.pass_adaptive_aux_buffer + 3;
|
||||
return buffer[aux_w_offset] == 0.0f;
|
||||
|
|
|
@ -466,10 +466,7 @@ ccl_device_inline void film_write_direct_light(KernelGlobals kg,
|
|||
Spectrum contribution = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
film_clamp_light(kg, &contribution, INTEGRATOR_STATE(state, shadow_path, bounce));
|
||||
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, shadow_path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset;
|
||||
ccl_global float *buffer = film_pass_pixel_render_buffer_shadow(kg, state, render_buffer);
|
||||
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag);
|
||||
const int sample = INTEGRATOR_STATE(state, shadow_path, sample);
|
||||
|
|
|
@ -23,6 +23,17 @@ ccl_device_forceinline ccl_global float *film_pass_pixel_render_buffer(
|
|||
return render_buffer + render_buffer_offset;
|
||||
}
|
||||
|
||||
ccl_device_forceinline ccl_global float *film_pass_pixel_render_buffer_shadow(
|
||||
KernelGlobals kg,
|
||||
ConstIntegratorShadowState state,
|
||||
ccl_global float *ccl_restrict render_buffer)
|
||||
{
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, shadow_path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
return render_buffer + render_buffer_offset;
|
||||
}
|
||||
|
||||
/* Accumulate in passes. */
|
||||
|
||||
ccl_device_inline void film_write_pass_float(ccl_global float *ccl_restrict buffer, float value)
|
||||
|
|
|
@ -207,7 +207,7 @@ ccl_device float curve_thickness(KernelGlobals kg, ccl_private const ShaderData
|
|||
P_curve[1] = kernel_data_fetch(curve_keys, k1);
|
||||
}
|
||||
else {
|
||||
motion_curve_keys_linear(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
|
||||
motion_curve_keys_linear(kg, sd->object, sd->time, k0, k1, P_curve);
|
||||
}
|
||||
|
||||
r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
|
||||
|
|
|
@ -650,7 +650,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg,
|
|||
curve[3] = kernel_data_fetch(curve_keys, kb);
|
||||
}
|
||||
else {
|
||||
motion_curve_keys(kg, object, prim, time, ka, k0, k1, kb, curve);
|
||||
motion_curve_keys(kg, object, time, ka, k0, k1, kb, curve);
|
||||
}
|
||||
|
||||
if (type & PRIMITIVE_CURVE_RIBBON) {
|
||||
|
@ -682,7 +682,6 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
|
|||
float3 P,
|
||||
float3 D,
|
||||
float t,
|
||||
const int isect_object,
|
||||
const int isect_prim)
|
||||
{
|
||||
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
|
||||
|
@ -709,7 +708,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
|
|||
P_curve[3] = kernel_data_fetch(curve_keys, kb);
|
||||
}
|
||||
else {
|
||||
motion_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
|
||||
motion_curve_keys(kg, sd->object, sd->time, ka, k0, k1, kb, P_curve);
|
||||
}
|
||||
|
||||
P = P + D * t;
|
||||
|
|
|
@ -45,7 +45,7 @@ ccl_device_inline void motion_curve_keys_for_step_linear(KernelGlobals kg,
|
|||
|
||||
/* return 2 curve key locations */
|
||||
ccl_device_inline void motion_curve_keys_linear(
|
||||
KernelGlobals kg, int object, int prim, float time, int k0, int k1, float4 keys[2])
|
||||
KernelGlobals kg, int object, float time, int k0, int k1, float4 keys[2])
|
||||
{
|
||||
/* get motion info */
|
||||
const int numsteps = kernel_data_fetch(objects, object).numsteps;
|
||||
|
@ -104,15 +104,8 @@ ccl_device_inline void motion_curve_keys_for_step(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* return 2 curve key locations */
|
||||
ccl_device_inline void motion_curve_keys(KernelGlobals kg,
|
||||
int object,
|
||||
int prim,
|
||||
float time,
|
||||
int k0,
|
||||
int k1,
|
||||
int k2,
|
||||
int k3,
|
||||
float4 keys[4])
|
||||
ccl_device_inline void motion_curve_keys(
|
||||
KernelGlobals kg, int object, float time, int k0, int k1, int k2, int k3, float4 keys[4])
|
||||
{
|
||||
/* get motion info */
|
||||
const int numsteps = kernel_data_fetch(objects, object).numsteps;
|
||||
|
|
|
@ -20,13 +20,8 @@ CCL_NAMESPACE_BEGIN
|
|||
/**
|
||||
* Use the barycentric coordinates to get the intersection location
|
||||
*/
|
||||
ccl_device_inline float3 motion_triangle_point_from_uv(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const int isect_object,
|
||||
const int isect_prim,
|
||||
const float u,
|
||||
const float v,
|
||||
float3 verts[3])
|
||||
ccl_device_inline float3 motion_triangle_point_from_uv(
|
||||
KernelGlobals kg, ccl_private ShaderData *sd, const float u, const float v, float3 verts[3])
|
||||
{
|
||||
/* This appears to give slightly better precision than interpolating with w = (1 - u - v). */
|
||||
float3 P = verts[0] + u * (verts[1] - verts[0]) + v * (verts[2] - verts[0]);
|
||||
|
|
|
@ -22,14 +22,7 @@ CCL_NAMESPACE_BEGIN
|
|||
* normals */
|
||||
|
||||
/* return 3 triangle vertex normals */
|
||||
ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const float3 P,
|
||||
const float3 D,
|
||||
const float ray_t,
|
||||
const int isect_object,
|
||||
const int isect_prim,
|
||||
bool is_local)
|
||||
ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg, ccl_private ShaderData *sd)
|
||||
{
|
||||
/* Get shader. */
|
||||
sd->shader = kernel_data_fetch(tri_shader, sd->prim);
|
||||
|
@ -46,7 +39,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
|
|||
motion_triangle_vertices(kg, sd->object, tri_vindex, numsteps, numverts, step, t, verts);
|
||||
|
||||
/* Compute refined position. */
|
||||
sd->P = motion_triangle_point_from_uv(kg, sd, isect_object, isect_prim, sd->u, sd->v, verts);
|
||||
sd->P = motion_triangle_point_from_uv(kg, sd, sd->u, sd->v, verts);
|
||||
/* Compute face normal. */
|
||||
float3 Ng;
|
||||
if (object_negative_scale_applied(sd->object_flag)) {
|
||||
|
|
|
@ -61,7 +61,7 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg,
|
|||
#ifdef __HAIR__
|
||||
if (sd->type & PRIMITIVE_CURVE) {
|
||||
/* curve */
|
||||
curve_shader_setup(kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim);
|
||||
curve_shader_setup(kg, sd, ray->P, ray->D, isect->t, isect->prim);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -76,27 +76,11 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg,
|
|||
{
|
||||
if (sd->type == PRIMITIVE_TRIANGLE) {
|
||||
/* static triangle */
|
||||
float3 Ng = triangle_normal(kg, sd);
|
||||
sd->shader = kernel_data_fetch(tri_shader, sd->prim);
|
||||
|
||||
/* vectors */
|
||||
sd->P = triangle_point_from_uv(kg, sd, isect->object, isect->prim, isect->u, isect->v);
|
||||
sd->Ng = Ng;
|
||||
sd->N = Ng;
|
||||
|
||||
/* smooth normal */
|
||||
if (sd->shader & SHADER_SMOOTH_NORMAL)
|
||||
sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
|
||||
|
||||
#ifdef __DPDU__
|
||||
/* dPdu/dPdv */
|
||||
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
|
||||
#endif
|
||||
triangle_shader_setup(kg, sd);
|
||||
}
|
||||
else {
|
||||
/* motion triangle */
|
||||
motion_triangle_shader_setup(
|
||||
kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim, false);
|
||||
motion_triangle_shader_setup(kg, sd);
|
||||
}
|
||||
|
||||
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
|
||||
|
|
|
@ -139,7 +139,6 @@ ccl_device_inline bool triangle_intersect_local(KernelGlobals kg,
|
|||
*/
|
||||
ccl_device_inline float3 triangle_point_from_uv(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
const int isect_object,
|
||||
const int isect_prim,
|
||||
const float u,
|
||||
const float v)
|
||||
|
@ -160,4 +159,26 @@ ccl_device_inline float3 triangle_point_from_uv(KernelGlobals kg,
|
|||
return P;
|
||||
}
|
||||
|
||||
ccl_device_inline void triangle_shader_setup(KernelGlobals kg, ccl_private ShaderData *sd)
|
||||
{
|
||||
sd->shader = kernel_data_fetch(tri_shader, sd->prim);
|
||||
|
||||
sd->P = triangle_point_from_uv(kg, sd, sd->prim, sd->u, sd->v);
|
||||
|
||||
/* Normals. */
|
||||
float3 Ng = triangle_normal(kg, sd);
|
||||
sd->Ng = Ng;
|
||||
sd->N = Ng;
|
||||
|
||||
/* Smooth normal. */
|
||||
if (sd->shader & SHADER_SMOOTH_NORMAL) {
|
||||
sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
|
||||
}
|
||||
|
||||
#ifdef __DPDU__
|
||||
/* dPdu/dPdv */
|
||||
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
|
||||
#endif
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -472,10 +472,7 @@ ccl_device_forceinline void guiding_write_debug_passes(KernelGlobals kg,
|
|||
return;
|
||||
}
|
||||
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset;
|
||||
ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer);
|
||||
|
||||
if (kernel_data.film.pass_guiding_probability != PASS_UNUSED) {
|
||||
float guiding_prob = state->guiding.surface_guiding_sampling_prob;
|
||||
|
|
|
@ -125,9 +125,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
|
|||
kg, state, render_buffer, scheduled_sample, tile->sample_offset);
|
||||
|
||||
/* Setup render buffers. */
|
||||
const int index = INTEGRATOR_STATE(state, path, render_pixel_index);
|
||||
const int pass_stride = kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + (uint64_t)index * pass_stride;
|
||||
ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer);
|
||||
|
||||
ccl_global float *primitive = buffer + kernel_data.film.pass_bake_primitive;
|
||||
ccl_global float *differential = buffer + kernel_data.film.pass_bake_differential;
|
||||
|
|
|
@ -150,7 +150,7 @@ ccl_device bool shadow_linking_pick_light_intersection(KernelGlobals kg,
|
|||
ccl_device bool shadow_linking_intersect(KernelGlobals kg, IntegratorState state)
|
||||
{
|
||||
/* Verify that the kernel is only scheduled if it is actually needed. */
|
||||
kernel_assert(shadow_linking_scene_need_shadow_ray(kg, state));
|
||||
kernel_assert(shadow_linking_scene_need_shadow_ray(kg));
|
||||
|
||||
/* Read ray from integrator state into local memory. */
|
||||
Ray ray ccl_optional_struct_init;
|
||||
|
|
|
@ -157,8 +157,7 @@ ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg,
|
|||
kg, sd_vtx->object, sd_vtx->prim, sd_vtx->time, verts, normals);
|
||||
|
||||
/* Compute refined position. */
|
||||
sd_vtx->P = motion_triangle_point_from_uv(
|
||||
kg, sd_vtx, isect->object, isect->prim, isect->u, isect->v, verts);
|
||||
sd_vtx->P = motion_triangle_point_from_uv(kg, sd_vtx, isect->u, isect->v, verts);
|
||||
}
|
||||
|
||||
/* Instance transform. */
|
||||
|
|
|
@ -107,13 +107,7 @@ ccl_device_inline void integrate_background(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* Background MIS weights. */
|
||||
float mis_weight = 1.0f;
|
||||
/* Check if background light exists or if we should skip PDF. */
|
||||
if (!(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_MIS_SKIP) &&
|
||||
kernel_data.background.use_mis)
|
||||
{
|
||||
mis_weight = light_sample_mis_weight_forward_background(kg, state, path_flag);
|
||||
}
|
||||
const float mis_weight = light_sample_mis_weight_forward_background(kg, state, path_flag);
|
||||
|
||||
guiding_record_background(kg, state, L, mis_weight);
|
||||
L *= mis_weight;
|
||||
|
@ -174,10 +168,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* MIS weighting. */
|
||||
float mis_weight = 1.0f;
|
||||
if (!(path_flag & PATH_RAY_MIS_SKIP)) {
|
||||
mis_weight = light_sample_mis_weight_forward_distant(kg, state, path_flag, &ls);
|
||||
}
|
||||
const float mis_weight = light_sample_mis_weight_forward_distant(kg, state, path_flag, &ls);
|
||||
|
||||
/* Write to render buffer. */
|
||||
guiding_record_background(kg, state, light_eval, mis_weight);
|
||||
|
|
|
@ -110,24 +110,17 @@ ccl_device bool shadow_linking_shade_light(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* MIS weighting. */
|
||||
if (!(path_flag & PATH_RAY_MIS_SKIP)) {
|
||||
mis_weight = shadow_linking_light_sample_mis_weight(kg, state, path_flag, &ls, ray.P);
|
||||
}
|
||||
mis_weight = shadow_linking_light_sample_mis_weight(kg, state, path_flag, &ls, ray.P);
|
||||
|
||||
bsdf_spectrum = light_eval * mis_weight *
|
||||
INTEGRATOR_STATE(state, shadow_link, dedicated_light_weight);
|
||||
|
||||
// TODO(: De-duplicate with the shade_surface.
|
||||
// Possibly by ensuring ls->group is always assigned properly.
|
||||
light_group = ls.type != LIGHT_BACKGROUND ? ls.group : kernel_data.background.lightgroup;
|
||||
light_group = ls.group;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device bool shadow_linking_shade_surface_emission(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private Ray &ccl_restrict ray,
|
||||
ccl_private Intersection &ccl_restrict isect,
|
||||
ccl_private ShaderData *emission_sd,
|
||||
ccl_global float *ccl_restrict render_buffer,
|
||||
ccl_private Spectrum &ccl_restrict
|
||||
|
@ -154,18 +147,7 @@ ccl_device bool shadow_linking_shade_surface_emission(KernelGlobals kg,
|
|||
|
||||
const Spectrum L = surface_shader_emission(emission_sd);
|
||||
|
||||
const bool has_mis = !(path_flag & PATH_RAY_MIS_SKIP) &&
|
||||
(emission_sd->flag &
|
||||
((emission_sd->flag & SD_BACKFACING) ? SD_MIS_BACK : SD_MIS_FRONT));
|
||||
|
||||
# ifdef __HAIR__
|
||||
if (has_mis && (emission_sd->type & PRIMITIVE_TRIANGLE))
|
||||
# else
|
||||
if (has_mis)
|
||||
# endif
|
||||
{
|
||||
mis_weight = light_sample_mis_weight_forward_surface(kg, state, path_flag, emission_sd);
|
||||
}
|
||||
mis_weight = light_sample_mis_weight_forward_surface(kg, state, path_flag, emission_sd);
|
||||
|
||||
bsdf_spectrum = L * mis_weight * INTEGRATOR_STATE(state, shadow_link, dedicated_light_weight);
|
||||
light_group = object_lightgroup(kg, emission_sd->object);
|
||||
|
@ -200,15 +182,8 @@ ccl_device void shadow_linking_shade(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!shadow_linking_shade_surface_emission(kg,
|
||||
state,
|
||||
ray,
|
||||
isect,
|
||||
emission_sd,
|
||||
render_buffer,
|
||||
bsdf_spectrum,
|
||||
mis_weight,
|
||||
light_group))
|
||||
if (!shadow_linking_shade_surface_emission(
|
||||
kg, state, emission_sd, render_buffer, bsdf_spectrum, mis_weight, light_group))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -55,10 +55,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* MIS weighting. */
|
||||
float mis_weight = 1.0f;
|
||||
if (!(path_flag & PATH_RAY_MIS_SKIP)) {
|
||||
mis_weight = light_sample_mis_weight_forward_lamp(kg, state, path_flag, &ls, ray_P);
|
||||
}
|
||||
const float mis_weight = light_sample_mis_weight_forward_lamp(kg, state, path_flag, &ls, ray_P);
|
||||
|
||||
/* Write to render buffer. */
|
||||
guiding_record_surface_emission(kg, state, light_eval, mis_weight);
|
||||
|
|
|
@ -138,19 +138,8 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
|
|||
|
||||
/* Evaluate emissive closure. */
|
||||
Spectrum L = surface_shader_emission(sd);
|
||||
float mis_weight = 1.0f;
|
||||
|
||||
const bool has_mis = !(path_flag & PATH_RAY_MIS_SKIP) &&
|
||||
(sd->flag & ((sd->flag & SD_BACKFACING) ? SD_MIS_BACK : SD_MIS_FRONT));
|
||||
|
||||
#ifdef __HAIR__
|
||||
if (has_mis && (sd->type & PRIMITIVE_TRIANGLE))
|
||||
#else
|
||||
if (has_mis)
|
||||
#endif
|
||||
{
|
||||
mis_weight = light_sample_mis_weight_forward_surface(kg, state, path_flag, sd);
|
||||
}
|
||||
const float mis_weight = light_sample_mis_weight_forward_surface(kg, state, path_flag, sd);
|
||||
|
||||
guiding_record_surface_emission(kg, state, L, mis_weight);
|
||||
film_write_surface_emission(
|
||||
|
@ -263,7 +252,6 @@ ccl_device
|
|||
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
|
||||
|
||||
if (!light_sample_from_position(kg,
|
||||
rng_state,
|
||||
rand_light,
|
||||
sd->time,
|
||||
sd->P,
|
||||
|
@ -339,16 +327,12 @@ ccl_device
|
|||
|
||||
/* Evaluate BSDF. */
|
||||
const float bsdf_pdf = surface_shader_bsdf_eval(kg, state, sd, ls.D, &bsdf_eval, ls.shader);
|
||||
bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf);
|
||||
|
||||
if (ls.shader & SHADER_USE_MIS) {
|
||||
const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf);
|
||||
bsdf_eval_mul(&bsdf_eval, mis_weight);
|
||||
}
|
||||
const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf);
|
||||
bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf * mis_weight);
|
||||
|
||||
/* Path termination. */
|
||||
const float terminate = path_state_rng_light_termination(kg, rng_state);
|
||||
if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) {
|
||||
if (light_sample_terminate(kg, &bsdf_eval, terminate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -361,13 +345,8 @@ ccl_device
|
|||
}
|
||||
|
||||
/* Branch off shadow kernel. */
|
||||
|
||||
// TODO(: De-duplicate with the shade_Dedicated_light.
|
||||
// Possibly by ensuring ls->group is always assigned properly.
|
||||
const int light_group = ls.type != LIGHT_BACKGROUND ? ls.group :
|
||||
kernel_data.background.lightgroup;
|
||||
IntegratorShadowState shadow_state = integrate_direct_light_shadow_init_common(
|
||||
kg, state, &ray, bsdf_eval_sum(&bsdf_eval), light_group, mnee_vertex_count);
|
||||
kg, state, &ray, bsdf_eval_sum(&bsdf_eval), ls.group, mnee_vertex_count);
|
||||
|
||||
if (is_transmission) {
|
||||
#ifdef __VOLUME__
|
||||
|
@ -570,8 +549,7 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
|
|||
IntegratorState state,
|
||||
ccl_private const ShaderData *ccl_restrict sd,
|
||||
ccl_private const RNGState *ccl_restrict
|
||||
rng_state,
|
||||
ccl_global float *ccl_restrict render_buffer)
|
||||
rng_state)
|
||||
{
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
|
||||
|
@ -752,7 +730,7 @@ ccl_device int integrate_surface(KernelGlobals kg,
|
|||
/* Ambient occlusion pass. */
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_AO) {
|
||||
PROFILING_EVENT(PROFILING_SHADE_SURFACE_AO);
|
||||
integrate_surface_ao(kg, state, &sd, &rng_state, render_buffer);
|
||||
integrate_surface_ao(kg, state, &sd, &rng_state);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -798,18 +798,13 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
|||
|
||||
/* Evaluate BSDF. */
|
||||
BsdfEval phase_eval ccl_optional_struct_init;
|
||||
float phase_pdf = volume_shader_phase_eval(kg, state, sd, phases, ls.D, &phase_eval);
|
||||
|
||||
if (ls.shader & SHADER_USE_MIS) {
|
||||
float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, phase_pdf);
|
||||
bsdf_eval_mul(&phase_eval, mis_weight);
|
||||
}
|
||||
|
||||
bsdf_eval_mul(&phase_eval, light_eval / ls.pdf);
|
||||
float phase_pdf = volume_shader_phase_eval(kg, state, sd, phases, ls.D, &phase_eval, ls.shader);
|
||||
const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, phase_pdf);
|
||||
bsdf_eval_mul(&phase_eval, light_eval / ls.pdf * mis_weight);
|
||||
|
||||
/* Path termination. */
|
||||
const float terminate = path_state_rng_light_termination(kg, rng_state);
|
||||
if (light_sample_terminate(kg, &ls, &phase_eval, terminate)) {
|
||||
if (light_sample_terminate(kg, &phase_eval, terminate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -871,10 +866,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
|||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, throughput) = throughput_phase;
|
||||
|
||||
/* Write Light-group, +1 as light-group is int but we need to encode into a uint8_t. */
|
||||
INTEGRATOR_STATE_WRITE(
|
||||
shadow_state, shadow_path, lightgroup) = (ls.type != LIGHT_BACKGROUND) ?
|
||||
ls.group + 1 :
|
||||
kernel_data.background.lightgroup + 1;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, lightgroup) = ls.group + 1;
|
||||
|
||||
# ifdef __PATH_GUIDING__
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unlit_throughput) = unlit_throughput;
|
||||
|
|
|
@ -13,8 +13,7 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
/* Check whether special shadow rays for shadow linking are needed in the current scene
|
||||
* configuration. */
|
||||
ccl_device_forceinline bool shadow_linking_scene_need_shadow_ray(KernelGlobals kg,
|
||||
IntegratorState state)
|
||||
ccl_device_forceinline bool shadow_linking_scene_need_shadow_ray(KernelGlobals kg)
|
||||
{
|
||||
if (!(kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_LINKING)) {
|
||||
/* No shadow linking in the scene, so no need to trace any extra rays. */
|
||||
|
@ -57,7 +56,7 @@ template<DeviceKernel current_kernel>
|
|||
ccl_device_inline bool shadow_linking_schedule_intersection_kernel(KernelGlobals kg,
|
||||
IntegratorState state)
|
||||
{
|
||||
if (!shadow_linking_scene_need_shadow_ray(kg, state)) {
|
||||
if (!shadow_linking_scene_need_shadow_ray(kg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -364,6 +364,12 @@ ccl_device_inline
|
|||
float pdf = _surface_shader_bsdf_eval_mis(
|
||||
kg, sd, wo, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
|
||||
|
||||
/* If the light does not use MIS, then it is only sampled via NEE, so the probability of hitting
|
||||
* the light using BSDF sampling is zero. */
|
||||
if (!(light_shader_flags & SHADER_USE_MIS)) {
|
||||
pdf = 0.0f;
|
||||
}
|
||||
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (pdf > 0.0f && state->guiding.use_surface_guiding) {
|
||||
const float guiding_sampling_prob = state->guiding.surface_guiding_sampling_prob;
|
||||
|
|
|
@ -249,7 +249,8 @@ ccl_device float volume_shader_phase_eval(KernelGlobals kg,
|
|||
ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderVolumePhases *phases,
|
||||
const float3 wo,
|
||||
ccl_private BsdfEval *phase_eval)
|
||||
ccl_private BsdfEval *phase_eval,
|
||||
const uint light_shader_flags)
|
||||
{
|
||||
bsdf_eval_init(phase_eval, zero_spectrum());
|
||||
|
||||
|
@ -263,6 +264,12 @@ ccl_device float volume_shader_phase_eval(KernelGlobals kg,
|
|||
}
|
||||
# endif
|
||||
|
||||
/* If the light does not use MIS, then it is only sampled via NEE, so the probability of hitting
|
||||
* the light using BSDF sampling is zero. */
|
||||
if (!(light_shader_flags & SHADER_USE_MIS)) {
|
||||
pdf = 0.0f;
|
||||
}
|
||||
|
||||
return pdf;
|
||||
}
|
||||
|
||||
|
|
|
@ -473,12 +473,12 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
|
|||
ls->group = lamp_lightgroup(kg, lamp);
|
||||
|
||||
if (type == LIGHT_SPOT) {
|
||||
if (!spot_light_sample_from_intersection(klight, isect, ray_P, ray_D, N, path_flag, ls)) {
|
||||
if (!spot_light_sample_from_intersection(klight, ray_P, ray_D, N, path_flag, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (type == LIGHT_POINT) {
|
||||
if (!point_light_sample_from_intersection(klight, isect, ray_P, ray_D, N, path_flag, ls)) {
|
||||
if (!point_light_sample_from_intersection(klight, ray_P, ray_D, N, path_flag, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,14 +148,13 @@ ccl_device_inline bool point_light_intersect(const ccl_global KernelLight *kligh
|
|||
}
|
||||
}
|
||||
|
||||
ccl_device_inline bool point_light_sample_from_intersection(
|
||||
const ccl_global KernelLight *klight,
|
||||
ccl_private const Intersection *ccl_restrict isect,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
ccl_device_inline bool point_light_sample_from_intersection(const ccl_global KernelLight *klight,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict
|
||||
ls)
|
||||
{
|
||||
const float r_sq = sqr(klight->spot.radius);
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ light_sample_shader_eval(KernelGlobals kg,
|
|||
|
||||
/* Early path termination of shadow rays. */
|
||||
ccl_device_inline bool light_sample_terminate(KernelGlobals kg,
|
||||
ccl_private const LightSample *ccl_restrict ls,
|
||||
ccl_private BsdfEval *ccl_restrict eval,
|
||||
const float rand_terminate)
|
||||
{
|
||||
|
@ -301,7 +300,10 @@ ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg,
|
|||
{
|
||||
#ifdef WITH_CYCLES_DEBUG
|
||||
if (kernel_data.integrator.direct_light_sampling_type == DIRECT_LIGHT_SAMPLING_FORWARD) {
|
||||
return 0.0f;
|
||||
/* Return 0.0f to only account for the contribution in forward path tracing, unless when the
|
||||
* light can not be forward sampled, in which case return 1.0f so it converges to the same
|
||||
* result. */
|
||||
return (forward_pdf == 0.0f);
|
||||
}
|
||||
else if (kernel_data.integrator.direct_light_sampling_type == DIRECT_LIGHT_SAMPLING_NEE) {
|
||||
return 1.0f;
|
||||
|
@ -351,7 +353,6 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
|
|||
}
|
||||
|
||||
ccl_device bool light_sample_from_position(KernelGlobals kg,
|
||||
ccl_private const RNGState *rng_state,
|
||||
const float3 rand,
|
||||
const float time,
|
||||
const float3 P,
|
||||
|
@ -422,6 +423,17 @@ ccl_device_inline float light_sample_mis_weight_forward_surface(KernelGlobals kg
|
|||
const uint32_t path_flag,
|
||||
const ccl_private ShaderData *sd)
|
||||
{
|
||||
bool has_mis = !(path_flag & PATH_RAY_MIS_SKIP) &&
|
||||
(sd->flag & ((sd->flag & SD_BACKFACING) ? SD_MIS_BACK : SD_MIS_FRONT));
|
||||
|
||||
#ifdef __HAIR__
|
||||
has_mis &= (sd->type & PRIMITIVE_TRIANGLE);
|
||||
#endif
|
||||
|
||||
if (!has_mis) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
const float bsdf_pdf = INTEGRATOR_STATE(state, path, mis_ray_pdf);
|
||||
const float t = sd->ray_length;
|
||||
float pdf = triangle_light_pdf(kg, sd, t);
|
||||
|
@ -455,6 +467,10 @@ ccl_device_inline float light_sample_mis_weight_forward_lamp(KernelGlobals kg,
|
|||
const ccl_private LightSample *ls,
|
||||
const float3 P)
|
||||
{
|
||||
if (path_flag & PATH_RAY_MIS_SKIP) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
const float mis_ray_pdf = INTEGRATOR_STATE(state, path, mis_ray_pdf);
|
||||
float pdf = ls->pdf;
|
||||
|
||||
|
@ -494,6 +510,11 @@ ccl_device_inline float light_sample_mis_weight_forward_background(KernelGlobals
|
|||
IntegratorState state,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
/* Check if background light exists or if we should skip PDF. */
|
||||
if (!kernel_data.background.use_mis || (path_flag & PATH_RAY_MIS_SKIP)) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
const float3 ray_P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
|
||||
const float mis_ray_pdf = INTEGRATOR_STATE(state, path, mis_ray_pdf);
|
||||
|
|
|
@ -220,14 +220,13 @@ ccl_device_inline bool spot_light_intersect(const ccl_global KernelLight *klight
|
|||
return point_light_intersect(klight, ray, t);
|
||||
}
|
||||
|
||||
ccl_device_inline bool spot_light_sample_from_intersection(
|
||||
const ccl_global KernelLight *klight,
|
||||
ccl_private const Intersection *ccl_restrict isect,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
ccl_device_inline bool spot_light_sample_from_intersection(const ccl_global KernelLight *klight,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict
|
||||
ls)
|
||||
{
|
||||
const float r_sq = sqr(klight->spot.radius);
|
||||
const float d_sq = len_squared(ray_P - klight->co);
|
||||
|
|
|
@ -134,7 +134,6 @@ ccl_device void light_tree_importance(const float3 N_or_D,
|
|||
const BoundingCone bcone,
|
||||
const float max_distance,
|
||||
const float min_distance,
|
||||
const float t,
|
||||
const float energy,
|
||||
ccl_private float &max_importance,
|
||||
ccl_private float &min_importance)
|
||||
|
@ -370,7 +369,6 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
|
|||
bcone,
|
||||
distance,
|
||||
distance,
|
||||
t,
|
||||
knode->energy,
|
||||
max_importance,
|
||||
min_importance);
|
||||
|
@ -477,7 +475,6 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
bcone,
|
||||
distance.x,
|
||||
distance.y,
|
||||
t,
|
||||
kemitter->energy,
|
||||
max_importance,
|
||||
min_importance);
|
||||
|
|
|
@ -203,24 +203,14 @@ ccl_device float3 svm_bevel(
|
|||
/* Quickly retrieve P and Ng without setting up ShaderData. */
|
||||
float3 hit_P;
|
||||
if (sd->type == PRIMITIVE_TRIANGLE) {
|
||||
hit_P = triangle_point_from_uv(kg,
|
||||
sd,
|
||||
isect.hits[hit].object,
|
||||
isect.hits[hit].prim,
|
||||
isect.hits[hit].u,
|
||||
isect.hits[hit].v);
|
||||
hit_P = triangle_point_from_uv(
|
||||
kg, sd, isect.hits[hit].prim, isect.hits[hit].u, isect.hits[hit].v);
|
||||
}
|
||||
# ifdef __OBJECT_MOTION__
|
||||
else if (sd->type == PRIMITIVE_MOTION_TRIANGLE) {
|
||||
float3 verts[3];
|
||||
motion_triangle_vertices(kg, sd->object, isect.hits[hit].prim, sd->time, verts);
|
||||
hit_P = motion_triangle_point_from_uv(kg,
|
||||
sd,
|
||||
isect.hits[hit].object,
|
||||
isect.hits[hit].prim,
|
||||
isect.hits[hit].u,
|
||||
isect.hits[hit].v,
|
||||
verts);
|
||||
hit_P = motion_triangle_point_from_uv(kg, sd, isect.hits[hit].u, isect.hits[hit].v, verts);
|
||||
}
|
||||
# endif /* __OBJECT_MOTION__ */
|
||||
|
||||
|
|
|
@ -1376,12 +1376,18 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
klights[light_index].tfm = light->tfm;
|
||||
klights[light_index].itfm = transform_inverse(light->tfm);
|
||||
|
||||
auto it = scene->lightgroups.find(light->lightgroup);
|
||||
if (it != scene->lightgroups.end()) {
|
||||
klights[light_index].lightgroup = it->second;
|
||||
/* Light group. */
|
||||
if (light->light_type == LIGHT_BACKGROUND) {
|
||||
klights[light_index].lightgroup = dscene->data.background.lightgroup;
|
||||
}
|
||||
else {
|
||||
klights[light_index].lightgroup = LIGHTGROUP_NONE;
|
||||
auto it = scene->lightgroups.find(light->lightgroup);
|
||||
if (it != scene->lightgroups.end()) {
|
||||
klights[light_index].lightgroup = it->second;
|
||||
}
|
||||
else {
|
||||
klights[light_index].lightgroup = LIGHTGROUP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
klights[light_index].light_set_membership = light->light_set_membership;
|
||||
|
|
|
@ -37,7 +37,6 @@ if(WITH_OPENSUBDIV)
|
|||
# Base.
|
||||
internal/base/memory.h
|
||||
internal/base/opensubdiv_capi.cc
|
||||
internal/base/type.h
|
||||
internal/base/type_convert.cc
|
||||
internal/base/type_convert.h
|
||||
internal/base/util.cc
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2013 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef OPENSUBDIV_BASE_TYPE_H_
|
||||
#define OPENSUBDIV_BASE_TYPE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::stack;
|
||||
using std::string;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
|
||||
using std::fill;
|
||||
using std::make_pair;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using std::move;
|
||||
using std::swap;
|
||||
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
||||
#endif // OPENSUBDIV_BASE_TYPE_H_
|
|
@ -7,22 +7,22 @@
|
|||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
void stringSplit(vector<string> *tokens,
|
||||
const string &str,
|
||||
const string &separators,
|
||||
void stringSplit(std::vector<std::string> *tokens,
|
||||
const std::string &str,
|
||||
const std::string &separators,
|
||||
bool skip_empty)
|
||||
{
|
||||
size_t token_start = 0, token_length = 0;
|
||||
for (size_t i = 0; i < str.length(); ++i) {
|
||||
const char ch = str[i];
|
||||
if (separators.find(ch) == string::npos) {
|
||||
if (separators.find(ch) == std::string::npos) {
|
||||
// Append non-separator char to a token.
|
||||
++token_length;
|
||||
}
|
||||
else {
|
||||
// Append current token to the list (if any).
|
||||
if (token_length > 0 || !skip_empty) {
|
||||
string token = str.substr(token_start, token_length);
|
||||
std::string token = str.substr(token_start, token_length);
|
||||
tokens->push_back(token);
|
||||
}
|
||||
// Re-set token pointers.
|
||||
|
@ -30,11 +30,11 @@ void stringSplit(vector<string> *tokens,
|
|||
token_length = 0;
|
||||
}
|
||||
}
|
||||
// Append token which might be at the end of the string.
|
||||
if ((token_length != 0) ||
|
||||
(!skip_empty && token_start > 0 && separators.find(str[token_start - 1]) != string::npos))
|
||||
// Append token which might be at the end of the std::string.
|
||||
if ((token_length != 0) || (!skip_empty && token_start > 0 &&
|
||||
separators.find(str[token_start - 1]) != std::string::npos))
|
||||
{
|
||||
string token = str.substr(token_start, token_length);
|
||||
std::string token = str.substr(token_start, token_length);
|
||||
tokens->push_back(token);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
#ifndef OPENSUBDIV_BASE_UTIL_H_
|
||||
#define OPENSUBDIV_BASE_UTIL_H_
|
||||
|
||||
#include "internal/base/type.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
void stringSplit(vector<string> *tokens,
|
||||
const string &str,
|
||||
const string &separators,
|
||||
void stringSplit(std::vector<std::string> *tokens,
|
||||
const std::string &str,
|
||||
const std::string &separators,
|
||||
bool skip_empty);
|
||||
|
||||
} // namespace opensubdiv
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <opensubdiv/osd/mesh.h>
|
||||
#include <opensubdiv/osd/types.h>
|
||||
|
||||
#include "internal/base/type.h"
|
||||
#include "internal/evaluator/evaluator_impl.h"
|
||||
|
||||
#include "opensubdiv_evaluator_capi.hh"
|
||||
|
@ -325,7 +324,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||
|
||||
VolatileEvalOutput(const StencilTable *vertex_stencils,
|
||||
const StencilTable *varying_stencils,
|
||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const std::vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const int face_varying_width,
|
||||
const PatchTable *patch_table,
|
||||
EvaluatorCache *evaluator_cache = NULL,
|
||||
|
@ -641,7 +640,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
|
|||
const STENCIL_TABLE *varying_stencils_;
|
||||
|
||||
int face_varying_width_;
|
||||
vector<FaceVaryingEval *> face_varying_evaluators_;
|
||||
std::vector<FaceVaryingEval *> face_varying_evaluators_;
|
||||
|
||||
EvaluatorCache *evaluator_cache_;
|
||||
DEVICE_CONTEXT *device_context_;
|
||||
|
|
|
@ -30,7 +30,7 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
|
|||
public:
|
||||
CpuEvalOutput(const StencilTable *vertex_stencils,
|
||||
const StencilTable *varying_stencils,
|
||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const std::vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const int face_varying_width,
|
||||
const PatchTable *patch_table,
|
||||
EvaluatorCache *evaluator_cache = NULL)
|
||||
|
|
|
@ -31,7 +31,7 @@ static void buildPatchArraysBufferFromVector(const PatchArrayVector &patch_array
|
|||
|
||||
GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils,
|
||||
const StencilTable *varying_stencils,
|
||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const std::vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const int face_varying_width,
|
||||
const PatchTable *patch_table,
|
||||
VolatileEvalOutput::EvaluatorCache *evaluator_cache)
|
||||
|
|
|
@ -26,7 +26,7 @@ class GpuEvalOutput : public VolatileEvalOutput<GLVertexBuffer,
|
|||
public:
|
||||
GpuEvalOutput(const StencilTable *vertex_stencils,
|
||||
const StencilTable *varying_stencils,
|
||||
const vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const std::vector<const StencilTable *> &all_face_varying_stencils,
|
||||
const int face_varying_width,
|
||||
const PatchTable *patch_table,
|
||||
EvaluatorCache *evaluator_cache = NULL);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "internal/base/type.h"
|
||||
#include "internal/evaluator/eval_output_cpu.h"
|
||||
#include "internal/evaluator/eval_output_gpu.h"
|
||||
#include "internal/evaluator/evaluator_cache_impl.h"
|
||||
|
@ -90,7 +89,8 @@ template<typename T, int kNumMaxElementsOnStack> class StackOrHeapArray {
|
|||
T *old_buffer = effective_elements_;
|
||||
effective_elements_ = allocate(num_elements);
|
||||
if (old_buffer != effective_elements_) {
|
||||
memcpy(effective_elements_, old_buffer, sizeof(T) * min(old_num_elements, num_elements));
|
||||
memcpy(
|
||||
effective_elements_, old_buffer, sizeof(T) * std::min(old_num_elements, num_elements));
|
||||
}
|
||||
if (old_buffer != stack_elements_) {
|
||||
delete[] old_buffer;
|
||||
|
@ -430,7 +430,6 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
|||
eOpenSubdivEvaluator evaluator_type,
|
||||
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr)
|
||||
{
|
||||
using blender::opensubdiv::vector;
|
||||
TopologyRefiner *refiner = topology_refiner->impl->topology_refiner;
|
||||
if (refiner == NULL) {
|
||||
// Happens on bad topology.
|
||||
|
@ -480,7 +479,7 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
|||
varying_stencils = StencilTableFactory::Create(*refiner, varying_stencil_options);
|
||||
}
|
||||
// Face warying stencil.
|
||||
vector<const StencilTable *> all_face_varying_stencils;
|
||||
std::vector<const StencilTable *> all_face_varying_stencils;
|
||||
all_face_varying_stencils.reserve(num_face_varying_channels);
|
||||
for (int face_varying_channel = 0; face_varying_channel < num_face_varying_channels;
|
||||
++face_varying_channel)
|
||||
|
|
|
@ -222,8 +222,8 @@ bool MeshTopology::isFaceVertexIndicesEqual(int face_index,
|
|||
sizeof(int) * num_expected_face_vertex_indices) == 0;
|
||||
}
|
||||
|
||||
bool MeshTopology::isFaceVertexIndicesEqual(int face_index,
|
||||
const vector<int> &expected_face_vertex_indices) const
|
||||
bool MeshTopology::isFaceVertexIndicesEqual(
|
||||
int face_index, const std::vector<int> &expected_face_vertex_indices) const
|
||||
{
|
||||
return isFaceVertexIndicesEqual(
|
||||
face_index, expected_face_vertex_indices.size(), expected_face_vertex_indices.data());
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
#ifndef OPENSUBDIV_MESH_TOPOLOGY_H_
|
||||
#define OPENSUBDIV_MESH_TOPOLOGY_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "internal/base/memory.h"
|
||||
#include "internal/base/type.h"
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
|
||||
|
@ -93,7 +92,7 @@ class MeshTopology {
|
|||
int num_expected_face_vertex_indices,
|
||||
const int *expected_face_vertex_indices) const;
|
||||
bool isFaceVertexIndicesEqual(int face_index,
|
||||
const vector<int> &expected_face_vertex_indices) const;
|
||||
const std::vector<int> &expected_face_vertex_indices) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Pipeline related.
|
||||
|
@ -142,21 +141,21 @@ class MeshTopology {
|
|||
};
|
||||
|
||||
int num_vertices_;
|
||||
vector<VertexTag> vertex_tags_;
|
||||
std::vector<VertexTag> vertex_tags_;
|
||||
|
||||
int num_edges_;
|
||||
vector<Edge> edges_;
|
||||
vector<EdgeTag> edge_tags_;
|
||||
std::vector<Edge> edges_;
|
||||
std::vector<EdgeTag> edge_tags_;
|
||||
|
||||
int num_faces_;
|
||||
|
||||
// Continuous array of all vertices of all faces:
|
||||
// [vertex indices of face 0][vertex indices of face 1] .. [vertex indices of face n].
|
||||
vector<int> face_vertex_indices_;
|
||||
std::vector<int> face_vertex_indices_;
|
||||
|
||||
// Indexed by face contains index within face_vertex_indices_ which corresponds
|
||||
// to the element which contains first vertex of the face.
|
||||
vector<int> faces_first_vertex_index_;
|
||||
std::vector<int> faces_first_vertex_index_;
|
||||
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("MeshTopology");
|
||||
};
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <opensubdiv/sdc/crease.h>
|
||||
|
||||
#include "internal/base/type.h"
|
||||
#include <vector>
|
||||
|
||||
#include "opensubdiv_converter_capi.hh"
|
||||
|
||||
|
@ -80,7 +79,7 @@ bool isEqualGeometryFace(const MeshTopology &mesh_topology, const OpenSubdiv_Con
|
|||
return false;
|
||||
}
|
||||
|
||||
vector<int> vertices_of_face;
|
||||
std::vector<int> vertices_of_face;
|
||||
for (int face_index = 0; face_index < num_requested_faces; ++face_index) {
|
||||
int num_face_vertices = converter->getNumFaceVertices(converter, face_index);
|
||||
if (mesh_topology.getNumFaceVertices(face_index) != num_face_vertices) {
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include "internal/base/type_convert.h"
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
|
||||
using blender::opensubdiv::vector;
|
||||
|
||||
namespace {
|
||||
|
||||
const OpenSubdiv::Far::TopologyRefiner *getOSDTopologyRefiner(
|
||||
|
|
|
@ -15,16 +15,11 @@
|
|||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
|
||||
#include "internal/base/type.h"
|
||||
#include "internal/base/type_convert.h"
|
||||
#include "internal/topology/mesh_topology.h"
|
||||
|
||||
#include "opensubdiv_converter_capi.hh"
|
||||
|
||||
using blender::opensubdiv::min;
|
||||
using blender::opensubdiv::stack;
|
||||
using blender::opensubdiv::vector;
|
||||
|
||||
struct TopologyRefinerData {
|
||||
const OpenSubdiv_Converter *converter;
|
||||
blender::opensubdiv::MeshTopology *base_mesh_topology;
|
||||
|
@ -138,7 +133,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology
|
|||
|
||||
// Vertex relations.
|
||||
const int num_vertices = converter->getNumVertices(converter);
|
||||
vector<int> vertex_faces, vertex_edges;
|
||||
std::vector<int> vertex_faces, vertex_edges;
|
||||
for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
|
||||
// Vertex-faces.
|
||||
IndexArray dst_vertex_faces = getBaseVertexFaces(refiner, vertex_index);
|
||||
|
@ -247,8 +242,8 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
|
|||
const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
|
||||
const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
|
||||
// TODO(sergey): Find a better mixing between edge and vertex sharpness.
|
||||
sharpness += min(sharpness0, sharpness1);
|
||||
sharpness = min(sharpness, 10.0f);
|
||||
sharpness += std::min(sharpness0, sharpness1);
|
||||
sharpness = std::min(sharpness, 10.0f);
|
||||
}
|
||||
|
||||
setBaseVertexSharpness(refiner, vertex_index, sharpness);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
|
||||
#include "internal/base/type.h"
|
||||
#include "internal/base/type_convert.h"
|
||||
#include "internal/topology/mesh_topology.h"
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2017-2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
@ -0,0 +1,573 @@
|
|||
# SPDX-FileCopyrightText: 2017-2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# TODO: file-type icons are currently not setup.
|
||||
# Currently `xdg-icon-resource` doesn't support SVG's, so we would need to generate PNG's.
|
||||
# Or wait until SVG's are supported, see: https://gitlab.freedesktop.org/xdg/xdg-utils/-/merge_requests/41
|
||||
#
|
||||
# NOTE: Typically this will run from Blender, you may also run this directly from Python
|
||||
# which can be useful for testing.
|
||||
|
||||
__all__ = (
|
||||
"register",
|
||||
"unregister",
|
||||
)
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from typing import (
|
||||
Callable,
|
||||
Optional,
|
||||
)
|
||||
|
||||
VERBOSE = True
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Environment
|
||||
|
||||
HOME_DIR = os.path.normpath(os.path.expanduser("~"))
|
||||
|
||||
# https://wiki.archlinux.org/title/XDG_Base_Directory
|
||||
# Typically: `~/.local/share`.
|
||||
XDG_DATA_HOME = os.environ.get("XDG_DATA_HOME") or os.path.join(HOME_DIR, ".local", "share")
|
||||
|
||||
HOMEDIR_LOCAL_BIN = os.path.join(HOME_DIR, ".local", "bin")
|
||||
|
||||
BLENDER_ENV = "bpy" in sys.modules
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Programs
|
||||
|
||||
# The command `xdg-mime` handles most of the file assosiation actions.
|
||||
XDG_MIME_PROG = shutil.which("xdg-mime") or ""
|
||||
|
||||
# Initialize by `bpy` or command line arguments.
|
||||
BLENDER_BIN = ""
|
||||
# Set to `os.path.dirname(BLENDER_BIN)`.
|
||||
BLENDER_DIR = ""
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Path Constants
|
||||
|
||||
# These files are included along side a portable Blender installation.
|
||||
BLENDER_DESKTOP = "blender.desktop"
|
||||
# The target binary.
|
||||
BLENDER_FILENAME = "blender"
|
||||
# The target binary (thumbnailer).
|
||||
BLENDER_THUMBNAILER_FILENAME = "blender-thumbnailer"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Other Constants
|
||||
|
||||
# The mime type Blender users.
|
||||
BLENDER_MIME = "application/x-blender"
|
||||
# Use `/usr/local` because this is not managed by the systems package manager.
|
||||
SYSTEM_PREFIX = "/usr/local"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Utility Functions
|
||||
|
||||
|
||||
# Display a short path, for nicer display only.
|
||||
def filepath_repr(filepath: str) -> str:
|
||||
if filepath.startswith(HOME_DIR):
|
||||
return "~" + filepath[len(HOME_DIR):]
|
||||
return filepath
|
||||
|
||||
|
||||
def system_path_contains(dirpath: str) -> bool:
|
||||
dirpath = os.path.normpath(dirpath)
|
||||
for path in os.environ.get("PATH", "").split(os.pathsep):
|
||||
# `$PATH` can include relative locations.
|
||||
path = os.path.normpath(os.path.abspath(path))
|
||||
if path == dirpath:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# When removing files to make way for newly copied file an `os.path.exists`
|
||||
# check isn't sufficient as the path may be a broken symbolic-link.
|
||||
def path_exists_or_is_link(path: str) -> bool:
|
||||
return os.path.exists(path) or os.path.islink(path)
|
||||
|
||||
|
||||
def filepath_ensure_removed(path: str) -> bool:
|
||||
if path_exists_or_is_link(path):
|
||||
os.remove(path)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Handle Associations
|
||||
#
|
||||
# On registration when handlers return False this causes registration to fail and unregister to be called.
|
||||
# Non fatal errors should print a message and return True instead.
|
||||
|
||||
def handle_bin(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
if all_users:
|
||||
dirpath_dst = os.path.join(SYSTEM_PREFIX, "bin")
|
||||
else:
|
||||
dirpath_dst = HOMEDIR_LOCAL_BIN
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("- {:s} symbolic-links in: {:s}\n".format(
|
||||
("Setup" if do_register else "Remove"),
|
||||
filepath_repr(dirpath_dst),
|
||||
))
|
||||
|
||||
if do_register:
|
||||
if not all_users:
|
||||
if not system_path_contains(dirpath_dst):
|
||||
sys.stdout.write(
|
||||
"The PATH environment variable doesn't contain \"{:s}\", not creating symlinks\n".format(
|
||||
dirpath_dst,
|
||||
))
|
||||
# NOTE: this is not an error, don't consider it a failure.
|
||||
return None
|
||||
|
||||
os.makedirs(dirpath_dst, exist_ok=True)
|
||||
|
||||
# Full path, then name to create at the destination.
|
||||
files_to_link = [
|
||||
(BLENDER_BIN, BLENDER_FILENAME, False),
|
||||
]
|
||||
|
||||
blender_thumbnailer_src = os.path.join(BLENDER_DIR, BLENDER_THUMBNAILER_FILENAME)
|
||||
if os.path.exists(blender_thumbnailer_src):
|
||||
# Unfortunately the thumbnailer must be copied for `bwrap` to find it.
|
||||
files_to_link.append((blender_thumbnailer_src, BLENDER_THUMBNAILER_FILENAME, True))
|
||||
else:
|
||||
sys.stdout.write(" Thumbnailer not found, skipping: \"{:s}\"\n".format(blender_thumbnailer_src))
|
||||
|
||||
for filepath_src, filename, do_full_copy in files_to_link:
|
||||
filepath_dst = os.path.join(dirpath_dst, filename)
|
||||
filepath_ensure_removed(filepath_dst)
|
||||
if not do_register:
|
||||
continue
|
||||
|
||||
if not os.path.exists(filepath_src):
|
||||
sys.stderr.write("File not found, skipping link: \"{:s}\" -> \"{:s}\"\n".format(
|
||||
filepath_src, filepath_dst,
|
||||
))
|
||||
if do_full_copy:
|
||||
shutil.copyfile(filepath_src, filepath_dst)
|
||||
os.chmod(filepath_dst, 0o755)
|
||||
else:
|
||||
os.symlink(filepath_src, filepath_dst)
|
||||
return None
|
||||
|
||||
|
||||
def handle_desktop_file(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
# `cp ./blender.desktop ~/.local/share/applications/`
|
||||
|
||||
filename = BLENDER_DESKTOP
|
||||
|
||||
if all_users:
|
||||
base_dir = os.path.join(SYSTEM_PREFIX, "share")
|
||||
else:
|
||||
base_dir = XDG_DATA_HOME
|
||||
|
||||
dirpath_dst = os.path.join(base_dir, "applications")
|
||||
|
||||
filepath_desktop_src = os.path.join(BLENDER_DIR, filename)
|
||||
filepath_desktop_dst = os.path.join(dirpath_dst, filename)
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("- {:s} desktop-file: {:s}\n".format(
|
||||
("Setup" if do_register else "Remove"),
|
||||
filepath_repr(filepath_desktop_dst),
|
||||
))
|
||||
|
||||
filepath_ensure_removed(filepath_desktop_dst)
|
||||
if not do_register:
|
||||
return None
|
||||
|
||||
if not os.path.exists(filepath_desktop_src):
|
||||
# Unlike other missing things, this must be an error otherwise
|
||||
# the MIME association fails which is the main purpose of registering types.
|
||||
return "Error: desktop file not found: {:s}".format(filepath_desktop_src)
|
||||
|
||||
os.makedirs(dirpath_dst, exist_ok=True)
|
||||
|
||||
with open(filepath_desktop_src, "r", encoding="utf-8") as fh:
|
||||
data = fh.read()
|
||||
|
||||
data = data.replace("\nExec=blender %f\n", "\nExec={:s} %f\n".format(BLENDER_BIN))
|
||||
|
||||
with open(filepath_desktop_dst, "w", encoding="utf-8") as fh:
|
||||
fh.write(data)
|
||||
return None
|
||||
|
||||
|
||||
def handle_thumbnailer(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
filename = "blender.thumbnailer"
|
||||
|
||||
if all_users:
|
||||
base_dir = os.path.join(SYSTEM_PREFIX, "share")
|
||||
else:
|
||||
base_dir = XDG_DATA_HOME
|
||||
|
||||
dirpath_dst = os.path.join(base_dir, "thumbnailers")
|
||||
filepath_thumbnailer_dst = os.path.join(dirpath_dst, filename)
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("- {:s} thumbnailer: {:s}\n".format(
|
||||
("Setup" if do_register else "Remove"),
|
||||
filepath_repr(filepath_thumbnailer_dst),
|
||||
))
|
||||
|
||||
filepath_ensure_removed(filepath_thumbnailer_dst)
|
||||
if not do_register:
|
||||
return None
|
||||
|
||||
blender_thumbnailer_bin = os.path.join(BLENDER_DIR, BLENDER_THUMBNAILER_FILENAME)
|
||||
if not os.path.exists(blender_thumbnailer_bin):
|
||||
sys.stderr.write("Thumbnailer not found, this may not be a portable installation: {:s}\n".format(
|
||||
blender_thumbnailer_bin,
|
||||
))
|
||||
return None
|
||||
|
||||
os.makedirs(dirpath_dst, exist_ok=True)
|
||||
|
||||
# NOTE: unfortunately this can't be `blender_thumbnailer_bin` because GNOME calls the command
|
||||
# with wrapper that means the command *must* be in the users `$PATH`.
|
||||
# and it cannot be a SYMLINK.
|
||||
if shutil.which("bwrap") is not None:
|
||||
command = BLENDER_THUMBNAILER_FILENAME
|
||||
else:
|
||||
command = blender_thumbnailer_bin
|
||||
|
||||
with open(filepath_thumbnailer_dst, "w", encoding="utf-8") as fh:
|
||||
fh.write("[Thumbnailer Entry]\n")
|
||||
fh.write("TryExec={:s}\n".format(command))
|
||||
fh.write("Exec={:s} %i %o\n".format(command))
|
||||
fh.write("MimeType={:s};\n".format(BLENDER_MIME))
|
||||
return None
|
||||
|
||||
|
||||
def handle_mime_association_xml(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
# `xdg-mime install x-blender.xml`
|
||||
filename = "x-blender.xml"
|
||||
|
||||
if all_users:
|
||||
base_dir = os.path.join(SYSTEM_PREFIX, "share")
|
||||
else:
|
||||
base_dir = XDG_DATA_HOME
|
||||
|
||||
# Ensure directories exist `xdg-mime` will fail with an error if these don't exist.
|
||||
for dirpath_dst in (
|
||||
os.path.join(base_dir, "mime", "application"),
|
||||
os.path.join(base_dir, "mime", "packages")
|
||||
):
|
||||
os.makedirs(dirpath_dst, exist_ok=True)
|
||||
del dirpath_dst
|
||||
|
||||
# Unfortunately there doesn't seem to be a way to know the installed location.
|
||||
# Use hard-coded location.
|
||||
package_xml_dst = os.path.join(base_dir, "mime", "application", filename)
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("- {:s} mime type: {:s}\n".format(
|
||||
("Setup" if do_register else "Remove"),
|
||||
filepath_repr(package_xml_dst),
|
||||
))
|
||||
|
||||
env = {
|
||||
**os.environ,
|
||||
"XDG_DATA_DIRS": os.path.join(SYSTEM_PREFIX, "share")
|
||||
}
|
||||
|
||||
if not do_register:
|
||||
if not os.path.exists(package_xml_dst):
|
||||
return None
|
||||
# NOTE: `xdg-mime query default application/x-blender` could be used to check
|
||||
# if the XML is installed, however there is some slim chance the XML is installed
|
||||
# but the default doesn't point to Blender, just uninstall as it's harmless.
|
||||
cmd = (
|
||||
XDG_MIME_PROG,
|
||||
"uninstall",
|
||||
"--mode", "system" if all_users else "user",
|
||||
package_xml_dst,
|
||||
)
|
||||
subprocess.check_output(cmd, env=env)
|
||||
return None
|
||||
|
||||
with tempfile.TemporaryDirectory() as tempdir:
|
||||
package_xml_src = os.path.join(tempdir, filename)
|
||||
with open(package_xml_src, mode="w", encoding="utf-8") as fh:
|
||||
fh.write("""<?xml version="1.0" encoding="UTF-8"?>\n""")
|
||||
fh.write("""<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">\n""")
|
||||
fh.write(""" <mime-type type="{:s}">\n""".format(BLENDER_MIME))
|
||||
# NOTE: not using a trailing full-stop seems to be the convention here.
|
||||
fh.write(""" <comment>Blender scene</comment>\n""")
|
||||
fh.write(""" <glob pattern="*.blend"/>\n""")
|
||||
# TODO: this doesn't seem to work, GNOME's Nautilus & KDE's Dolphin
|
||||
# already have a file-type icon for this so we might consider this low priority.
|
||||
if False:
|
||||
fh.write(""" <icon name="application-x-blender"/>\n""")
|
||||
fh.write(""" </mime-type>\n""")
|
||||
fh.write("""</mime-info>\n""")
|
||||
|
||||
cmd = (
|
||||
XDG_MIME_PROG,
|
||||
"install",
|
||||
"--mode", "system" if all_users else "user",
|
||||
package_xml_src,
|
||||
)
|
||||
subprocess.check_output(cmd, env=env)
|
||||
return None
|
||||
|
||||
|
||||
def handle_mime_association_default(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
# `xdg-mime default blender.desktop application/x-blender`
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("- {:s} mime type as default\n".format(
|
||||
("Setup" if do_register else "Remove"),
|
||||
))
|
||||
|
||||
# NOTE: there doesn't seem to be a way to reverse this action.
|
||||
if not do_register:
|
||||
return None
|
||||
|
||||
cmd = (
|
||||
XDG_MIME_PROG,
|
||||
"default",
|
||||
BLENDER_DESKTOP,
|
||||
BLENDER_MIME,
|
||||
)
|
||||
subprocess.check_output(cmd)
|
||||
return None
|
||||
|
||||
|
||||
def handle_icon(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
filename = "blender.svg"
|
||||
if all_users:
|
||||
base_dir = os.path.join(SYSTEM_PREFIX, "share")
|
||||
else:
|
||||
base_dir = XDG_DATA_HOME
|
||||
|
||||
dirpath_dst = os.path.join(base_dir, "icons", "hicolor", "scalable", "apps")
|
||||
|
||||
filepath_desktop_src = os.path.join(BLENDER_DIR, filename)
|
||||
filepath_desktop_dst = os.path.join(dirpath_dst, filename)
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("- {:s} icon: {:s}\n".format(
|
||||
("Setup" if do_register else "Remove"),
|
||||
filepath_repr(filepath_desktop_dst),
|
||||
))
|
||||
|
||||
filepath_ensure_removed(filepath_desktop_dst)
|
||||
if not do_register:
|
||||
return None
|
||||
|
||||
if not os.path.exists(filepath_desktop_src):
|
||||
sys.stderr.write(" Icon file not found, skipping: \"{:s}\"\n".format(filepath_desktop_src))
|
||||
# Not an error.
|
||||
return None
|
||||
|
||||
os.makedirs(dirpath_dst, exist_ok=True)
|
||||
|
||||
with open(filepath_desktop_src, "rb") as fh:
|
||||
data = fh.read()
|
||||
|
||||
with open(filepath_desktop_dst, "wb") as fh:
|
||||
fh.write(data)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Escalate Privileges
|
||||
|
||||
def main_run_as_root(do_register: bool) -> Optional[str]:
|
||||
# If the system prefix doesn't exist, fail with an error because it's highly likely that the
|
||||
# system won't use this when it has not been created.
|
||||
if not os.path.exists(SYSTEM_PREFIX):
|
||||
return "Error: system path does not exist {!r}".format(SYSTEM_PREFIX)
|
||||
|
||||
prog: Optional[str] = shutil.which("pkexec")
|
||||
if prog is None:
|
||||
return "Error: command \"pkexec\" not found"
|
||||
|
||||
cmd = [
|
||||
prog,
|
||||
sys.executable,
|
||||
# Skips users `site-packages`.
|
||||
"-s",
|
||||
__file__,
|
||||
BLENDER_BIN,
|
||||
"--action={:s}".format("register-allusers" if do_register else "unregister-allusers"),
|
||||
]
|
||||
if VERBOSE:
|
||||
sys.stdout.write("Executing: {:s}\n".format(shlex.join(cmd)))
|
||||
|
||||
proc = subprocess.run(cmd, stderr=subprocess.PIPE)
|
||||
if proc.returncode != 0:
|
||||
if proc.stderr:
|
||||
return proc.stderr.decode("utf-8", errors="surrogateescape")
|
||||
return "Error: pkexec returned non-zero returncode"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Checked Call
|
||||
#
|
||||
# While exceptions should not happen, we can't entirely prevent this as it's always possible
|
||||
# a file write fails or a command doesn't work as expected anymore.
|
||||
# Handle these cases gracefully.
|
||||
|
||||
def call_handle_checked(
|
||||
fn: Callable[[bool, bool], Optional[str]],
|
||||
*,
|
||||
do_register: bool,
|
||||
all_users: bool
|
||||
) -> Optional[str]:
|
||||
try:
|
||||
result = fn(do_register, all_users)
|
||||
except BaseException as ex:
|
||||
# This should never happen.
|
||||
result = "Internal Error: {!r}".format(ex)
|
||||
return result
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Main Registration Functions
|
||||
|
||||
def register_impl(do_register: bool, all_users: bool) -> Optional[str]:
|
||||
# A non-empty string indicates an error (which is forwarded to the user), otherwise None for success.
|
||||
|
||||
global BLENDER_BIN
|
||||
global BLENDER_DIR
|
||||
|
||||
if BLENDER_ENV:
|
||||
# Only use of `bpy`.
|
||||
BLENDER_BIN = os.path.normpath(__import__("bpy").app.binary_path)
|
||||
|
||||
# Running inside Blender, detect the need for privilege escalation (which will run outside of Blender).
|
||||
if all_users:
|
||||
if os.geteuid() != 0:
|
||||
# Run this script with escalated privileges.
|
||||
return main_run_as_root(do_register)
|
||||
else:
|
||||
assert BLENDER_BIN != ""
|
||||
|
||||
BLENDER_DIR = os.path.dirname(BLENDER_BIN)
|
||||
|
||||
if all_users:
|
||||
if not os.access(SYSTEM_PREFIX, os.W_OK):
|
||||
return "Error: {:s} not writable, this command may need to run as a superuser!".format(SYSTEM_PREFIX)
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write("{:s}: {:s}\n".format("Register" if do_register else "Unregister", BLENDER_BIN))
|
||||
|
||||
if XDG_MIME_PROG == "":
|
||||
return "Could not find \"xdg-mime\", unable to associate mime-types"
|
||||
|
||||
handlers = (
|
||||
handle_bin,
|
||||
handle_icon,
|
||||
handle_desktop_file,
|
||||
handle_mime_association_xml,
|
||||
# This only makes sense for users, although there may be a way to do this for all users.
|
||||
*(() if all_users else (handle_mime_association_default,)),
|
||||
# The thumbnailer only works when installed for all users.
|
||||
*((handle_thumbnailer,) if all_users else ()),
|
||||
)
|
||||
|
||||
error_or_none = None
|
||||
for i, fn in enumerate(handlers):
|
||||
if (error_or_none := call_handle_checked(fn, do_register=do_register, all_users=all_users)) is not None:
|
||||
break
|
||||
|
||||
if error_or_none is not None:
|
||||
# Roll back registration on failure.
|
||||
if do_register:
|
||||
for fn in reversed(handlers[:i + 1]):
|
||||
error_or_none_reverse = call_handle_checked(fn, do_register=False, all_users=all_users)
|
||||
if error_or_none_reverse is not None:
|
||||
sys.stdout.write("Error reverting action: {:s}\n".format(error_or_none_reverse))
|
||||
|
||||
# Print to the `stderr`, in case the user has a console open, it can be helpful
|
||||
# especially if it's multi-line.
|
||||
sys.stdout.write("{:s}\n".format(error_or_none))
|
||||
|
||||
return error_or_none
|
||||
|
||||
|
||||
def register(all_users: bool = False) -> Optional[str]:
|
||||
# Return an empty string for success.
|
||||
return register_impl(True, all_users)
|
||||
|
||||
|
||||
def unregister(all_users: bool = False) -> Optional[str]:
|
||||
# Return an empty string for success.
|
||||
return register_impl(False, all_users)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Running directly (Escalated Privileges)
|
||||
#
|
||||
# Needed when running as an administer.
|
||||
|
||||
register_actions = {
|
||||
"register": (True, False),
|
||||
"unregister": (False, False),
|
||||
"register-allusers": (True, True),
|
||||
"unregister-allusers": (False, True),
|
||||
}
|
||||
|
||||
|
||||
def argparse_create() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"blender_bin",
|
||||
metavar="BLENDER_BIN",
|
||||
type=str,
|
||||
help="The location of Blender's binary",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--action",
|
||||
choices=register_actions.keys(),
|
||||
dest="register_action",
|
||||
required=True,
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def main() -> int:
|
||||
global BLENDER_BIN
|
||||
assert BLENDER_BIN == ""
|
||||
args = argparse_create().parse_args()
|
||||
BLENDER_BIN = args.blender_bin
|
||||
do_register, all_users = register_actions[args.register_action]
|
||||
|
||||
if do_register:
|
||||
result = register(all_users=all_users)
|
||||
else:
|
||||
result = unregister(all_users=all_users)
|
||||
|
||||
if result:
|
||||
sys.stderr.write("{:s}\n".format(result))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
|
@ -667,15 +667,22 @@ class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, _context):
|
||||
# Only for Windows so far
|
||||
import sys
|
||||
return sys.platform[:3] == "win"
|
||||
# macOS isn't supported.
|
||||
from sys import platform
|
||||
if platform == "darwin":
|
||||
return False
|
||||
return True
|
||||
|
||||
def draw_centered(self, context, layout):
|
||||
if context.preferences.system.is_microsoft_store_install:
|
||||
layout.label(text="Microsoft Store installation")
|
||||
layout.label(text="Use Windows 'Default Apps' to associate with blend files")
|
||||
else:
|
||||
from sys import platform
|
||||
associate_supported = True
|
||||
if platform[:3] == "win":
|
||||
if context.preferences.system.is_microsoft_store_install:
|
||||
layout.label(text="Microsoft Store installation")
|
||||
layout.label(text="Use Windows 'Default Apps' to associate with blend files")
|
||||
associate_supported = False
|
||||
|
||||
if associate_supported:
|
||||
layout.label(text="Open blend files with this Blender version")
|
||||
split = layout.split(factor=0.5)
|
||||
split.alignment = 'LEFT'
|
||||
|
|
|
@ -58,11 +58,6 @@ struct BMEditMesh {
|
|||
/** Temp variables for x-mirror editing (-1 when the layer does not exist). */
|
||||
int mirror_cdlayer;
|
||||
|
||||
/**
|
||||
* Enable for evaluated copies, causes the edit-mesh to free the memory, not its contents.
|
||||
*/
|
||||
char is_shallow_copy;
|
||||
|
||||
/**
|
||||
* ID data is older than edit-mode data.
|
||||
* Set #Main.is_memfile_undo_flush_needed when enabling.
|
||||
|
|
|
@ -123,8 +123,6 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
|||
int corners_num,
|
||||
CustomData_MeshMasks mask);
|
||||
|
||||
void BKE_mesh_eval_delete(Mesh *mesh_eval);
|
||||
|
||||
/**
|
||||
* Performs copy for use during evaluation,
|
||||
* optional referencing original arrays to reduce memory.
|
||||
|
|
|
@ -111,11 +111,16 @@ struct MeshRuntime {
|
|||
const ImplicitSharingInfo *face_offsets_sharing_info = nullptr;
|
||||
|
||||
/**
|
||||
* Storage of the edit mode mesh. If it exists, it generally has the most up-to-date
|
||||
* information about the mesh.
|
||||
* Storage of the edit mode BMesh with some extra data for quick access in edit mode.
|
||||
* - For original (non-evaluated) meshes, when it exists, it generally has the most up-to-date
|
||||
* information about the mesh. That's because this is only allocated in edit mode.
|
||||
* - For evaluated meshes, this just references the BMesh from an original object in edit mode.
|
||||
* Conceptually this is a weak pointer for evaluated meshes. In other words, it doesn't have
|
||||
* ownership over the BMesh, and using `shared_ptr` is just a convenient way to avoid copying
|
||||
* the whole struct and making sure the reference is valid.
|
||||
* \note When the object is available, the preferred access method is #BKE_editmesh_from_object.
|
||||
*/
|
||||
BMEditMesh *edit_mesh = nullptr;
|
||||
std::shared_ptr<BMEditMesh> edit_mesh;
|
||||
|
||||
/**
|
||||
* A cache of bounds shared between data-blocks with unchanged positions. When changing positions
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
|
@ -14,7 +16,7 @@ struct BMEditMesh;
|
|||
struct CustomData_MeshMasks;
|
||||
struct Mesh;
|
||||
|
||||
Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
|
||||
Mesh *BKE_mesh_wrapper_from_editmesh(std::shared_ptr<BMEditMesh> em,
|
||||
const CustomData_MeshMasks *cd_mask_extra,
|
||||
const Mesh *me_settings);
|
||||
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh);
|
||||
|
|
|
@ -1009,7 +1009,6 @@ static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
|
|||
static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
BMEditMesh *em_input,
|
||||
const CustomData_MeshMasks *dataMask,
|
||||
/* return args */
|
||||
Mesh **r_cage,
|
||||
|
@ -1017,6 +1016,8 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
|
|||
GeometrySet **r_geometry_set)
|
||||
{
|
||||
Mesh *mesh_input = (Mesh *)ob->data;
|
||||
BMEditMesh *em_input = mesh_input->runtime->edit_mesh.get();
|
||||
|
||||
Mesh *mesh_cage = nullptr;
|
||||
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
|
||||
GeometrySet geometry_set_final;
|
||||
|
@ -1049,7 +1050,8 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
|
|||
CDMaskLink *md_datamask = datamasks;
|
||||
CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
|
||||
|
||||
Mesh *mesh_final = BKE_mesh_wrapper_from_editmesh(em_input, &final_datamask, mesh_input);
|
||||
Mesh *mesh_final = BKE_mesh_wrapper_from_editmesh(
|
||||
mesh_input->runtime->edit_mesh, &final_datamask, mesh_input);
|
||||
|
||||
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true);
|
||||
if (r_cage && cageIndex == -1) {
|
||||
|
@ -1094,9 +1096,7 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
|
|||
* cage mesh isn't modified anymore. */
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
|
||||
if (mesh_cage->runtime->edit_mesh) {
|
||||
mesh_final->runtime->edit_mesh = static_cast<BMEditMesh *>(
|
||||
MEM_dupallocN(mesh_cage->runtime->edit_mesh));
|
||||
mesh_final->runtime->edit_mesh->is_shallow_copy = true;
|
||||
mesh_final->runtime->edit_mesh = mesh_cage->runtime->edit_mesh;
|
||||
mesh_final->runtime->is_original_bmesh = true;
|
||||
if (mesh_cage->runtime->edit_data) {
|
||||
mesh_final->runtime->edit_data = std::make_unique<blender::bke::EditMeshData>(
|
||||
|
@ -1288,7 +1288,6 @@ static void mesh_build_data(Depsgraph *depsgraph,
|
|||
static void editbmesh_build_data(Depsgraph *depsgraph,
|
||||
const Scene *scene,
|
||||
Object *obedit,
|
||||
BMEditMesh *em,
|
||||
CustomData_MeshMasks *dataMask)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(obedit->data);
|
||||
|
@ -1297,13 +1296,13 @@ static void editbmesh_build_data(Depsgraph *depsgraph,
|
|||
GeometrySet *non_mesh_components;
|
||||
|
||||
editbmesh_calc_modifiers(
|
||||
depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final, &non_mesh_components);
|
||||
depsgraph, scene, obedit, dataMask, &me_cage, &me_final, &non_mesh_components);
|
||||
|
||||
/* The modifier stack result is expected to share edit mesh pointer with the input.
|
||||
* This is similar `mesh_calc_finalize()`. */
|
||||
BKE_mesh_free_editmesh(me_final);
|
||||
BKE_mesh_free_editmesh(me_cage);
|
||||
me_final->runtime->edit_mesh = me_cage->runtime->edit_mesh = em;
|
||||
me_final->runtime->edit_mesh = me_cage->runtime->edit_mesh = mesh->runtime->edit_mesh;
|
||||
|
||||
/* Object has edit_mesh but is not in edit mode (object shares mesh datablock with another object
|
||||
* with is in edit mode).
|
||||
|
@ -1407,14 +1406,13 @@ void makeDerivedMesh(Depsgraph *depsgraph,
|
|||
* `edit_mesh` pointer with the input. For example, if the object is first evaluated in the
|
||||
* object mode, and then user in another scene moves object to edit mode. */
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
|
||||
bool need_mapping;
|
||||
CustomData_MeshMasks cddata_masks = *dataMask;
|
||||
object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
|
||||
|
||||
if (em) {
|
||||
editbmesh_build_data(depsgraph, scene, ob, em, &cddata_masks);
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
editbmesh_build_data(depsgraph, scene, ob, &cddata_masks);
|
||||
}
|
||||
else {
|
||||
mesh_build_data(depsgraph, scene, ob, &cddata_masks, need_mapping);
|
||||
|
@ -1428,7 +1426,7 @@ Mesh *mesh_get_eval_deform(Depsgraph *depsgraph,
|
|||
Object *ob,
|
||||
const CustomData_MeshMasks *dataMask)
|
||||
{
|
||||
BMEditMesh *em = ((Mesh *)ob->data)->runtime->edit_mesh;
|
||||
BMEditMesh *em = ((Mesh *)ob->data)->runtime->edit_mesh.get();
|
||||
if (em != nullptr) {
|
||||
/* There is no such a concept as deformed mesh in edit mode.
|
||||
* Explicitly disallow this request so that the evaluated result is not modified with evaluated
|
||||
|
@ -1502,7 +1500,7 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
|
|||
Mesh *editbmesh_get_eval_cage(Depsgraph *depsgraph,
|
||||
const Scene *scene,
|
||||
Object *obedit,
|
||||
BMEditMesh *em,
|
||||
BMEditMesh * /*em*/,
|
||||
const CustomData_MeshMasks *dataMask)
|
||||
{
|
||||
CustomData_MeshMasks cddata_masks = *dataMask;
|
||||
|
@ -1515,7 +1513,7 @@ Mesh *editbmesh_get_eval_cage(Depsgraph *depsgraph,
|
|||
if (!obedit->runtime->editmesh_eval_cage ||
|
||||
!CustomData_MeshMasks_are_matching(&(obedit->runtime->last_data_mask), &cddata_masks))
|
||||
{
|
||||
editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks);
|
||||
editbmesh_build_data(depsgraph, scene, obedit, &cddata_masks);
|
||||
}
|
||||
|
||||
return obedit->runtime->editmesh_eval_cage;
|
||||
|
|
|
@ -58,8 +58,7 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
|
|||
}
|
||||
case ID_ME: {
|
||||
Mesh *mesh = (Mesh *)id;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
if (em != nullptr) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMesh *bm = em->bm;
|
||||
info[int(AttrDomain::Point)].customdata = &bm->vdata;
|
||||
info[int(AttrDomain::Point)].length = bm->totvert;
|
||||
|
@ -326,7 +325,7 @@ CustomDataLayer *BKE_id_attribute_new(ID *id,
|
|||
|
||||
if (GS(id->name) == ID_ME) {
|
||||
Mesh *mesh = reinterpret_cast<Mesh *>(id);
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
if (!mesh_edit_mode_attribute_valid(name, domain, type, reports)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -376,9 +375,8 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList
|
|||
|
||||
if (GS(id->name) == ID_ME) {
|
||||
Mesh *mesh = reinterpret_cast<Mesh *>(id);
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
BLI_assert_unreachable();
|
||||
UNUSED_VARS(em);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -457,7 +455,7 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
|||
|
||||
if (GS(id->name) == ID_ME) {
|
||||
Mesh *mesh = reinterpret_cast<Mesh *>(id);
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
|
||||
if (CustomData *data = info[domain].customdata) {
|
||||
const std::string name_copy = name;
|
||||
|
|
|
@ -273,7 +273,8 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(
|
|||
cd_mask_extra = datamasks->mask;
|
||||
BLI_linklist_free((LinkNode *)datamasks, nullptr);
|
||||
|
||||
mesh = BKE_mesh_wrapper_from_editmesh(em, &cd_mask_extra, me_input);
|
||||
mesh = BKE_mesh_wrapper_from_editmesh(
|
||||
std::make_shared<BMEditMesh>(*em), &cd_mask_extra, me_input);
|
||||
deformcos.reinitialize(verts_num);
|
||||
BKE_mesh_wrapper_vert_coords_copy(mesh, deformcos);
|
||||
deformmats.reinitialize(verts_num);
|
||||
|
|
|
@ -63,7 +63,7 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em)
|
|||
BMEditMesh *BKE_editmesh_from_object(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
return ((Mesh *)ob->data)->runtime->edit_mesh;
|
||||
return ((Mesh *)ob->data)->runtime->edit_mesh.get();
|
||||
}
|
||||
|
||||
void BKE_editmesh_looptris_calc_ex(BMEditMesh *em, const BMeshCalcTessellation_Params *params)
|
||||
|
|
|
@ -1285,7 +1285,7 @@ static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cac
|
|||
totvert = mesh->verts_num;
|
||||
|
||||
if (mesh->runtime->edit_mesh && mesh->runtime->edit_mesh->bm->totvert == totvert) {
|
||||
em = mesh->runtime->edit_mesh;
|
||||
em = mesh->runtime->edit_mesh.get();
|
||||
}
|
||||
}
|
||||
else if (ob->type == OB_LATTICE) {
|
||||
|
|
|
@ -219,7 +219,7 @@ bool BKE_view_layer_filter_edit_mesh_has_uvs(const Object *ob, void * /*user_dat
|
|||
{
|
||||
if (ob->type == OB_MESH) {
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
|
||||
if (const BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (const BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
if (CustomData_has_layer(&em->bm->ldata, CD_PROP_FLOAT2)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ bool BKE_view_layer_filter_edit_mesh_has_edges(const Object *ob, void * /*user_d
|
|||
{
|
||||
if (ob->type == OB_MESH) {
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
|
||||
if (const BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (const BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
if (em->bm->totedge != 0) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -204,15 +204,7 @@ static void mesh_copy_data(Main *bmain,
|
|||
|
||||
void BKE_mesh_free_editmesh(Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime->edit_mesh == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mesh->runtime->edit_mesh->is_shallow_copy == false) {
|
||||
BKE_editmesh_free_data(mesh->runtime->edit_mesh);
|
||||
}
|
||||
MEM_freeN(mesh->runtime->edit_mesh);
|
||||
mesh->runtime->edit_mesh = nullptr;
|
||||
mesh->runtime->edit_mesh.reset();
|
||||
}
|
||||
|
||||
static void mesh_free_data(ID *id)
|
||||
|
@ -848,15 +840,6 @@ Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src,
|
|||
me_src, verts_num, edges_num, 0, faces_num, corners_num, CD_MASK_EVERYTHING);
|
||||
}
|
||||
|
||||
void BKE_mesh_eval_delete(Mesh *mesh_eval)
|
||||
{
|
||||
/* Evaluated mesh may point to edit mesh, but never owns it. */
|
||||
mesh_eval->runtime->edit_mesh = nullptr;
|
||||
mesh_free_data(&mesh_eval->id);
|
||||
BKE_libblock_free_data(&mesh_eval->id, false);
|
||||
MEM_freeN(mesh_eval);
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_copy_for_eval(const Mesh *source)
|
||||
{
|
||||
return reinterpret_cast<Mesh *>(
|
||||
|
@ -1155,8 +1138,7 @@ void BKE_mesh_material_remap(Mesh *mesh, const uint *remap, uint remap_len)
|
|||
} \
|
||||
((void)0)
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMIter iter;
|
||||
BMFace *efa;
|
||||
|
||||
|
@ -1462,7 +1444,6 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
|
|||
* evaluated mesh, and we don't know what parts of the mesh did change. So we simply delete the
|
||||
* evaluated mesh and let objects to re-create it with updated settings. */
|
||||
if (mesh->runtime->mesh_eval != nullptr) {
|
||||
mesh->runtime->mesh_eval->runtime->edit_mesh = nullptr;
|
||||
BKE_id_free(nullptr, mesh->runtime->mesh_eval);
|
||||
mesh->runtime->mesh_eval = nullptr;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ void BKE_mesh_foreach_mapped_vert(
|
|||
MeshForeachFlag flag)
|
||||
{
|
||||
if (mesh->runtime->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
|
@ -94,7 +94,7 @@ void BKE_mesh_foreach_mapped_edge(
|
|||
void *user_data)
|
||||
{
|
||||
if (mesh->runtime->edit_mesh != nullptr && mesh->runtime->edit_data) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMEdge *eed;
|
||||
|
@ -153,7 +153,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
|||
* we want to always access `dm->loopData`, `EditDerivedBMesh` would
|
||||
* return loop data from BMesh itself. */
|
||||
if (mesh->runtime->edit_mesh != nullptr && mesh->runtime->edit_data) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMFace *efa;
|
||||
|
@ -233,7 +233,7 @@ void BKE_mesh_foreach_mapped_face_center(
|
|||
{
|
||||
using namespace blender;
|
||||
if (mesh->runtime->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMesh *bm = em->bm;
|
||||
BMFace *efa;
|
||||
BMIter iter;
|
||||
|
|
|
@ -36,7 +36,6 @@ namespace blender::bke {
|
|||
static void free_mesh_eval(MeshRuntime &mesh_runtime)
|
||||
{
|
||||
if (mesh_runtime.mesh_eval != nullptr) {
|
||||
mesh_runtime.mesh_eval->runtime->edit_mesh = nullptr;
|
||||
BKE_id_free(nullptr, mesh_runtime.mesh_eval);
|
||||
mesh_runtime.mesh_eval = nullptr;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
using blender::float3;
|
||||
using blender::Span;
|
||||
|
||||
Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
|
||||
Mesh *BKE_mesh_wrapper_from_editmesh(std::shared_ptr<BMEditMesh> em,
|
||||
const CustomData_MeshMasks *cd_mask_extra,
|
||||
const Mesh *me_settings)
|
||||
{
|
||||
|
@ -68,8 +68,7 @@ Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
|
|||
/* Use edit-mesh directly where possible. */
|
||||
mesh->runtime->is_original_bmesh = true;
|
||||
|
||||
mesh->runtime->edit_mesh = static_cast<BMEditMesh *>(MEM_dupallocN(em));
|
||||
mesh->runtime->edit_mesh->is_shallow_copy = true;
|
||||
mesh->runtime->edit_mesh = std::move(em);
|
||||
|
||||
/* Make sure we crash if these are ever used. */
|
||||
#ifndef NDEBUG
|
||||
|
@ -110,7 +109,7 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
|
|||
BLI_assert(mesh->runtime->edit_mesh != nullptr);
|
||||
BLI_assert(mesh->runtime->edit_data != nullptr);
|
||||
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BM_mesh_bm_to_me_for_eval(*em->bm, *mesh, &mesh->runtime->cd_mask_extra);
|
||||
|
||||
/* Adding original index layers here assumes that all BMesh Mesh wrappers are created from
|
||||
|
|
|
@ -63,7 +63,7 @@ static void multiresModifier_disp_run(
|
|||
|
||||
void multires_customdata_delete(Mesh *mesh)
|
||||
{
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
/* CustomData_external_remove is used here only to mark layer
|
||||
* as non-external for further freeing, so zero element count
|
||||
* looks safer than `em->bm->totface`. */
|
||||
|
@ -512,7 +512,7 @@ void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *o
|
|||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
const MDisps *mdisp;
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
mdisp = static_cast<const MDisps *>(CustomData_get_layer(&em->bm->ldata, CD_MDISPS));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1639,7 +1639,7 @@ void BKE_object_free_derived_caches(Object *ob)
|
|||
if (ob->runtime->editmesh_eval_cage &&
|
||||
ob->runtime->editmesh_eval_cage != reinterpret_cast<Mesh *>(ob->runtime->data_eval))
|
||||
{
|
||||
BKE_mesh_eval_delete(ob->runtime->editmesh_eval_cage);
|
||||
BKE_id_free(nullptr, ob->runtime->editmesh_eval_cage);
|
||||
}
|
||||
ob->runtime->editmesh_eval_cage = nullptr;
|
||||
|
||||
|
@ -1647,7 +1647,7 @@ void BKE_object_free_derived_caches(Object *ob)
|
|||
if (ob->runtime->is_data_eval_owned) {
|
||||
ID *data_eval = ob->runtime->data_eval;
|
||||
if (GS(data_eval->name) == ID_ME) {
|
||||
BKE_mesh_eval_delete((Mesh *)data_eval);
|
||||
BKE_id_free(nullptr, (Mesh *)data_eval);
|
||||
}
|
||||
else {
|
||||
BKE_libblock_free_data(data_eval, false);
|
||||
|
@ -1659,7 +1659,7 @@ void BKE_object_free_derived_caches(Object *ob)
|
|||
}
|
||||
if (ob->runtime->mesh_deform_eval != nullptr) {
|
||||
Mesh *mesh_deform_eval = ob->runtime->mesh_deform_eval;
|
||||
BKE_mesh_eval_delete(mesh_deform_eval);
|
||||
BKE_id_free(nullptr, mesh_deform_eval);
|
||||
ob->runtime->mesh_deform_eval = nullptr;
|
||||
}
|
||||
|
||||
|
@ -1806,8 +1806,7 @@ char *BKE_object_data_editmode_flush_ptr_get(ID *id)
|
|||
const short type = GS(id->name);
|
||||
switch (type) {
|
||||
case ID_ME: {
|
||||
BMEditMesh *em = ((Mesh *)id)->runtime->edit_mesh;
|
||||
if (em != nullptr) {
|
||||
if (BMEditMesh *em = ((Mesh *)id)->runtime->edit_mesh.get()) {
|
||||
return &em->needs_flush_to_id;
|
||||
}
|
||||
break;
|
||||
|
@ -3087,7 +3086,7 @@ static void give_parvert(const Object *par, int nr, float vec[3])
|
|||
|
||||
if (par->type == OB_MESH) {
|
||||
const Mesh *mesh = (const Mesh *)par->data;
|
||||
const BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
const BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
const Mesh *mesh_eval = (em) ? BKE_object_get_editmesh_eval_final(par) :
|
||||
BKE_object_get_evaluated_mesh(par);
|
||||
|
||||
|
|
|
@ -149,8 +149,7 @@ bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_sele
|
|||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
|
||||
if (cd_dvert_offset != -1) {
|
||||
|
@ -345,7 +344,7 @@ static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
|
|||
/* Else, make sure that any groups with higher indices are adjusted accordingly */
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
|
||||
BMIter iter;
|
||||
|
|
|
@ -291,7 +291,9 @@ static void deg_debug_graphviz_relation_arrowhead(const Relation *rel, dot::Dire
|
|||
OperationNode *op_from = (OperationNode *)rel->from;
|
||||
OperationNode *op_to = (OperationNode *)rel->to;
|
||||
if (op_from->owner->type == NodeType::COPY_ON_EVAL &&
|
||||
!op_to->owner->need_tag_cow_before_update())
|
||||
/* The #ID::recalc flag depends on run-time state which is not valid at this point in time.
|
||||
* Pass in all flags although there may be a better way to represent this. */
|
||||
!op_to->owner->need_tag_cow_before_update(ID_RECALC_ALL))
|
||||
{
|
||||
shape = shape_no_cow;
|
||||
}
|
||||
|
|
|
@ -296,7 +296,7 @@ void depsgraph_tag_component(Depsgraph *graph,
|
|||
}
|
||||
}
|
||||
/* If component depends on copy-on-evaluation, tag it as well. */
|
||||
if (component_node->need_tag_cow_before_update()) {
|
||||
if (component_node->need_tag_cow_before_update(IDRecalcFlag(id_node->id_cow->recalc))) {
|
||||
depsgraph_id_tag_copy_on_write(graph, id_node, update_source);
|
||||
}
|
||||
if (component_type == NodeType::COPY_ON_EVAL) {
|
||||
|
@ -531,8 +531,12 @@ void deg_graph_tag_parameters_if_needed(Main *bmain,
|
|||
}
|
||||
|
||||
/* Clear flags which are known to not affect parameters usable by drivers. */
|
||||
const uint clean_flags = flags & ~(ID_RECALC_SYNC_TO_EVAL | ID_RECALC_SELECT |
|
||||
ID_RECALC_BASE_FLAGS | ID_RECALC_SHADING);
|
||||
const uint clean_flags = flags &
|
||||
~(ID_RECALC_SYNC_TO_EVAL | ID_RECALC_SELECT | ID_RECALC_BASE_FLAGS |
|
||||
ID_RECALC_SHADING |
|
||||
/* While drivers may use the current-frame, this value is assigned
|
||||
* explicitly and doesn't require a the scene to be copied again. */
|
||||
ID_RECALC_FRAME_CHANGE);
|
||||
|
||||
if (clean_flags == 0) {
|
||||
/* Changes are limited to only things which are not usable by drivers. */
|
||||
|
|
|
@ -132,7 +132,7 @@ struct ComponentNode : public Node {
|
|||
|
||||
/* Denotes whether copy-on-eval component is to be tagged when this component
|
||||
* is tagged for update. */
|
||||
virtual bool need_tag_cow_before_update()
|
||||
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ struct ComponentNode : public Node {
|
|||
#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \
|
||||
struct name##ComponentNode : public ComponentNode { \
|
||||
DEG_COMPONENT_NODE_DECLARE; \
|
||||
virtual bool need_tag_cow_before_update() \
|
||||
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
|
@ -204,7 +204,6 @@ DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer);
|
|||
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Hierarchy);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Instancing);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Scene);
|
||||
|
@ -226,7 +225,7 @@ struct BoneComponentNode : public ComponentNode {
|
|||
/* Eventually we would not tag parameters in all cases.
|
||||
* Support for this each ID needs to be added on an individual basis. */
|
||||
struct ParametersComponentNode : public ComponentNode {
|
||||
virtual bool need_tag_cow_before_update() override
|
||||
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/) override
|
||||
{
|
||||
if (ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW(owner->id_type)) {
|
||||
/* Disabled as this is not true for newly added objects, needs investigation. */
|
||||
|
@ -239,6 +238,18 @@ struct ParametersComponentNode : public ComponentNode {
|
|||
DEG_COMPONENT_NODE_DECLARE;
|
||||
};
|
||||
|
||||
/* Audio component. */
|
||||
struct AudioComponentNode : public ComponentNode {
|
||||
virtual bool need_tag_cow_before_update(const IDRecalcFlag tag) override
|
||||
{
|
||||
/* Frame change doesn't require a copy of the scene, doing so can be a heavy operation
|
||||
* especially when the collection contains many objects, see #104798. */
|
||||
return (tag != ID_RECALC_FRAME_CHANGE);
|
||||
}
|
||||
|
||||
DEG_COMPONENT_NODE_DECLARE;
|
||||
};
|
||||
|
||||
void deg_register_component_depsnodes();
|
||||
|
||||
} // namespace blender::deg
|
||||
|
|
|
@ -137,9 +137,6 @@
|
|||
#define SUBSURFACE_RADIANCE_FORMAT GPU_R11F_G11F_B10F
|
||||
#define SUBSURFACE_OBJECT_ID_FORMAT GPU_R16UI
|
||||
|
||||
/* Minimum visibility size. */
|
||||
#define LIGHTPROBE_FILTER_VIS_GROUP_SIZE 16
|
||||
|
||||
/* Film. */
|
||||
#define FILM_GROUP_SIZE 16
|
||||
|
||||
|
|
|
@ -667,6 +667,7 @@ void IrradianceBake::sync()
|
|||
pass.bind_ssbo(SURFEL_BUF_SLOT, &surfels_buf_);
|
||||
pass.bind_ssbo(CAPTURE_BUF_SLOT, &capture_info_buf_);
|
||||
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
pass.bind_resources(inst_.uniform_data);
|
||||
pass.bind_resources(inst_.lights);
|
||||
pass.bind_resources(inst_.shadows);
|
||||
/* Sync with the surfel creation stage. */
|
||||
|
@ -750,6 +751,7 @@ void IrradianceBake::sync()
|
|||
pass.shader_set(inst_.shaders.static_shader_get(LIGHTPROBE_IRRADIANCE_OFFSET));
|
||||
pass.bind_ssbo(SURFEL_BUF_SLOT, &surfels_buf_);
|
||||
pass.bind_ssbo(CAPTURE_BUF_SLOT, &capture_info_buf_);
|
||||
pass.bind_ssbo("list_start_buf", &list_start_buf_);
|
||||
pass.bind_ssbo("list_info_buf", &list_info_buf_);
|
||||
pass.bind_image("cluster_list_img", &cluster_list_tx_);
|
||||
pass.bind_image("virtual_offset_img", &virtual_offset_tx_);
|
||||
|
|
|
@ -144,11 +144,14 @@ void WorldVolumePipeline::sync(GPUMaterial *gpumat)
|
|||
|
||||
world_ps_.material_set(*inst_.manager, gpumat);
|
||||
/* Bind correct dummy texture for attributes defaults. */
|
||||
volume_sub_pass(world_ps_, nullptr, nullptr, gpumat);
|
||||
PassSimple::Sub *sub = volume_sub_pass(world_ps_, nullptr, nullptr, gpumat);
|
||||
|
||||
world_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
/* Sync with object property pass. */
|
||||
world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
is_valid_ = (sub != nullptr);
|
||||
if (is_valid_) {
|
||||
world_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
/* Sync with object property pass. */
|
||||
world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldVolumePipeline::render(View &view)
|
||||
|
|
|
@ -84,7 +84,9 @@ static inline void volume_call(
|
|||
{
|
||||
if (matpass.sub_pass != nullptr) {
|
||||
PassMain::Sub *object_pass = volume_sub_pass(*matpass.sub_pass, scene, ob, matpass.gpumat);
|
||||
object_pass->draw(geom, res_handle);
|
||||
if (object_pass != nullptr) {
|
||||
object_pass->draw(geom, res_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +361,9 @@ void SyncModule::sync_volume(Object *ob, ObjectHandle & /*ob_handle*/, ResourceH
|
|||
}
|
||||
PassMain::Sub *object_pass = volume_sub_pass(
|
||||
*matpass.sub_pass, inst_.scene, ob, matpass.gpumat);
|
||||
object_pass->draw(geom, res_handle);
|
||||
if (object_pass != nullptr) {
|
||||
object_pass->draw(geom, res_handle);
|
||||
}
|
||||
};
|
||||
|
||||
drawcall_add(material.volume_occupancy, geom, res_handle);
|
||||
|
|
|
@ -236,7 +236,7 @@ static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob
|
|||
bool has_skin_roots = false;
|
||||
/* TODO: Should be its own function. */
|
||||
Mesh *mesh = (Mesh *)ob->data;
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
|
|||
/* TODO: Should be its own function. */
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
|
||||
if (is_edit_mode) {
|
||||
BLI_assert(mesh->runtime->edit_mesh);
|
||||
BLI_assert(mesh->runtime->edit_mesh.get());
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final);
|
||||
|
|
|
@ -79,7 +79,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
|
|||
{
|
||||
using namespace blender::draw;
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
|
||||
|
||||
|
|
|
@ -597,7 +597,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
|
||||
BLI_assert(editmesh_eval_cage && editmesh_eval_final);
|
||||
mr->bm = mesh->runtime->edit_mesh->bm;
|
||||
mr->edit_bmesh = mesh->runtime->edit_mesh;
|
||||
mr->edit_bmesh = mesh->runtime->edit_mesh.get();
|
||||
mr->mesh = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
|
||||
mr->edit_data = is_mode_active ? mr->mesh->runtime->edit_data.get() : nullptr;
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
DRWTextStore *dt = DRW_text_cache_ensure();
|
||||
const short txt_flag = DRW_TEXT_CACHE_GLOBALSPACE;
|
||||
const Mesh *mesh = BKE_object_get_editmesh_eval_cage(ob);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
float v1[3], v2[3], v3[3], vmid[3], fvec[3];
|
||||
char numstr[32]; /* Stores the measurement display text here */
|
||||
size_t numstr_len;
|
||||
|
|
|
@ -182,7 +182,7 @@ static bke::GeometrySet get_original_geometry_eval_copy(Object &object)
|
|||
}
|
||||
case OB_MESH: {
|
||||
const Mesh *mesh = static_cast<const Mesh *>(object.data);
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (std::shared_ptr<BMEditMesh> &em = mesh->runtime->edit_mesh) {
|
||||
Mesh *mesh_copy = BKE_mesh_wrapper_from_editmesh(em, nullptr, mesh);
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh_copy);
|
||||
Mesh *final_copy = BKE_mesh_copy_for_eval(mesh_copy);
|
||||
|
@ -253,7 +253,7 @@ static void store_result_geometry(
|
|||
BKE_object_material_from_eval_data(&bmain, &object, &new_mesh->id);
|
||||
if (object.mode == OB_MODE_EDIT) {
|
||||
EDBM_mesh_make_from_mesh(&object, new_mesh, scene.toolsettings->selectmode, true);
|
||||
BKE_editmesh_looptris_and_normals_calc(mesh.runtime->edit_mesh);
|
||||
BKE_editmesh_looptris_and_normals_calc(mesh.runtime->edit_mesh.get());
|
||||
BKE_id_free(nullptr, new_mesh);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -38,17 +38,12 @@
|
|||
|
||||
#include "eyedropper_intern.hh"
|
||||
|
||||
struct Colorband_RNAUpdateCb {
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
};
|
||||
namespace blender::ui {
|
||||
|
||||
struct EyedropperColorband {
|
||||
int event_xy_last[2];
|
||||
/* Alpha is currently fixed at 1.0, may support in future. */
|
||||
float (*color_buffer)[4];
|
||||
int color_buffer_alloc;
|
||||
int color_buffer_len;
|
||||
Vector<float4> color_buffer;
|
||||
bool sample_start;
|
||||
ColorBand init_color_band;
|
||||
ColorBand *color_band;
|
||||
|
@ -88,8 +83,8 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
if (band) {
|
||||
rna_update_ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
|
||||
rna_update_prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
|
||||
rna_update_ptr = but->rnapoin;
|
||||
rna_update_prop = but->rnaprop;
|
||||
is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
|
||||
}
|
||||
}
|
||||
|
@ -110,11 +105,7 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
|
|||
return false;
|
||||
}
|
||||
|
||||
EyedropperColorband *eye = MEM_cnew<EyedropperColorband>(__func__);
|
||||
eye->color_buffer_alloc = 16;
|
||||
eye->color_buffer = static_cast<float(*)[4]>(
|
||||
MEM_mallocN(sizeof(*eye->color_buffer) * eye->color_buffer_alloc, __func__));
|
||||
eye->color_buffer_len = 0;
|
||||
EyedropperColorband *eye = MEM_new<EyedropperColorband>(__func__, EyedropperColorband{});
|
||||
eye->color_band = band;
|
||||
eye->init_color_band = *eye->color_band;
|
||||
eye->ptr = rna_update_ptr;
|
||||
|
@ -131,16 +122,10 @@ static void eyedropper_colorband_sample_point(bContext *C,
|
|||
const int m_xy[2])
|
||||
{
|
||||
if (eye->event_xy_last[0] != m_xy[0] || eye->event_xy_last[1] != m_xy[1]) {
|
||||
float col[4];
|
||||
float4 col;
|
||||
col[3] = 1.0f; /* TODO: sample alpha */
|
||||
eyedropper_color_sample_fl(C, m_xy, col);
|
||||
if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
|
||||
eye->color_buffer_alloc *= 2;
|
||||
eye->color_buffer = static_cast<float(*)[4]>(
|
||||
MEM_reallocN(eye->color_buffer, sizeof(*eye->color_buffer) * eye->color_buffer_alloc));
|
||||
}
|
||||
copy_v4_v4(eye->color_buffer[eye->color_buffer_len], col);
|
||||
eye->color_buffer_len += 1;
|
||||
eye->color_buffer.append(col);
|
||||
copy_v2_v2_int(eye->event_xy_last, m_xy);
|
||||
eye->is_set = true;
|
||||
}
|
||||
|
@ -173,8 +158,7 @@ static void eyedropper_colorband_exit(bContext *C, wmOperator *op)
|
|||
|
||||
if (op->customdata) {
|
||||
EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
|
||||
MEM_freeN(eye->color_buffer);
|
||||
MEM_freeN(eye);
|
||||
MEM_delete(eye);
|
||||
op->customdata = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -184,8 +168,10 @@ static void eyedropper_colorband_apply(bContext *C, wmOperator *op)
|
|||
EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
|
||||
/* Always filter, avoids noise in resulting color-band. */
|
||||
const bool filter_samples = true;
|
||||
BKE_colorband_init_from_table_rgba(
|
||||
eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
|
||||
BKE_colorband_init_from_table_rgba(eye->color_band,
|
||||
reinterpret_cast<const float(*)[4]>(eye->color_buffer.data()),
|
||||
eye->color_buffer.size(),
|
||||
filter_samples);
|
||||
eye->is_set = true;
|
||||
if (eye->prop) {
|
||||
RNA_property_update(C, &eye->ptr, eye->prop);
|
||||
|
@ -256,15 +242,15 @@ static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const w
|
|||
eyedropper_colorband_exit(C, op);
|
||||
return OPERATOR_FINISHED;
|
||||
case EYE_MODAL_POINT_REMOVE_LAST:
|
||||
if (eye->color_buffer_len > 0) {
|
||||
eye->color_buffer_len -= 1;
|
||||
if (!eye->color_buffer.is_empty()) {
|
||||
eye->color_buffer.pop_last();
|
||||
eyedropper_colorband_apply(C, op);
|
||||
}
|
||||
break;
|
||||
case EYE_MODAL_POINT_SAMPLE:
|
||||
eyedropper_colorband_sample_point(C, eye, event->xy);
|
||||
eyedropper_colorband_apply(C, op);
|
||||
if (eye->color_buffer_len == MAXCOLORBAND) {
|
||||
if (eye->color_buffer.size() == MAXCOLORBAND) {
|
||||
eyedropper_colorband_exit(C, op);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -274,7 +260,7 @@ static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const w
|
|||
if (eye->prop) {
|
||||
RNA_property_update(C, &eye->ptr, eye->prop);
|
||||
}
|
||||
eye->color_buffer_len = 0;
|
||||
eye->color_buffer.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -367,3 +353,5 @@ void UI_OT_eyedropper_colorramp_point(wmOperatorType *ot)
|
|||
|
||||
/* properties */
|
||||
}
|
||||
|
||||
} // namespace blender::ui
|
||||
|
|
|
@ -1488,8 +1488,10 @@ void UI_OT_eyedropper_color(wmOperatorType *ot);
|
|||
|
||||
/* interface_eyedropper_colorband.c */
|
||||
|
||||
namespace blender::ui {
|
||||
void UI_OT_eyedropper_colorramp(wmOperatorType *ot);
|
||||
void UI_OT_eyedropper_colorramp_point(wmOperatorType *ot);
|
||||
} // namespace blender::ui
|
||||
|
||||
/* interface_eyedropper_datablock.c */
|
||||
|
||||
|
|
|
@ -2594,6 +2594,7 @@ static void UI_OT_drop_material(wmOperatorType *ot)
|
|||
|
||||
void ED_operatortypes_ui()
|
||||
{
|
||||
using namespace blender::ui;
|
||||
WM_operatortype_append(UI_OT_copy_data_path_button);
|
||||
WM_operatortype_append(UI_OT_copy_as_driver_button);
|
||||
WM_operatortype_append(UI_OT_copy_python_command_button);
|
||||
|
|
|
@ -3742,6 +3742,8 @@ static void colorband_buttons_layout(uiLayout *layout,
|
|||
|
||||
bt = uiDefBut(
|
||||
block, UI_BTYPE_COLORBAND, 0, "", xs, ys, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, "");
|
||||
bt->rnapoin = cb.ptr;
|
||||
bt->rnaprop = cb.prop;
|
||||
UI_but_func_set(bt, [cb](bContext &C) { rna_update_cb(C, cb); });
|
||||
|
||||
row = uiLayoutRow(layout, false);
|
||||
|
|
|
@ -39,7 +39,7 @@ static int set_sharpness_by_angle_exec(bContext *C, wmOperator *op)
|
|||
|
||||
for (Object *object : objects) {
|
||||
Mesh &mesh = *static_cast<Mesh *>(object->data);
|
||||
BMEditMesh *em = mesh.runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh.runtime->edit_mesh.get();
|
||||
|
||||
bool changed = false;
|
||||
BMIter iter;
|
||||
|
|
|
@ -3678,7 +3678,7 @@ static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
|
|||
scene, view_layer, CTX_wm_view3d(C));
|
||||
for (Object *obedit : objects) {
|
||||
Mesh *mesh = static_cast<Mesh *>(obedit->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
|
||||
if (em->bm->totvertsel == 0) {
|
||||
continue;
|
||||
|
@ -3757,7 +3757,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
|
|||
Mesh *me_ref = static_cast<Mesh *>(obedit_ref->data);
|
||||
Key *key_ref = me_ref->key;
|
||||
KeyBlock *kb_ref = nullptr;
|
||||
BMEditMesh *em_ref = me_ref->runtime->edit_mesh;
|
||||
BMEditMesh *em_ref = me_ref->runtime->edit_mesh.get();
|
||||
BMVert *eve;
|
||||
BMIter iter;
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
|
@ -3793,7 +3793,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
|
|||
Mesh *mesh = static_cast<Mesh *>(obedit->data);
|
||||
Key *key = mesh->key;
|
||||
KeyBlock *kb = nullptr;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
int shape;
|
||||
|
||||
if (em->bm->totvertsel == 0) {
|
||||
|
|
|
@ -843,7 +843,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em)
|
|||
|
||||
ob->shapenr = um->shapenr;
|
||||
|
||||
MEM_freeN(em_tmp);
|
||||
MEM_delete(em_tmp);
|
||||
|
||||
#ifdef USE_ARRAY_STORE
|
||||
um_arraystore_expand_clear(um);
|
||||
|
@ -947,11 +947,8 @@ static bool mesh_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
|
|||
|
||||
elem->obedit_ref.ptr = ob;
|
||||
Mesh *mesh = static_cast<Mesh *>(elem->obedit_ref.ptr->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
undomesh_from_editmesh(&elem->data,
|
||||
mesh->runtime->edit_mesh,
|
||||
mesh->key,
|
||||
um_references ? um_references[i] : nullptr);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
undomesh_from_editmesh(&elem->data, em, mesh->key, um_references ? um_references[i] : nullptr);
|
||||
em->needs_flush_to_id = 1;
|
||||
us->step.data_size += elem->data.undo_size;
|
||||
elem->data.uv_selectmode = ts->uv_selectmode;
|
||||
|
@ -997,7 +994,7 @@ static void mesh_undosys_step_decode(
|
|||
obedit->id.name);
|
||||
continue;
|
||||
}
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
undomesh_to_editmesh(&elem->data, obedit, em);
|
||||
em->needs_flush_to_id = 1;
|
||||
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
|
||||
|
|
|
@ -278,19 +278,20 @@ void EDBM_mesh_make_from_mesh(Object *ob,
|
|||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
/* this happens when switching shape keys */
|
||||
EDBM_mesh_free_data(mesh->runtime->edit_mesh);
|
||||
MEM_freeN(mesh->runtime->edit_mesh);
|
||||
EDBM_mesh_free_data(mesh->runtime->edit_mesh.get());
|
||||
mesh->runtime->edit_mesh.reset();
|
||||
}
|
||||
|
||||
/* Executing operators re-tessellates,
|
||||
* so we can avoid doing here but at some point it may need to be added back. */
|
||||
mesh->runtime->edit_mesh = BKE_editmesh_create(bm);
|
||||
mesh->runtime->edit_mesh = std::make_shared<BMEditMesh>();
|
||||
mesh->runtime->edit_mesh->bm = bm;
|
||||
|
||||
mesh->runtime->edit_mesh->selectmode = mesh->runtime->edit_mesh->bm->selectmode = select_mode;
|
||||
mesh->runtime->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
|
||||
|
||||
/* we need to flush selection because the mode may have changed from when last in editmode */
|
||||
EDBM_selectmode_flush(mesh->runtime->edit_mesh);
|
||||
EDBM_selectmode_flush(mesh->runtime->edit_mesh.get());
|
||||
}
|
||||
|
||||
void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
|
||||
|
@ -1653,7 +1654,7 @@ void EDBM_stats_update(BMEditMesh *em)
|
|||
|
||||
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
|
||||
{
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
/* Order of calling isn't important. */
|
||||
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id);
|
||||
|
|
|
@ -175,9 +175,7 @@ static void mesh_uv_reset_mface(const blender::IndexRange face, float2 *mloopuv)
|
|||
|
||||
void ED_mesh_uv_loop_reset_ex(Mesh *mesh, const int layernum)
|
||||
{
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
|
||||
if (em) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
/* Collect BMesh UVs */
|
||||
const int cd_loop_uv_offset = CustomData_get_n_offset(
|
||||
&em->bm->ldata, CD_PROP_FLOAT2, layernum);
|
||||
|
@ -225,7 +223,6 @@ int ED_mesh_uv_add(
|
|||
{
|
||||
/* NOTE: keep in sync with #ED_mesh_color_add. */
|
||||
|
||||
BMEditMesh *em;
|
||||
int layernum_dst;
|
||||
|
||||
if (!name) {
|
||||
|
@ -235,9 +232,7 @@ int ED_mesh_uv_add(
|
|||
const std::string unique_name = BKE_id_attribute_calc_unique_name(mesh->id, name);
|
||||
bool is_init = false;
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
em = mesh->runtime->edit_mesh;
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_PROP_FLOAT2);
|
||||
if (layernum_dst >= MAX_MTFACE) {
|
||||
BKE_reportf(reports, RPT_WARNING, "Cannot add more than %i UV maps", MAX_MTFACE);
|
||||
|
@ -366,12 +361,9 @@ bool *ED_mesh_uv_map_pin_layer_ensure(Mesh *mesh, const int uv_index)
|
|||
|
||||
void ED_mesh_uv_ensure(Mesh *mesh, const char *name)
|
||||
{
|
||||
BMEditMesh *em;
|
||||
int layernum_dst;
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
em = mesh->runtime->edit_mesh;
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_PROP_FLOAT2);
|
||||
if (layernum_dst == 0) {
|
||||
ED_mesh_uv_add(mesh, name, true, true, nullptr);
|
||||
|
@ -401,7 +393,7 @@ int ED_mesh_color_add(
|
|||
const char *active_name = mesh->active_color_attribute;
|
||||
if (const CustomDataLayer *active_layer = BKE_id_attributes_color_find(&mesh->id, active_name))
|
||||
{
|
||||
if (const BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (const BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMesh &bm = *em->bm;
|
||||
const int src_i = CustomData_get_named_layer(&bm.ldata, CD_PROP_BYTE_COLOR, active_name);
|
||||
const int dst_i = CustomData_get_named_layer(&bm.ldata, CD_PROP_BYTE_COLOR, layer->name);
|
||||
|
@ -754,7 +746,7 @@ static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperato
|
|||
{
|
||||
Mesh *mesh = ED_mesh_context(C);
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMesh &bm = *em->bm;
|
||||
if (!CustomData_has_layer(&bm.ldata, CD_CUSTOMLOOPNORMAL)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
|
|
@ -33,7 +33,7 @@ static struct {
|
|||
void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *mesh_eval)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
const bool use_em = (!mesh_eval && em && mesh->runtime->edit_mesh == em);
|
||||
const bool use_em = (!mesh_eval && em && mesh->runtime->edit_mesh.get() == em);
|
||||
const int totvert = use_em ? em->bm->totvert :
|
||||
mesh_eval ? mesh_eval->verts_num :
|
||||
mesh->verts_num;
|
||||
|
|
|
@ -832,7 +832,7 @@ BLI_INLINE void mesh_mirror_topo_table_get_meshes(Object *ob,
|
|||
if (mesh_eval != nullptr) {
|
||||
mesh_mirror = mesh_eval;
|
||||
}
|
||||
else if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
else if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
em_mirror = em;
|
||||
}
|
||||
else {
|
||||
|
@ -972,7 +972,7 @@ int ED_mesh_mirror_get_vert(Object *ob, int index)
|
|||
bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
|
||||
int index_mirr;
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMVert *eve, *eve_mirr;
|
||||
eve = BM_vert_at_index(em->bm, index);
|
||||
eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
|
||||
|
|
|
@ -1217,7 +1217,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
|
|||
}
|
||||
}
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
/* Copy to bmesh. */
|
||||
const int active_color_offset = CustomData_get_offset_named(
|
||||
&em->bm->vdata, eCustomDataType(active_color_layer->type), active_color_layer->name);
|
||||
|
@ -1252,7 +1252,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
|
|||
MEM_SAFE_FREE(num_loops_for_vertex);
|
||||
}
|
||||
else if (domain == bke::AttrDomain::Corner) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
/* Copy to bmesh. */
|
||||
const int active_color_offset = CustomData_get_offset_named(
|
||||
&em->bm->ldata, eCustomDataType(active_color_layer->type), active_color_layer->name);
|
||||
|
|
|
@ -583,9 +583,8 @@ static bool editmode_load_free_ex(Main *bmain,
|
|||
}
|
||||
|
||||
if (free_data) {
|
||||
EDBM_mesh_free_data(mesh->runtime->edit_mesh);
|
||||
MEM_freeN(mesh->runtime->edit_mesh);
|
||||
mesh->runtime->edit_mesh = nullptr;
|
||||
EDBM_mesh_free_data(mesh->runtime->edit_mesh.get());
|
||||
mesh->runtime->edit_mesh.reset();
|
||||
}
|
||||
/* will be recalculated as needed. */
|
||||
{
|
||||
|
|
|
@ -132,7 +132,7 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name,
|
|||
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMVert *eve;
|
||||
BMIter iter;
|
||||
int index = 0, nr = 0;
|
||||
|
@ -340,7 +340,7 @@ static bool object_hook_index_array(Main *bmain,
|
|||
|
||||
DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
|
||||
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
|
||||
BKE_editmesh_looptris_and_normals_calc(em);
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
|
|||
BKE_object_eval_reset(ob_eval);
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh_eval = mesh_create_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_DERIVEDMESH);
|
||||
BKE_mesh_eval_delete(mesh_eval);
|
||||
BKE_id_free(nullptr, mesh_eval);
|
||||
}
|
||||
else if (ob->type == OB_LATTICE) {
|
||||
BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval);
|
||||
|
@ -2687,7 +2687,7 @@ void OBJECT_OT_multires_rebuild_subdiv(wmOperatorType *ot)
|
|||
static void modifier_skin_customdata_delete(Object *ob)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -130,7 +130,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
|
|||
|
||||
DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
|
||||
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
|
||||
BKE_editmesh_looptris_and_normals_calc(em);
|
||||
|
||||
|
|
|
@ -1316,7 +1316,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
|
|||
if (obedit) {
|
||||
if (obedit->type == OB_MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(obedit->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMVert *eve;
|
||||
BMIter iter;
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ bool vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const
|
|||
case ID_ME: {
|
||||
Mesh *mesh = (Mesh *)id;
|
||||
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMesh *bm = em->bm;
|
||||
const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
|
||||
BMIter iter;
|
||||
|
@ -525,7 +525,7 @@ static void ED_mesh_defvert_mirror_update_em(
|
|||
Object *ob, BMVert *eve, int def_nr, int vidx, const int cd_dvert_offset)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMVert *eve_mirr;
|
||||
bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
|
||||
|
||||
|
@ -563,7 +563,7 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
|
|||
void vgroup_vert_active_mirror(Object *ob, int def_nr)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
MDeformVert *dvert_act;
|
||||
|
||||
if (mesh->symmetry & ME_SYMMETRY_X) {
|
||||
|
@ -599,7 +599,7 @@ static void vgroup_remove_weight(Object *ob, const int def_nr)
|
|||
static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
BMVert *eve_act;
|
||||
int v_act;
|
||||
MDeformVert *dvert_act;
|
||||
|
@ -638,13 +638,12 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type
|
|||
static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
MDeformVert *dvert_act;
|
||||
int i, vgroup_tot, subset_count;
|
||||
const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
|
||||
ob, subset_type, &vgroup_tot, &subset_count);
|
||||
|
||||
if (em) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
BMIter iter;
|
||||
BMVert *eve, *eve_act;
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
|
@ -935,8 +934,7 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
|
|||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
/* warning, this lookup is _not_ fast */
|
||||
|
||||
|
@ -1020,8 +1018,7 @@ static void vgroup_select_verts(Object *ob, int select)
|
|||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
|
||||
if (cd_dvert_offset != -1) {
|
||||
|
@ -2037,9 +2034,8 @@ void vgroup_mirror(Object *ob,
|
|||
/* only the active group */
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
|
||||
if (em) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
BMIter iter;
|
||||
|
||||
|
@ -2231,7 +2227,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
|
|||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh.get();
|
||||
int cd_dvert_offset;
|
||||
|
||||
BMIter iter;
|
||||
|
@ -3873,10 +3869,9 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
|
|||
MDeformVert *dvert_act;
|
||||
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
int i;
|
||||
|
||||
if (em) {
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
|
||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||
BMIter iter;
|
||||
BMVert *eve, *eve_act;
|
||||
|
|
|
@ -2147,7 +2147,7 @@ static void fill_mesh_color(Mesh &mesh,
|
|||
const bool use_face_sel,
|
||||
const bool affect_alpha)
|
||||
{
|
||||
if (BMEditMesh *em = mesh.runtime->edit_mesh) {
|
||||
if (BMEditMesh *em = mesh.runtime->edit_mesh.get()) {
|
||||
BMesh *bm = em->bm;
|
||||
const std::string name = attribute_name;
|
||||
const CustomDataLayer *layer = BKE_id_attributes_color_find(&mesh.id, name.c_str());
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue